diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 11:32:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 11:32:58 -0400 |
commit | 419f4319495043a9507ac3e616be9ca60af09744 (patch) | |
tree | 0f747d80d11a6d4cd726ad6556839d5cd40b23ac /net | |
parent | fb21affa49204acd409328415b49bfe90136653c (diff) | |
parent | 6eccece90b6addf80ef9e6db79b0bc873301034b (diff) |
Merge branch 'for-3.5' of git://linux-nfs.org/~bfields/linux
Pull the rest of the nfsd commits from Bruce Fields:
"... and then I cherry-picked the remainder of the patches from the
head of my previous branch"
This is the rest of the original nfsd branch, rebased without the
delegation stuff that I thought really needed to be redone.
I don't like rebasing things like this in general, but in this situation
this was the lesser of two evils.
* 'for-3.5' of git://linux-nfs.org/~bfields/linux: (50 commits)
nfsd4: fix, consolidate client_has_state
nfsd4: don't remove rebooted client record until confirmation
nfsd4: remove some dprintk's and a comment
nfsd4: return "real" sequence id in confirmed case
nfsd4: fix exchange_id to return confirm flag
nfsd4: clarify that renewing expired client is a bug
nfsd4: simpler ordering of setclientid_confirm checks
nfsd4: setclientid: remove pointless assignment
nfsd4: fix error return in non-matching-creds case
nfsd4: fix setclientid_confirm same_cred check
nfsd4: merge 3 setclientid cases to 2
nfsd4: pull out common code from setclientid cases
nfsd4: merge last two setclientid cases
nfsd4: setclientid/confirm comment cleanup
nfsd4: setclientid remove unnecessary terms from a logical expression
nfsd4: move rq_flavor into svc_cred
nfsd4: stricter cred comparison for setclientid/exchange_id
nfsd4: move principal name into svc_cred
nfsd4: allow removing clients not holding state
nfsd4: rearrange exchange_id logic to simplify
...
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 61 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 27 | ||||
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 12 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 23 | ||||
-rw-r--r-- | net/sunrpc/svc_xprt.c | 4 | ||||
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 6 |
6 files changed, 75 insertions, 58 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 38f388c39dce..107c4528654f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -381,21 +381,53 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | /* | 383 | /* |
384 | * We cannot currently handle tokens with rotated data. We need a | 384 | * We can shift data by up to LOCAL_BUF_LEN bytes in a pass. If we need |
385 | * generalized routine to rotate the data in place. It is anticipated | 385 | * to do more than that, we shift repeatedly. Kevin Coffman reports |
386 | * that we won't encounter rotated data in the general case. | 386 | * seeing 28 bytes as the value used by Microsoft clients and servers |
387 | * with AES, so this constant is chosen to allow handling 28 in one pass | ||
388 | * without using too much stack space. | ||
389 | * | ||
390 | * If that proves to a problem perhaps we could use a more clever | ||
391 | * algorithm. | ||
387 | */ | 392 | */ |
388 | static u32 | 393 | #define LOCAL_BUF_LEN 32u |
389 | rotate_left(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, u16 rrc) | 394 | |
395 | static void rotate_buf_a_little(struct xdr_buf *buf, unsigned int shift) | ||
390 | { | 396 | { |
391 | unsigned int realrrc = rrc % (buf->len - offset - GSS_KRB5_TOK_HDR_LEN); | 397 | char head[LOCAL_BUF_LEN]; |
398 | char tmp[LOCAL_BUF_LEN]; | ||
399 | unsigned int this_len, i; | ||
400 | |||
401 | BUG_ON(shift > LOCAL_BUF_LEN); | ||
392 | 402 | ||
393 | if (realrrc == 0) | 403 | read_bytes_from_xdr_buf(buf, 0, head, shift); |
394 | return 0; | 404 | for (i = 0; i + shift < buf->len; i += LOCAL_BUF_LEN) { |
405 | this_len = min(LOCAL_BUF_LEN, buf->len - (i + shift)); | ||
406 | read_bytes_from_xdr_buf(buf, i+shift, tmp, this_len); | ||
407 | write_bytes_to_xdr_buf(buf, i, tmp, this_len); | ||
408 | } | ||
409 | write_bytes_to_xdr_buf(buf, buf->len - shift, head, shift); | ||
410 | } | ||
395 | 411 | ||
396 | dprintk("%s: cannot process token with rotated data: " | 412 | static void _rotate_left(struct xdr_buf *buf, unsigned int shift) |
397 | "rrc %u, realrrc %u\n", __func__, rrc, realrrc); | 413 | { |
398 | return 1; | 414 | int shifted = 0; |
415 | int this_shift; | ||
416 | |||
417 | shift %= buf->len; | ||
418 | while (shifted < shift) { | ||
419 | this_shift = min(shift - shifted, LOCAL_BUF_LEN); | ||
420 | rotate_buf_a_little(buf, this_shift); | ||
421 | shifted += this_shift; | ||
422 | } | ||
423 | } | ||
424 | |||
425 | static void rotate_left(u32 base, struct xdr_buf *buf, unsigned int shift) | ||
426 | { | ||
427 | struct xdr_buf subbuf; | ||
428 | |||
429 | xdr_buf_subsegment(buf, &subbuf, base, buf->len - base); | ||
430 | _rotate_left(&subbuf, shift); | ||
399 | } | 431 | } |
400 | 432 | ||
401 | static u32 | 433 | static u32 |
@@ -495,11 +527,8 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
495 | 527 | ||
496 | seqnum = be64_to_cpup((__be64 *)(ptr + 8)); | 528 | seqnum = be64_to_cpup((__be64 *)(ptr + 8)); |
497 | 529 | ||
498 | if (rrc != 0) { | 530 | if (rrc != 0) |
499 | err = rotate_left(kctx, offset, buf, rrc); | 531 | rotate_left(offset + 16, buf, rrc); |
500 | if (err) | ||
501 | return GSS_S_FAILURE; | ||
502 | } | ||
503 | 532 | ||
504 | err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf, | 533 | err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf, |
505 | &headskip, &tailskip); | 534 | &headskip, &tailskip); |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 3089de37c433..73e957386600 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -336,7 +336,6 @@ struct rsc { | |||
336 | struct svc_cred cred; | 336 | struct svc_cred cred; |
337 | struct gss_svc_seq_data seqdata; | 337 | struct gss_svc_seq_data seqdata; |
338 | struct gss_ctx *mechctx; | 338 | struct gss_ctx *mechctx; |
339 | char *client_name; | ||
340 | }; | 339 | }; |
341 | 340 | ||
342 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); | 341 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); |
@@ -347,9 +346,7 @@ static void rsc_free(struct rsc *rsci) | |||
347 | kfree(rsci->handle.data); | 346 | kfree(rsci->handle.data); |
348 | if (rsci->mechctx) | 347 | if (rsci->mechctx) |
349 | gss_delete_sec_context(&rsci->mechctx); | 348 | gss_delete_sec_context(&rsci->mechctx); |
350 | if (rsci->cred.cr_group_info) | 349 | free_svc_cred(&rsci->cred); |
351 | put_group_info(rsci->cred.cr_group_info); | ||
352 | kfree(rsci->client_name); | ||
353 | } | 350 | } |
354 | 351 | ||
355 | static void rsc_put(struct kref *ref) | 352 | static void rsc_put(struct kref *ref) |
@@ -387,7 +384,7 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp) | |||
387 | tmp->handle.data = NULL; | 384 | tmp->handle.data = NULL; |
388 | new->mechctx = NULL; | 385 | new->mechctx = NULL; |
389 | new->cred.cr_group_info = NULL; | 386 | new->cred.cr_group_info = NULL; |
390 | new->client_name = NULL; | 387 | new->cred.cr_principal = NULL; |
391 | } | 388 | } |
392 | 389 | ||
393 | static void | 390 | static void |
@@ -402,8 +399,8 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp) | |||
402 | spin_lock_init(&new->seqdata.sd_lock); | 399 | spin_lock_init(&new->seqdata.sd_lock); |
403 | new->cred = tmp->cred; | 400 | new->cred = tmp->cred; |
404 | tmp->cred.cr_group_info = NULL; | 401 | tmp->cred.cr_group_info = NULL; |
405 | new->client_name = tmp->client_name; | 402 | new->cred.cr_principal = tmp->cred.cr_principal; |
406 | tmp->client_name = NULL; | 403 | tmp->cred.cr_principal = NULL; |
407 | } | 404 | } |
408 | 405 | ||
409 | static struct cache_head * | 406 | static struct cache_head * |
@@ -501,8 +498,8 @@ static int rsc_parse(struct cache_detail *cd, | |||
501 | /* get client name */ | 498 | /* get client name */ |
502 | len = qword_get(&mesg, buf, mlen); | 499 | len = qword_get(&mesg, buf, mlen); |
503 | if (len > 0) { | 500 | if (len > 0) { |
504 | rsci.client_name = kstrdup(buf, GFP_KERNEL); | 501 | rsci.cred.cr_principal = kstrdup(buf, GFP_KERNEL); |
505 | if (!rsci.client_name) | 502 | if (!rsci.cred.cr_principal) |
506 | goto out; | 503 | goto out; |
507 | } | 504 | } |
508 | 505 | ||
@@ -932,16 +929,6 @@ struct gss_svc_data { | |||
932 | struct rsc *rsci; | 929 | struct rsc *rsci; |
933 | }; | 930 | }; |
934 | 931 | ||
935 | char *svc_gss_principal(struct svc_rqst *rqstp) | ||
936 | { | ||
937 | struct gss_svc_data *gd = (struct gss_svc_data *)rqstp->rq_auth_data; | ||
938 | |||
939 | if (gd && gd->rsci) | ||
940 | return gd->rsci->client_name; | ||
941 | return NULL; | ||
942 | } | ||
943 | EXPORT_SYMBOL_GPL(svc_gss_principal); | ||
944 | |||
945 | static int | 932 | static int |
946 | svcauth_gss_set_client(struct svc_rqst *rqstp) | 933 | svcauth_gss_set_client(struct svc_rqst *rqstp) |
947 | { | 934 | { |
@@ -1220,7 +1207,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1220 | } | 1207 | } |
1221 | svcdata->rsci = rsci; | 1208 | svcdata->rsci = rsci; |
1222 | cache_get(&rsci->h); | 1209 | cache_get(&rsci->h); |
1223 | rqstp->rq_flavor = gss_svc_to_pseudoflavor( | 1210 | rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor( |
1224 | rsci->mechctx->mech_type, gc->gc_svc); | 1211 | rsci->mechctx->mech_type, gc->gc_svc); |
1225 | ret = SVC_OK; | 1212 | ret = SVC_OK; |
1226 | goto out; | 1213 | goto out; |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 3c0653439f3d..92509ffe15fc 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -180,14 +180,16 @@ void rpcb_put_local(struct net *net) | |||
180 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 180 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
181 | struct rpc_clnt *clnt = sn->rpcb_local_clnt; | 181 | struct rpc_clnt *clnt = sn->rpcb_local_clnt; |
182 | struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; | 182 | struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; |
183 | int shutdown; | 183 | int shutdown = 0; |
184 | 184 | ||
185 | spin_lock(&sn->rpcb_clnt_lock); | 185 | spin_lock(&sn->rpcb_clnt_lock); |
186 | if (--sn->rpcb_users == 0) { | 186 | if (sn->rpcb_users) { |
187 | sn->rpcb_local_clnt = NULL; | 187 | if (--sn->rpcb_users == 0) { |
188 | sn->rpcb_local_clnt4 = NULL; | 188 | sn->rpcb_local_clnt = NULL; |
189 | sn->rpcb_local_clnt4 = NULL; | ||
190 | } | ||
191 | shutdown = !sn->rpcb_users; | ||
189 | } | 192 | } |
190 | shutdown = !sn->rpcb_users; | ||
191 | spin_unlock(&sn->rpcb_clnt_lock); | 193 | spin_unlock(&sn->rpcb_clnt_lock); |
192 | 194 | ||
193 | if (shutdown) { | 195 | if (shutdown) { |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 017c0117d154..7e9baaa1e543 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -407,6 +407,14 @@ static int svc_uses_rpcbind(struct svc_serv *serv) | |||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | int svc_bind(struct svc_serv *serv, struct net *net) | ||
411 | { | ||
412 | if (!svc_uses_rpcbind(serv)) | ||
413 | return 0; | ||
414 | return svc_rpcb_setup(serv, net); | ||
415 | } | ||
416 | EXPORT_SYMBOL_GPL(svc_bind); | ||
417 | |||
410 | /* | 418 | /* |
411 | * Create an RPC service | 419 | * Create an RPC service |
412 | */ | 420 | */ |
@@ -471,15 +479,8 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
471 | spin_lock_init(&pool->sp_lock); | 479 | spin_lock_init(&pool->sp_lock); |
472 | } | 480 | } |
473 | 481 | ||
474 | if (svc_uses_rpcbind(serv)) { | 482 | if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) |
475 | if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { | 483 | serv->sv_shutdown = svc_rpcb_cleanup; |
476 | kfree(serv->sv_pools); | ||
477 | kfree(serv); | ||
478 | return NULL; | ||
479 | } | ||
480 | if (!serv->sv_shutdown) | ||
481 | serv->sv_shutdown = svc_rpcb_cleanup; | ||
482 | } | ||
483 | 484 | ||
484 | return serv; | 485 | return serv; |
485 | } | 486 | } |
@@ -536,8 +537,6 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net); | |||
536 | void | 537 | void |
537 | svc_destroy(struct svc_serv *serv) | 538 | svc_destroy(struct svc_serv *serv) |
538 | { | 539 | { |
539 | struct net *net = current->nsproxy->net_ns; | ||
540 | |||
541 | dprintk("svc: svc_destroy(%s, %d)\n", | 540 | dprintk("svc: svc_destroy(%s, %d)\n", |
542 | serv->sv_program->pg_name, | 541 | serv->sv_program->pg_name, |
543 | serv->sv_nrthreads); | 542 | serv->sv_nrthreads); |
@@ -552,8 +551,6 @@ svc_destroy(struct svc_serv *serv) | |||
552 | 551 | ||
553 | del_timer_sync(&serv->sv_temptimer); | 552 | del_timer_sync(&serv->sv_temptimer); |
554 | 553 | ||
555 | svc_shutdown_net(serv, net); | ||
556 | |||
557 | /* | 554 | /* |
558 | * The last user is gone and thus all sockets have to be destroyed to | 555 | * The last user is gone and thus all sockets have to be destroyed to |
559 | * the point. Check this. | 556 | * the point. Check this. |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index b98ee3514912..88f2bf671960 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -598,6 +598,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
598 | 598 | ||
599 | /* now allocate needed pages. If we get a failure, sleep briefly */ | 599 | /* now allocate needed pages. If we get a failure, sleep briefly */ |
600 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; | 600 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; |
601 | BUG_ON(pages >= RPCSVC_MAXPAGES); | ||
601 | for (i = 0; i < pages ; i++) | 602 | for (i = 0; i < pages ; i++) |
602 | while (rqstp->rq_pages[i] == NULL) { | 603 | while (rqstp->rq_pages[i] == NULL) { |
603 | struct page *p = alloc_page(GFP_KERNEL); | 604 | struct page *p = alloc_page(GFP_KERNEL); |
@@ -612,7 +613,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
612 | rqstp->rq_pages[i] = p; | 613 | rqstp->rq_pages[i] = p; |
613 | } | 614 | } |
614 | rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */ | 615 | rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */ |
615 | BUG_ON(pages >= RPCSVC_MAXPAGES); | ||
616 | 616 | ||
617 | /* Make arg->head point to first page and arg->pages point to rest */ | 617 | /* Make arg->head point to first page and arg->pages point to rest */ |
618 | arg = &rqstp->rq_arg; | 618 | arg = &rqstp->rq_arg; |
@@ -973,7 +973,7 @@ void svc_close_net(struct svc_serv *serv, struct net *net) | |||
973 | svc_clear_pools(serv, net); | 973 | svc_clear_pools(serv, net); |
974 | /* | 974 | /* |
975 | * At this point the sp_sockets lists will stay empty, since | 975 | * At this point the sp_sockets lists will stay empty, since |
976 | * svc_enqueue will not add new entries without taking the | 976 | * svc_xprt_enqueue will not add new entries without taking the |
977 | * sp_lock and checking XPT_BUSY. | 977 | * sp_lock and checking XPT_BUSY. |
978 | */ | 978 | */ |
979 | svc_clear_list(&serv->sv_tempsocks, net); | 979 | svc_clear_list(&serv->sv_tempsocks, net); |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 6138c925923d..2777fa896645 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -746,6 +746,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
746 | struct svc_cred *cred = &rqstp->rq_cred; | 746 | struct svc_cred *cred = &rqstp->rq_cred; |
747 | 747 | ||
748 | cred->cr_group_info = NULL; | 748 | cred->cr_group_info = NULL; |
749 | cred->cr_principal = NULL; | ||
749 | rqstp->rq_client = NULL; | 750 | rqstp->rq_client = NULL; |
750 | 751 | ||
751 | if (argv->iov_len < 3*4) | 752 | if (argv->iov_len < 3*4) |
@@ -773,7 +774,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
773 | svc_putnl(resv, RPC_AUTH_NULL); | 774 | svc_putnl(resv, RPC_AUTH_NULL); |
774 | svc_putnl(resv, 0); | 775 | svc_putnl(resv, 0); |
775 | 776 | ||
776 | rqstp->rq_flavor = RPC_AUTH_NULL; | 777 | rqstp->rq_cred.cr_flavor = RPC_AUTH_NULL; |
777 | return SVC_OK; | 778 | return SVC_OK; |
778 | } | 779 | } |
779 | 780 | ||
@@ -811,6 +812,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
811 | int len = argv->iov_len; | 812 | int len = argv->iov_len; |
812 | 813 | ||
813 | cred->cr_group_info = NULL; | 814 | cred->cr_group_info = NULL; |
815 | cred->cr_principal = NULL; | ||
814 | rqstp->rq_client = NULL; | 816 | rqstp->rq_client = NULL; |
815 | 817 | ||
816 | if ((len -= 3*4) < 0) | 818 | if ((len -= 3*4) < 0) |
@@ -847,7 +849,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
847 | svc_putnl(resv, RPC_AUTH_NULL); | 849 | svc_putnl(resv, RPC_AUTH_NULL); |
848 | svc_putnl(resv, 0); | 850 | svc_putnl(resv, 0); |
849 | 851 | ||
850 | rqstp->rq_flavor = RPC_AUTH_UNIX; | 852 | rqstp->rq_cred.cr_flavor = RPC_AUTH_UNIX; |
851 | return SVC_OK; | 853 | return SVC_OK; |
852 | 854 | ||
853 | badcred: | 855 | badcred: |