Whamcloud - gitweb
LU-18863 nodemap: warning for inconsistencies with offset 70/58570/7
authorSebastien Buisson <sbuisson@ddn.com>
Fri, 28 Mar 2025 08:30:21 +0000 (09:30 +0100)
committerOleg Drokin <green@whamcloud.com>
Fri, 2 May 2025 02:18:35 +0000 (02:18 +0000)
When offsets are defined on a nodemap, other properties related to id
mapping are impacted.
All squash values should be in the offset range [ 0, offset_limit-1 ],
otherwise squashed ids would escape offsetting.
Any explicit id mapping should map to an fsid in the offset range,
otherwise the mapped id would escape offsetting.
And the offset limit itself should be defined so that nobody (65534)
is included in the offset range.
lctl nodemap_add_offset, nodemap_modify and nodemap_add_idmap commands
are modified to print a warning when such an inconsistency is
detected.
lctl-nodemap-add-idmap.8, lctl-nodemap-add-offset.8 and
lctl-nodemap-modify.8 manpages are updated to explain these
constraints.

Test-Parameters: trivial testlist=sanity-sec
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I129265e73957660da34837444238fbb98c620240
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58570
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Marc Vef <mvef@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/doc/lctl-nodemap-add-idmap.8
lustre/doc/lctl-nodemap-add-offset.8
lustre/doc/lctl-nodemap-modify.8
lustre/utils/lustre_cfg.c
lustre/utils/obd.c
lustre/utils/obdctl.h

index 0b551d5..163ecb6 100644 (file)
@@ -15,6 +15,12 @@ or
 .B nodemap_add_idmap
 adds an identity mapping to a nodemap. Clients that are members of the given
 nodemap will have the identities of their users mapped accordingly.
+.PP
+When offsets are defined on the nodemap, any explicit identity mapping should
+map to an
+.I FSID
+in the offset range [ 0, offset_limit-1 ], otherwise the mapped ID would escape
+offsetting.
 .SH OPTIONS
 .TP
 .BI --name " NODEMAP_NAME"
@@ -46,8 +52,10 @@ filesystem package since release 2.6.0
 .BR lustre (7),
 .BR lctl-nodemap-activate (8),
 .BR lctl-nodemap-add (8),
+.BR lctl-nodemap-add-offset (8),
 .BR lctl-nodemap-add-range (8),
 .BR lctl-nodemap-del (8),
 .BR lctl-nodemap-del-idmap (8),
+.BR lctl-nodemap-del-offset (8),
 .BR lctl-nodemap-del-range (8),
 .BR lctl-nodemap-modify (8)
index 13b90b4..1ca10b4 100644 (file)
@@ -18,12 +18,12 @@ overlapping assignments in multi-tenant systems. The
 is used to specify the number of IDs mapped by the range, starting with the
 .BR root (0)
 user/group/project ID and extending through
-.BR FSID_COUNT-1 .
+.IR FSID_COUNT-1 "."
 .PP
 An offset range cannot overlap into another's offset range.
 .PP
 A nodemap can only have one offset defined. To modify the offset already
-defined, remove it first and recreate it with new values.
+defined, just assign a new value.
 Any existing files will
 .B not
 automatically be remapped to the new
@@ -34,6 +34,21 @@ and
 .BR lfs-project (1)
 on a trusted client that has access to the unmapped, canonical file system IDs.
 So modifying a nodemap offset should be avoided if possible.
+.PP
+Once an offset is set on a nodemap, please make sure the explicit mappings are
+defined so that they do not escape the offset range. This means an explicit
+mapping should not map a client id to a file system id greater than
+.IR FSID_COUNT-1 "."
+Similarly, the
+.BR squash_uid ", " squash_gid " and " squash_projid
+values should not be set to a value greater than
+.IR FSID_COUNT-1 "."
+Otherwise this would produce file system IDs outside of the offset range.
+Finally, the offset limit
+.I FSID_COUNT
+should be defined so that the
+.B nobody
+user (65534) is included in the offset range.
 .SH OPTIONS
 .TP
 .BI --name " NAME"
index 83dafb9..7bf4ab9 100644 (file)
@@ -39,8 +39,13 @@ Defaults to
 if not specified, which is 65534 to match the standard Linux
 .B nobody
 user ID.
-The user ID that unknown users (if not trusted)
-and root (if not admin) should be mapped to.
+The user ID that unknown users (if not
+.BR trusted " ) and "
+.BR root " (if not " admin )
+should be mapped to.
+When offsets are defined on the nodemap, the squash value should be in the
+offset range [ 0, offset_limit-1 ], otherwise squashed UIDs would escape
+offsetting.
 .TP
 .B squash_gid
 Defaults to
@@ -50,6 +55,9 @@ if not specified, which is 65534 to match the standard Linux
 user ID.
 The group ID that unknown groups (if not trusted)
 and root (if not admin) should be mapped to.
+When offsets are defined on the nodemap, the squash value should be in the
+offset range [ 0, offset_limit-1 ], otherwise squashed GIDs would escape
+offsetting.
 .TP
 .B squash_projid
 Defaults to
@@ -58,6 +66,9 @@ if not specified, which is 65534 to match the standard Linux
 .B nobody
 user ID.
 The project ID that unknown projects (if not trusted) should be mapped to.
+When offsets are defined on the nodemap, the squash value should be in the
+offset range [ 0, offset_limit-1 ], otherwise squashed PROJIDs would escape
+offsetting.
 .TP
 .B deny_unknown
 Defaults to 0. If set to 1 then unknown (squashed) users will be denied
@@ -176,7 +187,9 @@ filesystem package since release 2.6.0
 .BR lctl-nodemap-activate (8),
 .BR lctl-nodemap-add (8),
 .BR lctl-nodemap-add-idmap (8),
+.BR lctl-nodemap-add-offset (8),
 .BR lctl-nodemap-add-range (8),
 .BR lctl-nodemap-del (8),
 .BR lctl-nodemap-del-idmap (8),
+.BR lctl-nodemap-del-offset (8),
 .BR lctl-nodemap-del-range (8)
index 22a3013..162d608 100644 (file)
@@ -794,6 +794,62 @@ free_reply:
        return rc;
 }
 
+int yaml_get_limit_uid(const char *config)
+{
+       yaml_parser_t parser;
+       yaml_event_t event;
+       bool done = false;
+       int rc;
+
+       /* Initialize parser */
+       if (!yaml_parser_initialize(&parser))
+               return -EOPNOTSUPP;
+
+       /* Set input string */
+       yaml_parser_set_input_string(&parser, (const unsigned char *)config,
+                                    strlen(config));
+
+       while (!done) {
+               if (!yaml_parser_parse(&parser, &event)) {
+                       yaml_parser_log_error(&parser, stderr, "lctl: ");
+                       rc = -EINVAL;
+                       goto error;
+               }
+
+               if (event.type == YAML_SCALAR_EVENT) {
+                       char *value = (char *)event.data.scalar.value;
+
+                       if (strcmp(value, "limit_uid") == 0) {
+                               yaml_event_delete(&event);
+                               if (!yaml_parser_parse(&parser, &event)) {
+                                       rc = -EINVAL;
+                                       goto error;
+                               }
+                               value = (char *)event.data.scalar.value;
+                               errno = 0;
+                               rc = strtoul(value, NULL, 10);
+                               if (errno)
+                                       rc = -errno;
+                               yaml_event_delete(&event);
+                               goto out;
+                       }
+               }
+
+               done = (event.type == YAML_STREAM_END_EVENT);
+               yaml_event_delete(&event);
+       }
+
+       rc = -ENOENT; /* Key not found */
+
+out:
+       yaml_parser_delete(&parser);
+       return rc;
+
+error:
+       yaml_parser_delete(&parser);
+       return rc;
+}
+
 /* get device list by netlink or debugfs */
 int jt_device_list(int argc, char **argv)
 {
index cb0e0e5..6f37cec 100644 (file)
@@ -989,7 +989,33 @@ int jt_obd_abort_recovery_mdt(int argc, char **argv)
 
        return obd_abort_recovery(argv[0], OBD_FLG_ABORT_RECOV_MDT);
 }
-#else /* ! HAVE_SERVER_SUPPROT */
+
+static int lcfg_get_nm_offset_limit(char *nodemap)
+{
+       /* buffer to contain nodemap/<nodemap name>/offset */
+       char param[LUSTRE_NODEMAP_NAME_LENGTH + 16 + 1];
+       char *buf = NULL;
+       size_t buflen;
+       glob_t paths;
+       int rc;
+
+       snprintf(param, sizeof(param), "nodemap/%s/offset", nodemap);
+       rc = llapi_param_get_paths(param, &paths);
+       if (rc)
+               return -errno;
+
+       rc = llapi_param_get_value(paths.gl_pathv[0], &buf, &buflen);
+       if (rc)
+               goto free_all;
+
+       rc = yaml_get_limit_uid(buf);
+
+free_all:
+       free(buf);
+       llapi_param_paths_free(&paths);
+       return rc;
+}
+#else /* ! HAVE_SERVER_SUPPORT */
 int jt_obd_no_transno(int argc, char **argv)
 {
        if (argc != 1)
@@ -4720,6 +4746,23 @@ int jt_nodemap_modify(int argc, char **argv)
                return CMD_HELP;
        }
 
+       if (cmd == LCFG_NODEMAP_SQUASH_UID ||
+           cmd == LCFG_NODEMAP_SQUASH_GID ||
+           cmd == LCFG_NODEMAP_SQUASH_PROJID) {
+               int offset_limit;
+               int squash;
+
+               offset_limit = lcfg_get_nm_offset_limit(nodemap_name);
+               squash = strtol(value, NULL, 10);
+               if (errno == ERANGE)
+                       squash = -1;
+
+               if (offset_limit && squash >= offset_limit)
+                       fprintf(stderr,
+                               "Warning: it is not recommended to have a squash value outside of the offset range [ 0, %d ] as it will not be mapped properly.\n",
+                               offset_limit - 1);
+       }
+
        rc = nodemap_cmd(cmd, false, NULL, 0, argv[0], nodemap_name, param,
                         value, NULL);
        if (rc != 0) {
@@ -4796,7 +4839,12 @@ int jt_nodemap_add_offset(int argc, char **argv)
        /* user warnings for setting offset to 0 or less than 65536 */
        if (offset < 65536)
                fprintf(stderr,
-                       "It is not recomended to have an offset before 65536 as the nobody/squash id's will not be mapped properly.\n");
+                       "Warning: it is not recommended to have an offset before 65536 as the nobody/squash ids will not be mapped properly.\n");
+
+       /* user warning for setting limit to less than 65536 */
+       if (limit < 65536)
+               fprintf(stderr,
+                       "Warning: it is not recommended to have a limit below 65536 as the nobody/squash ids will not be mapped properly.\n");
 
        snprintf(param, sizeof(param), "%u+%u", offset, limit);
 
@@ -4869,6 +4917,8 @@ int jt_nodemap_add_idmap(int argc, char **argv)
        char *nodemap_name = NULL;
        char *idtype = NULL;
        char *idmap = NULL;
+       char *fsid = NULL;
+       int fsid_val = -1;
        int c, rc = 0;
 
        static struct option long_opts[] = {
@@ -4925,6 +4975,22 @@ add_idmap_usage:
                goto add_idmap_usage;
        }
 
+       fsid = strchr(idmap, ':');
+       if (fsid) {
+               fsid_val = strtol(fsid + 1, NULL, 10);
+               if (errno == ERANGE)
+                       fsid_val = -1;
+       }
+       if (fsid_val != -1) {
+               int offset_limit;
+
+               offset_limit = lcfg_get_nm_offset_limit(nodemap_name);
+               if (offset_limit && fsid_val >= offset_limit)
+                       fprintf(stderr,
+                               "Warning: it is not recommended to map an id outside of the offset range [ 0, %d ] as it will not be mapped properly.\n",
+                               offset_limit - 1);
+       }
+
        rc = nodemap_cmd(cmd, false, NULL, 0,
                         argv[0], nodemap_name, idmap, NULL);
        if (rc != 0) {
index bb87138..5e7efc5 100644 (file)
@@ -165,6 +165,7 @@ int jt_lcfg_param(int argc, char **argv);
 int jt_lcfg_confparam(int argc, char **argv);
 int jt_lcfg_applyyaml(int argc, char **argv);
 int jt_lcfg_setparam_perm(int argc, char **argv, struct param_opts *popt);
+int yaml_get_limit_uid(const char *config);
 
 int jt_pool_cmd(int argc, char **argv);
 int jt_del_ost(int argc, char **argv);