Whamcloud - gitweb
Branch HEAD
authorvs <vs>
Thu, 27 Nov 2008 02:12:20 +0000 (02:12 +0000)
committervs <vs>
Thu, 27 Nov 2008 02:12:20 +0000 (02:12 +0000)
b=12749
i=nathan,deen

Third of three patches for the root squash feature

map root UID/GID to UID/GID set via configuration parameter root_squash
with the exception for NID range set via configuration parameter nosquash_nids

lustre/ChangeLog
lustre/include/lustre_disk.h
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_lib.c
lustre/mdt/mdt_lproc.c
lustre/mgs/mgs_llog.c
lustre/obdclass/obd_mount.c

index 9b1a226..a4dd44c 100644 (file)
@@ -1831,6 +1831,17 @@ Details    : Mounting a filesystem with extents feature will fail on big-endian
              systems since ext3-based ldiskfs is not supported on big-endian
              systems. This can be over-riden with "bigendian_extents" mount option.
 
+Severity   : enhancement
+Bugzilla   : 12749
+Description: The root squash functionality
+Details    : A security feature, which is to prevent users from being able
+             to mount lustre on their desktop, run as root, and delete
+             all of the files in the filesystem. The goal is accomplished by
+             remapping user id (UID) and group id (GID) of the root user to
+             a UID and GID specified by the system administartor via Lustre
+             configuration management server (MGS). The functionality also
+             allows to specify sets of clients for which the remapping does
+             not apply.
 --------------------------------------------------------------------------------
 
 2007-08-10         Cluster File Systems, Inc. <info@clusterfs.com>
index e9b15b8..5049532 100644 (file)
@@ -63,6 +63,7 @@
 #define LDD_F_SV_TYPE_MDT   0x0001
 #define LDD_F_SV_TYPE_OST   0x0002
 #define LDD_F_SV_TYPE_MGS   0x0004
+#define LDD_F_SV_ALL        0x0008
 /** need an index assignment */
 #define LDD_F_NEED_INDEX    0x0010
 /** never registered */
@@ -138,9 +139,10 @@ static inline int server_make_name(__u32 flags, __u16 index, char *fs,
                                    char *name)
 {
         if (flags & (LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST)) {
-                sprintf(name, "%.8s-%s%04x", fs,
-                        (flags & LDD_F_SV_TYPE_MDT) ? "MDT" : "OST",
-                        index);
+                if (!(flags & LDD_F_SV_ALL))
+                        sprintf(name, "%.8s-%s%04x", fs,
+                                (flags & LDD_F_SV_TYPE_MDT) ? "MDT" : "OST",
+                                index);
         } else if (flags & LDD_F_SV_TYPE_MGS) {
                 sprintf(name, "MGS");
         } else {
index 4e8333b..1a5b7f7 100644 (file)
@@ -4194,6 +4194,13 @@ static void mdt_fini(const struct lu_env *env, struct mdt_device *m)
                 d->ld_obd->obd_namespace = m->mdt_namespace = NULL;
         }
 
+        cfs_free_nidlist(&m->mdt_nosquash_nids);
+        if (m->mdt_nosquash_str) {
+                OBD_FREE(m->mdt_nosquash_str, m->mdt_nosquash_strlen);
+                m->mdt_nosquash_str = NULL;
+                m->mdt_nosquash_strlen = 0;
+        }
+
         mdt_seq_fini(env, m);
         mdt_seq_fini_cli(m);
         mdt_fld_fini(env, m);
@@ -4368,6 +4375,12 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m,
         m->mdt_capa_timeout = CAPA_TIMEOUT;
         m->mdt_capa_alg = CAPA_HMAC_ALG_SHA1;
         m->mdt_ck_timeout = CAPA_KEY_TIMEOUT;
+        m->mdt_squash_uid = 0;
+        m->mdt_squash_gid = 0;
+        CFS_INIT_LIST_HEAD(&m->mdt_nosquash_nids);
+        m->mdt_nosquash_str = NULL;
+        m->mdt_nosquash_strlen = 0;
+        init_rwsem(&m->mdt_squash_sem);
 
         spin_lock_init(&m->mdt_client_bitmap_lock);
 
index ae204a9..c8f215c 100644 (file)
@@ -175,6 +175,14 @@ struct mdt_device {
         struct lustre_capa_key     mdt_capa_keys[2];
         unsigned int               mdt_capa_conf:1;
 
+        /* root squash */
+        uid_t                      mdt_squash_uid;
+        gid_t                      mdt_squash_gid;
+        struct list_head           mdt_nosquash_nids;
+        char                      *mdt_nosquash_str;
+        int                        mdt_nosquash_strlen;
+        struct rw_semaphore        mdt_squash_sem;
+
         cfs_proc_dir_entry_t      *mdt_proc_entry;
         struct lprocfs_stats      *mdt_stats;
         int                        mdt_sec_level;
index fadd75d..973571e 100644 (file)
@@ -53,6 +53,7 @@
 #define DEBUG_SUBSYSTEM S_MDS
 
 #include "mdt_internal.h"
+#include <lnet/lib-lnet.h>
 
 
 typedef enum ucred_init_type {
@@ -81,11 +82,48 @@ void mdt_exit_ucred(struct mdt_thread_info *info)
         }
 }
 
-/* XXX: root_squash will be redesigned in Lustre 1.7.
- * Do not root_squash for inter-MDS operations */
-static int mdt_root_squash(struct mdt_thread_info *info)
+static int match_nosquash_list(struct rw_semaphore *sem,
+                               struct list_head *nidlist,
+                               lnet_nid_t peernid)
 {
-        return 0;
+        int rc;
+        ENTRY;
+        down_read(sem);
+        rc = cfs_match_nid(peernid, nidlist);
+        up_read(sem);
+        RETURN(rc);
+}
+
+/* root_squash for inter-MDS operations */
+static int mdt_root_squash(struct mdt_thread_info *info, lnet_nid_t peernid)
+{
+        struct md_ucred *ucred = mdt_ucred(info);
+        ENTRY;
+
+        if (!info->mti_mdt->mdt_squash_uid || ucred->mu_fsuid)
+                RETURN(0);
+
+        if (match_nosquash_list(&info->mti_mdt->mdt_squash_sem,
+                                &info->mti_mdt->mdt_nosquash_nids,
+                                peernid)) {
+                CDEBUG(D_OTHER, "%s is in nosquash_nids list\n",
+                       libcfs_nid2str(peernid));
+                RETURN(0);
+        }
+
+        CDEBUG(D_OTHER, "squash req from %s, (%d:%d/%x)=>(%d:%d/%x)\n",
+               libcfs_nid2str(peernid),
+               ucred->mu_fsuid, ucred->mu_fsgid, ucred->mu_cap,
+               info->mti_mdt->mdt_squash_uid, info->mti_mdt->mdt_squash_gid,
+               0);
+
+        ucred->mu_fsuid = info->mti_mdt->mdt_squash_uid;
+        ucred->mu_fsgid = info->mti_mdt->mdt_squash_gid;
+        ucred->mu_cap = 0;
+        ucred->mu_suppgids[0] = -1;
+        ucred->mu_suppgids[1] = -1;
+
+        RETURN(0);
 }
 
 static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
@@ -237,8 +275,8 @@ static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
         ucred->mu_fsuid = pud->pud_fsuid;
         ucred->mu_fsgid = pud->pud_fsgid;
 
-        /* XXX: need to process root_squash here. */
-        mdt_root_squash(info);
+        /* process root_squash here. */
+        mdt_root_squash(info, peernid);
 
         /* remove fs privilege for non-root user. */
         if (ucred->mu_fsuid)
@@ -403,8 +441,8 @@ static int old_init_ucred(struct mdt_thread_info *info,
         }
         uc->mu_identity = identity;
 
-        /* XXX: need to process root_squash here. */
-        mdt_root_squash(info);
+        /* process root_squash here. */
+        mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid);
 
         /* remove fs privilege for non-root user. */
         if (uc->mu_fsuid)
@@ -443,8 +481,8 @@ static int old_init_ucred_reint(struct mdt_thread_info *info)
         }
         uc->mu_identity = identity;
 
-        /* XXX: need to process root_squash here. */
-        mdt_root_squash(info);
+        /* process root_squash here. */
+        mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid);
 
         /* remove fs privilege for non-root user. */
         if (uc->mu_fsuid)
index 37c1375..3ac423a 100644 (file)
@@ -66,6 +66,7 @@
 #include <lprocfs_status.h>
 #include <lu_time.h>
 #include "mdt_internal.h"
+#include <lnet/lib-lnet.h>
 
 static const char *mdt_proc_names[LPROC_MDT_NR] = {
 };
@@ -481,6 +482,171 @@ static int lprocfs_wr_cos(struct file *file, const char *buffer,
         return count;
 }
 
+static int lprocfs_rd_root_squash(char *page, char **start, off_t off,
+                                  int count, int *eof, void *data)
+{
+        struct obd_device *obd = data;
+        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+        ENTRY;
+
+        return snprintf(page, count, "%u:%u\n", mdt->mdt_squash_uid,
+                        mdt->mdt_squash_gid);
+}
+
+static int safe_strtoul(const char *str, char **endp, unsigned long *res)
+{
+        char n[24];
+
+        *res = simple_strtoul(str, endp, 0);
+        if (str == *endp)
+                return 1;
+
+        sprintf(n, "%lu", *res);
+        if (strncmp(n, str, *endp - str))
+                /* overflow */
+                return 1;
+        return 0;
+}
+
+static int lprocfs_wr_root_squash(struct file *file, const char *buffer,
+                                  unsigned long count, void *data)
+{
+        struct obd_device *obd = data;
+        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+        char kernbuf[50], *tmp, *end;
+        unsigned long uid, gid;
+        int nouid, nogid;
+        ENTRY;
+
+        if (count > (sizeof(kernbuf) - 1) ||
+            copy_from_user(kernbuf, buffer, count)) {
+                CWARN("%s: can't copy string to kernel space, "
+                      "uid:gid is expected, "
+                      "continue with %u:%u, "
+                      "there will be 0:0 on MDS restart\n",
+                      obd->obd_name, mdt->mdt_squash_uid,
+                      mdt->mdt_squash_gid);
+                RETURN(count);
+        }
+
+        if (copy_from_user(kernbuf, buffer, count))
+                RETURN(-EFAULT);
+
+        kernbuf[count] = '\0';
+
+        nouid = nogid = 0;
+        if (safe_strtoul(buffer, &tmp, &uid)) {
+                uid = mdt->mdt_squash_uid;
+                nouid = 1;
+        }
+
+        /* skip ':' */
+        if (*tmp == ':') {
+                tmp++;
+                if (safe_strtoul(tmp, &end, &gid)) {
+                        gid = mdt->mdt_squash_gid;
+                        nogid = 1;
+                }
+        } else {
+                gid = mdt->mdt_squash_gid;
+                nogid = 1;
+        }
+
+        mdt->mdt_squash_uid = uid;
+        mdt->mdt_squash_gid = gid;
+
+        if (nouid || nogid)
+                CWARN("%s: can't parse \"\%s\", uid:gid is expected, "
+                      "continue with %u:%u, "
+                      "there will be %u:%u on MDS restart\n",
+                      obd->obd_name,
+                      buffer, mdt->mdt_squash_uid, mdt->mdt_squash_gid,
+                      nouid ? 0 : mdt->mdt_squash_uid,
+                      nogid ? 0 : mdt->mdt_squash_gid);
+        else
+                LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
+                              obd->obd_name,
+                              mdt->mdt_squash_uid,  mdt->mdt_squash_gid);
+        RETURN(count);
+}
+
+static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
+                                    int count, int *eof, void *data)
+{
+        struct obd_device *obd = data;
+        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+
+        if (mdt->mdt_nosquash_str)
+                return snprintf(page, count, "%s\n", mdt->mdt_nosquash_str);
+        return snprintf(page, count, "NONE\n");
+}
+
+static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer,
+                                    unsigned long count, void *data)
+{
+        struct obd_device *obd = data;
+        struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+        int rc;
+        char *new;
+        struct list_head tmp;
+        ENTRY;
+
+        /* copy to kernel space */
+        OBD_ALLOC(new, count + 1);
+        if (new == 0)
+                GOTO(failed, rc = -ENOMEM);
+
+        if (copy_from_user(new, buffer, count))
+                GOTO(failed, rc = -EFAULT);
+
+        new[count] = 0;
+        if (strlen(new) != count)
+                GOTO(failed, rc = -EINVAL);
+
+        if (!strcmp(new, "NONE") || !strcmp(new, "clear")) {
+                /* empty string is special case */
+                down_write(&mdt->mdt_squash_sem);
+                if (!list_empty(&mdt->mdt_nosquash_nids)) {
+                        cfs_free_nidlist(&mdt->mdt_nosquash_nids);
+                        OBD_FREE(mdt->mdt_nosquash_str,
+                                 mdt->mdt_nosquash_strlen);
+                        mdt->mdt_nosquash_str = NULL;
+                        mdt->mdt_nosquash_strlen = 0;
+                }
+                up_write(&mdt->mdt_squash_sem);
+                LCONSOLE_INFO("%s: nosquash_nids is cleared\n",
+                              obd->obd_name);
+                OBD_FREE(new, count + 1);
+                RETURN(0);
+        }
+
+        CFS_INIT_LIST_HEAD(&tmp);
+        if (cfs_parse_nidlist(new, count, &tmp) <= 0)
+                GOTO(failed, rc = -EINVAL);
+
+        down_write(&mdt->mdt_squash_sem);
+        if (!list_empty(&mdt->mdt_nosquash_nids)) {
+                cfs_free_nidlist(&mdt->mdt_nosquash_nids);
+                OBD_FREE(mdt->mdt_nosquash_str, mdt->mdt_nosquash_strlen);
+        }
+        mdt->mdt_nosquash_str = new;
+        mdt->mdt_nosquash_strlen = count + 1;
+        list_splice(&tmp, &mdt->mdt_nosquash_nids);
+
+        LCONSOLE_INFO("%s: nosquash_nids is set to %s\n", obd->obd_name, new);
+        up_write(&mdt->mdt_squash_sem);
+        RETURN(count);
+
+ failed:
+        CWARN("%s: failed to set nosquash_nids (rc %d), "
+              "on MDS restart we will try to set it again, "
+              "continue with current nosquash_nids\n",
+              obd->obd_name, rc);
+        if (new)
+                OBD_FREE(new, count + 1);
+        RETURN(count);
+}
+
 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
         { "uuid",                       lprocfs_rd_uuid,                 0, 0 },
         { "recovery_status",            lprocfs_obd_rd_recovery_status,  0, 0 },
@@ -506,6 +672,10 @@ static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
         { "sec_level",                  lprocfs_rd_sec_level,
                                         lprocfs_wr_sec_level,               0 },
         { "commit_on_sharing",          lprocfs_rd_cos, lprocfs_wr_cos, 0 },
+        { "root_squash",                lprocfs_rd_root_squash,
+                                        lprocfs_wr_root_squash,             0 },
+        { "nosquash_nids",              lprocfs_rd_nosquash_nids,
+                                        lprocfs_wr_nosquash_nids,          0 },
         { 0 }
 };
 
index 72ea751..89dcf26 100644 (file)
@@ -2428,9 +2428,50 @@ static int mgs_write_log_param(struct obd_device *obd, struct fs_db *fsdb,
                 GOTO(end, rc);
         }
 
-        /* All mdt., ost. params in proc */
-        if ((class_match_param(ptr, PARAM_MDT, NULL) == 0) ||
-            (class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
+        /* All mdt. params in proc */
+        if (class_match_param(ptr, PARAM_MDT, NULL) == 0) {
+                char mdt_index[16];
+                int i;
+                __u32 idx;
+
+                CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
+                if (strncmp(mti->mti_svname, mti->mti_fsname,
+                            MTI_NAME_MAXLEN) == 0)
+                        /* device is unspecified completely? */
+                        rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
+                else
+                        rc = server_name2index(mti->mti_svname, &idx, NULL);
+                if (rc < 0)
+                        goto active_err;
+                if ((rc & LDD_F_SV_TYPE_MDT) == 0)
+                        goto active_err;
+                if (rc & LDD_F_SV_ALL) {
+                        for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
+                                if (!test_bit(i,
+                                              fsdb->fsdb_mdt_index_map))
+                                        continue;
+                                sprintf(mdt_index,"-MDT%04x", i);
+                                name_create(&logname, mti->mti_fsname,
+                                            mdt_index);
+                                rc = mgs_wlp_lcfg(obd, fsdb, mti,
+                                                  logname, &bufs,
+                                                  logname, ptr);
+                                name_destroy(&logname);
+                                if (rc)
+                                        goto active_err;
+                        }
+                } else {
+                        rc = mgs_wlp_lcfg(obd, fsdb, mti,
+                                          mti->mti_svname, &bufs,
+                                          mti->mti_svname, ptr);
+                        if (rc)
+                                goto active_err;
+                }
+                GOTO(end, rc);
+        }
+
+        /* All mdd., ost. params in proc */
+        if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
             (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
                 if (mgs_log_is_empty(obd, mti->mti_svname))
index be853c9..d6e7222 100644 (file)
@@ -1683,6 +1683,8 @@ int server_name2index(char *svname, __u32 *idx, char **endptr)
                 rc = LDD_F_SV_TYPE_OST;
         else
                 return(-EINVAL);
+        if (strcmp(dash + 4, "all") == 0)
+                return rc | LDD_F_SV_ALL;
 
         index = simple_strtoul(dash + 4, endptr, 16);
         *idx = index;