1
0
mirror of https://github.com/systemd/systemd synced 2025-10-06 00:13:24 +02:00

libacl → turn into dlopen() dependency (#39087)

This commit is contained in:
Yu Watanabe
2025-09-24 18:25:20 +09:00
committed by GitHub
15 changed files with 292 additions and 158 deletions

View File

@@ -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'))

View File

@@ -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,

View File

@@ -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',

View File

@@ -17,19 +17,22 @@
*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) { \
if (*p != (empty)) { \
DISABLE_WARNING_ADDRESS; \
assert(func); \
REENABLE_WARNING; \
func(*p); \
*p = (empty); \
} \
/* 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); \
REENABLE_WARNING; \
func(*p); \
*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. */
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(type, func, empty) \
static inline void func##p(type *p) { \

View File

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

View File

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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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(&copy, &new_entry) < 0)
if (sym_acl_create_entry(&copy, &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;

View File

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

View File

@@ -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;
}

View File

@@ -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'),

View File

@@ -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
}

View File

@@ -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,
],