| From 9507271d960a1911a51683888837d75c171cd91f Mon Sep 17 00:00:00 2001 |
| From: Scott Mayhew <smayhew@redhat.com> |
| Date: Tue, 28 Apr 2015 16:29:53 -0400 |
| Subject: svcrpc: fix potential GSSX_ACCEPT_SEC_CONTEXT decoding failures |
| |
| From: Scott Mayhew <smayhew@redhat.com> |
| |
| commit 9507271d960a1911a51683888837d75c171cd91f upstream. |
| |
| In an environment where the KDC is running Active Directory, the |
| exported composite name field returned in the context could be large |
| enough to span a page boundary. Attaching a scratch buffer to the |
| decoding xdr_stream helps deal with those cases. |
| |
| The case where we saw this was actually due to behavior that's been |
| fixed in newer gss-proxy versions, but we're fixing it here too. |
| |
| Signed-off-by: Scott Mayhew <smayhew@redhat.com> |
| Reviewed-by: Simo Sorce <simo@redhat.com> |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/sunrpc/auth_gss/gss_rpc_xdr.c | 23 ++++++++++++++++------- |
| 1 file changed, 16 insertions(+), 7 deletions(-) |
| |
| --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c |
| +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c |
| @@ -793,20 +793,26 @@ int gssx_dec_accept_sec_context(struct r |
| { |
| u32 value_follows; |
| int err; |
| + struct page *scratch; |
| + |
| + scratch = alloc_page(GFP_KERNEL); |
| + if (!scratch) |
| + return -ENOMEM; |
| + xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); |
| |
| /* res->status */ |
| err = gssx_dec_status(xdr, &res->status); |
| if (err) |
| - return err; |
| + goto out_free; |
| |
| /* res->context_handle */ |
| err = gssx_dec_bool(xdr, &value_follows); |
| if (err) |
| - return err; |
| + goto out_free; |
| if (value_follows) { |
| err = gssx_dec_ctx(xdr, res->context_handle); |
| if (err) |
| - return err; |
| + goto out_free; |
| } else { |
| res->context_handle = NULL; |
| } |
| @@ -814,11 +820,11 @@ int gssx_dec_accept_sec_context(struct r |
| /* res->output_token */ |
| err = gssx_dec_bool(xdr, &value_follows); |
| if (err) |
| - return err; |
| + goto out_free; |
| if (value_follows) { |
| err = gssx_dec_buffer(xdr, res->output_token); |
| if (err) |
| - return err; |
| + goto out_free; |
| } else { |
| res->output_token = NULL; |
| } |
| @@ -826,14 +832,17 @@ int gssx_dec_accept_sec_context(struct r |
| /* res->delegated_cred_handle */ |
| err = gssx_dec_bool(xdr, &value_follows); |
| if (err) |
| - return err; |
| + goto out_free; |
| if (value_follows) { |
| /* we do not support upcall servers sending this data. */ |
| - return -EINVAL; |
| + err = -EINVAL; |
| + goto out_free; |
| } |
| |
| /* res->options */ |
| err = gssx_dec_option_array(xdr, &res->options); |
| |
| +out_free: |
| + __free_page(scratch); |
| return err; |
| } |