From 09898fdea91045c7414a7b326811b819c670263c Mon Sep 17 00:00:00 2001 From: Jeremy Filizetti Date: Mon, 14 Dec 2015 00:19:56 -0500 Subject: [PATCH] LU-3289 gss: Add option for loading keys during mount This adds functionality for loading GSS shared keys using mount.lustre (mount) command. The --skpath option has been added which supports a directory or file of keys to load. The context from which the mount occurs is used to determine which type of key to load (MGS, MDT/OST, or client). Signed-off-by: Jeremy Filizetti Change-Id: I4ffbfb9ea76d32ed69f94da93f82e90e161cb99d Reviewed-on: http://review.whamcloud.com/17601 Reviewed-by: Andreas Dilger Tested-by: Jenkins Reviewed-by: Oleg Drokin Tested-by: Maloo --- lustre/doc/mount.lustre.8 | 7 ++++ lustre/utils/Makefile.am | 15 +++++--- lustre/utils/mount_lustre.c | 37 ++++++++++++++++-- lustre/utils/mount_utils.c | 93 +++++++++++++++++++++++++++++++++++++++++++++ lustre/utils/mount_utils.h | 9 ++++- 5 files changed, 151 insertions(+), 10 deletions(-) diff --git a/lustre/doc/mount.lustre.8 b/lustre/doc/mount.lustre.8 index c020ae2..db88cd6 100644 --- a/lustre/doc/mount.lustre.8 +++ b/lustre/doc/mount.lustre.8 @@ -105,6 +105,13 @@ Enable FID to path translation by regular users. .BI nouser_fid2path Disable FID to path translation by regular users. Root and process with CAP_DAC_READ_SEARCH can still perform FID to path translation. +.TP +.BI skpath= file|directory +Path to a file or directory with the keyfile(s) to load for this mount command. +Keys are inserted into the KEY_SPEC_SESSION_KEYRING keyring with a description +containing "lustre:" and a suffix which depends on whether the context of the +mount command is for an MGS, MDT/OST, or client. +This option is only available when built with --enable-gss. .PP In addition to the standard mount options and backing disk type (e.g. ext3) options listed in diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index 9fea34e..87b4861 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -19,6 +19,11 @@ if UTILS if GSS SUBDIRS = gss +GSSSRC = gss/sk_utils.c gss/sk_utils.h gss/err_util.c gss/err_util.h +GSSLIB = -lcrypto -lssl -lkeyutils -lm +else +GSSSRC = +GSSLIB = endif # mount only finds helpers in /sbin @@ -137,19 +142,19 @@ mount_osd_ldiskfs_la_LDFLAGS := -shared -export-dynamic -module -avoid-version mount_osd_ldiskfs_la_LIBADD := $(SELINUX) endif # LDISKFS_ENABLED -mount_lustre_SOURCES = mount_lustre.c mount_utils.c mount_utils.h +mount_lustre_SOURCES = mount_lustre.c mount_utils.c mount_utils.h $(GSSSRC) mount_lustre_CPPFLAGS := ${MNTMODCFLAGS} mount_lustre_LDFLAGS := ${MNTMODLDFLAGS} -mount_lustre_LDADD := $(LIBPTLCTL) $(SELINUX) $(LDLIBMOUNT) +mount_lustre_LDADD := $(LIBPTLCTL) $(SELINUX) $(LDLIBMOUNT) $(GSSLIB) mount_lustre_DEPENDENCIES := $(LIBPTLCTL) -mkfs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h +mkfs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h $(GSSSRC) mkfs_lustre_CPPFLAGS := -UTUNEFS ${MNTMODCFLAGS} mkfs_lustre_LDFLAGS := ${MNTMODLDFLAGS} -mkfs_lustre_LDADD := $(LIBPTLCTL) $(LDLIBMOUNT) +mkfs_lustre_LDADD := $(LIBPTLCTL) $(LDLIBMOUNT) $(GSSLIB) mkfs_lustre_DEPENDENCIES := $(LIBPTLCTL) -tunefs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h +tunefs_lustre_SOURCES = mkfs_lustre.c mount_utils.c mount_utils.h $(GSSSRC) tunefs_lustre_CPPFLAGS := -DTUNEFS ${MNTMODCFLAGS} tunefs_lustre_LDFLAGS := ${MNTMODLDFLAGS} tunefs_lustre_LDADD := $(mkfs_lustre_LDADD) diff --git a/lustre/utils/mount_lustre.c b/lustre/utils/mount_lustre.c index b247327..7ed9fff 100644 --- a/lustre/utils/mount_lustre.c +++ b/lustre/utils/mount_lustre.c @@ -114,6 +114,10 @@ void usage(FILE *out) "\t\tskip_lfsck: NOT auto resume the paused/crashed LFSCK\n" "\t\texclude=[:] : colon-separated list of " "inactive OSTs (e.g. lustre-OST0001)\n" +#ifdef HAVE_GSS + "\t\tskpath=: Path to a file or directory of" + "key configuration files to load into the kernel keyring\n" +#endif "\t\tretry=: number of times mount is retried by client\n" "\t\tmd_stripe_cache_size=: set the raid stripe cache " "size for the underlying raid if present\n"); @@ -277,6 +281,17 @@ int parse_options(struct mount_opts *mop, char *orig_options, int *flagp) /* XXX special check for 'force' option */ ++mop->mo_force; printf("force: %d\n", mop->mo_force); +#ifdef HAVE_GSS + } else if (val && strncmp(opt, "skpath=", 7) == 0) { + if (strlen(val) + 1 >= sizeof(mop->mo_skpath)) { + fprintf(stderr, + "%s: shared key path too long\n", + progname); + free(options); + return -1; + } + strncpy(mop->mo_skpath, val + 1, strlen(val + 1)); +#endif } else if (parse_one_option(opt, flagp) == 0) { /* pass this on as an option */ append_option(options, opt); @@ -629,6 +644,7 @@ int main(int argc, char *const argv[]) struct mount_opts mop; char *options; int i, rc, flags; + bool client; progname = strrchr(argv[0], '/'); progname = progname ? progname + 1 : argv[0]; @@ -687,7 +703,8 @@ int main(int argc, char *const argv[]) return rc; } - if (strstr(mop.mo_usource, ":/") == NULL) { + client = (strstr(mop.mo_usource, ":/") != NULL); + if (!client) { rc = osd_init(); if (rc) return rc; @@ -706,14 +723,26 @@ int main(int argc, char *const argv[]) printf("mounting device %s at %s, flags=%#x options=%s\n", mop.mo_source, mop.mo_target, flags, options); - if (strstr(mop.mo_usource, ":/") == NULL && - osd_tune_lustre(mop.mo_source, &mop)) { + if (!client && osd_tune_lustre(mop.mo_source, &mop)) { if (verbose) fprintf(stderr, "%s: unable to set tunables for %s" " (may cause reduced IO performance)\n", argv[0], mop.mo_source); } +#ifdef HAVE_GSS + if (mop.mo_skpath[0] != '\0') { + /* Treat shared key failures as fatal */ + rc = load_shared_keys(&mop); + if (rc) { + fprintf(stderr, + "%s: Error loading shared keys: %s\n", + progname, strerror(rc)); + return rc; + } + } +#endif + if (!mop.mo_fake) { /* flags and target get to lustre_get_sb(), but not * lustre_fill_super(). Lustre ignores the flags, but mount @@ -833,7 +862,7 @@ int main(int argc, char *const argv[]) /* mo_usource should be freed, but we can rely on the kernel */ free(mop.mo_source); - if (strstr(mop.mo_usource, ":/") == NULL) + if (!client) osd_fini(); return rc; diff --git a/lustre/utils/mount_utils.c b/lustre/utils/mount_utils.c index 8287d34..cf4dca3 100644 --- a/lustre/utils/mount_utils.c +++ b/lustre/utils/mount_utils.c @@ -52,8 +52,15 @@ #include #include #include +#include +#include #include +#ifdef HAVE_GSS +#include +#include +#endif + #include "mount_utils.h" extern char *progname; @@ -873,3 +880,89 @@ int file_create(char *path, __u64 size) return 0; } + +#ifdef HAVE_GSS +int load_shared_keys(struct mount_opts *mop) +{ + DIR *dir; + struct dirent *dentry; + struct stat sbuf; + char fullpath[PATH_MAX]; + char *path = mop->mo_skpath; + int type = 0; + int rc; + + if (IS_SERVER(&mop->mo_ldd)) { + if (IS_MGS(&mop->mo_ldd)) + type |= SK_TYPE_MGS; + if (IS_MDT(&mop->mo_ldd) || IS_OST(&mop->mo_ldd)) + type |= SK_TYPE_SERVER | SK_TYPE_CLIENT; + } else { + type |= SK_TYPE_CLIENT; + } + + /* init logging */ + sk_init_logging(NULL, 1, 1); + + rc = stat(path, &sbuf); + if (rc < 0) { + fprintf(stderr, "stat() failed for key %s: %s\n", path, + strerror(errno)); + return -errno; + } + + /* Load individual keys or a directory of them */ + if (S_ISREG(sbuf.st_mode)) { + return sk_load_keyfile(path, type); + } else if (!S_ISDIR(sbuf.st_mode)) { + fprintf(stderr, "Invalid shared key path: %s\n", path); + return -ENOKEY; + } + + dir = opendir(path); + if (dir == NULL) { + fprintf(stderr, "Unable to open shared key directory: %s\n", + path); + return -ENOENT; + } + + /* Loop through the files in the directory attempting to load them. + * Any issue with loading the keyfile is treated as an error although + * the loop continues until all files have been attempted. This will + * allow all errors be reported at once rather then requiring + * incremental corrections to fix each one and try again. */ + while ((dentry = readdir(dir)) != NULL) { + if (strcmp(".", dentry->d_name) == 0 || + strcmp("..", dentry->d_name) == 0) + continue; + + rc = snprintf(fullpath, PATH_MAX, "%s/%s", path, + dentry->d_name); + if (rc >= PATH_MAX) { + fprintf(stderr, "Path too long for %s/%s\n", + path, dentry->d_name); + rc = -ENAMETOOLONG; + continue; + } + + rc = stat(fullpath, &sbuf); + if (rc < 0) { + fprintf(stderr, "Unable to stat %s: %s\n", fullpath, + strerror(errno)); + rc = -errno; + continue; + } + + if (!S_ISREG(sbuf.st_mode)) + continue; + + rc = sk_load_keyfile(fullpath, type); + if (rc) { + fprintf(stderr, "Failed to load key %s\n", fullpath); + } + } + closedir(dir); + + return rc; +} +#endif diff --git a/lustre/utils/mount_utils.h b/lustre/utils/mount_utils.h index ae238eb..7fd9b34 100644 --- a/lustre/utils/mount_utils.h +++ b/lustre/utils/mount_utils.h @@ -100,6 +100,9 @@ struct mount_opts { char *mo_usource; /* user-specified mount device */ char *mo_source; /* our mount device name */ char mo_target[PATH_MAX]; /* mount directory */ +#ifdef HAVE_GSS + char mo_skpath[PATH_MAX]; /* shared key file/directory */ +#endif int mo_nomtab; int mo_fake; int mo_force; @@ -119,6 +122,10 @@ int get_mountdata(char *, struct lustre_disk_data *); #define IS_OST(data) ((data)->ldd_flags & LDD_F_SV_TYPE_OST) #undef IS_MGS #define IS_MGS(data) ((data)->ldd_flags & LDD_F_SV_TYPE_MGS) +#undef IS_SERVER +#define IS_SERVER(data) ((data)->ldd_flags & (LDD_F_SV_TYPE_MGS | \ + LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST)) + /* mkfs/mount helper functions */ void fatal(void); @@ -176,5 +183,5 @@ struct module_backfs_ops { struct module_backfs_ops *load_backfs_module(enum ldd_mount_type mount_type); void unload_backfs_ops(struct module_backfs_ops *ops); - +int load_shared_keys(struct mount_opts *mop); #endif -- 1.8.3.1