Merge pull request #16568 from poettering/creds-store

credentials logic to pass privileged data to services
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-08-26 10:32:30 +02:00
committed by GitHub
47 changed files with 1677 additions and 54 deletions
+7
View File
@@ -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);
}
+2
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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);