diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1d0406c31a44..a3a291f771f4 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -359,24 +359,25 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
359 | DQUOT_INIT(inode); | 359 | DQUOT_INIT(inode); |
360 | } | 360 | } |
361 | 361 | ||
362 | /* sanitize the mode change */ | ||
362 | if (iap->ia_valid & ATTR_MODE) { | 363 | if (iap->ia_valid & ATTR_MODE) { |
363 | iap->ia_mode &= S_IALLUGO; | 364 | iap->ia_mode &= S_IALLUGO; |
364 | iap->ia_mode |= (inode->i_mode & ~S_IALLUGO); | 365 | iap->ia_mode |= (inode->i_mode & ~S_IALLUGO); |
365 | /* if changing uid/gid revoke setuid/setgid in mode */ | 366 | } |
366 | if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) { | 367 | |
367 | iap->ia_valid |= ATTR_KILL_PRIV; | 368 | /* Revoke setuid/setgid on chown */ |
369 | if (((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) || | ||
370 | ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)) { | ||
371 | iap->ia_valid |= ATTR_KILL_PRIV; | ||
372 | if (iap->ia_valid & ATTR_MODE) { | ||
373 | /* we're setting mode too, just clear the s*id bits */ | ||
368 | iap->ia_mode &= ~S_ISUID; | 374 | iap->ia_mode &= ~S_ISUID; |
375 | if (iap->ia_mode & S_IXGRP) | ||
376 | iap->ia_mode &= ~S_ISGID; | ||
377 | } else { | ||
378 | /* set ATTR_KILL_* bits and let VFS handle it */ | ||
379 | iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID); | ||
369 | } | 380 | } |
370 | if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid) | ||
371 | iap->ia_mode &= ~S_ISGID; | ||
372 | } else { | ||
373 | /* | ||
374 | * Revoke setuid/setgid bit on chown/chgrp | ||
375 | */ | ||
376 | if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) | ||
377 | iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV; | ||
378 | if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid) | ||
379 | iap->ia_valid |= ATTR_KILL_SGID; | ||
380 | } | 381 | } |
381 | 382 | ||
382 | /* Change the attributes. */ | 383 | /* Change the attributes. */ |