summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/automount.c2
-rw-r--r--src/core/mount-setup.c8
-rw-r--r--src/hwdb/hwdb.c2
-rw-r--r--src/login/logind-user.c2
-rw-r--r--src/tmpfiles/tmpfiles.c2
-rw-r--r--src/udev/udev-node.c4
-rw-r--r--src/udev/udevadm-hwdb.c2
14 files changed, 123 insertions, 77 deletions
diff --git a/src/basic/label.c b/src/basic/label.c
index 18c9a23fea..134dd8d80a 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;
@@ -60,7 +60,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) {
@@ -78,5 +78,5 @@ 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);
}
diff --git a/src/basic/label.h b/src/basic/label.h
index d73dacec4f..269591c979 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);
int symlink_label(const char *old_path, const char *new_path);
diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c
index 2a44d276cb..9d4ef60e77 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 0c6e99b1d7..c60057f4f7 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 9780dca81e..1cb4ea4fe0 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);
int mac_selinux_apply(const char *path, const char *label);
int mac_selinux_get_create_label_from_exe(const char *exe, char **label);
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index f0018f013f..977de014f7 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"
@@ -134,7 +137,10 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
return r;
}
-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;
@@ -143,50 +149,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;
}
int mac_smack_copy(const char *dest, const char *src) {
diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h
index e4d46d7736..58e6a548b6 100644
--- a/src/basic/smack-util.h
+++ b/src/basic/smack-util.h
@@ -25,25 +25,26 @@
#include <stdbool.h>
#include <sys/types.h>
+#include "label.h"
#include "macro.h"
#define SMACK_FLOOR_LABEL "_"
#define SMACK_STAR_LABEL "*"
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;
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);
const char* smack_attr_to_string(SmackAttr i) _const_;
SmackAttr smack_attr_from_string(const char *s) _pure_;
diff --git a/src/core/automount.c b/src/core/automount.c
index a8d773686b..bcc6b0b04e 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -346,7 +346,7 @@ static int open_dev_autofs(Manager *m) {
if (m->dev_autofs_fd >= 0)
return m->dev_autofs_fd;
- label_fix("/dev/autofs", false, false);
+ (void) label_fix("/dev/autofs", 0);
m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY);
if (m->dev_autofs_fd < 0)
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index b7d654619c..0fe794d2af 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -168,7 +168,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) {
@@ -206,7 +206,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) {
@@ -374,7 +374,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... */
@@ -413,7 +413,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/hwdb/hwdb.c b/src/hwdb/hwdb.c
index f579ef737e..a60809ca65 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -688,7 +688,7 @@ static int hwdb_update(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failure writing database %s: %m", hwdb_bin);
- return label_fix(hwdb_bin, false, false);
+ return label_fix(hwdb_bin, 0);
}
static void help(void) {
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index dc8feacbf9..28574f49a2 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -368,7 +368,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);
}
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index b56b7ac963..61e76570b1 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -850,7 +850,7 @@ static int fd_set_perms(Item *i, int fd, const struct stat *st) {
}
shortcut:
- return label_fix(path, false, false);
+ return label_fix(path, 0);
}
static int path_set_perms(Item *i, const char *path) {
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 6a3ee93ca2..755bf665ab 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -79,7 +79,7 @@ static int node_symlink(struct udev_device *dev, const char *node, const char *s
buf[len] = '\0';
if (streq(target, buf)) {
log_debug("preserve already existing symlink '%s' to '%s'", slink, target);
- label_fix(slink, true, false);
+ (void) label_fix(slink, LABEL_IGNORE_ENOENT);
utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW);
goto exit;
}
@@ -324,7 +324,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply,
/* set the defaults */
if (!selinux)
- mac_selinux_fix(devnode, true, false);
+ (void) mac_selinux_fix(devnode, LABEL_IGNORE_ENOENT);
if (!smack)
mac_smack_apply(devnode, SMACK_ATTR_ACCESS, NULL);
}
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index dc3ae7484d..3a5b138b31 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -680,7 +680,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
rc = EXIT_FAILURE;
}
- label_fix(hwdb_bin, false, false);
+ (void) label_fix(hwdb_bin, 0);
}
if (test) {