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
This commit is contained in:
Kirk McKusick 2019-07-31 22:44:58 +00:00
parent 0a36d8cc81
commit 90381b1ca9
4 changed files with 8 additions and 6 deletions

View File

@ -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 @@ ffs_truncate(vp, length, flags, cred)
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);

View File

@ -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);

View File

@ -159,6 +159,7 @@ chkdq(struct inode *ip, ufs2_daddr_t change, struct ucred *cred, int flags)
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, int flags)
struct dquot *dq;
int i, error, warn, do_check;
MPASS(cred != NOCRED || (flags & FORCE) != 0);
#ifdef DIAGNOSTIC
if ((flags & CHOWN) == 0)
chkdquot(ip);

View File

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