LOCAL_C_INCLUDES += external/zlib
LOCAL_SHARED_LIBRARIES := libz
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
include $(BUILD_SHARED_LIBRARY)
LOCAL_C_INCLUDES += external/zlib
LOCAL_STATIC_LIBRARIES := libz
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
include $(BUILD_STATIC_LIBRARY)
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libz
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES += libext4_utils libz
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := make_ext4fs
LOCAL_STATIC_LIBRARIES += libext4_utils libz
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES += libext4_utils libz
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES += libext4_utils libz
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
#include "contents.h"
#include "extent.h"
#include "indirect.h"
+#include "xattr.h"
static u32 dentry_size(u32 entries, struct dentry *dentries)
{
return 0;
}
+
+#ifdef HAVE_SELINUX
+#define XATTR_SELINUX_SUFFIX "selinux"
+
+/* XXX */
+#define cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+
+int inode_set_selinux(u32 inode_num, const char *secon)
+{
+ struct ext4_inode *inode = get_inode(inode_num);
+ u32 *hdr;
+ struct ext4_xattr_entry *entry;
+ size_t name_len = strlen(XATTR_SELINUX_SUFFIX);
+ size_t value_len = strlen(secon)+1;
+ size_t size, min_offs;
+ char *val;
+
+ if (!secon)
+ return 0;
+
+ if (!inode)
+ return -1;
+
+ hdr = (u32 *) (inode + 1);
+ *hdr = cpu_to_le32(EXT4_XATTR_MAGIC);
+ entry = (struct ext4_xattr_entry *) (hdr+1);
+ memset(entry, 0, EXT4_XATTR_LEN(name_len));
+ entry->e_name_index = EXT4_XATTR_INDEX_SECURITY;
+ entry->e_name_len = name_len;
+ memcpy(entry->e_name, XATTR_SELINUX_SUFFIX, name_len);
+ entry->e_value_size = cpu_to_le32(value_len);
+ min_offs = (char *)inode + info.inode_size - (char*) entry;
+ size = EXT4_XATTR_SIZE(value_len);
+ val = (char *)entry + min_offs - size;
+ entry->e_value_offs = cpu_to_le16(min_offs - size);
+ memset(val + size - EXT4_XATTR_PAD, 0, EXT4_XATTR_PAD);
+ memcpy(val, secon, value_len);
+ inode->i_extra_isize = cpu_to_le16(sizeof(struct ext4_inode) - EXT4_GOOD_OLD_INODE_SIZE);
+
+ return 0;
+}
+#else
+int inode_set_selinux(u32 inode_num, const char *secon)
+{
+ return 0;
+}
+#endif
u16 gid;
u32 *inode;
u32 mtime;
+ char *secon;
};
u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries,
u32 make_file(const char *filename, u64 len);
u32 make_link(const char *filename, const char *link);
int inode_set_permissions(u32 inode_num, u16 mode, u16 uid, u16 gid, u32 mtime);
+int inode_set_selinux(u32 inode_num, const char *secon);
#endif
/* Read a local directory and create the same tree in the generated filesystem.
Calls itself recursively with each directory in the given directory */
static u32 build_directory_structure(const char *full_path, const char *dir_path,
- u32 dir_inode, int android)
+ u32 dir_inode, int android, struct selabel_handle *sehnd)
{
int entries = 0;
struct dentry *dentries;
error("can't set android permissions - built without android support");
#endif
}
+#ifdef HAVE_SELINUX
+ if (sehnd) {
+ char *sepath = NULL;
+ asprintf(&sepath, "/%s", dentries[i].path);
+ if (selabel_lookup(sehnd, &dentries[i].secon, sepath, stat.st_mode) < 0) {
+ error("cannot lookup security context for %s", sepath);
+ }
+ if (dentries[i].secon)
+ printf("Labeling %s as %s\n", sepath, dentries[i].secon);
+ free(sepath);
+ }
+#endif
if (S_ISREG(stat.st_mode)) {
dentries[i].file_type = EXT4_FT_REG_FILE;
entry_inode = make_file(dentries[i].full_path, dentries[i].size);
} else if (dentries[i].file_type == EXT4_FT_DIR) {
entry_inode = build_directory_structure(dentries[i].full_path,
- dentries[i].path, inode, android);
+ dentries[i].path, inode, android, sehnd);
} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {
entry_inode = make_link(dentries[i].full_path, dentries[i].link);
} else {
dentries[i].mtime);
if (ret)
error("failed to set permissions on %s\n", dentries[i].path);
+ ret = inode_set_selinux(entry_inode, dentries[i].secon);
+ if (ret)
+ error("failed to set SELinux context on %s\n", dentries[i].path);
free(dentries[i].path);
free(dentries[i].full_path);
free(dentries[i].link);
free((void *)dentries[i].filename);
+ free(dentries[i].secon);
}
free(dentries);
{
reset_ext4fs_info();
info.len = len;
- return make_ext4fs_internal(filename, NULL, NULL, 0, 0, 0, 0, 1, 0);
+ return make_ext4fs_internal(filename, NULL, NULL, 0, 0, 0, 0, 1, 0, 0);
}
int make_ext4fs_internal(const char *filename, const char *directory,
char *mountpoint, int android, int gzip, int sparse,
- int crc, int wipe, int init_itabs)
+ int crc, int wipe, int init_itabs,
+ struct selabel_handle *sehnd)
{
u32 root_inode_num;
u16 root_mode;
ext4_create_resize_inode();
if (directory)
- root_inode_num = build_directory_structure(directory, mountpoint, 0, android);
+ root_inode_num = build_directory_structure(directory, mountpoint, 0, android, sehnd);
else
root_inode_num = build_default_directory_structure();
root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
inode_set_permissions(root_inode_num, root_mode, 0, 0, 0);
+#ifdef HAVE_SELINUX
+ if (sehnd) {
+ char *sepath = NULL;
+ char *secontext = NULL;
+ asprintf(&sepath, "/%s", mountpoint);
+ if (selabel_lookup(sehnd, &secontext, sepath, S_IFDIR) < 0) {
+ error("cannot lookup security context for %s", sepath);
+ }
+ if (secontext) {
+ printf("Labeling %s as %s\n", sepath, secontext);
+ inode_set_selinux(root_inode_num, secontext);
+ }
+ free(sepath);
+ freecon(secontext);
+ }
+#endif
+
ext4_update_free();
if (init_itabs)
#include "ext4_utils.h"
#include "ext4.h"
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#else
+struct selabel_handle;
+#endif
+
void reset_ext4fs_info();
int make_ext4fs(const char *filename, s64 len);
int make_ext4fs_internal(const char *filename, const char *directory,
char *mountpoint, int android, int gzip, int sparse,
- int crc, int wipe, int init_itabs);
+ int crc, int wipe, int init_itabs,
+ struct selabel_handle *sehnd);
#endif
fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
+ fprintf(stderr, " [ -S file_contexts ]\n");
fprintf(stderr, " [ -z | -s ] [ -t ] [ -w ] [ -c ] [ -J ]\n");
fprintf(stderr, " <filename> [<directory>]\n");
}
int crc = 0;
int wipe = 0;
int init_itabs = 0;
+ struct selabel_handle *sehnd = NULL;
+#ifdef HAVE_SELINUX
+ struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
+#endif
- while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fwzJsct")) != -1) {
+ while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fwzJsctS:")) != -1) {
switch (opt) {
case 'l':
info.len = parse_num(optarg);
case 't':
init_itabs = 1;
break;
+ case 'S':
+#ifdef HAVE_SELINUX
+ seopts[0].value = optarg;
+ sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+ if (!sehnd) {
+ perror(optarg);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ break;
default: /* '?' */
usage(argv[0]);
exit(EXIT_FAILURE);
}
return make_ext4fs_internal(filename, directory, mountpoint, android, gzip,
- sparse, crc, wipe, init_itabs);
+ sparse, crc, wipe, init_itabs, sehnd);
}
-#!/bin/bash
+#!/bin/bash -x
#
# To call this script, make sure make_ext4fs is somewhere in PATH
function usage() {
cat<<EOT
Usage:
-mkuserimg.sh [-s] SRC_DIR OUTPUT_FILE EXT_VARIANT MOUNT_POINT SIZE
+mkuserimg.sh [-s] SRC_DIR OUTPUT_FILE EXT_VARIANT MOUNT_POINT SIZE [FILE_CONTEXTS]
EOT
}
shift
fi
-if [ $# -ne 4 -a $# -ne 5 ]; then
+if [ $# -ne 4 -a $# -ne 5 -a $# -ne 6 ]; then
usage
exit 1
fi
EXT_VARIANT=$3
MOUNT_POINT=$4
SIZE=$5
+FC=$6
case $EXT_VARIANT in
ext4) ;;
SIZE=128M
fi
-MAKE_EXT4FS_CMD="make_ext4fs $ENABLE_SPARSE_IMAGE -l $SIZE -a $MOUNT_POINT $OUTPUT_FILE $SRC_DIR"
+if [ -n "$FC" ]; then
+ FCOPT="-S $FC"
+fi
+
+MAKE_EXT4FS_CMD="make_ext4fs $ENABLE_SPARSE_IMAGE $FCOPT -l $SIZE -a $MOUNT_POINT $OUTPUT_FILE $SRC_DIR"
echo $MAKE_EXT4FS_CMD
$MAKE_EXT4FS_CMD
if [ $? -ne 0 ]; then
--- /dev/null
+#include <sys/types.h>
+
+#define EXT4_XATTR_MAGIC 0xEA020000
+#define EXT4_XATTR_INDEX_SECURITY 6
+
+struct ext4_xattr_entry {
+ __u8 e_name_len;
+ __u8 e_name_index;
+ __le16 e_value_offs;
+ __le32 e_value_block;
+ __le32 e_value_size;
+ __le32 e_hash;
+ char e_name[0];
+};
+
+#define EXT4_XATTR_PAD_BITS 2
+#define EXT4_XATTR_PAD (1<<EXT4_XATTR_PAD_BITS)
+#define EXT4_XATTR_ROUND (EXT4_XATTR_PAD-1)
+#define EXT4_XATTR_LEN(name_len) \
+ (((name_len) + EXT4_XATTR_ROUND + \
+ sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND)
+#define EXT4_XATTR_SIZE(size) \
+ (((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND)