discover-image: imply that hidden images are read-only

Marking a whole directory tree OS image as read-only is difficult
privilege-wise, because so far we rely on the FS_IMMUTABLE_FL which is
not accessible to unpriv clients.

One fundamental place where we currently rely on marking images
read-only is for keeping pristine copies of the originally downloaded
image around, which we place in "hidden" image directories. This is
probably the most relevant usecase for the read-only flag. And moreover,
the only usecase for the hidden images are these read-only pristine
copies.

Hence, let's make this work reasonably in the unpriv case, and simply
imply the read-only flag for hidden images. This is strictly speaking a
change in behaviour, but effectively it shouldn't be, because for nspawn
containers that are executed we insist on names that are hostname
compatible, and hidden names aren't (because they start with a dot).
This commit is contained in:
Lennart Poettering
2025-10-24 17:51:00 +02:00
parent 502f7a2b80
commit ee327e086e
10 changed files with 55 additions and 15 deletions
+2 -2
View File
@@ -1493,7 +1493,7 @@ int image_read_only(Image *i, bool b, RuntimeScope scope) {
assert(i);
if (image_is_vendor(i) || image_is_host(i))
if (image_is_vendor(i) || image_is_host(i) || image_is_hidden(i))
return -EROFS;
/* Make sure we don't interfere with a running nspawn */
@@ -2005,7 +2005,7 @@ int image_to_json(const struct Image *img, sd_json_variant **ret) {
SD_JSON_BUILD_PAIR_STRING("Class", image_class_to_string(img->class)),
SD_JSON_BUILD_PAIR_STRING("Name", img->name),
SD_JSON_BUILD_PAIR_CONDITION(!!img->path, "Path", SD_JSON_BUILD_STRING(img->path)),
SD_JSON_BUILD_PAIR_BOOLEAN("ReadOnly", img->read_only),
SD_JSON_BUILD_PAIR_BOOLEAN("ReadOnly", image_is_read_only(img)),
SD_JSON_BUILD_PAIR_CONDITION(img->crtime != 0, "CreationTimestamp", SD_JSON_BUILD_UNSIGNED(img->crtime)),
SD_JSON_BUILD_PAIR_CONDITION(img->mtime != 0, "ModificationTimestamp", SD_JSON_BUILD_UNSIGNED(img->mtime)),
SD_JSON_BUILD_PAIR_CONDITION(img->usage != UINT64_MAX, "Usage", SD_JSON_BUILD_UNSIGNED(img->usage)),
+16 -4
View File
@@ -84,16 +84,28 @@ static inline char** image_extension_release(Image *image, ImageClass class) {
return NULL;
}
static inline bool image_is_hidden(const struct Image *i) {
static inline bool image_is_hidden(const Image *i) {
assert(i);
return i->name && i->name[0] == '.';
}
bool image_is_vendor(const struct Image *i);
bool image_is_host(const struct Image *i);
static inline int image_is_read_only(const Image *i) {
assert(i);
int image_to_json(const struct Image *i, sd_json_variant **ret);
/* We enforce the rule that hidden images are always read-only too. If people want to change hidden
* images they should make a copy first, and make that one mutable */
if (image_is_hidden(i))
return true;
return i->read_only;
}
bool image_is_vendor(const Image *i);
bool image_is_host(const Image *i);
int image_to_json(const Image *i, sd_json_variant **ret);
int image_root_pick(RuntimeScope scope, ImageClass c, bool runtime, char **ret);