#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;
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) {
if (r < 0)
return r;
- return mac_smack_fix(path, false, false);
+ return mac_smack_fix(path, 0);
}
#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);
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) {
#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"
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) {
#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;
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;
#include <sys/types.h>
#include "macro.h"
+#include "label.h"
bool mac_selinux_use(void);
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);
***/
#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"
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;
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) {
#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_;
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)
/* 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) {
/* 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) {
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... */
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)
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) {
}
}
- 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);
}
}
shortcut:
- return label_fix(path, false, false);
+ return label_fix(path, 0);
}
static int path_set_perms(Item *i, const char *path) {
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;
}
/* 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);
}
rc = EXIT_FAILURE;
}
- label_fix(hwdb_bin, false, false);
+ (void) label_fix(hwdb_bin, 0);
}
if (test) {