From 6f36ecf0b3658668f20668e78bc50bc3c3b3b161 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 4 Apr 2012 01:41:29 +0200 Subject: [PATCH] execve(2) now pushes envp to the new stack and sets up registers. This fully implements environmental variables over exec. --- libmaxsi/x64/start.s | 2 ++ libmaxsi/x86/start.s | 2 ++ sortix/process.cpp | 69 +++++++++++++++++++++++++++++++++++------- sortix/process.h | 9 ++++-- sortix/x64/process.cpp | 6 +++- sortix/x86/process.cpp | 7 ++++- 6 files changed, 80 insertions(+), 15 deletions(-) diff --git a/libmaxsi/x64/start.s b/libmaxsi/x64/start.s index bb2bb21f..e6e6eedb 100644 --- a/libmaxsi/x64/start.s +++ b/libmaxsi/x64/start.s @@ -29,6 +29,8 @@ .type _start, @function _start: + movq %rcx, environ # envp + pushq %rsi pushq %rdi diff --git a/libmaxsi/x86/start.s b/libmaxsi/x86/start.s index b1b1c20a..3fcbed0e 100644 --- a/libmaxsi/x86/start.s +++ b/libmaxsi/x86/start.s @@ -30,6 +30,8 @@ .type _start, @function _start: + movl %ecx, environ # envp + # Arguments for main push %ebx # argv push %eax # argc diff --git a/sortix/process.cpp b/sortix/process.cpp index 74d9b63d..52721027 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -259,7 +259,10 @@ namespace Sortix ResetAddressSpace(); } - int Process::Execute(const char* programname, const byte* program, size_t programsize, int argc, const char* const* argv, CPU::InterruptRegisters* regs) + int Process::Execute(const char* programname, const byte* program, + size_t programsize, int argc, const char* const* argv, + int envc, const char* const* envp, + CPU::InterruptRegisters* regs) { ASSERT(CurrentProcess() == this); @@ -269,10 +272,11 @@ namespace Sortix // TODO: This may be an ugly hack! // TODO: Move this to x86/process.cpp. + addr_t stackpos = CurrentThread()->stackpos + CurrentThread()->stacksize; + // Alright, move argv onto the new stack! First figure out exactly how // big argv actually is. - addr_t stackpos = CurrentThread()->stackpos + CurrentThread()->stacksize; - addr_t argvpos = stackpos - sizeof(char*) * argc; + addr_t argvpos = stackpos - sizeof(char*) * (argc+1); char** stackargv = (char**) argvpos; size_t argvsize = 0; @@ -285,9 +289,31 @@ namespace Sortix Maxsi::Memory::Copy(dest, argv[i], len); } - stackpos = argvpos - argvsize; + stackargv[argc] = NULL; - ExecuteCPU(argc, stackargv, stackpos, entry, regs); + if ( argvsize % 16UL ) { argvsize += 16 - (argvsize % 16UL); } + + // And then move envp onto the stack. + addr_t envppos = argvpos - argvsize - sizeof(char*) * (envc+1); + char** stackenvp = (char**) envppos; + + size_t envpsize = 0; + for ( int i = 0; i < envc; i++ ) + { + size_t len = String::Length(envp[i]) + 1; + envpsize += len; + char* dest = ((char*) envppos) - envpsize; + stackenvp[i] = dest; + Maxsi::Memory::Copy(dest, envp[i], len); + } + + stackenvp[envc] = NULL; + + if ( envpsize % 16UL ) { envpsize += 16 - (envpsize % 16UL); } + + stackpos = envppos - envpsize; + + ExecuteCPU(argc, stackargv, envc, stackenvp, stackpos, entry, regs); descriptors.OnExecute(); @@ -303,7 +329,9 @@ namespace Sortix size_t count; size_t sofar; int argc; + int envc; char** argv; + char** envp; public: SysExecVEState() @@ -315,6 +343,8 @@ namespace Sortix sofar = 0; argc = 0; argv = NULL; + envc = 0; + envp = NULL; } ~SysExecVEState() @@ -324,6 +354,8 @@ namespace Sortix delete[] buffer; for ( int i = 0; i < argc; i++ ) { delete[] argv[i]; } delete[] argv; + for ( int i = 0; i < envc; i++ ) { delete[] envp[i]; } + delete[] envp; } }; @@ -350,7 +382,10 @@ namespace Sortix { CPU::InterruptRegisters* regs = Syscall::InterruptRegs(); Process* process = CurrentProcess(); - int result = process->Execute(state->filename, state->buffer, state->count, state->argc, state->argv, regs); + int result = process->Execute(state->filename, state->buffer, + state->count, state->argc, + state->argv, state->envc, + state->envp, regs); if ( result == 0 ) { Syscall::AsIs(); } delete state; return result; @@ -391,7 +426,7 @@ namespace Sortix return (DevBuffer*) dev; } - int SysExecVE(const char* filename, char* const argv[], char* const /*envp*/[]) + int SysExecVE(const char* filename, char* const argv[], char* const envp[]) { // TODO: Validate that all the pointer-y parameters are SAFE! @@ -404,12 +439,13 @@ namespace Sortix state->filename = String::Clone(filename); if ( !state->filename ) { delete state; return -1; } - int argc; for ( argc = 0; argv[argc]; argc++ ); + int argc; for ( argc = 0; argv && argv[argc]; argc++ ); + int envc; for ( envc = 0; envp && envp[envc]; envc++ ); - state->argc = argc; - state->argv = new char*[state->argc]; - Maxsi::Memory::Set(state->argv, 0, sizeof(char*) * state->argc); + state->argv = new char*[argc+1]; if ( !state->argv ) { delete state; return -1; } + state->argc = argc; + Maxsi::Memory::Set(state->argv, 0, sizeof(char*) * (state->argc+1)); for ( int i = 0; i < state->argc; i++ ) { @@ -417,6 +453,17 @@ namespace Sortix if ( !state->argv[i] ) { delete state; return -1; } } + state->envp = new char*[envc+1]; + if ( !state->envp ) { delete state; return -1; } + state->envc = envc; + Maxsi::Memory::Set(state->envp, 0, sizeof(char*) * (state->envc+1)); + + for ( int i = 0; i < state->envc; i++ ) + { + state->envp[i] = String::Clone(envp[i]); + if ( !state->envp[i] ) { delete state; return -1; } + } + Process* process = CurrentProcess(); state->dev = OpenProgramImage(state->filename, process->workingdir, "/bin"); if ( !state->dev ) { delete state; return -1; } diff --git a/sortix/process.h b/sortix/process.h index 2e1cf69d..1aab20e0 100644 --- a/sortix/process.h +++ b/sortix/process.h @@ -96,7 +96,10 @@ namespace Sortix bool sigint; public: - int Execute(const char* programname, const byte* program, size_t programsize, int argc, const char* const* argv, CPU::InterruptRegisters* regs); + int Execute(const char* programname, const byte* program, + size_t programsize, int argc, const char* const* argv, + int envc, const char* const* envp, + CPU::InterruptRegisters* regs); void ResetAddressSpace(); void Exit(int status); @@ -108,7 +111,9 @@ namespace Sortix private: Thread* ForkThreads(Process* processclone); - void ExecuteCPU(int argc, char** argv, addr_t stackpos, addr_t entry, CPU::InterruptRegisters* regs); + void ExecuteCPU(int argc, char** argv, int envc, char** envp, + addr_t stackpos, addr_t entry, + CPU::InterruptRegisters* regs); public: void ResetForExecute(); diff --git a/sortix/x64/process.cpp b/sortix/x64/process.cpp index f9518dc7..9de05cf9 100644 --- a/sortix/x64/process.cpp +++ b/sortix/x64/process.cpp @@ -27,10 +27,14 @@ namespace Sortix { - void Process::ExecuteCPU(int argc, char** argv, addr_t stackpos, addr_t entry, CPU::InterruptRegisters* regs) + void Process::ExecuteCPU(int argc, char** argv, int envc, char** envp, + addr_t stackpos, addr_t entry, + CPU::InterruptRegisters* regs) { regs->rdi = argc; regs->rsi = (size_t) argv; + regs->rdx = envc; + regs->rcx = (size_t) envp; regs->rip = entry; regs->userrsp = stackpos & ~(15UL); regs->rbp = stackpos; diff --git a/sortix/x86/process.cpp b/sortix/x86/process.cpp index b5e4cf7d..e0424fec 100644 --- a/sortix/x86/process.cpp +++ b/sortix/x86/process.cpp @@ -27,10 +27,15 @@ namespace Sortix { - void Process::ExecuteCPU(int argc, char** argv, addr_t stackpos, addr_t entry, CPU::InterruptRegisters* regs) + + void Process::ExecuteCPU(int argc, char** argv, int envc, char** envp, + addr_t stackpos, addr_t entry, + CPU::InterruptRegisters* regs) { regs->eax = argc; regs->ebx = (size_t) argv; + regs->edx = envc; + regs->ecx = (size_t) envp; regs->eip = entry; regs->useresp = stackpos; regs->ebp = stackpos;