From 9bcb6edfe419d390acddc2ed7d0c04d37b753ac3 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sat, 28 Sep 2019 21:40:31 +0200 Subject: Do the SELinux relabeling while generating the fstree This commit splits the SELinux relabeling function up into 3 parts: - open the label file - apply relabeling rules to a given file - close the label file The relabeling is done while building the tree (if reading from an input directory) or in a post process step if reading from a desription file. Signed-off-by: David Oberhollenzer --- mkfs/Makemodule.am | 3 +-- mkfs/dirscan.c | 26 ++++++++++++++++++----- mkfs/mkfs.c | 61 ++++++++++++++++++++++++++++++++++++++++++++---------- mkfs/mkfs.h | 11 ++++++++-- mkfs/selinux.c | 55 ++++++++++++++++++++++++++++-------------------- 5 files changed, 114 insertions(+), 42 deletions(-) diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am index 75fc3a4..cb37698 100644 --- a/mkfs/Makemodule.am +++ b/mkfs/Makemodule.am @@ -1,5 +1,5 @@ gensquashfs_SOURCES = mkfs/mkfs.c mkfs/mkfs.h mkfs/options.c -gensquashfs_SOURCES += mkfs/dirscan.c +gensquashfs_SOURCES += mkfs/dirscan.c mkfs/selinux.c gensquashfs_LDADD = libsqfshelper.a libsquashfs.la libfstree.a libutil.la gensquashfs_LDADD += $(LIBSELINUX_LIBS) gensquashfs_CPPFLAGS = $(AM_CPPFLAGS) @@ -7,7 +7,6 @@ gensquashfs_CFLAGS = $(AM_CFLAGS) $(LIBSELINUX_CFLAGS) if WITH_SELINUX gensquashfs_CPPFLAGS += -DWITH_SELINUX -gensquashfs_SOURCES += mkfs/selinux.c endif bin_PROGRAMS += gensquashfs diff --git a/mkfs/dirscan.c b/mkfs/dirscan.c index 5cb955a..160fbc3 100644 --- a/mkfs/dirscan.c +++ b/mkfs/dirscan.c @@ -109,9 +109,9 @@ fail: #endif static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart, - unsigned int flags) + void *selinux_handle, unsigned int flags) { - char *extra = NULL; + char *extra = NULL, *path; struct dirent *ent; struct stat sb; tree_node_t *n; @@ -177,6 +177,21 @@ static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart, goto fail; } #endif + if (selinux_handle != NULL) { + path = fstree_get_path(n); + if (path == NULL) { + perror("getting full path for " + "SELinux relabeling"); + goto fail; + } + + if (selinux_relable_node(selinux_handle, fs, n, path)) { + free(path); + goto fail; + } + + free(path); + } free(extra); extra = NULL; @@ -189,7 +204,7 @@ static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart, if (pushd(n->name)) return -1; - if (populate_dir(fs, n, devstart, flags)) + if (populate_dir(fs, n, devstart, selinux_handle, flags)) return -1; if (popd()) @@ -206,7 +221,8 @@ fail: return -1; } -int fstree_from_dir(fstree_t *fs, const char *path, unsigned int flags) +int fstree_from_dir(fstree_t *fs, const char *path, void *selinux_handle, + unsigned int flags) { struct stat sb; int ret; @@ -219,7 +235,7 @@ int fstree_from_dir(fstree_t *fs, const char *path, unsigned int flags) if (pushd(path)) return -1; - ret = populate_dir(fs, fs->root, sb.st_dev, flags); + ret = populate_dir(fs, fs->root, sb.st_dev, selinux_handle, flags); if (popd()) ret = -1; diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c index 5746c69..c3a4e73 100644 --- a/mkfs/mkfs.c +++ b/mkfs/mkfs.c @@ -89,13 +89,41 @@ static int pack_files(sqfs_data_writer_t *data, fstree_t *fs, return restore_working_dir(opt); } -static int read_fstree(fstree_t *fs, options_t *opt) +static int relabel_tree_dfs(fstree_t *fs, tree_node_t *n, void *selinux_handle) +{ + char *path = fstree_get_path(n); + + if (path == NULL) { + perror("getting absolute node path for SELinux relabeling"); + return -1; + } + + if (selinux_relable_node(selinux_handle, fs, n, path)) { + free(path); + return -1; + } + + free(path); + + if (S_ISDIR(n->mode)) { + for (n = n->data.dir.children; n != NULL; n = n->next) { + if (relabel_tree_dfs(fs, n, selinux_handle)) + return -1; + } + } + + return 0; +} + +static int read_fstree(fstree_t *fs, options_t *opt, void *selinux_handle) { FILE *fp; int ret; - if (opt->infile == NULL) - return fstree_from_dir(fs, opt->packdir, opt->dirscan_flags); + if (opt->infile == NULL) { + return fstree_from_dir(fs, opt->packdir, selinux_handle, + opt->dirscan_flags); + } fp = fopen(opt->infile, "rb"); if (fp == NULL) { @@ -115,6 +143,9 @@ static int read_fstree(fstree_t *fs, options_t *opt) if (restore_working_dir(opt)) return -1; + if (ret == 0 && selinux_handle != NULL) + ret = relabel_tree_dfs(fs, fs->root, selinux_handle); + return ret; } @@ -127,6 +158,7 @@ int main(int argc, char **argv) sqfs_compressor_t *cmp; sqfs_id_table_t *idtbl; sqfs_file_t *outfile; + void *sehnd = NULL; sqfs_super_t super; options_t opt; fstree_t fs; @@ -159,8 +191,22 @@ int main(int argc, char **argv) if (sqfs_super_write(&super, outfile)) goto out_outfile; - if (read_fstree(&fs, &opt)) + if (opt.selinux != NULL) { + sehnd = selinux_open_context_file(opt.selinux); + if (sehnd == NULL) + goto out_outfile; + } + + if (read_fstree(&fs, &opt, sehnd)) { + if (sehnd != NULL) + selinux_close_context_file(sehnd); goto out_outfile; + } + + if (sehnd != NULL) { + selinux_close_context_file(sehnd); + sehnd = NULL; + } tree_node_sort_recursive(fs.root); @@ -171,13 +217,6 @@ int main(int argc, char **argv) super.inode_count = fs.inode_tbl_size - 2; -#ifdef WITH_SELINUX - if (opt.selinux != NULL) { - if (fstree_relabel_selinux(&fs, opt.selinux)) - goto out_outfile; - } -#endif - fstree_xattr_deduplicate(&fs); cmp = sqfs_compressor_create(&cfg); diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h index f00898b..3a139a7 100644 --- a/mkfs/mkfs.h +++ b/mkfs/mkfs.h @@ -68,8 +68,15 @@ enum { void process_command_line(options_t *opt, int argc, char **argv); -int fstree_from_dir(fstree_t *fs, const char *path, unsigned int flags); +int fstree_from_dir(fstree_t *fs, const char *path, void *selinux_handle, + unsigned int flags); -int fstree_relabel_selinux(fstree_t *fs, const char *filename); + +void *selinux_open_context_file(const char *filename); + +int selinux_relable_node(void *sehnd, fstree_t *fs, + tree_node_t *node, const char *path); + +void selinux_close_context_file(void *sehnd); #endif /* MKFS_H */ diff --git a/mkfs/selinux.c b/mkfs/selinux.c index 5fc4f52..a4cda71 100644 --- a/mkfs/selinux.c +++ b/mkfs/selinux.c @@ -9,16 +9,13 @@ #define XATTR_NAME_SELINUX "security.selinux" #define XATTR_VALUE_SELINUX "system_u:object_r:unlabeled_t:s0" -static int relable_node(fstree_t *fs, struct selabel_handle *sehnd, - tree_node_t *node) +#ifdef WITH_SELINUX +int selinux_relable_node(void *sehnd, fstree_t *fs, + tree_node_t *node, const char *path) { - char *context = NULL, *path; + char *context = NULL; int ret; - path = fstree_get_path(node); - if (path == NULL) - goto fail; - if (selabel_lookup(sehnd, &context, path, node->mode) < 0) { context = strdup(XATTR_VALUE_SELINUX); if (context == NULL) @@ -27,36 +24,50 @@ static int relable_node(fstree_t *fs, struct selabel_handle *sehnd, ret = fstree_add_xattr(fs, node, XATTR_NAME_SELINUX, context); free(context); - free(path); return ret; fail: perror("relabeling files"); - free(path); return -1; } -int fstree_relabel_selinux(fstree_t *fs, const char *filename) +void *selinux_open_context_file(const char *filename) { struct selabel_handle *sehnd; struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, filename }, }; - size_t i; - int ret = 0; sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1); - - if (sehnd == NULL) { + if (sehnd == NULL) perror(filename); - return -1; - } - for (i = 2; i < fs->inode_tbl_size; ++i) { - ret = relable_node(fs, sehnd, fs->inode_table[i]); - if (ret) - break; - } + return sehnd; +} +void selinux_close_context_file(void *sehnd) +{ selabel_close(sehnd); - return ret; } +#else +int selinux_relable_node(void *sehnd, fstree_t *fs, + tree_node_t *node, const char *path) +{ + (void)sehnd; (void)fs; (void)node; (void)path; + fputs("Built without SELinux support, cannot add SELinux labels\n", + stderr); + return -1; +} + +void *selinux_open_context_file(const char *filename) +{ + (void)filename; + fputs("Built without SELinux support, cannot open contexts file\n", + stderr); + return NULL; +} + +void selinux_close_context_file(void *sehnd) +{ + (void)sehnd; +} +#endif -- cgit v1.2.3