Author: mckusick
Date: Wed Jul 31 22:44:58 2019
New Revision: 350490
URL: https://svnweb.freebsd.org/changeset/base/350490

Log:
  When updating the user or group disk quotas for the return of inodes or
  disk blocks, set the FORCE flag in the call to chkiq() or chkdq() since
  the user is always allowed to return resources and hence there is no need
  to check the user's credential .
  
  Reported by:    Christopher Krah, Thomas Barabosch, and Jan-Niclas Hilgert of 
Fraunhofer FKIE
  Reported as:    FS-1-UFS-1: Denial Of Service in mount (prison_priv_check)
  Discussed with: kib
  MFC:            1 week
  Sponsored by:   Netflix

Modified:
  head/sys/ufs/ffs/ffs_inode.c
  head/sys/ufs/ffs/ffs_softdep.c
  head/sys/ufs/ufs/ufs_quota.c
  head/sys/ufs/ufs/ufs_vnops.c

Modified: head/sys/ufs/ffs/ffs_inode.c
==============================================================================
--- head/sys/ufs/ffs/ffs_inode.c        Wed Jul 31 21:48:35 2019        
(r350489)
+++ head/sys/ufs/ffs/ffs_inode.c        Wed Jul 31 22:44:58 2019        
(r350490)
@@ -263,7 +263,7 @@ ffs_truncate(vp, length, flags, cred)
                        if ((error = ffs_syncvnode(vp, MNT_WAIT, 0)) != 0)
                                return (error);
 #ifdef QUOTA
-                       (void) chkdq(ip, -extblocks, NOCRED, 0);
+                       (void) chkdq(ip, -extblocks, NOCRED, FORCE);
 #endif
                        vinvalbuf(vp, V_ALT, 0, 0);
                        vn_pages_remove(vp,
@@ -621,7 +621,7 @@ done:
                DIP_SET(ip, i_blocks, 0);
        ip->i_flag |= IN_CHANGE;
 #ifdef QUOTA
-       (void) chkdq(ip, -blocksreleased, NOCRED, 0);
+       (void) chkdq(ip, -blocksreleased, NOCRED, FORCE);
 #endif
        return (allerror);
 

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c      Wed Jul 31 21:48:35 2019        
(r350489)
+++ head/sys/ufs/ffs/ffs_softdep.c      Wed Jul 31 22:44:58 2019        
(r350490)
@@ -6682,7 +6682,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
 #ifdef QUOTA
        /* Reference the quotas in case the block count is wrong in the end. */
        quotaref(vp, freeblks->fb_quota);
-       (void) chkdq(ip, -datablocks, NOCRED, 0);
+       (void) chkdq(ip, -datablocks, NOCRED, FORCE);
 #endif
        freeblks->fb_chkcnt = -datablocks;
        UFS_LOCK(ump);
@@ -6946,7 +6946,7 @@ softdep_setup_freeblocks(ip, length, flags)
 #ifdef QUOTA
        /* Reference the quotas in case the block count is wrong in the end. */
        quotaref(ITOV(ip), freeblks->fb_quota);
-       (void) chkdq(ip, -datablocks, NOCRED, 0);
+       (void) chkdq(ip, -datablocks, NOCRED, FORCE);
 #endif
        freeblks->fb_chkcnt = -datablocks;
        UFS_LOCK(ump);

Modified: head/sys/ufs/ufs/ufs_quota.c
==============================================================================
--- head/sys/ufs/ufs/ufs_quota.c        Wed Jul 31 21:48:35 2019        
(r350489)
+++ head/sys/ufs/ufs/ufs_quota.c        Wed Jul 31 22:44:58 2019        
(r350490)
@@ -159,6 +159,7 @@ chkdq(struct inode *ip, ufs2_daddr_t change, struct uc
        struct vnode *vp = ITOV(ip);
        int i, error, warn, do_check;
 
+       MPASS(cred != NOCRED || (flags & FORCE) != 0);
        /*
         * Disk quotas must be turned off for system files.  Currently
         * snapshot and quota files.
@@ -311,6 +312,7 @@ chkiq(struct inode *ip, int change, struct ucred *cred
        struct dquot *dq;
        int i, error, warn, do_check;
 
+       MPASS(cred != NOCRED || (flags & FORCE) != 0);
 #ifdef DIAGNOSTIC
        if ((flags & CHOWN) == 0)
                chkdquot(ip);

Modified: head/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- head/sys/ufs/ufs/ufs_vnops.c        Wed Jul 31 21:48:35 2019        
(r350489)
+++ head/sys/ufs/ufs/ufs_vnops.c        Wed Jul 31 22:44:58 2019        
(r350490)
@@ -811,8 +811,8 @@ ufs_chown(vp, uid, gid, cred, td)
                ip->i_dquot[GRPQUOTA] = NODQUOT;
        }
        change = DIP(ip, i_blocks);
-       (void) chkdq(ip, -change, cred, CHOWN);
-       (void) chkiq(ip, -1, cred, CHOWN);
+       (void) chkdq(ip, -change, cred, CHOWN|FORCE);
+       (void) chkiq(ip, -1, cred, CHOWN|FORCE);
        for (i = 0; i < MAXQUOTAS; i++) {
                dqrele(vp, ip->i_dquot[i]);
                ip->i_dquot[i] = NODQUOT;
_______________________________________________
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