diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-06-16 13:15:41 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-06-16 13:24:47 -0400 |
commit | ee7b75fc4f3ae49e1f25bf56219bb5de3c29afaf (patch) | |
tree | 929f8cb07d4e974f5cfa8952a8d6643edfb5a2f5 /fs/nfs | |
parent | 9e2dfdb3081edfae66a49013517e80dd8a0469fa (diff) |
NFSv4: Fix a readdir regression
Commit 7ebb9315 (NFS: use secinfo when crossing mountpoints) introduces
a regression when decoding an NFSv4 readdir entry that sets the
rdattr_error field.
By treating the resulting value as if it is a decoding error, the current
code may cause us to skip valid readdir entries.
Reported-by: Andy Adamson <andros@netapp.com>
Cc: stable@kernel.org [2.6.39]
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c4b7d6c04948..5db44a8dddf9 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3098,7 +3098,7 @@ out_overflow: | |||
3098 | return -EIO; | 3098 | return -EIO; |
3099 | } | 3099 | } |
3100 | 3100 | ||
3101 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | 3101 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) |
3102 | { | 3102 | { |
3103 | __be32 *p; | 3103 | __be32 *p; |
3104 | 3104 | ||
@@ -3109,7 +3109,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | |||
3109 | if (unlikely(!p)) | 3109 | if (unlikely(!p)) |
3110 | goto out_overflow; | 3110 | goto out_overflow; |
3111 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | 3111 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; |
3112 | return -be32_to_cpup(p); | 3112 | *res = -be32_to_cpup(p); |
3113 | } | 3113 | } |
3114 | return 0; | 3114 | return 0; |
3115 | out_overflow: | 3115 | out_overflow: |
@@ -4070,6 +4070,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4070 | int status; | 4070 | int status; |
4071 | umode_t fmode = 0; | 4071 | umode_t fmode = 0; |
4072 | uint32_t type; | 4072 | uint32_t type; |
4073 | int32_t err; | ||
4073 | 4074 | ||
4074 | status = decode_attr_type(xdr, bitmap, &type); | 4075 | status = decode_attr_type(xdr, bitmap, &type); |
4075 | if (status < 0) | 4076 | if (status < 0) |
@@ -4095,13 +4096,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4095 | goto xdr_error; | 4096 | goto xdr_error; |
4096 | fattr->valid |= status; | 4097 | fattr->valid |= status; |
4097 | 4098 | ||
4098 | status = decode_attr_error(xdr, bitmap); | 4099 | err = 0; |
4099 | if (status == -NFS4ERR_WRONGSEC) { | 4100 | status = decode_attr_error(xdr, bitmap, &err); |
4100 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
4101 | status = 0; | ||
4102 | } | ||
4103 | if (status < 0) | 4101 | if (status < 0) |
4104 | goto xdr_error; | 4102 | goto xdr_error; |
4103 | if (err == -NFS4ERR_WRONGSEC) | ||
4104 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
4105 | 4105 | ||
4106 | status = decode_attr_filehandle(xdr, bitmap, fh); | 4106 | status = decode_attr_filehandle(xdr, bitmap, fh); |
4107 | if (status < 0) | 4107 | if (status < 0) |