aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Mayhew <smayhew@redhat.com>2015-04-28 16:29:53 -0400
committerJ. Bruce Fields <bfields@redhat.com>2015-05-04 12:02:40 -0400
commit9507271d960a1911a51683888837d75c171cd91f (patch)
tree51ae70d0b2257ec9e32c78ade5e953dca00acdc2
parent8287f009bd95a5e548059dba62a67727bb9549cd (diff)
svcrpc: fix potential GSSX_ACCEPT_SEC_CONTEXT decoding failures
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> Cc: stable@vger.kernel.org Reviewed-by: Simo Sorce <simo@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_xdr.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
index 1ec19f6f0c2b..eeeba5adee6d 100644
--- 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 rpc_rqst *rqstp,
793{ 793{
794 u32 value_follows; 794 u32 value_follows;
795 int err; 795 int err;
796 struct page *scratch;
797
798 scratch = alloc_page(GFP_KERNEL);
799 if (!scratch)
800 return -ENOMEM;
801 xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE);
796 802
797 /* res->status */ 803 /* res->status */
798 err = gssx_dec_status(xdr, &res->status); 804 err = gssx_dec_status(xdr, &res->status);
799 if (err) 805 if (err)
800 return err; 806 goto out_free;
801 807
802 /* res->context_handle */ 808 /* res->context_handle */
803 err = gssx_dec_bool(xdr, &value_follows); 809 err = gssx_dec_bool(xdr, &value_follows);
804 if (err) 810 if (err)
805 return err; 811 goto out_free;
806 if (value_follows) { 812 if (value_follows) {
807 err = gssx_dec_ctx(xdr, res->context_handle); 813 err = gssx_dec_ctx(xdr, res->context_handle);
808 if (err) 814 if (err)
809 return err; 815 goto out_free;
810 } else { 816 } else {
811 res->context_handle = NULL; 817 res->context_handle = NULL;
812 } 818 }
@@ -814,11 +820,11 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
814 /* res->output_token */ 820 /* res->output_token */
815 err = gssx_dec_bool(xdr, &value_follows); 821 err = gssx_dec_bool(xdr, &value_follows);
816 if (err) 822 if (err)
817 return err; 823 goto out_free;
818 if (value_follows) { 824 if (value_follows) {
819 err = gssx_dec_buffer(xdr, res->output_token); 825 err = gssx_dec_buffer(xdr, res->output_token);
820 if (err) 826 if (err)
821 return err; 827 goto out_free;
822 } else { 828 } else {
823 res->output_token = NULL; 829 res->output_token = NULL;
824 } 830 }
@@ -826,14 +832,17 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
826 /* res->delegated_cred_handle */ 832 /* res->delegated_cred_handle */
827 err = gssx_dec_bool(xdr, &value_follows); 833 err = gssx_dec_bool(xdr, &value_follows);
828 if (err) 834 if (err)
829 return err; 835 goto out_free;
830 if (value_follows) { 836 if (value_follows) {
831 /* we do not support upcall servers sending this data. */ 837 /* we do not support upcall servers sending this data. */
832 return -EINVAL; 838 err = -EINVAL;
839 goto out_free;
833 } 840 }
834 841
835 /* res->options */ 842 /* res->options */
836 err = gssx_dec_option_array(xdr, &res->options); 843 err = gssx_dec_option_array(xdr, &res->options);
837 844
845out_free:
846 __free_page(scratch);
838 return err; 847 return err;
839} 848}