| $ cat 0001-selinux-use-the-labeldb-for-a-manual-transition-when.patch
|
| From e99be9903c9a54f045f5006146348e4cabaae281 Mon Sep 17 00:00:00 2001
|
| From: Rahul Sandhu <nvraxn@gmail.com>
|
| Date: Mon, 2 Jun 2025 17:35:03 +0100
|
| Subject: [PATCH] selinux: use the labeldb for a manual transition when
|
| creating dirs
|
|
|
| Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
|
| ---
|
| meson.build | 9 +++-
|
| meson_options.txt | 5 ++
|
| src/fs_utils.cc | 128 ++++++++++++++++++++++++++++++++++++++++++++++
|
| 3 files changed, 141 insertions(+), 1 deletion(-)
|
|
|
| diff --git a/meson.build b/meson.build
|
| index 770b982..a0d349f 100644
|
| --- a/meson.build
|
| +++ b/meson.build
|
| @@ -22,6 +22,12 @@ scdoc_dep = dependency(
|
| native: true
|
| )
|
|
|
| +libselinux_dep = dependency(
|
| + 'libselinux',
|
| + version: '>=2.1.9',
|
| + required: get_option('support_selinux')
|
| +)
|
| +
|
| have_dinit = get_option('dinit').enabled()
|
| have_runit = get_option('runit').enabled()
|
|
|
| @@ -31,6 +37,7 @@ conf_data.set_quoted('CONF_PATH', join_paths(
|
| get_option('prefix'), get_option('sysconfdir'), 'turnstile'
|
| ))
|
| conf_data.set10('MANAGE_RUNDIR', get_option('manage_rundir'))
|
| +conf_data.set10('HAVE_SELINUX', libselinux_dep.found())
|
|
|
| conf_data.set('HAVE_PAM_MISC', pam_misc_dep.found())
|
|
|
| @@ -82,7 +89,7 @@ daemon = executable(
|
| 'turnstiled', daemon_sources,
|
| include_directories: extra_inc,
|
| install: true,
|
| - dependencies: [rt_dep, pam_dep, pam_misc_dep],
|
| + dependencies: [rt_dep, pam_dep, pam_misc_dep, libselinux_dep],
|
| gnu_symbol_visibility: 'hidden'
|
| )
|
|
|
| diff --git a/meson_options.txt b/meson_options.txt
|
| index 29abb69..4d3af0c 100644
|
| --- a/meson_options.txt
|
| +++ b/meson_options.txt
|
| @@ -38,6 +38,11 @@ option('manage_rundir',
|
| description: 'Whether to manage rundir by default'
|
| )
|
|
|
| +option('support_selinux',
|
| + type: 'feature', value: 'auto',
|
| + description: 'Whether to support SELinux',
|
| +)
|
| +
|
| option('man',
|
| type: 'boolean', value: true,
|
| description: 'Whether to generate manpages'
|
| diff --git a/src/fs_utils.cc b/src/fs_utils.cc
|
| index ac91921..6ae8d0f 100644
|
| --- a/src/fs_utils.cc
|
| +++ b/src/fs_utils.cc
|
| @@ -10,11 +10,59 @@
|
|
|
| #include "turnstiled.hh"
|
|
|
| +#ifdef HAVE_SELINUX
|
| +#include <selinux/label.h>
|
| +#include <selinux/selinux.h>
|
| +#endif
|
| +
|
| int dir_make_at(int dfd, char const *dname, mode_t mode) {
|
| int sdfd = openat(dfd, dname, O_RDONLY | O_NOFOLLOW);
|
| struct stat st;
|
| int reterr = 0;
|
| int omask = umask(0);
|
| +
|
| +#ifdef HAVE_SELINUX
|
| + // We can't rely on policy transitions to set the user field of the context
|
| + // correctly as that depends on the seuser db, so calculate the context to
|
| + // create the runtimedir with ourselves.
|
| + char *path = nullptr;
|
| + char *context = nullptr;
|
| + {
|
| + char procfd[64];
|
| + ssize_t len;
|
| + snprintf(procfd, sizeof(procfd), "/proc/self/fd/%d", dfd);
|
| + char dfd_path[PATH_MAX];
|
| + len = readlink(procfd, dfd_path, sizeof(dfd_path)-1);
|
| + if (len < 0) {
|
| + goto ret_err;
|
| + }
|
| + dfd_path[len] = '\0';
|
| + path = (char *)malloc(strlen(dfd_path) + 1 + strlen(dname) + 2);
|
| + if (!path) {
|
| + goto ret_err;
|
| + }
|
| + sprintf(path, "%s/%s", dfd_path, dname);
|
| +
|
| + struct selabel_handle *sehandle =
|
| + selabel_open(SELABEL_CTX_FILE, nullptr, 0);
|
| + if (!sehandle) {
|
| + perror("selabel_open");
|
| + goto ret_err;
|
| + }
|
| + if (selabel_lookup_raw(sehandle, &context, path, mode) < 0) {
|
| + perror("selabel_lookup_raw");
|
| + selabel_close(sehandle);
|
| + goto ret_err;
|
| + }
|
| + selabel_close(sehandle);
|
| + if (setfscreatecon_raw(context) < 0) {
|
| + perror("setfscreatecon_raw");
|
| + goto ret_err;
|
| + }
|
| + }
|
| + print_err ("selinux: %s | %s", path, context);
|
| +#endif
|
| +
|
| if (fstat(sdfd, &st) || !S_ISDIR(st.st_mode)) {
|
| close(sdfd);
|
| if (mkdirat(dfd, dname, mode)) {
|
| @@ -29,6 +77,7 @@ int dir_make_at(int dfd, char const *dname, mode_t mode) {
|
| goto ret_err;
|
| }
|
| } else {
|
| + // TODO: dir already exists, call lsetfilecon.
|
| /* dir_clear_contents closes the descriptor, we need to keep it */
|
| int nfd;
|
| if ((fchmod(sdfd, mode) < 0) || ((nfd = dup(sdfd)) < 0)) {
|
| @@ -39,9 +88,34 @@ int dir_make_at(int dfd, char const *dname, mode_t mode) {
|
| goto ret_err;
|
| }
|
| }
|
| +
|
| +#ifdef HAVE_SELINUX
|
| + // Reset fs creation context so new objects are labelled correctly.
|
| + if (setfscreatecon(nullptr) < 0) {
|
| + perror("setfscreatecon");
|
| + goto ret_err;
|
| + }
|
| + if (context) {
|
| + free(context);
|
| + }
|
| + if (path) {
|
| + free(path);
|
| + }
|
| +#endif
|
| +
|
| umask(omask);
|
| return sdfd;
|
| +
|
| ret_err:
|
| +#ifdef HAVE_SELINUX
|
| + setfscreatecon(nullptr);
|
| + if (context) {
|
| + free(context);
|
| + }
|
| + if (path) {
|
| + free(path);
|
| + }
|
| +#endif
|
| umask(omask);
|
| if (sdfd >= 0) {
|
| close(sdfd);
|
| @@ -97,6 +171,46 @@ bool rundir_make(char *rundir, unsigned int uid, unsigned int gid) {
|
| sl = std::strchr(dirbase, '/');
|
| }
|
| umask(omask);
|
| +
|
| +#ifdef HAVE_SELINUX
|
| + // We can't rely on policy transitions to set the user field of the context
|
| + // correctly as that depends on the seuser db, so calculate the context to
|
| + // create the runtimedir with ourselves.
|
| + char *context = nullptr;
|
| + {
|
| + struct selabel_handle *sehandle =
|
| + selabel_open(SELABEL_CTX_FILE, nullptr, 0);
|
| + if (!sehandle) {
|
| + print_err(
|
| + "rundir: failed to make rundir %s (%s)",
|
| + rundir, strerror(errno)
|
| + );
|
| + close(bfd);
|
| + return false;
|
| + }
|
| + if (selabel_lookup_raw(sehandle, &context, rundir, 0700) < 0) {
|
| + print_err(
|
| + "rundir: failed to make rundir %s (%s)",
|
| + rundir, strerror(errno)
|
| + );
|
| + selabel_close(sehandle);
|
| + close(bfd);
|
| + return false;
|
| + }
|
| + selabel_close(sehandle);
|
| + if (setfscreatecon_raw(context) < 0) {
|
| + print_err(
|
| + "rundir: failed to make rundir %s (%s)",
|
| + rundir, strerror(errno)
|
| + );
|
| + close(bfd);
|
| + return false;
|
| + }
|
| + }
|
| + print_err ("selinux: %s | %s", rundir, context);
|
| +#endif
|
| +
|
| + // TODO: lsetfilecon for dir already existing.
|
| /* now create rundir or at least sanitize its perms */
|
| if (
|
| (fstatat(bfd, dirbase, &dstat, AT_SYMLINK_NOFOLLOW) < 0) ||
|
| @@ -115,6 +229,20 @@ bool rundir_make(char *rundir, unsigned int uid, unsigned int gid) {
|
| close(bfd);
|
| return false;
|
| }
|
| +
|
| +#ifdef HAVE_SELINUX
|
| + // Reset fs creation context so new objects are labelled correctly.
|
| + if (setfscreatecon(nullptr) < 0) {
|
| + perror("setfscreatecon");
|
| + close(bfd);
|
| + free(context);
|
| + return false;
|
| + }
|
| + if (context) {
|
| + free(context);
|
| + }
|
| +#endif
|
| +
|
| if (fchownat(bfd, dirbase, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) {
|
| print_err("rundir: fchownat failed for rundir (%s)", strerror(errno));
|
| close(bfd);
|
| --
|
| 2.49.0
|
|
|
| $ cat 0001-turnstiled-use-labeldb-when-creating-user-owned-fifo.patch
|
| From d809f35f6c0dbd0f30559eafaaa614d484f7b230 Mon Sep 17 00:00:00 2001
|
| From: Rahul Sandhu <nvraxn@gmail.com>
|
| Date: Tue, 3 Jun 2025 18:10:25 +0100
|
| Subject: [PATCH] turnstiled: use labeldb when creating user-owned fifofile
|
|
|
| Signed-off-by: Rahul Sandhu <nvraxn@gmail.com>
|
| ---
|
| src/turnstiled.cc | 52 +++++++++++++++++++++++++++++++++++++++++++++++
|
| 1 file changed, 52 insertions(+)
|
|
|
| diff --git a/src/turnstiled.cc b/src/turnstiled.cc
|
| index cf9e6d3..cf8580f 100644
|
| --- a/src/turnstiled.cc
|
| +++ b/src/turnstiled.cc
|
| @@ -33,6 +33,11 @@
|
| #include "turnstiled.hh"
|
| #include "utils.hh"
|
|
|
| +#ifdef HAVE_SELINUX
|
| +#include <selinux/label.h>
|
| +#include <selinux/selinux.h>
|
| +#endif
|
| +
|
| #ifndef CONF_PATH
|
| #error "No CONF_PATH is defined"
|
| #endif
|
| @@ -159,10 +164,57 @@ static bool srv_start(login &lgn) {
|
| }
|
| print_dbg("srv: create readiness pipe");
|
| unlinkat(lgn.dirfd, "ready", 0);
|
| +#ifdef HAVE_SELINUX
|
| + // We can't rely on policy transitions to set the user field of the context
|
| + // correctly as that depends on the seuser db, so calculate the context to
|
| + // create the runtimedir with ourselves.
|
| + char *context = nullptr;
|
| + {
|
| + struct selabel_handle *sehandle =
|
| + selabel_open(SELABEL_CTX_FILE, nullptr, 0);
|
| + if (!sehandle) {
|
| + print_err("srv: failed to make ready pipe (%s)", strerror(errno));
|
| + return false;
|
| + }
|
| + char ready_path[PATH_MAX];
|
| + if (const int r = std::snprintf(ready_path, sizeof(ready_path),
|
| + "%s/%s/%u/ready", RUN_PATH, SOCK_DIR, lgn.uid);
|
| + r < 0 || r >= PATH_MAX) {
|
| + print_err("srv: failed to make ready pipe (%s)", strerror(errno));
|
| + selabel_close(sehandle);
|
| + return false;
|
| + }
|
| + if (selabel_lookup_raw(sehandle, &context, ready_path, 0700) < 0) {
|
| + print_err("srv: failed to make ready pipe (%s)", strerror(errno));
|
| + selabel_close(sehandle);
|
| + return false;
|
| + }
|
| + selabel_close(sehandle);
|
| + if (setfscreatecon_raw(context) < 0) {
|
| + print_err("srv: failed to make ready pipe (%s)", strerror(errno));
|
| + free(context);
|
| + return false;
|
| + }
|
| + }
|
| +#endif
|
| if (mkfifoat(lgn.dirfd, "ready", 0700) < 0) {
|
| print_err("srv: failed to make ready pipe (%s)", strerror(errno));
|
| return false;
|
| }
|
| +#ifdef HAVE_SELINUX
|
| + // Reset fs creation context so new objects are labelled correctly.
|
| + if (context) {
|
| + free(context);
|
| + }
|
| + if (setfscreatecon(nullptr) < 0) {
|
| + print_err(
|
| + "srv: failed to set up ready pipe (%s)", strerror(errno)
|
| + );
|
| + unlinkat(lgn.dirfd, "ready", 0);
|
| + lgn.remove_sdir();
|
| + return false;
|
| + }
|
| +#endif
|
| /* ensure it's owned by user too, and open in nonblocking mode */
|
| if (fchownat(
|
| lgn.dirfd, "ready", lgn.uid, lgn.gid, AT_SYMLINK_NOFOLLOW
|
| --
|
| 2.49.0
|