Author: markj
Date: Sat Jun 29 16:11:09 2019
New Revision: 349547
URL: https://svnweb.freebsd.org/changeset/base/349547

Log:
  Use a consistent snapshot of the fd's rights in fget_mmap().
  
  fget_mmap() translates rights on the descriptor to a VM protection
  mask.  It was doing so without holding any locks on the descriptor
  table, so a writer could simultaneously be modifying those rights.
  Such a situation would be detected using a sequence counter, but
  not before an inconsistency could trigger assertion failures in
  the capability code.
  
  Fix the problem by copying the fd's rights to a structure on the stack,
  and perform the translation only once we know that that snapshot is
  consistent.
  
  Reported by:  syzbot+ae359438769fda184...@syzkaller.appspotmail.com
  Reviewed by:  brooks, mjg
  MFC after:    1 week
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D20800

Modified:
  head/sys/kern/kern_descrip.c

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Sat Jun 29 16:05:52 2019        
(r349546)
+++ head/sys/kern/kern_descrip.c        Sat Jun 29 16:11:09 2019        
(r349547)
@@ -2761,6 +2761,7 @@ fget_mmap(struct thread *td, int fd, cap_rights_t *rig
        if (maxprotp != NULL)
                *maxprotp = VM_PROT_ALL;
 #else
+       cap_rights_t fdrights;
        struct filedesc *fdp = td->td_proc->p_fd;
        seqc_t seq;
 
@@ -2769,15 +2770,18 @@ fget_mmap(struct thread *td, int fd, cap_rights_t *rig
                error = _fget(td, fd, fpp, 0, rightsp, &seq);
                if (error != 0)
                        return (error);
-               /*
-                * If requested, convert capability rights to access flags.
-                */
                if (maxprotp != NULL)
-                       *maxprotp = cap_rights_to_vmprot(cap_rights(fdp, fd));
+                       fdrights = *cap_rights(fdp, fd);
                if (!fd_modified(fdp, fd, seq))
                        break;
                fdrop(*fpp, td);
        }
+
+       /*
+        * If requested, convert capability rights to access flags.
+        */
+       if (maxprotp != NULL)
+               *maxprotp = cap_rights_to_vmprot(&fdrights);
 #endif
        return (error);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to