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,
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to