OSDN Git Service

nfsd: Return EPERM, not EACCES, in some SETATTR cases
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / nfsd / vfs.c
index 17138a9..7745d0a 100644 (file)
@@ -387,10 +387,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
        bool            get_write_count;
        bool            size_change = (iap->ia_valid & ATTR_SIZE);
 
-       if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
+       if (iap->ia_valid & ATTR_SIZE) {
                accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
-       if (iap->ia_valid & ATTR_SIZE)
                ftype = S_IFREG;
+       }
+
+       /*
+        * If utimes(2) and friends are called with times not NULL, we should
+        * not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
+        * will return EACCESS, when the caller's effective UID does not match
+        * the owner of the file, and the caller is not privileged. In this
+        * situation, we should return EPERM(notify_change will return this).
+        */
+       if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
+               accmode |= NFSD_MAY_OWNER_OVERRIDE;
+               if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
+                       accmode |= NFSD_MAY_WRITE;
+       }
 
        /* Callers that do fh_verify should do the fh_want_write: */
        get_write_count = !fhp->fh_dentry;