Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Jul 2012 04:52:38 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r238560 - in stable/9/sys: kern sys
Message-ID:  <201207180452.q6I4qcwJ029225@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjg
Date: Wed Jul 18 04:52:37 2012
New Revision: 238560
URL: http://svn.freebsd.org/changeset/base/238560

Log:
  MFC r238220, r238272:
  
  Unbreak handling of descriptors opened with O_EXEC by fexecve(2).
  
  While here return EBADF for descriptors opened for writing (previously it was ETXTBSY).
  
  Add fgetvp_exec function which performs appropriate checks.
  
  ==
  
  Follow-up commit to r238220:
  
  Pass only FEXEC (instead of FREAD|FEXEC) in fgetvp_exec. _fget has to check for
  !FWRITE anyway and may as well know about FREAD.
  
  Make _fget code a bit more readable by converting permission checking from if()
  to switch(). Assert that correct permission flags are passed.
  
  PR:		kern/169651
  In collaboration with:	kib
  Approved by:	re (hrs), trasz (mentor)

Modified:
  stable/9/sys/kern/kern_descrip.c
  stable/9/sys/kern/kern_exec.c
  stable/9/sys/sys/file.h
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/kern/kern_descrip.c
==============================================================================
--- stable/9/sys/kern/kern_descrip.c	Tue Jul 17 22:16:10 2012	(r238559)
+++ stable/9/sys/kern/kern_descrip.c	Wed Jul 18 04:52:37 2012	(r238560)
@@ -2329,8 +2329,8 @@ _fget(struct thread *td, int fd, struct 
 	struct file *fp;
 #ifdef CAPABILITIES
 	struct file *fp_fromcap;
-	int error;
 #endif
+	int error;
 
 	*fpp = NULL;
 	if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
@@ -2369,7 +2369,7 @@ _fget(struct thread *td, int fd, struct 
 		else
 			error = cap_funwrap_mmap(fp, needrights, maxprotp,
 			    &fp_fromcap);
-		if (error) {
+		if (error != 0) {
 			fdrop(fp, td);
 			return (error);
 		}
@@ -2394,14 +2394,30 @@ _fget(struct thread *td, int fd, struct 
 
 	/*
 	 * FREAD and FWRITE failure return EBADF as per POSIX.
-	 *
-	 * Only one flag, or 0, may be specified.
 	 */
-	if ((flags == FREAD && (fp->f_flag & FREAD) == 0) ||
-	    (flags == FWRITE && (fp->f_flag & FWRITE) == 0)) {
+	error = 0;
+	switch (flags) {
+	case FREAD:
+	case FWRITE:
+		if ((fp->f_flag & flags) == 0)
+			error = EBADF;
+		break;
+	case FEXEC:
+	    	if ((fp->f_flag & (FREAD | FEXEC)) == 0 ||
+		    ((fp->f_flag & FWRITE) != 0))
+			error = EBADF;
+		break;
+	case 0:
+		break;
+	default:
+		KASSERT(0, ("wrong flags"));
+	}
+
+	if (error != 0) {
 		fdrop(fp, td);
-		return (EBADF);
+		return (error);
 	}
+
 	*fpp = fp;
 	return (0);
 }
@@ -2498,6 +2514,13 @@ fgetvp_read(struct thread *td, int fd, c
 	return (_fgetvp(td, fd, FREAD, rights, NULL, vpp));
 }
 
+int
+fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
+{
+
+	return (_fgetvp(td, fd, FEXEC, rights, NULL, vpp));
+}
+
 #ifdef notyet
 int
 fgetvp_write(struct thread *td, int fd, cap_rights_t rights,

Modified: stable/9/sys/kern/kern_exec.c
==============================================================================
--- stable/9/sys/kern/kern_exec.c	Tue Jul 17 22:16:10 2012	(r238559)
+++ stable/9/sys/kern/kern_exec.c	Wed Jul 18 04:52:37 2012	(r238560)
@@ -443,8 +443,10 @@ interpret:
 		/*
 		 * Some might argue that CAP_READ and/or CAP_MMAP should also
 		 * be required here; such arguments will be entertained.
+		 *
+		 * Descriptors opened only with O_EXEC or O_RDONLY are allowed.
 		 */
-		error = fgetvp_read(td, args->fd, CAP_FEXECVE, &binvp);
+		error = fgetvp_exec(td, args->fd, CAP_FEXECVE, &binvp);
 		if (error)
 			goto exec_fail;
 		vfslocked = VFS_LOCK_GIANT(binvp->v_mount);

Modified: stable/9/sys/sys/file.h
==============================================================================
--- stable/9/sys/sys/file.h	Tue Jul 17 22:16:10 2012	(r238559)
+++ stable/9/sys/sys/file.h	Wed Jul 18 04:52:37 2012	(r238560)
@@ -225,6 +225,8 @@ fo_chown_t	invfo_chown;
 
 void finit(struct file *, u_int, short, void *, struct fileops *);
 int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
+int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights,
+    struct vnode **vpp);
 int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
     cap_rights_t *have, struct vnode **vpp);
 int fgetvp_read(struct thread *td, int fd, cap_rights_t rights,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207180452.q6I4qcwJ029225>