blob: 85131afc892c1ce44d14b9e79c5647f98fa1612b [file] [log] [blame]
From: Kenny Root <kroot@google.com>
Date: Tue, 29 Nov 2017 10:37:09 +0900
Subject: squashfs-tools: Allow setting selinux xattrs through
file_context
Add a context-file flag that allows passing an selinux security context
file to set security.selinux xattrs rather than reading xattrs from
filesystem's source directory.
Based on the original change to allow the use of SELinux file_contexts
directly from the source file which was committed to Android's copy
of squashfs-tools and written by Mohamad Ayyash <mkayyash@google.com>
---
diff -urN squashfs-tools/Makefile squashfs-tools/Makefile
--- a/squashfs-tools/Makefile 2017-12-06 15:59:56.569288884 +0900
+++ b/squashfs-tools/Makefile 2017-12-06 16:00:58.104681646 +0900
@@ -102,6 +102,22 @@
# default. Users can enable xattrs by using the -xattrs option.
XATTR_DEFAULT = 1
+###############################################
+# SELinux labelling support build options #
+###############################################
+#
+# Building SELinux labelling support for Mksquashfs. This provides an
+# alternative to reading SELinux labels from the filesystem with XATTR
+# support. It is possible to label the files in the Squashfs filesystem
+# differently than the source filesystem with this option.
+#
+# Note that SELinux labelling support requries that XATTR is also
+# supported.
+#
+# If your build/target environment does not have support for SELinux then
+# comment out the next line to build Mksquashfs without SELinux labelling
+# support.
+SELINUX_SUPPORT = 1
###############################################
# End of BUILD options section #
@@ -117,7 +133,7 @@
UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \
unsquash-4.o swap.o compressor.o unsquashfs_info.o
-CFLAGS ?= -O2
+CFLAGS ?= -O2 -ggdb
CFLAGS += $(EXTRA_CFLAGS) $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 \
-D_LARGEFILE_SOURCE -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" \
-Wall
@@ -185,6 +201,14 @@
endif
MKSQUASHFS_OBJS += xattr.o read_xattrs.o
UNSQUASHFS_OBJS += read_xattrs.o unsquashfs_xattr.o
+
+# SELinux support is only available if XATTR support is available
+ifeq ($(SELINUX_SUPPORT),1)
+CFLAGS += -DSELINUX_SUPPORT
+MKSQUASHFS_OBJS += selinux.o
+LIBS += -lselinux
+endif
+
endif
#
diff -urN --exclude compile_commands.json a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
--- a/squashfs-tools/mksquashfs.c 2017-12-06 15:59:56.569288884 +0900
+++ b/squashfs-tools/mksquashfs.c 2017-12-06 16:02:03.028041005 +0900
@@ -77,6 +77,7 @@
#include "read_fs.h"
#include "restore.h"
#include "process_fragments.h"
+#include "selinux.h"
int delete = FALSE;
int fd;
@@ -284,6 +285,11 @@
int append_fragments = 0;
struct append_file **file_mapping;
+/* selinux label */
+squashfs_selinux_handle *sehnd = NULL;
+char *context_file = NULL;
+char *mount_point = NULL;
+
static char *read_from_disk(long long start, unsigned int avail_bytes);
void add_old_root_entry(char *name, squashfs_inode inode, int inode_number,
int type);
@@ -5332,6 +5338,15 @@
else if(strcmp(argv[i], "-xattrs") == 0)
no_xattrs = FALSE;
+ else if(strcmp(argv[i], "-context-file") == 0) {
+ if(++i == argc) {
+ ERROR("%s: -context-file: missing filename\n",
+ argv[0]);
+ exit(1);
+ }
+ context_file = argv[i];
+ }
+
else if(strcmp(argv[i], "-nopad") == 0)
nopad = TRUE;
@@ -5347,6 +5362,15 @@
else if(strcmp(argv[i], "-keep-as-directory") == 0)
keep_as_directory = TRUE;
+ else if(strcmp(argv[i], "-mount-point") == 0) {
+ if(++i == argc) {
+ ERROR("%s: -mount-point: missing mount point name\n",
+ argv[0]);
+ exit(1);
+ }
+ mount_point = argv[i];
+ }
+
else if(strcmp(argv[i], "-exit-on-error") == 0)
exit_on_error = TRUE;
@@ -5382,6 +5406,9 @@
NOXOPT_STR "\n");
ERROR("-xattrs\t\t\tstore extended attributes" XOPT_STR
"\n");
+ ERROR("-context-file <file>\tApply SELinux context "
+ "xattr from <file> instead\n\t\t\t"
+ "of reading xattr from filesystem\n");
ERROR("-noI\t\t\tdo not compress inode table\n");
ERROR("-noD\t\t\tdo not compress data blocks\n");
ERROR("-noF\t\t\tdo not compress fragment blocks\n");
@@ -5402,6 +5429,9 @@
ERROR("\t\t\tdirectory containing that directory, "
"rather than the\n");
ERROR("\t\t\tcontents of the directory\n");
+ ERROR("-mount-point <name>\tWhen applying attributes such "
+ "as SELinux context, treat\n\t\t\t"
+ "the filesystem as mounted at <name>\n");
ERROR("-4k-align\t\tenables 4k alignment of all files\n");
ERROR("\nFilesystem filter options:\n");
ERROR("-p <pseudo-definition>\tAdd pseudo file "
diff -urN --exclude compile_commands.json a/squashfs-tools/selinux.c b/squashfs-tools/selinux.c
--- a/squashfs-tools/selinux.c 1970-01-01 09:00:00.000000000 +0900
+++ b/squashfs-tools/selinux.c 2017-12-06 15:59:36.481487118 +0900
@@ -0,0 +1,61 @@
+/* Copyright 2015 The Android Open Source Project */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <selinux/label.h>
+
+#include "error.h"
+#include "selinux.h"
+#include "xattr.h"
+
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+
+squashfs_selinux_handle *get_sehnd(const char *context_file) {
+ struct selinux_opt seopts[] = {
+ {
+ .type = SELABEL_OPT_PATH,
+ .value = context_file
+ }
+ };
+ struct selabel_handle *sehnd =
+ selabel_open(SELABEL_CTX_FILE, seopts, ARRAY_SIZE(seopts));
+
+ if(sehnd == NULL)
+ BAD_ERROR("Failure calling selabel_open: %s\n", strerror(errno));
+
+ return sehnd;
+}
+
+static char *set_selabel(const char *path, unsigned int mode, struct selabel_handle *sehnd) {
+ char *secontext;
+ if(sehnd == NULL)
+ BAD_ERROR("selabel handle is NULL\n");
+
+ int full_name_size = strlen(path) + 2;
+ char* full_name = (char*) malloc(full_name_size);
+ if(full_name == NULL)
+ MEM_ERROR();
+
+ full_name[0] = '/';
+ strncpy(full_name + 1, path, full_name_size - 1);
+
+ if(selabel_lookup(sehnd, &secontext, full_name, mode))
+ secontext = strdup("u:object_r:unlabeled:s0");
+
+ free(full_name);
+ return secontext;
+}
+
+void read_selinux_xattr_from_context_file(char *filename, int mode,
+ squashfs_selinux_handle *sehnd, struct xattr_list *xattrs) {
+ char *attr_val;
+
+ xattrs->type = get_prefix(xattrs, "security.selinux");
+ attr_val = set_selabel(filename, mode, sehnd);
+ xattrs->value = (void *)attr_val;
+ xattrs->vsize = strlen(attr_val);
+}
+
diff -urN --exclude compile_commands.json a/squashfs-tools/selinux.h b/squashfs-tools/selinux.h
--- a/squashfs-tools/selinux.h 1970-01-01 09:00:00.000000000 +0900
+++ b/squashfs-tools/selinux.h 2017-12-04 17:11:59.999931242 +0900
@@ -0,0 +1,27 @@
+/* Copyright 2015 The Android Open Source Project */
+
+#ifndef SELINUX_H
+#define SELINUX_H
+
+#include "xattr.h"
+
+#ifdef SELINUX_SUPPORT
+typedef struct selabel_handle squashfs_selinux_handle;
+extern squashfs_selinux_handle *get_sehnd(const char *context_file);
+extern void read_selinux_xattr_from_context_file(char *filename, int mode,
+ struct selabel_handle *sehnd, struct xattr_list *xattrs);
+#else
+typedef void squashfs_selinux_handle;
+
+
+static squashfs_selinux_handle *get_sehnd(const char *context_file) {
+ return NULL;
+}
+
+
+static void read_selinux_xattr_from_context_file(char *filename, int mode,
+ squashfs_selinux_handle *sehnd, struct xattr_list *xattrs) {
+}
+#endif
+
+#endif
diff -urN --exclude compile_commands.json a/squashfs-tools/xattr.c b/squashfs-tools/xattr.c
--- a/squashfs-tools/xattr.c 2017-12-06 15:59:56.569288884 +0900
+++ b/squashfs-tools/xattr.c 2017-12-06 15:59:24.473605618 +0900
@@ -33,6 +33,7 @@
#include <errno.h>
#include <dirent.h>
#include <string.h>
+#include <stdint.h>
#include <stdlib.h>
#include <sys/xattr.h>
@@ -40,6 +41,7 @@
#include "squashfs_swap.h"
#include "mksquashfs.h"
#include "xattr.h"
+#include "selinux.h"
#include "error.h"
#include "progressbar.h"
@@ -76,6 +78,8 @@
extern long long bytes;
extern int fd;
extern unsigned int xattr_bytes, total_xattr_bytes;
+extern char *context_file;
+extern char *mount_point;
/* helper functions from mksquashfs.c */
extern unsigned short get_checksum(char *, int, unsigned short);
@@ -83,14 +87,35 @@
extern long long generic_write_table(int, void *, int, void *, int);
extern int mangle(char *, char *, int, int, int, int);
extern char *pathname(struct dir_ent *);
+extern char *subpathname(struct dir_ent *);
/* helper functions and definitions from read_xattrs.c */
extern int read_xattrs_from_disk(int, struct squashfs_super_block *);
extern struct xattr_list *get_xattr(int, unsigned int *, int);
extern struct prefix prefix_table[];
+/* selinux label */
+extern squashfs_selinux_handle *sehnd;
-static int get_prefix(struct xattr_list *xattr, char *name)
+
+void alloc_mounted_path(const char *mount_point, const char *subpath, char **new_path) {
+ size_t mount_point_len = strlen(mount_point);
+ size_t subpath_len = strlen(subpath);
+ size_t new_path_len = mount_point_len + subpath_len + 1;
+
+ if(new_path_len < mount_point_len || new_path_len < subpath_len)
+ BAD_ERROR("Cannot allocate mounted path length; it is over %d\n",
+ SIZE_MAX);
+
+ *new_path = malloc(new_path_len);
+ if (*new_path == NULL)
+ MEM_ERROR();
+
+ strcpy(*new_path, mount_point);
+ strcat(*new_path, subpath);
+}
+
+int get_prefix(struct xattr_list *xattr, char *name)
{
int i;
@@ -110,13 +135,49 @@
return prefix_table[i].type;
}
-
-static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs)
+static struct xattr_list *xattr_list_add(int *xattr_count, struct xattr_list **xattrs) {
+ struct xattr_list *x, *next_xattr;
+
+ x = realloc(*xattrs, ++*xattr_count * sizeof(struct xattr_list));
+ if(x == NULL)
+ MEM_ERROR();
+
+ next_xattr = &x[*xattr_count - 1];
+ memset(next_xattr, 0, sizeof(struct xattr_list));
+
+ *xattrs = x;
+ return next_xattr;
+}
+
+static struct xattr_list *xattr_list_trim(int *xattr_count, struct xattr_list **xattrs) {
+ struct xattr_list *x, *last_xattr;
+
+ if (*xattr_count == 0 || *xattrs == NULL)
+ return NULL;
+ x = *xattrs;
+
+ last_xattr = &x[*xattr_count - 1];
+ free(last_xattr->full_name);
+ free(last_xattr->value);
+
+ if (--*xattr_count == 0) {
+ free(*xattrs);
+ *xattrs = NULL;
+ return NULL;
+ }
+
+ x = realloc(*xattrs, *xattr_count * sizeof(struct xattr_list));
+ if(x == NULL)
+ MEM_ERROR();
+
+ *xattrs = x;
+ return &x[*xattr_count - 1];
+}
+
+static int read_xattrs_from_system(char *filename, int *xattr_count, struct xattr_list **xattrs)
{
ssize_t size, vsize;
char *xattr_names, *p;
- int i;
- struct xattr_list *xattr_list = NULL;
while(1) {
size = llistxattr(filename, NULL, 0);
@@ -152,74 +213,69 @@
break;
}
- for(i = 0, p = xattr_names; p < xattr_names + size; i++) {
- struct xattr_list *x = realloc(xattr_list, (i + 1) *
- sizeof(struct xattr_list));
- if(x == NULL)
- MEM_ERROR();
- xattr_list = x;
+ for(p = xattr_names; p < xattr_names + size; ) {
+ struct xattr_list *next_xattr = xattr_list_add(xattr_count, xattrs);
- xattr_list[i].type = get_prefix(&xattr_list[i], p);
+ next_xattr->type = get_prefix(next_xattr, p);
p += strlen(p) + 1;
- if(xattr_list[i].type == -1) {
+ if(next_xattr->type == -1) {
ERROR("Unrecognised xattr prefix %s\n",
- xattr_list[i].full_name);
- free(xattr_list[i].full_name);
- i--;
+ next_xattr->full_name);
+ xattr_list_trim(xattr_count, xattrs);
continue;
}
while(1) {
- vsize = lgetxattr(filename, xattr_list[i].full_name,
+ errno = 0;
+ vsize = lgetxattr(filename, next_xattr->full_name,
NULL, 0);
if(vsize < 0) {
- ERROR_START("lgetxattr failed for %s in "
- "read_attrs, because %s", filename,
- strerror(errno));
+ ERROR_START("lgetxattr failed for %s attrib %s "
+ "in read_attrs, because %s", filename,
+ next_xattr->full_name, strerror(errno));
ERROR_EXIT(". Ignoring");
- free(xattr_list[i].full_name);
+ xattr_list_trim(xattr_count, xattrs);
goto failed;
}
- xattr_list[i].value = malloc(vsize);
- if(xattr_list[i].value == NULL)
+ next_xattr->value = malloc(vsize);
+ if(next_xattr->value == NULL)
MEM_ERROR();
- vsize = lgetxattr(filename, xattr_list[i].full_name,
- xattr_list[i].value, vsize);
+ errno = 0;
+ vsize = lgetxattr(filename, next_xattr->full_name,
+ next_xattr->value, vsize);
if(vsize < 0) {
- free(xattr_list[i].value);
+ free(next_xattr->value);
+ next_xattr->value = NULL;
if(errno == ERANGE)
/* xattr grew? Try again */
continue;
else {
ERROR_START("lgetxattr failed for %s "
- "in read_attrs, because %s",
- filename, strerror(errno));
+ "attrib %s in read_attrs, "
+ "because %s", filename,
+ next_xattr->full_name,
+ strerror(errno));
ERROR_EXIT(". Ignoring");
- free(xattr_list[i].full_name);
+ xattr_list_trim(xattr_count, xattrs);
goto failed;
}
}
-
+
break;
}
- xattr_list[i].vsize = vsize;
+ next_xattr->vsize = vsize;
TRACE("read_xattrs_from_system: filename %s, xattr name %s,"
- " vsize %d\n", filename, xattr_list[i].full_name,
- xattr_list[i].vsize);
+ " vsize %d\n", filename, next_xattr->full_name,
+ next_xattr->vsize);
}
free(xattr_names);
- *xattrs = xattr_list;
- return i;
+ return 1;
failed:
- while(--i >= 0) {
- free(xattr_list[i].full_name);
- free(xattr_list[i].value);
- }
- free(xattr_list);
+ while(xattr_list_trim(xattr_count, xattrs) != NULL);
free(xattr_names);
return 0;
}
@@ -608,13 +664,31 @@
struct dir_ent *dir_ent = d;
struct inode_info *inode = dir_ent->inode;
char *filename = pathname(dir_ent);
- struct xattr_list *xattr_list;
- int xattrs;
+ struct xattr_list *xattr_list = NULL, *next_xattr = NULL;
+ int xattrs = 0;
if(no_xattrs || IS_PSEUDO(inode) || inode->root_entry)
return SQUASHFS_INVALID_XATTR;
- xattrs = read_xattrs_from_system(filename, &xattr_list);
+ read_xattrs_from_system(filename, &xattrs, &xattr_list);
+
+ if(context_file) {
+ if(sehnd == NULL)
+ sehnd = get_sehnd(context_file);
+ if(mount_point) {
+ char *mounted_path;
+ alloc_mounted_path(mount_point, subpathname(dir_ent), &mounted_path);
+ next_xattr = xattr_list_add(&xattrs, &xattr_list);
+ read_selinux_xattr_from_context_file(mounted_path, inode->buf.st_mode,
+ sehnd, next_xattr);
+ free(mounted_path);
+ } else {
+ next_xattr = xattr_list_add(&xattrs, &xattr_list);
+ read_selinux_xattr_from_context_file(filename, inode->buf.st_mode,
+ sehnd, next_xattr);
+ }
+ }
+
if(xattrs == 0)
return SQUASHFS_INVALID_XATTR;
diff -urN --exclude compile_commands.json a/squashfs-tools/xattr.h b/squashfs-tools/xattr.h
--- a/squashfs-tools/xattr.h 2017-12-06 15:59:56.569288884 +0900
+++ b/squashfs-tools/xattr.h 2017-12-04 14:31:39.653943076 +0900
@@ -24,6 +24,8 @@
* xattr.h
*/
+#include "squashfs_fs.h"
+
#define XATTR_VALUE_OOL SQUASHFS_XATTR_VALUE_OOL
#define XATTR_PREFIX_MASK SQUASHFS_XATTR_PREFIX_MASK
@@ -66,6 +68,7 @@
extern int generate_xattrs(int, struct xattr_list *);
#ifdef XATTR_SUPPORT
+extern int get_prefix(struct xattr_list *xattr, char *name);
extern int get_xattrs(int, struct squashfs_super_block *);
extern int read_xattrs(void *);
extern long long write_xattrs();
@@ -77,6 +80,12 @@
extern struct xattr_list *get_xattr(int, unsigned int *, int);
extern void free_xattr(struct xattr_list *, int);
#else
+static inline int get_prefix(struct xattr_list *xattr, char *name)
+{
+ return -1;
+}
+
+
static inline int get_xattrs(int fd, struct squashfs_super_block *sBlk)
{
if(sBlk->xattr_id_table_start != SQUASHFS_INVALID_BLK) {