Commit 588d6141 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] remove_suid() fix

From: viro@parcelfarce.linux.theplanet.co.uk

bernhard_heibler@gmx.de has discovered that NFS is very slow when writing to
a file which has execute permissions.  See

	http://bugme.osdl.org/show_bug.cgi?id=1936

This patch fixes remove_suid() to not try to modify the inode mode on every
write to such a file.
parent fea7cfba
......@@ -1495,22 +1495,35 @@ __grab_cache_page(struct address_space *mapping, unsigned long index,
return page;
}
/*
* The logic we want is
*
* if suid or (sgid and xgrp)
* remove privs
*/
void remove_suid(struct dentry *dentry)
{
struct iattr newattrs;
struct inode *inode = dentry->d_inode;
unsigned int mode = inode->i_mode & (S_ISUID|S_ISGID|S_IXGRP);
mode_t mode = dentry->d_inode->i_mode;
int kill = 0;
/* suid always must be killed */
if (unlikely(mode & S_ISUID))
kill = ATTR_KILL_SUID;
if (!(mode & S_IXGRP))
mode &= S_ISUID;
/*
* sgid without any exec bits is just a mandatory locking mark; leave
* it alone. If some exec bits are set, it's a real sgid; kill it.
*/
if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
kill |= ATTR_KILL_SGID;
/* were any of the uid bits set? */
if (mode && !capable(CAP_FSETID)) {
newattrs.ia_valid = ATTR_KILL_SUID|ATTR_KILL_SGID|ATTR_FORCE;
if (unlikely(kill && !capable(CAP_FSETID))) {
struct iattr newattrs;
newattrs.ia_valid = ATTR_FORCE | kill;
notify_change(dentry, &newattrs);
}
}
EXPORT_SYMBOL(remove_suid);
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment