Whamcloud - gitweb
LU-3289 gss: Add option for loading keys during mount 01/17601/16
authorJeremy Filizetti <jeremy.filizetti@gmail.com>
Mon, 14 Dec 2015 05:19:56 +0000 (00:19 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 13 Jun 2016 17:16:32 +0000 (17:16 +0000)
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 <jeremy.filizetti@gmail.com>
Change-Id: I4ffbfb9ea76d32ed69f94da93f82e90e161cb99d
Reviewed-on: http://review.whamcloud.com/17601
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Jenkins
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
lustre/doc/mount.lustre.8
lustre/utils/Makefile.am
lustre/utils/mount_lustre.c
lustre/utils/mount_utils.c
lustre/utils/mount_utils.h

index c020ae2..db88cd6 100644 (file)
@@ -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
index 9fea34e..87b4861 100644 (file)
@@ -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)
index b247327..7ed9fff 100644 (file)
@@ -114,6 +114,10 @@ void usage(FILE *out)
                "\t\tskip_lfsck: NOT auto resume the paused/crashed LFSCK\n"
                "\t\texclude=<ostname>[:<ostname>] : colon-separated list of "
                "inactive OSTs (e.g. lustre-OST0001)\n"
+#ifdef HAVE_GSS
+               "\t\tskpath=<file|directory>: Path to a file or directory of"
+               "key configuration files to load into the kernel keyring\n"
+#endif
                "\t\tretry=<num>: number of times mount is retried by client\n"
                "\t\tmd_stripe_cache_size=<num>: 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;
index 8287d34..cf4dca3 100644 (file)
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <linux/loop.h>
+#include <sys/types.h>
+#include <dirent.h>
 #include <dlfcn.h>
 
+#ifdef HAVE_GSS
+#include <keyutils.h>
+#include <lustre/utils/gss/sk_utils.h>
+#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
index ae238eb..7fd9b34 100644 (file)
@@ -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