aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c35
1 files changed, 17 insertions, 18 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 304bf5f643c9..a3a291f771f4 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -264,7 +264,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
264 struct inode *inode; 264 struct inode *inode;
265 int accmode = MAY_SATTR; 265 int accmode = MAY_SATTR;
266 int ftype = 0; 266 int ftype = 0;
267 int imode;
268 __be32 err; 267 __be32 err;
269 int host_err; 268 int host_err;
270 int size_change = 0; 269 int size_change = 0;
@@ -360,25 +359,25 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
360 DQUOT_INIT(inode); 359 DQUOT_INIT(inode);
361 } 360 }
362 361
363 imode = inode->i_mode; 362 /* sanitize the mode change */
364 if (iap->ia_valid & ATTR_MODE) { 363 if (iap->ia_valid & ATTR_MODE) {
365 iap->ia_mode &= S_IALLUGO; 364 iap->ia_mode &= S_IALLUGO;
366 imode = iap->ia_mode |= (imode & ~S_IALLUGO); 365 iap->ia_mode |= (inode->i_mode & ~S_IALLUGO);
367 /* if changing uid/gid revoke setuid/setgid in mode */ 366 }
368 if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) { 367
369 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 */
370 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);
371 } 380 }
372 if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
373 iap->ia_mode &= ~S_ISGID;
374 } else {
375 /*
376 * Revoke setuid/setgid bit on chown/chgrp
377 */
378 if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
379 iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV;
380 if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
381 iap->ia_valid |= ATTR_KILL_SGID;
382 } 381 }
383 382
384 /* Change the attributes. */ 383 /* Change the attributes. */
@@ -988,7 +987,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
988 * flushing the data to disk is handled separately below. 987 * flushing the data to disk is handled separately below.
989 */ 988 */
990 989
991 if (file->f_op->fsync == 0) {/* COMMIT3 cannot work */ 990 if (!file->f_op->fsync) {/* COMMIT3 cannot work */
992 stable = 2; 991 stable = 2;
993 *stablep = 2; /* FILE_SYNC */ 992 *stablep = 2; /* FILE_SYNC */
994 } 993 }
@@ -1152,7 +1151,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1152} 1151}
1153#endif /* CONFIG_NFSD_V3 */ 1152#endif /* CONFIG_NFSD_V3 */
1154 1153
1155__be32 1154static __be32
1156nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp, 1155nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
1157 struct iattr *iap) 1156 struct iattr *iap)
1158{ 1157{