summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorAdrien Schildknecht <adriens@google.com>2016-11-29 22:01:52 -0800
committerTheodore Ts'o <tytso@mit.edu>2017-05-23 22:09:54 -0400
commit1e43f83f7ab338f64f77299031e0b8bf1b43e034 (patch)
tree65ad9d296b31780cf9010402b2747661fc13eb34 /contrib
parented8e189b38a96cf678e0ef901dd9a3fdb6c133d4 (diff)
downloade2fsprogs-1e43f83f7ab338f64f77299031e0b8bf1b43e034.tar.gz
AOSP: e2fsdroid: read and enforce android's permissions
Set the permissions and the extended attributes as defined by fs_config and selinux. Test: create an image with make_ext4 and with mke2fs + e2fsdroid Compare the output of: for f in `find . | sort`; do xattr -l "$f"; md5sum "$f" ls -lah "$f" done Change-Id: I64c97f81c7f5e2bcf3cee3431e410d064cf0735a From AOSP commit: 4c1e1f46301b3ff7f60be1d8e943ecc23b917ca7 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'contrib')
-rw-r--r--contrib/android/Android.mk15
-rw-r--r--contrib/android/e2fsdroid.c41
-rw-r--r--contrib/android/perms.c299
-rw-r--r--contrib/android/perms.h38
4 files changed, 388 insertions, 5 deletions
diff --git a/contrib/android/Android.mk b/contrib/android/Android.mk
index 60186959..ac128578 100644
--- a/contrib/android/Android.mk
+++ b/contrib/android/Android.mk
@@ -4,13 +4,18 @@ e2fsdroid_src := e2fsdroid.c \
block_range.c \
fsmap.c \
block_list.c \
- base_fs.c
+ base_fs.c \
+ perms.c
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(e2fsdroid_src)
LOCAL_MODULE := e2fsdroid
LOCAL_SHARED_LIBRARIES := libext2fs-host \
- libext2_com_err-host
+ libext2_com_err-host \
+ libcutils \
+ libbase \
+ libselinux \
+ libcrypto
include $(BUILD_HOST_EXECUTABLE)
@@ -18,5 +23,9 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(e2fsdroid_src)
LOCAL_MODULE := e2fsdroid
LOCAL_SHARED_LIBRARIES := libext2fs \
- libext2_com_err
+ libext2_com_err \
+ libcutils \
+ libbase \
+ libselinux \
+ libcrypto
include $(BUILD_EXECUTABLE)
diff --git a/contrib/android/e2fsdroid.c b/contrib/android/e2fsdroid.c
index 46782067..7237030a 100644
--- a/contrib/android/e2fsdroid.c
+++ b/contrib/android/e2fsdroid.c
@@ -5,6 +5,7 @@
#include <limits.h>
#include <ext2fs/ext2fs.h>
+#include "perms.h"
#include "base_fs.h"
#include "block_list.h"
@@ -13,11 +14,18 @@ const char *in_file;
const char *block_list;
const char *basefs_out;
const char *mountpoint = "";
+static time_t fixed_time;
+static char *fs_config_file;
+static char *file_contexts;
+static char *product_out;
+static int android_configure;
int android_sparse_file = 1;
static void usage(int ret)
{
- fprintf(stderr, "%s [-B block_list] [-D basefs_out] [-e] image\n",
+ fprintf(stderr, "%s [-B block_list] [-D basefs_out] [-T timestamp]\n"
+ "\t[-C fs_config] [-S file_contexts] [-p product_out]\n"
+ "\t[-a mountpoint] [-e] image\n",
prog_name);
exit(ret);
}
@@ -40,6 +48,7 @@ static char *absolute_path(const char *file)
int main(int argc, char *argv[])
{
int c;
+ char *p;
int flags = EXT2_FLAG_RW;
errcode_t retval;
io_manager io_mgr;
@@ -47,8 +56,26 @@ int main(int argc, char *argv[])
add_error_table(&et_ext2_error_table);
- while ((c = getopt (argc, argv, "D:B:e")) != EOF) {
+ while ((c = getopt (argc, argv, "T:C:S:p:a:D:B:e")) != EOF) {
switch (c) {
+ case 'T':
+ fixed_time = strtoul(optarg, &p, 0);
+ android_configure = 1;
+ break;
+ case 'C':
+ fs_config_file = absolute_path(optarg);
+ android_configure = 1;
+ break;
+ case 'S':
+ file_contexts = absolute_path(optarg);
+ android_configure = 1;
+ break;
+ case 'p':
+ product_out = strdup(optarg);
+ break;
+ case 'a':
+ mountpoint = strdup(optarg);
+ break;
case 'D':
basefs_out = absolute_path(optarg);
break;
@@ -75,6 +102,16 @@ int main(int argc, char *argv[])
return retval;
}
+ if (android_configure) {
+ retval = android_configure_fs(fs, product_out, mountpoint,
+ file_contexts, fs_config_file, fixed_time);
+ if (retval) {
+ com_err(prog_name, retval, "%s",
+ "while configuring the file system");
+ exit(1);
+ }
+ }
+
if (block_list) {
retval = fsmap_iter_filsys(fs, &block_list_format, block_list,
mountpoint);
diff --git a/contrib/android/perms.c b/contrib/android/perms.c
new file mode 100644
index 00000000..6a544189
--- /dev/null
+++ b/contrib/android/perms.c
@@ -0,0 +1,299 @@
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE //asprintf
+#endif
+#include "perms.h"
+#include "support/nls-enable.h"
+#include <time.h>
+#include <sys/stat.h>
+
+#ifndef XATTR_SELINUX_SUFFIX
+# define XATTR_SELINUX_SUFFIX "selinux"
+#endif
+#ifndef XATTR_CAPS_SUFFIX
+# define XATTR_CAPS_SUFFIX "capability"
+#endif
+
+struct inode_params {
+ ext2_filsys fs;
+ char *path;
+ char *filename;
+ char *target_out;
+ fs_config_f fs_config_func;
+ struct selabel_handle *sehnd;
+ time_t fixed_time;
+};
+
+static errcode_t ino_add_xattr(ext2_filsys fs, ext2_ino_t ino, const char *name,
+ const void *value, int value_len)
+{
+ errcode_t retval, close_retval;
+ struct ext2_xattr_handle *xhandle;
+
+ retval = ext2fs_xattrs_open(fs, ino, &xhandle);
+ if (retval) {
+ com_err(__func__, retval, _("while opening inode %u"), ino);
+ return retval;
+ }
+ retval = ext2fs_xattrs_read(xhandle);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while reading xattrs of inode %u"), ino);
+ goto xattrs_close;
+ }
+ retval = ext2fs_xattr_set(xhandle, name, value, value_len);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while setting xattrs of inode %u"), ino);
+ goto xattrs_close;
+ }
+ retval = ext2fs_xattrs_write(xhandle);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while writting xattrs of inode %u"), ino);
+ goto xattrs_close;
+ }
+xattrs_close:
+ close_retval = ext2fs_xattrs_close(&xhandle);
+ if (close_retval) {
+ com_err(__func__, close_retval,
+ _("while closing xattrs of inode %u"), ino);
+ return retval ? retval : close_retval;
+ }
+ return retval;
+}
+
+static errcode_t set_selinux_xattr(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+ char *secontext = NULL;
+ struct ext2_inode inode;
+
+ if (params->sehnd == NULL)
+ return 0;
+
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while reading inode %u"), ino);
+ return retval;
+ }
+
+ retval = selabel_lookup(params->sehnd, &secontext, params->filename,
+ inode.i_mode);
+ if (retval < 0) {
+ com_err(__func__, retval,
+ _("searching for label \"%s\""), params->filename);
+ return retval;
+ }
+
+ retval = ino_add_xattr(fs, ino, "security." XATTR_SELINUX_SUFFIX,
+ secontext, strlen(secontext) + 1);
+
+ freecon(secontext);
+ return retval;
+}
+
+static errcode_t set_perms_and_caps(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+ uint64_t capabilities = 0;
+ struct ext2_inode inode;
+ struct vfs_cap_data cap_data;
+ unsigned int uid = 0, gid = 0, imode = 0;
+
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval, _("while reading inode %u"), ino);
+ return retval;
+ }
+
+ /* Permissions */
+ if (params->fs_config_func != NULL) {
+ params->fs_config_func(params->filename, S_ISDIR(inode.i_mode),
+ params->target_out, &uid, &gid, &imode,
+ &capabilities);
+ inode.i_uid = uid & 0xffff;
+ inode.i_gid = gid & 0xffff;
+ inode.i_mode = (inode.i_mode & S_IFMT) | (imode & 0xffff);
+ retval = ext2fs_write_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while writting inode %u"), ino);
+ return retval;
+ }
+ }
+
+ /* Capabilities */
+ if (!capabilities)
+ return 0;
+ memset(&cap_data, 0, sizeof(cap_data));
+ cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
+ cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff);
+ cap_data.data[1].permitted = (uint32_t) (capabilities >> 32);
+ return ino_add_xattr(fs, ino, "security." XATTR_CAPS_SUFFIX,
+ &cap_data, sizeof(cap_data));
+}
+
+static errcode_t set_timestamp(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+ struct ext2_inode inode;
+
+ if (params->fixed_time != -1) {
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while reading inode %u"), ino);
+ return retval;
+ }
+ inode.i_atime = 0;
+ inode.i_mtime = inode.i_ctime = params->fixed_time;
+ retval = ext2fs_write_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while writting inode %u"), ino);
+ return retval;
+ }
+ }
+
+ return 0;
+}
+
+static int is_dir(ext2_filsys fs, ext2_ino_t ino)
+{
+ struct ext2_inode inode;
+
+ if (ext2fs_read_inode(fs, ino, &inode))
+ return 0;
+ return S_ISDIR(inode.i_mode);
+}
+
+static errcode_t androidify_inode(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+
+ retval = set_timestamp(fs, ino, params);
+ if (retval)
+ return retval;
+
+ retval = set_selinux_xattr(fs, ino, params);
+ if (retval)
+ return retval;
+
+ return set_perms_and_caps(fs, ino, params);
+}
+
+static int walk_dir(ext2_ino_t dir EXT2FS_ATTR((unused)),
+ int flags EXT2FS_ATTR((unused)),
+ struct ext2_dir_entry *de,
+ int offset EXT2FS_ATTR((unused)),
+ int blocksize EXT2FS_ATTR((unused)),
+ char *buf EXT2FS_ATTR((unused)), void *priv_data)
+{
+ __u16 name_len;
+ errcode_t retval;
+ struct inode_params *params = (struct inode_params *)priv_data;
+
+ name_len = de->name_len & 0xff;
+ if (!strncmp(de->name, ".", name_len)
+ || (!strncmp(de->name, "..", name_len)))
+ return 0;
+
+ if (asprintf(&params->filename, "%s/%.*s", params->path, name_len,
+ de->name) < 0)
+ return -ENOMEM;
+
+ if (!strncmp(de->name, "lost+found", 10)) {
+ retval = set_selinux_xattr(params->fs, de->inode, params);
+ if (retval)
+ goto end;
+ } else {
+ retval = androidify_inode(params->fs, de->inode, params);
+ if (retval)
+ goto end;
+ if (is_dir(params->fs, de->inode)) {
+ char *cur_path = params->path;
+ char *cur_filename = params->filename;
+ params->path = params->filename;
+ ext2fs_dir_iterate2(params->fs, de->inode, 0, NULL,
+ walk_dir, params);
+ params->path = cur_path;
+ params->filename = cur_filename;
+ }
+ }
+
+end:
+ free(params->filename);
+ return retval;
+}
+
+errcode_t __android_configure_fs(ext2_filsys fs, char *target_out,
+ char *mountpoint,
+ fs_config_f fs_config_func,
+ struct selabel_handle *sehnd,
+ time_t fixed_time)
+{
+ errcode_t retval;
+ struct inode_params params = {
+ .fs = fs,
+ .target_out = target_out,
+ .fs_config_func = fs_config_func,
+ .sehnd = sehnd,
+ .fixed_time = fixed_time,
+ .path = mountpoint,
+ .filename = mountpoint,
+ };
+
+ retval = set_selinux_xattr(fs, EXT2_ROOT_INO, &params);
+ if (retval)
+ return retval;
+ retval = set_timestamp(fs, EXT2_ROOT_INO, &params);
+ if (retval)
+ return retval;
+
+ return ext2fs_dir_iterate2(fs, EXT2_ROOT_INO, 0, NULL, walk_dir,
+ &params);
+}
+
+errcode_t android_configure_fs(ext2_filsys fs, char *target_out,
+ char *mountpoint,
+ char *file_contexts,
+ char *fs_config_file, time_t fixed_time)
+{
+ errcode_t retval;
+ fs_config_f fs_config_func = NULL;
+ struct selabel_handle *sehnd = NULL;
+
+ /* Retrieve file contexts */
+ if (file_contexts) {
+ struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
+ seopts[0].value = file_contexts;
+ sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+ if (!sehnd) {
+ com_err(__func__, -EINVAL,
+ _("while opening file contexts \"%s\""),
+ seopts[0].value);
+ return -EINVAL;
+ }
+ }
+
+ /* Load the FS config */
+ if (fs_config_file) {
+ retval = load_canned_fs_config(fs_config_file);
+ if (retval < 0) {
+ com_err(__func__, retval,
+ _("while loading fs_config \"%s\""),
+ fs_config_file);
+ return retval;
+ }
+ fs_config_func = canned_fs_config;
+ } else if (mountpoint)
+ fs_config_func = fs_config;
+
+ return __android_configure_fs(fs, target_out, mountpoint,
+ fs_config_func, sehnd, fixed_time);
+}
diff --git a/contrib/android/perms.h b/contrib/android/perms.h
new file mode 100644
index 00000000..6342faf4
--- /dev/null
+++ b/contrib/android/perms.h
@@ -0,0 +1,38 @@
+#ifndef ANDROID_PERMS_H
+# define ANDROID_PERMS_H
+
+# include "config.h"
+# include <ext2fs/ext2fs.h>
+
+typedef void (*fs_config_f)(const char *path, int dir,
+ const char *target_out_path,
+ unsigned *uid, unsigned *gid,
+ unsigned *mode, uint64_t *capabilities);
+
+# ifdef _WIN32
+struct selabel_handle;
+static inline errcode_t android_configure_fs(ext2_filsys fs,
+ char *target_out,
+ char *mountpoint,
+ char *file_contexts,
+ char *fs_config_file,
+ time_t fixed_time)
+{
+ return 0;
+}
+# else
+# include <selinux/selinux.h>
+# include <selinux/label.h>
+# if !defined(HOST)
+# include <selinux/android.h>
+# endif
+# include <private/android_filesystem_config.h>
+# include <private/canned_fs_config.h>
+
+errcode_t android_configure_fs(ext2_filsys fs, char *target_out,
+ char *mountpoint,
+ char *file_contexts,
+ char *fs_config_file, time_t fixed_time);
+
+# endif
+#endif /* !ANDROID_PERMS_H */