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>
This commit is contained in:
parent
6a36978e69
commit
9dfd87da1a
|
@ -213,6 +213,30 @@ static int gssp_call(struct net *net, struct rpc_message *msg)
|
|||
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
|
||||
|
@ -261,10 +285,16 @@ int gssp_accept_sec_context_upcall(struct net *net,
|
|||
arg.context_handle = &ctxh;
|
||||
res.output_token->len = GSSX_max_output_token_sz;
|
||||
|
||||
ret = gssp_alloc_receive_pages(&arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* use nfs/ for targ_name ? */
|
||||
|
||||
ret = gssp_call(net, &msg);
|
||||
|
||||
gssp_free_receive_pages(&arg);
|
||||
|
||||
/* we need to fetch all data even in case of error so
|
||||
* that we can free special strctures is they have been allocated */
|
||||
data->major_status = res.status.major_status;
|
||||
|
|
|
@ -780,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req,
|
|||
/* 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:
|
||||
if (err)
|
||||
dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
|
||||
|
|
|
@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context {
|
|||
struct gssx_cb *input_cb;
|
||||
u32 ret_deleg_cred;
|
||||
struct gssx_option_array options;
|
||||
struct page **pages;
|
||||
unsigned int npages;
|
||||
};
|
||||
|
||||
struct gssx_res_accept_sec_context {
|
||||
|
@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
|
|||
2 * GSSX_max_princ_sz + \
|
||||
8 + 8 + 4 + 4 + 4)
|
||||
#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 + \
|
||||
GSSX_default_ctx_sz + \
|
||||
GSSX_max_output_token_sz + \
|
||||
|
|
Loading…
Reference in a new issue