summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-07-05 20:03:48 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-07-05 20:06:22 +0200
commit4276749dd3546dea6cc4a5967c698886829f4573 (patch)
tree453a73cdd552f666b65f2fce6ec94a82eff03676
parentcore: check null_or_empty for masked units instead of /dev/null (diff)
downloadsystemd-4276749dd3546dea6cc4a5967c698886829f4573.tar.xz
systemd-4276749dd3546dea6cc4a5967c698886829f4573.zip
shared/install: do not require /dev/null to be present in chroots
This partially undoes the parent commit. We follow the symlink and if it appears to be a symlink to /dev/null, even if /dev/null is not present, we treat it as such. The addition of creation of /dev/null in the test is reverted.
-rw-r--r--src/shared/install.c22
-rw-r--r--src/test/test-install-root.c6
2 files changed, 17 insertions, 11 deletions
diff --git a/src/shared/install.c b/src/shared/install.c
index 0f2d407a36..fb5e166ff0 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1236,8 +1236,7 @@ static int unit_file_load(
"%s: unit type %s cannot be templated, ignoring.", path, unit_type_to_string(type));
if (!(flags & SEARCH_LOAD)) {
- r = lstat(path, &st);
- if (r < 0)
+ if (lstat(path, &st) < 0)
return -errno;
if (null_or_empty(&st))
@@ -1324,6 +1323,7 @@ static int unit_file_load_or_readlink(
const char *path,
const char *root_dir,
SearchFlags flags) {
+ _cleanup_free_ char *resolved = NULL;
struct stat st;
int r;
@@ -1331,15 +1331,27 @@ static int unit_file_load_or_readlink(
if (r != -ELOOP || (flags & SEARCH_DROPIN))
return r;
- r = chase_symlinks_and_stat(path, root_dir, CHASE_WARN, NULL, &st, NULL);
- if (r > 0 && null_or_empty(&st))
+ r = chase_symlinks(path, root_dir, CHASE_WARN | CHASE_NONEXISTENT, &resolved, NULL);
+ if (r >= 0 &&
+ root_dir &&
+ path_equal_ptr(path_startswith(resolved, root_dir), "dev/null"))
+ /* When looking under root_dir, we can't expect /dev/ to be mounted,
+ * so let's see if the path is a (possibly dangling) symlink to /dev/null. */
+ info->type = UNIT_FILE_TYPE_MASKED;
+
+ else if (r > 0 &&
+ stat(resolved, &st) >= 0 &&
+ null_or_empty(&st))
+
info->type = UNIT_FILE_TYPE_MASKED;
+
else {
_cleanup_free_ char *target = NULL;
const char *bn;
UnitType a, b;
- /* This is a symlink, let's read it. */
+ /* This is a symlink, let's read it. We read the link again, because last time
+ * we followed the link until resolution, and here we need to do one step. */
r = readlink_malloc(path, &target);
if (r < 0)
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index d437686bae..f309160889 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -1245,12 +1245,6 @@ int main(int argc, char *argv[]) {
p = strjoina(root, "/usr/lib/systemd/system-preset/");
assert_se(mkdir_p(p, 0755) >= 0);
- p = strjoina(root, "/dev/");
- assert_se(mkdir_p(p, 0755) >= 0);
-
- p = strjoina(root, "/dev/null");
- assert_se(touch(p) >= 0);
-
test_basic_mask_and_enable(root);
test_linked_units(root);
test_default(root);