mirror of
https://github.com/systemd/systemd
synced 2025-11-22 02:04:45 +01:00
Compare commits
12 Commits
2183d881b9
...
d88ecd2bca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d88ecd2bca | ||
|
|
a359d92547 | ||
|
|
01598d644f | ||
|
|
7c3a7f925f | ||
|
|
ab2b430487 | ||
|
|
31a66a1126 | ||
|
|
b388fa20c7 | ||
|
|
496489c2a7 | ||
|
|
696b1263dc | ||
|
|
264608e8c3 | ||
|
|
20693ffcd8 | ||
|
|
d096f80b27 |
44
docs/GOVERNANCE.md
Normal file
44
docs/GOVERNANCE.md
Normal 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
|
||||
@ -552,6 +552,15 @@
|
||||
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||
</listitem>
|
||||
</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>
|
||||
|
||||
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
|
||||
|
||||
@ -1183,6 +1183,7 @@ conf.set10('ENABLE_POLKIT', install_polkit)
|
||||
libacl = dependency('libacl',
|
||||
required : get_option('acl'))
|
||||
conf.set10('HAVE_ACL', libacl.found())
|
||||
libacl_cflags = libacl.partial_dependency(includes: true, compile_args: true)
|
||||
|
||||
libaudit = dependency('audit',
|
||||
required : get_option('audit'))
|
||||
|
||||
@ -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);
|
||||
* - 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,
|
||||
* 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.
|
||||
*
|
||||
* We try to use fchmodat2(), and, if it is not supported, resort
|
||||
* to the /proc/self/fd dance. */
|
||||
* We try to use fchmodat(3) first, and on EINVAL fall back to fchmodat2(), and, if that is also not
|
||||
* supported, resort to the /proc/self/fd dance. */
|
||||
|
||||
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;
|
||||
if (!IN_SET(errno, ENOSYS, EPERM)) /* Some container managers block unknown syscalls with EPERM */
|
||||
return -errno;
|
||||
|
||||
@ -150,48 +150,59 @@ static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) {
|
||||
return cc;
|
||||
}
|
||||
|
||||
static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
|
||||
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
|
||||
.Size = sizeof(capability),
|
||||
};
|
||||
static EFI_TCG2_PROTOCOL* tcg2_interface_check(EFI_TCG2_VERSION *ret_version) {
|
||||
EFI_STATUS err;
|
||||
EFI_TCG2_PROTOCOL *tcg;
|
||||
|
||||
EFI_TCG2_PROTOCOL *tcg;
|
||||
err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2_PROTOCOL), NULL, (void **) &tcg);
|
||||
if (err != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
|
||||
.Size = sizeof(capability),
|
||||
};
|
||||
err = tcg->GetCapability(tcg, &capability);
|
||||
if (err != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
if (capability.StructureVersion.Major == 1 &&
|
||||
capability.StructureVersion.Minor == 0) {
|
||||
EFI_TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 =
|
||||
(EFI_TCG_BOOT_SERVICE_CAPABILITY*) &capability;
|
||||
if (caps_1_0->TPMPresentFlag)
|
||||
return tcg;
|
||||
}
|
||||
assert(capability.Size >= endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, Size));
|
||||
|
||||
/* This is a paranoia check, given these fields existed from day one of the spec. But the spec also
|
||||
* suggests checking the structure size before accessing any fields, hence let's do so, for extra
|
||||
* paranoia. */
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
if (ret_version)
|
||||
*ret_version = capability.ProtocolVersion;
|
||||
|
||||
return tcg;
|
||||
}
|
||||
|
||||
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 active_pcr_banks = 0;
|
||||
EFI_TCG2_PROTOCOL *tpm2;
|
||||
EFI_STATUS err;
|
||||
|
||||
tpm2 = tcg2_interface_check();
|
||||
EFI_TCG2_PROTOCOL *tpm2;
|
||||
EFI_TCG2_VERSION version;
|
||||
tpm2 = tcg2_interface_check(&version);
|
||||
if (!tpm2)
|
||||
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);
|
||||
if (err != EFI_SUCCESS) {
|
||||
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);
|
||||
|
||||
tpm2 = tcg2_interface_check();
|
||||
tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
|
||||
if (!tpm2) {
|
||||
*ret_measured = false;
|
||||
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
|
||||
* 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 (ret_measured)
|
||||
*ret_measured = false;
|
||||
|
||||
@ -10,27 +10,11 @@
|
||||
#define EV_IPL 13
|
||||
#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 {
|
||||
uint8_t Major;
|
||||
uint8_t Minor;
|
||||
} 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 {
|
||||
uint8_t Size;
|
||||
EFI_TCG2_VERSION StructureVersion;
|
||||
|
||||
@ -131,8 +131,7 @@ libcore_static = static_library(
|
||||
include_directories : [includes, include_directories('.')],
|
||||
implicit_include_directories : false,
|
||||
c_args : ['-fvisibility=default'],
|
||||
dependencies : [libacl,
|
||||
libaudit_cflags,
|
||||
dependencies : [libaudit_cflags,
|
||||
libblkid,
|
||||
libdl,
|
||||
libm,
|
||||
|
||||
@ -24,7 +24,7 @@ executables += [
|
||||
'sources' : systemd_coredump_sources + systemd_coredump_extract_sources,
|
||||
'extract' : systemd_coredump_extract_sources,
|
||||
'link_with' : [libshared],
|
||||
'dependencies' : common_dependencies + [libacl],
|
||||
'dependencies' : common_dependencies,
|
||||
},
|
||||
executable_template + {
|
||||
'name' : 'coredumpctl',
|
||||
|
||||
@ -17,10 +17,10 @@
|
||||
*p = func(*p); \
|
||||
}
|
||||
|
||||
/* When func() doesn't return the appropriate type, set variable to empty afterwards.
|
||||
* The func() may be provided by a dynamically loaded shared library, hence add an assertion. */
|
||||
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \
|
||||
static inline void func##p(type *p) { \
|
||||
/* When func() doesn't return the appropriate type, set variable to empty afterwards. The func() may be
|
||||
* provided by a dynamically loaded (dlopen()) shared library, hence add an assertion. */
|
||||
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(type, func, name, empty) \
|
||||
static inline void name(type *p) { \
|
||||
if (*p != (empty)) { \
|
||||
DISABLE_WARNING_ADDRESS; \
|
||||
assert(func); \
|
||||
@ -30,6 +30,9 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#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. */
|
||||
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(type, func, empty) \
|
||||
static inline void func##p(type *p) { \
|
||||
|
||||
@ -49,7 +49,6 @@ executables += [
|
||||
'include_directories' : [libexec_template['include_directories'], include_directories('.')],
|
||||
'extract' : systemd_logind_extract_sources,
|
||||
'dependencies' : [
|
||||
libacl,
|
||||
threads,
|
||||
],
|
||||
},
|
||||
|
||||
@ -9,7 +9,6 @@ executables += [
|
||||
'name' : 'systemd-pstore',
|
||||
'sources' : files('pstore.c'),
|
||||
'dependencies' : [
|
||||
libacl,
|
||||
liblz4_cflags,
|
||||
libxz_cflags,
|
||||
libzstd_cflags,
|
||||
|
||||
@ -7,11 +7,74 @@
|
||||
#include "errno-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
|
||||
#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) {
|
||||
bool changed = false, found = false;
|
||||
@ -19,43 +82,47 @@ int devnode_acl(int fd, uid_t uid) {
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
r = dlopen_libacl();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_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)
|
||||
return -errno;
|
||||
|
||||
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 = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) {
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) {
|
||||
|
||||
acl_tag_t tag;
|
||||
if (acl_get_tag_type(entry, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(entry, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag != ACL_USER)
|
||||
continue;
|
||||
|
||||
if (uid > 0) {
|
||||
uid_t *u = acl_get_qualifier(entry);
|
||||
uid_t *u = sym_acl_get_qualifier(entry);
|
||||
if (!u)
|
||||
return -errno;
|
||||
|
||||
if (*u == uid) {
|
||||
acl_permset_t permset;
|
||||
if (acl_get_permset(entry, &permset) < 0)
|
||||
if (sym_acl_get_permset(entry, &permset) < 0)
|
||||
return -errno;
|
||||
|
||||
int rd = acl_get_perm(permset, ACL_READ);
|
||||
int rd = sym_acl_get_perm(permset, ACL_READ);
|
||||
if (rd < 0)
|
||||
return -errno;
|
||||
|
||||
int wt = acl_get_perm(permset, ACL_WRITE);
|
||||
int wt = sym_acl_get_perm(permset, ACL_WRITE);
|
||||
if (wt < 0)
|
||||
return -errno;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
changed = true;
|
||||
@ -75,20 +142,20 @@ int devnode_acl(int fd, uid_t uid) {
|
||||
return -errno;
|
||||
|
||||
if (!found && uid > 0) {
|
||||
if (acl_create_entry(&acl, &entry) < 0)
|
||||
if (sym_acl_create_entry(&acl, &entry) < 0)
|
||||
return -errno;
|
||||
|
||||
if (acl_set_tag_type(entry, ACL_USER) < 0)
|
||||
if (sym_acl_set_tag_type(entry, ACL_USER) < 0)
|
||||
return -errno;
|
||||
|
||||
if (acl_set_qualifier(entry, &uid) < 0)
|
||||
if (sym_acl_set_qualifier(entry, &uid) < 0)
|
||||
return -errno;
|
||||
|
||||
acl_permset_t permset;
|
||||
if (acl_get_permset(entry, &permset) < 0)
|
||||
if (sym_acl_get_permset(entry, &permset) < 0)
|
||||
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;
|
||||
|
||||
changed = true;
|
||||
@ -97,10 +164,10 @@ int devnode_acl(int fd, uid_t uid) {
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
if (acl_calc_mask(&acl) < 0)
|
||||
if (sym_acl_calc_mask(&acl) < 0)
|
||||
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 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(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 = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
|
||||
acl_tag_t tag;
|
||||
uid_t *u;
|
||||
bool b;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag != ACL_USER)
|
||||
continue;
|
||||
|
||||
u = acl_get_qualifier(i);
|
||||
_cleanup_(acl_free_uid_tpp) uid_t *u = NULL;
|
||||
u = sym_acl_get_qualifier(i);
|
||||
if (!u)
|
||||
return -errno;
|
||||
|
||||
b = *u == uid;
|
||||
acl_free(u);
|
||||
|
||||
if (b) {
|
||||
*ret_entry = i;
|
||||
return 1;
|
||||
@ -154,12 +219,12 @@ int calc_acl_mask_if_needed(acl_t *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 = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
|
||||
r = sym_acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
|
||||
acl_tag_t tag;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag == ACL_MASK)
|
||||
@ -171,7 +236,7 @@ int calc_acl_mask_if_needed(acl_t *acl_p) {
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (need && acl_calc_mask(acl_p) < 0)
|
||||
if (need && sym_acl_calc_mask(acl_p) < 0)
|
||||
return -errno;
|
||||
|
||||
return need;
|
||||
@ -187,12 +252,12 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
|
||||
assert(acl_p);
|
||||
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 = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
|
||||
r = sym_acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
|
||||
acl_tag_t tag;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
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)
|
||||
return -errno;
|
||||
|
||||
r = stat(path, &st);
|
||||
if (r < 0)
|
||||
if (stat(path, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
basic = acl_from_mode(st.st_mode);
|
||||
basic = sym_acl_from_mode(st.st_mode);
|
||||
if (!basic)
|
||||
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 = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) {
|
||||
r = sym_acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) {
|
||||
acl_tag_t tag;
|
||||
acl_entry_t dst;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
r = acl_create_entry(acl_p, &dst);
|
||||
r = sym_acl_create_entry(acl_p, &dst);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = acl_copy_entry(dst, i);
|
||||
r = sym_acl_copy_entry(dst, i);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
}
|
||||
@ -251,11 +315,15 @@ int acl_search_groups(const char *path, char ***ret_groups) {
|
||||
|
||||
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)
|
||||
return -errno;
|
||||
|
||||
r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
|
||||
r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
|
||||
for (;;) {
|
||||
_cleanup_(acl_free_gid_tpp) gid_t *gid = NULL;
|
||||
acl_tag_t tag;
|
||||
@ -265,13 +333,13 @@ int acl_search_groups(const char *path, char ***ret_groups) {
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (acl_get_tag_type(entry, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(entry, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag != ACL_GROUP)
|
||||
goto next;
|
||||
|
||||
gid = acl_get_qualifier(entry);
|
||||
gid = sym_acl_get_qualifier(entry);
|
||||
if (!gid)
|
||||
return -errno;
|
||||
|
||||
@ -295,7 +363,7 @@ int acl_search_groups(const char *path, char ***ret_groups) {
|
||||
}
|
||||
|
||||
next:
|
||||
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
|
||||
}
|
||||
|
||||
if (ret_groups)
|
||||
@ -324,6 +392,10 @@ int parse_acl(
|
||||
if (!split)
|
||||
return -ENOMEM;
|
||||
|
||||
r = dlopen_libacl();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(entry, split) {
|
||||
_cleanup_strv_free_ char **entry_split = NULL;
|
||||
_cleanup_free_ char *entry_join = NULL;
|
||||
@ -368,7 +440,7 @@ int parse_acl(
|
||||
if (!join)
|
||||
return -ENOMEM;
|
||||
|
||||
a_acl = acl_from_text(join);
|
||||
a_acl = sym_acl_from_text(join);
|
||||
if (!a_acl)
|
||||
return -errno;
|
||||
|
||||
@ -386,7 +458,7 @@ int parse_acl(
|
||||
if (!join)
|
||||
return -ENOMEM;
|
||||
|
||||
e_acl = acl_from_text(join);
|
||||
e_acl = sym_acl_from_text(join);
|
||||
if (!e_acl)
|
||||
return -errno;
|
||||
|
||||
@ -400,7 +472,7 @@ int parse_acl(
|
||||
if (!join)
|
||||
return -ENOMEM;
|
||||
|
||||
d_acl = acl_from_text(join);
|
||||
d_acl = sym_acl_from_text(join);
|
||||
if (!d_acl)
|
||||
return -errno;
|
||||
|
||||
@ -421,10 +493,10 @@ int parse_acl(
|
||||
static int acl_entry_equal(acl_entry_t a, acl_entry_t 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;
|
||||
|
||||
if (acl_get_tag_type(b, &tag_b) < 0)
|
||||
if (sym_acl_get_tag_type(b, &tag_b) < 0)
|
||||
return -errno;
|
||||
|
||||
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: {
|
||||
_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)
|
||||
return -errno;
|
||||
|
||||
uid_b = acl_get_qualifier(b);
|
||||
uid_b = sym_acl_get_qualifier(b);
|
||||
if (!uid_b)
|
||||
return -errno;
|
||||
|
||||
@ -453,11 +525,11 @@ static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
|
||||
case ACL_GROUP: {
|
||||
_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)
|
||||
return -errno;
|
||||
|
||||
gid_b = acl_get_qualifier(b);
|
||||
gid_b = sym_acl_get_qualifier(b);
|
||||
if (!gid_b)
|
||||
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;
|
||||
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 = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
|
||||
r = acl_entry_equal(i, entry);
|
||||
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);
|
||||
|
||||
applied = acl_get_file(path, type);
|
||||
r = dlopen_libacl();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
applied = sym_acl_get_file(path, type);
|
||||
if (!applied)
|
||||
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 = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
|
||||
acl_entry_t j;
|
||||
|
||||
r = find_acl_entry(applied, i, &j);
|
||||
if (r == -ENOENT) {
|
||||
if (acl_create_entry(&applied, &j) < 0)
|
||||
if (sym_acl_create_entry(&applied, &j) < 0)
|
||||
return -errno;
|
||||
} else if (r < 0)
|
||||
return r;
|
||||
|
||||
if (acl_copy_entry(j, i) < 0)
|
||||
if (sym_acl_copy_entry(j, i) < 0)
|
||||
return -errno;
|
||||
}
|
||||
if (r < 0)
|
||||
@ -553,33 +629,37 @@ int fd_add_uid_acl_permission(
|
||||
assert(fd >= 0);
|
||||
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)
|
||||
return -errno;
|
||||
|
||||
r = acl_find_uid(acl, uid, &entry);
|
||||
if (r <= 0) {
|
||||
if (acl_create_entry(&acl, &entry) < 0 ||
|
||||
acl_set_tag_type(entry, ACL_USER) < 0 ||
|
||||
acl_set_qualifier(entry, &uid) < 0)
|
||||
if (sym_acl_create_entry(&acl, &entry) < 0 ||
|
||||
sym_acl_set_tag_type(entry, ACL_USER) < 0 ||
|
||||
sym_acl_set_qualifier(entry, &uid) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (acl_get_permset(entry, &permset) < 0)
|
||||
if (sym_acl_get_permset(entry, &permset) < 0)
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
r = calc_acl_mask_if_needed(&acl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (acl_set_fd(fd, acl) < 0)
|
||||
if (sym_acl_set_fd(fd, acl) < 0)
|
||||
return -errno;
|
||||
|
||||
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
|
||||
* 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 (!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);
|
||||
}
|
||||
|
||||
for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
|
||||
for (r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
|
||||
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_tag_t tag;
|
||||
int b;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
/* 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))
|
||||
continue;
|
||||
|
||||
if (acl_get_permset(i, &permset) < 0)
|
||||
if (sym_acl_get_permset(i, &permset) < 0)
|
||||
return -errno;
|
||||
|
||||
b = acl_get_perm(permset, ACL_WRITE);
|
||||
b = sym_acl_get_perm(permset, ACL_WRITE);
|
||||
if (b < 0)
|
||||
return -errno;
|
||||
|
||||
if (b) {
|
||||
if (acl_delete_perm(permset, ACL_WRITE) < 0)
|
||||
if (sym_acl_delete_perm(permset, ACL_WRITE) < 0)
|
||||
return -errno;
|
||||
|
||||
changed = true;
|
||||
@ -640,7 +724,7 @@ int fd_acl_make_read_only(int fd) {
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
if (acl_set_fd(fd, acl) < 0) {
|
||||
if (sym_acl_set_fd(fd, acl) < 0) {
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(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
|
||||
* 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 (!ERRNO_IS_NOT_SUPPORTED(errno))
|
||||
return -errno;
|
||||
@ -667,30 +755,30 @@ int fd_acl_make_writable(int 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 = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
acl_permset_t permset;
|
||||
acl_tag_t tag;
|
||||
int b;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag != ACL_USER_OBJ)
|
||||
continue;
|
||||
|
||||
if (acl_get_permset(i, &permset) < 0)
|
||||
if (sym_acl_get_permset(i, &permset) < 0)
|
||||
return -errno;
|
||||
|
||||
b = acl_get_perm(permset, ACL_WRITE);
|
||||
b = sym_acl_get_perm(permset, ACL_WRITE);
|
||||
if (b < 0)
|
||||
return -errno;
|
||||
|
||||
if (b)
|
||||
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;
|
||||
|
||||
break;
|
||||
@ -698,7 +786,7 @@ int fd_acl_make_writable(int fd) {
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (acl_set_fd(fd, acl) < 0) {
|
||||
if (sym_acl_set_fd(fd, acl) < 0) {
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(errno))
|
||||
return -errno;
|
||||
|
||||
|
||||
@ -10,6 +10,35 @@ int fd_acl_make_writable_fallback(int fd);
|
||||
#include <acl/libacl.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 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_writable(int fd);
|
||||
|
||||
/* acl_free takes multiple argument types.
|
||||
* Multiple cleanup functions are necessary. */
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(acl_t, acl_free, NULL);
|
||||
#define acl_free_charp acl_free
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, acl_free_charp, 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);
|
||||
/* acl_free() takes multiple argument types. Multiple cleanup functions are necessary. */
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(acl_t, sym_acl_free, acl_freep, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(char*, sym_acl_free, acl_free_charpp, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(uid_t*, sym_acl_free, acl_free_uid_tpp, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(gid_t*, sym_acl_free, acl_free_gid_tpp, NULL);
|
||||
|
||||
#else
|
||||
|
||||
#define ACL_READ 0x04
|
||||
#define ACL_WRITE 0x02
|
||||
#define ACL_EXECUTE 0x01
|
||||
|
||||
static inline int dlopen_libacl(void) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int devnode_acl(int fd, uid_t uid) {
|
||||
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) {
|
||||
return fd_acl_make_writable_fallback(fd);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int inode_type_can_acl(mode_t mode);
|
||||
|
||||
@ -312,7 +312,7 @@ man_page_depends += ethtool_link_mode_xml
|
||||
libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag)
|
||||
|
||||
libshared_deps = [threads,
|
||||
libacl,
|
||||
libacl_cflags,
|
||||
libaudit_cflags,
|
||||
libblkid,
|
||||
libcap,
|
||||
|
||||
@ -29,6 +29,7 @@ static const NamingScheme naming_schemes[] = {
|
||||
{ "v255", NAMING_V255 },
|
||||
{ "v257", NAMING_V257 },
|
||||
{ "v258", NAMING_V258 },
|
||||
{ "v259", NAMING_V259 },
|
||||
/* … add more schemes here, as the logic to name devices is updated … */
|
||||
|
||||
EXTRA_NET_NAMING_MAP
|
||||
|
||||
@ -42,6 +42,7 @@ typedef enum NamingSchemeFlags {
|
||||
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_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 */
|
||||
NAMING_V238 = 0,
|
||||
@ -63,6 +64,7 @@ typedef enum NamingSchemeFlags {
|
||||
NAMING_V255 = NAMING_V254 & ~NAMING_BRIDGE_MULTIFUNCTION_SLOT,
|
||||
NAMING_V257 = NAMING_V255 | NAMING_FIRMWARE_NODE_SUN | NAMING_DEVICETREE_PORT_ALIASES,
|
||||
NAMING_V258 = NAMING_V257 | NAMING_USE_INTERFACE_PROPERTY,
|
||||
NAMING_V259 = NAMING_V258 | NAMING_DEVICETREE_ALIASES_WLAN,
|
||||
|
||||
EXTRA_NET_NAMING_SCHEMES
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "acl-util.h"
|
||||
#include "alloc-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.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)
|
||||
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)
|
||||
acl = acl_get_fd(fd);
|
||||
acl = sym_acl_get_fd(fd);
|
||||
else
|
||||
acl = acl_get_file(FORMAT_PROC_FD_PATH(fd), type);
|
||||
acl = sym_acl_get_file(FORMAT_PROC_FD_PATH(fd), type);
|
||||
if (!acl)
|
||||
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)
|
||||
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)
|
||||
r = acl_set_fd(fd, acl);
|
||||
r = sym_acl_set_fd(fd, acl);
|
||||
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)
|
||||
return -errno;
|
||||
|
||||
@ -80,7 +81,7 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
|
||||
assert(acl);
|
||||
assert(ret);
|
||||
|
||||
r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
|
||||
r = sym_acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
while (r > 0) {
|
||||
@ -88,7 +89,7 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
|
||||
bool modify = false;
|
||||
acl_tag_t tag;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
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 */
|
||||
assert_cc(sizeof(uid_t) == sizeof(gid_t));
|
||||
|
||||
old_uid = acl_get_qualifier(i);
|
||||
old_uid = sym_acl_get_qualifier(i);
|
||||
if (!old_uid)
|
||||
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
|
||||
* 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)
|
||||
return -errno;
|
||||
|
||||
copy = acl_init(n);
|
||||
copy = sym_acl_init(n);
|
||||
if (!copy)
|
||||
return -errno;
|
||||
|
||||
/* 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)
|
||||
return -errno;
|
||||
continue;
|
||||
@ -131,18 +132,18 @@ static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) {
|
||||
if (copy) {
|
||||
acl_entry_t new_entry;
|
||||
|
||||
if (acl_create_entry(©, &new_entry) < 0)
|
||||
if (sym_acl_create_entry(©, &new_entry) < 0)
|
||||
return -errno;
|
||||
|
||||
if (acl_copy_entry(new_entry, i) < 0)
|
||||
if (sym_acl_copy_entry(new_entry, i) < 0)
|
||||
return -errno;
|
||||
|
||||
if (modify)
|
||||
if (acl_set_qualifier(new_entry, &new_uid) < 0)
|
||||
if (sym_acl_set_qualifier(new_entry, &new_uid) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i);
|
||||
r = sym_acl_get_entry(acl, ACL_NEXT_ENTRY, &i);
|
||||
if (r < 0)
|
||||
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))
|
||||
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);
|
||||
if (r == -EOPNOTSUPP)
|
||||
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)) {
|
||||
acl_free(acl);
|
||||
sym_acl_free(acl);
|
||||
|
||||
if (shifted)
|
||||
acl_free(shifted);
|
||||
sym_acl_free(shifted);
|
||||
|
||||
acl = shifted = NULL;
|
||||
|
||||
|
||||
@ -400,7 +400,6 @@ executables += [
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-shift-uid.c'),
|
||||
'dependencies' : libacl,
|
||||
'type' : 'manual',
|
||||
},
|
||||
test_template + {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "acl-util.h"
|
||||
#include "apparmor-util.h"
|
||||
#include "bpf-dlopen.h"
|
||||
#include "compress.h"
|
||||
@ -52,6 +53,7 @@ static int run(int argc, char **argv) {
|
||||
ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR);
|
||||
ASSERT_DLOPEN(dlopen_libaudit, HAVE_AUDIT);
|
||||
ASSERT_DLOPEN(dlopen_libpam, HAVE_PAM);
|
||||
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ executables += [
|
||||
'public' : true,
|
||||
'sources' : systemd_tmpfiles_sources + systemd_tmpfiles_extract_sources,
|
||||
'extract' : systemd_tmpfiles_extract_sources,
|
||||
'dependencies' : libacl,
|
||||
'dependencies' : libacl_cflags,
|
||||
},
|
||||
executable_template + {
|
||||
'name' : 'systemd-tmpfiles.standalone',
|
||||
@ -30,7 +30,7 @@ executables += [
|
||||
libshared_static,
|
||||
libsystemd_static,
|
||||
],
|
||||
'dependencies' : libacl,
|
||||
'dependencies' : libacl_cflags,
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-offline-passwd.c'),
|
||||
|
||||
@ -1271,22 +1271,26 @@ static int parse_acl_cond_exec(
|
||||
assert(cond_exec);
|
||||
assert(ret);
|
||||
|
||||
r = dlopen_libacl();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!S_ISDIR(st->st_mode)) {
|
||||
_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)
|
||||
return -errno;
|
||||
|
||||
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 = acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) {
|
||||
r = sym_acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) {
|
||||
|
||||
acl_tag_t tag;
|
||||
|
||||
if (acl_get_tag_type(entry, &tag) < 0)
|
||||
if (sym_acl_get_tag_type(entry, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag == ACL_MASK)
|
||||
@ -1296,10 +1300,10 @@ static int parse_acl_cond_exec(
|
||||
if (!append && IN_SET(tag, ACL_USER, ACL_GROUP))
|
||||
continue;
|
||||
|
||||
if (acl_get_permset(entry, &permset) < 0)
|
||||
if (sym_acl_get_permset(entry, &permset) < 0)
|
||||
return -errno;
|
||||
|
||||
r = acl_get_perm(permset, ACL_EXECUTE);
|
||||
r = sym_acl_get_perm(permset, ACL_EXECUTE);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
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 */
|
||||
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 = 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;
|
||||
|
||||
r = acl_get_perm(permset, ACL_EXECUTE);
|
||||
r = sym_acl_get_perm(permset, ACL_EXECUTE);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (r > 0) {
|
||||
@ -1333,28 +1337,28 @@ static int parse_acl_cond_exec(
|
||||
} else
|
||||
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)
|
||||
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 = 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;
|
||||
|
||||
if (acl_create_entry(&parsed, &parsed_entry) < 0)
|
||||
if (sym_acl_create_entry(&parsed, &parsed_entry) < 0)
|
||||
return -errno;
|
||||
|
||||
if (acl_copy_entry(parsed_entry, entry) < 0)
|
||||
if (sym_acl_copy_entry(parsed_entry, entry) < 0)
|
||||
return -errno;
|
||||
|
||||
/* We substituted 'X' with 'x' in parse_acl(), so drop execute bit here if not applicable. */
|
||||
if (!has_exec) {
|
||||
if (acl_get_permset(parsed_entry, &permset) < 0)
|
||||
if (sym_acl_get_permset(parsed_entry, &permset) < 0)
|
||||
return -errno;
|
||||
|
||||
if (acl_delete_perm(permset, ACL_EXECUTE) < 0)
|
||||
if (sym_acl_delete_perm(permset, ACL_EXECUTE) < 0)
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
@ -1386,6 +1390,10 @@ static int path_set_acl(
|
||||
|
||||
assert(c);
|
||||
|
||||
r = dlopen_libacl();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Returns 0 for success, positive error if already warned, negative error otherwise. */
|
||||
|
||||
if (modify) {
|
||||
@ -1397,7 +1405,7 @@ static int path_set_acl(
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
dup = acl_dup(acl);
|
||||
dup = sym_acl_dup(acl);
|
||||
if (!dup)
|
||||
return -errno;
|
||||
|
||||
@ -1408,14 +1416,14 @@ static int path_set_acl(
|
||||
if (r < 0)
|
||||
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",
|
||||
"%s %s ACL %s on %s",
|
||||
type == ACL_TYPE_ACCESS ? "access" : "default",
|
||||
strna(t), pretty);
|
||||
|
||||
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))
|
||||
/* No error if filesystem doesn't support ACLs. Return negative. */
|
||||
return -errno;
|
||||
@ -3295,13 +3303,13 @@ static void item_free_contents(Item *i) {
|
||||
|
||||
#if HAVE_ACL
|
||||
if (i->acl_access)
|
||||
acl_free(i->acl_access);
|
||||
sym_acl_free(i->acl_access);
|
||||
|
||||
if (i->acl_access_exec)
|
||||
acl_free(i->acl_access_exec);
|
||||
sym_acl_free(i->acl_access_exec);
|
||||
|
||||
if (i->acl_default)
|
||||
acl_free(i->acl_default);
|
||||
sym_acl_free(i->acl_default);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -114,7 +114,7 @@ endif
|
||||
############################################################
|
||||
|
||||
udev_dependencies = [
|
||||
libacl,
|
||||
libacl_cflags,
|
||||
libblkid,
|
||||
libkmod,
|
||||
threads,
|
||||
@ -131,7 +131,7 @@ udev_plugin_template = executable_template + {
|
||||
udev_common_template = {
|
||||
'objects' : ['udevadm'],
|
||||
'dependencies' : [
|
||||
libacl,
|
||||
libacl_cflags,
|
||||
libblkid,
|
||||
threads,
|
||||
],
|
||||
|
||||
@ -788,20 +788,20 @@ static int names_platform(UdevEvent *event, const char *prefix) {
|
||||
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);
|
||||
_cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL;
|
||||
const char *ofnode_path, *ofnode_syspath, *devicetree_syspath;
|
||||
int r;
|
||||
|
||||
assert(prefix);
|
||||
assert(alias_prefix);
|
||||
|
||||
if (!naming_scheme_has(NAMING_DEVICETREE_ALIASES))
|
||||
return 0;
|
||||
/* Returns 1 if found, 0 if not found, negative if error */
|
||||
|
||||
/* only ethernet supported for now */
|
||||
if (!streq(prefix, "en"))
|
||||
return -EOPNOTSUPP;
|
||||
_cleanup_free_ char *alias_prefix_0 = strjoin(alias_prefix, "0");
|
||||
if (!alias_prefix_0)
|
||||
return log_oom_debug();
|
||||
|
||||
/* check if the device itself has an of_node */
|
||||
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;
|
||||
unsigned i;
|
||||
|
||||
alias_index = startswith(alias, "ethernet");
|
||||
alias_index = startswith(alias, alias_prefix);
|
||||
if (!alias_index)
|
||||
continue;
|
||||
|
||||
@ -873,31 +873,59 @@ static int names_devicetree(UdevEvent *event, const char *prefix) {
|
||||
/* If there's no index, we default to 0... */
|
||||
if (isempty(alias_index)) {
|
||||
i = 0;
|
||||
conflict = "ethernet0";
|
||||
conflict = alias_prefix_0;
|
||||
} else {
|
||||
r = safe_atou(alias_index, &i);
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(dev, r,
|
||||
"Could not get index of alias %s: %m", alias);
|
||||
conflict = "ethernet";
|
||||
conflict = alias_prefix;
|
||||
}
|
||||
|
||||
/* ...but make sure we don't have an alias conflict */
|
||||
if (i == 0 && device_get_sysattr_value_filtered(aliases_dev, conflict, NULL) >= 0)
|
||||
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];
|
||||
if (snprintf_ok(str, sizeof str, "%sd%u", prefix, i))
|
||||
udev_builtin_add_property(event, "ID_NET_NAME_ONBOARD", str);
|
||||
log_device_debug(dev, "DeviceTree identifier: alias_index=%u %s \"%s\"",
|
||||
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) {
|
||||
sd_device *parent, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
|
||||
_cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user