1
0
mirror of https://github.com/systemd/systemd synced 2026-03-10 23:24:49 +01:00

Compare commits

..

No commits in common. "10a04f6fd23d23b7c8adc4ad2720dccefe4de9ee" and "e8055af5f044b0af1da285760e59980bd40af99a" have entirely different histories.

24 changed files with 291 additions and 479 deletions

14
NEWS
View File

@ -31,12 +31,6 @@ CHANGES WITH 260 in spe:
rather than the first, to keep these options coherent with other
unit settings.
* Support for non-system users and groups in udev rules and
systemd-networkd configuration has been restored, but is deprecated
and discouraged. systemd-udevd and systemd-networkd will emit
warnings when non-system accounts are used. This support will be
removed in a future release.
Changes in other components:
* New options SYSTEMD_COLORS=auto-16, SYSTEMD_COLORS=auto-256, and
@ -675,13 +669,13 @@ CHANGES WITH 258:
an incompatible change of sorts, since per-user services will
typically not be available for such PAM sessions of system users.
* systemd-udevd warns about OWNER=/GROUP= settings with a non-system
user/group specified in udev rules files. Device nodes should not be
* systemd-udevd ignores OWNER=/GROUP= settings with a non-system
user/group specified in udev rules files, to avoid device nodes being
owned by a non-system user/group. It is recommended to check udev
rules files with 'udevadm verify' and/or 'udevadm test' commands if
the specified user/group in OWNER=/GROUP= are valid.
Similarly, systemd-networkd will warn about User=/Group= settings
with a non-system user/group specified in .netdev files for Tun/Tap
Similarly, systemd-networkd refuses User=/Group= settings with a
non-system user/group specified in .netdev files for Tun/Tap
interfaces.
* systemd-cryptenroll, systemd-repart and systemd-creds no longer

View File

@ -981,24 +981,6 @@ Defined-By: systemd
Support: %SUPPORT_URL%
Documentation: man:systemd(1)
An unsuccessful attempt has been made to break an ordering cycle between units
for which jobs have been enqueued as part of a transaction. The transaction
will fail.
-- 3405205d368e49feb5ab3925fee13874
Subject: Non-system user or group used for device ownership
Defined-By: systemd
Support: %SUPPORT_URL%
Documentation: man:systemd(1) systemd-udevd(8) systemd-networkd(8)
The ownership of a device managed by systemd-udevd or systemd-networkd is
assigned to a "regular" (non-system) user or group. This is currently allowed
for compatibility, but is deprecated and discouraged. Ownership of a device
node grants the privileges to change ACLs, the group, access mode, or set
labels or extended attributes, which creates a conflict of management, because
both udev and the user are in power to change these attributes. In addition,
device nodes appear early in boot, while regular users may appear only later.
For devices managed by systemd-udevd, it is instead recommended to use the
"uaccess"/"xaccess" mechanisms to grant limited and temporary access to device
nodes, see sd-login(8).
It has been attempted to break an ordering cycle between units for which jobs
have been enqueued as part of a transaction, but this was not successful. The
transaction will fail.

View File

@ -760,9 +760,6 @@ Tools using the Varlink protocol (such as `varlinkctl`) or sd-bus (such as
would listen on. If set to "-" the tool will turn stdin/stdout into a Varlink
connection.
* `$SYSTEMD_VARLINK_BRIDGES_DIR` overrides the default `$LIBEXEC/varlink-bridges/`
path when looking up custom scheme bridge helper binaries.
`systemd-mountfsd`:
* `$SYSTEMD_MOUNTFSD_TRUSTED_DIRECTORIES` takes a boolean argument. If true

View File

@ -256,21 +256,20 @@
</varlistentry>
<varlistentry>
<term><option>--match=this|other|any|auto</option></term>
<term><option>--match=</option></term>
<term><option>-A</option></term>
<term><option>-N</option></term>
<term><option>-T</option></term>
<listitem><para>Option <option>--match=</option> takes one of <literal>this</literal>,
<literal>other</literal>, <literal>any</literal> or <literal>auto</literal>. Some user record
settings can be defined to match only specific machines, or all machines but one, or all machines.
With this switch it is possibly to control to which machines to apply the settings appearing on the
command line after it. If <literal>this</literal> is specified the setting will only apply to the
local system (positive match), if <literal>other</literal> it will apply to all but the local system
(negative match), if <literal>any</literal> it will apply to all systems (unless there's a matching
positive or negative per-machine setting). If <literal>auto</literal> returns to the default logic:
whether a setting applies by default to the local system or all systems depends on the option in
question.</para>
<listitem><para>Takes one of <literal>this</literal>, <literal>other</literal>,
<literal>any</literal> or <literal>auto</literal>. Some user record settings can be defined to match
only specific machines, or all machines but one, or all machines. With this switch it is possibly to
control to which machines to apply the settings appearing on the command line after it. If
<literal>this</literal> is specified the setting will only apply to the local system (positive
match), if <literal>other</literal> it will apply to all but the local system (negative match), if
<literal>any</literal> it will apply to all systems (unless there's a matching positive or negative
per-machine setting). If <literal>auto</literal> returns to the default logic: whether a setting
applies by default to the local system or all systems depends on the option in question.</para>
<para>Note that only some user record settings can be conditioned like this. This option has no
effect on the others and is ignored there. This option may appear multiple times in a single command

View File

@ -57,29 +57,6 @@
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>Directories</title>
<variablelist>
<varlistentry>
<term><filename>/usr/lib/systemd/varlink-bridges/</filename></term>
<listitem>
<para>When <function>sd_varlink_connect_url()</function> encounters a URL with a scheme that is not
natively supported, it looks for a bridge helper binary named after the URL scheme in this
directory. The binary is invoked the same way as <literal>exec:</literal> binaries but with the full
URL passed as the first command line argument.</para>
<para>For example, if
<command>varlinkctl introspect https://example.com/ws/sockets/io.systemd.Hostname</command>
is called, <command>varlinkctl</command> will look for an executable
<filename>/usr/lib/systemd/varlink-bridges/https</filename> and invoke it with
<literal>https://example.com/ws/sockets/io.systemd.Hostname</literal> as its only
argument.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">

View File

@ -2019,18 +2019,16 @@ Ports=eth2</programlisting>
</varlistentry>
<varlistentry>
<term><varname>User=</varname></term>
<listitem><para>User to grant access to the <filename>/dev/net/tun</filename> device.
Note that the user must be resolvable during early boot. Using non-system users
is deprecated.</para>
<listitem><para>User to grant access to the <filename>/dev/net/tun</filename> device. The specified
user must be a system user.</para>
<xi:include href="version-info.xml" xpointer="v215"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Group=</varname></term>
<listitem><para>Group to grant access to the <filename>/dev/net/tun</filename> device.
Note that the group must be resolvable during early boot. Using non-system groups
is deprecated.</para>
<listitem><para>Group to grant access to the <filename>/dev/net/tun</filename> device. The specified
group must be a system group.</para>
<xi:include href="version-info.xml" xpointer="v215"/>
</listitem>

View File

@ -183,7 +183,6 @@ ntpservicelistdir = libexecdir / 'ntp-units.d'
credstoredir = prefixdir / 'lib/credstore'
pcrlockdir = prefixdir / 'lib/pcrlock.d'
mimepackagesdir = prefixdir / 'share/mime/packages'
varlinkbridgesdir = libexecdir / 'varlink-bridges'
configfiledir = get_option('configfiledir')
if configfiledir == ''
@ -312,7 +311,6 @@ conf.set_quoted('USER_GENERATOR_DIR', usergeneratordir)
conf.set_quoted('USER_KEYRING_PATH', pkgsysconfdir / 'import-pubring.pgp')
conf.set_quoted('USER_KEYRING_PATH_LEGACY', pkgsysconfdir / 'import-pubring.gpg')
conf.set_quoted('USER_PRESET_DIR', userpresetdir)
conf.set_quoted('VARLINK_BRIDGES_DIR', varlinkbridgesdir)
conf.set_quoted('VENDOR_KEYRING_PATH', libexecdir / 'import-pubring.pgp')
conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())

View File

@ -702,18 +702,13 @@ static int help(void) {
"Show top control groups by their resource usage.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --order=path|tasks|cpu|memory|io\n"
" Order by specified property\n"
" -p Same as --order=path, order by path\n"
" -t Same as --order=tasks, order by number of\n"
" tasks/processes\n"
" -c Same as --order=cpu, order by CPU load\n"
" -m Same as --order=memory, order by memory load\n"
" -i Same as --order=io, order by IO load\n"
" -p --order=path Order by path\n"
" -t --order=tasks Order by number of tasks/processes\n"
" -c --order=cpu Order by CPU load (default)\n"
" -m --order=memory Order by memory load\n"
" -i --order=io Order by IO load\n"
" -r --raw Provide raw (not human-readable) numbers\n"
" --cpu[=percentage]\n"
" Show CPU usage as percentage (default)\n"
" --cpu=percentage Show CPU usage as percentage (default)\n"
" --cpu=time Show CPU usage as time\n"
" -P Count userspace processes instead of tasks (excl. kernel)\n"
" -k Count all processes instead of tasks (incl. kernel)\n"

View File

@ -169,58 +169,6 @@ static int determine_default_node(void) {
return 0;
}
static int parse_wipe_slot(const char *arg) {
int r;
assert(arg);
if (isempty(arg)) {
arg_wipe_slots_mask = 0;
arg_wipe_slots_scope = WIPE_EXPLICIT;
return 0;
}
for (const char *p = arg;;) {
_cleanup_free_ char *slot = NULL;
r = extract_first_word(&p, &slot, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r == 0)
return 0;
if (r < 0)
return log_error_errno(r, "Failed to parse slot list: %s", arg);
if (streq(slot, "all"))
arg_wipe_slots_scope = WIPE_ALL;
else if (streq(slot, "empty")) {
if (arg_wipe_slots_scope != WIPE_ALL) /* if "all" was specified before, that wins */
arg_wipe_slots_scope = WIPE_EMPTY_PASSPHRASE;
} else if (streq(slot, "password"))
arg_wipe_slots_mask |= 1U << ENROLL_PASSWORD;
else if (streq(slot, "recovery"))
arg_wipe_slots_mask |= 1U << ENROLL_RECOVERY;
else if (streq(slot, "pkcs11"))
arg_wipe_slots_mask |= 1U << ENROLL_PKCS11;
else if (streq(slot, "fido2"))
arg_wipe_slots_mask |= 1U << ENROLL_FIDO2;
else if (streq(slot, "tpm2"))
arg_wipe_slots_mask |= 1U << ENROLL_TPM2;
else {
unsigned n;
r = safe_atou(slot, &n);
if (r < 0)
return log_error_errno(r, "Failed to parse slot index: %s", slot);
if (n > INT_MAX)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Slot index out of range: %u", n);
if (!GREEDY_REALLOC(arg_wipe_slots, arg_n_wipe_slots + 1))
return log_oom();
arg_wipe_slots[arg_n_wipe_slots++] = (int) n;
}
}
}
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@ -632,16 +580,62 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_WIPE_SLOT:
r = parse_wipe_slot(optarg);
if (r < 0)
return r;
case ARG_WIPE_SLOT: {
const char *p = optarg;
if (isempty(optarg)) {
arg_wipe_slots_mask = 0;
arg_wipe_slots_scope = WIPE_EXPLICIT;
break;
}
for (;;) {
_cleanup_free_ char *slot = NULL;
unsigned n;
r = extract_first_word(&p, &slot, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r == 0)
break;
if (r < 0)
return log_error_errno(r, "Failed to parse slot list: %s", optarg);
if (streq(slot, "all"))
arg_wipe_slots_scope = WIPE_ALL;
else if (streq(slot, "empty")) {
if (arg_wipe_slots_scope != WIPE_ALL) /* if "all" was specified before, that wins */
arg_wipe_slots_scope = WIPE_EMPTY_PASSPHRASE;
} else if (streq(slot, "password"))
arg_wipe_slots_mask |= 1U << ENROLL_PASSWORD;
else if (streq(slot, "recovery"))
arg_wipe_slots_mask |= 1U << ENROLL_RECOVERY;
else if (streq(slot, "pkcs11"))
arg_wipe_slots_mask |= 1U << ENROLL_PKCS11;
else if (streq(slot, "fido2"))
arg_wipe_slots_mask |= 1U << ENROLL_FIDO2;
else if (streq(slot, "tpm2"))
arg_wipe_slots_mask |= 1U << ENROLL_TPM2;
else {
r = safe_atou(slot, &n);
if (r < 0)
return log_error_errno(r, "Failed to parse slot index: %s", slot);
if (n > INT_MAX)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Slot index out of range: %u", n);
if (!GREEDY_REALLOC(arg_wipe_slots, arg_n_wipe_slots + 1))
return log_oom();
arg_wipe_slots[arg_n_wipe_slots++] = (int) n;
}
}
break;
}
case ARG_LIST_DEVICES:
return blockdev_list(BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_REQUIRE_LUKS,
/* ret_devices= */ NULL,
/* ret_n_devices= */ NULL);
r = blockdev_list(BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_REQUIRE_LUKS, /* ret_devices= */ NULL, /* ret_n_devices= */ NULL);
if (r < 0)
return r;
return 0;
case '?':
return -EINVAL;

View File

@ -106,6 +106,8 @@ static int arg_fido2_cred_alg = 0;
#endif
static bool arg_recovery_key = false;
static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
static bool arg_and_resize = false;
static bool arg_and_change_password = false;
static ExportFormat arg_export_format = EXPORT_FORMAT_FULL;
static uint64_t arg_capability_bounding_set = CAP_MASK_UNSET;
static uint64_t arg_capability_ambient_set = CAP_MASK_UNSET;
@ -1920,9 +1922,6 @@ static int update_home(int argc, char *argv[], void *userdata) {
} else
username = NULL;
bool and_change_password = !strv_isempty(arg_pkcs11_token_uri) || !strv_isempty(arg_fido2_device);
bool and_resize = arg_disk_size != UINT64_MAX || arg_disk_size_relative != UINT64_MAX;
r = acquire_bus(&bus);
if (r < 0)
return r;
@ -1954,7 +1953,7 @@ static int update_home(int argc, char *argv[], void *userdata) {
/* If we do multiple operations, let's output things more verbosely, since otherwise the repeated
* authentication might be confusing. */
if (and_resize || and_change_password)
if (arg_and_resize || arg_and_change_password)
log_info("Updating home directory.");
if (arg_offline)
@ -1989,7 +1988,7 @@ static int update_home(int argc, char *argv[], void *userdata) {
r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
if (r < 0) {
if (and_change_password &&
if (arg_and_change_password &&
sd_bus_error_has_name(&error, BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN))
/* In the generic handler we'd ask for a password in this case, but when
* changing passwords that's not sufficient, as we need to acquire all keys
@ -2003,13 +2002,13 @@ static int update_home(int argc, char *argv[], void *userdata) {
break;
}
if (and_resize)
if (arg_and_resize)
log_info("Resizing home.");
(void) home_record_reset_human_interaction_permission(hr);
/* Also sync down disk size to underlying LUKS/fscrypt/quota */
while (and_resize) {
while (arg_and_resize) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@ -2028,7 +2027,7 @@ static int update_home(int argc, char *argv[], void *userdata) {
r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
if (r < 0) {
if (and_change_password &&
if (arg_and_change_password &&
sd_bus_error_has_name(&error, BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN))
return log_error_errno(r, "Security token not inserted, refusing.");
@ -2039,13 +2038,13 @@ static int update_home(int argc, char *argv[], void *userdata) {
break;
}
if (and_change_password)
if (arg_and_change_password)
log_info("Synchronizing passwords and encryption keys.");
(void) home_record_reset_human_interaction_permission(hr);
/* Also sync down passwords to underlying LUKS/fscrypt */
while (and_change_password) {
while (arg_and_change_password) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@ -4157,6 +4156,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_FIDO2_WITH_UP,
ARG_FIDO2_WITH_UV,
ARG_RECOVERY_KEY,
ARG_AND_RESIZE,
ARG_AND_CHANGE_PASSWORD,
ARG_DROP_CACHES,
ARG_LUKS_EXTRA_MOUNT_OPTIONS,
ARG_AUTO_RESIZE_MODE,
@ -4265,6 +4266,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "fido2-with-user-presence", required_argument, NULL, ARG_FIDO2_WITH_UP },
{ "fido2-with-user-verification", required_argument, NULL, ARG_FIDO2_WITH_UV },
{ "recovery-key", required_argument, NULL, ARG_RECOVERY_KEY },
{ "and-resize", required_argument, NULL, ARG_AND_RESIZE },
{ "and-change-password", required_argument, NULL, ARG_AND_CHANGE_PASSWORD },
{ "drop-caches", required_argument, NULL, ARG_DROP_CACHES },
{ "luks-extra-mount-options", required_argument, NULL, ARG_LUKS_EXTRA_MOUNT_OPTIONS },
{ "auto-resize-mode", required_argument, NULL, ARG_AUTO_RESIZE_MODE },
@ -4797,6 +4800,14 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_AND_RESIZE:
arg_and_resize = true;
break;
case ARG_AND_CHANGE_PASSWORD:
arg_and_change_password = true;
break;
case ARG_DROP_CACHES:
r = parse_boolean_field(match_identity ?: &arg_identity_extra, "dropCaches", optarg);
if (r < 0)
@ -4997,6 +5008,12 @@ static int parse_argv(int argc, char *argv[]) {
}
}
if (!strv_isempty(arg_pkcs11_token_uri) || !strv_isempty(arg_fido2_device))
arg_and_change_password = true;
if (arg_disk_size != UINT64_MAX || arg_disk_size_relative != UINT64_MAX)
arg_and_resize = true;
if (!strv_isempty(arg_languages)) {
char **additional;

View File

@ -1035,15 +1035,12 @@ static int help(int argc, char *argv[], void *userdata) {
" --format=xz|gzip|bzip2|zstd\n"
" Desired output format for export\n"
" --force Install image even if already exists\n"
" --class=TYPE Install as the specified TYPE\n"
" -m Install as --class=machine, machine image\n"
" -P Install as --class=portable,\n"
" portable service image\n"
" -S Install as --class=sysext, system extension image\n"
" -C Install as --class=confext,\n"
" configuration extension image\n"
" -m --class=machine Install as machine image\n"
" -P --class=portable Install as portable service image\n"
" -S --class=sysext Install as system extension image\n"
" -C --class=confext Install as configuration extension image\n"
" --keep-download=BOOL Control whether to keep pristine copy of download\n"
" -N Same as --keep-download=no\n"
" -N Shortcut for --keep-download=no\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
link,

View File

@ -776,6 +776,8 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
opterr = 0;
while ((c = getopt_long(argc, argv, "hu:mM:D:", options, NULL)) >= 0)
switch (c) {
case 'h':
@ -880,7 +882,14 @@ static int parse_argv(int argc, char *argv[]) {
break;
case '?':
return -EINVAL;
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unknown option %s.",
argv[optind - 1]);
case ':':
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Missing argument to %s.",
argv[optind - 1]);
default:
assert_not_reached();

View File

@ -485,14 +485,6 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) {
return 0;
}
/* Do basic validation of the URL scheme (loosely following RFC 1738) */
static bool is_valid_url_scheme(const char *s) {
return !isempty(s) &&
strchr(LOWERCASE_LETTERS, s[0]) &&
in_charset(s, LOWERCASE_LETTERS DIGITS "+.-") &&
filename_is_valid(s);
}
_public_ int sd_varlink_connect_url(sd_varlink **ret, const char *url) {
_cleanup_free_ char *c = NULL;
const char *p;
@ -507,7 +499,7 @@ _public_ int sd_varlink_connect_url(sd_varlink **ret, const char *url) {
assert_return(ret, -EINVAL);
assert_return(url, -EINVAL);
// FIXME: Maybe add support for vsock: URL schemes here.
// FIXME: Maybe add support for vsock: and ssh-exec: URL schemes here.
/* The Varlink URL scheme is a bit underdefined. We support only the spec-defined unix: transport for
* now, plus exec:, ssh: transports we made up ourselves. Strictly speaking this shouldn't even be
@ -522,39 +514,11 @@ _public_ int sd_varlink_connect_url(sd_varlink **ret, const char *url) {
scheme = SCHEME_SSH_UNIX;
else if ((p = startswith(url, "ssh-exec:")))
scheme = SCHEME_SSH_EXEC;
else {
/* scheme is not built-in: check if we have a bridge helper binary */
const char *colon = strchr(url, ':');
if (!colon)
return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT),
"Invalid URL '%s': does not contain a ':'", url);
_cleanup_free_ char *scheme_name = strndup(url, colon - url);
if (!scheme_name)
return log_oom_debug();
if (!is_valid_url_scheme(scheme_name))
return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT),
"URL scheme not valid as bridge name: %s", scheme_name);
const char *bridges_dir = secure_getenv("SYSTEMD_VARLINK_BRIDGES_DIR") ?: VARLINK_BRIDGES_DIR;
_cleanup_free_ char *bridge = path_join(bridges_dir, scheme_name);
if (!bridge)
return log_oom_debug();
if (access(bridge, X_OK) < 0) {
if (errno == ENOENT)
return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "URL scheme '%s' not supported (and no auxiliary bridge binary is available).", scheme_name);
return log_debug_errno(errno, "Failed to look up varlink bridge binary '%s': %m", bridge);
}
return sd_varlink_connect_exec(ret, bridge, STRV_MAKE(bridge, url));
}
else
return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "URL scheme not supported.");
/* The varlink.org reference C library supports more than just file system paths. We might want to
* support that one day too. For now simply refuse that for our built-in schemes. It is fine for
* external scheme handled via plugins (see above). */
* support that one day too. For now simply refuse that. */
if (p[strcspn(p, ";?#")] != '\0')
return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "URL parameterization with ';', '?', '#' not supported.");

View File

@ -141,8 +141,7 @@ static int help(void) {
" --fsck=no Don't run file system check before mount\n"
" --description=TEXT Description for unit\n"
" -p --property=NAME=VALUE Set mount unit property\n"
" --automount=BOOL Create an automount point\n"
" -A Same as --automount=yes\n"
" -A --automount=BOOL Create an auto-mount point\n"
" --timeout-idle-sec=SEC Specify automount idle timeout\n"
" --automount-property=NAME=VALUE\n"
" Set automount unit property\n"

View File

@ -258,16 +258,6 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *str, GPERF_
/* Macros which append INTERFACE= to the message */
#define log_netdev_syntax(netdev, level, message_id, fmt, ...) \
({ \
const NetDev *_n = (netdev); \
const char *_ifname = _n ? _n->ifname : NULL; \
log_struct(level, \
LOG_MESSAGE(fmt, __VA_ARGS__), \
LOG_MESSAGE_ID(message_id), \
LOG_ITEM("INTERFACE=%s", strempty(_ifname))); \
})
#define log_netdev_full_errno_zerook(netdev, level, error, ...) \
({ \
const NetDev *_n = (netdev); \

View File

@ -6,8 +6,6 @@
#include <net/if_arp.h>
#include <sys/ioctl.h>
#include "sd-messages.h"
#include "alloc-util.h"
#include "daemon-util.h"
#include "fd-util.h"
@ -16,7 +14,6 @@
#include "socket-util.h"
#include "string-util.h"
#include "tuntap.h"
#include "uid-classification.h"
#include "user-record.h"
#include "user-util.h"
#include "userdb.h"
@ -239,43 +236,27 @@ static int tuntap_verify(NetDev *netdev, const char *filename) {
if (t->user_name) {
_cleanup_(user_record_unrefp) UserRecord *ur = NULL;
r = userdb_by_name(t->user_name, /* match = */ NULL,
r = userdb_by_name(t->user_name, &USERDB_MATCH_ROOT_AND_SYSTEM,
USERDB_SUPPRESS_SHADOW | USERDB_PARSE_NUMERIC,
&ur);
if (r < 0)
log_netdev_warning_errno(netdev, r, "Cannot resolve user name '%s', ignoring: %s",
t->user_name, STRERROR_USER(r));
else {
if (!uid_is_system(ur->uid))
log_netdev_syntax(netdev, LOG_WARNING,
SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR,
"User '%s' configured as owner is not a system user. "
"Support for device node ownership by non-system accounts is deprecated and will be removed in the future.",
t->user_name);
else
t->uid = ur->uid;
}
}
if (t->group_name) {
_cleanup_(group_record_unrefp) GroupRecord *gr = NULL;
r = groupdb_by_name(t->group_name, /* match = */ NULL,
r = groupdb_by_name(t->group_name, &USERDB_MATCH_ROOT_AND_SYSTEM,
USERDB_SUPPRESS_SHADOW | USERDB_PARSE_NUMERIC,
&gr);
if (r < 0)
log_netdev_warning_errno(netdev, r, "Cannot resolve group name '%s', ignoring: %s",
t->group_name, STRERROR_GROUP(r));
else {
if (!gid_is_system(gr->gid))
log_netdev_syntax(netdev, LOG_WARNING,
SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR,
"Group '%s' configured as owner is not a system group. "
"Support for device node ownership by non-system accounts is deprecated and will be removed in the future.",
t->group_name);
else
t->gid = gr->gid;
}
}
return 0;

View File

@ -292,71 +292,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_settings_filename, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
STATIC_DESTRUCTOR_REGISTER(arg_background, freep);
static int parse_private_users(
const char *s,
UserNamespaceMode *ret_userns_mode,
uid_t *ret_uid_shift,
uid_t *ret_uid_range) {
int boolean, r;
assert(ret_userns_mode);
assert(ret_uid_shift);
assert(ret_uid_range);
if (!s)
boolean = true;
else if (!in_charset(s, DIGITS))
/* do *not* parse numbers as booleans */
boolean = parse_boolean(s);
else
boolean = -1;
if (boolean == 0) {
/* no: User namespacing off */
*ret_userns_mode = USER_NAMESPACE_NO;
*ret_uid_shift = UID_INVALID;
*ret_uid_range = UINT32_C(0x10000);
} else if (boolean > 0) {
/* yes: User namespacing on, UID range is read from root dir */
*ret_userns_mode = USER_NAMESPACE_FIXED;
*ret_uid_shift = UID_INVALID;
*ret_uid_range = UINT32_C(0x10000);
} else if (streq(s, "pick")) {
/* pick: User namespacing on, UID range is picked randomly */
*ret_userns_mode = USER_NAMESPACE_PICK; /* Note that arg_userns_ownership is
* implied by USER_NAMESPACE_PICK
* further down. */
*ret_uid_shift = UID_INVALID;
*ret_uid_range = UINT32_C(0x10000);
} else if (streq(s, "identity")) {
/* identity: User namespaces on, UID range is map of the 0…0xFFFF range to
* itself, i.e. we don't actually map anything, but do take benefit of
* isolation of capability sets. */
*ret_userns_mode = USER_NAMESPACE_FIXED;
*ret_uid_shift = 0;
*ret_uid_range = UINT32_C(0x10000);
} else if (streq(optarg, "managed")) {
/* managed: User namespace on, and acquire it from systemd-nsresourced */
*ret_userns_mode = USER_NAMESPACE_MANAGED;
*ret_uid_shift = UID_INVALID;
*ret_uid_range = UINT32_C(0x10000);
} else {
/* anything else: User namespacing on, UID range is explicitly configured */
r = parse_userns_uid_range(optarg, ret_uid_shift, ret_uid_range);
if (r < 0)
return r;
*ret_userns_mode = USER_NAMESPACE_FIXED;
}
return 0;
}
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@ -1007,23 +942,31 @@ static int parse_argv(int argc, char *argv[]) {
}
case 'M':
if (!isempty(optarg) && !hostname_is_valid(optarg, /* flags= */ 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid machine name: %s", optarg);
if (isempty(optarg))
arg_machine = mfree(arg_machine);
else {
if (!hostname_is_valid(optarg, 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid machine name: %s", optarg);
r = free_and_strdup_warn(&arg_machine, optarg);
if (r < 0)
return r;
r = free_and_strdup(&arg_machine, optarg);
if (r < 0)
return log_oom();
}
break;
case ARG_HOSTNAME:
if (!isempty(optarg) && !hostname_is_valid(optarg, /* flags= */ 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid hostname: %s", optarg);
if (isempty(optarg))
arg_hostname = mfree(arg_hostname);
else {
if (!hostname_is_valid(optarg, 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid hostname: %s", optarg);
r = free_and_strdup_warn(&arg_hostname, optarg);
if (r < 0)
return r;
r = free_and_strdup(&arg_hostname, optarg);
if (r < 0)
return log_oom();
}
arg_settings_mask |= SETTING_HOSTNAME;
break;
@ -1198,13 +1141,58 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_PRIVATE_USERS:
r = parse_private_users(optarg, &arg_userns_mode, &arg_uid_shift, &arg_uid_range);
if (r < 0)
return r;
case ARG_PRIVATE_USERS: {
int boolean;
if (!optarg)
boolean = true;
else if (!in_charset(optarg, DIGITS))
/* do *not* parse numbers as booleans */
boolean = parse_boolean(optarg);
else
boolean = -1;
if (boolean == 0) {
/* no: User namespacing off */
arg_userns_mode = USER_NAMESPACE_NO;
arg_uid_shift = UID_INVALID;
arg_uid_range = UINT32_C(0x10000);
} else if (boolean > 0) {
/* yes: User namespacing on, UID range is read from root dir */
arg_userns_mode = USER_NAMESPACE_FIXED;
arg_uid_shift = UID_INVALID;
arg_uid_range = UINT32_C(0x10000);
} else if (streq(optarg, "pick")) {
/* pick: User namespacing on, UID range is picked randomly */
arg_userns_mode = USER_NAMESPACE_PICK; /* Note that arg_userns_ownership is
* implied by USER_NAMESPACE_PICK
* further down. */
arg_uid_shift = UID_INVALID;
arg_uid_range = UINT32_C(0x10000);
} else if (streq(optarg, "identity")) {
/* identity: User namespaces on, UID range is map of the 0…0xFFFF range to
* itself, i.e. we don't actually map anything, but do take benefit of
* isolation of capability sets. */
arg_userns_mode = USER_NAMESPACE_FIXED;
arg_uid_shift = 0;
arg_uid_range = UINT32_C(0x10000);
} else if (streq(optarg, "managed")) {
/* managed: User namespace on, and acquire it from systemd-nsresourced */
arg_userns_mode = USER_NAMESPACE_MANAGED;
arg_uid_shift = UID_INVALID;
arg_uid_range = UINT32_C(0x10000);
} else {
/* anything else: User namespacing on, UID range is explicitly configured */
r = parse_userns_uid_range(optarg, &arg_uid_shift, &arg_uid_range);
if (r < 0)
return r;
arg_userns_mode = USER_NAMESPACE_FIXED;
}
arg_settings_mask |= SETTING_USERNS;
break;
}
case 'U':
if (userns_supported()) {

View File

@ -250,11 +250,13 @@ static int run(int argc, char* argv[]) {
if (r <= 0)
return r;
if (optind >= argc)
return list_paths();
if (argc > optind) {
r = 0;
for (int i = optind; i < argc; i++)
RET_GATHER(r, print_path(argv[i]));
} else
r = list_paths();
for (int i = optind; i < argc; i++)
RET_GATHER(r, print_path(argv[i]));
return r;
}

View File

@ -14,12 +14,6 @@
#include "string-util.h"
#include "strv.h"
typedef enum LookupType {
LOOKUP_TYPE_REGULAR,
LOOKUP_TYPE_PRIVATE,
LOOKUP_TYPE_EXCLUSIVE, /* -x */
} LookupType;
static int resolvconf_help(void) {
_cleanup_free_ char *link = NULL;
int r;
@ -100,75 +94,6 @@ static int parse_search_domain(const char *string) {
return 0;
}
static int parse_stdin(LookupType lookup_type) {
int r;
for (unsigned n = 0;;) {
_cleanup_free_ char *line = NULL;
const char *a;
r = read_stripped_line(stdin, LONG_LINE_MAX, &line);
if (r < 0)
return log_error_errno(r, "Failed to read from stdin: %m");
if (r == 0)
break;
n++;
if (IN_SET(*line, '#', ';', 0))
continue;
a = first_word(line, "nameserver");
if (a) {
(void) parse_nameserver(a);
continue;
}
a = first_word(line, "domain");
if (!a)
a = first_word(line, "search");
if (a) {
(void) parse_search_domain(a);
continue;
}
log_syntax(NULL, LOG_DEBUG, "stdin", n, 0, "Ignoring resolv.conf line: %s", line);
}
switch (lookup_type) {
case LOOKUP_TYPE_REGULAR:
break;
case LOOKUP_TYPE_PRIVATE:
arg_disable_default_route = true;
break;
case LOOKUP_TYPE_EXCLUSIVE:
/* If -x mode is selected, let's preferably route non-suffixed lookups to this interface.
* This somewhat matches the original -x behaviour */
r = strv_extend(&arg_set_domain, "~.");
if (r < 0)
return log_oom();
break;
default:
assert_not_reached();
}
if (strv_isempty(arg_set_dns))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"No DNS servers specified, refusing operation.");
if (strv_isempty(arg_set_domain)) {
/* When no domain/search is set, clear the current domains. */
r = strv_extend(&arg_set_domain, "");
if (r < 0)
return log_oom();
}
return 0;
}
int resolvconf_parse_argv(int argc, char *argv[]) {
enum {
@ -189,18 +114,22 @@ int resolvconf_parse_argv(int argc, char *argv[]) {
{}
};
enum {
TYPE_REGULAR,
TYPE_PRIVATE,
TYPE_EXCLUSIVE, /* -x */
} type = TYPE_REGULAR;
int c, r;
assert(argc >= 0);
assert(argv);
/* openresolv checks these environment variables */
LookupType lookup_type = LOOKUP_TYPE_REGULAR;
if (getenv("IF_EXCLUSIVE"))
lookup_type = LOOKUP_TYPE_EXCLUSIVE;
type = TYPE_EXCLUSIVE;
if (getenv("IF_PRIVATE"))
lookup_type = LOOKUP_TYPE_PRIVATE;
type = TYPE_PRIVATE;
arg_mode = _MODE_INVALID;
@ -224,11 +153,11 @@ int resolvconf_parse_argv(int argc, char *argv[]) {
/* The exclusive/private/force stuff is an openresolv invention, we support in some skewed way */
case 'x':
lookup_type = LOOKUP_TYPE_EXCLUSIVE;
type = TYPE_EXCLUSIVE;
break;
case 'p':
lookup_type = LOOKUP_TYPE_PRIVATE;
type = TYPE_PRIVATE;
break;
case 'f':
@ -286,12 +215,75 @@ int resolvconf_parse_argv(int argc, char *argv[]) {
r = ifname_resolvconf_mangle(argv[optind]);
if (r <= 0)
return r;
optind++;
if (arg_mode == MODE_SET_LINK) {
r = parse_stdin(lookup_type);
if (r < 0)
return r;
unsigned n = 0;
for (;;) {
_cleanup_free_ char *line = NULL;
const char *a;
r = read_stripped_line(stdin, LONG_LINE_MAX, &line);
if (r < 0)
return log_error_errno(r, "Failed to read from stdin: %m");
if (r == 0)
break;
n++;
if (IN_SET(*line, '#', ';', 0))
continue;
a = first_word(line, "nameserver");
if (a) {
(void) parse_nameserver(a);
continue;
}
a = first_word(line, "domain");
if (!a)
a = first_word(line, "search");
if (a) {
(void) parse_search_domain(a);
continue;
}
log_syntax(NULL, LOG_DEBUG, "stdin", n, 0, "Ignoring resolv.conf line: %s", line);
}
switch (type) {
case TYPE_REGULAR:
break;
case TYPE_PRIVATE:
arg_disable_default_route = true;
break;
case TYPE_EXCLUSIVE:
/* If -x mode is selected, let's preferably route non-suffixed lookups to this interface. This
* somewhat matches the original -x behaviour */
r = strv_extend(&arg_set_domain, "~.");
if (r < 0)
return log_oom();
break;
default:
assert_not_reached();
}
if (strv_isempty(arg_set_dns))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"No DNS servers specified, refusing operation.");
if (strv_isempty(arg_set_domain)) {
/* When no domain/search is set, clear the current domains. */
r = strv_extend(&arg_set_domain, "");
if (r < 0)
return log_oom();
}
}
return 1; /* work to do */

View File

@ -303,9 +303,6 @@ _SD_BEGIN_DECLARATIONS;
#define SD_MESSAGE_CANT_BREAK_ORDERING_CYCLE SD_ID128_MAKE(b3,11,2d,da,d1,90,45,53,8c,76,68,5b,a5,91,8a,80)
#define SD_MESSAGE_CANT_BREAK_ORDERING_CYCLE_STR SD_ID128_MAKE_STR(b3,11,2d,da,d1,90,45,53,8c,76,68,5b,a5,91,8a,80)
#define SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED SD_ID128_MAKE(34,05,20,5d,36,8e,49,fe,b5,ab,39,25,fe,e1,38,74)
#define SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR SD_ID128_MAKE_STR(34,05,20,5d,36,8e,49,fe,b5,ab,39,25,fe,e1,38,74)
_SD_END_DECLARATIONS;
#endif

View File

@ -246,10 +246,7 @@ TEST(proc, .sd_booted = true) {
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
uid_t uid = UID_INVALID;
r = proc_dir_read_pidref(d, &pid);
if (r == -EINVAL) /* Can happen if we pick a non-thread-group leader */
continue;
ASSERT_OK(r);
ASSERT_OK(r = proc_dir_read_pidref(d, &pid));
if (r == 0)
break;

View File

@ -5,7 +5,6 @@
#include <unistd.h>
#include "sd-json.h"
#include "sd-messages.h"
#include "alloc-util.h"
#include "architecture.h"
@ -51,7 +50,6 @@
#include "udev-trace.h"
#include "udev-util.h"
#include "udev-worker.h"
#include "uid-classification.h"
#include "user-record.h"
#include "user-util.h"
#include "userdb.h"
@ -228,26 +226,6 @@ static bool token_is_for_parents(UdevRuleToken *token) {
/*** Logging helpers ***/
#define log_udev_event_syntax(event, token, level, message_id, fmt, ...) \
({ \
UdevEvent *_event = (event); \
UdevRuleToken *_token = ASSERT_PTR(token); \
int _level = (level); \
sd_device *_d = token_is_for_parents(_token) ? _event->dev_parent : _event->dev; \
const char *_sysname = NULL; \
\
if (_d && log_get_max_level() >= LOG_PRI(_level)) \
(void) sd_device_get_sysname(_d, &_sysname); \
log_struct(_level, \
LOG_MESSAGE("%s:%u %s:" fmt, \
strna(_token->rule_line->rule_file ? _token->rule_line->rule_file->filename : NULL), \
_token->rule_line->line_number, \
_token->token_str, \
__VA_ARGS__), \
LOG_MESSAGE_ID(message_id), \
LOG_ITEM("DEVICE=%s", strempty(_sysname))); \
})
#define _log_udev_rule_file_full(device, device_u, file, file_u, line_nr, level, level_u, error, fmt, ...) \
({ \
int level_u = (level); \
@ -531,19 +509,13 @@ static int rule_resolve_user(UdevRuleLine *rule_line, const char *name, uid_t *r
}
_cleanup_(user_record_unrefp) UserRecord *ur = NULL;
r = userdb_by_name(name, /* match= */ NULL,
r = userdb_by_name(name, &USERDB_MATCH_ROOT_AND_SYSTEM,
USERDB_SUPPRESS_SHADOW | USERDB_PARSE_NUMERIC | USERDB_SYNTHESIZE_NUMERIC,
&ur);
if (r < 0)
return log_line_error_errno(rule_line, r,
"Failed to resolve user '%s', ignoring: %s",
name, STRERROR_USER(r));
if (!uid_is_system(ur->uid))
log_struct(LOG_WARNING,
LOG_MESSAGE("%s:%u User %s configured to own a device node is not a system user. "
"Support for device node ownership by non-system accounts is deprecated and will be removed in the future.",
rule_line->rule_file->filename, rule_line->line_number, name),
LOG_MESSAGE_ID(SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR));
_cleanup_free_ char *n = strdup(name);
if (!n)
@ -572,19 +544,13 @@ static int rule_resolve_group(UdevRuleLine *rule_line, const char *name, gid_t *
}
_cleanup_(group_record_unrefp) GroupRecord *gr = NULL;
r = groupdb_by_name(name, /* match= */ NULL,
r = groupdb_by_name(name, &USERDB_MATCH_ROOT_AND_SYSTEM,
USERDB_SUPPRESS_SHADOW | USERDB_PARSE_NUMERIC | USERDB_SYNTHESIZE_NUMERIC,
&gr);
if (r < 0)
return log_line_error_errno(rule_line, r,
"Failed to resolve group '%s', ignoring: %s",
name, STRERROR_GROUP(r));
if (!gid_is_system(gr->gid))
log_struct(LOG_WARNING,
LOG_MESSAGE("%s:%u Group %s configured to own a device node is not a system group. "
"Support for device node ownership by non-system accounts is deprecated and will be removed in the future.",
rule_line->rule_file->filename, rule_line->line_number, name),
LOG_MESSAGE_ID(SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR));
_cleanup_free_ char *n = strdup(name);
if (!n)
@ -2708,7 +2674,7 @@ static int udev_rule_apply_token_to_event(
return true;
_cleanup_(user_record_unrefp) UserRecord *ur = NULL;
r = userdb_by_name(owner, /* match= */ NULL,
r = userdb_by_name(owner, &USERDB_MATCH_ROOT_AND_SYSTEM,
USERDB_SUPPRESS_SHADOW | USERDB_PARSE_NUMERIC | USERDB_SYNTHESIZE_NUMERIC,
&ur);
if (r < 0)
@ -2716,13 +2682,6 @@ static int udev_rule_apply_token_to_event(
"Failed to resolve user \"%s\", ignoring: %s",
owner, STRERROR_USER(r));
else {
if (!uid_is_system(ur->uid))
log_udev_event_syntax(event, token, LOG_WARNING,
SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR,
"User %s configured to own a device node is not a system user. "
"Support for device node ownership by non-system accounts is deprecated and will be removed in the future.",
owner);
event->uid = ur->uid;
log_event_debug(event, token, "Set owner: %s("UID_FMT")", owner, event->uid);
}
@ -2741,7 +2700,7 @@ static int udev_rule_apply_token_to_event(
return true;
_cleanup_(group_record_unrefp) GroupRecord *gr = NULL;
r = groupdb_by_name(group, /* match= */ NULL,
r = groupdb_by_name(group, &USERDB_MATCH_ROOT_AND_SYSTEM,
USERDB_SUPPRESS_SHADOW | USERDB_PARSE_NUMERIC | USERDB_SYNTHESIZE_NUMERIC,
&gr);
if (r < 0)
@ -2749,13 +2708,6 @@ static int udev_rule_apply_token_to_event(
"Failed to resolve group \"%s\", ignoring: %s",
group, STRERROR_GROUP(r));
else {
if (!gid_is_system(gr->gid))
log_udev_event_syntax(event, token, LOG_WARNING,
SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR,
"Group %s configured to own a device node is not a system group. "
"Support for device node ownership by non-system accounts is deprecated and will be removed in the future.",
group);
event->gid = gr->gid;
log_event_debug(event, token, "Set group: %s("GID_FMT")", group, event->gid);
}

View File

@ -11,5 +11,3 @@ executables += [
'sources' : varlinkctl_sources,
},
]
install_emptydir(varlinkbridgesdir)

View File

@ -315,10 +315,8 @@ if ! getent passwd 12345 >/dev/null; then
fi
# regular user
if getent passwd testuser >/dev/null; then
echo 'OWNER="testuser"' >"${rules}"
udevadm verify "${rules}"
echo "OWNER=\"$(id -u testuser)\"" >"${rules}"
udevadm verify "${rules}"
test_syntax_error 'OWNER="testuser"' "Failed to resolve user 'testuser', ignoring: Not a system user"
test_syntax_error "OWNER=\"$(id -u testuser)\"" "Failed to resolve user '$(id -u testuser)', ignoring: Not a system user"
fi
test_syntax_error 'GROUP{a}="b"' 'Invalid attribute for GROUP.'
test_syntax_error 'GROUP-="b"' 'Invalid operator for GROUP.'
@ -349,11 +347,8 @@ if ! getent group 12345 >/dev/null; then
fi
# regular group
if getent group testuser >/dev/null; then
echo 'GROUP="testuser"' >"${rules}"
udevadm verify "${rules}"
echo "GROUP=\"$(id -g testuser)\"" >"${rules}"
udevadm verify "${rules}"
test_syntax_error 'GROUP="testuser"' "Failed to resolve group 'testuser', ignoring: Not a system group"
test_syntax_error "GROUP=\"$(id -g testuser)\"" "Failed to resolve group '$(id -g testuser)', ignoring: Not a system group"
fi
test_syntax_error 'MODE{a}="b"' 'Invalid attribute for MODE.'
test_syntax_error 'MODE-="b"' 'Invalid operator for MODE.'