Module Name: src Committed By: sborrill Date: Mon Feb 3 11:54:02 UTC 2014
Modified Files: src/lib/libc/gen [netbsd-6]: posix_spawn.3 posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_init.3 posix_spawn_fileactions.c src/sys/compat/netbsd32 [netbsd-6]: netbsd32_execve.c src/sys/kern [netbsd-6]: kern_exec.c Log Message: Pull up the following revisions(s) (requested by martin in ticket #1023): lib/libc/gen/posix_spawn.3: revision 1.5 lib/libc/gen/posix_spawn_file_actions_addopen.3: revision 1.4 lib/libc/gen/posix_spawn_file_actions_init.3: revision 1.4 lib/libc/gen/posix_spawn_fileactions.c: revision 1.3 sys/compat/netbsd32/netbsd32_execve.c: revision 1.38 sys/kern/kern_exec.c: revision 1.373 Limit the amount of kernel memory a posix_spawn syscall can use (for handling the file action list) by limiting the maximum number of file actions to twice the current file descriptor limit. Fix a few bugs in the support functions and document the new limit. From Maxime Villard. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.2.2.1 src/lib/libc/gen/posix_spawn.3 cvs rdiff -u -r1.1 -r1.1.2.1 \ src/lib/libc/gen/posix_spawn_file_actions_addopen.3 \ src/lib/libc/gen/posix_spawn_file_actions_init.3 cvs rdiff -u -r1.1.2.1 -r1.1.2.2 src/lib/libc/gen/posix_spawn_fileactions.c cvs rdiff -u -r1.33.2.2 -r1.33.2.3 src/sys/compat/netbsd32/netbsd32_execve.c cvs rdiff -u -r1.339.2.6 -r1.339.2.7 src/sys/kern/kern_exec.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/gen/posix_spawn.3 diff -u src/lib/libc/gen/posix_spawn.3:1.2 src/lib/libc/gen/posix_spawn.3:1.2.2.1 --- src/lib/libc/gen/posix_spawn.3:1.2 Mon Feb 13 16:35:59 2012 +++ src/lib/libc/gen/posix_spawn.3 Mon Feb 3 11:54:02 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: posix_spawn.3,v 1.2 2012/02/13 16:35:59 njoly Exp $ +.\" $NetBSD: posix_spawn.3,v 1.2.2.1 2014/02/03 11:54:02 sborrill Exp $ .\" .\" Copyright (c) 2008 Ed Schouten <e...@freebsd.org> .\" All rights reserved. @@ -182,6 +182,12 @@ flag set (see is closed. .El .Pp +The maximum number of +.Fa file_actions +objects is limited to the +.Dv RLIMIT_NOFILE +rlimit times 2. +.Pp The .Vt posix_spawnattr_t spawn attributes object type is defined in @@ -420,6 +426,11 @@ or .Fn dup2 , in addition to those described by .Fn open . +Finally, if the number of +.Fa file_actions +objects exceeds the allowed limit, +.Er EINVAL +is returned. .El .Sh SEE ALSO .Xr close 2 , Index: src/lib/libc/gen/posix_spawn_file_actions_addopen.3 diff -u src/lib/libc/gen/posix_spawn_file_actions_addopen.3:1.1 src/lib/libc/gen/posix_spawn_file_actions_addopen.3:1.1.2.1 --- src/lib/libc/gen/posix_spawn_file_actions_addopen.3:1.1 Sat Feb 11 23:31:24 2012 +++ src/lib/libc/gen/posix_spawn_file_actions_addopen.3 Mon Feb 3 11:54:02 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: posix_spawn_file_actions_addopen.3,v 1.1 2012/02/11 23:31:24 martin Exp $ +.\" $NetBSD: posix_spawn_file_actions_addopen.3,v 1.1.2.1 2014/02/03 11:54:02 sborrill Exp $ .\" .\" Copyright (c) 2008 Ed Schouten <e...@freebsd.org> .\" All rights reserved. @@ -149,6 +149,10 @@ functions fail if: .Bl -tag -width Er .It Bq Er EINVAL The value specified by +.Fa file_actions +is invalid. +.It Bq Er EBADF +The value specified by .Fa fildes or .Fa newfildes Index: src/lib/libc/gen/posix_spawn_file_actions_init.3 diff -u src/lib/libc/gen/posix_spawn_file_actions_init.3:1.1 src/lib/libc/gen/posix_spawn_file_actions_init.3:1.1.2.1 --- src/lib/libc/gen/posix_spawn_file_actions_init.3:1.1 Sat Feb 11 23:31:24 2012 +++ src/lib/libc/gen/posix_spawn_file_actions_init.3 Mon Feb 3 11:54:02 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: posix_spawn_file_actions_init.3,v 1.1 2012/02/11 23:31:24 martin Exp $ +.\" $NetBSD: posix_spawn_file_actions_init.3,v 1.1.2.1 2014/02/03 11:54:02 sborrill Exp $ .\" .\" Copyright (c) 2008 Ed Schouten <e...@freebsd.org> .\" All rights reserved. @@ -81,6 +81,10 @@ function will fail if: .Bl -tag -width Er .It Bq Er ENOMEM Insufficient memory exists to initialize the spawn file actions object. +.It Bq Er EINVAL +The value specified by +.Fa file_actions +is invalid. .El .Sh SEE ALSO .Xr posix_spawn 3 , Index: src/lib/libc/gen/posix_spawn_fileactions.c diff -u src/lib/libc/gen/posix_spawn_fileactions.c:1.1.2.1 src/lib/libc/gen/posix_spawn_fileactions.c:1.1.2.2 --- src/lib/libc/gen/posix_spawn_fileactions.c:1.1.2.1 Thu Apr 12 17:05:37 2012 +++ src/lib/libc/gen/posix_spawn_fileactions.c Mon Feb 3 11:54:02 2014 @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: posix_spawn_fileactions.c,v 1.1.2.1 2012/04/12 17:05:37 riz Exp $"); +__RCSID("$NetBSD: posix_spawn_fileactions.c,v 1.1.2.2 2014/02/03 11:54:02 sborrill Exp $"); #include "namespace.h" @@ -48,11 +48,11 @@ int posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa) { if (fa == NULL) - return (-1); + return (EINVAL); fa->fae = malloc(MIN_SIZE * sizeof(struct posix_spawn_file_actions_entry)); if (fa->fae == NULL) - return (-1); + return (ENOMEM); fa->size = MIN_SIZE; fa->len = 0; @@ -65,7 +65,7 @@ posix_spawn_file_actions_destroy(posix_s unsigned int i; if (fa == NULL) - return (-1); + return (EINVAL); for (i = 0; i < fa->len; i++) { if (fa->fae[i].fae_action == FAE_OPEN) @@ -77,48 +77,53 @@ posix_spawn_file_actions_destroy(posix_s } static int -posix_spawn_file_actions_getentry(posix_spawn_file_actions_t *fa) +posix_spawn_file_actions_getentry(posix_spawn_file_actions_t *fa, + unsigned int *i) { + posix_spawn_file_actions_entry_t *fae; + if (fa == NULL) - return -1; + return (EINVAL); if (fa->len < fa->size) - return fa->len; - - fa->fae = realloc(fa->fae, (fa->size + MIN_SIZE) * - sizeof(struct posix_spawn_file_actions_entry)); + goto out; - if (fa->fae == NULL) - return -1; + fae = realloc(fa->fae, (fa->size + MIN_SIZE) * sizeof(*fa->fae)); + if (fae == NULL) + return (ENOMEM); + fa->fae = fae; fa->size += MIN_SIZE; - return fa->len; +out: + *i = fa->len; + return (0); } int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, int fildes, const char * __restrict path, int oflag, mode_t mode) { - int i, error; + char *faepath; + unsigned int i; + int error; if (fildes < 0) return (EBADF); - i = posix_spawn_file_actions_getentry(fa); - if (i < 0) + error = posix_spawn_file_actions_getentry(fa, &i); + if (error) + return (error); + + faepath = strdup(path); + if (faepath == NULL) return (ENOMEM); fa->fae[i].fae_action = FAE_OPEN; - fa->fae[i].fae_path = strdup(path); - if (fa->fae[i].fae_path == NULL) { - error = errno; - return (error); - } + fa->fae[i].fae_path = faepath; fa->fae[i].fae_fildes = fildes; fa->fae[i].fae_oflag = oflag; fa->fae[i].fae_mode = mode; - fa->len++; return (0); @@ -128,14 +133,15 @@ int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int fildes, int newfildes) { - int i; + unsigned int i; + int error; if (fildes < 0 || newfildes < 0) return (EBADF); - i = posix_spawn_file_actions_getentry(fa); - if (i < 0) - return (ENOMEM); + error = posix_spawn_file_actions_getentry(fa, &i); + if (error) + return (error); fa->fae[i].fae_action = FAE_DUP2; fa->fae[i].fae_fildes = fildes; @@ -149,14 +155,15 @@ int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, int fildes) { - int i; + unsigned int i; + int error; if (fildes < 0) return (EBADF); - i = posix_spawn_file_actions_getentry(fa); - if (i < 0) - return (ENOMEM); + error = posix_spawn_file_actions_getentry(fa, &i); + if (error) + return (error); fa->fae[i].fae_action = FAE_CLOSE; fa->fae[i].fae_fildes = fildes; Index: src/sys/compat/netbsd32/netbsd32_execve.c diff -u src/sys/compat/netbsd32/netbsd32_execve.c:1.33.2.2 src/sys/compat/netbsd32/netbsd32_execve.c:1.33.2.3 --- src/sys/compat/netbsd32/netbsd32_execve.c:1.33.2.2 Fri Feb 8 20:45:50 2013 +++ src/sys/compat/netbsd32/netbsd32_execve.c Mon Feb 3 11:54:02 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_execve.c,v 1.33.2.2 2013/02/08 20:45:50 riz Exp $ */ +/* $NetBSD: netbsd32_execve.c,v 1.33.2.3 2014/02/03 11:54:02 sborrill Exp $ */ /* * Copyright (c) 1998, 2001 Matthew R. Green @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_execve.c,v 1.33.2.2 2013/02/08 20:45:50 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_execve.c,v 1.33.2.3 2014/02/03 11:54:02 sborrill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -97,7 +97,7 @@ netbsd32_fexecve(struct lwp *l, const st static int netbsd32_posix_spawn_fa_alloc(struct posix_spawn_file_actions **fap, - const struct netbsd32_posix_spawn_file_actions *ufa) + const struct netbsd32_posix_spawn_file_actions *ufa, rlim_t lim) { struct posix_spawn_file_actions *fa; struct netbsd32_posix_spawn_file_actions fa32; @@ -117,6 +117,11 @@ netbsd32_posix_spawn_fa_alloc(struct pos fa = kmem_alloc(sizeof(*fa), KM_SLEEP); fa->len = fa->size = fa32.len; + if (fa->len > lim) { + kmem_free(fa, sizeof(*fa)); + return EINVAL; + } + fal = fa->len * sizeof(*fae); fal32 = fa->len * sizeof(*fae32); @@ -179,6 +184,8 @@ netbsd32_posix_spawn(struct lwp *l, struct posix_spawnattr *sa = NULL; pid_t pid; bool child_ok = false; + rlim_t max_fileactions; + proc_t *p = l->l_proc; error = check_posix_spawn(l); if (error) { @@ -188,8 +195,10 @@ netbsd32_posix_spawn(struct lwp *l, /* copy in file_actions struct */ if (SCARG_P32(uap, file_actions) != NULL) { + max_fileactions = 2 * min(p->p_rlimit[RLIMIT_NOFILE].rlim_cur, + maxfiles); error = netbsd32_posix_spawn_fa_alloc(&fa, - SCARG_P32(uap, file_actions)); + SCARG_P32(uap, file_actions), max_fileactions); if (error) goto error_exit; } Index: src/sys/kern/kern_exec.c diff -u src/sys/kern/kern_exec.c:1.339.2.6 src/sys/kern/kern_exec.c:1.339.2.7 --- src/sys/kern/kern_exec.c:1.339.2.6 Tue Nov 20 21:32:24 2012 +++ src/sys/kern/kern_exec.c Mon Feb 3 11:54:02 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.339.2.6 2012/11/20 21:32:24 riz Exp $ */ +/* $NetBSD: kern_exec.c,v 1.339.2.7 2014/02/03 11:54:02 sborrill Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.339.2.6 2012/11/20 21:32:24 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.339.2.7 2014/02/03 11:54:02 sborrill Exp $"); #include "opt_exec.h" #include "opt_ktrace.h" @@ -2068,7 +2068,7 @@ posix_spawn_fa_free(struct posix_spawn_f static int posix_spawn_fa_alloc(struct posix_spawn_file_actions **fap, - const struct posix_spawn_file_actions *ufa) + const struct posix_spawn_file_actions *ufa, rlim_t lim) { struct posix_spawn_file_actions *fa; struct posix_spawn_file_actions_entry *fae; @@ -2089,6 +2089,11 @@ posix_spawn_fa_alloc(struct posix_spawn_ return 0; } + if (fa->len > lim) { + kmem_free(fa, sizeof(*fa)); + return EINVAL; + } + fa->size = fa->len; size_t fal = fa->len * sizeof(*fae); fae = fa->fae; @@ -2444,6 +2449,8 @@ sys_posix_spawn(struct lwp *l1, const st struct posix_spawnattr *sa = NULL; pid_t pid; bool child_ok = false; + rlim_t max_fileactions; + proc_t *p = l1->l_proc; error = check_posix_spawn(l1); if (error) { @@ -2453,7 +2460,10 @@ sys_posix_spawn(struct lwp *l1, const st /* copy in file_actions struct */ if (SCARG(uap, file_actions) != NULL) { - error = posix_spawn_fa_alloc(&fa, SCARG(uap, file_actions)); + max_fileactions = 2 * min(p->p_rlimit[RLIMIT_NOFILE].rlim_cur, + maxfiles); + error = posix_spawn_fa_alloc(&fa, SCARG(uap, file_actions), + max_fileactions); if (error) goto error_exit; }