diff options
author | Kanoj Sarcar <kanoj@engr.sgi.com> | 2000-07-20 01:58:20 +0000 |
---|---|---|
committer | Kanoj Sarcar <kanoj@engr.sgi.com> | 2000-07-20 01:58:20 +0000 |
commit | d42919c8156a3317ee7896658b09c7cc4ea3d173 (patch) | |
tree | c2b0ca125905ae2477a9799d1e44f03b6a5a76d3 /arch/mips64/kernel | |
parent | 306c87a5e8eb065250a5668152bfe94cd31916e3 (diff) |
The 32 bit version of exec (picked from ia64) was writing into user
space from kernel without protection. Under tight memory conditions
when the page fault could not allocate a page, irritating messages
were being printed by the kernel. Write to user space with proper
protection.
Diffstat (limited to 'arch/mips64/kernel')
-rw-r--r-- | arch/mips64/kernel/linux32.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c index 70746da22..85444a18d 100644 --- a/arch/mips64/kernel/linux32.c +++ b/arch/mips64/kernel/linux32.c @@ -359,16 +359,18 @@ static int nargs(unsigned int arg, char **ap) { char *ptr; - int n; + int n, ret; n = 0; do { /* egcs is stupid */ if (!access_ok(VERIFY_READ, arg, sizeof (unsigned int))) return -EFAULT; - __get_user((long)ptr,(int *)A(arg)); - if (ap) - *ap++ = ptr; + if (IS_ERR(ret = __get_user((long)ptr,(int *)A(arg)))) + return ret; + if (ap) /* no access_ok needed, we allocated */ + if (IS_ERR(ret = __put_user(ptr, ap++))) + return ret; arg += sizeof(unsigned int); n++; } while (ptr); @@ -387,7 +389,11 @@ sys32_execve(abi64_no_regargs, struct pt_regs regs) char * filename; na = nargs(argv, NULL); + if (IS_ERR(na)) + return(na); ne = nargs(envp, NULL); + if (IS_ERR(ne)) + return(ne); len = (na + ne + 2) * sizeof(*av); /* * kmalloc won't work because the `sys_exec' code will attempt @@ -403,20 +409,25 @@ sys32_execve(abi64_no_regargs, struct pt_regs regs) up(¤t->mm->mmap_sem); if (IS_ERR(av)) - return((long) av); + return (long) av; ae = av + na + 1; - av[na] = (char *)0; - ae[ne] = (char *)0; - (void)nargs(argv, av); - (void)nargs(envp, ae); + if (IS_ERR(r = __put_user(0, (av + na)))) + goto out; + if (IS_ERR(r = __put_user(0, (ae + ne)))) + goto out; + if (IS_ERR(r = nargs(argv, av))) + goto out; + if (IS_ERR(r = nargs(envp, ae))) + goto out; filename = getname((char *) (long)regs.regs[4]); r = PTR_ERR(filename); if (IS_ERR(filename)) - return(r); + goto out; r = do_execve(filename, av, ae, ®s); putname(filename); if (IS_ERR(r)) +out: sys_munmap((unsigned long)av, len); return(r); } |