Merge pull request #16568 from poettering/creds-store
credentials logic to pass privileged data to services
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "glob-util.h"
|
||||
#include "log.h"
|
||||
@@ -1130,3 +1131,9 @@ bool prefixed_path_strv_contains(char **l, const char *path) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool credential_name_valid(const char *s) {
|
||||
/* We want that credential names are both valid in filenames (since that's our primary way to pass
|
||||
* them around) and as fdnames (which is how we might want to pass them around eventually) */
|
||||
return filename_is_valid(s) && fdname_is_valid(s);
|
||||
}
|
||||
|
||||
@@ -173,3 +173,5 @@ static inline const char *empty_to_root(const char *path) {
|
||||
|
||||
bool path_strv_contains(char **l, const char *path);
|
||||
bool prefixed_path_strv_contains(char **l, const char *path);
|
||||
|
||||
bool credential_name_valid(const char *s);
|
||||
|
||||
+46
-8
@@ -23,6 +23,46 @@ static bool is_physical_fs(const struct statfs *sfs) {
|
||||
return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs);
|
||||
}
|
||||
|
||||
static int unlinkat_harder(
|
||||
int dfd,
|
||||
const char *filename,
|
||||
int unlink_flags,
|
||||
RemoveFlags remove_flags) {
|
||||
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
/* Like unlinkat(), but tries harder: if we get EACCESS we'll try to set the r/w/x bits on the
|
||||
* directory. This is useful if we run unprivileged and have some files where the w bit is
|
||||
* missing. */
|
||||
|
||||
if (unlinkat(dfd, filename, unlink_flags) >= 0)
|
||||
return 0;
|
||||
if (errno != EACCES || !FLAGS_SET(remove_flags, REMOVE_CHMOD))
|
||||
return -errno;
|
||||
|
||||
if (fstat(dfd, &st) < 0)
|
||||
return -errno;
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return -ENOTDIR;
|
||||
if ((st.st_mode & 0700) == 0700) /* Already set? */
|
||||
return -EACCES; /* original error */
|
||||
if (st.st_uid != geteuid()) /* this only works if the UID matches ours */
|
||||
return -EACCES;
|
||||
|
||||
if (fchmod(dfd, (st.st_mode | 0700) & 07777) < 0)
|
||||
return -errno;
|
||||
|
||||
if (unlinkat(dfd, filename, unlink_flags) < 0) {
|
||||
r = -errno;
|
||||
/* Try to restore the original access mode if this didn't work */
|
||||
(void) fchmod(dfd, st.st_mode & 07777);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
struct dirent *de;
|
||||
@@ -132,17 +172,15 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
|
||||
if (r < 0 && ret == 0)
|
||||
ret = r;
|
||||
|
||||
if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
|
||||
if (ret == 0 && errno != ENOENT)
|
||||
ret = -errno;
|
||||
}
|
||||
r = unlinkat_harder(fd, de->d_name, AT_REMOVEDIR, flags);
|
||||
if (r < 0 && r != -ENOENT && ret == 0)
|
||||
ret = r;
|
||||
|
||||
} else if (!(flags & REMOVE_ONLY_DIRECTORIES)) {
|
||||
|
||||
if (unlinkat(fd, de->d_name, 0) < 0) {
|
||||
if (ret == 0 && errno != ENOENT)
|
||||
ret = -errno;
|
||||
}
|
||||
r = unlinkat_harder(fd, de->d_name, 0, flags);
|
||||
if (r < 0 && r != -ENOENT && ret == 0)
|
||||
ret = r;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -11,6 +11,7 @@ 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 */
|
||||
} RemoveFlags;
|
||||
|
||||
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev);
|
||||
|
||||
Reference in New Issue
Block a user