diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-04-26 08:39:34 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-04-26 08:39:34 +0000 |
commit | f43824c51fd94ddf989c3bd0f39e961ce68627ec (patch) | |
tree | d7702ccfd742e62de75e3cbe6f16b1d14bac7fe2 | |
parent | 0516bf8fa78813976e3dcf3bd1894792f765f4ef (diff) | |
parent | 334e5e559a8daca1c877b4098511774bfa7ab1be (diff) | |
download | minijail-f43824c51fd94ddf989c3bd0f39e961ce68627ec.tar.gz |
release-request-4850daec-e2fc-44da-a2dc-4646a78e4550-for-git_oc-dr1-release-3944849 snap-temp-L34500000057864766
Change-Id: If5b7fd10bdc81e3f5aebc7bd757d7c0d3d1aa9bb
-rw-r--r-- | Android.mk | 65 | ||||
-rw-r--r-- | gen.mk | 47 | ||||
-rw-r--r-- | libminijail.c | 43 | ||||
-rw-r--r-- | libminijail.h | 2 | ||||
-rw-r--r-- | minijail0.c | 26 | ||||
-rw-r--r-- | system.c | 35 | ||||
-rw-r--r-- | system.h | 24 |
7 files changed, 167 insertions, 75 deletions
@@ -38,54 +38,13 @@ minijailCommonLibraries := libcap # ========================================================= include $(CLEAR_VARS) LOCAL_MODULE := libminijail_generated +include $(LOCAL_PATH)/gen.mk +include $(BUILD_STATIC_LIBRARY) -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -generated_sources_dir := $(local-generated-sources-dir) - -my_gen := $(generated_sources_dir)/$(TARGET_ARCH)/libsyscalls.c -# We need the quotes so the shell script treats the following as one argument. -my_cc := "$(lastword $(CLANG)) \ - $(addprefix -I ,$(TARGET_C_INCLUDES)) \ - $(addprefix -isystem ,$(TARGET_C_SYSTEM_INCLUDES)) \ - $(CLANG_TARGET_GLOBAL_CFLAGS)" -$(my_gen): PRIVATE_CC := $(my_cc) -$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ -$(my_gen): $(LOCAL_PATH)/gen_syscalls.sh - $(transform-generated-source) -$(call include-depfile,$(my_gen).d,$(my_gen)) -LOCAL_GENERATED_SOURCES_$(TARGET_ARCH) += $(my_gen) - -my_gen := $(generated_sources_dir)/$(TARGET_ARCH)/libconstants.c -$(my_gen): PRIVATE_CC := $(my_cc) -$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ -$(my_gen): $(LOCAL_PATH)/gen_constants.sh - $(transform-generated-source) -$(call include-depfile,$(my_gen).d,$(my_gen)) -LOCAL_GENERATED_SOURCES_$(TARGET_ARCH) += $(my_gen) - -# For processes running in 32-bit compat mode on 64-bit processors. -ifdef TARGET_2ND_ARCH -my_gen := $(generated_sources_dir)/$(TARGET_2ND_ARCH)/libsyscalls.c -my_cc := "$(lastword $(CLANG)) \ - $(addprefix -I ,$($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_C_INCLUDES)) \ - $(addprefix -isystem ,$($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_C_SYSTEM_INCLUDES)) \ - $($(TARGET_2ND_ARCH_VAR_PREFIX)CLANG_TARGET_GLOBAL_CFLAGS)" -$(my_gen): PRIVATE_CC := $(my_cc) -$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ -$(my_gen): $(LOCAL_PATH)/gen_syscalls.sh - $(transform-generated-source) -LOCAL_GENERATED_SOURCES_$(TARGET_2ND_ARCH) += $(my_gen) - -my_gen := $(generated_sources_dir)/$(TARGET_2ND_ARCH)/libconstants.c -$(my_gen): PRIVATE_CC := $(my_cc) -$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ -$(my_gen): $(LOCAL_PATH)/gen_constants.sh - $(transform-generated-source) -LOCAL_GENERATED_SOURCES_$(TARGET_2ND_ARCH) += $(my_gen) -endif - -LOCAL_CFLAGS := $(minijailCommonCFlags) -LOCAL_CLANG := true +include $(CLEAR_VARS) +LOCAL_MODULE:= libminijail_generated_vendor +include $(LOCAL_PATH)/gen.mk +LOCAL_VENDOR_MODULE := true include $(BUILD_STATIC_LIBRARY) @@ -103,6 +62,18 @@ LOCAL_SHARED_LIBRARIES := $(minijailCommonLibraries) LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) include $(BUILD_SHARED_LIBRARY) +include $(CLEAR_VARS) +LOCAL_MODULE := libminijail_vendor + +LOCAL_CFLAGS := $(minijailCommonCFlags) +LOCAL_CLANG := true +LOCAL_SRC_FILES := $(libminijailSrcFiles) +LOCAL_VENDOR_MODULE := true + +LOCAL_STATIC_LIBRARIES := libminijail_generated_vendor +LOCAL_SHARED_LIBRARIES := $(minijailCommonLibraries) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) +include $(BUILD_SHARED_LIBRARY) # Example ASan-ified libminijail shared library for target. # Commented out since it's only needed for local debugging. @@ -0,0 +1,47 @@ +LOCAL_MODULE_CLASS := STATIC_LIBRARIES +generated_sources_dir := $(local-generated-sources-dir) + +my_gen := $(generated_sources_dir)/$(TARGET_ARCH)/libsyscalls.c +# We need the quotes so the shell script treats the following as one argument. +my_cc := "$(lastword $(CLANG)) \ + $(addprefix -I ,$(TARGET_C_INCLUDES)) \ + $(addprefix -isystem ,$(TARGET_C_SYSTEM_INCLUDES)) \ + $(CLANG_TARGET_GLOBAL_CFLAGS)" +$(my_gen): PRIVATE_CC := $(my_cc) +$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ +$(my_gen): $(LOCAL_PATH)/gen_syscalls.sh + $(transform-generated-source) +$(call include-depfile,$(my_gen).d,$(my_gen)) +LOCAL_GENERATED_SOURCES_$(TARGET_ARCH) += $(my_gen) + +my_gen := $(generated_sources_dir)/$(TARGET_ARCH)/libconstants.c +$(my_gen): PRIVATE_CC := $(my_cc) +$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ +$(my_gen): $(LOCAL_PATH)/gen_constants.sh + $(transform-generated-source) +$(call include-depfile,$(my_gen).d,$(my_gen)) +LOCAL_GENERATED_SOURCES_$(TARGET_ARCH) += $(my_gen) + +# For processes running in 32-bit compat mode on 64-bit processors. +ifdef TARGET_2ND_ARCH +my_gen := $(generated_sources_dir)/$(TARGET_2ND_ARCH)/libsyscalls.c +my_cc := "$(lastword $(CLANG)) \ + $(addprefix -I ,$($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_C_INCLUDES)) \ + $(addprefix -isystem ,$($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_C_SYSTEM_INCLUDES)) \ + $($(TARGET_2ND_ARCH_VAR_PREFIX)CLANG_TARGET_GLOBAL_CFLAGS)" +$(my_gen): PRIVATE_CC := $(my_cc) +$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ +$(my_gen): $(LOCAL_PATH)/gen_syscalls.sh + $(transform-generated-source) +LOCAL_GENERATED_SOURCES_$(TARGET_2ND_ARCH) += $(my_gen) + +my_gen := $(generated_sources_dir)/$(TARGET_2ND_ARCH)/libconstants.c +$(my_gen): PRIVATE_CC := $(my_cc) +$(my_gen): PRIVATE_CUSTOM_TOOL = $< $(PRIVATE_CC) $@ +$(my_gen): $(LOCAL_PATH)/gen_constants.sh + $(transform-generated-source) +LOCAL_GENERATED_SOURCES_$(TARGET_2ND_ARCH) += $(my_gen) +endif + +LOCAL_CFLAGS := $(minijailCommonCFlags) +LOCAL_CLANG := true diff --git a/libminijail.c b/libminijail.c index dada8fa..cddbffe 100644 --- a/libminijail.c +++ b/libminijail.c @@ -100,6 +100,7 @@ struct minijail { int keep_suppl_gids : 1; int use_caps : 1; int capbset_drop : 1; + int set_ambient_caps : 1; int vfs : 1; int enter_vfs : 1; int skip_remount_private : 1; @@ -388,6 +389,11 @@ void API minijail_capbset_drop(struct minijail *j, uint64_t capmask) j->flags.capbset_drop = 1; } +void API minijail_set_ambient_caps(struct minijail *j) +{ + j->flags.set_ambient_caps = 1; +} + void API minijail_reset_signal_mask(struct minijail *j) { j->flags.reset_signal_mask = 1; @@ -1358,17 +1364,15 @@ static void drop_caps(const struct minijail *j, unsigned int last_valid_cap) cap_t caps = cap_get_proc(); cap_value_t flag[1]; + const size_t ncaps = sizeof(j->caps) * 8; const uint64_t one = 1; unsigned int i; if (!caps) die("can't get process caps"); - if (cap_clear_flag(caps, CAP_INHERITABLE)) - die("can't clear inheritable caps"); - if (cap_clear_flag(caps, CAP_EFFECTIVE)) - die("can't clear effective caps"); - if (cap_clear_flag(caps, CAP_PERMITTED)) - die("can't clear permitted caps"); - for (i = 0; i < sizeof(j->caps) * 8 && i <= last_valid_cap; ++i) { + if (cap_clear(caps)) + die("can't clear caps"); + + for (i = 0; i < ncaps && i <= last_valid_cap; ++i) { /* Keep CAP_SETPCAP for dropping bounding set bits. */ if (i != CAP_SETPCAP && !(j->caps & (one << i))) continue; @@ -1405,6 +1409,31 @@ static void drop_caps(const struct minijail *j, unsigned int last_valid_cap) if (cap_set_proc(caps)) die("can't apply final cleaned capset"); + /* + * If ambient capabilities are supported, clear all capabilities first, + * then raise the requested ones. + */ + if (j->flags.set_ambient_caps) { + if (!cap_ambient_supported()) { + pdie("ambient capabilities not supported"); + } + if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL) != 0) { + pdie("can't clear ambient capabilities"); + } + + for (i = 0; i < ncaps && i <= last_valid_cap; ++i) { + if (!(j->caps & (one << i))) + continue; + + if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, + 0) != 0) { + pdie("prctl(PR_CAP_AMBIENT, " + "PR_CAP_AMBIENT_RAISE, %u) failed", + i); + } + } + } + cap_free(caps); } diff --git a/libminijail.h b/libminijail.h index 2bf3024..9177ca8 100644 --- a/libminijail.h +++ b/libminijail.h @@ -58,6 +58,8 @@ void minijail_log_seccomp_filter_failures(struct minijail *j); /* 'minijail_use_caps' and 'minijail_capbset_drop' are mutually exclusive. */ void minijail_use_caps(struct minijail *j, uint64_t capmask); void minijail_capbset_drop(struct minijail *j, uint64_t capmask); +/* 'minijail_set_ambient_caps' requires 'minijail_use_caps'. */ +void minijail_set_ambient_caps(struct minijail *j); void minijail_reset_signal_mask(struct minijail *j); void minijail_namespace_vfs(struct minijail *j); void minijail_namespace_enter_vfs(struct minijail *j, const char *ns_path); diff --git a/minijail0.c b/minijail0.c index 2c622b4..5917b44 100644 --- a/minijail0.c +++ b/minijail0.c @@ -116,7 +116,7 @@ static void usage(const char *progn) " [-b <src>,<dest>[,<writeable>]] [-k <src>,<dest>,<type>[,<flags>][,<data>]]\n" " [-c <caps>] [-C <dir>] [-P <dir>] [-e[file]] [-f <file>] [-g <group>]\n" " [-m[<uid> <loweruid> <count>]*] [-M[<gid> <lowergid> <count>]*]\n" - " [-S <file>] [-T <type>] [-u <user>] [-V <file>]\n" + " [-S <file>] [-t[size]] [-T <type>] [-u <user>] [-V <file>]\n" " <program> [args...]\n" " -a <table>: Use alternate syscall table <table>.\n" " -b: Bind <src> to <dest> in chroot.\n" @@ -177,7 +177,8 @@ static void usage(const char *progn) " -v: Enter new mount namespace.\n" " -V <file>: Enter specified mount namespace.\n" " -w: Create and join a new anonymous session keyring.\n" - " -Y: Synchronize seccomp filters across thread group.\n"); + " -Y: Synchronize seccomp filters across thread group.\n" + " --ambient: Raise ambient capabilities. Requires -c.\n"); /* clang-format on */ } @@ -201,6 +202,7 @@ static int parse_args(struct minijail *j, int argc, char *argv[], int chroot = 0, pivot_root = 0; int mount_ns = 0, skip_remount = 0; int inherit_suppl_gids = 0, keep_suppl_gids = 0; + int caps = 0, ambient_caps = 0; const size_t path_max = 4096; char *map; size_t size; @@ -211,7 +213,12 @@ static int parse_args(struct minijail *j, int argc, char *argv[], const char *optstring = "u:g:sS:c:C:P:b:V:f:m::M::k:a:e::T:vrGhHinNplLt::IUKwyY"; int longoption_index = 0; - const struct option long_options[] = {{0, 0, 0, 0}}; + /* clang-format off */ + const struct option long_options[] = { + {"ambient", no_argument, 0, 128}, + {0, 0, 0, 0}, + }; + /* clang-format on */ while ((opt = getopt_long(argc, argv, optstring, long_options, &longoption_index)) != -1) { @@ -253,6 +260,7 @@ static int parse_args(struct minijail *j, int argc, char *argv[], binding = 1; break; case 'c': + caps = 1; use_caps(j, optarg); break; case 'C': @@ -427,6 +435,11 @@ static int parse_args(struct minijail *j, int argc, char *argv[], case 'Y': minijail_set_seccomp_filter_tsync(j); break; + /* Long options. */ + case 128: /* Ambient caps. */ + ambient_caps = 1; + minijail_set_ambient_caps(j); + break; default: usage(argv[0]); exit(1); @@ -435,6 +448,13 @@ static int parse_args(struct minijail *j, int argc, char *argv[], break; } + /* Can only set ambient caps when using regular caps. */ + if (ambient_caps && !caps) { + fprintf(stderr, "Can't set ambient capabilities (--ambient) " + "without actually using capabilities (-c).\n"); + exit(1); + } + /* Only allow bind mounts when entering a chroot or using pivot_root. */ if (binding && !(chroot || pivot_root)) { fprintf(stderr, "Can't add bind mounts without chroot or" @@ -35,40 +35,33 @@ #define SECURE_ALL_BITS 0x55 #define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1) #endif -/* For kernels < 4.3. */ -#define OLD_SECURE_ALL_BITS 0x15 -#define OLD_SECURE_ALL_LOCKS (OLD_SECURE_ALL_BITS << 1) + +#define SECURE_BITS_NO_AMBIENT 0x15 +#define SECURE_LOCKS_NO_AMBIENT (SECURE_BITS_NO_AMBIENT << 1) /* * Assert the value of SECURE_ALL_BITS at compile-time. - * Brillo devices are currently compiled against 4.4 kernel headers. Kernel 4.3 + * Android devices are currently compiled against 4.4 kernel headers. Kernel 4.3 * added a new securebit. * When a new securebit is added, the new SECURE_ALL_BITS mask will return EPERM * when used on older kernels. The compile-time assert will catch this situation * at compile time. */ -#ifdef __BRILLO__ +#if defined(__ANDROID__) _Static_assert(SECURE_ALL_BITS == 0x55, "SECURE_ALL_BITS == 0x55."); #endif int lock_securebits(void) { /* - * Kernels 4.3+ define a new securebit (SECURE_NO_CAP_AMBIENT_RAISE), - * so using the SECURE_ALL_BITS and SECURE_ALL_LOCKS masks from - * newer kernel headers will return EPERM on older kernels. Detect this, - * and retry with the right mask for older (2.6.26-4.2) kernels. + * Ambient capabilities can only be raised if they're already present + * in the permitted *and* inheritable set. Therefore, we don't really + * need to lock the NO_CAP_AMBIENT_RAISE securebit, since we are already + * configuring the permitted and inheritable set. */ int securebits_ret = - prctl(PR_SET_SECUREBITS, SECURE_ALL_BITS | SECURE_ALL_LOCKS); - if (securebits_ret < 0) { - if (errno == EPERM) { - /* Possibly running on kernel < 4.3. */ - securebits_ret = - prctl(PR_SET_SECUREBITS, - OLD_SECURE_ALL_BITS | OLD_SECURE_ALL_LOCKS); - } - } + prctl(PR_SET_SECUREBITS, + SECURE_BITS_NO_AMBIENT | SECURE_LOCKS_NO_AMBIENT); if (securebits_ret < 0) { pwarn("prctl(PR_SET_SECUREBITS) failed"); return -1; @@ -144,6 +137,12 @@ unsigned int get_last_valid_cap(void) return last_valid_cap; } +int cap_ambient_supported(void) +{ + return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >= + 0; +} + int config_net_loopback(void) { const char ifname[] = "lo"; @@ -19,15 +19,39 @@ #ifndef _SYSTEM_H_ #define _SYSTEM_H_ +#include <sys/capability.h> +#include <sys/prctl.h> #include <sys/types.h> #ifdef __cplusplus extern "C" { #endif +/* Control the ambient capability set. */ +#ifndef PR_CAP_AMBIENT +#define PR_CAP_AMBIENT 47 +#endif + +#ifndef PR_CAP_AMBIENT_IS_SET +#define PR_CAP_AMBIENT_IS_SET 1 +#endif + +#ifndef PR_CAP_AMBIENT_RAISE +#define PR_CAP_AMBIENT_RAISE 2 +#endif + +#ifndef PR_CAP_AMBIENT_LOWER +#define PR_CAP_AMBIENT_LOWER 3 +#endif + +#ifndef PR_CAP_AMBIENT_CLEAR_ALL +#define PR_CAP_AMBIENT_CLEAR_ALL 4 +#endif + int lock_securebits(void); unsigned int get_last_valid_cap(void); +int cap_ambient_supported(void); int config_net_loopback(void); |