nfsd: handle vfs_getattr errors in acl protocol
authorJ. Bruce Fields <bfields@fieldses.org>
Fri, 1 Feb 2013 20:13:04 +0000 (15:13 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 26 Feb 2013 07:46:09 +0000 (02:46 -0500)
We're currently ignoring errors from vfs_getattr.

The correct thing to do is to do the stat in the main service procedure
not in the response encoding.

Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/nfsd/nfs2acl.c
fs/nfsd/nfsxdr.c
fs/nfsd/xdr.h
fs/nfsd/xdr3.h

index 9170861c804a6de666e8ef385ec582d81b30bb92..95d76dc6c5da5bf313c4778eaa8220eb91ac1665 100644 (file)
@@ -45,6 +45,10 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
                RETURN_STATUS(nfserr_inval);
        resp->mask = argp->mask;
 
+       nfserr = fh_getattr(fh, &resp->stat);
+       if (nfserr)
+               goto fail;
+
        if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
                acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
                if (IS_ERR(acl)) {
@@ -115,6 +119,9 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
                nfserr = nfserrno( nfsd_set_posix_acl(
                        fh, ACL_TYPE_DEFAULT, argp->acl_default) );
        }
+       if (!nfserr) {
+               nfserr = fh_getattr(fh, &resp->stat);
+       }
 
        /* argp->acl_{access,default} may have been allocated in
           nfssvc_decode_setaclargs. */
@@ -129,10 +136,15 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
 static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp,
                struct nfsd_fhandle *argp, struct nfsd_attrstat *resp)
 {
+       __be32 nfserr;
        dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
 
        fh_copy(&resp->fh, &argp->fh);
-       return fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
+       nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
+       if (nfserr)
+               return nfserr;
+       nfserr = fh_getattr(&resp->fh, &resp->stat);
+       return nfserr;
 }
 
 /*
@@ -150,6 +162,9 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessarg
        fh_copy(&resp->fh, &argp->fh);
        resp->access = argp->access;
        nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
+       if (nfserr)
+               return nfserr;
+       nfserr = fh_getattr(&resp->fh, &resp->stat);
        return nfserr;
 }
 
@@ -243,7 +258,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
                return 0;
        inode = dentry->d_inode;
 
-       p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+       p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
        *p++ = htonl(resp->mask);
        if (!xdr_ressize_check(rqstp, p))
                return 0;
@@ -274,7 +289,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
 static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p,
                struct nfsd_attrstat *resp)
 {
-       p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+       p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
        return xdr_ressize_check(rqstp, p);
 }
 
@@ -282,7 +297,7 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p,
 static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,
                struct nfsd3_accessres *resp)
 {
-       p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+       p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
        *p++ = htonl(resp->access);
        return xdr_ressize_check(rqstp, p);
 }
index bf6d3bccdd98a2ec842d00922909025c0f106a67..96e56192f984d3cf05558d88deb6002b9045a40e 100644 (file)
@@ -195,11 +195,9 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
 }
 
 /* Helper function for NFSv2 ACL code */
-__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
+__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat)
 {
-       struct kstat stat;
-       fh_getattr(fhp, &stat); /* BUG */
-       return encode_fattr(rqstp, p, fhp, &stat);
+       return encode_fattr(rqstp, p, fhp, stat);
 }
 
 /*
index 53b1863dd8f67b2e86fda47490a773fa3b5d41f7..4f0481d638048feda597888969712ab1d2dd3a08 100644 (file)
@@ -167,7 +167,7 @@ int nfssvc_encode_entry(void *, const char *name,
 int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *);
 
 /* Helper functions for NFSv2 ACL code */
-__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp);
+__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat);
 __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp);
 
 #endif /* LINUX_NFSD_H */
index 7df980eb05628789a336f0dea422c4ac49904609..b6d5542a4ac8e185e48d9d7c64fab36f5068dd88 100644 (file)
@@ -136,6 +136,7 @@ struct nfsd3_accessres {
        __be32                  status;
        struct svc_fh           fh;
        __u32                   access;
+       struct kstat            stat;
 };
 
 struct nfsd3_readlinkres {
@@ -225,6 +226,7 @@ struct nfsd3_getaclres {
        int                     mask;
        struct posix_acl        *acl_access;
        struct posix_acl        *acl_default;
+       struct kstat            stat;
 };
 
 /* dummy type for release */