]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/automount: Add ExtraOptions field
authorAndrew Stone <a@stne.dev>
Thu, 11 Nov 2021 21:45:47 +0000 (13:45 -0800)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Nov 2021 08:44:35 +0000 (09:44 +0100)
man/org.freedesktop.systemd1.xml
man/systemd.automount.xml
src/core/automount.c
src/core/automount.h
src/core/dbus-automount.c
src/core/load-fragment-gperf.gperf.in
src/shared/bus-unit-util.c
test/fuzz/fuzz-unit-file/directives.automount

index 86bf7ef108bc97c0233fec87f1d6ace204ddc634..e878f65de1a19f8813156de820f6acad456b5d35 100644 (file)
@@ -7595,6 +7595,8 @@ node /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s Where = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly s ExtraOptions = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly u DirectoryMode = ...;
       readonly s Result = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -7609,6 +7611,8 @@ node /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount
 
     <!--property Where is not documented!-->
 
+    <!--property ExtraOptions is not documented!-->
+
     <!--property DirectoryMode is not documented!-->
 
     <!--property TimeoutIdleUSec is not documented!-->
@@ -7625,6 +7629,8 @@ node /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount
 
     <variablelist class="dbus-property" generated="True" extra-ref="Where"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="ExtraOptions"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="DirectoryMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="Result"/>
index 37fd7435522d9dc3b9632fc23f3da7a1dab0f3e2..da35a7d26b01b35ce04884c18756e04cee754289 100644 (file)
         This option is mandatory.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>ExtraOptions=</varname></term>
+        <listitem><para>Extra mount options to use when creating the autofs
+        mountpoint. This takes a comma-separated list of options. This setting
+        is optional. Note that the usual specifier expansion is applied to this
+        setting, literal percent characters should hence be written as
+        <literal class='specifiers'>%%</literal>.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>DirectoryMode=</varname></term>
         <listitem><para>Directories of automount points (and any
index 0bb58fdcd150cfcd9afca8088d280c94863c230b..02089aed4e4966d02e38d52e83d4075a4d4c058d 100644 (file)
@@ -19,6 +19,7 @@
 #include "dbus-unit.h"
 #include "fd-util.h"
 #include "format-util.h"
+#include "fstab-util.h"
 #include "io-util.h"
 #include "label.h"
 #include "mkdir-label.h"
@@ -109,6 +110,7 @@ static void automount_done(Unit *u) {
         unmount_autofs(a);
 
         a->where = mfree(a->where);
+        a->extra_options = mfree(a->extra_options);
 
         a->tokens = set_free(a->tokens);
         a->expire_tokens = set_free(a->expire_tokens);
@@ -168,6 +170,15 @@ static int automount_add_default_dependencies(Automount *a) {
 }
 
 static int automount_verify(Automount *a) {
+        static const char *const reserved_options[] = {
+                "fd\0",
+                "pgrp\0",
+                "minproto\0",
+                "maxproto\0",
+                "direct\0",
+                "indirect\0",
+        };
+
         _cleanup_free_ char *e = NULL;
         int r;
 
@@ -184,6 +195,14 @@ static int automount_verify(Automount *a) {
         if (!unit_has_name(UNIT(a), e))
                 return log_unit_error_errno(UNIT(a), SYNTHETIC_ERRNO(ENOEXEC), "Where= setting doesn't match unit name. Refusing.");
 
+        for (size_t i = 0; i < ELEMENTSOF(reserved_options); i++)
+                if (fstab_test_option(a->extra_options, reserved_options[i]))
+                        return log_unit_error_errno(
+                                UNIT(a),
+                                SYNTHETIC_ERRNO(ENOEXEC),
+                                "ExtraOptions= setting may not contain reserved option %s.",
+                                reserved_options[i]);
+
         return 0;
 }
 
@@ -313,11 +332,13 @@ static void automount_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sAutomount State: %s\n"
                 "%sResult: %s\n"
                 "%sWhere: %s\n"
+                "%sExtraOptions: %s\n"
                 "%sDirectoryMode: %04o\n"
                 "%sTimeoutIdleUSec: %s\n",
                 prefix, automount_state_to_string(a->state),
                 prefix, automount_result_to_string(a->result),
                 prefix, a->where,
+                prefix, a->extra_options,
                 prefix, a->directory_mode,
                 prefix, FORMAT_TIMESPAN(a->timeout_idle_usec, USEC_PER_SEC));
 }
@@ -552,8 +573,7 @@ static void automount_enter_waiting(Automount *a) {
         _cleanup_close_ int ioctl_fd = -1;
         int p[2] = { -1, -1 };
         char name[STRLEN("systemd-") + DECIMAL_STR_MAX(pid_t) + 1];
-        char options[STRLEN("fd=,pgrp=,minproto=5,maxproto=5,direct")
-                     + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
+        _cleanup_free_ char *options = NULL;
         bool mounted = false;
         int r, dev_autofs_fd;
         struct stat st;
@@ -586,7 +606,17 @@ static void automount_enter_waiting(Automount *a) {
         if (r < 0)
                 goto fail;
 
-        xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
+        if (asprintf(
+                    &options,
+                    "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct%s%s",
+                    p[1],
+                    getpgrp(),
+                    isempty(a->extra_options) ? "" : ",",
+                    strempty(a->extra_options)) < 0) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
         xsprintf(name, "systemd-"PID_FMT, getpid_cached());
         r = mount_nofollow(name, a->where, "autofs", 0, options);
         if (r < 0)
index 4b0c633b79e1e83195fdd53077d024e28f12d3d4..684f2759a6d223d6cc0d955ae1eeef7171274600 100644 (file)
@@ -22,6 +22,7 @@ struct Automount {
         AutomountState state, deserialized_state;
 
         char *where;
+        char *extra_options;
         usec_t timeout_idle_usec;
 
         int pipe_fd;
index 3f74488daddb4f3a233b23e474926d1f967073e4..881bf50b6ee0fc92e4e529961ef22699be6629cd 100644 (file)
@@ -11,6 +11,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, Autom
 const sd_bus_vtable bus_automount_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Automount, where), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("ExtraOptions", "s", NULL, offsetof(Automount, extra_options), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Automount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Automount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("TimeoutIdleUSec", "t", bus_property_get_usec, offsetof(Automount, timeout_idle_usec), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -35,6 +36,9 @@ static int bus_automount_set_transient_property(
         if (streq(name, "Where"))
                 return bus_set_transient_path(u, name, &a->where, message, flags, error);
 
+        if (streq(name, "ExtraOptions"))
+                return bus_set_transient_string(u, name, &a->extra_options, message, flags, error);
+
         if (streq(name, "TimeoutIdleUSec"))
                 return bus_set_transient_usec_fix_0(u, name, &a->timeout_idle_usec, message, flags, error);
 
index 71a5904a7072a378782cfb436cfa569551cd03e4..67cb2d70a2457323c30020fca279dde8742a351f 100644 (file)
@@ -503,6 +503,7 @@ Mount.ReadWriteOnly,                     config_parse_bool,
 {{ CGROUP_CONTEXT_CONFIG_ITEMS('Mount') }}
 {{ KILL_CONTEXT_CONFIG_ITEMS('Mount') }}
 Automount.Where,                         config_parse_unit_path_printf,               0,                                  offsetof(Automount, where)
+Automount.ExtraOptions,                  config_parse_unit_string_printf,             0,                                  offsetof(Automount, extra_options)
 Automount.DirectoryMode,                 config_parse_mode,                           0,                                  offsetof(Automount, directory_mode)
 Automount.TimeoutIdleSec,                config_parse_sec_fix_0,                      0,                                  offsetof(Automount, timeout_idle_usec)
 Swap.What,                               config_parse_unit_path_printf,               0,                                  offsetof(Swap, parameters_fragment.what)
index bbf7499e57d7ac5173c015b305a5455995d4e6e0..b8fd85a1914fddc1d27879f496ca0c3e2c255f64 100644 (file)
@@ -894,7 +894,8 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
 }
 
 static int bus_append_automount_property(sd_bus_message *m, const char *field, const char *eq) {
-        if (streq(field, "Where"))
+        if (STR_IN_SET(field, "Where",
+                              "ExtraOptions"))
                 return bus_append_string(m, field, eq);
 
         if (streq(field, "DirectoryMode"))
index 70772ba06d5784a2183f9cce7650ddf6891578fd..fd0ce64a2e1fb9b43c4dc70dd7413142ed37c9e1 100644 (file)
@@ -3,3 +3,4 @@ automount
 DirectoryMode=
 TimeoutIdleSec=
 Where=
+ExtraOptions=