Compare commits

...

18 Commits

Author SHA1 Message Date
Lennart Poettering 3138812753
Merge af282c1cf0 into 9e05e33871 2024-11-23 17:35:04 +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
Lennart Poettering af282c1cf0 pam_systemd: introduce pam_get_data_many() helper and make use of it
This is to pam_get_data() what pam_get_item() is to pam_get_item_many().
2024-11-19 10:25:09 +01:00
Lennart Poettering 66ece37d97 pam_systemd: fix error code confusion when prepping D-Bus message
We got confused by the error codes here, and sometimes return PAM errors
where the caller propagated them unconverted as negative errno errors. Fix that.
2024-11-19 10:25:09 +01:00
Lennart Poettering 8eedde1c62 pam_systemd: split pam_sm_open_session() into more digestable blocks
Let's separate four different parts of pam_sm_open_session():

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

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

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

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

This addresses a weird asymmetry, as create_session_message() always
went to the process' own PID when doing pidfds but otherwise (i.e.
without pidfds) would honour the PID specified as function parameter.
2024-11-19 10:24:00 +01:00
Lennart Poettering a5c001ca9a pam-systemd: normalize parsing of XDG_VTNR
Let's make it more like the parsing of the "incomplete" boolean env var,
to streamline things.
2024-11-19 10:19:29 +01:00
20 changed files with 468 additions and 387 deletions

View File

@ -21,7 +21,7 @@
#define AUTOFS_MIN_PROTO_VERSION 3 #define AUTOFS_MIN_PROTO_VERSION 3
#define AUTOFS_MAX_PROTO_VERSION 5 #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 * 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 #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 { enum bpf_link_type {
BPF_LINK_TYPE_UNSPEC = 0, BPF_LINK_TYPE_UNSPEC = 0,
BPF_LINK_TYPE_RAW_TRACEPOINT = 1, BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
@ -2851,7 +2854,7 @@ union bpf_attr {
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**, * **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**, * **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**, * **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_IP**, which supports *optname* **IP_TOS**.
* * **IPPROTO_IPV6**, which supports the following *optname*\ s: * * **IPPROTO_IPV6**, which supports the following *optname*\ s:
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**. * **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
@ -5519,11 +5522,12 @@ union bpf_attr {
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if * **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
* invalid arguments are passed. * invalid arguments are passed.
* *
* void *bpf_kptr_xchg(void *map_value, void *ptr) * void *bpf_kptr_xchg(void *dst, void *ptr)
* Description * Description
* Exchange kptr at pointer *map_value* with *ptr*, and return the * Exchange kptr at pointer *dst* with *ptr*, and return the old value.
* old value. *ptr* can be NULL, otherwise it must be a referenced * *dst* can be map value or local kptr. *ptr* can be NULL, otherwise
* pointer which will be released when this helper is called. * it must be a referenced pointer which will be released when this helper
* is called.
* Return * Return
* The old value of kptr (which can be NULL). The returned pointer * The old value of kptr (which can be NULL). The returned pointer
* if not NULL, is a reference which must be released using its * if not NULL, is a reference which must be released using its
@ -6046,11 +6050,6 @@ enum {
BPF_F_MARK_ENFORCE = (1ULL << 6), 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. */ /* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
enum { enum {
BPF_F_TUNINFO_IPV6 = (1ULL << 0), BPF_F_TUNINFO_IPV6 = (1ULL << 0),
@ -6197,10 +6196,12 @@ enum {
BPF_F_BPRM_SECUREEXEC = (1ULL << 0), BPF_F_BPRM_SECUREEXEC = (1ULL << 0),
}; };
/* Flags for bpf_redirect_map helper */ /* Flags for bpf_redirect and bpf_redirect_map helpers */
enum { enum {
BPF_F_BROADCAST = (1ULL << 3), BPF_F_INGRESS = (1ULL << 0), /* used for skb path */
BPF_F_EXCLUDE_INGRESS = (1ULL << 4), 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) \ #define __bpf_md_ptr(type, name) \
@ -7080,6 +7081,7 @@ enum {
TCP_BPF_SYN = 1005, /* Copy the TCP header */ TCP_BPF_SYN = 1005, /* Copy the TCP header */
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and 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_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 { enum {
@ -7512,4 +7514,13 @@ struct bpf_iter_num {
__u64 __opaque[1]; __u64 __opaque[1];
} __attribute__((aligned(8))); } __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__ */ #endif /* __LINUX_BPF_H__ */

View File

@ -28,6 +28,23 @@
#define _BITUL(x) (_UL(1) << (x)) #define _BITUL(x) (_UL(1) << (x))
#define _BITULL(x) (_ULL(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(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) #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]; * __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 */ #endif /* _LINUX_ETHTOOL_H */

View File

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

View File

@ -230,8 +230,8 @@ struct tpacket_hdr_v1 {
* ts_first_pkt: * ts_first_pkt:
* Is always the time-stamp when the block was opened. * Is always the time-stamp when the block was opened.
* Case a) ZERO packets * Case a) ZERO packets
* No packets to deal with but atleast you know the * No packets to deal with but at least you know
* time-interval of this block. * the time-interval of this block.
* Case b) Non-zero packets * Case b) Non-zero packets
* Use the ts of the first packet in the block. * Use the ts of the first packet in the block.
* *
@ -265,7 +265,8 @@ enum tpacket_versions {
- struct tpacket_hdr - struct tpacket_hdr
- pad to TPACKET_ALIGNMENT=16 - pad to TPACKET_ALIGNMENT=16
- struct sockaddr_ll - 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_mac: [ Optional MAC header ]
- Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16. - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
- Pad to align 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 #define IP_PMTUDISC_INTERFACE 4
/* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get /* 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 #define IP_PMTUDISC_OMIT 5

View File

@ -140,25 +140,6 @@
#endif /* _NETINET_IN_H */ #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 */ /* Definitions for xattr.h */
#if defined(_SYS_XATTR_H) #if defined(_SYS_XATTR_H)
#define __UAPI_DEF_XATTR 0 #define __UAPI_DEF_XATTR 0
@ -240,23 +221,6 @@
#define __UAPI_DEF_IP6_MTUINFO 1 #define __UAPI_DEF_IP6_MTUINFO 1
#endif #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 */ /* Definitions for xattr.h */
#ifndef __UAPI_DEF_XATTR #ifndef __UAPI_DEF_XATTR
#define __UAPI_DEF_XATTR 1 #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_KEY: key value (NLA_NESTED: nft_data)
* @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes) * @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_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_EXPIRATION: expiration time (NLA_U64)
* @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
* @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) * @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_TABLE: name of the table containing the expression (NLA_STRING)
* @NFTA_FLOWTABLE_NAME: name of this flow table (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_USE: number of references to this flow table (NLA_U32)
* @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
* @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32) * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)

View File

@ -16,10 +16,15 @@ struct nhmsg {
struct nexthop_grp { struct nexthop_grp {
__u32 id; /* nexthop id - must exist */ __u32 id; /* nexthop id - must exist */
__u8 weight; /* weight of this nexthop */ __u8 weight; /* weight of this nexthop */
__u8 resvd1; __u8 weight_high; /* high order bits of weight */
__u16 resvd2; __u16 resvd2;
}; };
static __inline__ __u16 nexthop_grp_weight(const struct nexthop_grp *entry)
{
return ((entry->weight_high << 8) | entry->weight) + 1;
}
enum { enum {
NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group
* default type if not specified * default type if not specified
@ -33,6 +38,9 @@ enum {
#define NHA_OP_FLAG_DUMP_STATS BIT(0) #define NHA_OP_FLAG_DUMP_STATS BIT(0)
#define NHA_OP_FLAG_DUMP_HW_STATS BIT(1) #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 { enum {
NHA_UNSPEC, NHA_UNSPEC,
NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */ 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); userns_fd = userns_acquire(uid_map, gid_map);
if (ERRNO_IS_NEG_NOT_SUPPORTED(userns_fd) || ERRNO_IS_NEG_PRIVILEGE(userns_fd)) if (ERRNO_IS_NEG_NOT_SUPPORTED(userns_fd) || ERRNO_IS_NEG_PRIVILEGE(userns_fd))
return false; 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) 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)); dir_fd = RET_NERRNO(open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (ERRNO_IS_NEG_NOT_SUPPORTED(dir_fd)) if (ERRNO_IS_NEG_NOT_SUPPORTED(dir_fd))
return false; return false;
if (dir_fd < 0) 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)); 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) if (ERRNO_IS_NEG_NOT_SUPPORTED(mount_fd) || ERRNO_IS_NEG_PRIVILEGE(mount_fd) || mount_fd == -EINVAL)
return false; return false;
if (mount_fd < 0) 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, r = RET_NERRNO(mount_setattr(mount_fd, "", AT_EMPTY_PATH,
&(struct mount_attr) { &(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) if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
return false; return false;
if (r < 0) 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; return true;
} }

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)
else if (streq(key, "fastboot") && !value) {
log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line.");
arg_skip = true; arg_skip = true;
} else if (streq(key, "forcefsck") && !value) { else if (streq(key, "forcefsck") && !value)
log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line.");
arg_force = true; arg_force = true;
}
#endif
return 0; return 0;
} }

View File

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

View File

@ -2280,10 +2280,9 @@ static int copy_devnode_one(const char *dest, const char *node, bool ignore_mkno
r = path_extract_directory(from, &parent); r = path_extract_directory(from, &parent);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to extract directory from %s: %m", from); return log_error_errno(r, "Failed to extract directory from %s: %m", from);
if (!path_equal(parent, "/dev/")) { r = userns_mkdir(dest, parent, 0755, 0, 0);
if (userns_mkdir(dest, parent, 0755, 0, 0) < 0) if (r < 0)
return log_error_errno(r, "Failed to create directory %s: %m", parent); return log_error_errno(r, "Failed to create directory %s: %m", parent);
}
if (mknod(to, st.st_mode, st.st_rdev) < 0) { if (mknod(to, st.st_mode, st.st_rdev) < 0) {
r = -errno; /* Save the original error code. */ 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); ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred || ucred->pid != inner_child_pid) { 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; 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; arg_skip = true;
else else
log_warning("Invalid quotacheck.mode= value, ignoring: %s", value); log_warning("Invalid quotacheck.mode= value, ignoring: %s", value);
}
#if HAVE_SYSV_COMPAT } else if (streq(key, "forcequotacheck") && !value)
else if (streq(key, "forcequotacheck") && !value) {
log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line. Proceeding anyway.");
arg_force = true; arg_force = true;
}
#endif
return 0; return 0;
} }

View File

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

View File

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

View File

@ -98,15 +98,17 @@ static int delete_dm(DeviceMapper *m) {
assert(major(m->devnum) != 0); assert(major(m->devnum) != 0);
assert(m->path); 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); fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
if (fd < 0) if (fd < 0)
return -errno; return log_debug_errno(errno, "Failed to open /dev/mapper/control: %m");
_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 RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) { return RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) {
.version = { .version = {

View File

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

View File

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