Merge pull request #15955 from anitazha/nullorempty

core: check null_or_empty_path for masked units instead of /dev/null
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-07-08 22:18:17 +02:00 committed by GitHub
commit 02b0109af5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 12 deletions

View File

@ -5955,7 +5955,7 @@ const char *unit_label_path(const Unit *u) {
return NULL;
/* If a unit is masked, then don't read the SELinux label of /dev/null, as that really makes no sense */
if (path_equal(p, "/dev/null"))
if (null_or_empty_path(p) > 0)
return NULL;
return p;

View File

@ -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,26 +1323,40 @@ static int unit_file_load_or_readlink(
const char *path,
const char *root_dir,
SearchFlags flags) {
_cleanup_free_ char *target = NULL;
_cleanup_free_ char *resolved = NULL;
struct stat st;
int r;
r = unit_file_load(c, info, path, root_dir, flags);
if (r != -ELOOP || (flags & SEARCH_DROPIN))
return r;
/* This is a symlink, let's read it. */
r = readlink_malloc(path, &target);
if (r < 0)
return r;
if (path_equal(target, "/dev/null"))
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. 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)
return r;
bn = basename(target);
if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {

View File

@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "install.h"
#include "mkdir.h"
#include "rm-rf.h"
@ -23,6 +24,7 @@ static void test_basic_mask_and_enable(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) == -ENOENT);
p = strjoina(root, "/usr/lib/systemd/system/a.service");
assert_se(write_string_file(p,
@ -150,6 +152,22 @@ static void test_basic_mask_and_enable(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
/* Test masking with relative symlinks */
p = strjoina(root, "/usr/lib/systemd/system/e.service");
assert_se(symlink("../../../../../../dev/null", p) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", &state) >= 0 && state == UNIT_FILE_MASKED);
assert_se(unlink(p) == 0);
assert_se(symlink("/usr/../dev/null", p) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", &state) >= 0 && state == UNIT_FILE_MASKED);
assert_se(unlink(p) == 0);
}
static void test_linked_units(const char *root) {