.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Neil Brown <neilb@cse.unsw.edu.au> |
---|
3 | 4 | * J. Bruce Fields <bfields@umich.edu> |
---|
.. | .. |
---|
48 | 49 | #include <linux/sunrpc/svcauth.h> |
---|
49 | 50 | #include <linux/sunrpc/svcauth_gss.h> |
---|
50 | 51 | #include <linux/sunrpc/cache.h> |
---|
| 52 | + |
---|
| 53 | +#include <trace/events/rpcgss.h> |
---|
| 54 | + |
---|
51 | 55 | #include "gss_rpc_upcall.h" |
---|
52 | 56 | |
---|
53 | | - |
---|
54 | | -#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
---|
55 | | -# define RPCDBG_FACILITY RPCDBG_AUTH |
---|
56 | | -#endif |
---|
57 | 57 | |
---|
58 | 58 | /* The rpcsec_init cache is used for mapping RPCSEC_GSS_{,CONT_}INIT requests |
---|
59 | 59 | * into replies. |
---|
.. | .. |
---|
76 | 76 | struct xdr_netobj in_handle, in_token; |
---|
77 | 77 | struct xdr_netobj out_handle, out_token; |
---|
78 | 78 | int major_status, minor_status; |
---|
| 79 | + struct rcu_head rcu_head; |
---|
79 | 80 | }; |
---|
80 | 81 | |
---|
81 | 82 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old); |
---|
.. | .. |
---|
89 | 90 | kfree(rsii->out_token.data); |
---|
90 | 91 | } |
---|
91 | 92 | |
---|
| 93 | +static void rsi_free_rcu(struct rcu_head *head) |
---|
| 94 | +{ |
---|
| 95 | + struct rsi *rsii = container_of(head, struct rsi, rcu_head); |
---|
| 96 | + |
---|
| 97 | + rsi_free(rsii); |
---|
| 98 | + kfree(rsii); |
---|
| 99 | +} |
---|
| 100 | + |
---|
92 | 101 | static void rsi_put(struct kref *ref) |
---|
93 | 102 | { |
---|
94 | 103 | struct rsi *rsii = container_of(ref, struct rsi, h.ref); |
---|
95 | | - rsi_free(rsii); |
---|
96 | | - kfree(rsii); |
---|
| 104 | + |
---|
| 105 | + call_rcu(&rsii->rcu_head, rsi_free_rcu); |
---|
97 | 106 | } |
---|
98 | 107 | |
---|
99 | 108 | static inline int rsi_hash(struct rsi *item) |
---|
.. | .. |
---|
171 | 180 | return NULL; |
---|
172 | 181 | } |
---|
173 | 182 | |
---|
| 183 | +static int rsi_upcall(struct cache_detail *cd, struct cache_head *h) |
---|
| 184 | +{ |
---|
| 185 | + return sunrpc_cache_pipe_upcall_timeout(cd, h); |
---|
| 186 | +} |
---|
| 187 | + |
---|
174 | 188 | static void rsi_request(struct cache_detail *cd, |
---|
175 | 189 | struct cache_head *h, |
---|
176 | 190 | char **bpp, int *blen) |
---|
.. | .. |
---|
190 | 204 | char *ep; |
---|
191 | 205 | int len; |
---|
192 | 206 | struct rsi rsii, *rsip = NULL; |
---|
193 | | - time_t expiry; |
---|
| 207 | + time64_t expiry; |
---|
194 | 208 | int status = -EINVAL; |
---|
195 | 209 | |
---|
196 | 210 | memset(&rsii, 0, sizeof(rsii)); |
---|
.. | .. |
---|
269 | 283 | .hash_size = RSI_HASHMAX, |
---|
270 | 284 | .name = "auth.rpcsec.init", |
---|
271 | 285 | .cache_put = rsi_put, |
---|
| 286 | + .cache_upcall = rsi_upcall, |
---|
272 | 287 | .cache_request = rsi_request, |
---|
273 | 288 | .cache_parse = rsi_parse, |
---|
274 | 289 | .match = rsi_match, |
---|
.. | .. |
---|
282 | 297 | struct cache_head *ch; |
---|
283 | 298 | int hash = rsi_hash(item); |
---|
284 | 299 | |
---|
285 | | - ch = sunrpc_cache_lookup(cd, &item->h, hash); |
---|
| 300 | + ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash); |
---|
286 | 301 | if (ch) |
---|
287 | 302 | return container_of(ch, struct rsi, h); |
---|
288 | 303 | else |
---|
.. | .. |
---|
317 | 332 | |
---|
318 | 333 | struct gss_svc_seq_data { |
---|
319 | 334 | /* highest seq number seen so far: */ |
---|
320 | | - int sd_max; |
---|
| 335 | + u32 sd_max; |
---|
321 | 336 | /* for i such that sd_max-GSS_SEQ_WIN < i <= sd_max, the i-th bit of |
---|
322 | 337 | * sd_win is nonzero iff sequence number i has been seen already: */ |
---|
323 | 338 | unsigned long sd_win[GSS_SEQ_WIN/BITS_PER_LONG]; |
---|
.. | .. |
---|
330 | 345 | struct svc_cred cred; |
---|
331 | 346 | struct gss_svc_seq_data seqdata; |
---|
332 | 347 | struct gss_ctx *mechctx; |
---|
| 348 | + struct rcu_head rcu_head; |
---|
333 | 349 | }; |
---|
334 | 350 | |
---|
335 | 351 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); |
---|
.. | .. |
---|
343 | 359 | free_svc_cred(&rsci->cred); |
---|
344 | 360 | } |
---|
345 | 361 | |
---|
| 362 | +static void rsc_free_rcu(struct rcu_head *head) |
---|
| 363 | +{ |
---|
| 364 | + struct rsc *rsci = container_of(head, struct rsc, rcu_head); |
---|
| 365 | + |
---|
| 366 | + kfree(rsci->handle.data); |
---|
| 367 | + kfree(rsci); |
---|
| 368 | +} |
---|
| 369 | + |
---|
346 | 370 | static void rsc_put(struct kref *ref) |
---|
347 | 371 | { |
---|
348 | 372 | struct rsc *rsci = container_of(ref, struct rsc, h.ref); |
---|
349 | 373 | |
---|
350 | | - rsc_free(rsci); |
---|
351 | | - kfree(rsci); |
---|
| 374 | + if (rsci->mechctx) |
---|
| 375 | + gss_delete_sec_context(&rsci->mechctx); |
---|
| 376 | + free_svc_cred(&rsci->cred); |
---|
| 377 | + call_rcu(&rsci->rcu_head, rsc_free_rcu); |
---|
352 | 378 | } |
---|
353 | 379 | |
---|
354 | 380 | static inline int |
---|
.. | .. |
---|
404 | 430 | return NULL; |
---|
405 | 431 | } |
---|
406 | 432 | |
---|
| 433 | +static int rsc_upcall(struct cache_detail *cd, struct cache_head *h) |
---|
| 434 | +{ |
---|
| 435 | + return -EINVAL; |
---|
| 436 | +} |
---|
| 437 | + |
---|
407 | 438 | static int rsc_parse(struct cache_detail *cd, |
---|
408 | 439 | char *mesg, int mlen) |
---|
409 | 440 | { |
---|
.. | .. |
---|
412 | 443 | int id; |
---|
413 | 444 | int len, rv; |
---|
414 | 445 | struct rsc rsci, *rscp = NULL; |
---|
415 | | - time_t expiry; |
---|
| 446 | + time64_t expiry; |
---|
416 | 447 | int status = -EINVAL; |
---|
417 | 448 | struct gss_api_mech *gm = NULL; |
---|
418 | 449 | |
---|
.. | .. |
---|
453 | 484 | * treatment so are checked for validity here.) |
---|
454 | 485 | */ |
---|
455 | 486 | /* uid */ |
---|
456 | | - rsci.cred.cr_uid = make_kuid(&init_user_ns, id); |
---|
| 487 | + rsci.cred.cr_uid = make_kuid(current_user_ns(), id); |
---|
457 | 488 | |
---|
458 | 489 | /* gid */ |
---|
459 | 490 | if (get_int(&mesg, &id)) |
---|
460 | 491 | goto out; |
---|
461 | | - rsci.cred.cr_gid = make_kgid(&init_user_ns, id); |
---|
| 492 | + rsci.cred.cr_gid = make_kgid(current_user_ns(), id); |
---|
462 | 493 | |
---|
463 | 494 | /* number of additional gid's */ |
---|
464 | 495 | if (get_int(&mesg, &N)) |
---|
.. | .. |
---|
476 | 507 | kgid_t kgid; |
---|
477 | 508 | if (get_int(&mesg, &id)) |
---|
478 | 509 | goto out; |
---|
479 | | - kgid = make_kgid(&init_user_ns, id); |
---|
| 510 | + kgid = make_kgid(current_user_ns(), id); |
---|
480 | 511 | if (!gid_valid(kgid)) |
---|
481 | 512 | goto out; |
---|
482 | 513 | rsci.cred.cr_group_info->gid[i] = kgid; |
---|
.. | .. |
---|
530 | 561 | .hash_size = RSC_HASHMAX, |
---|
531 | 562 | .name = "auth.rpcsec.context", |
---|
532 | 563 | .cache_put = rsc_put, |
---|
| 564 | + .cache_upcall = rsc_upcall, |
---|
533 | 565 | .cache_parse = rsc_parse, |
---|
534 | 566 | .match = rsc_match, |
---|
535 | 567 | .init = rsc_init, |
---|
.. | .. |
---|
542 | 574 | struct cache_head *ch; |
---|
543 | 575 | int hash = rsc_hash(item); |
---|
544 | 576 | |
---|
545 | | - ch = sunrpc_cache_lookup(cd, &item->h, hash); |
---|
| 577 | + ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash); |
---|
546 | 578 | if (ch) |
---|
547 | 579 | return container_of(ch, struct rsc, h); |
---|
548 | 580 | else |
---|
.. | .. |
---|
581 | 613 | return found; |
---|
582 | 614 | } |
---|
583 | 615 | |
---|
584 | | -/* Implements sequence number algorithm as specified in RFC 2203. */ |
---|
585 | | -static int |
---|
586 | | -gss_check_seq_num(struct rsc *rsci, int seq_num) |
---|
| 616 | +/** |
---|
| 617 | + * gss_check_seq_num - GSS sequence number window check |
---|
| 618 | + * @rqstp: RPC Call to use when reporting errors |
---|
| 619 | + * @rsci: cached GSS context state (updated on return) |
---|
| 620 | + * @seq_num: sequence number to check |
---|
| 621 | + * |
---|
| 622 | + * Implements sequence number algorithm as specified in |
---|
| 623 | + * RFC 2203, Section 5.3.3.1. "Context Management". |
---|
| 624 | + * |
---|
| 625 | + * Return values: |
---|
| 626 | + * %true: @rqstp's GSS sequence number is inside the window |
---|
| 627 | + * %false: @rqstp's GSS sequence number is outside the window |
---|
| 628 | + */ |
---|
| 629 | +static bool gss_check_seq_num(const struct svc_rqst *rqstp, struct rsc *rsci, |
---|
| 630 | + u32 seq_num) |
---|
587 | 631 | { |
---|
588 | 632 | struct gss_svc_seq_data *sd = &rsci->seqdata; |
---|
| 633 | + bool result = false; |
---|
589 | 634 | |
---|
590 | 635 | spin_lock(&sd->sd_lock); |
---|
591 | 636 | if (seq_num > sd->sd_max) { |
---|
592 | 637 | if (seq_num >= sd->sd_max + GSS_SEQ_WIN) { |
---|
593 | | - memset(sd->sd_win,0,sizeof(sd->sd_win)); |
---|
| 638 | + memset(sd->sd_win, 0, sizeof(sd->sd_win)); |
---|
594 | 639 | sd->sd_max = seq_num; |
---|
595 | 640 | } else while (sd->sd_max < seq_num) { |
---|
596 | 641 | sd->sd_max++; |
---|
.. | .. |
---|
598 | 643 | } |
---|
599 | 644 | __set_bit(seq_num % GSS_SEQ_WIN, sd->sd_win); |
---|
600 | 645 | goto ok; |
---|
601 | | - } else if (seq_num <= sd->sd_max - GSS_SEQ_WIN) { |
---|
602 | | - goto drop; |
---|
| 646 | + } else if (seq_num + GSS_SEQ_WIN <= sd->sd_max) { |
---|
| 647 | + goto toolow; |
---|
603 | 648 | } |
---|
604 | | - /* sd_max - GSS_SEQ_WIN < seq_num <= sd_max */ |
---|
605 | 649 | if (__test_and_set_bit(seq_num % GSS_SEQ_WIN, sd->sd_win)) |
---|
606 | | - goto drop; |
---|
| 650 | + goto alreadyseen; |
---|
| 651 | + |
---|
607 | 652 | ok: |
---|
| 653 | + result = true; |
---|
| 654 | +out: |
---|
608 | 655 | spin_unlock(&sd->sd_lock); |
---|
609 | | - return 1; |
---|
610 | | -drop: |
---|
611 | | - spin_unlock(&sd->sd_lock); |
---|
612 | | - return 0; |
---|
| 656 | + return result; |
---|
| 657 | + |
---|
| 658 | +toolow: |
---|
| 659 | + trace_rpcgss_svc_seqno_low(rqstp, seq_num, |
---|
| 660 | + sd->sd_max - GSS_SEQ_WIN, |
---|
| 661 | + sd->sd_max); |
---|
| 662 | + goto out; |
---|
| 663 | +alreadyseen: |
---|
| 664 | + trace_rpcgss_svc_seqno_seen(rqstp, seq_num); |
---|
| 665 | + goto out; |
---|
613 | 666 | } |
---|
614 | 667 | |
---|
615 | 668 | static inline u32 round_up_to_quad(u32 i) |
---|
.. | .. |
---|
689 | 742 | } |
---|
690 | 743 | |
---|
691 | 744 | if (gc->gc_seq > MAXSEQ) { |
---|
692 | | - dprintk("RPC: svcauth_gss: discarding request with " |
---|
693 | | - "large sequence number %d\n", gc->gc_seq); |
---|
| 745 | + trace_rpcgss_svc_seqno_large(rqstp, gc->gc_seq); |
---|
694 | 746 | *authp = rpcsec_gsserr_ctxproblem; |
---|
695 | 747 | return SVC_DENIED; |
---|
696 | 748 | } |
---|
697 | | - if (!gss_check_seq_num(rsci, gc->gc_seq)) { |
---|
698 | | - dprintk("RPC: svcauth_gss: discarding request with " |
---|
699 | | - "old sequence number %d\n", gc->gc_seq); |
---|
| 749 | + if (!gss_check_seq_num(rqstp, rsci, gc->gc_seq)) |
---|
700 | 750 | return SVC_DROP; |
---|
701 | | - } |
---|
702 | 751 | return SVC_OK; |
---|
703 | 752 | } |
---|
704 | 753 | |
---|
.. | .. |
---|
836 | 885 | static int |
---|
837 | 886 | unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) |
---|
838 | 887 | { |
---|
| 888 | + u32 integ_len, rseqno, maj_stat; |
---|
839 | 889 | int stat = -EINVAL; |
---|
840 | | - u32 integ_len, maj_stat; |
---|
841 | 890 | struct xdr_netobj mic; |
---|
842 | 891 | struct xdr_buf integ_buf; |
---|
| 892 | + |
---|
| 893 | + mic.data = NULL; |
---|
843 | 894 | |
---|
844 | 895 | /* NFS READ normally uses splice to send data in-place. However |
---|
845 | 896 | * the data in cache can change after the reply's MIC is computed |
---|
.. | .. |
---|
855 | 906 | |
---|
856 | 907 | integ_len = svc_getnl(&buf->head[0]); |
---|
857 | 908 | if (integ_len & 3) |
---|
858 | | - return stat; |
---|
| 909 | + goto unwrap_failed; |
---|
859 | 910 | if (integ_len > buf->len) |
---|
860 | | - return stat; |
---|
861 | | - if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len)) { |
---|
862 | | - WARN_ON_ONCE(1); |
---|
863 | | - return stat; |
---|
864 | | - } |
---|
| 911 | + goto unwrap_failed; |
---|
| 912 | + if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len)) |
---|
| 913 | + goto unwrap_failed; |
---|
| 914 | + |
---|
865 | 915 | /* copy out mic... */ |
---|
866 | 916 | if (read_u32_from_xdr_buf(buf, integ_len, &mic.len)) |
---|
867 | | - return stat; |
---|
| 917 | + goto unwrap_failed; |
---|
868 | 918 | if (mic.len > RPC_MAX_AUTH_SIZE) |
---|
869 | | - return stat; |
---|
| 919 | + goto unwrap_failed; |
---|
870 | 920 | mic.data = kmalloc(mic.len, GFP_KERNEL); |
---|
871 | 921 | if (!mic.data) |
---|
872 | | - return stat; |
---|
| 922 | + goto unwrap_failed; |
---|
873 | 923 | if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len)) |
---|
874 | | - goto out; |
---|
| 924 | + goto unwrap_failed; |
---|
875 | 925 | maj_stat = gss_verify_mic(ctx, &integ_buf, &mic); |
---|
876 | 926 | if (maj_stat != GSS_S_COMPLETE) |
---|
877 | | - goto out; |
---|
878 | | - if (svc_getnl(&buf->head[0]) != seq) |
---|
879 | | - goto out; |
---|
| 927 | + goto bad_mic; |
---|
| 928 | + rseqno = svc_getnl(&buf->head[0]); |
---|
| 929 | + if (rseqno != seq) |
---|
| 930 | + goto bad_seqno; |
---|
880 | 931 | /* trim off the mic and padding at the end before returning */ |
---|
881 | 932 | xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4); |
---|
882 | 933 | stat = 0; |
---|
883 | 934 | out: |
---|
884 | 935 | kfree(mic.data); |
---|
885 | 936 | return stat; |
---|
| 937 | + |
---|
| 938 | +unwrap_failed: |
---|
| 939 | + trace_rpcgss_svc_unwrap_failed(rqstp); |
---|
| 940 | + goto out; |
---|
| 941 | +bad_seqno: |
---|
| 942 | + trace_rpcgss_svc_seqno_bad(rqstp, seq, rseqno); |
---|
| 943 | + goto out; |
---|
| 944 | +bad_mic: |
---|
| 945 | + trace_rpcgss_svc_mic(rqstp, maj_stat); |
---|
| 946 | + goto out; |
---|
886 | 947 | } |
---|
887 | 948 | |
---|
888 | 949 | static inline int |
---|
.. | .. |
---|
906 | 967 | unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) |
---|
907 | 968 | { |
---|
908 | 969 | u32 priv_len, maj_stat; |
---|
909 | | - int pad, saved_len, remaining_len, offset; |
---|
| 970 | + int pad, remaining_len, offset; |
---|
| 971 | + u32 rseqno; |
---|
910 | 972 | |
---|
911 | 973 | clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags); |
---|
912 | 974 | |
---|
.. | .. |
---|
921 | 983 | * not yet read from the head, so these two values are different: */ |
---|
922 | 984 | remaining_len = total_buf_len(buf); |
---|
923 | 985 | if (priv_len > remaining_len) |
---|
924 | | - return -EINVAL; |
---|
| 986 | + goto unwrap_failed; |
---|
925 | 987 | pad = remaining_len - priv_len; |
---|
926 | 988 | buf->len -= pad; |
---|
927 | 989 | fix_priv_head(buf, pad); |
---|
928 | 990 | |
---|
929 | | - /* Maybe it would be better to give gss_unwrap a length parameter: */ |
---|
930 | | - saved_len = buf->len; |
---|
931 | | - buf->len = priv_len; |
---|
932 | | - maj_stat = gss_unwrap(ctx, 0, buf); |
---|
| 991 | + maj_stat = gss_unwrap(ctx, 0, priv_len, buf); |
---|
933 | 992 | pad = priv_len - buf->len; |
---|
934 | | - buf->len = saved_len; |
---|
935 | | - buf->len -= pad; |
---|
936 | 993 | /* The upper layers assume the buffer is aligned on 4-byte boundaries. |
---|
937 | 994 | * In the krb5p case, at least, the data ends up offset, so we need to |
---|
938 | 995 | * move it around. */ |
---|
939 | 996 | /* XXX: This is very inefficient. It would be better to either do |
---|
940 | 997 | * this while we encrypt, or maybe in the receive code, if we can peak |
---|
941 | 998 | * ahead and work out the service and mechanism there. */ |
---|
942 | | - offset = buf->head[0].iov_len % 4; |
---|
| 999 | + offset = xdr_pad_size(buf->head[0].iov_len); |
---|
943 | 1000 | if (offset) { |
---|
944 | 1001 | buf->buflen = RPCSVC_MAXPAYLOAD; |
---|
945 | 1002 | xdr_shift_buf(buf, offset); |
---|
946 | 1003 | fix_priv_head(buf, pad); |
---|
947 | 1004 | } |
---|
948 | 1005 | if (maj_stat != GSS_S_COMPLETE) |
---|
949 | | - return -EINVAL; |
---|
| 1006 | + goto bad_unwrap; |
---|
950 | 1007 | out_seq: |
---|
951 | | - if (svc_getnl(&buf->head[0]) != seq) |
---|
952 | | - return -EINVAL; |
---|
| 1008 | + rseqno = svc_getnl(&buf->head[0]); |
---|
| 1009 | + if (rseqno != seq) |
---|
| 1010 | + goto bad_seqno; |
---|
953 | 1011 | return 0; |
---|
| 1012 | + |
---|
| 1013 | +unwrap_failed: |
---|
| 1014 | + trace_rpcgss_svc_unwrap_failed(rqstp); |
---|
| 1015 | + return -EINVAL; |
---|
| 1016 | +bad_seqno: |
---|
| 1017 | + trace_rpcgss_svc_seqno_bad(rqstp, seq, rseqno); |
---|
| 1018 | + return -EINVAL; |
---|
| 1019 | +bad_unwrap: |
---|
| 1020 | + trace_rpcgss_svc_unwrap(rqstp, maj_stat); |
---|
| 1021 | + return -EINVAL; |
---|
954 | 1022 | } |
---|
955 | 1023 | |
---|
956 | 1024 | struct gss_svc_data { |
---|
.. | .. |
---|
1088 | 1156 | return res; |
---|
1089 | 1157 | |
---|
1090 | 1158 | inlen = svc_getnl(argv); |
---|
1091 | | - if (inlen > (argv->iov_len + rqstp->rq_arg.page_len)) |
---|
| 1159 | + if (inlen > (argv->iov_len + rqstp->rq_arg.page_len)) { |
---|
| 1160 | + kfree(in_handle->data); |
---|
1092 | 1161 | return SVC_DENIED; |
---|
| 1162 | + } |
---|
1093 | 1163 | |
---|
1094 | 1164 | pages = DIV_ROUND_UP(inlen, PAGE_SIZE); |
---|
1095 | 1165 | in_token->pages = kcalloc(pages, sizeof(struct page *), GFP_KERNEL); |
---|
1096 | | - if (!in_token->pages) |
---|
| 1166 | + if (!in_token->pages) { |
---|
| 1167 | + kfree(in_handle->data); |
---|
1097 | 1168 | return SVC_DENIED; |
---|
| 1169 | + } |
---|
1098 | 1170 | in_token->page_base = 0; |
---|
1099 | 1171 | in_token->page_len = inlen; |
---|
1100 | 1172 | for (i = 0; i < pages; i++) { |
---|
1101 | 1173 | in_token->pages[i] = alloc_page(GFP_KERNEL); |
---|
1102 | 1174 | if (!in_token->pages[i]) { |
---|
| 1175 | + kfree(in_handle->data); |
---|
1103 | 1176 | gss_free_in_token_pages(in_token); |
---|
1104 | 1177 | return SVC_DENIED; |
---|
1105 | 1178 | } |
---|
.. | .. |
---|
1206 | 1279 | static atomic64_t ctxhctr; |
---|
1207 | 1280 | long long ctxh; |
---|
1208 | 1281 | struct gss_api_mech *gm = NULL; |
---|
1209 | | - time_t expiry; |
---|
| 1282 | + time64_t expiry; |
---|
1210 | 1283 | int status = -EINVAL; |
---|
1211 | 1284 | |
---|
1212 | 1285 | memset(&rsci, 0, sizeof(rsci)); |
---|
.. | .. |
---|
1230 | 1303 | if (!ud->found_creds) { |
---|
1231 | 1304 | /* userspace seem buggy, we should always get at least a |
---|
1232 | 1305 | * mapping to nobody */ |
---|
1233 | | - dprintk("RPC: No creds found!\n"); |
---|
1234 | 1306 | goto out; |
---|
1235 | 1307 | } else { |
---|
1236 | 1308 | struct timespec64 boot; |
---|
.. | .. |
---|
1296 | 1368 | if (status) |
---|
1297 | 1369 | goto out; |
---|
1298 | 1370 | |
---|
1299 | | - dprintk("RPC: svcauth_gss: gss major status = %d " |
---|
1300 | | - "minor status = %d\n", |
---|
1301 | | - ud.major_status, ud.minor_status); |
---|
| 1371 | + trace_rpcgss_svc_accept_upcall(rqstp, ud.major_status, ud.minor_status); |
---|
1302 | 1372 | |
---|
1303 | 1373 | switch (ud.major_status) { |
---|
1304 | 1374 | case GSS_S_CONTINUE_NEEDED: |
---|
.. | .. |
---|
1306 | 1376 | break; |
---|
1307 | 1377 | case GSS_S_COMPLETE: |
---|
1308 | 1378 | status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle); |
---|
1309 | | - if (status) { |
---|
1310 | | - pr_info("%s: gss_proxy_save_rsc failed (%d)\n", |
---|
1311 | | - __func__, status); |
---|
| 1379 | + if (status) |
---|
1312 | 1380 | goto out; |
---|
1313 | | - } |
---|
1314 | 1381 | cli_handle.data = (u8 *)&handle; |
---|
1315 | 1382 | cli_handle.len = sizeof(handle); |
---|
1316 | 1383 | break; |
---|
1317 | 1384 | default: |
---|
1318 | | - ret = SVC_CLOSE; |
---|
1319 | 1385 | goto out; |
---|
1320 | 1386 | } |
---|
1321 | 1387 | |
---|
1322 | 1388 | /* Got an answer to the upcall; use it: */ |
---|
1323 | 1389 | if (gss_write_init_verf(sn->rsc_cache, rqstp, |
---|
1324 | | - &cli_handle, &ud.major_status)) { |
---|
1325 | | - pr_info("%s: gss_write_init_verf failed\n", __func__); |
---|
| 1390 | + &cli_handle, &ud.major_status)) |
---|
1326 | 1391 | goto out; |
---|
1327 | | - } |
---|
1328 | 1392 | if (gss_write_resv(resv, PAGE_SIZE, |
---|
1329 | 1393 | &cli_handle, &ud.out_token, |
---|
1330 | | - ud.major_status, ud.minor_status)) { |
---|
1331 | | - pr_info("%s: gss_write_resv failed\n", __func__); |
---|
| 1394 | + ud.major_status, ud.minor_status)) |
---|
1332 | 1395 | goto out; |
---|
1333 | | - } |
---|
1334 | 1396 | |
---|
1335 | 1397 | ret = SVC_COMPLETE; |
---|
1336 | 1398 | out: |
---|
.. | .. |
---|
1418 | 1480 | return len; |
---|
1419 | 1481 | } |
---|
1420 | 1482 | |
---|
1421 | | -static const struct file_operations use_gss_proxy_ops = { |
---|
1422 | | - .open = nonseekable_open, |
---|
1423 | | - .write = write_gssp, |
---|
1424 | | - .read = read_gssp, |
---|
| 1483 | +static const struct proc_ops use_gss_proxy_proc_ops = { |
---|
| 1484 | + .proc_open = nonseekable_open, |
---|
| 1485 | + .proc_write = write_gssp, |
---|
| 1486 | + .proc_read = read_gssp, |
---|
1425 | 1487 | }; |
---|
1426 | 1488 | |
---|
1427 | 1489 | static int create_use_gss_proxy_proc_entry(struct net *net) |
---|
.. | .. |
---|
1432 | 1494 | sn->use_gss_proxy = -1; |
---|
1433 | 1495 | *p = proc_create_data("use-gss-proxy", S_IFREG | 0600, |
---|
1434 | 1496 | sn->proc_net_rpc, |
---|
1435 | | - &use_gss_proxy_ops, net); |
---|
| 1497 | + &use_gss_proxy_proc_ops, net); |
---|
1436 | 1498 | if (!*p) |
---|
1437 | 1499 | return -ENOMEM; |
---|
1438 | 1500 | init_gssp_clnt(sn); |
---|
.. | .. |
---|
1480 | 1542 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
---|
1481 | 1543 | int ret; |
---|
1482 | 1544 | struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); |
---|
1483 | | - |
---|
1484 | | - dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", |
---|
1485 | | - argv->iov_len); |
---|
1486 | 1545 | |
---|
1487 | 1546 | *authp = rpc_autherr_badcred; |
---|
1488 | 1547 | if (!svcdata) |
---|
.. | .. |
---|
1600 | 1659 | GSS_C_QOP_DEFAULT, |
---|
1601 | 1660 | gc->gc_svc); |
---|
1602 | 1661 | ret = SVC_OK; |
---|
| 1662 | + trace_rpcgss_svc_authenticate(rqstp, gc); |
---|
1603 | 1663 | goto out; |
---|
1604 | 1664 | } |
---|
1605 | 1665 | garbage_args: |
---|
.. | .. |
---|
1666 | 1726 | goto out; |
---|
1667 | 1727 | integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base; |
---|
1668 | 1728 | integ_len = resbuf->len - integ_offset; |
---|
1669 | | - BUG_ON(integ_len % 4); |
---|
| 1729 | + if (integ_len & 3) |
---|
| 1730 | + goto out; |
---|
1670 | 1731 | *p++ = htonl(integ_len); |
---|
1671 | 1732 | *p++ = htonl(gc->gc_seq); |
---|
1672 | 1733 | if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len)) { |
---|
.. | .. |
---|
1690 | 1751 | resv->iov_len += XDR_QUADLEN(mic.len) << 2; |
---|
1691 | 1752 | /* not strictly required: */ |
---|
1692 | 1753 | resbuf->len += XDR_QUADLEN(mic.len) << 2; |
---|
1693 | | - BUG_ON(resv->iov_len > PAGE_SIZE); |
---|
| 1754 | + if (resv->iov_len > PAGE_SIZE) |
---|
| 1755 | + goto out_err; |
---|
1694 | 1756 | out: |
---|
1695 | 1757 | stat = 0; |
---|
1696 | 1758 | out_err: |
---|
.. | .. |
---|
1726 | 1788 | * both the head and tail. |
---|
1727 | 1789 | */ |
---|
1728 | 1790 | if (resbuf->tail[0].iov_base) { |
---|
1729 | | - BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base |
---|
1730 | | - + PAGE_SIZE); |
---|
1731 | | - BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base); |
---|
| 1791 | + if (resbuf->tail[0].iov_base >= |
---|
| 1792 | + resbuf->head[0].iov_base + PAGE_SIZE) |
---|
| 1793 | + return -EINVAL; |
---|
| 1794 | + if (resbuf->tail[0].iov_base < resbuf->head[0].iov_base) |
---|
| 1795 | + return -EINVAL; |
---|
1732 | 1796 | if (resbuf->tail[0].iov_len + resbuf->head[0].iov_len |
---|
1733 | 1797 | + 2 * RPC_MAX_AUTH_SIZE > PAGE_SIZE) |
---|
1734 | 1798 | return -ENOMEM; |
---|
.. | .. |
---|
1822 | 1886 | } |
---|
1823 | 1887 | |
---|
1824 | 1888 | static void |
---|
1825 | | -svcauth_gss_domain_release(struct auth_domain *dom) |
---|
| 1889 | +svcauth_gss_domain_release_rcu(struct rcu_head *head) |
---|
1826 | 1890 | { |
---|
| 1891 | + struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head); |
---|
1827 | 1892 | struct gss_domain *gd = container_of(dom, struct gss_domain, h); |
---|
1828 | 1893 | |
---|
1829 | 1894 | kfree(dom->name); |
---|
1830 | 1895 | kfree(gd); |
---|
1831 | 1896 | } |
---|
1832 | 1897 | |
---|
| 1898 | +static void |
---|
| 1899 | +svcauth_gss_domain_release(struct auth_domain *dom) |
---|
| 1900 | +{ |
---|
| 1901 | + call_rcu(&dom->rcu_head, svcauth_gss_domain_release_rcu); |
---|
| 1902 | +} |
---|
| 1903 | + |
---|
1833 | 1904 | static struct auth_ops svcauthops_gss = { |
---|
1834 | 1905 | .name = "rpcsec_gss", |
---|
1835 | 1906 | .owner = THIS_MODULE, |
---|