From 68ff3c244592d9ed08ca13554d909da7a7e01b2d Mon Sep 17 00:00:00 2001 From: Stephan Uphoff Date: Wed, 8 Mar 2006 20:21:54 +0000 Subject: [PATCH] Fix exec_map resource leaks. Tested by: kris@ --- sys/amd64/linux32/linux32_machdep.c | 23 ++++++++++++--------- sys/compat/freebsd32/freebsd32_misc.c | 22 +++++++++++--------- sys/kern/kern_exec.c | 29 ++++++++++++++++++--------- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c index 2163bc217cb0..83ebf53aafad 100644 --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -130,7 +130,7 @@ linux_exec_copyin_args(struct image_args *args, char *fname, copystr(fname, args->fname, PATH_MAX, &length) : copyinstr(fname, args->fname, PATH_MAX, &length); if (error != 0) - return (error); + goto err_exit; /* * extract arguments first @@ -139,16 +139,16 @@ linux_exec_copyin_args(struct image_args *args, char *fname, for (;;) { error = copyin(p32++, &arg, sizeof(arg)); if (error) - return (error); + goto err_exit; if (arg == 0) break; argp = PTRIN(arg); error = copyinstr(argp, args->endp, args->stringspace, &length); if (error) { if (error == ENAMETOOLONG) - return (E2BIG); - else - return (error); + error = E2BIG; + + goto err_exit; } args->stringspace -= length; args->endp += length; @@ -165,7 +165,7 @@ linux_exec_copyin_args(struct image_args *args, char *fname, for (;;) { error = copyin(p32++, &arg, sizeof(arg)); if (error) - return (error); + goto err_exit; if (arg == 0) break; envp = PTRIN(arg); @@ -173,9 +173,8 @@ linux_exec_copyin_args(struct image_args *args, char *fname, &length); if (error) { if (error == ENAMETOOLONG) - return (E2BIG); - else - return (error); + error = E2BIG; + goto err_exit; } args->stringspace -= length; args->endp += length; @@ -184,6 +183,12 @@ linux_exec_copyin_args(struct image_args *args, char *fname, } return (0); + +err_exit: + kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, + PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); + args->buf = NULL; + return (error); } int diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 1045d1257123..472ef24aa884 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -260,7 +260,7 @@ freebsd32_exec_copyin_args(struct image_args *args, char *fname, copystr(fname, args->fname, PATH_MAX, &length) : copyinstr(fname, args->fname, PATH_MAX, &length); if (error != 0) - return (error); + goto err_exit; /* * extract arguments first @@ -269,16 +269,15 @@ freebsd32_exec_copyin_args(struct image_args *args, char *fname, for (;;) { error = copyin(p32++, &arg, sizeof(arg)); if (error) - return (error); + goto err_exit; if (arg == 0) break; argp = PTRIN(arg); error = copyinstr(argp, args->endp, args->stringspace, &length); if (error) { if (error == ENAMETOOLONG) - return (E2BIG); - else - return (error); + error = E2BIG; + goto err_exit; } args->stringspace -= length; args->endp += length; @@ -295,7 +294,7 @@ freebsd32_exec_copyin_args(struct image_args *args, char *fname, for (;;) { error = copyin(p32++, &arg, sizeof(arg)); if (error) - return (error); + goto err_exit; if (arg == 0) break; envp = PTRIN(arg); @@ -303,9 +302,8 @@ freebsd32_exec_copyin_args(struct image_args *args, char *fname, &length); if (error) { if (error == ENAMETOOLONG) - return (E2BIG); - else - return (error); + error = E2BIG; + goto err_exit; } args->stringspace -= length; args->endp += length; @@ -314,6 +312,12 @@ freebsd32_exec_copyin_args(struct image_args *args, char *fname, } return (0); + +err_exit: + kmem_free_wakeup(exec_map, (vm_offset_t)args->buf, + PATH_MAX + ARG_MAX + MAXSHELLCMDLEN); + args->buf = NULL; + return (error); } int diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index c2392ffd68e7..acc64d2dd387 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -243,6 +243,7 @@ kern_execve(td, args, mac_p) PROC_LOCK(p); if (thread_single(SINGLE_BOUNDARY)) { PROC_UNLOCK(p); + exec_free_args(args); return (ERESTART); /* Try again later. */ } PROC_UNLOCK(p); @@ -980,19 +981,21 @@ exec_copyin_args(struct image_args *args, char *fname, copystr(fname, args->fname, PATH_MAX, &length) : copyinstr(fname, args->fname, PATH_MAX, &length); if (error != 0) - return (error); + goto err_exit; /* * extract arguments first */ while ((argp = (caddr_t) (intptr_t) fuword(argv++))) { - if (argp == (caddr_t) -1) - return (EFAULT); + if (argp == (caddr_t) -1) { + error = EFAULT; + goto err_exit; + } if ((error = copyinstr(argp, args->endp, args->stringspace, &length))) { - if (error == ENAMETOOLONG) - return (E2BIG); - return (error); + if (error == ENAMETOOLONG) + error = E2BIG; + goto err_exit; } args->stringspace -= length; args->endp += length; @@ -1006,13 +1009,15 @@ exec_copyin_args(struct image_args *args, char *fname, */ if (envv) { while ((envp = (caddr_t)(intptr_t)fuword(envv++))) { - if (envp == (caddr_t)-1) - return (EFAULT); + if (envp == (caddr_t)-1) { + error = EFAULT; + goto err_exit; + } if ((error = copyinstr(envp, args->endp, args->stringspace, &length))) { if (error == ENAMETOOLONG) - return (E2BIG); - return (error); + error = E2BIG; + goto err_exit; } args->stringspace -= length; args->endp += length; @@ -1021,6 +1026,10 @@ exec_copyin_args(struct image_args *args, char *fname, } return (0); + +err_exit: + exec_free_args(args); + return (error); } static void