| @@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid) · 438 unmodified lines |
| 439 | 439 | return -EINVAL; |
| 440 | 440 | } |
| 441 | 441 | return 0; |
| 442 | | − |
| 443 | 442 | } |
| 444 | 443 | |
| 445 | 444 | #ifdef CONFIG_NFSD_V4 |
| @@ -546,6 +545,29 @@ static inline int · 100 unmodified lines |
| 546 | 545 | secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; } |
| 547 | 546 | #endif |
| 548 | 547 | |
| 548 | +static int xprtsec_parse(char **mesg, char *buf, struct svc_export *exp) |
| 549 | +{ |
| 550 | + unsigned int i, mode, listsize; |
| 551 | + int err; |
| 552 | + |
| 553 | + err = get_uint(mesg, &listsize); |
| 554 | + if (err) |
| 555 | + return err; |
| 556 | + if (listsize > NFSEXP_XPRTSEC_NUM) |
| 557 | + return -EINVAL; |
| 558 | + |
| 559 | + exp->ex_xprtsec_modes = 0; |
| 560 | + for (i = 0; i < listsize; i++) { |
| 561 | + err = get_uint(mesg, &mode); |
| 562 | + if (err) |
| 563 | + return err; |
| 564 | + if (mode > NFSEXP_XPRTSEC_MTLS) |
| 565 | + return -EINVAL; |
| 566 | + exp->ex_xprtsec_modes |= mode; |
| 567 | + } |
| 568 | + return 0; |
| 569 | +} |
| 570 | + |
| 549 | 571 | static inline int |
| 550 | 572 | nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid) |
| 551 | 573 | { |
| @@ -608,6 +630,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) · 56 unmodified lines |
| 608 | 630 | exp.ex_client = dom; |
| 609 | 631 | exp.cd = cd; |
| 610 | 632 | exp.ex_devid_map = NULL; |
| 633 | + exp.ex_xprtsec_modes = NFSEXP_XPRTSEC_ALL; |
| 611 | 634 | |
| 612 | 635 | /* expiry */ |
| 613 | 636 | err = get_expiry(&mesg, &exp.h.expiry_time); |
| @@ -649,6 +672,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) · 35 unmodified lines |
| 649 | 672 | err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid); |
| 650 | 673 | else if (strcmp(buf, "secinfo") == 0) |
| 651 | 674 | err = secinfo_parse(&mesg, buf, &exp); |
| 675 | + else if (strcmp(buf, "xprtsec") == 0) |
| 676 | + err = xprtsec_parse(&mesg, buf, &exp); |
| 652 | 677 | else |
| 653 | 678 | /* quietly ignore unknown words and anything |
| 654 | 679 | * following. Newer user-space can try to set |
| @@ -662,6 +687,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) · 7 unmodified lines |
| 662 | 687 | err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid); |
| 663 | 688 | if (err) |
| 664 | 689 | goto out4; |
| 690 | + |
| 665 | 691 | /* |
| 666 | 692 | * No point caching this if it would immediately expire. |
| 667 | 693 | * Also, this protects exportfs's dummy export from the |
| @@ -823,6 +849,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) · 155 unmodified lines |
| 823 | 849 | for (i = 0; i < MAX_SECINFO_LIST; i++) { |
| 824 | 850 | new->ex_flavors[i] = item->ex_flavors[i]; |
| 825 | 851 | } |
| 852 | + new->ex_xprtsec_modes = item->ex_xprtsec_modes; |
| 826 | 853 | } |
| 827 | 854 | |
| 828 | 855 | static struct cache_head *svc_export_alloc(void) |
| @@ -1034,9 +1061,26 @@ static struct svc_export *exp_find(struct cache_detail *cd, · 205 unmodified lines |
| 1034 | 1061 | |
| 1035 | 1062 | __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) |
| 1036 | 1063 | { |
| 1037 | | − struct exp_flavor_info *f; |
| 1038 | | − struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors; |
| 1064 | + struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; |
| 1065 | + struct svc_xprt *xprt = rqstp->rq_xprt; |
| 1066 | + |
| 1067 | + if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) { |
| 1068 | + if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags)) |
| 1069 | + goto ok; |
| 1070 | + } |
| 1071 | + if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_TLS) { |
| 1072 | + if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) && |
| 1073 | + !test_bit(XPT_PEER_AUTH, &xprt->xpt_flags)) |
| 1074 | + goto ok; |
| 1075 | + } |
| 1076 | + if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_MTLS) { |
| 1077 | + if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) && |
| 1078 | + test_bit(XPT_PEER_AUTH, &xprt->xpt_flags)) |
| 1079 | + goto ok; |
| 1080 | + } |
| 1081 | + goto denied; |
| 1039 | 1082 | |
| 1083 | +ok: |
| 1040 | 1084 | /* legacy gss-only clients are always OK: */ |
| 1041 | 1085 | if (exp->ex_client == rqstp->rq_gssclient) |
| 1042 | 1086 | return 0; |
| @@ -1061,6 +1105,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) · 18 unmodified lines |
| 1061 | 1105 | if (nfsd4_spo_must_allow(rqstp)) |
| 1062 | 1106 | return 0; |
| 1063 | 1107 | |
| 1108 | +denied: |
| 1064 | 1109 | return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec; |
| 1065 | 1110 | } |
| 1066 | 1111 | |