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;
 	}

Reply via email to