| @@ -439,7 +439,6 @@ static int check_export(struct path *path, int *flags, unsigned char *uuid) · 438 unmodified lines |
| 439 | return -EINVAL; | 439 | return -EINVAL; |
| 440 | } | 440 | } |
| 441 | return 0; | 441 | return 0; |
| 442 | | | |
| 443 | } | 442 | } |
| 444 | | 443 | |
| 445 | #ifdef CONFIG_NFSD_V4 | 444 | #ifdef CONFIG_NFSD_V4 |
| @@ -546,6 +545,29 @@ static inline int · 100 unmodified lines |
| 546 | secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; } | 545 | secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; } |
| 547 | #endif | 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 | static inline int | 571 | static inline int |
| 550 | nfsd_uuid_parse(char **mesg, char *buf, unsigned char **puuid) | 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 | exp.ex_client = dom; | 630 | exp.ex_client = dom; |
| 609 | exp.cd = cd; | 631 | exp.cd = cd; |
| 610 | exp.ex_devid_map = NULL; | 632 | exp.ex_devid_map = NULL; |
| | 633 | exp.ex_xprtsec_modes = NFSEXP_XPRTSEC_ALL; |
| 611 | | 634 | |
| 612 | /* expiry */ | 635 | /* expiry */ |
| 613 | err = get_expiry(&mesg, &exp.h.expiry_time); | 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 | err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid); | 672 | err = nfsd_uuid_parse(&mesg, buf, &exp.ex_uuid); |
| 650 | else if (strcmp(buf, "secinfo") == 0) | 673 | else if (strcmp(buf, "secinfo") == 0) |
| 651 | err = secinfo_parse(&mesg, buf, &exp); | 674 | err = secinfo_parse(&mesg, buf, &exp); |
| | 675 | else if (strcmp(buf, "xprtsec") == 0) |
| | 676 | err = xprtsec_parse(&mesg, buf, &exp); |
| 652 | else | 677 | else |
| 653 | /* quietly ignore unknown words and anything | 678 | /* quietly ignore unknown words and anything |
| 654 | * following. Newer user-space can try to set | 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 | err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid); | 687 | err = check_export(&exp.ex_path, &exp.ex_flags, exp.ex_uuid); |
| 663 | if (err) | 688 | if (err) |
| 664 | goto out4; | 689 | goto out4; |
| | 690 | |
| 665 | /* | 691 | /* |
| 666 | * No point caching this if it would immediately expire. | 692 | * No point caching this if it would immediately expire. |
| 667 | * Also, this protects exportfs's dummy export from the | 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 | for (i = 0; i < MAX_SECINFO_LIST; i++) { | 849 | for (i = 0; i < MAX_SECINFO_LIST; i++) { |
| 824 | new->ex_flavors[i] = item->ex_flavors[i]; | 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 | static struct cache_head *svc_export_alloc(void) | 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 | __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) | 1062 | __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) |
| 1036 | { | 1063 | { |
| 1037 | struct exp_flavor_info *f; | 1064 | struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; |
| 1038 | struct exp_flavor_info *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 | /* legacy gss-only clients are always OK: */ | 1084 | /* legacy gss-only clients are always OK: */ |
| 1041 | if (exp->ex_client == rqstp->rq_gssclient) | 1085 | if (exp->ex_client == rqstp->rq_gssclient) |
| 1042 | return 0; | 1086 | return 0; |
| @@ -1061,6 +1105,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) · 18 unmodified lines |
| 1061 | if (nfsd4_spo_must_allow(rqstp)) | 1105 | if (nfsd4_spo_must_allow(rqstp)) |
| 1062 | return 0; | 1106 | return 0; |
| 1063 | | 1107 | |
| | 1108 | denied: |
| 1064 | return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec; | 1109 | return rqstp->rq_vers < 4 ? nfserr_acces : nfserr_wrongsec; |
| 1065 | } | 1110 | } |
| 1066 | | 1111 | |