summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-10-26 16:58:56 +0200
committerLennart Poettering <lennart@poettering.net>2021-10-27 22:46:46 +0200
commit4c2ee5c7f26fda41d7eb1250c61c85cc869a90de (patch)
tree4c7a6c4433e6fcbb6d2104c5b4b44ef7bf5e3f57
parent22aba9b2fcb5db1b48abb267f12a1420fd15ea4d (diff)
downloadsystemd-4c2ee5c7f26fda41d7eb1250c61c85cc869a90de.tar.gz
homework: allow specifying explicit additional mount options when using CIFS backend
This is useful since certain shares can only be mounted with additional mount flags. For example the SMB share in modern AVM Fritz!Boxes requires "noserverino" to be set to work from Linux.
-rw-r--r--docs/USER_RECORD.md22
-rw-r--r--man/homectl.xml6
-rw-r--r--src/home/homectl.c20
-rw-r--r--src/home/homework-cifs.c4
-rw-r--r--src/shared/user-record.c3
-rw-r--r--src/shared/user-record.h1
6 files changed, 39 insertions, 17 deletions
diff --git a/docs/USER_RECORD.md b/docs/USER_RECORD.md
index 6710b00c0c..c134ec42e3 100644
--- a/docs/USER_RECORD.md
+++ b/docs/USER_RECORD.md
@@ -415,6 +415,9 @@ mount as home directory of the user on login. Should be in format
`//<host>/<service>/<directory/…>`. The directory part is optional. If missing
the top-level directory of the CIFS share is used.
+`cifsExtraMountOptions` → A string with additional mount options to pass to
+`mount.cifs` when mounting the home directory CIFS share.
+
`imagePath` → A string with an absolute file system path to the file, directory
or block device to use for storage backing the home directory. If the `luks`
storage is used this refers to the loopback file or block device node to store
@@ -707,15 +710,16 @@ that may be used in this section are identical to the equally named ones in the
`notAfterUSec`, `storage`, `diskSize`, `diskSizeRelative`, `skeletonDirectory`,
`accessMode`, `tasksMax`, `memoryHigh`, `memoryMax`, `cpuWeight`, `ioWeight`,
`mountNoDevices`, `mountNoSuid`, `mountNoExecute`, `cifsDomain`,
-`cifsUserName`, `cifsService`, `imagePath`, `uid`, `gid`, `memberOf`,
-`fileSystemType`, `partitionUuid`, `luksUuid`, `fileSystemUuid`, `luksDiscard`,
-`luksOfflineDiscard`, `luksCipher`, `luksCipherMode`, `luksVolumeKeySize`,
-`luksPbkdfHashAlgorithm`, `luksPbkdfType`, `luksPbkdfTimeCostUSec`,
-`luksPbkdfMemoryCost`, `luksPbkdfParallelThreads`, `rateLimitIntervalUSec`,
-`rateLimitBurst`, `enforcePasswordPolicy`, `autoLogin`, `stopDelayUSec`,
-`killProcesses`, `passwordChangeMinUSec`, `passwordChangeMaxUSec`,
-`passwordChangeWarnUSec`, `passwordChangeInactiveUSec`, `passwordChangeNow`,
-`pkcs11TokenUri`, `fido2HmacCredential`.
+`cifsUserName`, `cifsService`, `cifsExtraMountOptions`, `imagePath`, `uid`,
+`gid`, `memberOf`, `fileSystemType`, `partitionUuid`, `luksUuid`,
+`fileSystemUuid`, `luksDiscard`, `luksOfflineDiscard`, `luksCipher`,
+`luksCipherMode`, `luksVolumeKeySize`, `luksPbkdfHashAlgorithm`,
+`luksPbkdfType`, `luksPbkdfTimeCostUSec`, `luksPbkdfMemoryCost`,
+`luksPbkdfParallelThreads`, `rateLimitIntervalUSec`, `rateLimitBurst`,
+`enforcePasswordPolicy`, `autoLogin`, `stopDelayUSec`, `killProcesses`,
+`passwordChangeMinUSec`, `passwordChangeMaxUSec`, `passwordChangeWarnUSec`,
+`passwordChangeInactiveUSec`, `passwordChangeNow`, `pkcs11TokenUri`,
+`fido2HmacCredential`.
## Fields in the `binding` section
diff --git a/man/homectl.xml b/man/homectl.xml
index f670566593..01e9c3b29b 100644
--- a/man/homectl.xml
+++ b/man/homectl.xml
@@ -688,13 +688,17 @@
<term><option>--cifs-domain=</option><replaceable>DOMAIN</replaceable></term>
<term><option>--cifs-user-name=</option><replaceable>USER</replaceable></term>
<term><option>--cifs-service=</option><replaceable>SERVICE</replaceable></term>
+ <term><option>--cifs-extra-mount-options=</option><replaceable>OPTIONS</replaceable></term>
<listitem><para>Configures the Windows File Sharing (CIFS) domain and user to associate with the home
directory/user account, as well as the file share ("service") to mount as directory. The latter is
used when <literal>cifs</literal> storage is selected. The file share should be specified in format
<literal>//<replaceable>host</replaceable>/<replaceable>share</replaceable>/<replaceable>directory/…</replaceable></literal>. The
directory part is optional — if not specified the home directory will be placed in the top-level
- directory of the share.</para></listitem>
+ directory of the share. The <option>--cifs-extra-mount-options=</option> setting allows specifying
+ additional mount options when mounting the share, see <citerefentry
+ project='man-pages'><refentrytitle>mount.cifs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for details.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/home/homectl.c b/src/home/homectl.c
index 502329eedd..4f1aebfe30 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -2161,6 +2161,8 @@ static int help(int argc, char *argv[], void *userdata) {
" --cifs-domain=DOMAIN CIFS (Windows) domain\n"
" --cifs-user-name=USER CIFS (Windows) user name\n"
" --cifs-service=SERVICE CIFS (Windows) service to mount as home area\n"
+ " --cifs-extra-mount-options=OPTIONS\n"
+ " CIFS (Windows) extra mount options\n"
"\n%4$sLogin Behaviour User Record Properties:%5$s\n"
" --stop-delay=SECS How long to leave user services running after\n"
" logout\n"
@@ -2217,6 +2219,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_CIFS_DOMAIN,
ARG_CIFS_USER_NAME,
ARG_CIFS_SERVICE,
+ ARG_CIFS_EXTRA_MOUNT_OPTIONS,
ARG_TASKS_MAX,
ARG_MEMORY_HIGH,
ARG_MEMORY_MAX,
@@ -2309,6 +2312,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "cifs-user-name", required_argument, NULL, ARG_CIFS_USER_NAME },
{ "cifs-domain", required_argument, NULL, ARG_CIFS_DOMAIN },
{ "cifs-service", required_argument, NULL, ARG_CIFS_SERVICE },
+ { "cifs-extra-mount-options", required_argument, NULL, ARG_CIFS_EXTRA_MOUNT_OPTIONS },
{ "rate-limit-interval", required_argument, NULL, ARG_RATE_LIMIT_INTERVAL },
{ "rate-limit-burst", required_argument, NULL, ARG_RATE_LIMIT_BURST },
{ "stop-delay", required_argument, NULL, ARG_STOP_DELAY },
@@ -2447,15 +2451,17 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_LOCATION:
case ARG_ICON_NAME:
case ARG_CIFS_USER_NAME:
- case ARG_CIFS_DOMAIN: {
+ case ARG_CIFS_DOMAIN:
+ case ARG_CIFS_EXTRA_MOUNT_OPTIONS: {
const char *field =
- c == ARG_EMAIL_ADDRESS ? "emailAddress" :
- c == ARG_LOCATION ? "location" :
- c == ARG_ICON_NAME ? "iconName" :
- c == ARG_CIFS_USER_NAME ? "cifsUserName" :
- c == ARG_CIFS_DOMAIN ? "cifsDomain" :
- NULL;
+ c == ARG_EMAIL_ADDRESS ? "emailAddress" :
+ c == ARG_LOCATION ? "location" :
+ c == ARG_ICON_NAME ? "iconName" :
+ c == ARG_CIFS_USER_NAME ? "cifsUserName" :
+ c == ARG_CIFS_DOMAIN ? "cifsDomain" :
+ c == ARG_CIFS_EXTRA_MOUNT_OPTIONS ? "cifsExtraMountOptions" :
+ NULL;
assert(field);
diff --git a/src/home/homework-cifs.c b/src/home/homework-cifs.c
index 6184d7c30e..6a4431c229 100644
--- a/src/home/homework-cifs.c
+++ b/src/home/homework-cifs.c
@@ -83,6 +83,10 @@ int home_setup_cifs(
p, h->uid, user_record_gid(h), user_record_access_mode(h), user_record_access_mode(h)) < 0)
return log_oom();
+ if (h->cifs_extra_mount_options)
+ if (!strextend_with_separator(&options, ",", h->cifs_extra_mount_options))
+ return log_oom();
+
r = safe_fork("(mount)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_STDOUT_TO_STDERR, &mount_pid);
if (r < 0)
return r;
diff --git a/src/shared/user-record.c b/src/shared/user-record.c
index 9b2029bfcf..49febade2a 100644
--- a/src/shared/user-record.c
+++ b/src/shared/user-record.c
@@ -271,6 +271,7 @@ static UserRecord* user_record_free(UserRecord *h) {
free(h->cifs_service);
free(h->cifs_user_name);
free(h->cifs_domain);
+ free(h->cifs_extra_mount_options);
free(h->image_path);
free(h->image_path_auto);
@@ -1267,6 +1268,7 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
{ "cifsDomain", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_domain), JSON_SAFE },
{ "cifsUserName", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_user_name), JSON_SAFE },
{ "cifsService", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_service), JSON_SAFE },
+ { "cifsExtraMountOptions", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_extra_mount_options), 0 },
{ "imagePath", JSON_VARIANT_STRING, json_dispatch_path, offsetof(UserRecord, image_path), 0 },
{ "uid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(UserRecord, uid), 0 },
{ "gid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(UserRecord, gid), 0 },
@@ -1612,6 +1614,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
{ "cifsDomain", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_domain), JSON_SAFE },
{ "cifsUserName", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_user_name), JSON_SAFE },
{ "cifsService", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_service), JSON_SAFE },
+ { "cifsExtraMountOptions", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, cifs_extra_mount_options), 0 },
{ "imagePath", JSON_VARIANT_STRING, json_dispatch_path, offsetof(UserRecord, image_path), 0 },
{ "homeDirectory", JSON_VARIANT_STRING, json_dispatch_home_directory, offsetof(UserRecord, home_directory), 0 },
{ "uid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(UserRecord, uid), 0 },
diff --git a/src/shared/user-record.h b/src/shared/user-record.h
index 975e3e175b..acf2cdc9d4 100644
--- a/src/shared/user-record.h
+++ b/src/shared/user-record.h
@@ -304,6 +304,7 @@ typedef struct UserRecord {
char *cifs_domain;
char *cifs_user_name;
char *cifs_service;
+ char *cifs_extra_mount_options;
char *image_path;
char *image_path_auto; /* when none is configured explicitly, this is where we place the implicit image */