Module Name: src Committed By: martin Date: Sun Feb 2 14:48:57 UTC 2014
Modified Files: src/lib/libc/gen: posix_spawn.3 posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_init.3 posix_spawn_fileactions.c src/sys/compat/netbsd32: netbsd32_execve.c src/sys/kern: kern_exec.c Log Message: 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.4 -r1.5 src/lib/libc/gen/posix_spawn.3 cvs rdiff -u -r1.3 -r1.4 src/lib/libc/gen/posix_spawn_file_actions_addopen.3 \ src/lib/libc/gen/posix_spawn_file_actions_init.3 cvs rdiff -u -r1.2 -r1.3 src/lib/libc/gen/posix_spawn_fileactions.c cvs rdiff -u -r1.37 -r1.38 src/sys/compat/netbsd32/netbsd32_execve.c cvs rdiff -u -r1.372 -r1.373 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.4 src/lib/libc/gen/posix_spawn.3:1.5 --- src/lib/libc/gen/posix_spawn.3:1.4 Sat Jul 20 21:39:57 2013 +++ src/lib/libc/gen/posix_spawn.3 Sun Feb 2 14:48:57 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: posix_spawn.3,v 1.4 2013/07/20 21:39:57 wiz Exp $ +.\" $NetBSD: posix_spawn.3,v 1.5 2014/02/02 14:48:57 martin 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.3 src/lib/libc/gen/posix_spawn_file_actions_addopen.3:1.4 --- src/lib/libc/gen/posix_spawn_file_actions_addopen.3:1.3 Sat Jul 20 21:39:57 2013 +++ src/lib/libc/gen/posix_spawn_file_actions_addopen.3 Sun Feb 2 14:48:57 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: posix_spawn_file_actions_addopen.3,v 1.3 2013/07/20 21:39:57 wiz Exp $ +.\" $NetBSD: posix_spawn_file_actions_addopen.3,v 1.4 2014/02/02 14:48:57 martin 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.3 src/lib/libc/gen/posix_spawn_file_actions_init.3:1.4 --- src/lib/libc/gen/posix_spawn_file_actions_init.3:1.3 Sat Jul 20 21:39:57 2013 +++ src/lib/libc/gen/posix_spawn_file_actions_init.3 Sun Feb 2 14:48:57 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: posix_spawn_file_actions_init.3,v 1.3 2013/07/20 21:39:57 wiz Exp $ +.\" $NetBSD: posix_spawn_file_actions_init.3,v 1.4 2014/02/02 14:48:57 martin 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.2 src/lib/libc/gen/posix_spawn_fileactions.c:1.3 --- src/lib/libc/gen/posix_spawn_fileactions.c:1.2 Sun Apr 8 11:27:44 2012 +++ src/lib/libc/gen/posix_spawn_fileactions.c Sun Feb 2 14:48:57 2014 @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: posix_spawn_fileactions.c,v 1.2 2012/04/08 11:27:44 martin Exp $"); +__RCSID("$NetBSD: posix_spawn_fileactions.c,v 1.3 2014/02/02 14:48:57 martin 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.37 src/sys/compat/netbsd32/netbsd32_execve.c:1.38 --- src/sys/compat/netbsd32/netbsd32_execve.c:1.37 Tue Jan 15 17:14:11 2013 +++ src/sys/compat/netbsd32/netbsd32_execve.c Sun Feb 2 14:48:57 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_execve.c,v 1.37 2013/01/15 17:14:11 hannken Exp $ */ +/* $NetBSD: netbsd32_execve.c,v 1.38 2014/02/02 14:48:57 martin 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.37 2013/01/15 17:14:11 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_execve.c,v 1.38 2014/02/02 14:48:57 martin 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.372 src/sys/kern/kern_exec.c:1.373 --- src/sys/kern/kern_exec.c:1.372 Sun Feb 2 08:25:23 2014 +++ src/sys/kern/kern_exec.c Sun Feb 2 14:48:57 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.372 2014/02/02 08:25:23 dogcow Exp $ */ +/* $NetBSD: kern_exec.c,v 1.373 2014/02/02 14:48:57 martin 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.372 2014/02/02 08:25:23 dogcow Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.373 2014/02/02 14:48:57 martin Exp $"); #include "opt_exec.h" #include "opt_execfmt.h" @@ -2065,7 +2065,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; @@ -2080,6 +2080,11 @@ posix_spawn_fa_alloc(struct posix_spawn_ return error; /* 0 if not an error, and len == 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; @@ -2437,6 +2442,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) { @@ -2446,7 +2453,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; }