Compare commits

...

27 Commits

Author SHA1 Message Date
Ronan Pigott d763d474a6
Merge d4f1b642c2 into c946b13575 2024-11-22 22:43:49 +00:00
Christian Hesse c946b13575 link README.logs from tmpfiles.d/legacy.conf only if available
The file README.logs is installed only if SysVInit support is enabled.
Thus the link should depend on it as well.
2024-11-22 18:33:20 +00:00
Lennart Poettering e39cbb1442 varlink: apparently on old kernels SO_PEERPIDFD returns EINVAL 2024-11-23 03:09:49 +09:00
Marco Tomaschett bc4a027f9c
hwdb: add support for PineTab2 to 60-sensor.hwdb (#35304)
Add accelerometer support for PineTab2
2024-11-23 03:08:06 +09:00
Lennart Poettering d209e197f8
userdbctl: two trivial fixlets (#35296)
Fixes: #35294
2024-11-22 16:06:01 +01:00
Antonio Alvarez Feijoo 9ed090230e tpm2-util: fix parameter name 2024-11-22 16:04:16 +01:00
Luca Boccassi 9bf6ffe166
man: split cryptenroll man page into sections (#35297) 2024-11-22 12:01:07 +00:00
Lennart Poettering 47c5ca237b userdbctl: respect selected disposition also when showing gid boundaries
Follow-up for: ad5de3222f
2024-11-22 11:28:30 +01:00
Lennart Poettering 7f8a4f12df userdbctl: fix counting
Fixes: #35294
2024-11-22 11:28:28 +01:00
Lennart Poettering e412fc5e04 userbdctl: show 'mapped' user range only inside of userns
Outside of userns the concept makes no sense, there cannot be users
mapped from further outside.
2024-11-22 11:28:17 +01:00
Lennart Poettering cc6baba720 cryptenroll: it's called PKCS#11, not PKCS11
In the --help text we really should use the official spelling, just like
in the man page.
2024-11-22 10:42:37 +01:00
Lennart Poettering 3ae48d071c man: add enrollment type sections to cryptenroll man page
We have the same sections in the --help text, hence we even more so
should have them in the man page.
2024-11-22 10:42:37 +01:00
Antonio Alvarez Feijoo 2ccacdd57c bash-completion: add --list-devices to systemd-cryptenroll
And also use it to list suitable block devices.
2024-11-22 10:38:19 +01:00
Yu Watanabe d99198819c core/service: service_add_fd_store() consumes passed fd
Without this change, the fd is closed twice on failure.

Fixes a bug introduced by dff9808a62.

Fixes #35288.
2024-11-22 04:15:51 +01:00
Tobias Zimmermann f70e5620b6 hwdb: Add quirk for Logitech MX Keys for Mac
The KEY_102ND and KEY_GRAVE keys are switched on the
Logitech MX Keys for Mac, so switch them back
2024-11-21 21:16:07 +01:00
Zbigniew Jędrzejewski-Szmek 3127c71bf4
Keep tmpfiles/legacy.conf even if SysVInit support is dropped (#35278) 2024-11-21 21:13:50 +01:00
Yuri Chornoivan b153eebfb2 po: Translated using Weblate (Ukrainian)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Yuri Chornoivan <yurchor@ukr.net>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/uk/
Translation: systemd/main
2024-11-22 05:02:16 +09:00
Zbigniew Jędrzejewski-Szmek 2c06e40ae9 tmpfiles: add period at end of the sentence
The license that is immediately above is properly punctuated and it looks
sloppy when our line below isn't.
2024-11-21 18:35:18 +01:00
Zbigniew Jędrzejewski-Szmek 5ca9149464 tmpfiles: narrow scope of HAVE_SYSV_COMPAT condition for legacy.conf
That file contains a bunch of entries of which only some are related to SysV.
The rest are just "traditional APIs" that need to stay. In particular,
/var/lock a.k.a. /run/lock is used by many programs (LVM, iscsi, alsactl).
Similarly, the README about /var/log is something that should stay as long as
we have people migrating from older systems or using the copiuos documentation
that mentions /var/log/messages.txt on the Internet.

/var/lock/subsys is only used by sysvinit, and our code to support /forcefsck,
/fastboot, and /forcequotacheck is conditionalized on HAVE_SYSV_COMPAT, so
conditionalize those here on HAVE_SYSV_COMPAT too.
2024-11-21 18:32:46 +01:00
Ronan Pigott d4f1b642c2 pam: add session class "none" to disable logind sessions
pam_systemd is used to create logind sessions and to apply extended
attributes from json user records. Not every application that creates a
pam session expects a login scope, but may be interested in the extended
attributes of json user records. Session class "none" implements this
service by disabling logind for this session altogether.
2024-11-15 11:38:19 -07:00
Lennart Poettering 65250fac6a pam_systemd: introduce pam_get_data_many() helper and make use of it
This is to pam_get_data() what pam_get_item() is to pam_get_item_many().
2024-11-15 15:23:41 +01:00
Lennart Poettering 5d8efe440e pam_systemd: fix error code confusion when prepping D-Bus message
We got confused by the error codes here, and sometimes return PAM errors
where the caller propagated them unconverted as negative errno errors. Fix that.
2024-11-15 15:10:58 +01:00
Lennart Poettering 524f0d14e1 pam_systemd: split pam_sm_open_session() into more digestable blocks
Let's separate four different parts of pam_sm_open_session():

1. Acquiring of our various parameters from pam env, pam data, pam items
2. Mangling of that data to clean it up
3. Registering of the service with logind
4. Importing shell credentials into environment variables
5. Enforcement of user record data

This makes the code a lot more readable, and gets rid of an ugly got
label.

It also corrects things: if step 3 doesnt work because logind is not
around, we'll now still do step 4, which we previously erroneously
skipped.

Besodes that no real code changes.
2024-11-15 15:10:56 +01:00
Lennart Poettering ae40305e65 pam_systemd: split out setting of shell env vars from credentials and move it later
Let's shorten the code of pam_sm_open_session() a bit, and also make
sure the importing of the env vars from the creds also happens if the
session registration with logind is skipped.
2024-11-15 15:10:53 +01:00
Lennart Poettering ceb5d4cc73 pam_systemd: drop "uid" field from SessionContext
Let's instead just pass over the UserRecord, it's a much more useful
object with lots more information we'll sooner or later need
(preparation for later commits).
2024-11-15 15:10:51 +01:00
Lennart Poettering 68b0318194 pam_systemd: drop "pid" field from SessionContext
We never use the field and this is not going to change...

This recomes a weird asymmetry, as create_session_message() always went
to the process' own PID when ding pidfds but otherwise took the pid as
input.
2024-11-15 15:10:48 +01:00
Lennart Poettering 51160b6bca pam-systemd: normalize parsing of XDG_VTNR
Let's make it more like the parsing of the "incomplete" boolean env var,
to streamline things.
2024-11-15 15:10:46 +01:00
36 changed files with 532 additions and 384 deletions

View File

@ -1438,6 +1438,11 @@ evdev:input:b0003v046DpC309*
KEYBOARD_KEY_c01b6=images # My Pictures (F11) KEYBOARD_KEY_c01b6=images # My Pictures (F11)
KEYBOARD_KEY_c01b7=audio # My Music (F12) KEYBOARD_KEY_c01b7=audio # My Music (F12)
# Logitech MX Keys for Mac
evdev:input:b0003v046Dp4092*
KEYBOARD_KEY_70035=102nd # '<' key
KEYBOARD_KEY_70064=grave # '^' key
########################################################### ###########################################################
# Maxdata # Maxdata
########################################################### ###########################################################

View File

@ -953,6 +953,15 @@ sensor:modalias:acpi:MXC6655*:dmi:*:svnDefaultstring*:pnP612F:*
sensor:modalias:acpi:SMO8500*:dmi:*:svnPEAQ:pnPEAQPMMC1010MD99187:* sensor:modalias:acpi:SMO8500*:dmi:*:svnPEAQ:pnPEAQPMMC1010MD99187:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
# Pine64
#########################################
# PineTab2
sensor:modalias:of:NaccelerometerT_null_Csilan,sc7a20:*
ACCEL_MOUNT_MATRIX=0, 0, -1; 1, 0, 0; 0, -1, 0
######################################### #########################################
# Pipo # Pipo
######################################### #########################################

View File

@ -143,6 +143,10 @@
<entry><constant>manager-early</constant></entry> <entry><constant>manager-early</constant></entry>
<entry>Similar to <constant>manager</constant>, but for the root user. Compare with the <constant>user</constant> vs. <constant>user-early</constant> situation. (Added in v256.)</entry> <entry>Similar to <constant>manager</constant>, but for the root user. Compare with the <constant>user</constant> vs. <constant>user-early</constant> situation. (Added in v256.)</entry>
</row> </row>
<row>
<entry><constant>none</constant></entry>
<entry>Skips registering this session with logind. No session scope will be created, and the user service manager will not be started. (Added in v258.)</entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>

View File

@ -265,32 +265,11 @@
</refsect1> </refsect1>
<refsect1> <refsect1>
<title>Options</title> <title>Unlocking</title>
<para>The following options are understood:</para> <para>The following options are understood that may be used to unlock the device in preparation of the enrollment operations:</para>
<variablelist> <variablelist>
<varlistentry>
<term><option>--password</option></term>
<listitem><para>Enroll a regular password/passphrase. This command is mostly equivalent to
<command>cryptsetup luksAddKey</command>, however may be combined with
<option>--wipe-slot=</option> in one call, see below.</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--recovery-key</option></term>
<listitem><para>Enroll a recovery key. Recovery keys are mostly identical to passphrases, but are
computer-generated instead of being chosen by a human, and thus have a guaranteed high entropy. The
key uses a character set that is easy to type in, and may be scanned off screen via a QR code.
</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--unlock-key-file=<replaceable>PATH</replaceable></option></term> <term><option>--unlock-key-file=<replaceable>PATH</replaceable></option></term>
@ -328,7 +307,45 @@
<xi:include href="version-info.xml" xpointer="v256"/></listitem> <xi:include href="version-info.xml" xpointer="v256"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Simple Enrollment</title>
<para>The following options are understood that may be used to enroll simple user input based
unlocking:</para>
<variablelist>
<varlistentry>
<term><option>--password</option></term>
<listitem><para>Enroll a regular password/passphrase. This command is mostly equivalent to
<command>cryptsetup luksAddKey</command>, however may be combined with
<option>--wipe-slot=</option> in one call, see below.</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--recovery-key</option></term>
<listitem><para>Enroll a recovery key. Recovery keys are mostly identical to passphrases, but are
computer-generated instead of being chosen by a human, and thus have a guaranteed high entropy. The
key uses a character set that is easy to type in, and may be scanned off screen via a QR code.
</para>
<xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>PKCS#11 Enrollment</title>
<para>The following option is understood that may be used to enroll PKCS#11 tokens:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--pkcs11-token-uri=<replaceable>URI</replaceable></option></term> <term><option>--pkcs11-token-uri=<replaceable>URI</replaceable></option></term>
@ -361,7 +378,15 @@
<xi:include href="version-info.xml" xpointer="v248"/></listitem> <xi:include href="version-info.xml" xpointer="v248"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>FIDO2 Enrollment</title>
<para>The following options are understood that may be used to enroll PKCS#11 tokens:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--fido2-credential-algorithm=<replaceable>STRING</replaceable></option></term> <term><option>--fido2-credential-algorithm=<replaceable>STRING</replaceable></option></term>
<listitem><para>Specify COSE algorithm used in credential generation. The default value is <listitem><para>Specify COSE algorithm used in credential generation. The default value is
@ -461,7 +486,15 @@
<xi:include href="version-info.xml" xpointer="v249"/></listitem> <xi:include href="version-info.xml" xpointer="v249"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>TPM2 Enrollment</title>
<para>The following options are understood that may be used to enroll TPM2 devices:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--tpm2-device=<replaceable>PATH</replaceable></option></term> <term><option>--tpm2-device=<replaceable>PATH</replaceable></option></term>
@ -636,7 +669,15 @@
<xi:include href="version-info.xml" xpointer="v255"/></listitem> <xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry> </varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Other Options</title>
<para>The following additional options are understood:</para>
<variablelist>
<varlistentry> <varlistentry>
<term><option>--wipe-slot=<replaceable>SLOT<optional>,SLOT...</optional></replaceable></option></term> <term><option>--wipe-slot=<replaceable>SLOT<optional>,SLOT...</optional></replaceable></option></term>

View File

@ -9,8 +9,8 @@ msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-11-20 19:13+0000\n" "PO-Revision-Date: 2024-11-21 19:38+0000\n"
"Last-Translator: Dmytro Markevych <hotr1pak@gmail.com>\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/" "Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/"
"systemd/main/uk/>\n" "systemd/main/uk/>\n"
"Language: uk\n" "Language: uk\n"
@ -120,11 +120,11 @@ msgstr "Для оновлення домашньої теки користува
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
msgid "Update your home area" msgid "Update your home area"
msgstr "Оновіть свій домашній простір" msgstr "Оновлення домашньої області"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "Для оновлення домашньої області потрібна автентифікація." msgstr "Для оновлення домашньої області слід пройти розпізнавання."
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1215,7 +1215,7 @@ msgstr "Керування додатковими функціями"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "Для керування додатковими функціями потрібна автентифікація" msgstr "Для керування додатковими можливостями слід пройти розпізнавання"
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -38,19 +38,12 @@ __get_tpm2_devices() {
done done
} }
__get_block_devices() {
local i
for i in /dev/*; do
[ -b "$i" ] && printf '%s\n' "$i"
done
}
_systemd_cryptenroll() { _systemd_cryptenroll() {
local comps local comps
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
local -A OPTS=( local -A OPTS=(
[STANDALONE]='-h --help --version [STANDALONE]='-h --help --version
--password --recovery-key' --password --recovery-key --list-devices'
[ARG]='--unlock-key-file [ARG]='--unlock-key-file
--unlock-fido2-device --unlock-fido2-device
--unlock-tpm2-device --unlock-tpm2-device
@ -116,7 +109,7 @@ _systemd_cryptenroll() {
return 0 return 0
fi fi
comps=$(__get_block_devices) comps=$(systemd-cryptenroll --list-devices)
COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0 return 0
} }

View File

@ -3426,14 +3426,12 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
return 0; return 0;
} }
r = service_add_fd_store(s, fd, fdn, do_poll); r = service_add_fd_store(s, TAKE_FD(fd), fdn, do_poll);
if (r < 0) { if (r < 0) {
log_unit_debug_errno(u, r, log_unit_debug_errno(u, r,
"Failed to store deserialized fd '%s', ignoring: %m", fdn); "Failed to store deserialized fd '%s', ignoring: %m", fdn);
return 0; return 0;
} }
TAKE_FD(fd);
} else if (streq(key, "extra-fd")) { } else if (streq(key, "extra-fd")) {
_cleanup_free_ char *fdv = NULL, *fdn = NULL; _cleanup_free_ char *fdv = NULL, *fdn = NULL;
_cleanup_close_ int fd = -EBADF; _cleanup_close_ int fd = -EBADF;

View File

@ -193,7 +193,7 @@ static int help(void) {
"\n%3$sSimple Enrollment:%4$s\n" "\n%3$sSimple Enrollment:%4$s\n"
" --password Enroll a user-supplied password\n" " --password Enroll a user-supplied password\n"
" --recovery-key Enroll a recovery key\n" " --recovery-key Enroll a recovery key\n"
"\n%3$sPKCS11 Enrollment:%4$s\n" "\n%3$sPKCS#11 Enrollment:%4$s\n"
" --pkcs11-token-uri=URI\n" " --pkcs11-token-uri=URI\n"
" Specify PKCS#11 security token URI\n" " Specify PKCS#11 security token URI\n"
"\n%3$sFIDO2 Enrollment:%4$s\n" "\n%3$sFIDO2 Enrollment:%4$s\n"

View File

@ -16,7 +16,7 @@ int varlink_get_peer_pidref(sd_varlink *v, PidRef *ret) {
int pidfd = sd_varlink_get_peer_pidfd(v); int pidfd = sd_varlink_get_peer_pidfd(v);
if (pidfd < 0) { if (pidfd < 0) {
if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd)) if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd) && pidfd != -EINVAL)
return pidfd; return pidfd;
pid_t pid; pid_t pid;

View File

@ -863,6 +863,27 @@ static int create_session(
if (!uid_is_valid(uid)) if (!uid_is_valid(uid))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID"); return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
if (isempty(type))
t = _SESSION_TYPE_INVALID;
else {
t = session_type_from_string(type);
if (t < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid session type %s", type);
}
if (isempty(class))
c = _SESSION_CLASS_INVALID;
else {
c = session_class_from_string(class);
if (c < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid session class %s", class);
if (c == SESSION_NONE)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Refusing session class %s", class);
}
if (flags != 0) if (flags != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags must be zero."); return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags must be zero.");
@ -882,24 +903,6 @@ static int create_session(
if (leader.pid == 1 || leader.pid == getpid_cached()) if (leader.pid == 1 || leader.pid == getpid_cached())
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID"); return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
if (isempty(type))
t = _SESSION_TYPE_INVALID;
else {
t = session_type_from_string(type);
if (t < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid session type %s", type);
}
if (isempty(class))
c = _SESSION_CLASS_INVALID;
else {
c = session_class_from_string(class);
if (c < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid session class %s", class);
}
if (isempty(desktop)) if (isempty(desktop))
desktop = NULL; desktop = NULL;
else { else {

View File

@ -29,6 +29,7 @@ typedef enum SessionClass {
SESSION_BACKGROUND_LIGHT, /* Like SESSION_BACKGROUND, but without the service manager */ SESSION_BACKGROUND_LIGHT, /* Like SESSION_BACKGROUND, but without the service manager */
SESSION_MANAGER, /* The service manager */ SESSION_MANAGER, /* The service manager */
SESSION_MANAGER_EARLY, /* The service manager for root (which is allowed to run before systemd-user-sessions.service) */ SESSION_MANAGER_EARLY, /* The service manager for root (which is allowed to run before systemd-user-sessions.service) */
SESSION_NONE, /* A session not registered with logind */
_SESSION_CLASS_MAX, _SESSION_CLASS_MAX,
_SESSION_CLASS_INVALID = -EINVAL, _SESSION_CLASS_INVALID = -EINVAL,
} SessionClass; } SessionClass;
@ -44,7 +45,7 @@ typedef enum SessionClass {
#define SESSION_CLASS_WANTS_SERVICE_MANAGER(class) IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER, SESSION_LOCK_SCREEN, SESSION_BACKGROUND) #define SESSION_CLASS_WANTS_SERVICE_MANAGER(class) IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER, SESSION_LOCK_SCREEN, SESSION_BACKGROUND)
/* Which session classes can pin our user tracking? */ /* Which session classes can pin our user tracking? */
#define SESSION_CLASS_PIN_USER(class) (!IN_SET((class), SESSION_MANAGER, SESSION_MANAGER_EARLY)) #define SESSION_CLASS_PIN_USER(class) (!IN_SET((class), SESSION_MANAGER, SESSION_MANAGER_EARLY, SESSION_NONE))
/* Which session classes decide whether system is idle? (should only cover sessions that have input, and are not idle screens themselves)*/ /* Which session classes decide whether system is idle? (should only cover sessions that have input, and are not idle screens themselves)*/
#define SESSION_CLASS_CAN_IDLE(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER)) #define SESSION_CLASS_CAN_IDLE(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER))

View File

@ -390,116 +390,108 @@ static int export_legacy_dbus_address(
} }
static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) { static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
uint64_t val;
int r; int r;
assert(handle);
assert(m);
if (isempty(limit)) if (isempty(limit))
return PAM_SUCCESS; return 0;
if (streq(limit, "infinity")) { if (streq(limit, "infinity"))
r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", UINT64_MAX); return sd_bus_message_append(m, "(sv)", "MemoryMax", "t", UINT64_MAX);
if (r < 0)
return pam_bus_log_create_error(handle, r);
return PAM_SUCCESS;
}
r = parse_permyriad(limit); r = parse_permyriad(limit);
if (r >= 0) { if (r < 0) {
r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", UINT32_SCALE_FROM_PERMYRIAD(r)); uint64_t val;
if (r < 0)
return pam_bus_log_create_error(handle, r);
return PAM_SUCCESS;
}
r = parse_size(limit, 1024, &val); r = parse_size(limit, 1024, &val);
if (r >= 0) { if (r < 0) {
r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
return PAM_SUCCESS;
}
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.memory_max, ignoring: %s", limit); pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.memory_max, ignoring: %s", limit);
return PAM_SUCCESS; return PAM_SUCCESS;
}
return sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val);
}
return sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", UINT32_SCALE_FROM_PERMYRIAD(r));
} }
static int append_session_runtime_max_sec(pam_handle_t *handle, sd_bus_message *m, const char *limit) { static int append_session_runtime_max_sec(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
usec_t val;
int r; int r;
assert(handle);
assert(m);
/* No need to parse "infinity" here, it will be set by default later in scope_init() */ /* No need to parse "infinity" here, it will be set by default later in scope_init() */
if (isempty(limit) || streq(limit, "infinity")) if (isempty(limit) || streq(limit, "infinity"))
return PAM_SUCCESS; return 0;
usec_t val;
r = parse_sec(limit, &val); r = parse_sec(limit, &val);
if (r >= 0) { if (r < 0) {
r = sd_bus_message_append(m, "(sv)", "RuntimeMaxUSec", "t", (uint64_t) val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
} else
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.runtime_max_sec: %s, ignoring.", limit); pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.runtime_max_sec: %s, ignoring.", limit);
return 0;
}
return PAM_SUCCESS; return sd_bus_message_append(m, "(sv)", "RuntimeMaxUSec", "t", (uint64_t) val);
} }
static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) { static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
uint64_t val;
int r; int r;
assert(handle);
assert(m);
/* No need to parse "infinity" here, it will be set unconditionally later in manager_start_scope() */ /* No need to parse "infinity" here, it will be set unconditionally later in manager_start_scope() */
if (isempty(limit) || streq(limit, "infinity")) if (isempty(limit) || streq(limit, "infinity"))
return PAM_SUCCESS; return 0;
uint64_t val;
r = safe_atou64(limit, &val); r = safe_atou64(limit, &val);
if (r >= 0) { if (r < 0) {
r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
} else
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.tasks_max, ignoring: %s", limit); pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.tasks_max, ignoring: %s", limit);
return 0;
}
return PAM_SUCCESS; return sd_bus_message_append(m, "(sv)", "TasksMax", "t", val);
} }
static int append_session_cpu_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) { static int append_session_cpu_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
uint64_t val;
int r; int r;
if (isempty(limit)) assert(handle);
return PAM_SUCCESS; assert(m);
if (isempty(limit))
return 0;
uint64_t val;
r = cg_cpu_weight_parse(limit, &val); r = cg_cpu_weight_parse(limit, &val);
if (r < 0) if (r < 0) {
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight, ignoring: %s", limit); pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight, ignoring: %s", limit);
else { return 0;
r = sd_bus_message_append(m, "(sv)", "CPUWeight", "t", val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
} }
return PAM_SUCCESS; return sd_bus_message_append(m, "(sv)", "CPUWeight", "t", val);
} }
static int append_session_io_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) { static int append_session_io_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
uint64_t val;
int r; int r;
if (isempty(limit)) assert(handle);
return PAM_SUCCESS; assert(m);
if (isempty(limit))
return 0;
uint64_t val;
r = cg_weight_parse(limit, &val); r = cg_weight_parse(limit, &val);
if (r < 0) if (r < 0) {
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight, ignoring: %s", limit); pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight, ignoring: %s", limit);
else { return 0;
r = sd_bus_message_append(m, "(sv)", "IOWeight", "t", val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
} }
return PAM_SUCCESS; return sd_bus_message_append(m, "(sv)", "IOWeight", "t", val);
} }
static const char* getenv_harder(pam_handle_t *handle, const char *key, const char *fallback) { static const char* getenv_harder(pam_handle_t *handle, const char *key, const char *fallback) {
@ -549,6 +541,26 @@ static bool getenv_harder_bool(pam_handle_t *handle, const char *key, bool fallb
return r; return r;
} }
static uint32_t getenv_harder_uint32(pam_handle_t *handle, const char *key, uint32_t fallback) {
int r;
assert(handle);
assert(key);
const char *v = getenv_harder(handle, key, NULL);
if (isempty(v))
return fallback;
uint32_t u;
r = safe_atou32(v, &u);
if (r < 0) {
pam_syslog(handle, LOG_ERR, "Unsigned integer environment variable value of '%s' is not valid: %s", key, v);
return fallback;
}
return u;
}
static int update_environment(pam_handle_t *handle, const char *key, const char *value) { static int update_environment(pam_handle_t *handle, const char *key, const char *value) {
int r; int r;
@ -826,17 +838,15 @@ static uint64_t pick_default_capability_ambient_set(
} }
typedef struct SessionContext { typedef struct SessionContext {
const uid_t uid;
const pid_t pid;
const char *service; const char *service;
const char *type; const char *type;
const char *class; const char *class;
const char *desktop; const char *desktop;
const char *seat; const char *seat;
const uint32_t vtnr; uint32_t vtnr;
const char *tty; const char *tty;
const char *display; const char *display;
const bool remote; bool remote;
const char *remote_user; const char *remote_user;
const char *remote_host; const char *remote_host;
const char *memory_max; const char *memory_max;
@ -844,11 +854,13 @@ typedef struct SessionContext {
const char *cpu_weight; const char *cpu_weight;
const char *io_weight; const char *io_weight;
const char *runtime_max_sec; const char *runtime_max_sec;
bool incomplete;
} SessionContext; } SessionContext;
static int create_session_message( static int create_session_message(
sd_bus *bus, sd_bus *bus,
pam_handle_t *handle, pam_handle_t *handle,
UserRecord *ur,
const SessionContext *context, const SessionContext *context,
bool avoid_pidfd, bool avoid_pidfd,
sd_bus_message **ret) { sd_bus_message **ret) {
@ -859,6 +871,7 @@ static int create_session_message(
assert(bus); assert(bus);
assert(handle); assert(handle);
assert(ur);
assert(context); assert(context);
assert(ret); assert(ret);
@ -872,10 +885,11 @@ static int create_session_message(
if (r < 0) if (r < 0)
return r; return r;
r = sd_bus_message_append(m, r = sd_bus_message_append(
m,
pidfd >= 0 ? "uhsssssussbss" : "uusssssussbss", pidfd >= 0 ? "uhsssssussbss" : "uusssssussbss",
(uint32_t) context->uid, (uint32_t) ur->uid,
pidfd >= 0 ? pidfd : context->pid, pidfd >= 0 ? pidfd : 0,
context->service, context->service,
context->type, context->type,
context->class, context->class,
@ -901,23 +915,23 @@ static int create_session_message(
return r; return r;
r = append_session_memory_max(handle, m, context->memory_max); r = append_session_memory_max(handle, m, context->memory_max);
if (r != PAM_SUCCESS) if (r < 0)
return r; return r;
r = append_session_runtime_max_sec(handle, m, context->runtime_max_sec); r = append_session_runtime_max_sec(handle, m, context->runtime_max_sec);
if (r != PAM_SUCCESS) if (r < 0)
return r; return r;
r = append_session_tasks_max(handle, m, context->tasks_max); r = append_session_tasks_max(handle, m, context->tasks_max);
if (r != PAM_SUCCESS) if (r < 0)
return r; return r;
r = append_session_cpu_weight(handle, m, context->cpu_weight); r = append_session_cpu_weight(handle, m, context->cpu_weight);
if (r != PAM_SUCCESS) if (r < 0)
return r; return r;
r = append_session_io_weight(handle, m, context->io_weight); r = append_session_io_weight(handle, m, context->io_weight);
if (r != PAM_SUCCESS) if (r < 0)
return r; return r;
r = sd_bus_message_close_container(m); r = sd_bus_message_close_container(m);
@ -928,10 +942,93 @@ static int create_session_message(
return 0; return 0;
} }
_public_ PAM_EXTERN int pam_sm_open_session( static void session_context_mangle(
pam_handle_t *handle, pam_handle_t *handle,
int flags, SessionContext *c,
int argc, const char **argv) { UserRecord *ur,
bool debug) {
assert(handle);
assert(c);
assert(ur);
if (streq_ptr(c->service, "systemd-user")) {
/* If we detect that we are running in the "systemd-user" PAM stack, then let's patch the class to
* 'manager' if not set, simply for robustness reasons. */
c->type = "unspecified";
c->class = IN_SET(user_record_disposition(ur), USER_INTRINSIC, USER_SYSTEM, USER_DYNAMIC) ?
"manager-early" : "manager";
c->tty = NULL;
} else if (c->tty && strchr(c->tty, ':')) {
/* A tty with a colon is usually an X11 display, placed there to show up in utmp. We rearrange things
* and don't pretend that an X display was a tty. */
if (isempty(c->display))
c->display = c->tty;
c->tty = NULL;
} else if (streq_ptr(c->tty, "cron")) {
/* cron is setting PAM_TTY to "cron" for some reason (the commit carries no information why, but
* probably because it wants to set it to something as pam_time/pam_access/ require PAM_TTY to be set
* (as they otherwise even try to update it!) but cron doesn't actually allocate a TTY for its forked
* off processes.) */
c->type = "unspecified";
c->class = "background";
c->tty = NULL;
} else if (streq_ptr(c->tty, "ssh")) {
/* ssh has been setting PAM_TTY to "ssh" (for the same reason as cron does this, see above. For further
* details look for "PAM_TTY_KLUDGE" in the openssh sources). */
c->type = "tty";
c->class = "user";
c->tty = NULL; /* This one is particularly sad, as this means that ssh sessions — even though
* usually associated with a pty won't be tracked by their tty in
* logind. This is because ssh does the PAM session registration early for new
* connections, and registers a pty only much later (this is because it doesn't
* know yet if it needs one at all, as whether to register a pty or not is
* negotiated much later in the protocol). */
} else if (c->tty)
/* Chop off leading /dev prefix that some clients specify, but others do not. */
c->tty = skip_dev_prefix(c->tty);
if (!isempty(c->display) && !c->vtnr) {
if (isempty(c->seat))
(void) get_seat_from_display(c->display, &c->seat, &c->vtnr);
else if (streq(c->seat, "seat0"))
(void) get_seat_from_display(c->display, /* seat= */ NULL, &c->vtnr);
}
if (c->seat && !streq(c->seat, "seat0") && c->vtnr != 0) {
pam_debug_syslog(handle, debug, "Ignoring vtnr %"PRIu32" for %s which is not seat0", c->vtnr, c->seat);
c->vtnr = 0;
}
if (isempty(c->type))
c->type = !isempty(c->display) ? "x11" :
!isempty(c->tty) ? "tty" : "unspecified";
if (isempty(c->class))
c->class = streq(c->type, "unspecified") ? "background" :
((IN_SET(user_record_disposition(ur), USER_INTRINSIC, USER_SYSTEM, USER_DYNAMIC) &&
streq(c->type, "tty")) ? "user-early" : "user");
if (c->incomplete) {
if (streq(c->class, "user"))
c->class = "user-incomplete";
else
pam_syslog_pam_error(handle, LOG_WARNING, 0, "PAM session of class '%s' is incomplete, which is not supported, ignoring.", c->class);
}
c->remote = !isempty(c->remote_host) && !is_localhost(c->remote_host);
}
static int register_session(
pam_handle_t *handle,
SessionContext *c,
UserRecord *ur,
bool debug,
char **ret_seat) {
/* Let's release the D-Bus connection once this function exits, after all the session might live /* Let's release the D-Bus connection once this function exits, after all the session might live
* quite a long time, and we are not going to process the bus connection in that time, so let's * quite a long time, and we are not going to process the bus connection in that time, so let's
@ -939,152 +1036,21 @@ _public_ PAM_EXTERN int pam_sm_open_session(
_cleanup_(pam_bus_data_disconnectp) PamBusData *d = NULL; _cleanup_(pam_bus_data_disconnectp) PamBusData *d = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
const char
*id, *object_path, *runtime_path,
*service = NULL,
*tty = NULL, *display = NULL,
*remote_user = NULL, *remote_host = NULL,
*seat = NULL,
*type = NULL, *class = NULL,
*class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL, *desktop_pam = NULL,
*memory_max = NULL, *tasks_max = NULL, *cpu_weight = NULL, *io_weight = NULL, *runtime_max_sec = NULL;
uint64_t default_capability_bounding_set = UINT64_MAX, default_capability_ambient_set = UINT64_MAX;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(user_record_unrefp) UserRecord *ur = NULL; int r;
int session_fd = -EBADF, existing, r;
bool debug = false, remote, incomplete;
uint32_t vtnr = 0;
uid_t original_uid;
assert(handle); assert(handle);
assert(c);
pam_log_setup(); assert(ur);
assert(ret_seat);
if (parse_argv(handle,
argc, argv,
&class_pam,
&type_pam,
&desktop_pam,
&debug,
&default_capability_bounding_set,
&default_capability_ambient_set) < 0)
return PAM_SESSION_ERR;
pam_debug_syslog(handle, debug, "pam-systemd initializing");
r = acquire_user_record(handle, &ur);
if (r != PAM_SUCCESS)
return r;
/* Make most of this a NOP on non-logind systems */ /* Make most of this a NOP on non-logind systems */
if (!logind_running()) if (!logind_running())
goto success; goto skip;
r = pam_get_item_many( /* We don't register session class none with logind */
handle, if (streq(c->class, "none"))
PAM_SERVICE, &service, goto skip;
PAM_XDISPLAY, &display,
PAM_TTY, &tty,
PAM_RUSER, &remote_user,
PAM_RHOST, &remote_host);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM items: @PAMERR@");
seat = getenv_harder(handle, "XDG_SEAT", NULL);
cvtnr = getenv_harder(handle, "XDG_VTNR", NULL);
type = getenv_harder(handle, "XDG_SESSION_TYPE", type_pam);
class = getenv_harder(handle, "XDG_SESSION_CLASS", class_pam);
desktop = getenv_harder(handle, "XDG_SESSION_DESKTOP", desktop_pam);
incomplete = getenv_harder_bool(handle, "XDG_SESSION_INCOMPLETE", false);
if (streq_ptr(service, "systemd-user")) {
/* If we detect that we are running in the "systemd-user" PAM stack, then let's patch the class to
* 'manager' if not set, simply for robustness reasons. */
type = "unspecified";
class = IN_SET(user_record_disposition(ur), USER_INTRINSIC, USER_SYSTEM, USER_DYNAMIC) ?
"manager-early" : "manager";
tty = NULL;
} else if (tty && strchr(tty, ':')) {
/* A tty with a colon is usually an X11 display, placed there to show up in utmp. We rearrange things
* and don't pretend that an X display was a tty. */
if (isempty(display))
display = tty;
tty = NULL;
} else if (streq_ptr(tty, "cron")) {
/* cron is setting PAM_TTY to "cron" for some reason (the commit carries no information why, but
* probably because it wants to set it to something as pam_time/pam_access/ require PAM_TTY to be set
* (as they otherwise even try to update it!) but cron doesn't actually allocate a TTY for its forked
* off processes.) */
type = "unspecified";
class = "background";
tty = NULL;
} else if (streq_ptr(tty, "ssh")) {
/* ssh has been setting PAM_TTY to "ssh" (for the same reason as cron does this, see above. For further
* details look for "PAM_TTY_KLUDGE" in the openssh sources). */
type = "tty";
class = "user";
tty = NULL; /* This one is particularly sad, as this means that ssh sessions — even though usually
* associated with a pty won't be tracked by their tty in logind. This is because ssh
* does the PAM session registration early for new connections, and registers a pty only
* much later (this is because it doesn't know yet if it needs one at all, as whether to
* register a pty or not is negotiated much later in the protocol). */
} else if (tty)
/* Chop off leading /dev prefix that some clients specify, but others do not. */
tty = skip_dev_prefix(tty);
/* If this fails vtnr will be 0, that's intended */
if (!isempty(cvtnr))
(void) safe_atou32(cvtnr, &vtnr);
if (!isempty(display) && !vtnr) {
if (isempty(seat))
(void) get_seat_from_display(display, &seat, &vtnr);
else if (streq(seat, "seat0"))
(void) get_seat_from_display(display, NULL, &vtnr);
}
if (seat && !streq(seat, "seat0") && vtnr != 0) {
pam_debug_syslog(handle, debug, "Ignoring vtnr %"PRIu32" for %s which is not seat0", vtnr, seat);
vtnr = 0;
}
if (isempty(type))
type = !isempty(display) ? "x11" :
!isempty(tty) ? "tty" : "unspecified";
if (isempty(class))
class = streq(type, "unspecified") ? "background" :
((IN_SET(user_record_disposition(ur), USER_INTRINSIC, USER_SYSTEM, USER_DYNAMIC) &&
streq(type, "tty")) ? "user-early" : "user");
if (incomplete) {
if (streq(class, "user"))
class = "user-incomplete";
else
pam_syslog_pam_error(handle, LOG_WARNING, 0, "PAM session of class '%s' is incomplete, which is not supported, ignoring.", class);
}
remote = !isempty(remote_host) && !is_localhost(remote_host);
r = pam_get_data(handle, "systemd.memory_max", (const void **)&memory_max);
if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA))
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM systemd.memory_max data: @PAMERR@");
r = pam_get_data(handle, "systemd.tasks_max", (const void **)&tasks_max);
if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA))
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM systemd.tasks_max data: @PAMERR@");
r = pam_get_data(handle, "systemd.cpu_weight", (const void **)&cpu_weight);
if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA))
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM systemd.cpu_weight data: @PAMERR@");
r = pam_get_data(handle, "systemd.io_weight", (const void **)&io_weight);
if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA))
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM systemd.io_weight data: @PAMERR@");
r = pam_get_data(handle, "systemd.runtime_max_sec", (const void **)&runtime_max_sec);
if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA))
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM systemd.runtime_max_sec data: @PAMERR@");
/* Talk to logind over the message bus */ /* Talk to logind over the message bus */
r = pam_acquire_bus_connection(handle, "pam-systemd", debug, &bus, &d); r = pam_acquire_bus_connection(handle, "pam-systemd", debug, &bus, &d);
@ -1095,39 +1061,20 @@ _public_ PAM_EXTERN int pam_sm_open_session(
"Asking logind to create session: " "Asking logind to create session: "
"uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s", "uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s",
ur->uid, getpid_cached(), ur->uid, getpid_cached(),
strempty(service), strempty(c->service),
type, class, strempty(desktop), c->type, c->class, strempty(c->desktop),
strempty(seat), vtnr, strempty(tty), strempty(display), strempty(c->seat), c->vtnr, strempty(c->tty), strempty(c->display),
yes_no(remote), strempty(remote_user), strempty(remote_host)); yes_no(c->remote), strempty(c->remote_user), strempty(c->remote_host));
pam_debug_syslog(handle, debug, pam_debug_syslog(handle, debug,
"Session limits: " "Session limits: "
"memory_max=%s tasks_max=%s cpu_weight=%s io_weight=%s runtime_max_sec=%s", "memory_max=%s tasks_max=%s cpu_weight=%s io_weight=%s runtime_max_sec=%s",
strna(memory_max), strna(tasks_max), strna(cpu_weight), strna(io_weight), strna(runtime_max_sec)); strna(c->memory_max), strna(c->tasks_max), strna(c->cpu_weight), strna(c->io_weight), strna(c->runtime_max_sec));
const SessionContext context = { r = create_session_message(
.uid = ur->uid, bus,
.pid = 0,
.service = service,
.type = type,
.class = class,
.desktop = desktop,
.seat = seat,
.vtnr = vtnr,
.tty = tty,
.display = display,
.remote = remote,
.remote_user = remote_user,
.remote_host = remote_host,
.memory_max = memory_max,
.tasks_max = tasks_max,
.cpu_weight = cpu_weight,
.io_weight = io_weight,
.runtime_max_sec = runtime_max_sec,
};
r = create_session_message(bus,
handle, handle,
&context, ur,
c,
/* avoid_pidfd = */ false, /* avoid_pidfd = */ false,
&m); &m);
if (r < 0) if (r < 0)
@ -1142,7 +1089,8 @@ _public_ PAM_EXTERN int pam_sm_open_session(
m = sd_bus_message_unref(m); m = sd_bus_message_unref(m);
r = create_session_message(bus, r = create_session_message(bus,
handle, handle,
&context, ur,
c,
/* avoid_pidfd = */ true, /* avoid_pidfd = */ true,
&m); &m);
if (r < 0) if (r < 0)
@ -1155,7 +1103,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
/* We are already in a session, don't do anything */ /* We are already in a session, don't do anything */
pam_debug_syslog(handle, debug, pam_debug_syslog(handle, debug,
"Not creating session: %s", bus_error_message(&error, r)); "Not creating session: %s", bus_error_message(&error, r));
goto success; goto skip;
} }
pam_syslog(handle, LOG_ERR, pam_syslog(handle, LOG_ERR,
@ -1163,15 +1111,19 @@ _public_ PAM_EXTERN int pam_sm_open_session(
return PAM_SESSION_ERR; return PAM_SESSION_ERR;
} }
r = sd_bus_message_read(reply, const char *id, *object_path, *runtime_path, *real_seat;
int session_fd = -EBADF, existing;
uint32_t original_uid, real_vtnr;
r = sd_bus_message_read(
reply,
"soshusub", "soshusub",
&id, &id,
&object_path, &object_path,
&runtime_path, &runtime_path,
&session_fd, &session_fd,
&original_uid, &original_uid,
&seat, &real_seat,
&vtnr, &real_vtnr,
&existing); &existing);
if (r < 0) if (r < 0)
return pam_bus_log_parse_error(handle, r); return pam_bus_log_parse_error(handle, r);
@ -1179,7 +1131,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
pam_debug_syslog(handle, debug, pam_debug_syslog(handle, debug,
"Reply from logind: " "Reply from logind: "
"id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u", "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u",
id, object_path, runtime_path, session_fd, seat, vtnr, original_uid); id, object_path, runtime_path, session_fd, real_seat, real_vtnr, original_uid);
/* Please update manager_default_environment() in core/manager.c accordingly if more session envvars /* Please update manager_default_environment() in core/manager.c accordingly if more session envvars
* shall be added. */ * shall be added. */
@ -1202,38 +1154,25 @@ _public_ PAM_EXTERN int pam_sm_open_session(
* somewhere else (for example PAM module parameters). Let's now update the environment variables, so that this * somewhere else (for example PAM module parameters). Let's now update the environment variables, so that this
* data is inherited into the session processes, and programs can rely on them to be initialized. */ * data is inherited into the session processes, and programs can rely on them to be initialized. */
r = update_environment(handle, "XDG_SESSION_TYPE", type); r = update_environment(handle, "XDG_SESSION_TYPE", c->type);
if (r != PAM_SUCCESS) if (r != PAM_SUCCESS)
return r; return r;
r = update_environment(handle, "XDG_SESSION_CLASS", class); r = update_environment(handle, "XDG_SESSION_CLASS", c->class);
if (r != PAM_SUCCESS) if (r != PAM_SUCCESS)
return r; return r;
r = update_environment(handle, "XDG_SESSION_DESKTOP", desktop); r = update_environment(handle, "XDG_SESSION_DESKTOP", c->desktop);
if (r != PAM_SUCCESS) if (r != PAM_SUCCESS)
return r; return r;
r = update_environment(handle, "XDG_SEAT", seat); r = update_environment(handle, "XDG_SEAT", real_seat);
if (r != PAM_SUCCESS) if (r != PAM_SUCCESS)
return r; return r;
static const char *const propagate[] = { if (real_vtnr > 0) {
"shell.prompt.prefix", "SHELL_PROMPT_PREFIX", char buf[DECIMAL_STR_MAX(real_vtnr)];
"shell.prompt.suffix", "SHELL_PROMPT_SUFFIX", sprintf(buf, "%u", real_vtnr);
"shell.welcome", "SHELL_WELCOME",
NULL
};
STRV_FOREACH_PAIR(k, v, propagate) {
r = propagate_credential_to_environment(handle, *k, *v);
if (r != PAM_SUCCESS)
return r;
}
if (vtnr > 0) {
char buf[DECIMAL_STR_MAX(vtnr)];
sprintf(buf, "%u", vtnr);
r = update_environment(handle, "XDG_VTNR", buf); r = update_environment(handle, "XDG_VTNR", buf);
if (r != PAM_SUCCESS) if (r != PAM_SUCCESS)
@ -1255,9 +1194,115 @@ _public_ PAM_EXTERN int pam_sm_open_session(
TAKE_FD(fd); TAKE_FD(fd);
} }
success: /* Everything worked, hence let's patch in the data we learned. Since 'real_set' points into the
* D-Bus message, let's copy it and return it as a buffer */
char *rs = strdup(real_seat);
if (!rs)
return pam_log_oom(handle);
c->seat = *ret_seat = rs;
c->vtnr = real_vtnr;
return PAM_SUCCESS;
skip:
*ret_seat = NULL;
return PAM_SUCCESS;
}
static int import_shell_credentials(pam_handle_t *handle) {
static const char *const propagate[] = {
"shell.prompt.prefix", "SHELL_PROMPT_PREFIX",
"shell.prompt.suffix", "SHELL_PROMPT_SUFFIX",
"shell.welcome", "SHELL_WELCOME",
NULL
};
int r;
assert(handle);
STRV_FOREACH_PAIR(k, v, propagate) {
r = propagate_credential_to_environment(handle, *k, *v);
if (r != PAM_SUCCESS)
return r;
}
return PAM_SUCCESS;
}
_public_ PAM_EXTERN int pam_sm_open_session(
pam_handle_t *handle,
int flags,
int argc, const char **argv) {
int r;
assert(handle);
pam_log_setup();
uint64_t default_capability_bounding_set = UINT64_MAX, default_capability_ambient_set = UINT64_MAX;
const char *class_pam = NULL, *type_pam = NULL, *desktop_pam = NULL;
bool debug = false;
if (parse_argv(handle,
argc, argv,
&class_pam,
&type_pam,
&desktop_pam,
&debug,
&default_capability_bounding_set,
&default_capability_ambient_set) < 0)
return PAM_SESSION_ERR;
pam_debug_syslog(handle, debug, "pam-systemd initializing");
_cleanup_(user_record_unrefp) UserRecord *ur = NULL;
r = acquire_user_record(handle, &ur);
if (r != PAM_SUCCESS)
return r;
SessionContext c = {};
r = pam_get_item_many(
handle,
PAM_SERVICE, &c.service,
PAM_XDISPLAY, &c.display,
PAM_TTY, &c.tty,
PAM_RUSER, &c.remote_user,
PAM_RHOST, &c.remote_host);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM items: @PAMERR@");
c.seat = getenv_harder(handle, "XDG_SEAT", NULL);
c.vtnr = getenv_harder_uint32(handle, "XDG_VTNR", 0);
c.type = getenv_harder(handle, "XDG_SESSION_TYPE", type_pam);
c.class = getenv_harder(handle, "XDG_SESSION_CLASS", class_pam);
c.desktop = getenv_harder(handle, "XDG_SESSION_DESKTOP", desktop_pam);
c.incomplete = getenv_harder_bool(handle, "XDG_SESSION_INCOMPLETE", false);
r = pam_get_data_many(
handle,
"systemd.memory_max", &c.memory_max,
"systemd.tasks_max", &c.tasks_max,
"systemd.cpu_weight", &c.cpu_weight,
"systemd.io_weight", &c.io_weight,
"systemd.runtime_max_sec", &c.runtime_max_sec);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM data: @PAMERR@");
session_context_mangle(handle, &c, ur, debug);
_cleanup_free_ char *seat_buffer = NULL;
r = register_session(handle, &c, ur, debug, &seat_buffer);
if (r != PAM_SUCCESS)
return r;
r = import_shell_credentials(handle);
if (r != PAM_SUCCESS)
return r;
if (default_capability_ambient_set == UINT64_MAX) if (default_capability_ambient_set == UINT64_MAX)
default_capability_ambient_set = pick_default_capability_ambient_set(ur, service, seat); default_capability_ambient_set = pick_default_capability_ambient_set(ur, c.service, c.seat);
return apply_user_record_settings(handle, ur, debug, default_capability_bounding_set, default_capability_ambient_set); return apply_user_record_settings(handle, ur, debug, default_capability_bounding_set, default_capability_ambient_set);
} }

View File

@ -253,17 +253,17 @@ int pam_get_item_many_internal(pam_handle_t *handle, ...) {
va_list ap; va_list ap;
int r; int r;
assert(handle);
va_start(ap, handle); va_start(ap, handle);
for (;;) { for (;;) {
int item_type = va_arg(ap, int); int item_type = va_arg(ap, int);
if (item_type <= 0) { if (item_type <= 0) {
r = PAM_SUCCESS; r = PAM_SUCCESS;
break; break;
} }
const void **value = ASSERT_PTR(va_arg(ap, const void **)); const void **value = ASSERT_PTR(va_arg(ap, const void **));
r = pam_get_item(handle, item_type, value); r = pam_get_item(handle, item_type, value);
if (!IN_SET(r, PAM_BAD_ITEM, PAM_SUCCESS)) if (!IN_SET(r, PAM_BAD_ITEM, PAM_SUCCESS))
break; break;
@ -273,6 +273,30 @@ int pam_get_item_many_internal(pam_handle_t *handle, ...) {
return r; return r;
} }
int pam_get_data_many_internal(pam_handle_t *handle, ...) {
va_list ap;
int r;
assert(handle);
va_start(ap, handle);
for (;;) {
const char *data_name = va_arg(ap, const char *);
if (!data_name) {
r = PAM_SUCCESS;
break;
}
const void **value = ASSERT_PTR(va_arg(ap, const void **));
r = pam_get_data(handle, data_name, value);
if (!IN_SET(r, PAM_NO_MODULE_DATA, PAM_SUCCESS))
break;
}
va_end(ap);
return r;
}
int pam_prompt_graceful(pam_handle_t *handle, int style, char **ret_response, const char *fmt, ...) { int pam_prompt_graceful(pam_handle_t *handle, int style, char **ret_response, const char *fmt, ...) {
va_list args; va_list args;
int r; int r;

View File

@ -44,7 +44,9 @@ int pam_get_bus_data(pam_handle_t *handle, const char *module_name, PamBusData *
void pam_cleanup_free(pam_handle_t *handle, void *data, int error_status); void pam_cleanup_free(pam_handle_t *handle, void *data, int error_status);
int pam_get_item_many_internal(pam_handle_t *handle, ...); int pam_get_item_many_internal(pam_handle_t *handle, ...);
#define pam_get_item_many(handle, ...) pam_get_item_many_internal(handle, __VA_ARGS__, -1) #define pam_get_item_many(handle, ...) pam_get_item_many_internal(handle, __VA_ARGS__, -1)
int pam_get_data_many_internal(pam_handle_t *handle, ...);
#define pam_get_data_many(handle, ...) pam_get_data_many_internal(handle, __VA_ARGS__, NULL)
int pam_prompt_graceful(pam_handle_t *handle, int style, char **ret_response, const char *fmt, ...) _printf_(4,5); int pam_prompt_graceful(pam_handle_t *handle, int style, char **ret_response, const char *fmt, ...) _printf_(4,5);

View File

@ -392,7 +392,7 @@ int tpm2_make_pcr_json_array(uint32_t pcr_mask, sd_json_variant **ret);
int tpm2_parse_pcr_json_array(sd_json_variant *v, uint32_t *ret); int tpm2_parse_pcr_json_array(sd_json_variant *v, uint32_t *ret);
int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const struct iovec *pubkey, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const struct iovec blobs[], size_t n_blobs, const struct iovec policy_hash[], size_t n_policy_hash, const struct iovec *salt, const struct iovec *srk, const struct iovec *pcrlock_nv, TPM2Flags flags, sd_json_variant **ret); int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const struct iovec *pubkey, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const struct iovec blobs[], size_t n_blobs, const struct iovec policy_hash[], size_t n_policy_hash, const struct iovec *salt, const struct iovec *srk, const struct iovec *pcrlock_nv, TPM2Flags flags, sd_json_variant **ret);
int tpm2_parse_luks2_json(sd_json_variant *v, int *ret_keyslot, uint32_t *ret_hash_pcr_mask, uint16_t *ret_pcr_bank, struct iovec *ret_pubkey, uint32_t *ret_pubkey_pcr_mask, uint16_t *ret_primary_alg, struct iovec **ret_blobs, size_t *ret_n_blobs, struct iovec **ret_policy_hash, size_t *ret_n_policy_hash, struct iovec *ret_salt, struct iovec *ret_srk, struct iovec *pcrlock_nv, TPM2Flags *ret_flags); int tpm2_parse_luks2_json(sd_json_variant *v, int *ret_keyslot, uint32_t *ret_hash_pcr_mask, uint16_t *ret_pcr_bank, struct iovec *ret_pubkey, uint32_t *ret_pubkey_pcr_mask, uint16_t *ret_primary_alg, struct iovec **ret_blobs, size_t *ret_n_blobs, struct iovec **ret_policy_hash, size_t *ret_n_policy_hash, struct iovec *ret_salt, struct iovec *ret_srk, struct iovec *ret_pcrlock_nv, TPM2Flags *ret_flags);
/* Default to PCR 7 only */ /* Default to PCR 7 only */
#define TPM2_PCR_INDEX_DEFAULT UINT32_C(7) #define TPM2_PCR_INDEX_DEFAULT UINT32_C(7)

View File

@ -23,6 +23,7 @@
#include "user-util.h" #include "user-util.h"
#include "userdb.h" #include "userdb.h"
#include "verbs.h" #include "verbs.h"
#include "virt.h"
static enum { static enum {
OUTPUT_CLASSIC, OUTPUT_CLASSIC,
@ -139,10 +140,16 @@ static int show_user(UserRecord *ur, Table *table) {
return 0; return 0;
} }
static bool test_show_mapped(void) {
/* Show mapped user range only in environments where user mapping is a thing. */
return running_in_userns() > 0;
}
static const struct { static const struct {
uid_t first, last; uid_t first, last;
const char *name; const char *name;
UserDisposition disposition; UserDisposition disposition;
bool (*test)(void);
} uid_range_table[] = { } uid_range_table[] = {
{ {
.first = 1, .first = 1,
@ -175,11 +182,12 @@ static const struct {
.last = MAP_UID_MAX, .last = MAP_UID_MAX,
.name = "mapped", .name = "mapped",
.disposition = USER_REGULAR, .disposition = USER_REGULAR,
.test = test_show_mapped,
}, },
}; };
static int table_add_uid_boundaries(Table *table, const UIDRange *p) { static int table_add_uid_boundaries(Table *table, const UIDRange *p) {
int r; int r, n_added = 0;
assert(table); assert(table);
@ -192,6 +200,9 @@ static int table_add_uid_boundaries(Table *table, const UIDRange *p) {
if (!uid_range_covers(p, i->first, i->last - i->first + 1)) if (!uid_range_covers(p, i->first, i->last - i->first + 1))
continue; continue;
if (i->test && !i->test())
continue;
name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN), name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN),
" begin ", i->name, " users ", " begin ", i->name, " users ",
special_glyph(SPECIAL_GLYPH_ARROW_DOWN)); special_glyph(SPECIAL_GLYPH_ARROW_DOWN));
@ -249,9 +260,11 @@ static int table_add_uid_boundaries(Table *table, const UIDRange *p) {
TABLE_INT, 1); /* sort after any other entry with the same UID */ TABLE_INT, 1); /* sort after any other entry with the same UID */
if (r < 0) if (r < 0)
return table_log_add_error(r); return table_log_add_error(r);
n_added += 2;
} }
return ELEMENTSOF(uid_range_table) * 2; return n_added;
} }
static int add_unavailable_uid(Table *table, uid_t start, uid_t end) { static int add_unavailable_uid(Table *table, uid_t start, uid_t end) {
@ -565,16 +578,22 @@ static int show_group(GroupRecord *gr, Table *table) {
} }
static int table_add_gid_boundaries(Table *table, const UIDRange *p) { static int table_add_gid_boundaries(Table *table, const UIDRange *p) {
int r; int r, n_added = 0;
assert(table); assert(table);
FOREACH_ELEMENT(i, uid_range_table) { FOREACH_ELEMENT(i, uid_range_table) {
_cleanup_free_ char *name = NULL, *comment = NULL; _cleanup_free_ char *name = NULL, *comment = NULL;
if (!FLAGS_SET(arg_disposition_mask, UINT64_C(1) << i->disposition))
continue;
if (!uid_range_covers(p, i->first, i->last - i->first + 1)) if (!uid_range_covers(p, i->first, i->last - i->first + 1))
continue; continue;
if (i->test && !i->test())
continue;
name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN), name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN),
" begin ", i->name, " groups ", " begin ", i->name, " groups ",
special_glyph(SPECIAL_GLYPH_ARROW_DOWN)); special_glyph(SPECIAL_GLYPH_ARROW_DOWN));
@ -626,9 +645,11 @@ static int table_add_gid_boundaries(Table *table, const UIDRange *p) {
TABLE_INT, 1); /* sort after any other entry with the same GID */ TABLE_INT, 1); /* sort after any other entry with the same GID */
if (r < 0) if (r < 0)
return table_log_add_error(r); return table_log_add_error(r);
n_added += 2;
} }
return ELEMENTSOF(uid_range_table) * 2; return n_added;
} }
static int add_unavailable_gid(Table *table, uid_t start, uid_t end) { static int add_unavailable_gid(Table *table, uid_t start, uid_t end) {

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
{% if LINK_SHELL_EXTRA_DROPIN %} {% if LINK_SHELL_EXTRA_DROPIN %}
L$ {{SHELLPROFILEDIR}}/70-systemd-shell-extra.sh - - - - {{LIBEXECDIR}}/profile.d/70-systemd-shell-extra.sh L$ {{SHELLPROFILEDIR}}/70-systemd-shell-extra.sh - - - - {{LIBEXECDIR}}/profile.d/70-systemd-shell-extra.sh

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
{% if LINK_SSH_PROXY_DROPIN %} {% if LINK_SSH_PROXY_DROPIN %}
L$ {{SSHCONFDIR}}/20-systemd-ssh-proxy.conf - - - - {{LIBEXECDIR}}/ssh_config.d/20-systemd-ssh-proxy.conf L$ {{SSHCONFDIR}}/20-systemd-ssh-proxy.conf - - - - {{LIBEXECDIR}}/ssh_config.d/20-systemd-ssh-proxy.conf

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
# Copy systemd-stub provided metadata such as PCR signature and public key file # Copy systemd-stub provided metadata such as PCR signature and public key file
# from initrd into /run/, so that it will survive the initrd stage # from initrd into /run/, so that it will survive the initrd stage

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
{% if LINK_SSHD_USERDB_DROPIN %} {% if LINK_SSHD_USERDB_DROPIN %}
L {{SSHDCONFDIR}}/20-systemd-userdb.conf - - - - {{LIBEXECDIR}}/sshd_config.d/20-systemd-userdb.conf L {{SSHDCONFDIR}}/20-systemd-userdb.conf - - - - {{LIBEXECDIR}}/sshd_config.d/20-systemd-userdb.conf

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
d /etc/credstore 0700 root root d /etc/credstore 0700 root root
d /etc/credstore.encrypted 0700 root root d /etc/credstore.encrypted 0700 root root

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
L /etc/os-release - - - - ../usr/lib/os-release L /etc/os-release - - - - ../usr/lib/os-release
L+ /etc/mtab - - - - ../proc/self/mounts L+ /etc/mtab - - - - ../proc/self/mounts

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
Q /home 0755 - - - Q /home 0755 - - -
q /srv 0755 - - - q /srv 0755 - - -

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
# Set the NOCOW attribute for directories of journal files. This flag # Set the NOCOW attribute for directories of journal files. This flag
# is inherited by their new files and sub-directories. Matters only # is inherited by their new files and sub-directories. Matters only

View File

@ -5,26 +5,28 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
# These files are considered legacy and are unnecessary on legacy-free # The functionality provided by these files and directories has been replaced
# systems. # by newer interfaces. Their use is discouraged on legacy-free systems. This
# configuration is provided to maintain backward compatibility.
d /run/lock 0755 root root - d /run/lock 0755 root root -
L /var/lock - - - - ../run/lock L /var/lock - - - - ../run/lock
{% if HAVE_SYSV_COMPAT %}
{% if CREATE_LOG_DIRS %} {% if CREATE_LOG_DIRS %}
L$ /var/log/README - - - - ../..{{DOC_DIR}}/README.logs L$ /var/log/README - - - - ../..{{DOC_DIR}}/README.logs
{% endif %} {% endif %}
# /run/lock/subsys is used for serializing SysV service execution, and # /run/lock/subsys is used for serializing SysV service execution, and
# hence without use on SysV-less systems. # hence without use on SysV-less systems.
d /run/lock/subsys 0755 root root - d /run/lock/subsys 0755 root root -
# /forcefsck, /fastboot and /forcequotacheck are deprecated in favor of the # /forcefsck, /fastboot and /forcequotacheck are deprecated in favor of the
# kernel command line options 'fsck.mode=force', 'fsck.mode=skip' and # kernel command line options 'fsck.mode=force', 'fsck.mode=skip' and
# 'quotacheck.mode=force' # 'quotacheck.mode=force'
r! /forcefsck r! /forcefsck
r! /fastboot r! /fastboot
r! /forcequotacheck r! /forcequotacheck
{% endif %}

View File

@ -35,7 +35,7 @@ in_files = [
['20-systemd-stub.conf', 'ENABLE_EFI'], ['20-systemd-stub.conf', 'ENABLE_EFI'],
['20-systemd-userdb.conf', 'ENABLE_SSH_USERDB_CONFIG'], ['20-systemd-userdb.conf', 'ENABLE_SSH_USERDB_CONFIG'],
['etc.conf'], ['etc.conf'],
['legacy.conf', 'HAVE_SYSV_COMPAT'], ['legacy.conf'],
['static-nodes-permissions.conf'], ['static-nodes-permissions.conf'],
['systemd.conf'], ['systemd.conf'],
['var.conf'], ['var.conf'],

View File

@ -1,4 +1,4 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
Q /var/lib/portables 0700 Q /var/lib/portables 0700

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
# Provision additional login messages from credentials, if they are set. Note # Provision additional login messages from credentials, if they are set. Note
# that these lines are NOPs if the credentials are not set or if the files # that these lines are NOPs if the credentials are not set or if the files

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
d$ /run/systemd/netif 0755 systemd-network systemd-network - d$ /run/systemd/netif 0755 systemd-network systemd-network -
d$ /run/systemd/netif/links 0755 systemd-network systemd-network - d$ /run/systemd/netif/links 0755 systemd-network systemd-network -

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
Q /var/lib/machines 0700 - - - Q /var/lib/machines 0700 - - -

View File

@ -5,6 +5,6 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
L! /etc/resolv.conf - - - - ../run/systemd/resolve/stub-resolv.conf L! /etc/resolv.conf - - - - ../run/systemd/resolve/stub-resolv.conf

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
# Exclude namespace mountpoints created with PrivateTmp=yes # Exclude namespace mountpoints created with PrivateTmp=yes
x /tmp/systemd-private-%b-* x /tmp/systemd-private-%b-*

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
d /run/user 0755 root root - d /run/user 0755 root root -
{% if ENABLE_UTMP %} {% if ENABLE_UTMP %}

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
# Clear tmp directories separately, to make them easier to override # Clear tmp directories separately, to make them easier to override
q /tmp 1777 root root 10d q /tmp 1777 root root 10d

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
q /var 0755 - - - q /var 0755 - - -

View File

@ -5,7 +5,7 @@
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version. # (at your option) any later version.
# See tmpfiles.d(5) for details # See tmpfiles.d(5) for details.
# Make sure these are created by default so that nobody else can # Make sure these are created by default so that nobody else can
# or empty them at startup # or empty them at startup