diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-02-19 16:08:27 -0500 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2017-02-21 16:56:16 -0500 |
commit | 6da59ce2fd2047fd9cb141479f20d5f84614e84f (patch) | |
tree | 7007e354377157d35bc78de64978e652086c205a /fs/nfs/nfs4xdr.c | |
parent | ab6e9aaf16cfdfca630f9745fd6d453818df7f64 (diff) |
NFSv4: Replace the open coded decode_opaque_inline() with the new generic
Also ensure that we always check that the size of the decoded object
matches the expectation that it must be smaller than NFS4_OPAQUE_LIMIT.
This should be true for all the current users of decode_opaque_inline(),
including decode_ace(), decode_pathname(), decode_attr_fs_locations()
and decode_exchange_id().
Note that this allows us to get rid of a number of existing checks in
decode_exchange_id(),
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 29 |
1 files changed, 8 insertions, 21 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5f0a6fcd0030..d10cc2a62dff 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3050,20 +3050,15 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | |||
3050 | 3050 | ||
3051 | static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) | 3051 | static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string) |
3052 | { | 3052 | { |
3053 | __be32 *p; | 3053 | ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string, |
3054 | 3054 | NFS4_OPAQUE_LIMIT); | |
3055 | p = xdr_inline_decode(xdr, 4); | 3055 | if (unlikely(ret < 0)) { |
3056 | if (unlikely(!p)) | 3056 | if (ret == -EBADMSG) |
3057 | goto out_overflow; | 3057 | print_overflow_msg(__func__, xdr); |
3058 | *len = be32_to_cpup(p); | 3058 | return -EIO; |
3059 | p = xdr_inline_decode(xdr, *len); | 3059 | } |
3060 | if (unlikely(!p)) | 3060 | *len = ret; |
3061 | goto out_overflow; | ||
3062 | *string = (char *)p; | ||
3063 | return 0; | 3061 | return 0; |
3064 | out_overflow: | ||
3065 | print_overflow_msg(__func__, xdr); | ||
3066 | return -EIO; | ||
3067 | } | 3062 | } |
3068 | 3063 | ||
3069 | static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) | 3064 | static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) |
@@ -5645,8 +5640,6 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5645 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5640 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5646 | if (unlikely(status)) | 5641 | if (unlikely(status)) |
5647 | return status; | 5642 | return status; |
5648 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | ||
5649 | return -EIO; | ||
5650 | memcpy(res->server_owner->major_id, dummy_str, dummy); | 5643 | memcpy(res->server_owner->major_id, dummy_str, dummy); |
5651 | res->server_owner->major_id_sz = dummy; | 5644 | res->server_owner->major_id_sz = dummy; |
5652 | 5645 | ||
@@ -5654,8 +5647,6 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5654 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5647 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5655 | if (unlikely(status)) | 5648 | if (unlikely(status)) |
5656 | return status; | 5649 | return status; |
5657 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | ||
5658 | return -EIO; | ||
5659 | memcpy(res->server_scope->server_scope, dummy_str, dummy); | 5650 | memcpy(res->server_scope->server_scope, dummy_str, dummy); |
5660 | res->server_scope->server_scope_sz = dummy; | 5651 | res->server_scope->server_scope_sz = dummy; |
5661 | 5652 | ||
@@ -5670,16 +5661,12 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
5670 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5661 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5671 | if (unlikely(status)) | 5662 | if (unlikely(status)) |
5672 | return status; | 5663 | return status; |
5673 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | ||
5674 | return -EIO; | ||
5675 | memcpy(res->impl_id->domain, dummy_str, dummy); | 5664 | memcpy(res->impl_id->domain, dummy_str, dummy); |
5676 | 5665 | ||
5677 | /* nii_name */ | 5666 | /* nii_name */ |
5678 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | 5667 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); |
5679 | if (unlikely(status)) | 5668 | if (unlikely(status)) |
5680 | return status; | 5669 | return status; |
5681 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | ||
5682 | return -EIO; | ||
5683 | memcpy(res->impl_id->name, dummy_str, dummy); | 5670 | memcpy(res->impl_id->name, dummy_str, dummy); |
5684 | 5671 | ||
5685 | /* nii_date */ | 5672 | /* nii_date */ |