feat: extend syscall with copyUserArgv
This commit is contained in:
1 parent
8d63b96ad9
commit
0a1f4868dd
1 file changed
+53
@@ -5,10 +5,24 @@
|
||||
#include "vfs.h"
|
||||
#include "fs.h"
|
||||
#include "string.h"
|
||||
#include "elf.h"
|
||||
#include "paging.h"
|
||||
#include "signal.h"
|
||||
#include "keyboard.h"
|
||||
#include "pit.h"
|
||||
#include "poll.h"
|
||||
#include "rtc.h"
|
||||
#include "mmap.h"
|
||||
|
||||
#define userSpaceMin 0x0000000040000000ull
|
||||
#define userSpaceMax 0x0000800000000000ull
|
||||
|
||||
/* Matches kmain.c's userStackSize -- both sides map exactly one slot's
|
||||
worth of stack for a freshly loaded binary, whether it was spawned at
|
||||
boot (kmain.c's spawnUser, addresses picked by hand) or at runtime
|
||||
(doSpawn/doExec below, addresses derived from elfSlotStackTop). */
|
||||
#define execStackSize 0x4000
|
||||
|
||||
static bool userRangeOk(uint64 pointer, uint64 length)
|
||||
{
|
||||
if (pointer < userSpaceMin)
|
||||
@@ -34,6 +48,45 @@ static bool copyUserPath(uint64 pointer, char* dst, uint64 max)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define execArgMaxLen 256
|
||||
|
||||
/* Copies a NULL-terminated array of user-space `const char*` (the argv
|
||||
parameter of sysExec/sysSpawn -- userExec/userSpawn, ulib.c) into kernel
|
||||
memory: up to elfMaxArgs (elf.h) pointers are read out of userspace one
|
||||
at a time (each individually range-checked, since the array itself is
|
||||
just user memory a buggy or hostile caller controls) and each string
|
||||
copied via copyUserPath into `storage`, which the caller owns for as
|
||||
long as it needs argvPtrs to stay valid. A null `argvPointer` (the
|
||||
common "no arguments" case) is not an error -- it yields argc 0, letting
|
||||
userExec(path, nullptr) mean the same as a bare execve(path) with an
|
||||
otherwise-empty argv. Fails (leaving *outArgc untouched) on a bad
|
||||
pointer, a string that doesn't fit `execArgMaxLen`, or an argv longer
|
||||
than elfMaxArgs entries that never hits its NULL terminator. */
|
||||
static bool copyUserArgv(uint64 argvPointer, char storage[elfMaxArgs][execArgMaxLen],
|
||||
const char* argvPtrs[elfMaxArgs], int* outArgc)
|
||||
{
|
||||
if (argvPointer == 0) {
|
||||
*outArgc = 0;
|
||||
return true;
|
||||
}
|
||||
if (!userRangeOk(argvPointer, sizeof(uint64) * (elfMaxArgs + 1)))
|
||||
return false;
|
||||
|
||||
const uint64* userArgv = (const uint64*)argvPointer;
|
||||
int argc = 0;
|
||||
while (argc < elfMaxArgs && userArgv[argc] != 0) {
|
||||
if (!copyUserPath(userArgv[argc], storage[argc], execArgMaxLen))
|
||||
return false;
|
||||
argvPtrs[argc] = storage[argc];
|
||||
argc++;
|
||||
}
|
||||
if (argc == elfMaxArgs && userArgv[argc] != 0)
|
||||
return false;
|
||||
|
||||
*outArgc = argc;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int64 doWrite(uint64 fd, uint64 buffer, uint64 length)
|
||||
{
|
||||
if (!userRangeOk(buffer, length))
|
||||
|
||||
Reference in new issue
Block a user