diff options
-rw-r--r-- | fs/nfsd/export.c | 56 | ||||
-rw-r--r-- | include/linux/nfsd/export.h | 17 |
2 files changed, 71 insertions, 2 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index d4accdcb53a2..fbbbcc5a2fa3 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/nfsd/nfsfh.h> | 33 | #include <linux/nfsd/nfsfh.h> |
34 | #include <linux/nfsd/syscall.h> | 34 | #include <linux/nfsd/syscall.h> |
35 | #include <linux/lockd/bind.h> | 35 | #include <linux/lockd/bind.h> |
36 | #include <linux/sunrpc/msg_prot.h> | ||
37 | #include <linux/sunrpc/gss_api.h> | ||
36 | 38 | ||
37 | #define NFSDDBG_FACILITY NFSDDBG_EXPORT | 39 | #define NFSDDBG_FACILITY NFSDDBG_EXPORT |
38 | 40 | ||
@@ -452,8 +454,48 @@ out_free_all: | |||
452 | return err; | 454 | return err; |
453 | } | 455 | } |
454 | 456 | ||
457 | static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) | ||
458 | { | ||
459 | int listsize, err; | ||
460 | struct exp_flavor_info *f; | ||
461 | |||
462 | err = get_int(mesg, &listsize); | ||
463 | if (err) | ||
464 | return err; | ||
465 | if (listsize < 0 || listsize > MAX_SECINFO_LIST) | ||
466 | return -EINVAL; | ||
467 | |||
468 | for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { | ||
469 | err = get_int(mesg, &f->pseudoflavor); | ||
470 | if (err) | ||
471 | return err; | ||
472 | /* | ||
473 | * Just a quick sanity check; we could also try to check | ||
474 | * whether this pseudoflavor is supported, but at worst | ||
475 | * an unsupported pseudoflavor on the export would just | ||
476 | * be a pseudoflavor that won't match the flavor of any | ||
477 | * authenticated request. The administrator will | ||
478 | * probably discover the problem when someone fails to | ||
479 | * authenticate. | ||
480 | */ | ||
481 | if (f->pseudoflavor < 0) | ||
482 | return -EINVAL; | ||
483 | err = get_int(mesg, &f->flags); | ||
484 | if (err) | ||
485 | return err; | ||
486 | /* Only some flags are allowed to differ between flavors: */ | ||
487 | if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags)) | ||
488 | return -EINVAL; | ||
489 | } | ||
490 | exp->ex_nflavors = listsize; | ||
491 | return 0; | ||
492 | } | ||
493 | |||
455 | #else /* CONFIG_NFSD_V4 */ | 494 | #else /* CONFIG_NFSD_V4 */ |
456 | static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; } | 495 | static inline int |
496 | fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;} | ||
497 | static inline int | ||
498 | secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; } | ||
457 | #endif | 499 | #endif |
458 | 500 | ||
459 | static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | 501 | static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) |
@@ -477,6 +519,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
477 | 519 | ||
478 | exp.ex_uuid = NULL; | 520 | exp.ex_uuid = NULL; |
479 | 521 | ||
522 | /* secinfo */ | ||
523 | exp.ex_nflavors = 0; | ||
524 | |||
480 | if (mesg[mlen-1] != '\n') | 525 | if (mesg[mlen-1] != '\n') |
481 | return -EINVAL; | 526 | return -EINVAL; |
482 | mesg[mlen-1] = 0; | 527 | mesg[mlen-1] = 0; |
@@ -554,7 +599,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
554 | if (exp.ex_uuid == NULL) | 599 | if (exp.ex_uuid == NULL) |
555 | err = -ENOMEM; | 600 | err = -ENOMEM; |
556 | } | 601 | } |
557 | } else | 602 | } else if (strcmp(buf, "secinfo") == 0) |
603 | err = secinfo_parse(&mesg, buf, &exp); | ||
604 | else | ||
558 | /* quietly ignore unknown words and anything | 605 | /* quietly ignore unknown words and anything |
559 | * following. Newer user-space can try to set | 606 | * following. Newer user-space can try to set |
560 | * new values, then see what the result was. | 607 | * new values, then see what the result was. |
@@ -655,6 +702,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) | |||
655 | { | 702 | { |
656 | struct svc_export *new = container_of(cnew, struct svc_export, h); | 703 | struct svc_export *new = container_of(cnew, struct svc_export, h); |
657 | struct svc_export *item = container_of(citem, struct svc_export, h); | 704 | struct svc_export *item = container_of(citem, struct svc_export, h); |
705 | int i; | ||
658 | 706 | ||
659 | new->ex_flags = item->ex_flags; | 707 | new->ex_flags = item->ex_flags; |
660 | new->ex_anon_uid = item->ex_anon_uid; | 708 | new->ex_anon_uid = item->ex_anon_uid; |
@@ -670,6 +718,10 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) | |||
670 | item->ex_fslocs.locations_count = 0; | 718 | item->ex_fslocs.locations_count = 0; |
671 | new->ex_fslocs.migrated = item->ex_fslocs.migrated; | 719 | new->ex_fslocs.migrated = item->ex_fslocs.migrated; |
672 | item->ex_fslocs.migrated = 0; | 720 | item->ex_fslocs.migrated = 0; |
721 | new->ex_nflavors = item->ex_nflavors; | ||
722 | for (i = 0; i < MAX_SECINFO_LIST; i++) { | ||
723 | new->ex_flavors[i] = item->ex_flavors[i]; | ||
724 | } | ||
673 | } | 725 | } |
674 | 726 | ||
675 | static struct cache_head *svc_export_alloc(void) | 727 | static struct cache_head *svc_export_alloc(void) |
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 9f62d6182d32..736f0eafcedf 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h | |||
@@ -42,6 +42,8 @@ | |||
42 | #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ | 42 | #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */ |
43 | #define NFSEXP_ALLFLAGS 0xFE3F | 43 | #define NFSEXP_ALLFLAGS 0xFE3F |
44 | 44 | ||
45 | /* The flags that may vary depending on security flavor: */ | ||
46 | #define NFSEXP_SECINFO_FLAGS 0 | ||
45 | 47 | ||
46 | #ifdef __KERNEL__ | 48 | #ifdef __KERNEL__ |
47 | 49 | ||
@@ -64,6 +66,19 @@ struct nfsd4_fs_locations { | |||
64 | int migrated; | 66 | int migrated; |
65 | }; | 67 | }; |
66 | 68 | ||
69 | /* | ||
70 | * We keep an array of pseudoflavors with the export, in order from most | ||
71 | * to least preferred. For the forseeable future, we don't expect more | ||
72 | * than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3, | ||
73 | * spkm3i, and spkm3p (and using all 8 at once should be rare). | ||
74 | */ | ||
75 | #define MAX_SECINFO_LIST 8 | ||
76 | |||
77 | struct exp_flavor_info { | ||
78 | u32 pseudoflavor; | ||
79 | u32 flags; | ||
80 | }; | ||
81 | |||
67 | struct svc_export { | 82 | struct svc_export { |
68 | struct cache_head h; | 83 | struct cache_head h; |
69 | struct auth_domain * ex_client; | 84 | struct auth_domain * ex_client; |
@@ -76,6 +91,8 @@ struct svc_export { | |||
76 | int ex_fsid; | 91 | int ex_fsid; |
77 | unsigned char * ex_uuid; /* 16 byte fsid */ | 92 | unsigned char * ex_uuid; /* 16 byte fsid */ |
78 | struct nfsd4_fs_locations ex_fslocs; | 93 | struct nfsd4_fs_locations ex_fslocs; |
94 | int ex_nflavors; | ||
95 | struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST]; | ||
79 | }; | 96 | }; |
80 | 97 | ||
81 | /* an "export key" (expkey) maps a filehandlefragement to an | 98 | /* an "export key" (expkey) maps a filehandlefragement to an |