diff options
Diffstat (limited to 'src')
42 files changed, 348 insertions, 205 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c index aa1657c118..52a29e2f7b 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -289,7 +289,8 @@ int write_string_file_full( const char *fn, const char *line, WriteStringFileFlags flags, - const struct timespec *ts) { + const struct timespec *ts, + const char *label_fn) { bool call_label_ops_post = false, made_file = false; _cleanup_fclose_ FILE *f = NULL; @@ -321,7 +322,8 @@ int write_string_file_full( mode_t mode = write_string_file_flags_to_mode(flags); if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) { - r = label_ops_pre(dir_fd, fn, mode); + const char *lookup = label_fn ? label_fn : fn; + r = label_ops_pre(dir_fd, lookup, mode); if (r < 0) goto fail; diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 8f54491c12..08017f8270 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -51,12 +51,13 @@ int write_string_stream_full(FILE *f, const char *line, WriteStringFileFlags fla static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) { return write_string_stream_full(f, line, flags, /* ts= */ NULL); } -int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts); + +int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts, const char *label_fn); static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) { - return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL); + return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL); } static inline int write_string_file_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags) { - return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL); + return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL); } int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4); diff --git a/src/basic/linux/auto_fs.h b/src/basic/linux/auto_fs.h index 623015682a..fedff6e751 100644 --- a/src/basic/linux/auto_fs.h +++ b/src/basic/linux/auto_fs.h @@ -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 diff --git a/src/basic/linux/bpf.h b/src/basic/linux/bpf.h index f4d7e495dd..aa381a3d98 100644 --- a/src/basic/linux/bpf.h +++ b/src/basic/linux/bpf.h @@ -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__ */ diff --git a/src/basic/linux/const.h b/src/basic/linux/const.h index 1eb84b5087..2122610de7 100644 --- a/src/basic/linux/const.h +++ b/src/basic/linux/const.h @@ -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)) diff --git a/src/basic/linux/ethtool.h b/src/basic/linux/ethtool.h index 5aa2ae0a4b..a32293ba20 100644 --- a/src/basic/linux/ethtool.h +++ b/src/basic/linux/ethtool.h @@ -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 */ diff --git a/src/basic/linux/fib_rules.h b/src/basic/linux/fib_rules.h index 232df14e12..a6924dd3af 100644 --- a/src/basic/linux/fib_rules.h +++ b/src/basic/linux/fib_rules.h @@ -67,6 +67,7 @@ enum { FRA_IP_PROTO, /* ip proto */ FRA_SPORT_RANGE, /* sport */ FRA_DPORT_RANGE, /* dport */ + FRA_DSCP, /* dscp */ __FRA_MAX }; diff --git a/src/basic/linux/if_packet.h b/src/basic/linux/if_packet.h index 9efc42382f..1d2718dd96 100644 --- a/src/basic/linux/if_packet.h +++ b/src/basic/linux/if_packet.h @@ -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 diff --git a/src/basic/linux/in.h b/src/basic/linux/in.h index 43cfcb010c..a7d41bb6c6 100644 --- a/src/basic/linux/in.h +++ b/src/basic/linux/in.h @@ -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 diff --git a/src/basic/linux/libc-compat.h b/src/basic/linux/libc-compat.h index a1599911e7..e25cd3f486 100644 --- a/src/basic/linux/libc-compat.h +++ b/src/basic/linux/libc-compat.h @@ -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 diff --git a/src/basic/linux/netfilter/nf_tables.h b/src/basic/linux/netfilter/nf_tables.h index 639894ed1b..9e90793213 100644 --- a/src/basic/linux/netfilter/nf_tables.h +++ b/src/basic/linux/netfilter/nf_tables.h @@ -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) diff --git a/src/basic/linux/nexthop.h b/src/basic/linux/nexthop.h index 7e340bec94..afbd064f8f 100644 --- a/src/basic/linux/nexthop.h +++ b/src/basic/linux/nexthop.h @@ -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 */ diff --git a/src/basic/missing_namespace.h b/src/basic/missing_namespace.h new file mode 100644 index 0000000000..318c0143b8 --- /dev/null +++ b/src/basic/missing_namespace.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +/* Root namespace inode numbers, as per include/linux/proc_ns.h in the kernel source tree, since v3.8: + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=98f842e675f96ffac96e6c50315790912b2812be */ + +#define PROC_IPC_INIT_INO ((ino_t) UINT32_C(0xEFFFFFFF)) +#define PROC_UTS_INIT_INO ((ino_t) UINT32_C(0xEFFFFFFE)) +#define PROC_USER_INIT_INO ((ino_t) UINT32_C(0xEFFFFFFD)) +#define PROC_PID_INIT_INO ((ino_t) UINT32_C(0xEFFFFFFC)) +#define PROC_CGROUP_INIT_INO ((ino_t) UINT32_C(0xEFFFFFFB)) +#define PROC_TIME_INIT_INO ((ino_t) UINT32_C(0xEFFFFFFA)) diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index 2c61506149..5d02ac6025 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -12,6 +12,7 @@ #include "fileio.h" #include "missing_fs.h" #include "missing_magic.h" +#include "missing_namespace.h" #include "missing_sched.h" #include "missing_syscall.h" #include "mountpoint-util.h" @@ -23,17 +24,17 @@ #include "user-util.h" const struct namespace_info namespace_info[_NAMESPACE_TYPE_MAX + 1] = { - [NAMESPACE_CGROUP] = { "cgroup", "ns/cgroup", CLONE_NEWCGROUP, }, - [NAMESPACE_IPC] = { "ipc", "ns/ipc", CLONE_NEWIPC, }, - [NAMESPACE_NET] = { "net", "ns/net", CLONE_NEWNET, }, + [NAMESPACE_CGROUP] = { "cgroup", "ns/cgroup", CLONE_NEWCGROUP, PROC_CGROUP_INIT_INO }, + [NAMESPACE_IPC] = { "ipc", "ns/ipc", CLONE_NEWIPC, PROC_IPC_INIT_INO }, + [NAMESPACE_NET] = { "net", "ns/net", CLONE_NEWNET, 0 }, /* So, the mount namespace flag is called CLONE_NEWNS for historical * reasons. Let's expose it here under a more explanatory name: "mnt". * This is in-line with how the kernel exposes namespaces in /proc/$PID/ns. */ - [NAMESPACE_MOUNT] = { "mnt", "ns/mnt", CLONE_NEWNS, }, - [NAMESPACE_PID] = { "pid", "ns/pid", CLONE_NEWPID, }, - [NAMESPACE_USER] = { "user", "ns/user", CLONE_NEWUSER, }, - [NAMESPACE_UTS] = { "uts", "ns/uts", CLONE_NEWUTS, }, - [NAMESPACE_TIME] = { "time", "ns/time", CLONE_NEWTIME, }, + [NAMESPACE_MOUNT] = { "mnt", "ns/mnt", CLONE_NEWNS, 0 }, + [NAMESPACE_PID] = { "pid", "ns/pid", CLONE_NEWPID, PROC_PID_INIT_INO }, + [NAMESPACE_USER] = { "user", "ns/user", CLONE_NEWUSER, PROC_USER_INIT_INO }, + [NAMESPACE_UTS] = { "uts", "ns/uts", CLONE_NEWUTS, PROC_UTS_INIT_INO }, + [NAMESPACE_TIME] = { "time", "ns/time", CLONE_NEWTIME, PROC_TIME_INIT_INO }, { /* Allow callers to iterate over the array without using _NAMESPACE_TYPE_MAX. */ }, }; @@ -479,6 +480,28 @@ int namespace_open_by_type(NamespaceType type) { return fd; } +int namespace_is_init(NamespaceType type) { + int r; + + assert(type >= 0); + assert(type <= _NAMESPACE_TYPE_MAX); + + if (namespace_info[type].root_inode == 0) + return -EBADR; /* Cannot answer this question */ + + const char *p = pid_namespace_path(0, type); + + struct stat st; + r = RET_NERRNO(stat(p, &st)); + if (r == -ENOENT) + /* If the /proc/ns/<type> API is not around in /proc/ then ns is off in the kernel and we are in the init ns */ + return proc_mounted() == 0 ? -ENOSYS : true; + if (r < 0) + return r; + + return st.st_ino == namespace_info[type].root_inode; +} + int is_our_namespace(int fd, NamespaceType request_type) { int clone_flag; @@ -531,20 +554,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 +581,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; } diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h index 105bab6fdb..e92d407864 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -24,6 +24,7 @@ extern const struct namespace_info { const char *proc_name; const char *proc_path; unsigned int clone_flag; + ino_t root_inode; } namespace_info[_NAMESPACE_TYPE_MAX + 1]; int pidref_namespace_open( @@ -74,6 +75,8 @@ int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_r int namespace_open_by_type(NamespaceType type); +int namespace_is_init(NamespaceType type); + int is_our_namespace(int fd, NamespaceType type); int is_idmapping_supported(const char *path); diff --git a/src/basic/virt.c b/src/basic/virt.c index fd0c353791..9dcafb9dea 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -585,6 +585,14 @@ static int running_in_cgroupns(void) { if (!cg_ns_supported()) return false; + r = namespace_is_init(NAMESPACE_CGROUP); + if (r < 0) + log_debug_errno(r, "Failed to test if in root cgroup namespace, ignoring: %m"); + else if (r > 0) + return false; + + // FIXME: We really should drop the heuristics below. + r = cg_all_unified(); if (r < 0) return r; @@ -645,6 +653,16 @@ static int running_in_cgroupns(void) { } } +static int running_in_pidns(void) { + int r; + + r = namespace_is_init(NAMESPACE_PID); + if (r < 0) + return log_debug_errno(r, "Failed to test if in root PID namespace, ignoring: %m"); + + return !r; +} + static Virtualization detect_container_files(void) { static const struct { const char *file_path; @@ -790,12 +808,21 @@ check_files: r = running_in_cgroupns(); if (r > 0) { + log_debug("Running in a cgroup namespace, assuming unknown container manager."); v = VIRTUALIZATION_CONTAINER_OTHER; goto finish; } if (r < 0) log_debug_errno(r, "Failed to detect cgroup namespace: %m"); + /* Finally, the root pid namespace has an hardcoded inode number of 0xEFFFFFFC since kernel 3.8, so + * if all else fails we can check the inode number of our pid namespace and compare it. */ + if (running_in_pidns() > 0) { + log_debug("Running in a pid namespace, assuming unknown container manager."); + v = VIRTUALIZATION_CONTAINER_OTHER; + goto finish; + } + /* If none of that worked, give up, assume no container manager. */ v = VIRTUALIZATION_NONE; goto finish; @@ -863,6 +890,14 @@ int running_in_userns(void) { _cleanup_free_ char *line = NULL; int r; + r = namespace_is_init(NAMESPACE_USER); + if (r < 0) + log_debug_errno(r, "Failed to test if in root user namespace, ignoring: %m"); + else if (r > 0) + return false; + + // FIXME: We really should drop the heuristics below. + r = userns_has_mapping("/proc/self/uid_map"); if (r != 0) return r; diff --git a/src/core/device.c b/src/core/device.c index 03a730f624..a8921e91c3 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -1048,9 +1048,6 @@ static void device_enumerate(Manager *m) { _cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL; Device *d; - if (device_is_processed(dev) <= 0) - continue; - if (device_setup_units(m, dev, &ready_units, ¬_ready_units) < 0) continue; diff --git a/src/core/service.c b/src/core/service.c index 5b0bb76af2..34d40c6950 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3426,14 +3426,12 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, 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) { log_unit_debug_errno(u, r, "Failed to store deserialized fd '%s', ignoring: %m", fdn); return 0; } - - TAKE_FD(fd); } else if (streq(key, "extra-fd")) { _cleanup_free_ char *fdv = NULL, *fdn = NULL; _cleanup_close_ int fd = -EBADF; diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index e1f72a3529..dccb320c5d 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -193,7 +193,7 @@ static int help(void) { "\n%3$sSimple Enrollment:%4$s\n" " --password Enroll a user-supplied password\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" " Specify PKCS#11 security token URI\n" "\n%3$sFIDO2 Enrollment:%4$s\n" diff --git a/src/cryptsetup/cryptsetup-pkcs11.c b/src/cryptsetup/cryptsetup-pkcs11.c index 3443b8f585..c7ecca865e 100644 --- a/src/cryptsetup/cryptsetup-pkcs11.c +++ b/src/cryptsetup/cryptsetup-pkcs11.c @@ -16,6 +16,7 @@ #include "fileio.h" #include "format-util.h" #include "hexdecoct.h" +#include "iovec-util.h" #include "macro.h" #include "memory-util.h" #include "parse-util.h" @@ -31,8 +32,7 @@ int decrypt_pkcs11_key( const char *key_file, /* We either expect key_file and associated parameters to be set (for file keys) … */ size_t key_file_size, uint64_t key_file_offset, - const void *key_data, /* … or key_data and key_data_size (for literal keys) */ - size_t key_data_size, + const struct iovec *key_data, /* … or literal keys via key_data */ usec_t until, AskPasswordFlags askpw_flags, void **ret_decrypted_key, @@ -47,15 +47,15 @@ int decrypt_pkcs11_key( assert(friendly_name); assert(pkcs11_uri); - assert(key_file || key_data); + assert(key_file || iovec_is_set(key_data)); assert(ret_decrypted_key); assert(ret_decrypted_key_size); /* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */ - if (key_data) { - data.encrypted_key = (void*) key_data; - data.encrypted_key_size = key_data_size; + if (iovec_is_set(key_data)) { + data.encrypted_key = (void*) key_data->iov_base; + data.encrypted_key_size = key_data->iov_len; data.free_encrypted_key = false; } else { diff --git a/src/cryptsetup/cryptsetup-pkcs11.h b/src/cryptsetup/cryptsetup-pkcs11.h index 22e6992582..83a2b54be3 100644 --- a/src/cryptsetup/cryptsetup-pkcs11.h +++ b/src/cryptsetup/cryptsetup-pkcs11.h @@ -16,8 +16,7 @@ int decrypt_pkcs11_key( const char *key_file, size_t key_file_size, uint64_t key_file_offset, - const void *key_data, - size_t key_data_size, + const struct iovec *key_data, usec_t until, AskPasswordFlags askpw_flags, void **ret_decrypted_key, @@ -39,8 +38,7 @@ static inline int decrypt_pkcs11_key( const char *key_file, size_t key_file_size, uint64_t key_file_offset, - const void *key_data, - size_t key_data_size, + const struct iovec *key_data, usec_t until, AskPasswordFlags askpw_flags, void **ret_decrypted_key, diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index a415c3e6d7..ee93fd3dca 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -1471,8 +1471,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2( struct crypt_device *cd, const char *name, const char *key_file, - const void *key_data, - size_t key_data_size, + const struct iovec *key_data, usec_t until, uint32_t flags, bool pass_volume_key) { @@ -1489,7 +1488,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2( assert(name); assert(arg_fido2_device || arg_fido2_device_auto); - if (arg_fido2_cid && !key_file && !key_data) + if (arg_fido2_cid && !key_file && !iovec_is_set(key_data)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "FIDO2 mode with manual parameters selected, but no keyfile specified, refusing."); @@ -1513,7 +1512,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2( arg_fido2_rp_id, arg_fido2_cid, arg_fido2_cid_size, key_file, arg_keyfile_size, arg_keyfile_offset, - key_data, key_data_size, + key_data, until, arg_fido2_manual_flags, "cryptsetup.fido2-pin", @@ -1623,8 +1622,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11( struct crypt_device *cd, const char *name, const char *key_file, - const void *key_data, - size_t key_data_size, + const struct iovec *key_data, usec_t until, uint32_t flags, bool pass_volume_key) { @@ -1635,6 +1633,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11( _cleanup_(erase_and_freep) void *decrypted_key = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_free_ void *discovered_key = NULL; + struct iovec discovered_key_data = {}; int keyslot = arg_key_slot, r; const char *uri = NULL; bool use_libcryptsetup_plugin = use_token_plugins(); @@ -1653,13 +1652,13 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11( return r; uri = discovered_uri; - key_data = discovered_key; - key_data_size = discovered_key_size; + discovered_key_data = IOVEC_MAKE(discovered_key, discovered_key_size); + key_data = &discovered_key_data; } } else { uri = arg_pkcs11_uri; - if (!key_file && !key_data) + if (!key_file && !iovec_is_set(key_data)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing."); } @@ -1682,7 +1681,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11( friendly, uri, key_file, arg_keyfile_size, arg_keyfile_offset, - key_data, key_data_size, + key_data, until, arg_ask_password_flags, &decrypted_key, &decrypted_key_size); @@ -2231,9 +2230,9 @@ static int attach_luks_or_plain_or_bitlk( if (token_type == TOKEN_TPM2) return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, until, flags, pass_volume_key); if (token_type == TOKEN_FIDO2) - return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data->iov_base, key_data->iov_len, until, flags, pass_volume_key); + return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data, until, flags, pass_volume_key); if (token_type == TOKEN_PKCS11) - return attach_luks_or_plain_or_bitlk_by_pkcs11(cd, name, key_file, key_data->iov_base, key_data->iov_len, until, flags, pass_volume_key); + return attach_luks_or_plain_or_bitlk_by_pkcs11(cd, name, key_file, key_data, until, flags, pass_volume_key); if (key_data) return attach_luks_or_plain_or_bitlk_by_key_data(cd, name, key_data, flags, pass_volume_key); if (key_file) diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 4ec8989a3f..c8dea245c8 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -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; } diff --git a/src/import/curl-util.c b/src/import/curl-util.c index cc97ce6b55..85c4f9b462 100644 --- a/src/import/curl-util.c +++ b/src/import/curl-util.c @@ -75,6 +75,10 @@ static int curl_glue_socket_callback(CURL *curl, curl_socket_t s, int action, vo return 0; } + /* Don't configure io event source anymore when the event loop is dead already. */ + if (g->event && sd_event_get_state(g->event) == SD_EVENT_FINISHED) + return 0; + r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops); if (r < 0) { log_oom(); diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c index c7a8a504f2..150ce4edda 100644 --- a/src/libsystemd/sd-varlink/sd-varlink.c +++ b/src/libsystemd/sd-varlink/sd-varlink.c @@ -1698,7 +1698,8 @@ _public_ int sd_varlink_get_events(sd_varlink *v) { ret |= EPOLLIN; if (!v->write_disconnected && - v->output_buffer_size > 0) + (v->output_queue || + v->output_buffer_size > 0)) ret |= EPOLLOUT; return ret; diff --git a/src/libsystemd/sd-varlink/varlink-util.c b/src/libsystemd/sd-varlink/varlink-util.c index 971be643e8..b16d4bddb6 100644 --- a/src/libsystemd/sd-varlink/varlink-util.c +++ b/src/libsystemd/sd-varlink/varlink-util.c @@ -16,7 +16,7 @@ int varlink_get_peer_pidref(sd_varlink *v, PidRef *ret) { int pidfd = sd_varlink_get_peer_pidfd(v); if (pidfd < 0) { - if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd)) + if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd) && pidfd != -EINVAL) return pidfd; pid_t pid; diff --git a/src/measure/measure.c b/src/measure/measure.c index 979426c18f..e583444e0b 100644 --- a/src/measure/measure.c +++ b/src/measure/measure.c @@ -101,18 +101,19 @@ static int help(int argc, char *argv[], void *userdata) { " -j Same as --json=pretty on tty, --json=short otherwise\n" " --append=PATH Load specified JSON signature, and append new signature to it\n" "\n%3$sUKI PE Section Options:%4$s %3$sUKI PE Section%4$s\n" - " --linux=PATH Path to Linux kernel image file %7$s .linux\n" - " --osrel=PATH Path to os-release file %7$s .osrel\n" - " --cmdline=PATH Path to file with kernel command line %7$s .cmdline\n" - " --initrd=PATH Path to initrd image file %7$s .initrd\n" - " --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" - " --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" - " --profile=PATH Path to profile file %7$s .profile\n" - " --hwids=PATH Path to HWIDs file %7$s .hwids\n" + " --linux=PATH Path to Linux kernel image file %7$s .linux\n" + " --osrel=PATH Path to os-release file %7$s .osrel\n" + " --cmdline=PATH Path to file with kernel command line %7$s .cmdline\n" + " --initrd=PATH Path to initrd image file %7$s .initrd\n" + " --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" + " --profile=PATH Path to profile file %7$s .profile\n" + " --hwids=PATH Path to HWIDs file %7$s .hwids\n" "\nSee the %2$s for details.\n", program_invocation_short_name, link, diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 5dd289c1b4..91700d9282 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -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) - return log_error_errno(r, "Failed to create directory %s: %m", parent); - } + 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; } diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c index d46f280bf4..63940142ac 100644 --- a/src/quotacheck/quotacheck.c +++ b/src/quotacheck/quotacheck.c @@ -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; } diff --git a/src/shared/cryptsetup-fido2.c b/src/shared/cryptsetup-fido2.c index 9ac728594a..1e1ef6dec0 100644 --- a/src/shared/cryptsetup-fido2.c +++ b/src/shared/cryptsetup-fido2.c @@ -24,8 +24,7 @@ int acquire_fido2_key( const char *key_file, size_t key_file_size, uint64_t key_file_offset, - const void *key_data, - size_t key_data_size, + const struct iovec *key_data, usec_t until, Fido2EnrollFlags required, const char *askpw_credential, @@ -45,10 +44,10 @@ int acquire_fido2_key( "Local verification is required to unlock this volume, but the 'headless' parameter was set."); assert(cid); - assert(key_file || key_data); + assert(key_file || iovec_is_set(key_data)); - if (key_data) - salt = IOVEC_MAKE(key_data, key_data_size); + if (iovec_is_set(key_data)) + salt = *key_data; else { if (key_file_size > 0) log_debug("Ignoring 'keyfile-size=' option for a FIDO2 salt file."); @@ -252,7 +251,7 @@ int acquire_fido2_key_auto( /* key_file= */ NULL, /* salt is read from LUKS header instead of key_file */ /* key_file_size= */ 0, /* key_file_offset= */ 0, - salt, salt_size, + &IOVEC_MAKE(salt, salt_size), until, required, "cryptsetup.fido2-pin", diff --git a/src/shared/cryptsetup-fido2.h b/src/shared/cryptsetup-fido2.h index bd25566806..86ac30c766 100644 --- a/src/shared/cryptsetup-fido2.h +++ b/src/shared/cryptsetup-fido2.h @@ -20,8 +20,7 @@ int acquire_fido2_key( const char *key_file, size_t key_file_size, uint64_t key_file_offset, - const void *key_data, - size_t key_data_size, + const struct iovec *key_data, usec_t until, Fido2EnrollFlags required, const char *askpw_credential, @@ -52,8 +51,7 @@ static inline int acquire_fido2_key( const char *key_file, size_t key_file_size, uint64_t key_file_offset, - const void *key_data, - size_t key_data_size, + const struct iovec *key_data, usec_t until, Fido2EnrollFlags required, const char *askpw_credential, diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index b0ea2c9e5f..77cd7dbcaf 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -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_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 */ #define TPM2_PCR_INDEX_DEFAULT UINT32_C(7) diff --git a/src/shutdown/detach-dm.c b/src/shutdown/detach-dm.c index bddd748d63..88e6a47a27 100644 --- a/src/shutdown/detach-dm.c +++ b/src/shutdown/detach-dm.c @@ -98,15 +98,17 @@ static int delete_dm(DeviceMapper *m) { assert(major(m->devnum) != 0); assert(m->path); - fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC); + fd = open(m->path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); 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); + else { + (void) sync_with_progress(fd); + fd = safe_close(fd); + } + + fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC); + if (fd < 0) + return log_debug_errno(errno, "Failed to open /dev/mapper/control: %m"); return RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) { .version = { diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c index 57bb9a82d0..e26a8579c5 100644 --- a/src/shutdown/shutdown.c +++ b/src/shutdown/shutdown.c @@ -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; } diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 0adfab253c..aab1f972a4 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include <errno.h> #include <fcntl.h> #include <getopt.h> #include <linux/loop.h> @@ -45,6 +46,7 @@ #include "process-util.h" #include "rm-rf.h" #include "sort-util.h" +#include "selinux-util.h" #include "string-table.h" #include "string-util.h" #include "terminal-util.h" @@ -899,6 +901,7 @@ static int resolve_mutable_directory( _cleanup_free_ char *path = NULL, *resolved_path = NULL, *dir_name = NULL; const char *root = arg_root, *base = MUTABLE_EXTENSIONS_BASE_DIR; int r; + _cleanup_close_ int atfd = -EBADF; assert(hierarchy); assert(ret_resolved_mutable_directory); @@ -943,6 +946,14 @@ static int resolve_mutable_directory( r = mkdir_p(path_in_root, 0700); if (r < 0) return log_error_errno(r, "Failed to create a directory '%s': %m", path_in_root); + + atfd = open(path_in_root, O_DIRECTORY|O_CLOEXEC); + if (atfd < 0) + return log_error_errno(errno, "Failed to open directory '%s': %m", path_in_root); + + r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0); + if (r < 0) + return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", path_in_root); } r = chase(path, root, CHASE_PREFIX_ROOT, &resolved_path, NULL); @@ -1289,6 +1300,7 @@ static int mount_overlayfs_with_op( int r; const char *top_layer = NULL; + _cleanup_close_ int atfd = -EBADF; assert(op); assert(overlay_path); @@ -1301,10 +1313,28 @@ static int mount_overlayfs_with_op( if (r < 0) return log_error_errno(r, "Failed to make directory '%s': %m", meta_path); + atfd = open(meta_path, O_DIRECTORY|O_CLOEXEC); + if (atfd < 0) + return log_error_errno(errno, "Failed to open directory '%s': %m", meta_path); + + r = mac_selinux_fix_full(atfd, NULL, op->hierarchy, 0); + if (r < 0) + return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", meta_path); + if (op->upper_dir && op->work_dir) { r = mkdir_p(op->work_dir, 0700); if (r < 0) return log_error_errno(r, "Failed to make directory '%s': %m", op->work_dir); + _cleanup_close_ int dfd = -EBADF; + + dfd = open(op->work_dir, O_DIRECTORY|O_CLOEXEC); + if (dfd < 0) + return log_error_errno(errno, "Failed to open directory '%s': %m", op->work_dir); + + r = mac_selinux_fix_full(dfd, NULL, op->hierarchy, 0); + if (r < 0) + return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", op->work_dir); + top_layer = op->upper_dir; } else { assert(!strv_isempty(op->lower_dirs)); @@ -1325,7 +1355,7 @@ static int mount_overlayfs_with_op( return 0; } -static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path) { +static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path, const char *hierarchy) { _cleanup_free_ char *f = NULL, *buf = NULL; int r; @@ -1343,14 +1373,15 @@ static int write_extensions_file(ImageClass image_class, char **extensions, cons if (!buf) return log_oom(); - r = write_string_file(f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755); + const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural); + r = write_string_file_full(AT_FDCWD,f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path); if (r < 0) return log_error_errno(r, "Failed to write extension meta file '%s': %m", f); return 0; } -static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path) { +static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path, const char *hierarchy) { _cleanup_free_ char *f = NULL; struct stat st; int r; @@ -1372,14 +1403,15 @@ static int write_dev_file(ImageClass image_class, const char *meta_path, const c /* Modifying the underlying layers while the overlayfs is mounted is technically undefined, but at * least it won't crash or deadlock, as per the kernel docs about overlayfs: * https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#changes-to-underlying-filesystems */ - r = write_string_file(f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE); + const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural); + r = write_string_file_full(AT_FDCWD, f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path); if (r < 0) return log_error_errno(r, "Failed to write '%s': %m", f); return 0; } -static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir) { +static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir, const char* hierarchy) { _cleanup_free_ char *escaped_work_dir_in_root = NULL, *f = NULL; char *work_dir_in_root = NULL; int r; @@ -1406,7 +1438,8 @@ static int write_work_dir_file(ImageClass image_class, const char *meta_path, co escaped_work_dir_in_root = cescape(work_dir_in_root); if (!escaped_work_dir_in_root) return log_oom(); - r = write_string_file(f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE); + const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, "work_dir"); + r = write_string_file_full(AT_FDCWD, f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path); if (r < 0) return log_error_errno(r, "Failed to write '%s': %m", f); @@ -1418,8 +1451,10 @@ static int store_info_in_meta( char **extensions, const char *meta_path, const char *overlay_path, - const char *work_dir) { - + const char *work_dir, + const char *hierarchy) { + _cleanup_free_ char *f = NULL; + _cleanup_close_ int atfd = -EBADF; int r; assert(extensions); @@ -1427,15 +1462,32 @@ static int store_info_in_meta( assert(overlay_path); /* work_dir may be NULL */ - r = write_extensions_file(image_class, extensions, meta_path); + f = path_join(meta_path, image_class_info[image_class].dot_directory_name); + if (!f) + return log_oom(); + + r = mkdir_p(f, 0755); + if (r < 0) + return r; + + atfd = open(f, O_DIRECTORY|O_CLOEXEC); + if (atfd < 0) + return log_error_errno(errno, "Failed to open directory '%s': %m", f); + + r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0); + + if (r < 0) + return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", hierarchy); + + r = write_extensions_file(image_class, extensions, meta_path, hierarchy); if (r < 0) return r; - r = write_dev_file(image_class, meta_path, overlay_path); + r = write_dev_file(image_class, meta_path, overlay_path, hierarchy); if (r < 0) return r; - r = write_work_dir_file(image_class, meta_path, work_dir); + r = write_work_dir_file(image_class, meta_path, work_dir, hierarchy); if (r < 0) return r; @@ -1501,6 +1553,8 @@ static int merge_hierarchy( assert(overlay_path); assert(workspace_path); + mac_selinux_init(); + r = determine_used_extensions(hierarchy, paths, &used_paths, &extensions_used); if (r < 0) return r; @@ -1528,7 +1582,7 @@ static int merge_hierarchy( if (r < 0) return r; - r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir); + r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir, op->hierarchy); if (r < 0) return r; diff --git a/src/sysupdate/updatectl.c b/src/sysupdate/updatectl.c index 7cfccb66f4..6cb7c6fbf1 100644 --- a/src/sysupdate/updatectl.c +++ b/src/sysupdate/updatectl.c @@ -1414,7 +1414,7 @@ static int verb_enable(int argc, char **argv, void *userdata) { "SetFeatureEnabled", &error, /* reply= */ NULL, - "sbt", + "sit", *feature, (int) enable, UINT64_C(0)); diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index 37bce0ae1d..66a8bdf427 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -213,9 +213,23 @@ TEST(idmapping_supported) { assert_se(is_idmapping_supported("/etc") >= 0); } +TEST(namespace_is_init) { + int r; + + for (NamespaceType t = 0; t < _NAMESPACE_TYPE_MAX; t++) { + r = namespace_is_init(t); + if (r == -EBADR) + log_info_errno(r, "In root namespace of type '%s': don't know", namespace_info[t].proc_name); + else { + ASSERT_OK(r); + log_info("In root namespace of type '%s': %s", namespace_info[t].proc_name, yes_no(r)); + } + } +} + static int intro(void) { if (!have_namespaces()) - return log_tests_skipped("Don't have namespace support"); + return log_tests_skipped("Don't have namespace support or lacking privileges"); return EXIT_SUCCESS; } diff --git a/src/ukify/mypy.ini b/src/ukify/mypy.ini deleted file mode 100644 index c9836169c1..0000000000 --- a/src/ukify/mypy.ini +++ /dev/null @@ -1,22 +0,0 @@ -[mypy] -python_version = 3.9 -# belonging to --strict -warn_unused_configs = true -disallow_any_generics = true -disallow_subclassing_any = true -disallow_untyped_calls = true -disallow_untyped_defs = true -disallow_untyped_decorators = true -disallow_incomplete_defs = true -check_untyped_defs = true -no_implicit_optional = true -warn_redundant_casts = true -warn_unused_ignores = false -warn_return_any = true -no_implicit_reexport = true -# extra options not in --strict -pretty = true -show_error_codes = true -show_column_numbers = true -warn_unreachable = true -strict_equality = true diff --git a/src/ukify/ruff.toml b/src/ukify/ruff.toml deleted file mode 100644 index 6c0ec6ceb8..0000000000 --- a/src/ukify/ruff.toml +++ /dev/null @@ -1,6 +0,0 @@ -target-version = "py39" -line-length = 109 -lint.select = ["E", "F", "I", "UP"] - -[format] -quote-style = "single" diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index 1ab383f5a9..a5719615cc 100755 --- a/src/ukify/ukify.py +++ b/src/ukify/ukify.py @@ -468,7 +468,7 @@ class SignTool: raise NotImplementedError() @staticmethod - def from_string(name) -> type['SignTool']: + def from_string(name: str) -> type['SignTool']: if name == 'pesign': return PeSign elif name == 'sbsign': diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index 277d2860b9..fdfbb7b52e 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -29,7 +29,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) { timespec_load_nsec(ts)) < 0) return log_oom(); - r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts); + r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts, NULL); if (r == -EROFS) log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path); else if (r < 0) diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c index cbbd9b10b5..bc69175b10 100644 --- a/src/userdb/userdbctl.c +++ b/src/userdb/userdbctl.c @@ -23,6 +23,7 @@ #include "user-util.h" #include "userdb.h" #include "verbs.h" +#include "virt.h" static enum { OUTPUT_CLASSIC, @@ -139,10 +140,16 @@ static int show_user(UserRecord *ur, Table *table) { 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 { uid_t first, last; const char *name; UserDisposition disposition; + bool (*test)(void); } uid_range_table[] = { { .first = 1, @@ -175,11 +182,12 @@ static const struct { .last = MAP_UID_MAX, .name = "mapped", .disposition = USER_REGULAR, + .test = test_show_mapped, }, }; static int table_add_uid_boundaries(Table *table, const UIDRange *p) { - int r; + int r, n_added = 0; 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)) continue; + if (i->test && !i->test()) + continue; + name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN), " begin ", i->name, " users ", 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 */ if (r < 0) 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) { @@ -565,16 +578,22 @@ static int show_group(GroupRecord *gr, Table *table) { } static int table_add_gid_boundaries(Table *table, const UIDRange *p) { - int r; + int r, n_added = 0; assert(table); FOREACH_ELEMENT(i, uid_range_table) { _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)) continue; + if (i->test && !i->test()) + continue; + name = strjoin(special_glyph(SPECIAL_GLYPH_ARROW_DOWN), " begin ", i->name, " groups ", 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 */ if (r < 0) 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) { |