execve()/creat(): handle NULL env correctly and support for holding executable file so that write access returns ETXTBSY
This commit is contained in:
committed by
Balazs Gerofi bgerofi@riken.jp
parent
b7088e654a
commit
55aeceb1bf
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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 = {
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user