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.
Change-Id: Icad4d38a736137d85835a0eab9650c0c99908721
Signed-off-by: Mohamad Ayyash <mkayyash@google.com>
diff --git a/squashfs-tools/Android.mk b/squashfs-tools/Android.mk
index e266e3d..2df06b6 100644
--- a/squashfs-tools/Android.mk
+++ b/squashfs-tools/Android.mk
@@ -65,6 +65,8 @@
LOCAL_LDLIBS := -lpthread -lm -lz
+LOCAL_STATIC_LIBRARIES := libselinux
+
LOCAL_MODULE_TAGS := optional
include $(BUILD_HOST_EXECUTABLE)
diff --git a/squashfs-tools/android.c b/squashfs-tools/android.c
index 0b1c11a..a59c210 100644
--- a/squashfs-tools/android.c
+++ b/squashfs-tools/android.c
@@ -18,10 +18,66 @@
** images generated by build tools (mkbootfs and mkyaffs2image) and
** by the device side of adb.
*/
-#include "android.h"
-void android_fs_config(char* path, struct stat* stat) {
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <selinux/android.h>
+#include <selinux/label.h>
+#include <selinux/selinux.h>
+
+#include "android.h"
+#include "private/android_filesystem_config.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+void android_fs_config(const char *path, struct stat *stat) {
unsigned long capabilities = 0;
- fs_config(path, S_ISDIR(stat->st_mode), &stat->st_uid, &stat->st_gid, &stat->st_mode, &capabilities);
+ fs_config(path, S_ISDIR(stat->st_mode), &stat->st_uid, &stat->st_gid, &stat->st_mode,
+ &capabilities);
}
+
+struct selabel_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) {
+ perror("Error running selabel_open.");
+ exit(EXIT_FAILURE);
+ }
+ return sehnd;
+}
+
+
+char *set_selabel(const char *path, unsigned int mode, struct selabel_handle *sehnd) {
+ char *secontext;
+ if (sehnd != NULL) {
+ int full_name_size = strlen(path) + 2;
+ char* full_name = (char*) malloc(full_name_size);
+ if (full_name == NULL) {
+ perror("Malloc Failure.");
+ exit(EXIT_FAILURE);
+ }
+
+ 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;
+ }
+ perror("Selabel handle is NULL.");
+ exit(EXIT_FAILURE);
+}
diff --git a/squashfs-tools/android.h b/squashfs-tools/android.h
index e505c6a..766cf0a 100644
--- a/squashfs-tools/android.h
+++ b/squashfs-tools/android.h
@@ -14,6 +14,11 @@
* limitations under the License.
*/
-#include <private/android_filesystem_config.h>
+#ifndef _ANDROID_H_
+#define _ANDROID_H_
-void android_fs_config(char* path, struct stat* stat);
+void android_fs_config(const char *path, struct stat *stat);
+struct selabel_handle *get_sehnd(const char *context_file);
+char *set_selabel(const char *path, unsigned int mode, struct selabel_handle *sehnd);
+
+#endif
diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
index 4f8d020..11401e2 100644
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -81,6 +81,7 @@
#ifdef ANDROID
#include "android.h"
int android_config = FALSE;
+char *context_file = NULL;
#endif
/* ANDROID CHANGES END */
@@ -5542,6 +5543,18 @@
else if(strcmp(argv[i], "-xattrs") == 0)
no_xattrs = FALSE;
+/* ANDROID CHANGES START*/
+#ifdef ANDROID
+ else if(strcmp(argv[i], "-context-file") == 0) {
+ if(++i == argc) {
+ ERROR("%s: -context-file: missing file name\n",
+ argv[0]);
+ exit(1);
+ }
+ context_file = argv[i];
+ }
+#endif
+/* ANDROID CHANGES END */
else if(strcmp(argv[i], "-nopad") == 0)
nopad = TRUE;
@@ -5596,6 +5609,13 @@
NOXOPT_STR "\n");
ERROR("-xattrs\t\t\tstore extended attributes" XOPT_STR
"\n");
+/* ANDROID CHANGES START*/
+#ifdef ANDROID
+ ERROR("-context-file <file>\tApply selinux security "
+ "xattrs from context-file instead\n\t\t\t"
+ "of reading xattrs from file system\n");
+#endif
+/* ANDROID CHANGES END */
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");
diff --git a/squashfs-tools/xattr.c b/squashfs-tools/xattr.c
index b46550c..bef7115 100644
--- a/squashfs-tools/xattr.c
+++ b/squashfs-tools/xattr.c
@@ -43,6 +43,13 @@
#include "error.h"
#include "progressbar.h"
+/* ANDROID CHANGES START*/
+#ifdef ANDROID
+#include "android.h"
+static struct selabel_handle *sehnd = NULL;
+#endif
+/* ANDROID CHANGES END */
+
/* compressed xattr table */
static char *xattr_table = NULL;
static unsigned int xattr_size = 0;
@@ -76,6 +83,9 @@
extern long long bytes;
extern int fd;
extern unsigned int xattr_bytes, total_xattr_bytes;
+/* ANDROID CHANGES START*/
+extern char *context_file;
+/* ANDROID CHANGES END */
/* helper functions from mksquashfs.c */
extern unsigned short get_checksum(char *, int, unsigned short);
@@ -110,7 +120,28 @@
return prefix_table[i].type;
}
-
+
+/* ANDROID CHANGES START*/
+#ifdef ANDROID
+static int read_xattrs_from_context_file(char *filename, int mode,
+ struct selabel_handle *sehnd, struct xattr_list **xattrs)
+{
+ char *attr_val;
+ struct xattr_list *x = malloc(sizeof(*x));
+ if(x == NULL)
+ MEM_ERROR();
+
+ x->type = get_prefix(x, "security.selinux");
+ attr_val = set_selabel(filename, mode, sehnd);
+ x->value = (void *)attr_val;
+ x->vsize = strlen(attr_val);
+ *xattrs = x;
+ return 1;
+}
+#endif
+/* ANDROID CHANGES END */
+
+
static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs)
{
ssize_t size, vsize;
@@ -614,7 +645,21 @@
if(no_xattrs || IS_PSEUDO(inode) || inode->root_entry)
return SQUASHFS_INVALID_XATTR;
+/* ANDROID CHANGES START*/
+#ifdef ANDROID
+ if (context_file) {
+ if (sehnd == NULL)
+ sehnd = get_sehnd(context_file);
+ xattrs = read_xattrs_from_context_file(filename, inode->buf.st_mode,
+ sehnd, &xattr_list);
+ } else {
+ xattrs = read_xattrs_from_system(filename, &xattr_list);
+ }
+#else
xattrs = read_xattrs_from_system(filename, &xattr_list);
+#endif
+/* ANDROID CHANGES END */
+
if(xattrs == 0)
return SQUASHFS_INVALID_XATTR;