tmpfiles: add '=' action modifier.

Add the '=' action modifier that instructs tmpfiles.d to check the file
type of a path and remove objects that do not match before trying to
open or create the path.

BUG=chromium:1186405
TEST=./test/test-systemd-tmpfiles.py "$(which systemd-tmpfiles)"

Change-Id: If807dc0db427393e9e0047aba640d0d114897c26
This commit is contained in:
Allen Webb
2021-06-08 17:23:26 +02:00
committed by Zbigniew Jędrzejewski-Szmek
parent 90a404f5d4
commit c46c323385
7 changed files with 288 additions and 29 deletions
+1 -1
View File
@@ -733,7 +733,7 @@ int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) {
return wd;
}
static bool unsafe_transition(const struct stat *a, const struct stat *b) {
bool unsafe_transition(const struct stat *a, const struct stat *b) {
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
* making us believe we read something safe even though it isn't safe in the specific context we open it in. */
+2
View File
@@ -94,6 +94,8 @@ enum {
CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */
};
bool unsafe_transition(const struct stat *a, const struct stat *b);
/* How many iterations to execute before returning -ELOOP */
#define CHASE_SYMLINKS_MAX 32
+10 -9
View File
@@ -48,11 +48,7 @@ static int patch_dirfd_mode(
return 0;
}
static int unlinkat_harder(
int dfd,
const char *filename,
int unlink_flags,
RemoveFlags remove_flags) {
int unlinkat_harder(int dfd, const char *filename, int unlink_flags, RemoveFlags remove_flags) {
mode_t old_mode;
int r;
@@ -77,13 +73,15 @@ static int unlinkat_harder(
return r;
}
/* If this worked, we won't reset the old mode, since we'll need it for other entries too, and we
* should destroy the whole thing */
if (FLAGS_SET(remove_flags, REMOVE_CHMOD_RESTORE) && fchmod(dfd, old_mode) < 0)
return -errno;
/* If this worked, we won't reset the old mode by default, since we'll need it for other entries too,
* and we should destroy the whole thing */
return 0;
}
static int fstatat_harder(
int dfd,
int fstatat_harder(int dfd,
const char *filename,
struct stat *ret,
int fstatat_flags,
@@ -109,6 +107,9 @@ static int fstatat_harder(
return r;
}
if (FLAGS_SET(remove_flags, REMOVE_CHMOD_RESTORE) && fchmod(dfd, old_mode) < 0)
return -errno;
return 0;
}
+9 -1
View File
@@ -12,9 +12,17 @@ typedef enum RemoveFlags {
REMOVE_PHYSICAL = 1 << 2, /* If not set, only removes files on tmpfs, never physical file systems */
REMOVE_SUBVOLUME = 1 << 3, /* Drop btrfs subvolumes in the tree too */
REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */
REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete something */
REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete or access something */
REMOVE_CHMOD_RESTORE = 1 << 6, /* Restore the old mode before returning */
} RemoveFlags;
int unlinkat_harder(int dfd, const char *filename, int unlink_flags, RemoveFlags remove_flags);
int fstatat_harder(int dfd,
const char *filename,
struct stat *ret,
int fstatat_flags,
RemoveFlags remove_flags);
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev);
int rm_rf(const char *path, RemoveFlags flags);