diff options
author | J. Bruce Fields <bfields@fieldses.org> | 2013-02-01 15:13:04 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-26 02:46:09 -0500 |
commit | 4f4a4faddea0fe45bf508e723c3a810c5190ed62 (patch) | |
tree | 8c34a07ce0258fcc187f0884f2fc58c7361686bb /fs/nfsd | |
parent | 3dadecce20603aa380023c65e6f55f108fd5e952 (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.c | 23 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 6 | ||||
-rw-r--r-- | fs/nfsd/xdr.h | 2 | ||||
-rw-r--r-- | fs/nfsd/xdr3.h | 2 |
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, | |||
129 | static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp, | 136 | static __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, | |||
274 | static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p, | 289 | static 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, | |||
282 | static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p, | 297 | static 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, | |||
167 | int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *); | 167 | int 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 | ||
141 | struct nfsd3_readlinkres { | 142 | struct 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 */ |