summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-01-12 17:18:53 +0100
committerLennart Poettering <lennart@poettering.net>2021-01-19 13:41:42 +0100
commitd577d4a432dd7bb056d2f7df53956122ebcb1ab0 (patch)
tree12fe73d70c67def5ad1cc4b8afd5b8a699928be1 /src/shared
parent7a87fb611986db0b55dbc045230b5edceef05a87 (diff)
downloadsystemd-d577d4a432dd7bb056d2f7df53956122ebcb1ab0.tar.gz
machine-image: properly support searching for images below some --root= path
systemd-sysext supports --root= for everything but the image discovery. Fix that.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/machine-image.c93
-rw-r--r--src/shared/machine-image.h8
2 files changed, 61 insertions, 40 deletions
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index f7b1f90c6f..d2b726efc4 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -421,7 +421,11 @@ static int image_make(
return -EMEDIUMTYPE;
}
-int image_find(ImageClass class, const char *name, Image **ret) {
+int image_find(ImageClass class,
+ const char *name,
+ const char *root,
+ Image **ret) {
+
const char *path;
int r;
@@ -434,20 +438,22 @@ int image_find(ImageClass class, const char *name, Image **ret) {
return -ENOENT;
NULSTR_FOREACH(path, image_search_path[class]) {
+ _cleanup_free_ char *resolved = NULL;
_cleanup_closedir_ DIR *d = NULL;
struct stat st;
+ int flags;
- d = opendir(path);
- if (!d) {
- if (errno == ENOENT)
- continue;
-
- return -errno;
- }
+ r = chase_symlinks_and_opendir(path, root, CHASE_PREFIX_ROOT, &resolved, &d);
+ if (r == -ENOENT)
+ continue;
+ if (r < 0)
+ return r;
- /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people to
- * symlink block devices into the search path */
- if (fstatat(dirfd(d), name, &st, 0) < 0) {
+ /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people
+ * to symlink block devices into the search path. (For now, we disable that when operating
+ * relative to some root directory.) */
+ flags = root ? AT_SYMLINK_NOFOLLOW : 0;
+ if (fstatat(dirfd(d), name, &st, flags) < 0) {
_cleanup_free_ char *raw = NULL;
if (errno != ENOENT)
@@ -457,8 +463,7 @@ int image_find(ImageClass class, const char *name, Image **ret) {
if (!raw)
return -ENOMEM;
- if (fstatat(dirfd(d), raw, &st, 0) < 0) {
-
+ if (fstatat(dirfd(d), raw, &st, flags) < 0) {
if (errno == ENOENT)
continue;
@@ -468,13 +473,13 @@ int image_find(ImageClass class, const char *name, Image **ret) {
if (!S_ISREG(st.st_mode))
continue;
- r = image_make(name, dirfd(d), path, raw, &st, ret);
+ r = image_make(name, dirfd(d), resolved, raw, &st, ret);
} else {
if (!S_ISDIR(st.st_mode) && !S_ISBLK(st.st_mode))
continue;
- r = image_make(name, dirfd(d), path, name, &st, ret);
+ r = image_make(name, dirfd(d), resolved, name, &st, ret);
}
if (IN_SET(r, -ENOENT, -EMEDIUMTYPE))
continue;
@@ -488,7 +493,7 @@ int image_find(ImageClass class, const char *name, Image **ret) {
}
if (class == IMAGE_MACHINE && streq(name, ".host")) {
- r = image_make(".host", AT_FDCWD, NULL, "/", NULL, ret);
+ r = image_make(".host", AT_FDCWD, NULL, empty_to_root(root), NULL, ret);
if (r < 0)
return r;
@@ -513,14 +518,18 @@ int image_from_path(const char *path, Image **ret) {
return image_make(NULL, AT_FDCWD, NULL, path, NULL, ret);
}
-int image_find_harder(ImageClass class, const char *name_or_path, Image **ret) {
+int image_find_harder(ImageClass class, const char *name_or_path, const char *root, Image **ret) {
if (image_name_is_valid(name_or_path))
- return image_find(class, name_or_path, ret);
+ return image_find(class, name_or_path, root, ret);
return image_from_path(name_or_path, ret);
}
-int image_discover(ImageClass class, Hashmap *h) {
+int image_discover(
+ ImageClass class,
+ const char *root,
+ Hashmap *h) {
+
const char *path;
int r;
@@ -529,29 +538,30 @@ int image_discover(ImageClass class, Hashmap *h) {
assert(h);
NULSTR_FOREACH(path, image_search_path[class]) {
+ _cleanup_free_ char *resolved = NULL;
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
- d = opendir(path);
- if (!d) {
- if (errno == ENOENT)
- continue;
-
- return -errno;
- }
+ r = chase_symlinks_and_opendir(path, root, CHASE_PREFIX_ROOT, &resolved, &d);
+ if (r == -ENOENT)
+ continue;
+ if (r < 0)
+ return r;
FOREACH_DIRENT_ALL(de, d, return -errno) {
_cleanup_(image_unrefp) Image *image = NULL;
_cleanup_free_ char *truncated = NULL;
const char *pretty;
struct stat st;
+ int flags;
if (dot_or_dot_dot(de->d_name))
continue;
- /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people
- * to symlink block devices into the search path */
- if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
+ /* As mentioned above, we follow symlinks on this fstatat(), because we want to
+ * permit people to symlink block devices into the search path. */
+ flags = root ? AT_SYMLINK_NOFOLLOW : 0;
+ if (fstatat(dirfd(d), de->d_name, &st, flags) < 0) {
if (errno == ENOENT)
continue;
@@ -581,7 +591,7 @@ int image_discover(ImageClass class, Hashmap *h) {
if (hashmap_contains(h, pretty))
continue;
- r = image_make(pretty, dirfd(d), path, de->d_name, &st, &image);
+ r = image_make(pretty, dirfd(d), resolved, de->d_name, &st, &image);
if (IN_SET(r, -ENOENT, -EMEDIUMTYPE))
continue;
if (r < 0)
@@ -600,7 +610,7 @@ int image_discover(ImageClass class, Hashmap *h) {
if (class == IMAGE_MACHINE && !hashmap_contains(h, ".host")) {
_cleanup_(image_unrefp) Image *image = NULL;
- r = image_make(".host", AT_FDCWD, NULL, "/", NULL, &image);
+ r = image_make(".host", AT_FDCWD, NULL, empty_to_root("/"), NULL, &image);
if (r < 0)
return r;
@@ -743,7 +753,7 @@ int image_rename(Image *i, const char *new_name) {
if (r < 0)
return r;
- r = image_find(IMAGE_MACHINE, new_name, NULL);
+ r = image_find(IMAGE_MACHINE, new_name, NULL, NULL);
if (r >= 0)
return -EEXIST;
if (r != -ENOENT)
@@ -856,7 +866,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
if (r < 0)
return r;
- r = image_find(IMAGE_MACHINE, new_name, NULL);
+ r = image_find(IMAGE_MACHINE, new_name, NULL, NULL);
if (r >= 0)
return -EEXIST;
if (r != -ENOENT)
@@ -1248,16 +1258,27 @@ bool image_name_is_valid(const char *s) {
return true;
}
-bool image_in_search_path(ImageClass class, const char *image) {
+bool image_in_search_path(
+ ImageClass class,
+ const char *root,
+ const char *image) {
+
const char *path;
assert(image);
NULSTR_FOREACH(path, image_search_path[class]) {
- const char *p;
+ const char *p, *q;
size_t k;
- p = path_startswith(image, path);
+ if (!empty_or_root(root)) {
+ q = path_startswith(path, root);
+ if (!q)
+ continue;
+ } else
+ q = path;
+
+ p = path_startswith(q, path);
if (!p)
continue;
diff --git a/src/shared/machine-image.h b/src/shared/machine-image.h
index eea94e0324..c568fff751 100644
--- a/src/shared/machine-image.h
+++ b/src/shared/machine-image.h
@@ -62,10 +62,10 @@ Image *image_ref(Image *i);
DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref);
-int image_find(ImageClass class, const char *name, Image **ret);
+int image_find(ImageClass class, const char *root, const char *name, Image **ret);
int image_from_path(const char *path, Image **ret);
-int image_find_harder(ImageClass class, const char *name_or_path, Image **ret);
-int image_discover(ImageClass class, Hashmap *map);
+int image_find_harder(ImageClass class, const char *root, const char *name_or_path, Image **ret);
+int image_discover(ImageClass class, const char *root, Hashmap *map);
int image_remove(Image *i);
int image_rename(Image *i, const char *new_name);
@@ -84,7 +84,7 @@ int image_set_limit(Image *i, uint64_t referenced_max);
int image_read_metadata(Image *i);
-bool image_in_search_path(ImageClass class, const char *image);
+bool image_in_search_path(ImageClass class, const char *root, const char *image);
static inline bool IMAGE_IS_HIDDEN(const struct Image *i) {
assert(i);