Whamcloud - gitweb
LU-7839 nodemap: add a flag to deny access to unmapped users 58/18758/10
authorKit Westneat <kit.westneat@gmail.com>
Thu, 3 Mar 2016 03:36:49 +0000 (22:36 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 20 Jul 2016 17:42:53 +0000 (17:42 +0000)
Sometimes it makes more sense to deny access to users who aren't
mapped, instead of just squashing them to nobody. This patch adds a
per-nodemap flag which, if enabled, makes it so EACCES is returned to
all users mapped to the squashed UID. One use case is preventing an
unmapped user from being able to fill a /tmp-style directory, and in
conjunction with SSK it can restrict users of authorized clients to
their subset of the filesystem namespace, essentially providing
isolated containers.

Signed-off-by: Kit Westneat <kit.westneat@gmail.com>
Change-Id: Ia511c887dd94bdec281cbb85e46d49496f85721c
Reviewed-on: http://review.whamcloud.com/18758
Tested-by: Jenkins
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/doc/lctl-nodemap-modify.8
lustre/include/lustre_cfg.h
lustre/include/lustre_nodemap.h
lustre/mdt/mdt_lib.c
lustre/mgs/mgs_handler.c
lustre/mgs/mgs_llog.c
lustre/ptlrpc/nodemap_handler.c
lustre/ptlrpc/nodemap_lproc.c
lustre/ptlrpc/nodemap_storage.c
lustre/utils/lctl.c
lustre/utils/obd.c

index 8e01dea..846eb99 100644 (file)
@@ -42,6 +42,17 @@ squash_gid
 .RS 4
 Defaults to 99. The group ID that unknown groups (if not trusted) and root (if not admin) should be mapped to.
 .RE
+.PP
+deny_unknown
+.RS 4
+Defaults to off. If set to on then unknown (squashed) users will be denied
+access to the filesystem completely instead of just being squashed. Users are
+considered unknown by nodemap if the admin flag is off and the user is root, or
+trusted are set to off and the user is not mapped.
+
+Note: directory entries cached by a Lustre client may be visible to unknown
+users located on the same client, though the contents of the files will not be.
+.RE
 
 .I value
 is the value to set for the property. Should be 0 or 1 for admin and trusted.
index f635786..dce22ff 100644 (file)
@@ -118,6 +118,7 @@ enum lcfg_command_type {
        LCFG_NODEMAP_TEST_NID   = 0x00ce055, /**< test for nodemap membership */
        LCFG_NODEMAP_TEST_ID    = 0x00ce056, /**< test uid/gid mapping */
        LCFG_NODEMAP_SET_FILESET   = 0x00ce057, /**< set fileset */
+       LCFG_NODEMAP_DENY_UNKNOWN  = 0x00ce058, /**< deny squashed nodemap users */
 };
 
 struct lustre_cfg_bufs {
index 3729253..6eb79ce 100644 (file)
@@ -64,6 +64,7 @@ struct lu_nodemap {
        char                     nm_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
        /* flags to govern nodemap behavior */
        bool                     nmf_trust_client_ids:1,
+                                nmf_deny_unknown:1,
                                 nmf_allow_root_access:1;
        /* unique ID set by MGS */
        unsigned int             nm_id;
@@ -119,6 +120,7 @@ int nodemap_add_range(const char *name, const lnet_nid_t nid[2]);
 int nodemap_del_range(const char *name, const lnet_nid_t nid[2]);
 int nodemap_set_allow_root(const char *name, bool allow_root);
 int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids);
+int nodemap_set_deny_unknown(const char *name, bool deny_unknown);
 int nodemap_set_squash_uid(const char *name, uid_t uid);
 int nodemap_set_squash_gid(const char *name, gid_t gid);
 bool nodemap_can_setquota(const struct lu_nodemap *nodemap);
index eb08efc..990b482 100644 (file)
@@ -405,6 +405,18 @@ static int old_init_ucred_common(struct mdt_thread_info *info,
        struct mdt_device       *mdt = info->mti_mdt;
        struct md_identity      *identity = NULL;
 
+       if (nodemap && uc->uc_o_uid == nodemap->nm_squash_uid) {
+               /* deny access before we get identity ref */
+               if (nodemap->nmf_deny_unknown)
+                       RETURN(-EACCES);
+
+               uc->uc_fsuid = nodemap->nm_squash_uid;
+               uc->uc_fsgid = nodemap->nm_squash_gid;
+               uc->uc_cap = 0;
+               uc->uc_suppgids[0] = -1;
+               uc->uc_suppgids[1] = -1;
+       }
+
        if (!is_identity_get_disabled(mdt->mdt_identity_cache)) {
                identity = mdt_identity_get(mdt->mdt_identity_cache,
                                            uc->uc_fsuid);
@@ -421,14 +433,6 @@ static int old_init_ucred_common(struct mdt_thread_info *info,
        }
        uc->uc_identity = identity;
 
-       if (nodemap && uc->uc_o_uid == nodemap->nm_squash_uid) {
-               uc->uc_fsuid = nodemap->nm_squash_uid;
-               uc->uc_fsgid = nodemap->nm_squash_gid;
-               uc->uc_cap = 0;
-               uc->uc_suppgids[0] = -1;
-               uc->uc_suppgids[1] = -1;
-       }
-
        /* process root_squash here. */
        mdt_root_squash(info, mdt_info_req(info)->rq_peer.nid);
 
@@ -438,6 +442,8 @@ static int old_init_ucred_common(struct mdt_thread_info *info,
        uc->uc_valid = UCRED_OLD;
        ucred_set_jobid(info, uc);
 
+       EXIT;
+
        return 0;
 }
 
index 06f5a08..3fa8c39 100644 (file)
@@ -763,6 +763,7 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
                break;
        case LCFG_NODEMAP_ADMIN:
        case LCFG_NODEMAP_TRUSTED:
+       case LCFG_NODEMAP_DENY_UNKNOWN:
        case LCFG_NODEMAP_SQUASH_UID:
        case LCFG_NODEMAP_SQUASH_GID:
                if (lcfg->lcfg_bufcount != 4)
index 22e0e8d..0d0736a 100644 (file)
@@ -4163,6 +4163,10 @@ int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
                bool_switch = simple_strtoul(param, NULL, 10);
                rc = nodemap_set_allow_root(nodemap_name, bool_switch);
                break;
+       case LCFG_NODEMAP_DENY_UNKNOWN:
+               bool_switch = simple_strtoul(param, NULL, 10);
+               rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
+               break;
        case LCFG_NODEMAP_TRUSTED:
                bool_switch = simple_strtoul(param, NULL, 10);
                rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
index e4f1124..e80247a 100644 (file)
@@ -1005,6 +1005,7 @@ struct lu_nodemap *nodemap_create(const char *name,
        if (is_default || default_nodemap == NULL) {
                nodemap->nmf_trust_client_ids = 0;
                nodemap->nmf_allow_root_access = 0;
+               nodemap->nmf_deny_unknown = 0;
 
                nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
                nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
@@ -1016,6 +1017,8 @@ struct lu_nodemap *nodemap_create(const char *name,
                                default_nodemap->nmf_trust_client_ids;
                nodemap->nmf_allow_root_access =
                                default_nodemap->nmf_allow_root_access;
+               nodemap->nmf_deny_unknown =
+                               default_nodemap->nmf_deny_unknown;
 
                nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
                nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
@@ -1030,12 +1033,39 @@ out:
 }
 
 /**
- * update flag to turn on or off nodemap functions
+ * Set the nmf_deny_unknown flag to true or false.
  * \param      name            nodemap name
- * \param      admin_string    string containing updated value
+ * \param      deny_unknown    if true, squashed users will get EACCES
+ * \retval     0 on success
+ *
+ */
+int nodemap_set_deny_unknown(const char *name, bool deny_unknown)
+{
+       struct lu_nodemap       *nodemap = NULL;
+       int                     rc = 0;
+
+       mutex_lock(&active_config_lock);
+       nodemap = nodemap_lookup(name);
+       mutex_unlock(&active_config_lock);
+       if (IS_ERR(nodemap))
+               GOTO(out, rc = PTR_ERR(nodemap));
+
+       nodemap->nmf_deny_unknown = deny_unknown;
+       rc = nodemap_idx_nodemap_update(nodemap);
+
+       nm_member_revoke_locks(nodemap);
+       nodemap_putref(nodemap);
+out:
+       return rc;
+}
+EXPORT_SYMBOL(nodemap_set_deny_unknown);
+
+/**
+ * Set the nmf_allow_root_access flag to true or false.
+ * \param      name            nodemap name
+ * \param      allow_root      if true, nodemap will not squash the root user
  * \retval     0 on success
  *
- * Update admin flag to turn on or off nodemap functions.
  */
 int nodemap_set_allow_root(const char *name, bool allow_root)
 {
@@ -1059,13 +1089,12 @@ out:
 EXPORT_SYMBOL(nodemap_set_allow_root);
 
 /**
- * updated trust_client_ids flag for nodemap
+ * Set the nmf_trust_client_ids flag to true or false.
  *
- * \param      name            nodemap name
- * \param      trust_string    new value for trust flag
+ * \param      name                    nodemap name
+ * \param      trust_client_ids        if true, nodemap will not map its IDs
  * \retval     0 on success
  *
- * Update the trust_client_ids flag for a nodemap.
  */
 int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids)
 {
@@ -1089,10 +1118,10 @@ out:
 EXPORT_SYMBOL(nodemap_set_trust_client_ids);
 
 /**
- * update the squash_uid for a nodemap
+ * Update the squash_uid for a nodemap.
  *
  * \param      name            nodemap name
- * \param      uid_string      string containing new squash_uid value
+ * \param      uid             the new uid to squash unknown users to
  * \retval     0 on success
  *
  * Update the squash_uid for a nodemap. The squash_uid is the uid
@@ -1125,7 +1154,7 @@ EXPORT_SYMBOL(nodemap_set_squash_uid);
  * Update the squash_gid for a nodemap.
  *
  * \param      name            nodemap name
- * \param      gid_string      string containing new squash_gid value
+ * \param      gid             the new gid to squash unknown gids to
  * \retval     0 on success
  *
  * Update the squash_gid for a nodemap. The squash_uid is the gid
index fa6a6a7..49e7ac6 100644 (file)
@@ -463,6 +463,33 @@ static int nodemap_admin_seq_show(struct seq_file *m, void *data)
        return 0;
 }
 
+/**
+ * Reads and prints the deny_unknown flag for the given nodemap.
+ *
+ * \param      m               seq file in proc fs
+ * \param      data            unused
+ * \retval     0               success
+ */
+static int nodemap_deny_unknown_seq_show(struct seq_file *m, void *data)
+{
+       struct lu_nodemap *nodemap;
+       int rc;
+
+       mutex_lock(&active_config_lock);
+       nodemap = nodemap_lookup(m->private);
+       mutex_unlock(&active_config_lock);
+       if (IS_ERR(nodemap)) {
+               rc = PTR_ERR(nodemap);
+               CERROR("cannot find nodemap '%s': rc = %d\n",
+                       (char *)m->private, rc);
+               return rc;
+       }
+
+       seq_printf(m, "%d\n", (int)nodemap->nmf_deny_unknown);
+       nodemap_putref(nodemap);
+       return 0;
+}
+
 #ifdef NODEMAP_PROC_DEBUG
 /**
  * Helper functions to set nodemap flags.
@@ -1067,6 +1094,8 @@ LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
 #endif
 
+LPROC_SEQ_FOPS_RO(nodemap_deny_unknown);
+
 const struct file_operations nodemap_ranges_fops = {
        .open                   = nodemap_ranges_open,
        .read                   = seq_read,
@@ -1102,6 +1131,10 @@ static struct lprocfs_vars lprocfs_nodemap_vars[] = {
                .fops           = &nodemap_admin_fops,
        },
        {
+               .name           = "deny_unknown",
+               .fops           = &nodemap_deny_unknown_fops,
+       },
+       {
                .name           = "squash_uid",
                .fops           = &nodemap_squash_uid_fops,
        },
index b117120..8586745 100644 (file)
@@ -71,6 +71,7 @@ static struct nm_config_file *nodemap_mgs_ncf;
 enum nm_flag_shifts {
        NM_FL_ALLOW_ROOT_ACCESS = 0x1,
        NM_FL_TRUST_CLIENT_IDS = 0x2,
+       NM_FL_DENY_UNKNOWN = 0x4,
 };
 
 static void nodemap_cluster_key_init(struct nodemap_key *nk, unsigned int nm_id)
@@ -89,8 +90,12 @@ static void nodemap_cluster_rec_init(union nodemap_rec *nr,
        nr->ncr.ncr_squash_uid = cpu_to_le32(nodemap->nm_squash_uid);
        nr->ncr.ncr_squash_gid = cpu_to_le32(nodemap->nm_squash_gid);
        nr->ncr.ncr_flags = cpu_to_le32(
-               (nodemap->nmf_trust_client_ids ? NM_FL_TRUST_CLIENT_IDS : 0) |
-               (nodemap->nmf_allow_root_access ? NM_FL_ALLOW_ROOT_ACCESS : 0));
+               (nodemap->nmf_trust_client_ids ?
+                       NM_FL_TRUST_CLIENT_IDS : 0) |
+               (nodemap->nmf_allow_root_access ?
+                       NM_FL_ALLOW_ROOT_ACCESS : 0) |
+               (nodemap->nmf_deny_unknown ?
+                       NM_FL_DENY_UNKNOWN : 0));
 }
 
 static void nodemap_idmap_key_init(struct nodemap_key *nk, unsigned int nm_id,
@@ -640,6 +645,8 @@ static int nodemap_process_keyrec(struct nodemap_config *config,
                                        flags & NM_FL_ALLOW_ROOT_ACCESS;
                nodemap->nmf_trust_client_ids =
                                        flags & NM_FL_TRUST_CLIENT_IDS;
+               nodemap->nmf_deny_unknown =
+                                       flags & NM_FL_DENY_UNKNOWN;
 
                if (*recent_nodemap == NULL) {
                        *recent_nodemap = nodemap;
index bf1c32b..4d00475 100644 (file)
@@ -265,7 +265,7 @@ command_t cmdlist[] = {
        {"=== Nodemap ===", jt_noop, 0, "nodemap management"},
        {"nodemap_activate", jt_nodemap_activate, 0,
         "activate nodemap idmapping functions\n"
-        "usage: nodemap_activate"},
+        "usage: nodemap_activate {0|1}"},
        {"nodemap_add", jt_nodemap_add, 0,
         "add a new nodemap\n"
         "usage: nodemap_add <nodemap_name>"},
index 37a9b8e..5f0fa5d 100644 (file)
@@ -3801,7 +3801,7 @@ int jt_nodemap_modify(int argc, char **argv)
                fprintf(stderr, "usage: nodemap_modify --name <nodemap_name> "
                                "--property <property_name> --value <value>\n");
                fprintf(stderr, "valid properties: admin trusted "
-                               "squash_uid squash_gid\n");
+                               "squash_uid squash_gid deny_unknown\n");
                return -1;
        }
 
@@ -3809,6 +3809,8 @@ int jt_nodemap_modify(int argc, char **argv)
                cmd = LCFG_NODEMAP_ADMIN;
        } else if (strcmp("trusted", param) == 0) {
                cmd = LCFG_NODEMAP_TRUSTED;
+       } else if (strcmp("deny_unknown", param) == 0) {
+               cmd = LCFG_NODEMAP_DENY_UNKNOWN;
        } else if (strcmp("squash_uid", param) == 0) {
                cmd = LCFG_NODEMAP_SQUASH_UID;
        } else if (strcmp("squash_gid", param) == 0) {