1
0
mirror of https://github.com/systemd/systemd synced 2025-11-22 02:04:45 +01:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Yu Watanabe
d88ecd2bca
libacl → turn into dlopen() dependency (#39087) 2025-09-24 18:25:20 +09:00
Yu Watanabe
a359d92547
measure: strip tpm 1.x remnants and make GetActivePcrBanks() work (#39089)
Let's never bother with old TPM 1.x structures, they are not mentioned
in the TCG for TPM2 spec at all. However, the spec does say we should
check the Size field of the relevant structs, before accessing them,
hence do that.

Use that to determine the version of the protocol, before accessing
GetActiveBanks().

Alternative to: #39034
Fixes: #38932
Follow-up to: 6eab4cd44c3c43698dcfc2c3bc8cd31ed610a812
2025-09-24 18:14:09 +09:00
Yu Watanabe
01598d644f
udev-builtin-net_id: Add DeviceTree-based names for WLAN devices (#39060)
Add support for generating names like wldN based on DeviceTree aliases.

DeviceTree alias names follow de facto conventions. As of writing, there
are so far two ways WLAN devices are represented in DeviceTree aliases
in upstream Linux DTS files:

- Firstly, as wifi0, used for example in t600x-j314-j316.dtsi
- Secondly, as ethernet0 or ethernet1, used for example in
sun8i-q8-common.dtsi, with a comment saying the reason is to "Make
u-boot set mac-address for wifi without an eeprom"

So we need to handle both while generating names. Refactor most of the
logic in names_devicetree() into a helper
names_devicetree_alias_prefix() that takes an alias_prefix instead of
hardcoding "ethernet", and, in the new names_devicetree():

- For prefix "en", use alias_prefix "ethernet"
- For prefix "wl", try alias_prefix "wifi" first, and if that was not
found, fall back to alias_prefix "ethernet"

Since this is a naming scheme change, also gate this behind
NAMING_DEVICETREE_ALIASES_WLAN and NAMING_V259, and document this
change.
2025-09-24 18:10:27 +09:00
Lennart Poettering
7c3a7f925f acl: turn libacl dep into a dlopen() one
I initially didn't think it would be worth doing this, but I changed my
mind. People out there quite successfully build systemd without ACL
support, and that suggests life without it is quite possible. Moreover
we only use it as very specific places:

1. in udev/logind for "uaccess" mgmt
2. in tmpfiles to implement explicitly configured acl changes
3. in journald/coredump/pstore to manage access to unpriv users
4. in pid1 to manage access to credential files
5. when shifting UIDs of container trees

I specific container environments it should be entirely fine to live without all
of these, hence let's pull this in on demand only.
2025-09-24 09:47:41 +02:00
Lennart Poettering
ab2b430487 tree-wide: drop deps on libacl
test-shift-uid.c doesn't actually use anything from libacl. It all goes
through shared/, and the dep there is enough.

Same for the coredump stuffi, logind and core/.

And pstore doesn't use it at all, neither directly or indirectly.
2025-09-24 09:47:30 +02:00
Lennart Poettering
31a66a1126 cleanup: add cleanup func macro that renames the function
This is useful when having to add a "sym_" prefix to functions
2025-09-24 09:41:21 +02:00
Lennart Poettering
b388fa20c7 boot: check protocol version before assuming GetActiveBanks() exists
Alternative to: #39034
Fixes: #38932
Follow-up to: 6eab4cd44c3c43698dcfc2c3bc8cd31ed610a812
2025-09-24 08:57:11 +02:00
Lennart Poettering
496489c2a7 measure: strip tpm 1.x remnants
Let's never bother with old TPM 1.x structures, they are not mentioned
in the TCG for TPM2 spec at all. However, the spec does say we should
check the Size field of the relevant structs, before accessing them,
hence do that.
2025-09-24 08:49:23 +02:00
Luca Boccassi
696b1263dc fs-util: prefer glibc's fchmodat() if possible
Since v2.39 glibc's fchmodat() will call into the kernel's fchmodat2()
if flags are passed:

https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=65341f7bbea824d2ff9d37db15d8be162df42bd3;hp=c52c2c32db15aba8bbe1a0b4d3235f97d9c1a525

On older versions, if the flag is anything other than AT_SYMLINK_NOFOLLOW,
it returns EINVAL, so we can detect it and call the kernel syscall directly
ourselves.

Using the glibc wrappers when possible is prefereable so that programs
like fakeroot can intercept its calls and redirect them.

Follow-up for adecfb3bc0be0def49433277fcad5333893756cc
2025-09-24 08:48:42 +02:00
Lennart Poettering
264608e8c3 docs: add a governance document
Since there have been disagreements on certain aspects of the technical
direction, let's clear things up, and introduce a governance document,
taking inspiration from:

https://github.com/uapi-group/uapi-group.github.io/blob/main/content/_index.md#governance
2025-09-24 08:48:17 +02:00
dramforever
20693ffcd8 udev-builtin-net_id: Add DeviceTree-based names for WLAN devices
Add support for generating names like wldN based on DeviceTree aliases.

DeviceTree alias names follow de facto conventions. As of writing, there
are so far two ways WLAN devices are represented in DeviceTree aliases
in upstream Linux DTS files:

- Firstly, as wifi0, used for example in t600x-j314-j316.dtsi
- Secondly, as ethernet0 or ethernet1, used for example in
  sun8i-q8-common.dtsi, with a comment saying the reason is to "Make
  u-boot set mac-address for wifi without an eeprom"

Therefore for prefix "wl", try alias_prefix "wifi" first, and if that
was not found, fall back to alias_prefix "ethernet"

Since this is a naming scheme change, also gate this behind
NAMING_DEVICETREE_ALIASES_WLAN and NAMING_V259, and document this
change.
2025-09-24 03:13:32 +08:00
dramforever
d096f80b27 udev-builtin-net_id: Refactor names_devicetree() to avoid hardcoding
Refactor most of the logic in names_devicetree() into a helper
names_devicetree_alias_prefix() that takes an alias_prefix instead of
hardcoding "ethernet".

The return value names_devicetree_alias_prefix() will be used in further
commits to allow for alias_prefix fallback.
2025-09-24 03:13:26 +08:00
23 changed files with 426 additions and 208 deletions

44
docs/GOVERNANCE.md Normal file
View File

@ -0,0 +1,44 @@
---
title: Governance
category: Contributing
layout: default
SPDX-License-Identifier: LGPL-2.1-or-later
---
The systemd project is governed as a Free Software project, with the following rules:
1. Anyone is welcome to submit comments and reviews.
2. Every project maintainer has the right to merge changes, if they feel that
they hold the expertise in the specific area.
3. Except for trivial changes, an approval from at least one project maintainer
who is not the author is required before merging.
4. Regular contributors may be invited to join the project maintainers team.
5. If there's disagreement whether technical changes should be merged or not,
and attempts to resolve the situation amicably didn't result in a solution,
the subsystem maintainer makes the final decision. If a subsystem has no
specific maintainer, then the project leader has the final say.
6. Changes to the list of maintainers or this governance document require a
simple majority vote of all maintainers.
# Maintainers
Currently, the project maintainers are as follows (in alphabetical order):
* Daan De Meyer
* Lennart Poettering
* Luca Boccassi
* Mike Yuan
* Yu Watanabe
* Zbigniew Jędrzejewski-Szmek
Currently, subsystem maintainers are as follows:
* systemd-networkd, systemd-udevd: Yu Watanabe
* systemd-repart, mkosi, integration tests: Daan De Meyer
Currently, the project leader is: Lennart Poettering

View File

@ -552,6 +552,15 @@
<xi:include href="version-info.xml" xpointer="v258"/> <xi:include href="version-info.xml" xpointer="v258"/>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><constant>v259</constant></term>
<listitem><para>The naming scheme based on devicetree aliases was extended to support WLAN devices.</para>
<xi:include href="version-info.xml" xpointer="v259"/>
</listitem>
</varlistentry>
</variablelist> </variablelist>
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this <para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this

View File

@ -1183,6 +1183,7 @@ conf.set10('ENABLE_POLKIT', install_polkit)
libacl = dependency('libacl', libacl = dependency('libacl',
required : get_option('acl')) required : get_option('acl'))
conf.set10('HAVE_ACL', libacl.found()) conf.set10('HAVE_ACL', libacl.found())
libacl_cflags = libacl.partial_dependency(includes: true, compile_args: true)
libaudit = dependency('audit', libaudit = dependency('audit',
required : get_option('audit')) required : get_option('audit'))

View File

@ -288,15 +288,20 @@ int fchmod_opath(int fd, mode_t m) {
* - fchmod(2) only operates on open files (i. e., fds with an open file description); * - fchmod(2) only operates on open files (i. e., fds with an open file description);
* - fchmodat(2) does not have a flag arg like fchownat(2) does, so no way to pass AT_EMPTY_PATH; * - fchmodat(2) does not have a flag arg like fchownat(2) does, so no way to pass AT_EMPTY_PATH;
* + it should not be confused with the libc fchmodat(3) interface, which adds 4th flag argument, * + it should not be confused with the libc fchmodat(3) interface, which adds 4th flag argument,
* but does not support AT_EMPTY_PATH (only supports AT_SYMLINK_NOFOLLOW); * and supports AT_EMPTY_PATH since v2.39 (previously only supported AT_SYMLINK_NOFOLLOW). So if
* the kernel has fchmodat2(2), since v2.39 glibc will call into it directly. If the kernel
* doesn't, or glibc is older than v2.39, glibc's internal fallback will return EINVAL if
* AT_EMPTY_PATH is passed.
* - fchmodat2(2) supports all the AT_* flags, but is still very recent. * - fchmodat2(2) supports all the AT_* flags, but is still very recent.
* *
* We try to use fchmodat2(), and, if it is not supported, resort * We try to use fchmodat(3) first, and on EINVAL fall back to fchmodat2(), and, if that is also not
* to the /proc/self/fd dance. */ * supported, resort to the /proc/self/fd dance. */
assert(fd >= 0); assert(fd >= 0);
if (fchmodat2(fd, "", m, AT_EMPTY_PATH) >= 0) if (fchmodat(fd, "", m, AT_EMPTY_PATH) >= 0)
return 0;
if (errno == EINVAL && fchmodat2(fd, "", m, AT_EMPTY_PATH) >= 0) /* glibc too old? */
return 0; return 0;
if (!IN_SET(errno, ENOSYS, EPERM)) /* Some container managers block unknown syscalls with EPERM */ if (!IN_SET(errno, ENOSYS, EPERM)) /* Some container managers block unknown syscalls with EPERM */
return -errno; return -errno;

View File

@ -150,48 +150,59 @@ static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) {
return cc; return cc;
} }
static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) { static EFI_TCG2_PROTOCOL* tcg2_interface_check(EFI_TCG2_VERSION *ret_version) {
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
.Size = sizeof(capability),
};
EFI_STATUS err; EFI_STATUS err;
EFI_TCG2_PROTOCOL *tcg;
EFI_TCG2_PROTOCOL *tcg;
err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2_PROTOCOL), NULL, (void **) &tcg); err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2_PROTOCOL), NULL, (void **) &tcg);
if (err != EFI_SUCCESS) if (err != EFI_SUCCESS)
return NULL; return NULL;
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
.Size = sizeof(capability),
};
err = tcg->GetCapability(tcg, &capability); err = tcg->GetCapability(tcg, &capability);
if (err != EFI_SUCCESS) if (err != EFI_SUCCESS)
return NULL; return NULL;
if (capability.StructureVersion.Major == 1 && assert(capability.Size >= endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, Size));
capability.StructureVersion.Minor == 0) {
EFI_TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 = /* This is a paranoia check, given these fields existed from day one of the spec. But the spec also
(EFI_TCG_BOOT_SERVICE_CAPABILITY*) &capability; * suggests checking the structure size before accessing any fields, hence let's do so, for extra
if (caps_1_0->TPMPresentFlag) * paranoia. */
return tcg; if (capability.Size < CONST_MAX(endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, TPMPresentFlag),
} endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, ProtocolVersion)))
return NULL;
if (!capability.TPMPresentFlag) if (!capability.TPMPresentFlag)
return NULL; return NULL;
if (ret_version)
*ret_version = capability.ProtocolVersion;
return tcg; return tcg;
} }
bool tpm_present(void) { bool tpm_present(void) {
return tcg2_interface_check(); return tcg2_interface_check(/* ret_version= */ NULL);
} }
uint32_t tpm_get_active_pcr_banks(void) { uint32_t tpm_get_active_pcr_banks(void) {
uint32_t active_pcr_banks = 0;
EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err; EFI_STATUS err;
tpm2 = tcg2_interface_check(); EFI_TCG2_PROTOCOL *tpm2;
EFI_TCG2_VERSION version;
tpm2 = tcg2_interface_check(&version);
if (!tpm2) if (!tpm2)
return 0; return 0;
/* GetActivePcrBanks() was added only in version 1.1 of the spec */
if (version.Major < 1 || (version.Major == 1 && version.Minor < 1)) {
log_debug("TCG protocol too old for GetActivePcrBanks(), claiming no active banks.");
return 0;
}
uint32_t active_pcr_banks = 0;
err = tpm2->GetActivePcrBanks(tpm2, &active_pcr_banks); err = tpm2->GetActivePcrBanks(tpm2, &active_pcr_banks);
if (err != EFI_SUCCESS) { if (err != EFI_SUCCESS) {
log_warning_status(err, "Failed to get TPM2 active PCR banks, assuming none: %m"); log_warning_status(err, "Failed to get TPM2 active PCR banks, assuming none: %m");
@ -207,7 +218,7 @@ static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buf
assert(ret_measured); assert(ret_measured);
tpm2 = tcg2_interface_check(); tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
if (!tpm2) { if (!tpm2) {
*ret_measured = false; *ret_measured = false;
return EFI_SUCCESS; return EFI_SUCCESS;
@ -289,7 +300,7 @@ EFI_STATUS tpm_log_tagged_event(
/* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured /* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
* something, or false if measurement was turned off. */ * something, or false if measurement was turned off. */
tpm2 = tcg2_interface_check(); tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */ if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */
if (ret_measured) if (ret_measured)
*ret_measured = false; *ret_measured = false;

View File

@ -10,27 +10,11 @@
#define EV_IPL 13 #define EV_IPL 13
#define EV_EVENT_TAG UINT32_C(6) #define EV_EVENT_TAG UINT32_C(6)
typedef struct {
uint8_t Major;
uint8_t Minor;
uint8_t RevMajor;
uint8_t RevMinor;
} TCG_VERSION;
typedef struct { typedef struct {
uint8_t Major; uint8_t Major;
uint8_t Minor; uint8_t Minor;
} EFI_TCG2_VERSION; } EFI_TCG2_VERSION;
typedef struct {
uint8_t Size;
TCG_VERSION StructureVersion;
TCG_VERSION ProtocolSpecVersion;
uint8_t HashAlgorithmBitmap;
bool TPMPresentFlag;
bool TPMDeactivatedFlag;
} EFI_TCG_BOOT_SERVICE_CAPABILITY;
typedef struct { typedef struct {
uint8_t Size; uint8_t Size;
EFI_TCG2_VERSION StructureVersion; EFI_TCG2_VERSION StructureVersion;

View File

@ -131,8 +131,7 @@ libcore_static = static_library(
include_directories : [includes, include_directories('.')], include_directories : [includes, include_directories('.')],
implicit_include_directories : false, implicit_include_directories : false,
c_args : ['-fvisibility=default'], c_args : ['-fvisibility=default'],
dependencies : [libacl, dependencies : [libaudit_cflags,
libaudit_cflags,
libblkid, libblkid,
libdl, libdl,
libm, libm,

View File

@ -24,7 +24,7 @@ executables += [
'sources' : systemd_coredump_sources + systemd_coredump_extract_sources, 'sources' : systemd_coredump_sources + systemd_coredump_extract_sources,
'extract' : systemd_coredump_extract_sources, 'extract' : systemd_coredump_extract_sources,
'link_with' : [libshared], 'link_with' : [libshared],
'dependencies' : common_dependencies + [libacl], 'dependencies' : common_dependencies,
}, },
executable_template + { executable_template + {
'name' : 'coredumpctl', 'name' : 'coredumpctl',

View File

@ -17,19 +17,22 @@
*p = func(*p); \ *p = func(*p); \
} }
/* When func() doesn't return the appropriate type, set variable to empty afterwards. /* When func() doesn't return the appropriate type, set variable to empty afterwards. The func() may be
* The func() may be provided by a dynamically loaded shared library, hence add an assertion. */ * provided by a dynamically loaded (dlopen()) shared library, hence add an assertion. */
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \ #define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(type, func, name, empty) \
static inline void func##p(type *p) { \ static inline void name(type *p) { \
if (*p != (empty)) { \ if (*p != (empty)) { \
DISABLE_WARNING_ADDRESS; \ DISABLE_WARNING_ADDRESS; \
assert(func); \ assert(func); \
REENABLE_WARNING; \ REENABLE_WARNING; \
func(*p); \ func(*p); \
*p = (empty); \ *p = (empty); \
} \ } \
} }
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(type, func, func##p, empty)
/* When func() doesn't return the appropriate type, and is also a macro, set variable to empty afterwards. */ /* When func() doesn't return the appropriate type, and is also a macro, set variable to empty afterwards. */
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(type, func, empty) \ #define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(type, func, empty) \
static inline void func##p(type *p) { \ static inline void func##p(type *p) { \

View File

@ -49,7 +49,6 @@ executables += [
'include_directories' : [libexec_template['include_directories'], include_directories('.')], 'include_directories' : [libexec_template['include_directories'], include_directories('.')],
'extract' : systemd_logind_extract_sources, 'extract' : systemd_logind_extract_sources,
'dependencies' : [ 'dependencies' : [
libacl,
threads, threads,
], ],
}, },

View File

@ -9,7 +9,6 @@ executables += [
'name' : 'systemd-pstore', 'name' : 'systemd-pstore',
'sources' : files('pstore.c'), 'sources' : files('pstore.c'),
'dependencies' : [ 'dependencies' : [
libacl,
liblz4_cflags, liblz4_cflags,
libxz_cflags, libxz_cflags,
libzstd_cflags, libzstd_cflags,

View File

@ -7,11 +7,74 @@
#include "errno-util.h" #include "errno-util.h"
#include "extract-word.h" #include "extract-word.h"
#include "fd-util.h" #include "fd-util.h"
#include "log.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "user-util.h" #include "user-util.h"
#if HAVE_ACL #if HAVE_ACL
static void *libacl_dl = NULL;
DLSYM_PROTOTYPE(acl_add_perm);
DLSYM_PROTOTYPE(acl_calc_mask);
DLSYM_PROTOTYPE(acl_copy_entry);
DLSYM_PROTOTYPE(acl_create_entry);
DLSYM_PROTOTYPE(acl_delete_entry);
DLSYM_PROTOTYPE(acl_delete_perm);
DLSYM_PROTOTYPE(acl_dup);
DLSYM_PROTOTYPE(acl_entries);
DLSYM_PROTOTYPE(acl_free);
DLSYM_PROTOTYPE(acl_from_mode);
DLSYM_PROTOTYPE(acl_from_text);
DLSYM_PROTOTYPE(acl_get_entry);
DLSYM_PROTOTYPE(acl_get_fd);
DLSYM_PROTOTYPE(acl_get_file);
DLSYM_PROTOTYPE(acl_get_perm);
DLSYM_PROTOTYPE(acl_get_permset);
DLSYM_PROTOTYPE(acl_get_qualifier);
DLSYM_PROTOTYPE(acl_get_tag_type);
DLSYM_PROTOTYPE(acl_init);
DLSYM_PROTOTYPE(acl_set_fd);
DLSYM_PROTOTYPE(acl_set_file);
DLSYM_PROTOTYPE(acl_set_qualifier);
DLSYM_PROTOTYPE(acl_set_tag_type);
DLSYM_PROTOTYPE(acl_to_any_text);
int dlopen_libacl(void) {
ELF_NOTE_DLOPEN("acl",
"Support for file Access Control Lists (ACLs)",
ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
"libacl.so.1");
return dlopen_many_sym_or_warn(
&libacl_dl,
"libacl.so.1",
LOG_DEBUG,
DLSYM_ARG(acl_add_perm),
DLSYM_ARG(acl_calc_mask),
DLSYM_ARG(acl_copy_entry),
DLSYM_ARG(acl_create_entry),
DLSYM_ARG(acl_delete_entry),
DLSYM_ARG(acl_delete_perm),
DLSYM_ARG(acl_dup),
DLSYM_ARG(acl_entries),
DLSYM_ARG(acl_free),
DLSYM_ARG(acl_from_mode),
DLSYM_ARG(acl_from_text),
DLSYM_ARG(acl_get_entry),
DLSYM_ARG(acl_get_fd),
DLSYM_ARG(acl_get_file),
DLSYM_ARG(acl_get_perm),
DLSYM_ARG(acl_get_permset),
DLSYM_ARG(acl_get_qualifier),
DLSYM_ARG(acl_get_tag_type),
DLSYM_ARG(acl_init),
DLSYM_ARG(acl_set_fd),
DLSYM_ARG(acl_set_file),
DLSYM_ARG(acl_set_qualifier),
DLSYM_ARG(acl_set_tag_type),
DLSYM_ARG(acl_to_any_text));
}
int devnode_acl(int fd, uid_t uid) { int devnode_acl(int fd, uid_t uid) {
bool changed = false, found = false; bool changed = false, found = false;
@ -19,43 +82,47 @@ int devnode_acl(int fd, uid_t uid) {
assert(fd >= 0); assert(fd >= 0);
r = dlopen_libacl();
if (r < 0)
return r;
_cleanup_(acl_freep) acl_t acl = NULL; _cleanup_(acl_freep) acl_t acl = NULL;
acl = acl_get_file(FORMAT_PROC_FD_PATH(fd), ACL_TYPE_ACCESS); acl = sym_acl_get_file(FORMAT_PROC_FD_PATH(fd), ACL_TYPE_ACCESS);
if (!acl) if (!acl)
return -errno; return -errno;
acl_entry_t entry; acl_entry_t entry;
for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
r > 0; r > 0;
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) { r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) {
acl_tag_t tag; acl_tag_t tag;
if (acl_get_tag_type(entry, &tag) < 0) if (sym_acl_get_tag_type(entry, &tag) < 0)
return -errno; return -errno;
if (tag != ACL_USER) if (tag != ACL_USER)
continue; continue;
if (uid > 0) { if (uid > 0) {
uid_t *u = acl_get_qualifier(entry); uid_t *u = sym_acl_get_qualifier(entry);
if (!u) if (!u)
return -errno; return -errno;
if (*u == uid) { if (*u == uid) {
acl_permset_t permset; acl_permset_t permset;
if (acl_get_permset(entry, &permset) < 0) if (sym_acl_get_permset(entry, &permset) < 0)
return -errno; return -errno;
int rd = acl_get_perm(permset, ACL_READ); int rd = sym_acl_get_perm(permset, ACL_READ);
if (rd < 0) if (rd < 0)
return -errno; return -errno;
int wt = acl_get_perm(permset, ACL_WRITE); int wt = sym_acl_get_perm(permset, ACL_WRITE);
if (wt < 0) if (wt < 0)
return -errno; return -errno;
if (!rd || !wt) { if (!rd || !wt) {
if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) if (sym_acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0)
return -errno; return -errno;
changed = true; changed = true;
@ -66,7 +133,7 @@ int devnode_acl(int fd, uid_t uid) {
} }
} }
if (acl_delete_entry(acl, entry) < 0) if (sym_acl_delete_entry(acl, entry) < 0)
return -errno; return -errno;
changed = true; changed = true;
@ -75,20 +142,20 @@ int devnode_acl(int fd, uid_t uid) {
return -errno; return -errno;
if (!found && uid > 0) { if (!found && uid > 0) {
if (acl_create_entry(&acl, &entry) < 0) if (sym_acl_create_entry(&acl, &entry) < 0)
return -errno; return -errno;
if (acl_set_tag_type(entry, ACL_USER) < 0) if (sym_acl_set_tag_type(entry, ACL_USER) < 0)
return -errno; return -errno;
if (acl_set_qualifier(entry, &uid) < 0) if (sym_acl_set_qualifier(entry, &uid) < 0)
return -errno; return -errno;
acl_permset_t permset; acl_permset_t permset;
if (acl_get_permset(entry, &permset) < 0) if (sym_acl_get_permset(entry, &permset) < 0)
return -errno; return -errno;
if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) if (sym_acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0)
return -errno; return -errno;
changed = true; changed = true;
@ -97,10 +164,10 @@ int devnode_acl(int fd, uid_t uid) {
if (!changed) if (!changed)
return 0; return 0;
if (acl_calc_mask(&acl) < 0) if (sym_acl_calc_mask(&acl) < 0)
return -errno; return -errno;
if (acl_set_file(FORMAT_PROC_FD_PATH(fd), ACL_TYPE_ACCESS, acl) < 0) if (sym_acl_set_file(FORMAT_PROC_FD_PATH(fd), ACL_TYPE_ACCESS, acl) < 0)
return -errno; return -errno;
return 0; return 0;
@ -114,27 +181,25 @@ static int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *ret_entry) {
assert(uid_is_valid(uid)); assert(uid_is_valid(uid));
assert(ret_entry); assert(ret_entry);
for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
acl_tag_t tag; acl_tag_t tag;
uid_t *u;
bool b; bool b;
if (acl_get_tag_type(i, &tag) < 0) if (sym_acl_get_tag_type(i, &tag) < 0)
return -errno; return -errno;
if (tag != ACL_USER) if (tag != ACL_USER)
continue; continue;
u = acl_get_qualifier(i); _cleanup_(acl_free_uid_tpp) uid_t *u = NULL;
u = sym_acl_get_qualifier(i);
if (!u) if (!u)
return -errno; return -errno;
b = *u == uid; b = *u == uid;
acl_free(u);
if (b) { if (b) {
*ret_entry = i; *ret_entry = i;
return 1; return 1;
@ -154,12 +219,12 @@ int calc_acl_mask_if_needed(acl_t *acl_p) {
assert(acl_p); assert(acl_p);
for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
acl_tag_t tag; acl_tag_t tag;
if (acl_get_tag_type(i, &tag) < 0) if (sym_acl_get_tag_type(i, &tag) < 0)
return -errno; return -errno;
if (tag == ACL_MASK) if (tag == ACL_MASK)
@ -171,7 +236,7 @@ int calc_acl_mask_if_needed(acl_t *acl_p) {
if (r < 0) if (r < 0)
return -errno; return -errno;
if (need && acl_calc_mask(acl_p) < 0) if (need && sym_acl_calc_mask(acl_p) < 0)
return -errno; return -errno;
return need; return need;
@ -187,12 +252,12 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
assert(acl_p); assert(acl_p);
assert(path); assert(path);
for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
acl_tag_t tag; acl_tag_t tag;
if (acl_get_tag_type(i, &tag) < 0) if (sym_acl_get_tag_type(i, &tag) < 0)
return -errno; return -errno;
if (tag == ACL_USER_OBJ) if (tag == ACL_USER_OBJ)
@ -207,21 +272,20 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
if (r < 0) if (r < 0)
return -errno; return -errno;
r = stat(path, &st); if (stat(path, &st) < 0)
if (r < 0)
return -errno; return -errno;
basic = acl_from_mode(st.st_mode); basic = sym_acl_from_mode(st.st_mode);
if (!basic) if (!basic)
return -errno; return -errno;
for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(basic, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) {
acl_tag_t tag; acl_tag_t tag;
acl_entry_t dst; acl_entry_t dst;
if (acl_get_tag_type(i, &tag) < 0) if (sym_acl_get_tag_type(i, &tag) < 0)
return -errno; return -errno;
if ((tag == ACL_USER_OBJ && have_user_obj) || if ((tag == ACL_USER_OBJ && have_user_obj) ||
@ -229,11 +293,11 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
(tag == ACL_OTHER && have_other)) (tag == ACL_OTHER && have_other))
continue; continue;
r = acl_create_entry(acl_p, &dst); r = sym_acl_create_entry(acl_p, &dst);
if (r < 0) if (r < 0)
return -errno; return -errno;
r = acl_copy_entry(dst, i); r = sym_acl_copy_entry(dst, i);
if (r < 0) if (r < 0)
return -errno; return -errno;
} }
@ -251,11 +315,15 @@ int acl_search_groups(const char *path, char ***ret_groups) {
assert(path); assert(path);
acl = acl_get_file(path, ACL_TYPE_DEFAULT); r = dlopen_libacl();
if (r < 0)
return r;
acl = sym_acl_get_file(path, ACL_TYPE_DEFAULT);
if (!acl) if (!acl)
return -errno; return -errno;
r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
for (;;) { for (;;) {
_cleanup_(acl_free_gid_tpp) gid_t *gid = NULL; _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL;
acl_tag_t tag; acl_tag_t tag;
@ -265,13 +333,13 @@ int acl_search_groups(const char *path, char ***ret_groups) {
if (r == 0) if (r == 0)
break; break;
if (acl_get_tag_type(entry, &tag) < 0) if (sym_acl_get_tag_type(entry, &tag) < 0)
return -errno; return -errno;
if (tag != ACL_GROUP) if (tag != ACL_GROUP)
goto next; goto next;
gid = acl_get_qualifier(entry); gid = sym_acl_get_qualifier(entry);
if (!gid) if (!gid)
return -errno; return -errno;
@ -295,7 +363,7 @@ int acl_search_groups(const char *path, char ***ret_groups) {
} }
next: next:
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
} }
if (ret_groups) if (ret_groups)
@ -324,6 +392,10 @@ int parse_acl(
if (!split) if (!split)
return -ENOMEM; return -ENOMEM;
r = dlopen_libacl();
if (r < 0)
return r;
STRV_FOREACH(entry, split) { STRV_FOREACH(entry, split) {
_cleanup_strv_free_ char **entry_split = NULL; _cleanup_strv_free_ char **entry_split = NULL;
_cleanup_free_ char *entry_join = NULL; _cleanup_free_ char *entry_join = NULL;
@ -368,7 +440,7 @@ int parse_acl(
if (!join) if (!join)
return -ENOMEM; return -ENOMEM;
a_acl = acl_from_text(join); a_acl = sym_acl_from_text(join);
if (!a_acl) if (!a_acl)
return -errno; return -errno;
@ -386,7 +458,7 @@ int parse_acl(
if (!join) if (!join)
return -ENOMEM; return -ENOMEM;
e_acl = acl_from_text(join); e_acl = sym_acl_from_text(join);
if (!e_acl) if (!e_acl)
return -errno; return -errno;
@ -400,7 +472,7 @@ int parse_acl(
if (!join) if (!join)
return -ENOMEM; return -ENOMEM;
d_acl = acl_from_text(join); d_acl = sym_acl_from_text(join);
if (!d_acl) if (!d_acl)
return -errno; return -errno;
@ -421,10 +493,10 @@ int parse_acl(
static int acl_entry_equal(acl_entry_t a, acl_entry_t b) { static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
acl_tag_t tag_a, tag_b; acl_tag_t tag_a, tag_b;
if (acl_get_tag_type(a, &tag_a) < 0) if (sym_acl_get_tag_type(a, &tag_a) < 0)
return -errno; return -errno;
if (acl_get_tag_type(b, &tag_b) < 0) if (sym_acl_get_tag_type(b, &tag_b) < 0)
return -errno; return -errno;
if (tag_a != tag_b) if (tag_a != tag_b)
@ -440,11 +512,11 @@ static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
case ACL_USER: { case ACL_USER: {
_cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL; _cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL;
uid_a = acl_get_qualifier(a); uid_a = sym_acl_get_qualifier(a);
if (!uid_a) if (!uid_a)
return -errno; return -errno;
uid_b = acl_get_qualifier(b); uid_b = sym_acl_get_qualifier(b);
if (!uid_b) if (!uid_b)
return -errno; return -errno;
@ -453,11 +525,11 @@ static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
case ACL_GROUP: { case ACL_GROUP: {
_cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL; _cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL;
gid_a = acl_get_qualifier(a); gid_a = sym_acl_get_qualifier(a);
if (!gid_a) if (!gid_a)
return -errno; return -errno;
gid_b = acl_get_qualifier(b); gid_b = sym_acl_get_qualifier(b);
if (!gid_b) if (!gid_b)
return -errno; return -errno;
@ -472,9 +544,9 @@ static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *ret) {
acl_entry_t i; acl_entry_t i;
int r; int r;
for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
r = acl_entry_equal(i, entry); r = acl_entry_equal(i, entry);
if (r < 0) if (r < 0)
@ -498,24 +570,28 @@ int acls_for_file(const char *path, acl_type_t type, acl_t acl, acl_t *ret) {
assert(path); assert(path);
applied = acl_get_file(path, type); r = dlopen_libacl();
if (r < 0)
return r;
applied = sym_acl_get_file(path, type);
if (!applied) if (!applied)
return -errno; return -errno;
for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
acl_entry_t j; acl_entry_t j;
r = find_acl_entry(applied, i, &j); r = find_acl_entry(applied, i, &j);
if (r == -ENOENT) { if (r == -ENOENT) {
if (acl_create_entry(&applied, &j) < 0) if (sym_acl_create_entry(&applied, &j) < 0)
return -errno; return -errno;
} else if (r < 0) } else if (r < 0)
return r; return r;
if (acl_copy_entry(j, i) < 0) if (sym_acl_copy_entry(j, i) < 0)
return -errno; return -errno;
} }
if (r < 0) if (r < 0)
@ -553,33 +629,37 @@ int fd_add_uid_acl_permission(
assert(fd >= 0); assert(fd >= 0);
assert(uid_is_valid(uid)); assert(uid_is_valid(uid));
acl = acl_get_fd(fd); r = dlopen_libacl();
if (r < 0)
return r;
acl = sym_acl_get_fd(fd);
if (!acl) if (!acl)
return -errno; return -errno;
r = acl_find_uid(acl, uid, &entry); r = acl_find_uid(acl, uid, &entry);
if (r <= 0) { if (r <= 0) {
if (acl_create_entry(&acl, &entry) < 0 || if (sym_acl_create_entry(&acl, &entry) < 0 ||
acl_set_tag_type(entry, ACL_USER) < 0 || sym_acl_set_tag_type(entry, ACL_USER) < 0 ||
acl_set_qualifier(entry, &uid) < 0) sym_acl_set_qualifier(entry, &uid) < 0)
return -errno; return -errno;
} }
if (acl_get_permset(entry, &permset) < 0) if (sym_acl_get_permset(entry, &permset) < 0)
return -errno; return -errno;
if ((mask & ACL_READ) && acl_add_perm(permset, ACL_READ) < 0) if ((mask & ACL_READ) && sym_acl_add_perm(permset, ACL_READ) < 0)
return -errno; return -errno;
if ((mask & ACL_WRITE) && acl_add_perm(permset, ACL_WRITE) < 0) if ((mask & ACL_WRITE) && sym_acl_add_perm(permset, ACL_WRITE) < 0)
return -errno; return -errno;
if ((mask & ACL_EXECUTE) && acl_add_perm(permset, ACL_EXECUTE) < 0) if ((mask & ACL_EXECUTE) && sym_acl_add_perm(permset, ACL_EXECUTE) < 0)
return -errno; return -errno;
r = calc_acl_mask_if_needed(&acl); r = calc_acl_mask_if_needed(&acl);
if (r < 0) if (r < 0)
return r; return r;
if (acl_set_fd(fd, acl) < 0) if (sym_acl_set_fd(fd, acl) < 0)
return -errno; return -errno;
return 0; return 0;
@ -596,7 +676,11 @@ int fd_acl_make_read_only(int fd) {
/* Safely drops all W bits from all relevant ACL entries of the file, without changing entries which /* Safely drops all W bits from all relevant ACL entries of the file, without changing entries which
* are masked by the ACL mask */ * are masked by the ACL mask */
acl = acl_get_fd(fd); r = dlopen_libacl();
if (r < 0)
return r;
acl = sym_acl_get_fd(fd);
if (!acl) { if (!acl) {
if (!ERRNO_IS_NOT_SUPPORTED(errno)) if (!ERRNO_IS_NOT_SUPPORTED(errno))
@ -606,29 +690,29 @@ int fd_acl_make_read_only(int fd) {
return fd_acl_make_read_only_fallback(fd); return fd_acl_make_read_only_fallback(fd);
} }
for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
acl_permset_t permset; acl_permset_t permset;
acl_tag_t tag; acl_tag_t tag;
int b; int b;
if (acl_get_tag_type(i, &tag) < 0) if (sym_acl_get_tag_type(i, &tag) < 0)
return -errno; return -errno;
/* These three control the x bits overall (as ACL_MASK affects all remaining tags) */ /* These three control the x bits overall (as ACL_MASK affects all remaining tags) */
if (!IN_SET(tag, ACL_USER_OBJ, ACL_MASK, ACL_OTHER)) if (!IN_SET(tag, ACL_USER_OBJ, ACL_MASK, ACL_OTHER))
continue; continue;
if (acl_get_permset(i, &permset) < 0) if (sym_acl_get_permset(i, &permset) < 0)
return -errno; return -errno;
b = acl_get_perm(permset, ACL_WRITE); b = sym_acl_get_perm(permset, ACL_WRITE);
if (b < 0) if (b < 0)
return -errno; return -errno;
if (b) { if (b) {
if (acl_delete_perm(permset, ACL_WRITE) < 0) if (sym_acl_delete_perm(permset, ACL_WRITE) < 0)
return -errno; return -errno;
changed = true; changed = true;
@ -640,7 +724,7 @@ int fd_acl_make_read_only(int fd) {
if (!changed) if (!changed)
return 0; return 0;
if (acl_set_fd(fd, acl) < 0) { if (sym_acl_set_fd(fd, acl) < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(errno)) if (!ERRNO_IS_NOT_SUPPORTED(errno))
return -errno; return -errno;
@ -658,7 +742,11 @@ int fd_acl_make_writable(int fd) {
/* Safely adds the writable bit to the owner's ACL entry of this inode. (And only the owner's! This /* Safely adds the writable bit to the owner's ACL entry of this inode. (And only the owner's! This
* not the obvious inverse of fd_acl_make_read_only() hence!) */ * not the obvious inverse of fd_acl_make_read_only() hence!) */
acl = acl_get_fd(fd); r = dlopen_libacl();
if (r < 0)
return r;
acl = sym_acl_get_fd(fd);
if (!acl) { if (!acl) {
if (!ERRNO_IS_NOT_SUPPORTED(errno)) if (!ERRNO_IS_NOT_SUPPORTED(errno))
return -errno; return -errno;
@ -667,30 +755,30 @@ int fd_acl_make_writable(int fd) {
return fd_acl_make_writable_fallback(fd); return fd_acl_make_writable_fallback(fd);
} }
for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
r > 0; r > 0;
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
acl_permset_t permset; acl_permset_t permset;
acl_tag_t tag; acl_tag_t tag;
int b; int b;
if (acl_get_tag_type(i, &tag) < 0) if (sym_acl_get_tag_type(i, &tag) < 0)
return -errno; return -errno;
if (tag != ACL_USER_OBJ) if (tag != ACL_USER_OBJ)
continue; continue;
if (acl_get_permset(i, &permset) < 0) if (sym_acl_get_permset(i, &permset) < 0)
return -errno; return -errno;
b = acl_get_perm(permset, ACL_WRITE); b = sym_acl_get_perm(permset, ACL_WRITE);
if (b < 0) if (b < 0)
return -errno; return -errno;
if (b) if (b)
return 0; /* Already set? Then there's nothing to do. */ return 0; /* Already set? Then there's nothing to do. */
if (acl_add_perm(permset, ACL_WRITE) < 0) if (sym_acl_add_perm(permset, ACL_WRITE) < 0)
return -errno; return -errno;
break; break;
@ -698,7 +786,7 @@ int fd_acl_make_writable(int fd) {
if (r < 0) if (r < 0)
return -errno; return -errno;
if (acl_set_fd(fd, acl) < 0) { if (sym_acl_set_fd(fd, acl) < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(errno)) if (!ERRNO_IS_NOT_SUPPORTED(errno))
return -errno; return -errno;

View File

@ -10,6 +10,35 @@ int fd_acl_make_writable_fallback(int fd);
#include <acl/libacl.h> /* IWYU pragma: export */ #include <acl/libacl.h> /* IWYU pragma: export */
#include <sys/acl.h> /* IWYU pragma: export */ #include <sys/acl.h> /* IWYU pragma: export */
#include "dlfcn-util.h"
extern DLSYM_PROTOTYPE(acl_add_perm);
extern DLSYM_PROTOTYPE(acl_calc_mask);
extern DLSYM_PROTOTYPE(acl_copy_entry);
extern DLSYM_PROTOTYPE(acl_create_entry);
extern DLSYM_PROTOTYPE(acl_delete_entry);
extern DLSYM_PROTOTYPE(acl_delete_perm);
extern DLSYM_PROTOTYPE(acl_dup);
extern DLSYM_PROTOTYPE(acl_entries);
extern DLSYM_PROTOTYPE(acl_free);
extern DLSYM_PROTOTYPE(acl_from_mode);
extern DLSYM_PROTOTYPE(acl_from_text);
extern DLSYM_PROTOTYPE(acl_get_entry);
extern DLSYM_PROTOTYPE(acl_get_fd);
extern DLSYM_PROTOTYPE(acl_get_file);
extern DLSYM_PROTOTYPE(acl_get_perm);
extern DLSYM_PROTOTYPE(acl_get_permset);
extern DLSYM_PROTOTYPE(acl_get_qualifier);
extern DLSYM_PROTOTYPE(acl_get_tag_type);
extern DLSYM_PROTOTYPE(acl_init);
extern DLSYM_PROTOTYPE(acl_set_fd);
extern DLSYM_PROTOTYPE(acl_set_file);
extern DLSYM_PROTOTYPE(acl_set_qualifier);
extern DLSYM_PROTOTYPE(acl_set_tag_type);
extern DLSYM_PROTOTYPE(acl_to_any_text);
int dlopen_libacl(void);
int devnode_acl(int fd, uid_t uid); int devnode_acl(int fd, uid_t uid);
int calc_acl_mask_if_needed(acl_t *acl_p); int calc_acl_mask_if_needed(acl_t *acl_p);
@ -27,21 +56,22 @@ int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask);
int fd_acl_make_read_only(int fd); int fd_acl_make_read_only(int fd);
int fd_acl_make_writable(int fd); int fd_acl_make_writable(int fd);
/* acl_free takes multiple argument types. /* acl_free() takes multiple argument types. Multiple cleanup functions are necessary. */
* Multiple cleanup functions are necessary. */ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(acl_t, sym_acl_free, acl_freep, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(acl_t, acl_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(char*, sym_acl_free, acl_free_charpp, NULL);
#define acl_free_charp acl_free DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(uid_t*, sym_acl_free, acl_free_uid_tpp, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, acl_free_charp, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(gid_t*, sym_acl_free, acl_free_gid_tpp, NULL);
#define acl_free_uid_tp acl_free
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(uid_t*, acl_free_uid_tp, NULL);
#define acl_free_gid_tp acl_free
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gid_t*, acl_free_gid_tp, NULL);
#else #else
#define ACL_READ 0x04 #define ACL_READ 0x04
#define ACL_WRITE 0x02 #define ACL_WRITE 0x02
#define ACL_EXECUTE 0x01 #define ACL_EXECUTE 0x01
static inline int dlopen_libacl(void) {
return -EOPNOTSUPP;
}
static inline int devnode_acl(int fd, uid_t uid) { static inline int devnode_acl(int fd, uid_t uid) {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
@ -57,7 +87,6 @@ static inline int fd_acl_make_read_only(int fd) {
static inline int fd_acl_make_writable(int fd) { static inline int fd_acl_make_writable(int fd) {
return fd_acl_make_writable_fallback(fd); return fd_acl_make_writable_fallback(fd);
} }
#endif #endif
int inode_type_can_acl(mode_t mode); int inode_type_can_acl(mode_t mode);

View File

@ -312,7 +312,7 @@ man_page_depends += ethtool_link_mode_xml
libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag) libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag)
libshared_deps = [threads, libshared_deps = [threads,
libacl, libacl_cflags,
libaudit_cflags, libaudit_cflags,
libblkid, libblkid,
libcap, libcap,

View File

@ -29,6 +29,7 @@ static const NamingScheme naming_schemes[] = {
{ "v255", NAMING_V255 }, { "v255", NAMING_V255 },
{ "v257", NAMING_V257 }, { "v257", NAMING_V257 },
{ "v258", NAMING_V258 }, { "v258", NAMING_V258 },
{ "v259", NAMING_V259 },
/* … add more schemes here, as the logic to name devices is updated … */ /* … add more schemes here, as the logic to name devices is updated … */
EXTRA_NET_NAMING_MAP EXTRA_NET_NAMING_MAP

View File

@ -42,6 +42,7 @@ typedef enum NamingSchemeFlags {
NAMING_FIRMWARE_NODE_SUN = 1 << 18, /* Use firmware_node/sun to get PCI slot number */ NAMING_FIRMWARE_NODE_SUN = 1 << 18, /* Use firmware_node/sun to get PCI slot number */
NAMING_DEVICETREE_PORT_ALIASES = 1 << 19, /* Include aliases of OF nodes of a netdev itself, not just its parent. See PR #33958. */ NAMING_DEVICETREE_PORT_ALIASES = 1 << 19, /* Include aliases of OF nodes of a netdev itself, not just its parent. See PR #33958. */
NAMING_USE_INTERFACE_PROPERTY = 1 << 20, /* Use INTERFACE udev property, rather than sysname, when no renaming is requested. */ NAMING_USE_INTERFACE_PROPERTY = 1 << 20, /* Use INTERFACE udev property, rather than sysname, when no renaming is requested. */
NAMING_DEVICETREE_ALIASES_WLAN = 1 << 21, /* Generate names from devicetree aliases for WLAN devices */
/* And now the masks that combine the features above */ /* And now the masks that combine the features above */
NAMING_V238 = 0, NAMING_V238 = 0,
@ -63,6 +64,7 @@ typedef enum NamingSchemeFlags {
NAMING_V255 = NAMING_V254 & ~NAMING_BRIDGE_MULTIFUNCTION_SLOT, NAMING_V255 = NAMING_V254 & ~NAMING_BRIDGE_MULTIFUNCTION_SLOT,
NAMING_V257 = NAMING_V255 | NAMING_FIRMWARE_NODE_SUN | NAMING_DEVICETREE_PORT_ALIASES, NAMING_V257 = NAMING_V255 | NAMING_FIRMWARE_NODE_SUN | NAMING_DEVICETREE_PORT_ALIASES,
NAMING_V258 = NAMING_V257 | NAMING_USE_INTERFACE_PROPERTY, NAMING_V258 = NAMING_V257 | NAMING_USE_INTERFACE_PROPERTY,
NAMING_V259 = NAMING_V258 | NAMING_DEVICETREE_ALIASES_WLAN,
EXTRA_NET_NAMING_SCHEMES EXTRA_NET_NAMING_SCHEMES

View File

@ -7,6 +7,7 @@
#include "acl-util.h" #include "acl-util.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "dirent-util.h" #include "dirent-util.h"
#include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
@ -36,11 +37,11 @@ static int get_acl(int fd, const char *name, acl_type_t type, acl_t *ret) {
if (child_fd < 0) if (child_fd < 0)
return -errno; return -errno;
acl = acl_get_file(FORMAT_PROC_FD_PATH(child_fd), type); acl = sym_acl_get_file(FORMAT_PROC_FD_PATH(child_fd), type);
} else if (type == ACL_TYPE_ACCESS) } else if (type == ACL_TYPE_ACCESS)
acl = acl_get_fd(fd); acl = sym_acl_get_fd(fd);
else else
acl = acl_get_file(FORMAT_PROC_FD_PATH(fd), type); acl = sym_acl_get_file(FORMAT_PROC_FD_PATH(fd), type);
if (!acl) if (!acl)
return -errno; return -errno;
@ -61,11 +62,11 @@ static int set_acl(int fd, const char *name, acl_type_t type, acl_t acl) {
if (child_fd < 0) if (child_fd < 0)
return -errno; return -errno;
r = acl_set_file(FORMAT_PROC_FD_PATH(child_fd), type, acl); r = sym_acl_set_file(FORMAT_PROC_FD_PATH(child_fd), type, acl);
} else if (type == ACL_TYPE_ACCESS) } else if (type == ACL_TYPE_ACCESS)
r = acl_set_fd(fd, acl); r = sym_acl_set_fd(fd, acl);
else else
r = acl_set_file(FORMAT_PROC_FD_PATH(fd), type, acl); r = sym_acl_set_file(FORMAT_PROC_FD_PATH(fd), type, acl);
if (r < 0) if (r < 0)
return -errno; return -errno;
@ -80,7 +81,7 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
assert(acl); assert(acl);
assert(ret); assert(ret);
r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
if (r < 0) if (r < 0)
return -errno; return -errno;
while (r > 0) { while (r > 0) {
@ -88,7 +89,7 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
bool modify = false; bool modify = false;
acl_tag_t tag; acl_tag_t tag;
if (acl_get_tag_type(i, &tag) < 0) if (sym_acl_get_tag_type(i, &tag) < 0)
return -errno; return -errno;
if (IN_SET(tag, ACL_USER, ACL_GROUP)) { if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
@ -97,7 +98,7 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
* this is actually OK */ * this is actually OK */
assert_cc(sizeof(uid_t) == sizeof(gid_t)); assert_cc(sizeof(uid_t) == sizeof(gid_t));
old_uid = acl_get_qualifier(i); old_uid = sym_acl_get_qualifier(i);
if (!old_uid) if (!old_uid)
return -errno; return -errno;
@ -112,16 +113,16 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
/* There's no copy of the ACL yet? if so, let's create one, and start the loop from the /* There's no copy of the ACL yet? if so, let's create one, and start the loop from the
* beginning, so that we copy all entries, starting from the first, this time. */ * beginning, so that we copy all entries, starting from the first, this time. */
n = acl_entries(acl); n = sym_acl_entries(acl);
if (n < 0) if (n < 0)
return -errno; return -errno;
copy = acl_init(n); copy = sym_acl_init(n);
if (!copy) if (!copy)
return -errno; return -errno;
/* Seek back to the beginning */ /* Seek back to the beginning */
r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
if (r < 0) if (r < 0)
return -errno; return -errno;
continue; continue;
@ -131,18 +132,18 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
if (copy) { if (copy) {
acl_entry_t new_entry; acl_entry_t new_entry;
if (acl_create_entry(&copy, &new_entry) < 0) if (sym_acl_create_entry(&copy, &new_entry) < 0)
return -errno; return -errno;
if (acl_copy_entry(new_entry, i) < 0) if (sym_acl_copy_entry(new_entry, i) < 0)
return -errno; return -errno;
if (modify) if (modify)
if (acl_set_qualifier(new_entry, &new_uid) < 0) if (sym_acl_set_qualifier(new_entry, &new_uid) < 0)
return -errno; return -errno;
} }
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i); r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i);
if (r < 0) if (r < 0)
return -errno; return -errno;
} }
@ -164,6 +165,12 @@ static int patch_acls(int fd, const char *name, const struct stat *st, uid_t shi
if (!inode_type_can_acl(st->st_mode)) if (!inode_type_can_acl(st->st_mode))
return 0; return 0;
r = dlopen_libacl();
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return 0;
if (r < 0)
return r;
r = get_acl(fd, name, ACL_TYPE_ACCESS, &acl); r = get_acl(fd, name, ACL_TYPE_ACCESS, &acl);
if (r == -EOPNOTSUPP) if (r == -EOPNOTSUPP)
return 0; return 0;
@ -182,10 +189,10 @@ static int patch_acls(int fd, const char *name, const struct stat *st, uid_t shi
} }
if (S_ISDIR(st->st_mode)) { if (S_ISDIR(st->st_mode)) {
acl_free(acl); sym_acl_free(acl);
if (shifted) if (shifted)
acl_free(shifted); sym_acl_free(shifted);
acl = shifted = NULL; acl = shifted = NULL;

View File

@ -400,7 +400,6 @@ executables += [
}, },
test_template + { test_template + {
'sources' : files('test-shift-uid.c'), 'sources' : files('test-shift-uid.c'),
'dependencies' : libacl,
'type' : 'manual', 'type' : 'manual',
}, },
test_template + { test_template + {

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "acl-util.h"
#include "apparmor-util.h" #include "apparmor-util.h"
#include "bpf-dlopen.h" #include "bpf-dlopen.h"
#include "compress.h" #include "compress.h"
@ -52,6 +53,7 @@ static int run(int argc, char **argv) {
ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR); ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR);
ASSERT_DLOPEN(dlopen_libaudit, HAVE_AUDIT); ASSERT_DLOPEN(dlopen_libaudit, HAVE_AUDIT);
ASSERT_DLOPEN(dlopen_libpam, HAVE_PAM); ASSERT_DLOPEN(dlopen_libpam, HAVE_PAM);
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
return 0; return 0;
} }

View File

@ -17,7 +17,7 @@ executables += [
'public' : true, 'public' : true,
'sources' : systemd_tmpfiles_sources + systemd_tmpfiles_extract_sources, 'sources' : systemd_tmpfiles_sources + systemd_tmpfiles_extract_sources,
'extract' : systemd_tmpfiles_extract_sources, 'extract' : systemd_tmpfiles_extract_sources,
'dependencies' : libacl, 'dependencies' : libacl_cflags,
}, },
executable_template + { executable_template + {
'name' : 'systemd-tmpfiles.standalone', 'name' : 'systemd-tmpfiles.standalone',
@ -30,7 +30,7 @@ executables += [
libshared_static, libshared_static,
libsystemd_static, libsystemd_static,
], ],
'dependencies' : libacl, 'dependencies' : libacl_cflags,
}, },
test_template + { test_template + {
'sources' : files('test-offline-passwd.c'), 'sources' : files('test-offline-passwd.c'),

View File

@ -1271,22 +1271,26 @@ static int parse_acl_cond_exec(
assert(cond_exec); assert(cond_exec);
assert(ret); assert(ret);
r = dlopen_libacl();
if (r < 0)
return r;
if (!S_ISDIR(st->st_mode)) { if (!S_ISDIR(st->st_mode)) {
_cleanup_(acl_freep) acl_t old = NULL; _cleanup_(acl_freep) acl_t old = NULL;
old = acl_get_file(path, ACL_TYPE_ACCESS); old = sym_acl_get_file(path, ACL_TYPE_ACCESS);
if (!old) if (!old)
return -errno; return -errno;
has_exec = false; has_exec = false;
for (r = acl_get_entry(old, ACL_FIRST_ENTRY, &entry); for (r = sym_acl_get_entry(old, ACL_FIRST_ENTRY, &entry);
r > 0; r > 0;
r = acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) { r = sym_acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) {
acl_tag_t tag; acl_tag_t tag;
if (acl_get_tag_type(entry, &tag) < 0) if (sym_acl_get_tag_type(entry, &tag) < 0)
return -errno; return -errno;
if (tag == ACL_MASK) if (tag == ACL_MASK)
@ -1296,10 +1300,10 @@ static int parse_acl_cond_exec(
if (!append && IN_SET(tag, ACL_USER, ACL_GROUP)) if (!append && IN_SET(tag, ACL_USER, ACL_GROUP))
continue; continue;
if (acl_get_permset(entry, &permset) < 0) if (sym_acl_get_permset(entry, &permset) < 0)
return -errno; return -errno;
r = acl_get_perm(permset, ACL_EXECUTE); r = sym_acl_get_perm(permset, ACL_EXECUTE);
if (r < 0) if (r < 0)
return -errno; return -errno;
if (r > 0) { if (r > 0) {
@ -1312,14 +1316,14 @@ static int parse_acl_cond_exec(
/* Check if we're about to set the execute bit in acl_access */ /* Check if we're about to set the execute bit in acl_access */
if (!has_exec && access) { if (!has_exec && access) {
for (r = acl_get_entry(access, ACL_FIRST_ENTRY, &entry); for (r = sym_acl_get_entry(access, ACL_FIRST_ENTRY, &entry);
r > 0; r > 0;
r = acl_get_entry(access, ACL_NEXT_ENTRY, &entry)) { r = sym_acl_get_entry(access, ACL_NEXT_ENTRY, &entry)) {
if (acl_get_permset(entry, &permset) < 0) if (sym_acl_get_permset(entry, &permset) < 0)
return -errno; return -errno;
r = acl_get_perm(permset, ACL_EXECUTE); r = sym_acl_get_perm(permset, ACL_EXECUTE);
if (r < 0) if (r < 0)
return -errno; return -errno;
if (r > 0) { if (r > 0) {
@ -1333,28 +1337,28 @@ static int parse_acl_cond_exec(
} else } else
has_exec = true; has_exec = true;
_cleanup_(acl_freep) acl_t parsed = access ? acl_dup(access) : acl_init(0); _cleanup_(acl_freep) acl_t parsed = access ? sym_acl_dup(access) : sym_acl_init(0);
if (!parsed) if (!parsed)
return -errno; return -errno;
for (r = acl_get_entry(cond_exec, ACL_FIRST_ENTRY, &entry); for (r = sym_acl_get_entry(cond_exec, ACL_FIRST_ENTRY, &entry);
r > 0; r > 0;
r = acl_get_entry(cond_exec, ACL_NEXT_ENTRY, &entry)) { r = sym_acl_get_entry(cond_exec, ACL_NEXT_ENTRY, &entry)) {
acl_entry_t parsed_entry; acl_entry_t parsed_entry;
if (acl_create_entry(&parsed, &parsed_entry) < 0) if (sym_acl_create_entry(&parsed, &parsed_entry) < 0)
return -errno; return -errno;
if (acl_copy_entry(parsed_entry, entry) < 0) if (sym_acl_copy_entry(parsed_entry, entry) < 0)
return -errno; return -errno;
/* We substituted 'X' with 'x' in parse_acl(), so drop execute bit here if not applicable. */ /* We substituted 'X' with 'x' in parse_acl(), so drop execute bit here if not applicable. */
if (!has_exec) { if (!has_exec) {
if (acl_get_permset(parsed_entry, &permset) < 0) if (sym_acl_get_permset(parsed_entry, &permset) < 0)
return -errno; return -errno;
if (acl_delete_perm(permset, ACL_EXECUTE) < 0) if (sym_acl_delete_perm(permset, ACL_EXECUTE) < 0)
return -errno; return -errno;
} }
} }
@ -1386,6 +1390,10 @@ static int path_set_acl(
assert(c); assert(c);
r = dlopen_libacl();
if (r < 0)
return r;
/* Returns 0 for success, positive error if already warned, negative error otherwise. */ /* Returns 0 for success, positive error if already warned, negative error otherwise. */
if (modify) { if (modify) {
@ -1397,7 +1405,7 @@ static int path_set_acl(
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
dup = acl_dup(acl); dup = sym_acl_dup(acl);
if (!dup) if (!dup)
return -errno; return -errno;
@ -1408,14 +1416,14 @@ static int path_set_acl(
if (r < 0) if (r < 0)
return r; return r;
t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE); t = sym_acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
log_action("Would set", "Setting", log_action("Would set", "Setting",
"%s %s ACL %s on %s", "%s %s ACL %s on %s",
type == ACL_TYPE_ACCESS ? "access" : "default", type == ACL_TYPE_ACCESS ? "access" : "default",
strna(t), pretty); strna(t), pretty);
if (!arg_dry_run && if (!arg_dry_run &&
acl_set_file(path, type, dup) < 0) { sym_acl_set_file(path, type, dup) < 0) {
if (ERRNO_IS_NOT_SUPPORTED(errno)) if (ERRNO_IS_NOT_SUPPORTED(errno))
/* No error if filesystem doesn't support ACLs. Return negative. */ /* No error if filesystem doesn't support ACLs. Return negative. */
return -errno; return -errno;
@ -3295,13 +3303,13 @@ static void item_free_contents(Item *i) {
#if HAVE_ACL #if HAVE_ACL
if (i->acl_access) if (i->acl_access)
acl_free(i->acl_access); sym_acl_free(i->acl_access);
if (i->acl_access_exec) if (i->acl_access_exec)
acl_free(i->acl_access_exec); sym_acl_free(i->acl_access_exec);
if (i->acl_default) if (i->acl_default)
acl_free(i->acl_default); sym_acl_free(i->acl_default);
#endif #endif
} }

View File

@ -114,7 +114,7 @@ endif
############################################################ ############################################################
udev_dependencies = [ udev_dependencies = [
libacl, libacl_cflags,
libblkid, libblkid,
libkmod, libkmod,
threads, threads,
@ -131,7 +131,7 @@ udev_plugin_template = executable_template + {
udev_common_template = { udev_common_template = {
'objects' : ['udevadm'], 'objects' : ['udevadm'],
'dependencies' : [ 'dependencies' : [
libacl, libacl_cflags,
libblkid, libblkid,
threads, threads,
], ],

View File

@ -788,20 +788,20 @@ static int names_platform(UdevEvent *event, const char *prefix) {
return 0; return 0;
} }
static int names_devicetree(UdevEvent *event, const char *prefix) { static int names_devicetree_alias_prefix(UdevEvent *event, const char *prefix, const char *alias_prefix) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL; _cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL;
const char *ofnode_path, *ofnode_syspath, *devicetree_syspath; const char *ofnode_path, *ofnode_syspath, *devicetree_syspath;
int r; int r;
assert(prefix); assert(prefix);
assert(alias_prefix);
if (!naming_scheme_has(NAMING_DEVICETREE_ALIASES)) /* Returns 1 if found, 0 if not found, negative if error */
return 0;
/* only ethernet supported for now */ _cleanup_free_ char *alias_prefix_0 = strjoin(alias_prefix, "0");
if (!streq(prefix, "en")) if (!alias_prefix_0)
return -EOPNOTSUPP; return log_oom_debug();
/* check if the device itself has an of_node */ /* check if the device itself has an of_node */
if (naming_scheme_has(NAMING_DEVICETREE_PORT_ALIASES)) { if (naming_scheme_has(NAMING_DEVICETREE_PORT_ALIASES)) {
@ -860,7 +860,7 @@ static int names_devicetree(UdevEvent *event, const char *prefix) {
const char *alias_path, *alias_index, *conflict; const char *alias_path, *alias_index, *conflict;
unsigned i; unsigned i;
alias_index = startswith(alias, "ethernet"); alias_index = startswith(alias, alias_prefix);
if (!alias_index) if (!alias_index)
continue; continue;
@ -873,31 +873,59 @@ static int names_devicetree(UdevEvent *event, const char *prefix) {
/* If there's no index, we default to 0... */ /* If there's no index, we default to 0... */
if (isempty(alias_index)) { if (isempty(alias_index)) {
i = 0; i = 0;
conflict = "ethernet0"; conflict = alias_prefix_0;
} else { } else {
r = safe_atou(alias_index, &i); r = safe_atou(alias_index, &i);
if (r < 0) if (r < 0)
return log_device_debug_errno(dev, r, return log_device_debug_errno(dev, r,
"Could not get index of alias %s: %m", alias); "Could not get index of alias %s: %m", alias);
conflict = "ethernet"; conflict = alias_prefix;
} }
/* ...but make sure we don't have an alias conflict */ /* ...but make sure we don't have an alias conflict */
if (i == 0 && device_get_sysattr_value_filtered(aliases_dev, conflict, NULL) >= 0) if (i == 0 && device_get_sysattr_value_filtered(aliases_dev, conflict, NULL) >= 0)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST), return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
"Ethernet alias conflict: ethernet and ethernet0 both exist."); "DeviceTree alias conflict: %s and %s both exist.",
alias_prefix, alias_prefix_0);
char str[ALTIFNAMSIZ]; char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%sd%u", prefix, i)) if (snprintf_ok(str, sizeof str, "%sd%u", prefix, i))
udev_builtin_add_property(event, "ID_NET_NAME_ONBOARD", str); udev_builtin_add_property(event, "ID_NET_NAME_ONBOARD", str);
log_device_debug(dev, "DeviceTree identifier: alias_index=%u %s \"%s\"", log_device_debug(dev, "DeviceTree identifier: alias_index=%u %s \"%s\"",
i, glyph(GLYPH_ARROW_RIGHT), str + strlen(prefix)); i, glyph(GLYPH_ARROW_RIGHT), str + strlen(prefix));
return 0; return 1;
} }
return -ENOENT; return 0;
} }
static int names_devicetree(UdevEvent *event, const char *prefix) {
int r;
assert(event);
assert(prefix);
if (!naming_scheme_has(NAMING_DEVICETREE_ALIASES))
return 0;
if (streq(prefix, "en"))
r = names_devicetree_alias_prefix(event, prefix, "ethernet");
else if (naming_scheme_has(NAMING_DEVICETREE_ALIASES_WLAN) &&
streq(prefix, "wl")) {
r = names_devicetree_alias_prefix(event, prefix, "wifi");
/* Sometimes DeviceTrees have WLAN devices with alias ethernetN, fall back to those */
if (r == 0)
r = names_devicetree_alias_prefix(event, prefix, "ethernet");
} else
return -EOPNOTSUPP; /* Unsupported interface type */
if (r < 0)
return r;
if (r == 0) /* Not found */
return -ENOENT;
return 0; /* Found */
};
static int names_pci(UdevEvent *event, const char *prefix) { static int names_pci(UdevEvent *event, const char *prefix) {
sd_device *parent, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); sd_device *parent, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL; _cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;