From 0bbd84e31ec8bbe8d1e28e981c577fd56c8b8664 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sat, 11 May 2019 00:27:06 +0200 Subject: Add SELinux labeling to fstree code Use libselinux to lookup the context attributes from a file. Signed-off-by: David Oberhollenzer --- configure.ac | 22 +++++++++++ include/fstree.h | 12 ++++++ lib/Makemodule.am | 9 +++++ lib/fstree/selinux.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ mkfs/Makemodule.am | 4 ++ 5 files changed, 157 insertions(+) create mode 100644 lib/fstree/selinux.c diff --git a/configure.ac b/configure.ac index b138c6f..5b98b7b 100644 --- a/configure.ac +++ b/configure.ac @@ -81,17 +81,29 @@ AC_ARG_WITH([lz4], esac], [AM_CONDITIONAL([WITH_LZ4], [true])]) +AC_ARG_WITH([selinux], + [AS_HELP_STRING([--without-selinux], + [Build without SELinux label file support])], + [case "${withval}" in + yes) AM_CONDITIONAL([WITH_SELINUX], [true]) ;; + no) AM_CONDITIONAL([WITH_SELINUX], [false]) ;; + *) AC_MSG_ERROR([bad value ${withval} for --without-selinux]) ;; + esac], + [AM_CONDITIONAL([WITH_SELINUX], [true])]) + ##### search for dependencies ##### need_zlib="no" need_xz="no" need_lzo="no" need_lz4="no" +need_selinux="no" AM_COND_IF([WITH_GZIP], [need_zlib="yes"]) AM_COND_IF([WITH_XZ], [need_xz="yes"]) AM_COND_IF([WITH_LZO], [need_lzo="yes"]) AM_COND_IF([WITH_LZ4], [need_lz4="yes"]) +AM_COND_IF([WITH_SELINUX], [need_selinux="yes"]) if test "x$need_zlib" = "xyes"; then PKG_CHECK_MODULES(ZLIB, [zlib], [], [AC_MSG_ERROR([cannot find zlib])]) @@ -117,6 +129,16 @@ if test "x$need_lz4" = "xyes"; then [AC_MSG_ERROR([cannot lz4 library])]) fi +if test "x$need_selinux" = "xyes"; then + PKG_CHECK_MODULES(LIBSELINUX, [libselinux], [], + [AC_MSG_ERROR([cannot find libselinux])]) + + AC_CHECK_HEADERS([selinux/selinux.h], [], + [AC_MSG_ERROR([cannot find SELinux system headers])]) + AC_CHECK_HEADERS([selinux/label.h], [], + [AC_MSG_ERROR([cannot find SELinux system headers])]) +fi + ##### generate output ##### AC_CONFIG_HEADERS([config.h]) diff --git a/include/fstree.h b/include/fstree.h index 64541a3..a7d19c2 100644 --- a/include/fstree.h +++ b/include/fstree.h @@ -388,4 +388,16 @@ int fstree_from_file(fstree_t *fs, const char *filename); */ void fstree_sort(fstree_t *fs); +/** + * @brief Add labels from an SELinux labeling file to all tree nodes + * + * @memberof fstree_t + * + * @param fs A pointer to an fstree object + * @param filename The name of the SELinux context file + * + * @return Zero on success, -1 on failure + */ +int fstree_relabel_selinux(fstree_t *fs, const char *filename); + #endif /* FSTREE_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index cd24eae..737b474 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -1,6 +1,8 @@ libfstree_a_SOURCES = lib/fstree/fstree.c lib/fstree/fstree_from_file.c libfstree_a_SOURCES += lib/fstree/fstree_sort.c libfstree_a_SOURCES += include/fstree.h +libfstree_a_CFLAGS = $(AM_CFLAGS) +libfstree_a_CPPFLAGS = $(AM_CPPFLAGS) libcompress_a_SOURCES = lib/comp/compressor.c lib/comp/internal.h libcompress_a_SOURCES += include/compress.h @@ -50,4 +52,11 @@ libcompress_a_CFLAGS += $(LZ4_CFLAGS) libcompress_a_CPPFLAGS += -DWITH_LZ4 endif +if WITH_SELINUX +libfstree_a_SOURCES += lib/fstree/selinux.c + +libfstree_a_CFLAGS += $(LIBSELINUX_CFLAGS) +libfstree_a_CPPFLAGS += -DWITH_SELINUX +endif + noinst_LIBRARIES += libfstree.a libcompress.a libutil.a libsquashfs.a diff --git a/lib/fstree/selinux.c b/lib/fstree/selinux.c new file mode 100644 index 0000000..ef858f2 --- /dev/null +++ b/lib/fstree/selinux.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "fstree.h" + +#include +#include +#include +#include +#include + +#define XATTR_NAME_SELINUX "security.selinux" +#define XATTR_VALUE_SELINUX "system_u:object_r:unlabeled_t:s0" + +static char *get_path(tree_node_t *node) +{ + tree_node_t *it; + char *str, *ptr; + size_t len = 0; + + if (node->parent == NULL) { + str = strdup("/"); + + if (str == NULL) + goto fail_alloc; + return str; + } + + for (it = node; it != NULL && it->parent != NULL; it = it->parent) { + len += strlen(it->name) + 1; + } + + str = malloc(len + 1); + if (str == NULL) + goto fail_alloc; + + ptr = str + len; + *ptr = '\0'; + + for (it = node; it != NULL && it->parent != NULL; it = it->parent) { + len = strlen(it->name); + ptr -= len; + + memcpy(ptr, it->name, len); + *(--ptr) = '/'; + } + + return str; +fail_alloc: + perror("relabeling files"); + return NULL; +} + +static int relable_node(fstree_t *fs, struct selabel_handle *sehnd, + tree_node_t *node) +{ + char *context = NULL, *path; + tree_node_t *it; + int ret; + + path = get_path(node); + if (path == NULL) + return -1; + + if (selabel_lookup(sehnd, &context, path, node->mode) < 0) { + free(path); + + ret = fstree_add_xattr(fs, node, XATTR_NAME_SELINUX, + XATTR_VALUE_SELINUX); + } else { + free(path); + ret = fstree_add_xattr(fs, node, XATTR_NAME_SELINUX, context); + free(context); + } + + if (ret) + return -1; + + if (S_ISDIR(node->mode)) { + it = node->data.dir->children; + + while (it != NULL) { + if (relable_node(fs, sehnd, it)) + return -1; + + it = it->next; + } + } + + return 0; +} + +int fstree_relabel_selinux(fstree_t *fs, const char *filename) +{ + struct selabel_handle *sehnd; + struct selinux_opt seopts[] = { + { SELABEL_OPT_PATH, filename }, + }; + int ret; + + sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1); + + if (sehnd == NULL) { + perror(filename); + return -1; + } + + ret = relable_node(fs, sehnd, fs->root); + + selabel_close(sehnd); + return ret; +} diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am index dc105a0..33471fc 100644 --- a/mkfs/Makemodule.am +++ b/mkfs/Makemodule.am @@ -18,4 +18,8 @@ if WITH_LZ4 gensquashfs_LDADD += $(LZ4_LIBS) endif +if WITH_SELINUX +gensquashfs_LDADD += $(LIBSELINUX_LIBS) +endif + bin_PROGRAMS += gensquashfs -- cgit v1.2.3