]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mount-tool: add explicitly control of path canonicalization
authorLennart Poettering <lennart@poettering.net>
Fri, 7 Feb 2025 11:32:16 +0000 (12:32 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 18 Feb 2025 12:49:24 +0000 (13:49 +0100)
With this the default canonicalization of paths can be turned off,
giving users explicit control on what shall happen if symlinks are
encountered within a path.

man/systemd-mount.xml
src/mount/mount-tool.c

index d0eb9678d7fcd68a193c8727cafaa25747c771ad..9723af64d665cd8b080d5e6fe6d07fab87f6cbb2 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--canonicalize=</option></term>
+
+        <listitem>
+          <para>Controls whether the specified path shall be canonicalized on the client side before
+          requesting the operation or not. Takes a boolean parameter, defaults to true. Note that for
+          non-local operation (i.e. when <option>--machine=</option> or --<option>--host=</option> are used)
+          canonicalization is implicitly turned off.</para>
+
+          <para>Canonicalization of path entails resolving of symlinks, <literal>..</literal> path elements
+          and <varname>LABEL=</varname>/<varname>UUID=</varname> style device node expansion. If
+          canonicalization is disabled and the path contains a symlink element, <literal>..</literal>, or a
+          <varname>LABEL=</varname>/<varname>UUID=</varname>/… expansion the operation will fail.</para>
+
+          <xi:include href="version-info.xml" xpointer="v258"/>
+        </listitem>
+      </varlistentry>
+
       <xi:include href="user-system-options.xml" xpointer="user" />
       <xi:include href="user-system-options.xml" xpointer="system" />
       <xi:include href="user-system-options.xml" xpointer="host" />
index 3dd34b9e7391ca2319b4d30746c1a2acffc60223..27fd318fb059c9d1a38ecaad55ba2113807162cb 100644 (file)
@@ -75,6 +75,7 @@ static bool arg_fsck = true;
 static bool arg_aggressive_gc = false;
 static bool arg_tmpfs = false;
 static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
+static bool arg_canonicalize = true;
 
 STATIC_DESTRUCTOR_REGISTER(arg_mount_what, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_mount_where, freep);
@@ -90,14 +91,14 @@ static int parse_where(const char *input, char **ret_where) {
         assert(input);
         assert(ret_where);
 
-        if (arg_transport == BUS_TRANSPORT_LOCAL) {
-                r = chase(input, NULL, CHASE_NONEXISTENT, ret_where, NULL);
+        if (arg_transport == BUS_TRANSPORT_LOCAL && arg_canonicalize) {
+                r = chase(input, /* root= */ NULL, CHASE_NONEXISTENT, ret_where, /* ret_fd= */ NULL);
                 if (r < 0)
                         return log_error_errno(r, "Failed to make path %s absolute: %m", input);
         } else {
                 if (!path_is_absolute(input))
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "Path must be absolute when operating remotely: %s",
+                                               "Path must be absolute when operating remotely or when canonicalization is turned off: %s",
                                                input);
 
                 r = path_simplify_alloc(input, ret_where);
@@ -119,8 +120,9 @@ static int help(void) {
         printf("systemd-mount [OPTIONS...] WHAT [WHERE]\n"
                "systemd-mount [OPTIONS...] --tmpfs [NAME] WHERE\n"
                "systemd-mount [OPTIONS...] --list\n"
-               "%s [OPTIONS...] %sWHAT|WHERE...\n\n"
-               "%sEstablish a mount or auto-mount point transiently.%s\n\n"
+               "%1$s [OPTIONS...] %7$sWHAT|WHERE...\n"
+               "\n%5$sEstablish a mount or auto-mount point transiently.%6$s\n"
+               "\n%3$sOptions:%4$s\n"
                "  -h --help                       Show this help\n"
                "     --version                    Show package version\n"
                "     --no-block                   Do not wait until operation finished\n"
@@ -149,12 +151,16 @@ static int help(void) {
                "  -u --umount                     Unmount mount points\n"
                "  -G --collect                    Unload unit after it stopped, even when failed\n"
                "  -T --tmpfs                      Create a new tmpfs on the mount point\n"
-               "\nSee the %s for details.\n",
+               "     --canonicalize=BOOL          Controls whether to canonicalize path before\n"
+               "                                  operation\n"
+               "\nSee the %2$s for details.\n",
                program_invocation_short_name,
-               streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount ",
+               link,
+               ansi_underline(),
+               ansi_normal(),
                ansi_highlight(),
                ansi_normal(),
-               link);
+               streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount ");
 
         return 0;
 }
@@ -181,6 +187,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_BIND_DEVICE,
                 ARG_LIST,
                 ARG_JSON,
+                ARG_CANONICALIZE,
         };
 
         static const struct option options[] = {
@@ -213,6 +220,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "collect",            no_argument,       NULL, 'G'                    },
                 { "tmpfs",              no_argument,       NULL, 'T'                    },
                 { "json",               required_argument, NULL, ARG_JSON               },
+                { "canonicalize",       required_argument, NULL, ARG_CANONICALIZE       },
                 {},
         };
 
@@ -374,6 +382,13 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_CANONICALIZE:
+                        r = parse_boolean_argument("--canonicalize=", optarg, &arg_canonicalize);
+                        if (r < 0)
+                                return r;
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -441,21 +456,21 @@ static int parse_argv(int argc, char *argv[]) {
                                 if (!arg_mount_what)
                                         return log_oom();
 
-                        } else if (arg_transport == BUS_TRANSPORT_LOCAL) {
+                        } else if (arg_transport == BUS_TRANSPORT_LOCAL && arg_canonicalize) {
                                 _cleanup_free_ char *u = NULL;
 
                                 u = fstab_node_to_udev_node(argv[optind]);
                                 if (!u)
                                         return log_oom();
 
-                                r = chase(u, NULL, 0, &arg_mount_what, NULL);
+                                r = chase(u, /* root= */ NULL, /* flags= */ 0, &arg_mount_what, /* ret_fd= */ NULL);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to make path %s absolute: %m", u);
 
                         } else {
                                 if (!path_is_absolute(argv[optind]))
                                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                               "Path must be absolute when operating remotely: %s",
+                                                               "Path must be absolute when operating remotely or when canonicalization is turned off: %s",
                                                                argv[optind]);
 
                                 r = path_simplify_alloc(argv[optind], &arg_mount_what);
@@ -1050,7 +1065,7 @@ static int action_umount(
         assert(argv);
         assert(argc > optind);
 
-        if (arg_transport != BUS_TRANSPORT_LOCAL) {
+        if (arg_transport != BUS_TRANSPORT_LOCAL || !arg_canonicalize) {
                 for (int i = optind; i < argc; i++) {
                         _cleanup_free_ char *p = NULL;