diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-10 23:04:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-10 23:04:59 -0400 |
commit | cf596766fc53bbfa0e2b21e3569932aa54f5f9ca (patch) | |
tree | 6e88bae48c06f5b4a099989abb04178b939d2b24 /net/sunrpc | |
parent | 516f7b3f2a7dbe93d3075e76a06bbfcd0c0ee4f7 (diff) | |
parent | d4a516560fc96a9d486a9939bcb567e3fdce8f49 (diff) |
Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields:
"This was a very quiet cycle! Just a few bugfixes and some cleanup"
* 'nfsd-next' of git://linux-nfs.org/~bfields/linux:
rpc: let xdr layer allocate gssproxy receieve pages
rpc: fix huge kmalloc's in gss-proxy
rpc: comment on linux_cred encoding, treat all as unsigned
rpc: clean up decoding of gssproxy linux creds
svcrpc: remove unused rq_resused
nfsd4: nfsd4_create_clid_dir prints uninitialized data
nfsd4: fix leak of inode reference on delegation failure
Revert "nfsd: nfs4_file_get_access: need to be more careful with O_RDWR"
sunrpc: prepare NFS for 2038
nfsd4: fix setlease error return
nfsd: nfs4_file_get_access: need to be more careful with O_RDWR
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_upcall.c | 26 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_xdr.c | 41 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_xdr.h | 5 |
3 files changed, 50 insertions, 22 deletions
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c index af7ffd447fee..f1eb0d16666c 100644 --- a/net/sunrpc/auth_gss/gss_rpc_upcall.c +++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c | |||
@@ -213,6 +213,26 @@ static int gssp_call(struct net *net, struct rpc_message *msg) | |||
213 | return status; | 213 | return status; |
214 | } | 214 | } |
215 | 215 | ||
216 | static 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 | |||
224 | static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg) | ||
225 | { | ||
226 | arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE); | ||
227 | arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL); | ||
228 | /* | ||
229 | * XXX: actual pages are allocated by xdr layer in | ||
230 | * xdr_partial_copy_from_skb. | ||
231 | */ | ||
232 | if (!arg->pages) | ||
233 | return -ENOMEM; | ||
234 | return 0; | ||
235 | } | ||
216 | 236 | ||
217 | /* | 237 | /* |
218 | * Public functions | 238 | * Public functions |
@@ -261,10 +281,16 @@ int gssp_accept_sec_context_upcall(struct net *net, | |||
261 | arg.context_handle = &ctxh; | 281 | arg.context_handle = &ctxh; |
262 | res.output_token->len = GSSX_max_output_token_sz; | 282 | res.output_token->len = GSSX_max_output_token_sz; |
263 | 283 | ||
284 | ret = gssp_alloc_receive_pages(&arg); | ||
285 | if (ret) | ||
286 | return ret; | ||
287 | |||
264 | /* use nfs/ for targ_name ? */ | 288 | /* use nfs/ for targ_name ? */ |
265 | 289 | ||
266 | ret = gssp_call(net, &msg); | 290 | ret = gssp_call(net, &msg); |
267 | 291 | ||
292 | gssp_free_receive_pages(&arg); | ||
293 | |||
268 | /* we need to fetch all data even in case of error so | 294 | /* we need to fetch all data even in case of error so |
269 | * that we can free special strctures is they have been allocated */ | 295 | * that we can free special strctures is they have been allocated */ |
270 | data->major_status = res.status.major_status; | 296 | 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 3c85d1c8a028..f0f78c5f1c7d 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c | |||
@@ -166,14 +166,15 @@ static int dummy_dec_opt_array(struct xdr_stream *xdr, | |||
166 | return 0; | 166 | return 0; |
167 | } | 167 | } |
168 | 168 | ||
169 | static int get_s32(void **p, void *max, s32 *res) | 169 | static int get_host_u32(struct xdr_stream *xdr, u32 *res) |
170 | { | 170 | { |
171 | void *base = *p; | 171 | __be32 *p; |
172 | void *next = (void *)((char *)base + sizeof(s32)); | 172 | |
173 | if (unlikely(next > max || next < base)) | 173 | p = xdr_inline_decode(xdr, 4); |
174 | if (!p) | ||
174 | return -EINVAL; | 175 | return -EINVAL; |
175 | memcpy(res, base, sizeof(s32)); | 176 | /* Contents of linux creds are all host-endian: */ |
176 | *p = next; | 177 | memcpy(res, p, sizeof(u32)); |
177 | return 0; | 178 | return 0; |
178 | } | 179 | } |
179 | 180 | ||
@@ -182,9 +183,9 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
182 | { | 183 | { |
183 | u32 length; | 184 | u32 length; |
184 | __be32 *p; | 185 | __be32 *p; |
185 | void *q, *end; | 186 | u32 tmp; |
186 | s32 tmp; | 187 | u32 N; |
187 | int N, i, err; | 188 | int i, err; |
188 | 189 | ||
189 | p = xdr_inline_decode(xdr, 4); | 190 | p = xdr_inline_decode(xdr, 4); |
190 | if (unlikely(p == NULL)) | 191 | if (unlikely(p == NULL)) |
@@ -192,33 +193,28 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
192 | 193 | ||
193 | length = be32_to_cpup(p); | 194 | length = be32_to_cpup(p); |
194 | 195 | ||
195 | /* FIXME: we do not want to use the scratch buffer for this one | 196 | if (length > (3 + NGROUPS_MAX) * sizeof(u32)) |
196 | * may need to use functions that allows us to access an io vector | ||
197 | * directly */ | ||
198 | p = xdr_inline_decode(xdr, length); | ||
199 | if (unlikely(p == NULL)) | ||
200 | return -ENOSPC; | 197 | return -ENOSPC; |
201 | 198 | ||
202 | q = p; | ||
203 | end = q + length; | ||
204 | |||
205 | /* uid */ | 199 | /* uid */ |
206 | err = get_s32(&q, end, &tmp); | 200 | err = get_host_u32(xdr, &tmp); |
207 | if (err) | 201 | if (err) |
208 | return err; | 202 | return err; |
209 | creds->cr_uid = make_kuid(&init_user_ns, tmp); | 203 | creds->cr_uid = make_kuid(&init_user_ns, tmp); |
210 | 204 | ||
211 | /* gid */ | 205 | /* gid */ |
212 | err = get_s32(&q, end, &tmp); | 206 | err = get_host_u32(xdr, &tmp); |
213 | if (err) | 207 | if (err) |
214 | return err; | 208 | return err; |
215 | creds->cr_gid = make_kgid(&init_user_ns, tmp); | 209 | creds->cr_gid = make_kgid(&init_user_ns, tmp); |
216 | 210 | ||
217 | /* number of additional gid's */ | 211 | /* number of additional gid's */ |
218 | err = get_s32(&q, end, &tmp); | 212 | err = get_host_u32(xdr, &tmp); |
219 | if (err) | 213 | if (err) |
220 | return err; | 214 | return err; |
221 | N = tmp; | 215 | N = tmp; |
216 | if ((3 + N) * sizeof(u32) != length) | ||
217 | return -EINVAL; | ||
222 | creds->cr_group_info = groups_alloc(N); | 218 | creds->cr_group_info = groups_alloc(N); |
223 | if (creds->cr_group_info == NULL) | 219 | if (creds->cr_group_info == NULL) |
224 | return -ENOMEM; | 220 | return -ENOMEM; |
@@ -226,7 +222,7 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
226 | /* gid's */ | 222 | /* gid's */ |
227 | for (i = 0; i < N; i++) { | 223 | for (i = 0; i < N; i++) { |
228 | kgid_t kgid; | 224 | kgid_t kgid; |
229 | err = get_s32(&q, end, &tmp); | 225 | err = get_host_u32(xdr, &tmp); |
230 | if (err) | 226 | if (err) |
231 | goto out_free_groups; | 227 | goto out_free_groups; |
232 | err = -EINVAL; | 228 | err = -EINVAL; |
@@ -784,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req, | |||
784 | /* arg->options */ | 780 | /* arg->options */ |
785 | err = dummy_enc_opt_array(xdr, &arg->options); | 781 | err = dummy_enc_opt_array(xdr, &arg->options); |
786 | 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); | ||
787 | done: | 786 | done: |
788 | if (err) | 787 | if (err) |
789 | 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 | ||
152 | struct gssx_res_accept_sec_context { | 154 | struct 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 + \ |