diff options
author | J. Bruce Fields <bfields@fieldses.org> | 2007-07-17 07:04:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-17 13:23:07 -0400 |
commit | 4b2ca38ad6c44ed0442092a829e6e954bf3580af (patch) | |
tree | d3256d5a1e2a0276326f8abb2e6aabc3df3812da /fs/nfsd/vfs.c | |
parent | 0ac68d17996eb421dde51452b89d5545ba07c6fe (diff) |
knfsd: nfsd4: fix handling of acl errrors
nfs4_acl_nfsv4_to_posix() returns an error and returns any posix acls
calculated in two caller-provided pointers. It was setting these pointers to
-errno in some error cases, resulting in nfsd4_set_nfs4_acl() calling
posix_acl_release() with a -errno as an argument.
Fix both the caller and the callee, by modifying nfsd4_set_nfs4_acl() to
stop relying on the passed-in-pointers being left as NULL in the error
case, and by modifying nfs4_acl_nfsv4_to_posix() to stop returning
garbage in those pointers.
Thanks to Alex Soule for reporting the bug.
Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu>
Cc: Alexander Soule <soule@umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 22 |
1 files changed, 7 insertions, 15 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 945b1cedde2b..8d6b5c483ae1 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -435,7 +435,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
435 | /* Get inode */ | 435 | /* Get inode */ |
436 | error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR); | 436 | error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR); |
437 | if (error) | 437 | if (error) |
438 | goto out; | 438 | return error; |
439 | 439 | ||
440 | dentry = fhp->fh_dentry; | 440 | dentry = fhp->fh_dentry; |
441 | inode = dentry->d_inode; | 441 | inode = dentry->d_inode; |
@@ -444,33 +444,25 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
444 | 444 | ||
445 | host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags); | 445 | host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags); |
446 | if (host_error == -EINVAL) { | 446 | if (host_error == -EINVAL) { |
447 | error = nfserr_attrnotsupp; | 447 | return nfserr_attrnotsupp; |
448 | goto out; | ||
449 | } else if (host_error < 0) | 448 | } else if (host_error < 0) |
450 | goto out_nfserr; | 449 | goto out_nfserr; |
451 | 450 | ||
452 | host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); | 451 | host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS); |
453 | if (host_error < 0) | 452 | if (host_error < 0) |
454 | goto out_nfserr; | 453 | goto out_release; |
455 | 454 | ||
456 | if (S_ISDIR(inode->i_mode)) { | 455 | if (S_ISDIR(inode->i_mode)) |
457 | host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); | 456 | host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT); |
458 | if (host_error < 0) | ||
459 | goto out_nfserr; | ||
460 | } | ||
461 | |||
462 | error = nfs_ok; | ||
463 | 457 | ||
464 | out: | 458 | out_release: |
465 | posix_acl_release(pacl); | 459 | posix_acl_release(pacl); |
466 | posix_acl_release(dpacl); | 460 | posix_acl_release(dpacl); |
467 | return (error); | ||
468 | out_nfserr: | 461 | out_nfserr: |
469 | if (host_error == -EOPNOTSUPP) | 462 | if (host_error == -EOPNOTSUPP) |
470 | error = nfserr_attrnotsupp; | 463 | return nfserr_attrnotsupp; |
471 | else | 464 | else |
472 | error = nfserrno(host_error); | 465 | return nfserrno(host_error); |
473 | goto out; | ||
474 | } | 466 | } |
475 | 467 | ||
476 | static struct posix_acl * | 468 | static struct posix_acl * |