1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/*
* SYSCALL_DEFINE3(execve,
* const char __user *, filename,
* const char __user *const __user *, argv,
* const char __user *const __user *, envp)
*
* On success, execve() does not return
* on error -1 is returned, and errno is set appropriately.
*
* TODO: Redirect stdin/stdout.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "arch.h" // page_size
#include "random.h" // generate_rand_bytes
#include "sanitise.h"
#include "shm.h"
#include "syscall.h"
#include "tables.h"
#include "trinity.h" // __unused__
#include "utils.h"
#include "compat.h"
static unsigned int argvcount;
static unsigned int envpcount;
static unsigned long ** gen_ptrs_to_crap(unsigned int count)
{
void **ptr;
unsigned int i;
/* Fabricate argv */
ptr = zmalloc(count * sizeof(void *));
for (i = 0; i < count; i++) {
ptr[i] = zmalloc(page_size);
generate_rand_bytes((unsigned char *) ptr[i], rnd() % page_size);
}
return (unsigned long **) ptr;
}
static void sanitise_execve(struct syscallrecord *rec)
{
unsigned long **argv, **envp;
/* we don't want to block if something tries to read from stdin */
fclose(stdin);
/* Fabricate argv */
argvcount = rnd() % 32;
argv = gen_ptrs_to_crap(argvcount);
/* Fabricate envp */
envpcount = rnd() % 32;
envp = gen_ptrs_to_crap(envpcount);
if (this_syscallname("execve") == FALSE) {
rec->a2 = (unsigned long) argv;
rec->a3 = (unsigned long) envp;
} else {
rec->a3 = (unsigned long) argv;
rec->a4 = (unsigned long) envp;
}
}
/* if execve succeeds, we'll never get back here, so this only
* has to worry about the case where execve returned a failure.
*/
static void free_execve_ptrs(void **argv, void **envp)
{
unsigned int i;
for (i = 0; i < argvcount; i++)
free(argv[i]);
free(argv);
for (i = 0; i < envpcount; i++)
free(envp[i]);
free(envp);
}
static void post_execve(struct syscallrecord *rec)
{
free_execve_ptrs((void **) rec->a2, (void **) rec->a3);
}
static void post_execveat(struct syscallrecord *rec)
{
free_execve_ptrs((void **) rec->a3, (void **) rec->a4);
}
struct syscallentry syscall_execve = {
.name = "execve",
.num_args = 3,
.arg1name = "name",
.arg1type = ARG_PATHNAME,
.arg2name = "argv",
.arg2type = ARG_ADDRESS,
.arg3name = "envp",
.arg3type = ARG_ADDRESS,
.sanitise = sanitise_execve,
.post = post_execve,
.group = GROUP_VFS,
.flags = EXTRA_FORK,
};
static unsigned long execveat_flags[] = {
AT_EMPTY_PATH, AT_SYMLINK_NOFOLLOW,
};
struct syscallentry syscall_execveat = {
.name = "execveat",
.num_args = 5,
.arg1name = "fd",
.arg1type = ARG_FD,
.arg2name = "name",
.arg2type = ARG_PATHNAME,
.arg3name = "argv",
.arg3type = ARG_ADDRESS,
.arg4name = "envp",
.arg4type = ARG_ADDRESS,
.arg5name = "flags",
.arg5type = ARG_LIST,
.arg5list = ARGLIST(execveat_flags),
.sanitise = sanitise_execve,
.post = post_execveat,
.group = GROUP_VFS,
.flags = EXTRA_FORK,
};
|