aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-08-20 18:13:27 -0400
committerJ. Bruce Fields <bfields@redhat.com>2013-09-06 11:45:58 -0400
commit9dfd87da1aeb0fd364167ad199f40fe96a6a87be (patch)
treeadf9d2edff56be3fa54e330b55b3c76fe51c25cf /net/sunrpc
parent6a36978e6931e6601be586eb313375335f2cfaa3 (diff)
rpc: fix huge kmalloc's in gss-proxy
The reply to a gssproxy can include up to NGROUPS_MAX gid's, which will take up more than a page. We therefore need to allocate an array of pages to hold the reply instead of trying to allocate a single huge buffer. Tested-by: Simo Sorce <simo@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c30
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_xdr.c3
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_xdr.h5
3 files changed, 37 insertions, 1 deletions
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index af7ffd447fee..be95af3d1058 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -213,6 +213,30 @@ static int gssp_call(struct net *net, struct rpc_message *msg)
213 return status; 213 return status;
214} 214}
215 215
216static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
217{
218 int i;
219
220 for (i = 0; i < arg->npages && arg->pages[i]; i++)
221 __free_page(arg->pages[i]);
222}
223
224static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
225{
226 int i;
227
228 arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
229 arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
230
231 for (i=0; i < arg->npages; i++) {
232 arg->pages[i] = alloc_page(GFP_KERNEL);
233 if (arg->pages[i] == NULL) {
234 gssp_free_receive_pages(arg);
235 return -ENOMEM;
236 }
237 }
238 return 0;
239}
216 240
217/* 241/*
218 * Public functions 242 * Public functions
@@ -261,10 +285,16 @@ int gssp_accept_sec_context_upcall(struct net *net,
261 arg.context_handle = &ctxh; 285 arg.context_handle = &ctxh;
262 res.output_token->len = GSSX_max_output_token_sz; 286 res.output_token->len = GSSX_max_output_token_sz;
263 287
288 ret = gssp_alloc_receive_pages(&arg);
289 if (ret)
290 return ret;
291
264 /* use nfs/ for targ_name ? */ 292 /* use nfs/ for targ_name ? */
265 293
266 ret = gssp_call(net, &msg); 294 ret = gssp_call(net, &msg);
267 295
296 gssp_free_receive_pages(&arg);
297
268 /* we need to fetch all data even in case of error so 298 /* we need to fetch all data even in case of error so
269 * that we can free special strctures is they have been allocated */ 299 * that we can free special strctures is they have been allocated */
270 data->major_status = res.status.major_status; 300 data->major_status = res.status.major_status;
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
index 3c19c7d48899..f0f78c5f1c7d 100644
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
@@ -780,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req,
780 /* arg->options */ 780 /* arg->options */
781 err = dummy_enc_opt_array(xdr, &arg->options); 781 err = dummy_enc_opt_array(xdr, &arg->options);
782 782
783 xdr_inline_pages(&req->rq_rcv_buf,
784 PAGE_SIZE/2 /* pretty arbitrary */,
785 arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
783done: 786done:
784 if (err) 787 if (err)
785 dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); 788 dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.h b/net/sunrpc/auth_gss/gss_rpc_xdr.h
index 1c98b27d870c..685a688f3d8a 100644
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.h
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.h
@@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context {
147 struct gssx_cb *input_cb; 147 struct gssx_cb *input_cb;
148 u32 ret_deleg_cred; 148 u32 ret_deleg_cred;
149 struct gssx_option_array options; 149 struct gssx_option_array options;
150 struct page **pages;
151 unsigned int npages;
150}; 152};
151 153
152struct gssx_res_accept_sec_context { 154struct gssx_res_accept_sec_context {
@@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
240 2 * GSSX_max_princ_sz + \ 242 2 * GSSX_max_princ_sz + \
241 8 + 8 + 4 + 4 + 4) 243 8 + 8 + 4 + 4 + 4)
242#define GSSX_max_output_token_sz 1024 244#define GSSX_max_output_token_sz 1024
243#define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4) 245/* grouplist not included; we allocate separate pages for that: */
246#define GSSX_max_creds_sz (4 + 4 + 4 /* + NGROUPS_MAX*4 */)
244#define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \ 247#define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \
245 GSSX_default_ctx_sz + \ 248 GSSX_default_ctx_sz + \
246 GSSX_max_output_token_sz + \ 249 GSSX_max_output_token_sz + \