summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-02-03 22:24:53 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-02-04 14:03:03 +0900
commitd8f9686c0f1f276c0a687d9bd69f3adf33f15a95 (patch)
treefcfeeca93b50ed0ae13dbae45912689e0481d84a
parent5d80583d5dbebab91197d7c5e3e909b7ecf817c6 (diff)
downloadsystemd-d8f9686c0f1f276c0a687d9bd69f3adf33f15a95.tar.gz
import: use +i (immutable) chattr flag for marking OS images read-only
This is what nspawn and machine-image.[ch] actually look for, hence us it here too.
-rw-r--r--src/import/import-common.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/src/import/import-common.c b/src/import/import-common.c
index bbe0ba719c..f77564c41d 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -8,6 +8,7 @@
#include "alloc-util.h"
#include "btrfs-util.h"
#include "capability-util.h"
+#include "chattr-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -22,6 +23,7 @@
#include "util.h"
int import_make_read_only_fd(int fd) {
+ struct stat st;
int r;
assert(fd >= 0);
@@ -29,25 +31,34 @@ int import_make_read_only_fd(int fd) {
/* First, let's make this a read-only subvolume if it refers
* to a subvolume */
r = btrfs_subvol_set_read_only_fd(fd, true);
- if (IN_SET(r, -ENOTTY, -ENOTDIR, -EINVAL)) {
- struct stat st;
+ if (r >= 0)
+ return 0;
- /* This doesn't refer to a subvolume, or the file
- * system isn't even btrfs. In that, case fall back to
- * chmod()ing */
+ if (!ERRNO_IS_NOT_SUPPORTED(r) && !IN_SET(r, -ENOTDIR, -EINVAL))
+ return log_error_errno(r, "Failed to make subvolume read-only: %m");
- r = fstat(fd, &st);
- if (r < 0)
- return log_error_errno(errno, "Failed to stat temporary image: %m");
+ /* This doesn't refer to a subvolume, or the file system isn't even btrfs. In that, case fall back to
+ * chmod()ing */
+
+ r = fstat(fd, &st);
+ if (r < 0)
+ return log_error_errno(errno, "Failed to stat image: %m");
- /* Drop "w" flag */
- if (fchmod(fd, st.st_mode & 07555) < 0)
- return log_error_errno(errno, "Failed to chmod() final image: %m");
+ if (S_ISDIR(st.st_mode)) {
+ /* For directories set the immutable flag on the dir itself */
- return 0;
+ r = chattr_fd(fd, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set +i attribute on directory image: %m");
- } else if (r < 0)
- return log_error_errno(r, "Failed to make subvolume read-only: %m");
+ } else if (S_ISREG(st.st_mode)) {
+ /* For regular files drop "w" flags */
+
+ if ((st.st_mode & 0222) != 0)
+ if (fchmod(fd, st.st_mode & 07555) < 0)
+ return log_error_errno(errno, "Failed to chmod() image: %m");
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EBADFD), "Image of unexpected type");
return 0;
}