summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/label.c10
-rw-r--r--src/basic/label.h7
-rw-r--r--src/basic/mkdir-label.c2
-rw-r--r--src/basic/selinux-util.c66
-rw-r--r--src/basic/selinux-util.h3
-rw-r--r--src/basic/smack-util.c75
-rw-r--r--src/basic/smack-util.h15
-rw-r--r--src/core/mount-setup.c8
-rw-r--r--src/login/logind-user.c2
9 files changed, 117 insertions, 71 deletions
diff --git a/src/basic/label.c b/src/basic/label.c
index 50cdd8c73..d988dae04 100644
--- a/src/basic/label.c
+++ b/src/basic/label.c
@@ -28,11 +28,11 @@
#include "selinux-util.h"
#include "smack-util.h"
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int label_fix(const char *path, LabelFixFlags flags) {
int r, q;
- r = mac_selinux_fix(path, ignore_enoent, ignore_erofs);
- q = mac_smack_fix(path, ignore_enoent, ignore_erofs);
+ r = mac_selinux_fix(path, flags);
+ q = mac_smack_fix(path, flags);
if (r < 0)
return r;
@@ -62,7 +62,7 @@ int symlink_label(const char *old_path, const char *new_path) {
if (r < 0)
return r;
- return mac_smack_fix(new_path, false, false);
+ return mac_smack_fix(new_path, 0);
}
int btrfs_subvol_make_label(const char *path) {
@@ -80,6 +80,6 @@ int btrfs_subvol_make_label(const char *path) {
if (r < 0)
return r;
- return mac_smack_fix(path, false, false);
+ return mac_smack_fix(path, 0);
}
#endif // 0
diff --git a/src/basic/label.h b/src/basic/label.h
index 4bfcfe39f..cad224ce7 100644
--- a/src/basic/label.h
+++ b/src/basic/label.h
@@ -23,7 +23,12 @@
#include <stdbool.h>
#include <sys/types.h>
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+typedef enum LabelFixFlags {
+ LABEL_IGNORE_ENOENT = 1U << 0,
+ LABEL_IGNORE_EROFS = 1U << 1,
+} LabelFixFlags;
+
+int label_fix(const char *path, LabelFixFlags flags);
int mkdir_label(const char *path, mode_t mode);
#if 0 /// UNNEEDED by elogind
diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c
index 4e5b7c961..6b4656669 100644
--- a/src/basic/mkdir-label.c
+++ b/src/basic/mkdir-label.c
@@ -44,7 +44,7 @@ int mkdir_label(const char *path, mode_t mode) {
if (r < 0)
return r;
- return mac_smack_fix(path, false, false);
+ return mac_smack_fix(path, 0);
}
int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 5d782ab5d..955b8def7 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -34,10 +34,12 @@
#endif
#include "alloc-util.h"
+//#include "fd-util.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "selinux-util.h"
+//#include "stdio-util.h"
#include "time-util.h"
#include "util.h"
@@ -51,7 +53,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
static int cached_use = -1;
static struct selabel_handle *label_hnd = NULL;
-#define log_enforcing(...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, errno, __VA_ARGS__)
+#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
+#define log_enforcing_errno(r, ...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, r, __VA_ARGS__)
#endif
bool mac_selinux_use(void) {
@@ -120,9 +123,12 @@ void mac_selinux_finish(void) {
#endif
}
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_selinux_fix(const char *path, LabelFixFlags flags) {
#if HAVE_SELINUX
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_freecon_ char* fcon = NULL;
+ _cleanup_close_ int fd = -1;
struct stat st;
int r;
@@ -132,37 +138,55 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
if (!label_hnd)
return 0;
- r = lstat(path, &st);
- if (r >= 0) {
- _cleanup_freecon_ char* fcon = NULL;
+ /* Open the file as O_PATH, to pin it while we determine and adjust the label */
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+ if (fd < 0) {
+ if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
+ return 0;
- r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
+ return -errno;
+ }
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ if (selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode) < 0) {
+ r = -errno;
/* If there's no label to set, then exit without warning */
- if (r < 0 && errno == ENOENT)
+ if (r == -ENOENT)
return 0;
- if (r >= 0) {
- r = lsetfilecon_raw(path, fcon);
-
- /* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
- return 0;
- }
+ goto fail;
}
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ if (setfilecon_raw(procfs_path, fcon) < 0) {
+ _cleanup_freecon_ char *oldcon = NULL;
+
+ r = -errno;
+
+ /* If the FS doesn't support labels, then exit without warning */
+ if (r == -EOPNOTSUPP)
return 0;
- if (ignore_erofs && errno == EROFS)
+ /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
+ if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
return 0;
- log_enforcing("Unable to fix SELinux security context of %s: %m", path);
- if (security_getenforce() == 1)
- return -errno;
+ /* If the old label is identical to the new one, suppress any kind of error */
+ if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon))
+ return 0;
+
+ goto fail;
}
+
+ return 0;
+
+fail:
+ log_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", path);
+ if (security_getenforce() == 1)
+ return r;
#endif
return 0;
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index 4dfef4f06..ea7386cdf 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -25,6 +25,7 @@
#include <sys/types.h>
#include "macro.h"
+//#include "label.h"
bool mac_selinux_use(void);
void mac_selinux_retest(void);
@@ -32,7 +33,7 @@ void mac_selinux_retest(void);
int mac_selinux_init(void);
void mac_selinux_finish(void);
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+int mac_selinux_fix(const char *path, LabelFixFlags flags);
#if 0 /// UNNEEDED by elogind
int mac_selinux_apply(const char *path, const char *label);
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index fc09226a5..682a612b1 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -21,18 +21,21 @@
***/
#include <errno.h>
+//#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <unistd.h>
#include "alloc-util.h"
+//#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "process-util.h"
#include "smack-util.h"
+//#include "stdio-util.h"
#include "string-table.h"
#include "xattr-util.h"
@@ -136,7 +139,10 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
}
#endif // 0
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+int mac_smack_fix(const char *path, LabelFixFlags flags) {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int fd = -1;
+ const char *label;
struct stat st;
int r;
@@ -145,50 +151,59 @@ int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
if (!mac_smack_use())
return 0;
- /*
- * Path must be in /dev and must exist
- */
+ /* Path must be in /dev */
if (!path_startswith(path, "/dev"))
return 0;
- r = lstat(path, &st);
- if (r >= 0) {
- const char *label;
-
- /*
- * Label directories and character devices "*".
- * Label symlinks "_".
- * Don't change anything else.
- */
-
- if (S_ISDIR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else if (S_ISLNK(st.st_mode))
- label = SMACK_FLOOR_LABEL;
- else if (S_ISCHR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+ if (fd < 0) {
+ if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
return 0;
- r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
+ return -errno;
+ }
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ /*
+ * Label directories and character devices "*".
+ * Label symlinks "_".
+ * Don't change anything else.
+ */
+
+ if (S_ISDIR(st.st_mode))
+ label = SMACK_STAR_LABEL;
+ else if (S_ISLNK(st.st_mode))
+ label = SMACK_FLOOR_LABEL;
+ else if (S_ISCHR(st.st_mode))
+ label = SMACK_STAR_LABEL;
+ else
+ return 0;
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+ if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) {
+ _cleanup_free_ char *old_label = NULL;
+
+ r = -errno;
/* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
+ if (r == -EOPNOTSUPP)
return 0;
- }
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
+ /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
+ if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
return 0;
- if (ignore_erofs && errno == EROFS)
+ /* If the old label is identical to the new one, suppress any kind of error */
+ if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 &&
+ streq(old_label, label))
return 0;
- r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
+ return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", path);
}
- return r;
+ return 0;
}
#if 0 /// UNNEEDED by elogind
diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h
index c691fdc12..6f8e3ea0c 100644
--- a/src/basic/smack-util.h
+++ b/src/basic/smack-util.h
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include <sys/types.h>
+//#include "label.h"
#include "macro.h"
#define SMACK_FLOOR_LABEL "_"
@@ -32,12 +33,12 @@
#if 0 /// UNNEEDED by elogind
typedef enum SmackAttr {
- SMACK_ATTR_ACCESS = 0,
- SMACK_ATTR_EXEC = 1,
- SMACK_ATTR_MMAP = 2,
- SMACK_ATTR_TRANSMUTE = 3,
- SMACK_ATTR_IPIN = 4,
- SMACK_ATTR_IPOUT = 5,
+ SMACK_ATTR_ACCESS,
+ SMACK_ATTR_EXEC,
+ SMACK_ATTR_MMAP,
+ SMACK_ATTR_TRANSMUTE,
+ SMACK_ATTR_IPIN,
+ SMACK_ATTR_IPOUT,
_SMACK_ATTR_MAX,
_SMACK_ATTR_INVALID = -1,
} SmackAttr;
@@ -45,7 +46,7 @@ typedef enum SmackAttr {
bool mac_smack_use(void);
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
+int mac_smack_fix(const char *path, LabelFixFlags flags);
#if 0 /// UNNEEDED by elogind
const char* smack_attr_to_string(SmackAttr i) _const_;
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index 7073175e1..f53d2fca0 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -182,7 +182,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
/* Relabel first, just in case */
if (relabel)
- (void) label_fix(p->where, true, true);
+ (void) label_fix(p->where, LABEL_IGNORE_ENOENT|LABEL_IGNORE_EROFS);
r = path_is_mount_point(p->where, NULL, AT_SYMLINK_FOLLOW);
if (r < 0 && r != -ENOENT) {
@@ -220,7 +220,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
/* Relabel again, since we now mounted something fresh here */
if (relabel)
- (void) label_fix(p->where, false, false);
+ (void) label_fix(p->where, 0);
if (p->mode & MNT_CHECK_WRITABLE) {
if (access(p->where, W_OK) < 0) {
@@ -389,7 +389,7 @@ static int nftw_cb(
if (_unlikely_(ftwbuf->level == 0))
return FTW_CONTINUE;
- label_fix(fpath, false, false);
+ (void) label_fix(fpath, 0);
/* /run/initramfs is static data and big, no need to
* dynamically relabel its contents at boot... */
@@ -430,7 +430,7 @@ int mount_setup(bool loaded_policy) {
r = cg_all_unified();
if (r == 0) {
(void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL);
- label_fix("/sys/fs/cgroup", false, false);
+ (void) label_fix("/sys/fs/cgroup", 0);
nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
(void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL);
} else if (r < 0)
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 155ec6a5a..20b8601c1 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -374,7 +374,7 @@ static int user_mkdir_runtime_path(User *u) {
}
}
- r = label_fix(u->runtime_path, false, false);
+ r = label_fix(u->runtime_path, 0);
if (r < 0)
log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", u->runtime_path);
}