Merge pull request #23009 from keszybz/fix-detection-of-libsystemd-shared-with-suffix

Fix detection of libsystemd-shared with suffix
This commit is contained in:
Lennart Poettering 2022-04-08 15:43:09 +02:00 committed by GitHub
commit 492f9e74ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 218 additions and 174 deletions

1
README
View file

@ -37,6 +37,7 @@ REQUIREMENTS:
≥ 4.10 for cgroup-bpf egress and ingress hooks
≥ 4.15 for cgroup-bpf device hook and cpu controller in cgroup v2
≥ 4.17 for cgroup-bpf socket address hooks
≥ 4.20 for PSI (used by systemd-oomd)
≥ 5.3 for bounded loops in BPF program
≥ 5.4 for signed Verity images
≥ 5.7 for BPF links and the BPF LSM hook

View file

@ -4,6 +4,7 @@
* Use 'ninja -C build update-syscall-tables' to download new syscall tables,
* and 'ninja -C build update-syscall-header' to regenerate this file.
*/
#pragma once
/* Note: if this code looks strange, this is because it is derived from the same
* template as the per-syscall blocks below. */

View file

@ -142,6 +142,7 @@ def print_syscall_defs(syscalls, tables, out):
* Use 'ninja -C build update-syscall-tables' to download new syscall tables,
* and 'ninja -C build update-syscall-header' to regenerate this file.
*/
#pragma once
''',
file=out)
print(ARCH_CHECK, file=out)

View file

@ -17,17 +17,13 @@
#include "extract-word.h"
#include "fd-util.h"
#include "fs-util.h"
#include "glob-util.h"
#include "log.h"
#include "macro.h"
#include "nulstr-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "utf8.h"
int path_split_and_make_absolute(const char *p, char ***ret) {
char **l;
@ -376,52 +372,6 @@ char *path_simplify(char *path) {
return path;
}
int path_simplify_and_warn(
char *path,
unsigned flag,
const char *unit,
const char *filename,
unsigned line,
const char *lvalue) {
bool fatal = flag & PATH_CHECK_FATAL;
assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
if (!utf8_is_valid(path))
return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
bool absolute;
absolute = path_is_absolute(path);
if (!absolute && (flag & PATH_CHECK_ABSOLUTE))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path is not absolute%s: %s",
lvalue, fatal ? "" : ", ignoring", path);
if (absolute && (flag & PATH_CHECK_RELATIVE))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path is absolute%s: %s",
lvalue, fatal ? "" : ", ignoring", path);
}
path_simplify(path);
if (!path_is_valid(path))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path has invalid length (%zu bytes)%s.",
lvalue, strlen(path), fatal ? "" : ", ignoring");
if (!path_is_normalized(path))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path is not normalized%s: %s",
lvalue, fatal ? "" : ", ignoring", path);
return 0;
}
char *path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) {
assert(path);
assert(prefix);
@ -1314,74 +1264,6 @@ bool valid_device_allow_pattern(const char *path) {
return valid_device_node_path(path);
}
int systemd_installation_has_version(const char *root, unsigned minimal_version) {
const char *pattern;
int r;
/* Try to guess if systemd installation is later than the specified version. This
* is hacky and likely to yield false negatives, particularly if the installation
* is non-standard. False positives should be relatively rare.
*/
NULSTR_FOREACH(pattern,
/* /lib works for systems without usr-merge, and for systems with a sane
* usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary
* for Gentoo which does a merge without making /lib a symlink.
*/
"lib/systemd/libsystemd-shared-*.so\0"
"lib64/systemd/libsystemd-shared-*.so\0"
"usr/lib/systemd/libsystemd-shared-*.so\0"
"usr/lib64/systemd/libsystemd-shared-*.so\0") {
_cleanup_strv_free_ char **names = NULL;
_cleanup_free_ char *path = NULL;
char *c;
path = path_join(root, pattern);
if (!path)
return -ENOMEM;
r = glob_extend(&names, path, 0);
if (r == -ENOENT)
continue;
if (r < 0)
return r;
assert_se(c = endswith(path, "*.so"));
*c = '\0'; /* truncate the glob part */
STRV_FOREACH(name, names) {
/* This is most likely to run only once, hence let's not optimize anything. */
char *t, *t2;
unsigned version;
t = startswith(*name, path);
if (!t)
continue;
t2 = endswith(t, ".so");
if (!t2)
continue;
t2[0] = '\0'; /* truncate the suffix */
r = safe_atou(t, &version);
if (r < 0) {
log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name);
continue;
}
log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).",
*name, version,
version >= minimal_version ? "OK" : "too old");
if (version >= minimal_version)
return true;
}
}
return false;
}
bool dot_or_dot_dot(const char *path) {
if (!path)
return false;

View file

@ -77,14 +77,6 @@ char* path_extend_internal(char **x, ...);
char* path_simplify(char *path);
enum {
PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */
PATH_CHECK_ABSOLUTE = 1 << 1,
PATH_CHECK_RELATIVE = 1 << 2,
};
int path_simplify_and_warn(char *path, unsigned flag, const char *unit, const char *filename, unsigned line, const char *lvalue);
static inline bool path_equal_ptr(const char *a, const char *b) {
return !!a == !!b && (!a || path_equal(a, b));
}
@ -181,8 +173,6 @@ bool is_device_path(const char *path);
bool valid_device_node_path(const char *path);
bool valid_device_allow_pattern(const char *path);
int systemd_installation_has_version(const char *root, unsigned minimal_version);
bool dot_or_dot_dot(const char *path);
static inline const char *skip_dev_prefix(const char *p) {

View file

@ -473,6 +473,7 @@ sendmmsg
sendmsg
sendto
set_mempolicy
set_mempolicy_home_node
set_robust_list
set_thread_area
set_tid_address

View file

@ -473,6 +473,7 @@ sendmmsg 503
sendmsg 114
sendto 133
set_mempolicy 431
set_mempolicy_home_node 560
set_robust_list 466
set_thread_area
set_tid_address 411

View file

@ -473,6 +473,7 @@ sendmmsg 269
sendmsg 211
sendto 206
set_mempolicy 237
set_mempolicy_home_node 450
set_robust_list 99
set_thread_area
set_tid_address 96

View file

@ -473,6 +473,7 @@ sendmmsg 374
sendmsg 296
sendto 290
set_mempolicy 321
set_mempolicy_home_node 450
set_robust_list 338
set_thread_area
set_tid_address 256

View file

@ -473,6 +473,7 @@ sendmmsg 269
sendmsg 211
sendto 206
set_mempolicy 237
set_mempolicy_home_node 450
set_robust_list 99
set_thread_area
set_tid_address 96

View file

@ -473,6 +473,7 @@ sendmmsg 345
sendmsg 370
sendto 369
set_mempolicy 276
set_mempolicy_home_node 450
set_robust_list 311
set_thread_area 243
set_tid_address 258

View file

@ -473,6 +473,7 @@ sendmmsg 1331
sendmsg 1205
sendto 1199
set_mempolicy 1261
set_mempolicy_home_node 1474
set_robust_list 1298
set_thread_area
set_tid_address 1233

View file

@ -473,6 +473,7 @@ sendmmsg 269
sendmsg 211
sendto 206
set_mempolicy 237
set_mempolicy_home_node 450
set_robust_list 99
set_thread_area
set_tid_address 96

View file

@ -473,6 +473,7 @@ sendmmsg 372
sendmsg 367
sendto 366
set_mempolicy 270
set_mempolicy_home_node 450
set_robust_list 304
set_thread_area 334
set_tid_address 253

View file

@ -473,6 +473,7 @@ sendmmsg 5302
sendmsg 5045
sendto 5043
set_mempolicy 5229
set_mempolicy_home_node 5450
set_robust_list 5268
set_thread_area 5242
set_tid_address 5212

View file

@ -473,6 +473,7 @@ sendmmsg 6307
sendmsg 6045
sendto 6043
set_mempolicy 6233
set_mempolicy_home_node 6450
set_robust_list 6272
set_thread_area 6246
set_tid_address 6213

View file

@ -473,6 +473,7 @@ sendmmsg 4343
sendmsg 4179
sendto 4180
set_mempolicy 4270
set_mempolicy_home_node 4450
set_robust_list 4309
set_thread_area 4283
set_tid_address 4252

View file

@ -473,6 +473,7 @@ sendmmsg 349
sendmsg 341
sendto 335
set_mempolicy 261
set_mempolicy_home_node 450
set_robust_list 300
set_thread_area
set_tid_address 232

View file

@ -473,6 +473,7 @@ sendmmsg 349
sendmsg 341
sendto 335
set_mempolicy 261
set_mempolicy_home_node 450
set_robust_list 300
set_thread_area
set_tid_address 232

View file

@ -473,6 +473,7 @@ sendmmsg 269
sendmsg 211
sendto 206
set_mempolicy 237
set_mempolicy_home_node 450
set_robust_list 99
set_thread_area
set_tid_address 96

View file

@ -473,6 +473,7 @@ sendmmsg 269
sendmsg 211
sendto 206
set_mempolicy 237
set_mempolicy_home_node 450
set_robust_list 99
set_thread_area
set_tid_address 96

View file

@ -473,6 +473,7 @@ sendmmsg 358
sendmsg 370
sendto 369
set_mempolicy 270
set_mempolicy_home_node 450
set_robust_list 304
set_thread_area
set_tid_address 252

View file

@ -473,6 +473,7 @@ sendmmsg 358
sendmsg 370
sendto 369
set_mempolicy 270
set_mempolicy_home_node 450
set_robust_list 304
set_thread_area
set_tid_address 252

View file

@ -473,6 +473,7 @@ sendmmsg 336
sendmsg 114
sendto 133
set_mempolicy 305
set_mempolicy_home_node 450
set_robust_list 300
set_thread_area
set_tid_address 166

View file

@ -473,6 +473,7 @@ sendmmsg 307
sendmsg 46
sendto 44
set_mempolicy 238
set_mempolicy_home_node 450
set_robust_list 273
set_thread_area 205
set_tid_address 218

View file

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <efi.h>

View file

@ -49,7 +49,7 @@
#include "missing_ioprio.h"
#include "mountpoint-util.h"
#include "nulstr-util.h"
#include "parse-socket-bind-item.h"
#include "parse-helpers.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"

View file

@ -16,7 +16,6 @@
int locale_setup(char ***environment) {
_cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {};
_cleanup_strv_free_ char **add = NULL;
LocaleVariable i;
int r;
r = proc_cmdline_get_key_many(PROC_CMDLINE_STRIP_RD_PREFIX,
@ -58,7 +57,7 @@ int locale_setup(char ***environment) {
log_warning_errno(r, "Failed to read /etc/locale.conf: %m");
}
for (i = 0; i < _VARIABLE_LC_MAX; i++) {
for (LocaleVariable i = 0; i < _VARIABLE_LC_MAX; i++) {
char *s;
if (!variables[i])

View file

@ -23,8 +23,7 @@
#include "main-func.h"
#include "mkdir.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "parse-helpers.h"
#include "pretty-print.h"
#include "process-util.h"
#include "rlimit-util.h"

View file

@ -14,7 +14,7 @@
#include "memory-util.h"
#include "netlink-util.h"
#include "networkd-manager.h"
#include "path-util.h"
#include "parse-helpers.h"
#include "socket-util.h"
#include "string-table.h"
#include "string-util.h"

View file

@ -23,8 +23,8 @@
#include "networkd-route-util.h"
#include "networkd-route.h"
#include "networkd-util.h"
#include "parse-helpers.h"
#include "parse-util.h"
#include "path-util.h"
#include "random-util.h"
#include "resolve-private.h"
#include "string-util.h"

View file

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <inttypes.h>

View file

@ -28,6 +28,8 @@ libnspawn_core_sources = files(
'nspawn-setuid.h',
'nspawn-stub-pid1.c',
'nspawn-stub-pid1.h',
'nspawn-util.c',
'nspawn-util.h',
'nspawn.h',
)
@ -58,6 +60,11 @@ tests += [
libshared],
[libseccomp]],
[files('test-nspawn-util.c'),
[libnspawn_core,
libshared],
[libseccomp]],
[files('test-patch-uid.c'),
[libnspawn_core,
libshared],

69
src/nspawn/nspawn-util.c Normal file
View file

@ -0,0 +1,69 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "glob-util.h"
#include "log.h"
#include "nspawn-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "string-util.h"
int systemd_installation_has_version(const char *root, const char *minimal_version) {
int r;
/* Try to guess if systemd installation is later than the specified version. This
* is hacky and likely to yield false negatives, particularly if the installation
* is non-standard. False positives should be relatively rare.
*/
FOREACH_STRING(pattern,
/* /lib works for systems without usr-merge, and for systems with a sane
* usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary
* for Gentoo which does a merge without making /lib a symlink.
*/
"/lib/systemd/libsystemd-shared-*.so",
"/lib64/systemd/libsystemd-shared-*.so",
"/usr/lib/systemd/libsystemd-shared-*.so",
"/usr/lib64/systemd/libsystemd-shared-*.so") {
_cleanup_strv_free_ char **names = NULL;
_cleanup_free_ char *path = NULL;
char *c;
path = path_join(root, pattern);
if (!path)
return -ENOMEM;
r = glob_extend(&names, path, 0);
if (r == -ENOENT)
continue;
if (r < 0)
return r;
assert_se(c = endswith(path, "*.so"));
*c = '\0'; /* truncate the glob part */
STRV_FOREACH(name, names) {
/* This is most likely to run only once, hence let's not optimize anything. */
char *t, *t2;
t = startswith(*name, path);
if (!t)
continue;
t2 = endswith(t, ".so");
if (!t2)
continue;
*t2 = '\0';
r = strverscmp_improved(t, minimal_version);
log_debug("Found libsystemd shared at \"%s.so\", version %s (%s).",
*name, t,
r >= 0 ? "OK" : "too old");
if (r >= 0)
return true;
}
}
return false;
}

4
src/nspawn/nspawn-util.h Normal file
View file

@ -0,0 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int systemd_installation_has_version(const char *root, const char *minimal_version);

View file

@ -78,13 +78,13 @@
#include "nspawn-settings.h"
#include "nspawn-setuid.h"
#include "nspawn-stub-pid1.h"
#include "nspawn-util.h"
#include "nspawn.h"
#include "nulstr-util.h"
#include "os-util.h"
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "ptyfwd.h"
@ -509,7 +509,7 @@ static int detect_unified_cgroup_hierarchy_from_image(const char *directory) {
if (r > 0) {
/* Unified cgroup hierarchy support was added in 230. Unfortunately the detection
* routine only detects 231, so we'll have a false negative here for 230. */
r = systemd_installation_has_version(directory, 230);
r = systemd_installation_has_version(directory, "230");
if (r < 0)
return log_error_errno(r, "Failed to determine systemd version in container: %m");
if (r > 0)
@ -518,7 +518,7 @@ static int detect_unified_cgroup_hierarchy_from_image(const char *directory) {
arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE;
} else if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) {
/* Mixed cgroup hierarchy support was added in 233 */
r = systemd_installation_has_version(directory, 233);
r = systemd_installation_has_version(directory, "233");
if (r < 0)
return log_error_errno(r, "Failed to determine systemd version in container: %m");
if (r > 0)

View file

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "nspawn-util.h"
#include "string-util.h"
#include "strv.h"
#include "tests.h"
TEST(systemd_installation_has_version) {
int r;
FOREACH_STRING(version, "0", "231", STRINGIFY(PROJECT_VERSION), "999") {
r = systemd_installation_has_version(saved_argv[1], version);
assert_se(r >= 0);
log_info("%s has systemd >= %s: %s",
saved_argv[1] ?: "Current installation", version, yes_no(r));
}
}
/* This program can be called with a path to an installation root.
* For example: build/test-nspawn-util /var/lib/machines/rawhide
*/
DEFINE_TEST_MAIN(LOG_DEBUG);

View file

@ -46,8 +46,7 @@
#include "mount-util.h"
#include "mountpoint-util.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "path-util.h"
#include "parse-helpers.h"
#include "pretty-print.h"
#include "proc-cmdline.h"
#include "process-util.h"

View file

@ -29,7 +29,7 @@
#include "mountpoint-util.h"
#include "nsflags.h"
#include "numa-util.h"
#include "parse-socket-bind-item.h"
#include "parse-helpers.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"

View file

@ -24,6 +24,7 @@
#include "macro.h"
#include "missing_network.h"
#include "nulstr-util.h"
#include "parse-helpers.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"

View file

@ -245,8 +245,8 @@ shared_sources = files(
'pager.h',
'parse-argument.c',
'parse-argument.h',
'parse-socket-bind-item.c',
'parse-socket-bind-item.h',
'parse-helpers.c',
'parse-helpers.h',
'pcre2-dlopen.c',
'pcre2-dlopen.h',
'pe-header.h',

View file

@ -3,8 +3,57 @@
#include "af-list.h"
#include "extract-word.h"
#include "ip-protocol-list.h"
#include "parse-socket-bind-item.h"
#include "log.h"
#include "parse-helpers.h"
#include "parse-util.h"
#include "path-util.h"
#include "utf8.h"
int path_simplify_and_warn(
char *path,
unsigned flag,
const char *unit,
const char *filename,
unsigned line,
const char *lvalue) {
bool fatal = flag & PATH_CHECK_FATAL;
assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
if (!utf8_is_valid(path))
return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
bool absolute;
absolute = path_is_absolute(path);
if (!absolute && (flag & PATH_CHECK_ABSOLUTE))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path is not absolute%s: %s",
lvalue, fatal ? "" : ", ignoring", path);
if (absolute && (flag & PATH_CHECK_RELATIVE))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path is absolute%s: %s",
lvalue, fatal ? "" : ", ignoring", path);
}
path_simplify(path);
if (!path_is_valid(path))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path has invalid length (%zu bytes)%s.",
lvalue, strlen(path), fatal ? "" : ", ignoring");
if (!path_is_normalized(path))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL),
"%s= path is not normalized%s: %s",
lvalue, fatal ? "" : ", ignoring", path);
return 0;
}
static int parse_af_token(
const char *token,

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdint.h>
enum {
PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */
PATH_CHECK_ABSOLUTE = 1 << 1,
PATH_CHECK_RELATIVE = 1 << 2,
};
int path_simplify_and_warn(
char *path,
unsigned flag,
const char *unit,
const char *filename,
unsigned line,
const char *lvalue);
int parse_socket_bind_item(
const char *str,
int *address_family,
int *ip_protocol,
uint16_t *nr_ports,
uint16_t *port_min);

View file

@ -1,12 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdint.h>
int parse_socket_bind_item(
const char *str,
int *address_family,
int *ip_protocol,
uint16_t *nr_ports,
uint16_t *port_min);

View file

@ -12,8 +12,8 @@
#include "gpt.h"
#include "hexdecoct.h"
#include "install-file.h"
#include "parse-helpers.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rm-rf.h"
#include "specifier.h"

View file

@ -261,7 +261,7 @@ tests += [
[files('test-parse-argument.c')],
[files('test-parse-socket-bind-item.c')],
[files('test-parse-helpers.c')],
[files('test-parse-util.c')],

View file

@ -5,7 +5,7 @@
#include <stdio.h>
#include "macro.h"
#include "parse-socket-bind-item.h"
#include "parse-helpers.h"
#include "tests.h"
static void test_valid_item(

View file

@ -960,21 +960,6 @@ TEST(hidden_or_backup_file) {
assert_se(!hidden_or_backup_file("test.dpkg-old.foo"));
}
TEST(systemd_installation_has_version) {
int r;
const unsigned versions[] = {0, 231, PROJECT_VERSION, 999};
unsigned i;
log_info("/* %s */", __func__);
for (i = 0; i < ELEMENTSOF(versions); i++) {
r = systemd_installation_has_version(saved_argv[1], versions[i]);
assert_se(r >= 0);
log_info("%s has systemd >= %u: %s",
saved_argv[1] ?: "Current installation", versions[i], yes_no(r));
}
}
TEST(skip_dev_prefix) {
assert_se(streq(skip_dev_prefix("/"), "/"));
assert_se(streq(skip_dev_prefix("/dev"), ""));