Compare commits

...

17 Commits

Author SHA1 Message Date
leafcompost 91de928dc4
Merge bf2328c714 into 4b356c90dc 2024-11-23 10:10:57 -08:00
Ani Sinha 4b356c90dc measure: add 'dtbauto' option in help message
'dtbauto' command line was missing from the help string. Add it.
2024-11-23 12:43:34 +00:00
Léane GRASSER f28e16d14e po: Translated using Weblate (French)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Léane GRASSER <leane.grasser@proton.me>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fr/
Translation: systemd/main
2024-11-23 20:49:18 +09:00
Yu Watanabe 9e05e33871 networkd-test.py: fix interface state checker
After 259125d53d, network interfaces
declared by .netdev files are created after systemd-networkd sends READY
notification. So, even when networkd is started, the netdevs may not
be created yet, and 'ip' command may fail. Let's also check the return
code of the command.

This also
- drops never worked stdout checks,
- makes the test fail if the interface is not created within the timeout.
2024-11-23 17:33:43 +09:00
Lennart Poettering 95116bdfd5 nspawn: improve log message on bad incoming sd_notify() message
It's the PID that is wrong, not the UID/GID, be precise.
2024-11-23 17:33:17 +09:00
Lennart Poettering 2bd290ca02 nspawn: fix userns_mkdir() invocation
The wrong error code was logged.

But actually given that userns_mkdir() is fine with existing dirs, let's
drop the redundant conditionalization.

Follow-up for: a1fcaa1549
2024-11-23 17:33:06 +09:00
Yu Watanabe 1e9fb1d456 shutdown: propagate one more error from sync_making_progress()
No functional change, just refactoring, as anyway all errors will be
ignored by the caller.
2024-11-23 17:32:51 +09:00
Yu Watanabe 56c761f8c6
namespace-util: handle -ENOSPC by userns_acquire() gracefully in is_idmapping_supported() (#35313)
Follow-up for edae62120f.
Fixes #35311.
2024-11-23 17:32:23 +09:00
Yu Watanabe b76730f3fe shutdown: close DM block device before issuing DM_DEV_REMOVE ioctl
Otherwise, the ioctl() may fail with EBUSY.

Follow-up for b4b66b2662.
Hopefully fixes #35243.
2024-11-23 17:31:36 +09:00
Yu Watanabe 3dda236c5c basic/linux: update kernel headers from v6.12 2024-11-23 17:31:12 +09:00
Zbigniew Jędrzejewski-Szmek 5598454a3f Undeprecate commandline params forcequotacheck, fastboot, and forcefsck
Those are historical names, but there is nothing wrong with them. The files on
/ (/fastboot, /forcefsck, and /forcequotacheck) are problematic because they
require a modification of the root file system. But the commandline params work
fine. They have the obvious advantage compared to our "modern" option that they
are much easier to type without looking up the spelling in the docs. Undeprecate
them to avoid unnecessary churn.
2024-11-23 17:30:56 +09:00
Yu Watanabe 2994ca354b namespace-util: update log messages 2024-11-23 06:52:48 +09:00
Yu Watanabe eb14b993bb namespace-util: handle -ENOSPC by userns_acquire() gracefully in is_idmapping_supported()
Follow-up for edae62120f.
Fixes #35311.
2024-11-23 06:52:38 +09:00
maia x. bf2328c714 man: document confext reload behavior for ExtensionDirectories/Images 2024-10-05 15:55:53 -07:00
maia x. 1e4e23cb7e test: check reloading notify-reload service refreshes vpick extensions 2024-10-05 15:55:53 -07:00
maia x. 77eb9bf10d core: reload confexts when reloading notify-reload services
`ExtensionImages=` and `ExtensionDirectories=` now let you specify vpick-named
extensions; however, since they just get set up once when the service is
started, you can't see newer versions without restarting the service entirely.
Here, also reload confext extensions when you reload a service. This allows you
to deploy a new version of some configuration and have it picked up at reload
time without interruption to your workload.

Right now, we would only reload confext extensions and leave the sysext ones
behind, since it didn't seem prudent to swap out what is likely program code at
reload. This is made possible by only going for the
`SYSTEMD_CONFEXT_HIERARCHIES` overlays (which only contains `/etc`). For now, we
also only do this for the notify-reload service type until more knobs are added
in the future.
2024-10-05 15:55:53 -07:00
maia x. 650e82ee3c vpick: add path_uses_vpick helper method
Add a path_uses_vpick helper method to determine if a path matches
the vpick format ('PATH/NAME.SUFFIX.v' or 'PATH.v/NAME___.SUFFIX').
2024-10-05 15:55:53 -07:00
31 changed files with 490 additions and 108 deletions

View File

@ -562,6 +562,13 @@
To disable the safety check that the extension-release file name matches the image file name, the
<varname>x-systemd.relax-extension-release-check</varname> mount option may be appended.</para>
<para>This option can be used together with a <option>notify-reload</option> service type and
<citerefentry><refentrytitle>systemd.v</refentrytitle><manvolnum>7</manvolnum></citerefentry>
to manage configuration updates. When such a service carrying confext images is reloaded, the confext
itself will also be reloaded to pick up any changes. This only applies to confext extensions. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
also for details.</para>
<para>When <varname>DevicePolicy=</varname> is set to <literal>closed</literal> or
<literal>strict</literal>, or set to <literal>auto</literal> and <varname>DeviceAllow=</varname> is
set, then this setting adds <filename>/dev/loop-control</filename> with <constant>rw</constant> mode,
@ -606,6 +613,14 @@
or the host. See:
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>This option can be used together with a <option>notify-reload</option> service type and
<citerefentry><refentrytitle>systemd.v</refentrytitle><manvolnum>7</manvolnum></citerefentry>
to manage configuration updates. When such a system service carrying confext directories is reloaded,
the confext itself will also be reloaded to pick up any changes. This only applies to confext
extensions. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
also for details.</para>
<para>Note that usage from user units requires overlayfs support in unprivileged user namespaces,
which was first introduced in kernel v5.11.</para>

View File

@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \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-23 10:38+0000\n"
"Last-Translator: Léane GRASSER <leane.grasser@proton.me>\n"
"Language-Team: French <https://translate.fedoraproject.org/projects/systemd/"
"main/fr/>\n"
@ -1258,7 +1258,7 @@ msgstr ""
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features"
msgstr "Gérer les fonctionnalités en option"
msgstr "Gérer les fonctionnalités facultatives"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76
msgid "Authentication is required to manage optional features"

View File

@ -21,7 +21,7 @@
#define AUTOFS_MIN_PROTO_VERSION 3
#define AUTOFS_MAX_PROTO_VERSION 5
#define AUTOFS_PROTO_SUBVERSION 5
#define AUTOFS_PROTO_SUBVERSION 6
/*
* The wait_queue_token (autofs_wqt_t) is part of a structure which is passed

View File

@ -1121,6 +1121,9 @@ enum bpf_attach_type {
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
/* Add BPF_LINK_TYPE(type, name) in bpf_types.h to keep bpf_link_type_strs[]
* in sync with the definitions below.
*/
enum bpf_link_type {
BPF_LINK_TYPE_UNSPEC = 0,
BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
@ -2851,7 +2854,7 @@ union bpf_attr {
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
* **TCP_BPF_RTO_MIN**.
* **TCP_BPF_RTO_MIN**, **TCP_BPF_SOCK_OPS_CB_FLAGS**.
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
@ -5519,11 +5522,12 @@ union bpf_attr {
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
* invalid arguments are passed.
*
* void *bpf_kptr_xchg(void *map_value, void *ptr)
* void *bpf_kptr_xchg(void *dst, void *ptr)
* Description
* Exchange kptr at pointer *map_value* with *ptr*, and return the
* old value. *ptr* can be NULL, otherwise it must be a referenced
* pointer which will be released when this helper is called.
* Exchange kptr at pointer *dst* with *ptr*, and return the old value.
* *dst* can be map value or local kptr. *ptr* can be NULL, otherwise
* it must be a referenced pointer which will be released when this helper
* is called.
* Return
* The old value of kptr (which can be NULL). The returned pointer
* if not NULL, is a reference which must be released using its
@ -6046,11 +6050,6 @@ enum {
BPF_F_MARK_ENFORCE = (1ULL << 6),
};
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
enum {
BPF_F_INGRESS = (1ULL << 0),
};
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
enum {
BPF_F_TUNINFO_IPV6 = (1ULL << 0),
@ -6197,10 +6196,12 @@ enum {
BPF_F_BPRM_SECUREEXEC = (1ULL << 0),
};
/* Flags for bpf_redirect_map helper */
/* Flags for bpf_redirect and bpf_redirect_map helpers */
enum {
BPF_F_BROADCAST = (1ULL << 3),
BPF_F_EXCLUDE_INGRESS = (1ULL << 4),
BPF_F_INGRESS = (1ULL << 0), /* used for skb path */
BPF_F_BROADCAST = (1ULL << 3), /* used for XDP path */
BPF_F_EXCLUDE_INGRESS = (1ULL << 4), /* used for XDP path */
#define BPF_F_REDIRECT_FLAGS (BPF_F_INGRESS | BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS)
};
#define __bpf_md_ptr(type, name) \
@ -7080,6 +7081,7 @@ enum {
TCP_BPF_SYN = 1005, /* Copy the TCP header */
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and TCP header */
TCP_BPF_SYN_MAC = 1007, /* Copy the MAC, IP[46], and TCP header */
TCP_BPF_SOCK_OPS_CB_FLAGS = 1008, /* Get or Set TCP sock ops flags */
};
enum {
@ -7512,4 +7514,13 @@ struct bpf_iter_num {
__u64 __opaque[1];
} __attribute__((aligned(8)));
/*
* Flags to control BPF kfunc behaviour.
* - BPF_F_PAD_ZEROS: Pad destination buffer with zeros. (See the respective
* helper documentation for details.)
*/
enum bpf_kfunc_flags {
BPF_F_PAD_ZEROS = (1ULL << 0),
};
#endif /* __LINUX_BPF_H__ */

View File

@ -28,6 +28,23 @@
#define _BITUL(x) (_UL(1) << (x))
#define _BITULL(x) (_ULL(1) << (x))
#if !defined(__ASSEMBLY__)
/*
* Missing __asm__ support
*
* __BIT128() would not work in the __asm__ code, as it shifts an
* 'unsigned __init128' data type as direct representation of
* 128 bit constants is not supported in the gcc compiler, as
* they get silently truncated.
*
* TODO: Please revisit this implementation when gcc compiler
* starts representing 128 bit constants directly like long
* and unsigned long etc. Subsequently drop the comment for
* GENMASK_U128() which would then start supporting __asm__ code.
*/
#define _BIT128(x) ((unsigned __int128)(1) << (x))
#endif
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))

View File

@ -2531,4 +2531,20 @@ struct ethtool_link_settings {
* __u32 map_lp_advertising[link_mode_masks_nwords];
*/
};
/**
* enum phy_upstream - Represents the upstream component a given PHY device
* is connected to, as in what is on the other end of the MII bus. Most PHYs
* will be attached to an Ethernet MAC controller, but in some cases, there's
* an intermediate PHY used as a media-converter, which will driver another
* MII interface as its output.
* @PHY_UPSTREAM_MAC: Upstream component is a MAC (a switch port,
* or ethernet controller)
* @PHY_UPSTREAM_PHY: Upstream component is a PHY (likely a media converter)
*/
enum phy_upstream {
PHY_UPSTREAM_MAC,
PHY_UPSTREAM_PHY,
};
#endif /* _LINUX_ETHTOOL_H */

View File

@ -67,6 +67,7 @@ enum {
FRA_IP_PROTO, /* ip proto */
FRA_SPORT_RANGE, /* sport */
FRA_DPORT_RANGE, /* dport */
FRA_DSCP, /* dscp */
__FRA_MAX
};

View File

@ -230,8 +230,8 @@ struct tpacket_hdr_v1 {
* ts_first_pkt:
* Is always the time-stamp when the block was opened.
* Case a) ZERO packets
* No packets to deal with but atleast you know the
* time-interval of this block.
* No packets to deal with but at least you know
* the time-interval of this block.
* Case b) Non-zero packets
* Use the ts of the first packet in the block.
*
@ -265,7 +265,8 @@ enum tpacket_versions {
- struct tpacket_hdr
- pad to TPACKET_ALIGNMENT=16
- struct sockaddr_ll
- Gap, chosen so that packet data (Start+tp_net) alignes to TPACKET_ALIGNMENT=16
- Gap, chosen so that packet data (Start+tp_net) aligns to
TPACKET_ALIGNMENT=16
- Start+tp_mac: [ Optional MAC header ]
- Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
- Pad to align to TPACKET_ALIGNMENT=16

View File

@ -141,7 +141,7 @@ struct in_addr {
*/
#define IP_PMTUDISC_INTERFACE 4
/* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get
* fragmented if they exeed the interface mtu
* fragmented if they exceed the interface mtu
*/
#define IP_PMTUDISC_OMIT 5

View File

@ -140,25 +140,6 @@
#endif /* _NETINET_IN_H */
/* Coordinate with glibc netipx/ipx.h header. */
#if defined(__NETIPX_IPX_H)
#define __UAPI_DEF_SOCKADDR_IPX 0
#define __UAPI_DEF_IPX_ROUTE_DEFINITION 0
#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 0
#define __UAPI_DEF_IPX_CONFIG_DATA 0
#define __UAPI_DEF_IPX_ROUTE_DEF 0
#else /* defined(__NETIPX_IPX_H) */
#define __UAPI_DEF_SOCKADDR_IPX 1
#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1
#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1
#define __UAPI_DEF_IPX_CONFIG_DATA 1
#define __UAPI_DEF_IPX_ROUTE_DEF 1
#endif /* defined(__NETIPX_IPX_H) */
/* Definitions for xattr.h */
#if defined(_SYS_XATTR_H)
#define __UAPI_DEF_XATTR 0
@ -240,23 +221,6 @@
#define __UAPI_DEF_IP6_MTUINFO 1
#endif
/* Definitions for ipx.h */
#ifndef __UAPI_DEF_SOCKADDR_IPX
#define __UAPI_DEF_SOCKADDR_IPX 1
#endif
#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION
#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1
#endif
#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION
#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1
#endif
#ifndef __UAPI_DEF_IPX_CONFIG_DATA
#define __UAPI_DEF_IPX_CONFIG_DATA 1
#endif
#ifndef __UAPI_DEF_IPX_ROUTE_DEF
#define __UAPI_DEF_IPX_ROUTE_DEF 1
#endif
/* Definitions for xattr.h */
#ifndef __UAPI_DEF_XATTR
#define __UAPI_DEF_XATTR 1

View File

@ -436,7 +436,7 @@ enum nft_set_elem_flags {
* @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data)
* @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes)
* @NFTA_SET_ELEM_FLAGS: bitmask of nft_set_elem_flags (NLA_U32)
* @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64)
* @NFTA_SET_ELEM_TIMEOUT: timeout value, zero means never times out (NLA_U64)
* @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64)
* @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
* @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes)
@ -1694,7 +1694,7 @@ enum nft_flowtable_flags {
*
* @NFTA_FLOWTABLE_TABLE: name of the table containing the expression (NLA_STRING)
* @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING)
* @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
* @NFTA_FLOWTABLE_HOOK: netfilter hook configuration (NLA_NESTED)
* @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
* @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
* @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)

View File

@ -16,10 +16,15 @@ struct nhmsg {
struct nexthop_grp {
__u32 id; /* nexthop id - must exist */
__u8 weight; /* weight of this nexthop */
__u8 resvd1;
__u8 weight_high; /* high order bits of weight */
__u16 resvd2;
};
static __inline__ __u16 nexthop_grp_weight(const struct nexthop_grp *entry)
{
return ((entry->weight_high << 8) | entry->weight) + 1;
}
enum {
NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group
* default type if not specified
@ -33,6 +38,9 @@ enum {
#define NHA_OP_FLAG_DUMP_STATS BIT(0)
#define NHA_OP_FLAG_DUMP_HW_STATS BIT(1)
/* Response OP_FLAGS. */
#define NHA_OP_FLAG_RESP_GRP_RESVD_0 BIT(31) /* Dump clears resvd fields. */
enum {
NHA_UNSPEC,
NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */

View File

@ -531,20 +531,24 @@ int is_idmapping_supported(const char *path) {
userns_fd = userns_acquire(uid_map, gid_map);
if (ERRNO_IS_NEG_NOT_SUPPORTED(userns_fd) || ERRNO_IS_NEG_PRIVILEGE(userns_fd))
return false;
if (userns_fd == -ENOSPC) {
log_debug_errno(userns_fd, "Failed to acquire new user namespace, user.max_user_namespaces seems to be exhausted or maybe even zero, assuming ID-mapping is not supported: %m");
return false;
}
if (userns_fd < 0)
return log_debug_errno(userns_fd, "ID-mapping supported namespace acquire failed for '%s' : %m", path);
return log_debug_errno(userns_fd, "Failed to acquire new user namespace for checking if '%s' supports ID-mapping: %m", path);
dir_fd = RET_NERRNO(open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (ERRNO_IS_NEG_NOT_SUPPORTED(dir_fd))
return false;
if (dir_fd < 0)
return log_debug_errno(dir_fd, "ID-mapping supported open failed for '%s' : %m", path);
return log_debug_errno(dir_fd, "Failed to open '%s', cannot determine if ID-mapping is supported: %m", path);
mount_fd = RET_NERRNO(open_tree(dir_fd, "", AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC));
if (ERRNO_IS_NEG_NOT_SUPPORTED(mount_fd) || ERRNO_IS_NEG_PRIVILEGE(mount_fd) || mount_fd == -EINVAL)
return false;
if (mount_fd < 0)
return log_debug_errno(mount_fd, "ID-mapping supported open_tree failed for '%s' : %m", path);
return log_debug_errno(mount_fd, "Failed to open mount tree '%s', cannot determine if ID-mapping is supported: %m", path);
r = RET_NERRNO(mount_setattr(mount_fd, "", AT_EMPTY_PATH,
&(struct mount_attr) {
@ -554,7 +558,7 @@ int is_idmapping_supported(const char *path) {
if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
return false;
if (r < 0)
return log_debug_errno(r, "ID-mapping supported setattr failed for '%s' : %m", path);
return log_debug_errno(r, "Failed to set mount attribute to '%s', cannot determine if ID-mapping is supported: %m", path);
return true;
}

View File

@ -71,6 +71,7 @@
#include "unit-serialize.h"
#include "user-util.h"
#include "utmp-wtmp.h"
#include "vpick.h"
static bool is_terminal_input(ExecInput i) {
return IN_SET(i,
@ -1938,6 +1939,25 @@ char** exec_context_get_restrict_filesystems(const ExecContext *c) {
return l ? TAKE_PTR(l) : strv_new(NULL);
}
int exec_context_has_vpicked_extensions(const ExecContext *context) {
int r;
assert(context);
FOREACH_ARRAY(mi, context->extension_images, context->n_extension_images) {
r = path_uses_vpick(mi->source);
if (r != 0)
return r;
}
STRV_FOREACH(ed, context->extension_directories) {
r = path_uses_vpick(*ed);
if (r != 0)
return r;
}
return 0;
}
void exec_status_start(ExecStatus *s, pid_t pid, const dual_timestamp *ts) {
assert(s);

View File

@ -559,6 +559,8 @@ char** exec_context_get_syscall_log(const ExecContext *c);
char** exec_context_get_address_families(const ExecContext *c);
char** exec_context_get_restrict_filesystems(const ExecContext *c);
int exec_context_has_vpicked_extensions(const ExecContext *context);
void exec_status_start(ExecStatus *s, pid_t pid, const dual_timestamp *ts);
void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status);
void exec_status_handoff(ExecStatus *s, const struct ucred *ucred, const dual_timestamp *ts);

View File

@ -37,6 +37,8 @@
#include "nulstr-util.h"
#include "os-util.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "selinux-util.h"
#include "socket-util.h"
#include "sort-util.h"
@ -3296,6 +3298,117 @@ bool ns_type_supported(NamespaceType type) {
return access(ns_proc, F_OK) == 0;
}
int refresh_extensions_in_namespace(
const PidRef *target,
const char *hierarchy_env,
const NamespaceParameters *p) {
const char *overlay_prefix = "/run/systemd/mount-rootfs";
_cleanup_(mount_list_done) MountList ml = {};
_cleanup_free_ char *extension_dir = NULL;
_cleanup_strv_free_ char **hierarchies = NULL;
MountInNamespaceFlags min_flags = 0;
int r;
assert(pidref_is_set(target));
assert(hierarchy_env);
assert(p);
log_debug("Refreshing extensions in-namespace for hierarchy '%s'", hierarchy_env);
extension_dir = path_join(p->private_namespace_dir, "unit-extensions");
if (!extension_dir)
return -ENOMEM;
min_flags |= MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY;
r = parse_env_extension_hierarchies(&hierarchies, hierarchy_env);
if (r < 0)
return r;
r = append_extensions(
&ml,
overlay_prefix,
p->private_namespace_dir,
hierarchies,
p->extension_images,
p->n_extension_images,
p->extension_directories);
if (r < 0)
return r;
if (ml.n_mounts == 0)
return 0;
r = safe_fork("(sd-ns-refresh-exts)",
FORK_DEATHSIG_SIGTERM | FORK_WAIT | FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE,
NULL);
if (r < 0)
return r;
if (r == 0) {
(void) mkdir_p_label(overlay_prefix, 0555);
/* This is effectively two rounds, since all the extensions come before overlays
* (setup_namespace() similarly relies on this property).
*
* (1) First, set up all the extension mounts in the child, which are not visible from the
* process. (2) Then, set up overlays for the sysext/confext hierarchies again using the new
* extension mounts as layers, and move them into the namespace. */
FOREACH_ARRAY(m, ml.mounts, ml.n_mounts) {
if (IN_SET(m->mode, MOUNT_EXTENSION_DIRECTORY, MOUNT_EXTENSION_IMAGE)) {
r = apply_one_mount(p->root_directory, m, p);
if (r < 0) {
log_debug_errno(r, "Failed to apply extension mount: %m");
_exit(EXIT_FAILURE);
}
} else if (m->mode == MOUNT_OVERLAY) {
_cleanup_free_ char *path_relative = NULL, *path_in_namespace = NULL;
r = apply_one_mount(p->root_directory, m, p);
if (r < 0)
_exit(EXIT_FAILURE);
if (r == 0) {
/* Tried to mount overlay, but it is now empty - umount it then. */
min_flags |= MOUNT_IN_NAMESPACE_UMOUNT;
}
/* bind_mount_in_namespace takes a src on the outside and a dest evaluated
* within the namespace. First, figure out where we want the overlay on top
* of within the namespace.
*/
r = path_make_relative(overlay_prefix, mount_entry_path(m), &path_relative);
if (r < 0) {
log_debug_errno(r, "Failed to make path relative: %m");
_exit(EXIT_FAILURE);
}
r = asprintf(&path_in_namespace, "%s/%s", empty_to_root(p->root_directory), path_relative);
if (r < 0) {
log_oom_debug();
_exit(EXIT_FAILURE);
}
r = bind_mount_in_namespace(
target,
p->propagate_dir,
p->incoming_dir,
/* src= */ mount_entry_path(m),
/* dest= */ path_in_namespace,
min_flags);
if (r < 0) {
log_debug_errno(
r,
"Failed to move overlay within %s->%s: %m",
mount_entry_path(m),
path_in_namespace);
_exit(EXIT_FAILURE);
}
}
}
_exit(EXIT_SUCCESS);
}
return 0;
}
static const char *const protect_home_table[_PROTECT_HOME_MAX] = {
[PROTECT_HOME_NO] = "no",
[PROTECT_HOME_YES] = "yes",

View File

@ -16,6 +16,7 @@ typedef struct MountImage MountImage;
#include "fs-util.h"
#include "macro.h"
#include "namespace-util.h"
#include "pidref.h"
#include "runtime-scope.h"
#include "string-util.h"
@ -250,3 +251,8 @@ const char* namespace_type_to_string(NamespaceType t) _const_;
NamespaceType namespace_type_from_string(const char *s) _pure_;
bool ns_type_supported(NamespaceType type);
int refresh_extensions_in_namespace(
const PidRef *target,
const char *hierarchy_env,
const NamespaceParameters *p);

View File

@ -21,6 +21,7 @@
#include "devnum-util.h"
#include "env-util.h"
#include "escape.h"
#include "execute.h"
#include "exec-credential.h"
#include "exit-status.h"
#include "fd-util.h"
@ -33,11 +34,13 @@
#include "manager.h"
#include "missing_audit.h"
#include "mount-util.h"
#include "namespace.h"
#include "open-file.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "runtime-scope.h"
#include "selinux-util.h"
#include "serialize.h"
#include "service.h"
@ -2709,6 +2712,67 @@ static void service_enter_reload_by_notify(Service *s) {
log_unit_warning(UNIT(s), "Failed to schedule propagation of reload, ignoring: %s", bus_error_message(&error, r));
}
static bool service_should_reload_extensions(Service *s) {
int r;
assert(s);
/* Only support this for notify-reload service types. */
if (s->type != SERVICE_NOTIFY_RELOAD)
return false;
/* TODO: Add support for user services, which can use
* ExtensionDirectories= + notify-reload. For now, skip for user
* services. */
if (UNIT(s)->manager->runtime_scope != RUNTIME_SCOPE_SYSTEM) {
log_unit_debug(UNIT(s), "Not reloading extensions for user services.");
return false;
}
r = exec_context_has_vpicked_extensions(&s->exec_context);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to determine if service should reload extensions, assuming false: %m");
return false;
}
return r > 0;
}
static int service_reload_extensions(Service *s) {
/* TODO: do this asynchronously */
_cleanup_free_ char *propagate_dir = NULL;
assert(s);
/* TODO: remove after adding support for user services */
assert(UNIT(s)->manager->runtime_scope == RUNTIME_SCOPE_SYSTEM);
if (!service_should_reload_extensions(s))
return 0;
propagate_dir = path_join("/run/systemd/propagate/", UNIT(s)->id);
if (!propagate_dir)
return -ENOMEM;
NamespaceParameters p = {
.private_namespace_dir = "/run/systemd",
.incoming_dir = "/run/systemd/incoming",
.propagate_dir = propagate_dir,
.runtime_scope = UNIT(s)->manager->runtime_scope,
.root_directory = s->exec_context.root_directory,
.extension_images = s->exec_context.extension_images,
.n_extension_images = s->exec_context.n_extension_images,
.extension_directories = s->exec_context.extension_directories,
.extension_image_policy = s->exec_context.extension_image_policy
};
/* Only reload confext, and not sysext, because it doesn't make sense
for program code to be swapped at reload. */
return refresh_extensions_in_namespace(
unit_main_pid(UNIT(s)),
"SYSTEMD_CONFEXT_HIERARCHIES",
&p);
}
static void service_enter_reload(Service *s) {
bool killed = false;
int r;
@ -2720,6 +2784,14 @@ static void service_enter_reload(Service *s) {
usec_t ts = now(CLOCK_MONOTONIC);
/* If we have confexts extensions, try to reload vpick'd confext extensions, which is particularly
* beneficial for notify-reload services that could potentially pick up a new version of its
* configuration.
*/
r = service_reload_extensions(s);
if (r < 0)
log_unit_warning_errno(UNIT(s), r, "Failed to reload confexts, ignoring: %m");
if (s->type == SERVICE_NOTIFY_RELOAD && pidref_is_set(&s->main_pid)) {
r = pidref_kill_and_sigcont(&s->main_pid, s->reload_signal);
if (r < 0) {

View File

@ -98,16 +98,11 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
}
}
#if HAVE_SYSV_COMPAT
else if (streq(key, "fastboot") && !value) {
log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line.");
else if (streq(key, "fastboot") && !value)
arg_skip = true;
} else if (streq(key, "forcefsck") && !value) {
log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line.");
else if (streq(key, "forcefsck") && !value)
arg_force = true;
}
#endif
return 0;
}

View File

@ -108,6 +108,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --ucode=PATH Path to microcode image file %7$s .ucode\n"
" --splash=PATH Path to splash bitmap file %7$s .splash\n"
" --dtb=PATH Path to DeviceTree file %7$s .dtb\n"
" --dtbauto=PATH Path to DeviceTree file for auto selection %7$s .dtbauto\n"
" --uname=PATH Path to 'uname -r' file %7$s .uname\n"
" --sbat=PATH Path to SBAT file %7$s .sbat\n"
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"

View File

@ -2280,10 +2280,9 @@ static int copy_devnode_one(const char *dest, const char *node, bool ignore_mkno
r = path_extract_directory(from, &parent);
if (r < 0)
return log_error_errno(r, "Failed to extract directory from %s: %m", from);
if (!path_equal(parent, "/dev/")) {
if (userns_mkdir(dest, parent, 0755, 0, 0) < 0)
r = userns_mkdir(dest, parent, 0755, 0, 0);
if (r < 0)
return log_error_errno(r, "Failed to create directory %s: %m", parent);
}
if (mknod(to, st.st_mode, st.st_rdev) < 0) {
r = -errno; /* Save the original error code. */
@ -4654,7 +4653,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred || ucred->pid != inner_child_pid) {
log_debug("Received notify message without valid credentials. Ignoring.");
log_debug("Received notify message from process that is not the payload's PID 1. Ignoring.");
return 0;
}

View File

@ -36,14 +36,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
arg_skip = true;
else
log_warning("Invalid quotacheck.mode= value, ignoring: %s", value);
}
#if HAVE_SYSV_COMPAT
else if (streq(key, "forcequotacheck") && !value) {
log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line. Proceeding anyway.");
} else if (streq(key, "forcequotacheck") && !value)
arg_force = true;
}
#endif
return 0;
}

View File

@ -1132,7 +1132,7 @@ static int mount_in_namespace(
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
pid_t child;
if (flags & MOUNT_IN_NAMESPACE_IS_IMAGE) {
if (!(flags & MOUNT_IN_NAMESPACE_UMOUNT) && flags & MOUNT_IN_NAMESPACE_IS_IMAGE) {
r = verity_dissect_and_mount(
chased_src_fd,
chased_src_path,
@ -1150,7 +1150,7 @@ static int mount_in_namespace(
return log_debug_errno(r,
"Failed to dissect and mount image '%s': %m",
chased_src_path);
} else {
} else if (!(flags & MOUNT_IN_NAMESPACE_UMOUNT)) {
new_mount_fd = open_tree(
chased_src_fd,
"",
@ -1189,6 +1189,18 @@ static int mount_in_namespace(
if (r == 0) {
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
if (flags & MOUNT_IN_NAMESPACE_UMOUNT) {
r = umount_verbose(LOG_DEBUG, dest, UMOUNT_NOFOLLOW);
if (r < 0) {
(void) write(errno_pipe_fd[1], &r, sizeof(r));
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
if (flags & MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY)
(void) mkdir_parents(dest, 0755);

View File

@ -119,6 +119,7 @@ typedef enum MountInNamespaceFlags {
MOUNT_IN_NAMESPACE_READ_ONLY = 1 << 0,
MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY = 1 << 1,
MOUNT_IN_NAMESPACE_IS_IMAGE = 1 << 2,
MOUNT_IN_NAMESPACE_UMOUNT = 1 << 3,
} MountInNamespaceFlags;
int bind_mount_in_namespace(

View File

@ -681,6 +681,41 @@ int path_pick_update_warn(
return 1;
}
int path_uses_vpick(const char *path) {
_cleanup_free_ char *dir = NULL, *parent = NULL, *fname = NULL;
int r;
assert(path);
r = path_extract_filename(path, &fname);
if (r == -EADDRNOTAVAIL)
return 0;
if (r < 0)
return r;
/* ...PATH/NAME.SUFFIX.v */
if (endswith(fname, ".v"))
return 1;
/* ...PATH.v/NAME___.SUFFIX */
if (!strrstr(fname, "___"))
return 0;
r = path_extract_directory(path, &dir);
if (IN_SET(r, -EDESTADDRREQ, -EADDRNOTAVAIL)) /* only filename specified (no dir), or root or "." */
return 0;
if (r < 0)
return r;
r = path_extract_filename(dir, &parent);
if (r == -EADDRNOTAVAIL)
return 0;
if (r < 0)
return r;
return !!endswith(parent, ".v");
}
const PickFilter pick_filter_image_raw = {
.type_mask = (UINT32_C(1) << DT_REG) | (UINT32_C(1) << DT_BLK),
.architecture = _ARCHITECTURE_INVALID,

View File

@ -56,6 +56,8 @@ int path_pick_update_warn(
PickFlags flags,
PickResult *ret);
int path_uses_vpick(const char *path);
extern const PickFilter pick_filter_image_raw;
extern const PickFilter pick_filter_image_dir;
extern const PickFilter pick_filter_image_any;

View File

@ -98,15 +98,17 @@ static int delete_dm(DeviceMapper *m) {
assert(major(m->devnum) != 0);
assert(m->path);
fd = open(m->path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
log_debug_errno(errno, "Failed to open DM block device %s for syncing, ignoring: %m", m->path);
else {
(void) sync_with_progress(fd);
fd = safe_close(fd);
}
fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
if (fd < 0)
return -errno;
_cleanup_close_ int block_fd = open(m->path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (block_fd < 0)
log_debug_errno(errno, "Failed to open DM block device %s for syncing, ignoring: %m", m->path);
else
(void) sync_with_progress(block_fd);
return log_debug_errno(errno, "Failed to open /dev/mapper/control: %m");
return RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) {
.version = {

View File

@ -211,10 +211,8 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
continue;
errno = 0;
if (sscanf(line, "%*s %llu %*s", &ull) != 1) {
log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field, ignoring: %m");
return false;
}
if (sscanf(line, "%*s %llu %*s", &ull) != 1)
return log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field: %m");
val += ull;
}

View File

@ -168,4 +168,27 @@ TEST(path_pick) {
assert_se(result.architecture == ARCHITECTURE_S390);
}
TEST(path_uses_vpick) {
assert_se(path_uses_vpick("foo.v") > 0);
assert_se(path_uses_vpick("path/to/foo.v") > 0);
assert_se(path_uses_vpick("./path/to/foo.v") > 0);
assert_se(path_uses_vpick("path/to.v/foo.v") > 0);
assert_se(path_uses_vpick("path/to/foo.raw.v") > 0);
assert_se(path_uses_vpick("/var/lib/machines/mymachine.raw.v/") > 0);
assert_se(path_uses_vpick("path/to.v/foo___.hi/a.v") > 0);
assert_se(!path_uses_vpick("path/to/foo.mp4.vtt"));
assert_se(!path_uses_vpick("path/to/foo.mp4.v.1"));
assert_se(!path_uses_vpick("path/to.v/a"));
assert_se(path_uses_vpick("to.v/foo___.raw") > 0);
assert_se(path_uses_vpick("path/to.v/foo___.raw") > 0);
assert_se(!path_uses_vpick("path/to/foo___.raw"));
assert_se(!path_uses_vpick("path/to.v/foo__"));
assert_se(!path_uses_vpick("foo___.raw"));
assert_se(path_uses_vpick("/") < 1);
assert_se(path_uses_vpick(".") < 1);
assert_se(path_uses_vpick("") < 1);
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -960,10 +960,13 @@ exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ {{ s/^.*=/
# wait until devices got created
for _ in range(50):
out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.if_router])
if b'state UP' in out and b'scope global' in out:
if subprocess.run(['ip', 'link', 'show', 'dev', self.if_router],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0:
break
time.sleep(0.1)
else:
subprocess.call(['ip', 'link', 'show', 'dev', self.if_router])
self.fail('Timed out waiting for {ifr} created.'.format(ifr=self.if_router))
def shutdown_iface(self):
'''Remove test interface and stop DHCP server'''

View File

@ -518,6 +518,72 @@ rm -rf "$VDIR" "$EMPTY_VDIR"
systemd-dissect --umount "$IMAGE_DIR/app0"
systemd-dissect --umount "$IMAGE_DIR/app1"
# Check reloading refreshes vpick extensions
VBASE="vtest$RANDOM"
VDIR="/tmp/${VBASE}.v"
mkdir "$VDIR"
cat >/run/systemd/system/testservice-50g.service <<EOF
[Service]
Type=notify-reload
EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
ExtensionDirectories=${VDIR}
ExecStart=bash -c ' \\
trap "{ \\
systemd-notify --reloading; \\
ls /etc | grep marker; \\
systemd-notify --ready; \\
}" SIGHUP; \\
systemd-notify --ready; \\
while true; do sleep 1; done; \\
'
EOF
mkdir -p "$VDIR/${VBASE}_1/etc/extension-release.d/"
echo "ID=_any" >"$VDIR/${VBASE}_1/etc/extension-release.d/extension-release.${VBASE}_1"
touch "$VDIR/${VBASE}_1/etc/${VBASE}_1.marker"
systemctl start testservice-50g.service
systemctl is-active testservice-50g.service
# First reload; at reload time, the marker file in /etc should be picked up.
systemctl try-reload-or-restart testservice-50g.service
journalctl -b -u testservice-50g | grep -q -F "${VBASE}_1.marker"
# Make a version 2 and reload again; this time we should see the v2 marker
mkdir -p "$VDIR/${VBASE}_2/etc/extension-release.d/"
echo "ID=_any" >"$VDIR/${VBASE}_2/etc/extension-release.d/extension-release.${VBASE}_2"
touch "$VDIR/${VBASE}_2/etc/${VBASE}_2.marker"
systemctl try-reload-or-restart testservice-50g.service
journalctl --sync
journalctl -b -u testservice-50g | grep -q -F "${VBASE}_2.marker"
# Do it for a couple more times (to make sure we're tearing down old overlays)
for _ in {1..5}; do systemctl reload testservice-50g.service; done
systemctl stop testservice-50g.service
# Repeat the same vpick notify-reload test with ExtensionImages= (keeping the
# same VBASE and reusing VDIR files for convenience, but using .raw extensions
# this time)
VDIR2="/tmp/${VBASE}.raw.v"
mkdir "$VDIR2"
cp /run/systemd/system/testservice-50g.service /run/systemd/system/testservice-50h.service
sed -i "s%ExtensionDirectories=.*%ExtensionImages=$VDIR2%g" \
/run/systemd/system/testservice-50h.service
mksquashfs "$VDIR/${VBASE}_1" "$VDIR2/${VBASE}_1.raw"
systemctl start testservice-50h.service
systemctl is-active testservice-50h.service
# First reload should pick up the v1 marker
systemctl try-reload-or-restart testservice-50h.service
journalctl --sync
journalctl -b -u testservice-50h | grep -q -F "${VBASE}_1.marker"
# Second reload should pick up the v2 marker
mksquashfs "$VDIR/${VBASE}_2" "$VDIR2/${VBASE}_2.raw"
systemctl try-reload-or-restart testservice-50h.service
journalctl --sync
journalctl -b -u testservice-50h | grep -q -F "${VBASE}_2.marker"
# Test that removing all the extensions don't cause any issues
rm -rf "${VDIR2:?}"/*
systemctl try-reload-or-restart testservice-50h.service
systemctl is-active testservice-50h.service
systemctl stop testservice-50h.service
rm -rf "$VDIR" "$VDIR2"
# Test that an extension consisting of an empty directory under /etc/extensions/ takes precedence
mkdir -p /var/lib/extensions/
ln -s /tmp/app-nodistro.raw /var/lib/extensions/app-nodistro.raw