[patch] fix for major securty problem in dquota code

Andrea Arcangeli (andrea@e-mind.com)
Thu, 11 Mar 1999 22:54:19 +0100 (CET)


My friend Andrea Borgia (master admin of our University) reported to me
this afternoon that dquota could be overridden by the nfs-server on 2.2.x
kernels.

I took a look and and the problem was exactly what I anticipated to you
today (since you said me that quota was fine except when using the
nfs-userspace-server, that's the only bit of code that play with fsuid ;).
The problem is that dquot think that the initiator of the operation is the
euid of nfsd (and nfsd run as root) and not the euid of the student that
is using the NFS client (stored instead in the fsuid field).

I developed a completly untested fix against 2.2.3.

AndreaB let me know if this will fix things for you. I am quite sure of
yes (this is why I just posted to the list and to Linus ;).

Index: fs/dquot.c
===================================================================
RCS file: /var/cvs/linux/fs/dquot.c,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 dquot.c
--- dquot.c 1999/03/09 01:23:51 1.1.2.2
+++ linux/fs/dquot.c 1999/03/11 21:38:34
@@ -21,6 +21,9 @@
* Revised list management to avoid races
* -- Bill Hawes, <whawes@star.net>, 9/98
*
+ * Fixed Major Security problem exploitable via NFS because was used
+ * euid instead of fsuid on all checks. -arca
+ *
* (C) Copyright 1994 - 1997 Marco van Wieringen
*/

Index: include/linux/quotaops.h
===================================================================
RCS file: /var/cvs/linux/include/linux/quotaops.h,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 quotaops.h
--- quotaops.h 1999/01/18 01:33:17 1.1.2.1
+++ linux/include/linux/quotaops.h 1999/03/11 21:36:42
@@ -55,7 +55,7 @@
{
if (sb->dq_op) {
if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
- current->euid, 0) == NO_QUOTA)
+ current->fsuid, 0) == NO_QUOTA)
return 1;
}
return 0;
@@ -65,7 +65,7 @@
{
if (sb->dq_op) {
if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize),
- current->euid, 1) == NO_QUOTA)
+ current->fsuid, 1) == NO_QUOTA)
return 1;
}
return 0;
@@ -75,7 +75,7 @@
{
if (sb->dq_op) {
sb->dq_op->initialize (inode, -1);
- if (sb->dq_op->alloc_inode (inode, 1, current->euid))
+ if (sb->dq_op->alloc_inode (inode, 1, current->fsuid))
return 1;
}
inode->i_flags |= S_QUOTA;
@@ -101,11 +101,11 @@
if (dentry->d_inode->i_sb->dq_op) {
if (IS_QUOTAINIT(dentry->d_inode) == 0)
dentry->d_inode->i_sb->dq_op->initialize(dentry->d_inode, -1);
- if (dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 0, current->euid))
+ if (dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 0, current->fsuid))
goto out;
error = notify_change(dentry, iattr);
if (error)
- dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 1, current->euid);
+ dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 1, current->fsuid);
} else {
error = notify_change(dentry, iattr);
}

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/