diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-07-05 20:03:48 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-07-05 20:06:22 +0200 |
commit | 4276749dd3546dea6cc4a5967c698886829f4573 (patch) | |
tree | 453a73cdd552f666b65f2fce6ec94a82eff03676 | |
parent | core: check null_or_empty for masked units instead of /dev/null (diff) | |
download | systemd-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.c | 22 | ||||
-rw-r--r-- | src/test/test-install-root.c | 6 |
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); |