aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-04-26 08:39:34 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-04-26 08:39:34 +0000
commitf43824c51fd94ddf989c3bd0f39e961ce68627ec (patch)
treed7702ccfd742e62de75e3cbe6f16b1d14bac7fe2
parent0516bf8fa78813976e3dcf3bd1894792f765f4ef (diff)
parent334e5e559a8daca1c877b4098511774bfa7ab1be (diff)
downloadminijail-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.mk65
-rw-r--r--gen.mk47
-rw-r--r--libminijail.c43
-rw-r--r--libminijail.h2
-rw-r--r--minijail0.c26
-rw-r--r--system.c35
-rw-r--r--system.h24
7 files changed, 167 insertions, 75 deletions
diff --git a/Android.mk b/Android.mk
index 25daa8e..c16770c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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.
diff --git a/gen.mk b/gen.mk
new file mode 100644
index 0000000..7368871
--- /dev/null
+++ b/gen.mk
@@ -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"
diff --git a/system.c b/system.c
index 05d0c47..49f8915 100644
--- a/system.c
+++ b/system.c
@@ -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";
diff --git a/system.h b/system.h
index 9ef2b29..6f1be49 100644
--- a/system.h
+++ b/system.h
@@ -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);