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
					
				
			
		
					 3 changed files with 37 additions and 1 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 J. Bruce Fields
				J. Bruce Fields