aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@fieldses.org>2013-02-01 15:13:04 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2013-02-26 02:46:09 -0500
commit4f4a4faddea0fe45bf508e723c3a810c5190ed62 (patch)
tree8c34a07ce0258fcc187f0884f2fc58c7361686bb /fs/nfsd
parent3dadecce20603aa380023c65e6f55f108fd5e952 (diff)
nfsd: handle vfs_getattr errors in acl protocol
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>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs2acl.c23
-rw-r--r--fs/nfsd/nfsxdr.c6
-rw-r--r--fs/nfsd/xdr.h2
-rw-r--r--fs/nfsd/xdr3.h2
4 files changed, 24 insertions, 9 deletions
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 9170861c804a..95d76dc6c5da 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -45,6 +45,10 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
45 RETURN_STATUS(nfserr_inval); 45 RETURN_STATUS(nfserr_inval);
46 resp->mask = argp->mask; 46 resp->mask = argp->mask;
47 47
48 nfserr = fh_getattr(fh, &resp->stat);
49 if (nfserr)
50 goto fail;
51
48 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) { 52 if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
49 acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS); 53 acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
50 if (IS_ERR(acl)) { 54 if (IS_ERR(acl)) {
@@ -115,6 +119,9 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
115 nfserr = nfserrno( nfsd_set_posix_acl( 119 nfserr = nfserrno( nfsd_set_posix_acl(
116 fh, ACL_TYPE_DEFAULT, argp->acl_default) ); 120 fh, ACL_TYPE_DEFAULT, argp->acl_default) );
117 } 121 }
122 if (!nfserr) {
123 nfserr = fh_getattr(fh, &resp->stat);
124 }
118 125
119 /* argp->acl_{access,default} may have been allocated in 126 /* argp->acl_{access,default} may have been allocated in
120 nfssvc_decode_setaclargs. */ 127 nfssvc_decode_setaclargs. */
@@ -129,10 +136,15 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
129static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp, 136static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp,
130 struct nfsd_fhandle *argp, struct nfsd_attrstat *resp) 137 struct nfsd_fhandle *argp, struct nfsd_attrstat *resp)
131{ 138{
139 __be32 nfserr;
132 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); 140 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
133 141
134 fh_copy(&resp->fh, &argp->fh); 142 fh_copy(&resp->fh, &argp->fh);
135 return fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP); 143 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
144 if (nfserr)
145 return nfserr;
146 nfserr = fh_getattr(&resp->fh, &resp->stat);
147 return nfserr;
136} 148}
137 149
138/* 150/*
@@ -150,6 +162,9 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessarg
150 fh_copy(&resp->fh, &argp->fh); 162 fh_copy(&resp->fh, &argp->fh);
151 resp->access = argp->access; 163 resp->access = argp->access;
152 nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); 164 nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
165 if (nfserr)
166 return nfserr;
167 nfserr = fh_getattr(&resp->fh, &resp->stat);
153 return nfserr; 168 return nfserr;
154} 169}
155 170
@@ -243,7 +258,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
243 return 0; 258 return 0;
244 inode = dentry->d_inode; 259 inode = dentry->d_inode;
245 260
246 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); 261 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
247 *p++ = htonl(resp->mask); 262 *p++ = htonl(resp->mask);
248 if (!xdr_ressize_check(rqstp, p)) 263 if (!xdr_ressize_check(rqstp, p))
249 return 0; 264 return 0;
@@ -274,7 +289,7 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
274static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p, 289static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p,
275 struct nfsd_attrstat *resp) 290 struct nfsd_attrstat *resp)
276{ 291{
277 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); 292 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
278 return xdr_ressize_check(rqstp, p); 293 return xdr_ressize_check(rqstp, p);
279} 294}
280 295
@@ -282,7 +297,7 @@ static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p,
282static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p, 297static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,
283 struct nfsd3_accessres *resp) 298 struct nfsd3_accessres *resp)
284{ 299{
285 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh); 300 p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
286 *p++ = htonl(resp->access); 301 *p++ = htonl(resp->access);
287 return xdr_ressize_check(rqstp, p); 302 return xdr_ressize_check(rqstp, p);
288} 303}
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index bf6d3bccdd98..96e56192f984 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -195,11 +195,9 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
195} 195}
196 196
197/* Helper function for NFSv2 ACL code */ 197/* Helper function for NFSv2 ACL code */
198__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 198__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat)
199{ 199{
200 struct kstat stat; 200 return encode_fattr(rqstp, p, fhp, stat);
201 fh_getattr(fhp, &stat); /* BUG */
202 return encode_fattr(rqstp, p, fhp, &stat);
203} 201}
204 202
205/* 203/*
diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
index 53b1863dd8f6..4f0481d63804 100644
--- a/fs/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -167,7 +167,7 @@ int nfssvc_encode_entry(void *, const char *name,
167int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *); 167int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *);
168 168
169/* Helper functions for NFSv2 ACL code */ 169/* Helper functions for NFSv2 ACL code */
170__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp); 170__be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat);
171__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp); 171__be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp);
172 172
173#endif /* LINUX_NFSD_H */ 173#endif /* LINUX_NFSD_H */
diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
index 7df980eb0562..b6d5542a4ac8 100644
--- a/fs/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -136,6 +136,7 @@ struct nfsd3_accessres {
136 __be32 status; 136 __be32 status;
137 struct svc_fh fh; 137 struct svc_fh fh;
138 __u32 access; 138 __u32 access;
139 struct kstat stat;
139}; 140};
140 141
141struct nfsd3_readlinkres { 142struct nfsd3_readlinkres {
@@ -225,6 +226,7 @@ struct nfsd3_getaclres {
225 int mask; 226 int mask;
226 struct posix_acl *acl_access; 227 struct posix_acl *acl_access;
227 struct posix_acl *acl_default; 228 struct posix_acl *acl_default;
229 struct kstat stat;
228}; 230};
229 231
230/* dummy type for release */ 232/* dummy type for release */