execve()/creat(): handle NULL env correctly and support for holding executable file so that write access returns ETXTBSY

This commit is contained in:
bgerofi@riken.jp
2014-09-18 21:19:24 +09:00
committed by Balazs Gerofi bgerofi@riken.jp
parent b7088e654a
commit 55aeceb1bf
5 changed files with 103 additions and 9 deletions

View File

@ -42,7 +42,8 @@
#define MCEXEC_UP_PREPARE_DMA 0x30a02910 #define MCEXEC_UP_PREPARE_DMA 0x30a02910
#define MCEXEC_UP_FREE_DMA 0x30a02911 #define MCEXEC_UP_FREE_DMA 0x30a02911
#define MCEXEC_UP_TEST_OPEN_EXEC 0x30a02912 #define MCEXEC_UP_OPEN_EXEC 0x30a02912
#define MCEXEC_UP_CLOSE_EXEC 0x30a02913
#define MCEXEC_UP_TRANSFER_TO_REMOTE 0 #define MCEXEC_UP_TRANSFER_TO_REMOTE 0
#define MCEXEC_UP_TRANSFER_FROM_REMOTE 1 #define MCEXEC_UP_TRANSFER_FROM_REMOTE 1

View File

@ -692,9 +692,22 @@ long mcexec_ret_syscall(ihk_os_t os, struct syscall_ret_desc *__user arg)
return 0; return 0;
} }
int mcexec_test_open_exec(ihk_os_t os, char * __user filename) LIST_HEAD(mckernel_exec_files);
spinlock_t mckernel_exec_file_lock = SPIN_LOCK_UNLOCKED;
struct mckernel_exec_file {
ihk_os_t os;
pid_t pid;
struct file *fp;
struct list_head list;
};
int mcexec_open_exec(ihk_os_t os, char * __user filename)
{ {
struct file *file; struct file *file;
struct mckernel_exec_file *mcef;
struct mckernel_exec_file *mcef_iter;
int retval; int retval;
file = open_exec(filename); file = open_exec(filename);
@ -703,13 +716,65 @@ int mcexec_test_open_exec(ihk_os_t os, char * __user filename)
goto out_return; goto out_return;
} }
retval = 0; mcef = kmalloc(sizeof(*mcef), GFP_KERNEL);
if (!mcef) {
retval = ENOMEM;
goto out_put_file;
}
spin_lock_irq(&mckernel_exec_file_lock);
/* Find previous file (if exists) and drop it */
list_for_each_entry(mcef_iter, &mckernel_exec_files, list) {
if (mcef_iter->os == os && mcef_iter->pid == current->tgid) {
allow_write_access(mcef_iter->fp);
fput(mcef_iter->fp);
list_del(&mcef_iter->list);
kfree(mcef_iter);
dprintk("%d open_exec dropped previous executable \n", (int)current->tgid);
break;
}
}
/* Add new exec file to the list */
mcef->os = os;
mcef->pid = current->tgid;
mcef->fp = file;
list_add_tail(&mcef->list, &mckernel_exec_files);
spin_unlock(&mckernel_exec_file_lock);
dprintk("%d open_exec and holding file: %s\n", (int)current->tgid, filename);
return 0;
out_put_file:
fput(file); fput(file);
out_return: out_return:
return -retval; return -retval;
} }
int mcexec_close_exec(ihk_os_t os)
{
struct mckernel_exec_file *mcef = NULL;
int found = 0;
spin_lock_irq(&mckernel_exec_file_lock);
list_for_each_entry(mcef, &mckernel_exec_files, list) {
if (mcef->os == os && mcef->pid == current->tgid) {
allow_write_access(mcef->fp);
fput(mcef->fp);
list_del(&mcef->list);
kfree(mcef);
found = 1;
dprintk("%d close_exec dropped executable \n", (int)current->tgid);
break;
}
}
spin_unlock(&mckernel_exec_file_lock);
return (found ? 0 : EINVAL);
}
long mcexec_strncpy_from_user(ihk_os_t os, struct strncpy_from_user_desc * __user arg) long mcexec_strncpy_from_user(ihk_os_t os, struct strncpy_from_user_desc * __user arg)
{ {
struct strncpy_from_user_desc desc; struct strncpy_from_user_desc desc;
@ -793,8 +858,11 @@ long __mcctrl_control(ihk_os_t os, unsigned int req, unsigned long arg)
return mcexec_strncpy_from_user(os, return mcexec_strncpy_from_user(os,
(struct strncpy_from_user_desc *)arg); (struct strncpy_from_user_desc *)arg);
case MCEXEC_UP_TEST_OPEN_EXEC: case MCEXEC_UP_OPEN_EXEC:
return mcexec_test_open_exec(os, (char *)arg); return mcexec_open_exec(os, (char *)arg);
case MCEXEC_UP_CLOSE_EXEC:
return mcexec_close_exec(os);
case MCEXEC_UP_PREPARE_DMA: case MCEXEC_UP_PREPARE_DMA:
return mcexec_pin_region(os, (unsigned long *)arg); return mcexec_pin_region(os, (unsigned long *)arg);

View File

@ -57,7 +57,8 @@ static struct ihk_os_user_call_handler mcctrl_uchs[] = {
{ .request = MCEXEC_UP_STRNCPY_FROM_USER, .func = mcctrl_ioctl }, { .request = MCEXEC_UP_STRNCPY_FROM_USER, .func = mcctrl_ioctl },
{ .request = MCEXEC_UP_PREPARE_DMA, .func = mcctrl_ioctl }, { .request = MCEXEC_UP_PREPARE_DMA, .func = mcctrl_ioctl },
{ .request = MCEXEC_UP_FREE_DMA, .func = mcctrl_ioctl }, { .request = MCEXEC_UP_FREE_DMA, .func = mcctrl_ioctl },
{ .request = MCEXEC_UP_TEST_OPEN_EXEC, .func = mcctrl_ioctl }, { .request = MCEXEC_UP_OPEN_EXEC, .func = mcctrl_ioctl },
{ .request = MCEXEC_UP_CLOSE_EXEC, .func = mcctrl_ioctl },
}; };
static struct ihk_os_user_call mcctrl_uc_proto = { static struct ihk_os_user_call mcctrl_uc_proto = {

View File

@ -352,7 +352,7 @@ retry:
if (strncmp(filename, "/", 1)) { if (strncmp(filename, "/", 1)) {
/* Is filename a single component without path? */ /* Is filename a single component without path? */
if (strncmp(filename, ".", 1) && !strchr(filename, '/')) { while (strncmp(filename, ".", 1) && !strchr(filename, '/')) {
char *token, *string, *tofree; char *token, *string, *tofree;
char *PATH = getenv("COKERNEL_PATH"); char *PATH = getenv("COKERNEL_PATH");
@ -363,6 +363,21 @@ retry:
if (strlen(filename) >= 255) { if (strlen(filename) >= 255) {
return ENAMETOOLONG; return ENAMETOOLONG;
} }
/* See first whether file is available in current working dir */
error = access(filename, X_OK);
if (error == 0) {
__dprintf("lookup_exec_path(): found %s in cwd\n", filename);
error = snprintf(path, max_len, "%s", filename);
if (error < 0 || error >= max_len) {
fprintf(stderr, "lookup_exec_path(): array too small?\n");
return ENOMEM;
}
found = 1;
break;
}
__dprintf("PATH: %s\n", PATH); __dprintf("PATH: %s\n", PATH);
@ -390,6 +405,7 @@ retry:
} }
free(tofree); free(tofree);
break;
} }
/* Not in path, file to be open from the working directory */ /* Not in path, file to be open from the working directory */
@ -520,7 +536,7 @@ int load_elf_desc(char *filename, struct program_load_desc **desc_p,
rewind(fp); rewind(fp);
if ((ret = ioctl(fd, MCEXEC_UP_TEST_OPEN_EXEC, filename)) != 0) { if ((ret = ioctl(fd, MCEXEC_UP_OPEN_EXEC, filename)) != 0) {
fprintf(stderr, "Error: open_exec() fails for %s: %d (fd: %d)\n", fprintf(stderr, "Error: open_exec() fails for %s: %d (fd: %d)\n",
filename, ret, fd); filename, ret, fd);
return ret; return ret;
@ -1392,6 +1408,12 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock, int mcosid)
case __NR_exit_group: case __NR_exit_group:
sig = 0; sig = 0;
term = 0; term = 0;
/* Drop executable file */
if ((ret = ioctl(fd, MCEXEC_UP_CLOSE_EXEC)) != 0) {
fprintf(stderr, "WARNING: close_exec() couldn't find exec file?\n");
}
do_syscall_return(fd, cpu, 0, 0, 0, 0, 0); do_syscall_return(fd, cpu, 0, 0, 0, 0, 0);
__dprintf("__NR_exit/__NR_exit_group: %ld (cpu_id: %d)\n", __dprintf("__NR_exit/__NR_exit_group: %ld (cpu_id: %d)\n",

View File

@ -1244,9 +1244,11 @@ SYSCALL_DECLARE(arch_prctl)
SYSCALL_DECLARE(execve) SYSCALL_DECLARE(execve)
{ {
long ret; long ret;
char *empty_envp[1] = {NULL};
const char *filename = (const char *)ihk_mc_syscall_arg0(ctx); const char *filename = (const char *)ihk_mc_syscall_arg0(ctx);
char **argv = (char **)ihk_mc_syscall_arg1(ctx); char **argv = (char **)ihk_mc_syscall_arg1(ctx);
char **envp = (char **)ihk_mc_syscall_arg2(ctx); char **envp = (char **)ihk_mc_syscall_arg2(ctx) ?
(char **)ihk_mc_syscall_arg2(ctx) : empty_envp;
char *argv_flat = NULL; char *argv_flat = NULL;
int argv_flat_len = 0; int argv_flat_len = 0;