Commit 9dfd87da authored by J. Bruce Fields's avatar J. Bruce Fields

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: default avatarSimo Sorce <simo@redhat.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 6a36978e
...@@ -213,6 +213,30 @@ static int gssp_call(struct net *net, struct rpc_message *msg) ...@@ -213,6 +213,30 @@ static int gssp_call(struct net *net, struct rpc_message *msg)
return status; return status;
} }
static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
{
int i;
for (i = 0; i < arg->npages && arg->pages[i]; i++)
__free_page(arg->pages[i]);
}
static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
{
int i;
arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
for (i=0; i < arg->npages; i++) {
arg->pages[i] = alloc_page(GFP_KERNEL);
if (arg->pages[i] == NULL) {
gssp_free_receive_pages(arg);
return -ENOMEM;
}
}
return 0;
}
/* /*
* Public functions * Public functions
...@@ -261,10 +285,16 @@ int gssp_accept_sec_context_upcall(struct net *net, ...@@ -261,10 +285,16 @@ int gssp_accept_sec_context_upcall(struct net *net,
arg.context_handle = &ctxh; arg.context_handle = &ctxh;
res.output_token->len = GSSX_max_output_token_sz; res.output_token->len = GSSX_max_output_token_sz;
ret = gssp_alloc_receive_pages(&arg);
if (ret)
return ret;
/* use nfs/ for targ_name ? */ /* use nfs/ for targ_name ? */
ret = gssp_call(net, &msg); ret = gssp_call(net, &msg);
gssp_free_receive_pages(&arg);
/* we need to fetch all data even in case of error so /* we need to fetch all data even in case of error so
* that we can free special strctures is they have been allocated */ * that we can free special strctures is they have been allocated */
data->major_status = res.status.major_status; data->major_status = res.status.major_status;
......
...@@ -780,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req, ...@@ -780,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req,
/* arg->options */ /* arg->options */
err = dummy_enc_opt_array(xdr, &arg->options); err = dummy_enc_opt_array(xdr, &arg->options);
xdr_inline_pages(&req->rq_rcv_buf,
PAGE_SIZE/2 /* pretty arbitrary */,
arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
done: done:
if (err) if (err)
dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
......
...@@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context { ...@@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context {
struct gssx_cb *input_cb; struct gssx_cb *input_cb;
u32 ret_deleg_cred; u32 ret_deleg_cred;
struct gssx_option_array options; struct gssx_option_array options;
struct page **pages;
unsigned int npages;
}; };
struct gssx_res_accept_sec_context { struct gssx_res_accept_sec_context {
...@@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, ...@@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
2 * GSSX_max_princ_sz + \ 2 * GSSX_max_princ_sz + \
8 + 8 + 4 + 4 + 4) 8 + 8 + 4 + 4 + 4)
#define GSSX_max_output_token_sz 1024 #define GSSX_max_output_token_sz 1024
#define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4) /* grouplist not included; we allocate separate pages for that: */
#define GSSX_max_creds_sz (4 + 4 + 4 /* + NGROUPS_MAX*4 */)
#define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \ #define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \
GSSX_default_ctx_sz + \ GSSX_default_ctx_sz + \
GSSX_max_output_token_sz + \ GSSX_max_output_token_sz + \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment