aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2017-06-29 22:49:35 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-06-29 22:49:35 +0000
commitb27ba66cd5351077f0740635814f120d7f027545 (patch)
treecc351c6d924ed880274295055f49dd11995b34b0
parent2577ef10ccf6b9d6d804044e1591bae021c00ae7 (diff)
parent0f72ef4240eede66e73f380d5fd7e1e9104de6ce (diff)
downloadminijail-b27ba66cd5351077f0740635814f120d7f027545.tar.gz
Add the ability to set rlimits on the jailed process
am: 0f72ef4240 Change-Id: I95fa1ce3d78261ba2807823671df9e1a5ba5facd
-rw-r--r--libminijail.c47
-rw-r--r--libminijail.h3
-rw-r--r--minijail0.13
-rw-r--r--minijail0.c26
4 files changed, 76 insertions, 3 deletions
diff --git a/libminijail.c b/libminijail.c
index 81cea4b..b119542 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -25,6 +25,7 @@
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/prctl.h>
+#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/user.h>
@@ -74,9 +75,17 @@
#define MAX_CGROUPS 10 /* 10 different controllers supported by Linux. */
+#define MAX_RLIMITS 32 /* Currently there are 15 supported by Linux. */
+
/* Keyctl commands. */
#define KEYCTL_JOIN_SESSION_KEYRING 1
+struct minijail_rlimit {
+ int type;
+ uint32_t cur;
+ uint32_t max;
+};
+
struct mountpoint {
char *src;
char *dest;
@@ -155,6 +164,8 @@ struct minijail {
size_t tmpfs_size;
char *cgroups[MAX_CGROUPS];
size_t cgroup_count;
+ struct minijail_rlimit rlimits[MAX_RLIMITS];
+ size_t rlimit_count;
};
/*
@@ -639,6 +650,26 @@ int API minijail_add_to_cgroup(struct minijail *j, const char *path)
return 0;
}
+int API minijail_rlimit(struct minijail *j, int type, uint32_t cur,
+ uint32_t max)
+{
+ size_t i;
+
+ if (j->rlimit_count >= MAX_RLIMITS)
+ return -ENOMEM;
+ /* It's an error if the caller sets the same rlimit multiple times. */
+ for (i = 0; i < j->rlimit_count; i++) {
+ if (j->rlimits[i].type == type)
+ return -EEXIST;
+ }
+
+ j->rlimits[j->rlimit_count].type = type;
+ j->rlimits[j->rlimit_count].cur = cur;
+ j->rlimits[j->rlimit_count].max = max;
+ j->rlimit_count++;
+ return 0;
+}
+
int API minijail_forward_signals(struct minijail *j)
{
j->flags.forward_signals = 1;
@@ -1307,6 +1338,19 @@ static void add_to_cgroups_or_die(const struct minijail *j)
}
}
+static void set_rlimits_or_die(const struct minijail *j)
+{
+ size_t i;
+
+ for (i = 0; i < j->rlimit_count; ++i) {
+ struct rlimit limit;
+ limit.rlim_cur = j->rlimits[i].cur;
+ limit.rlim_max = j->rlimits[i].max;
+ if (prlimit(j->initpid, j->rlimits[i].type, &limit, NULL))
+ kill_child_and_die(j, "failed to set rlimit");
+ }
+}
+
static void write_ugid_maps_or_die(const struct minijail *j)
{
if (j->uidmap && write_proc_file(j->initpid, j->uidmap, "uid_map") != 0)
@@ -2118,6 +2162,9 @@ int minijail_run_internal(struct minijail *j, const char *filename,
if (j->flags.cgroups)
add_to_cgroups_or_die(j);
+ if (j->rlimit_count)
+ set_rlimits_or_die(j);
+
if (j->flags.userns)
write_ugid_maps_or_die(j);
diff --git a/libminijail.h b/libminijail.h
index 08fdf2b..bad8407 100644
--- a/libminijail.h
+++ b/libminijail.h
@@ -97,6 +97,9 @@ void minijail_inherit_usergroups(struct minijail *j);
*/
int minijail_use_alt_syscall(struct minijail *j, const char *table);
+/* Sets the given runtime limit. See getrlimit(2). */
+int minijail_rlimit(struct minijail *j, int type, uint32_t cur, uint32_t max);
+
/*
* Adds the jailed process to the cgroup given by |path|. |path| should be the
* full path to the cgroups "tasks" file.
diff --git a/minijail0.1 b/minijail0.1
index 27a1a2d..c817708 100644
--- a/minijail0.1
+++ b/minijail0.1
@@ -105,6 +105,9 @@ Remount /proc readonly. This implies \fB-v\fR. Remounting /proc readonly means
that even if the process has write access to a system config knob in /proc
(e.g., in /sys/kernel), it cannot change the value.
.TP
+\fB-R <rlim_type, rlim_cur, rlim_max>\fR
+Set an rlimit value, see \fBgetrlimit\fR(2) for allowed values.
+.TP
\fB-s\fR
Enable \fBseccomp\fR(2) in mode 1, which restricts the child process to a very
small set of system calls.
diff --git a/minijail0.c b/minijail0.c
index a714bfb..017c1bf 100644
--- a/minijail0.c
+++ b/minijail0.c
@@ -75,6 +75,22 @@ static void add_binding(struct minijail *j, char *arg)
}
}
+static void add_rlimit(struct minijail *j, char *arg)
+{
+ char *type = strtok(arg, ",");
+ char *cur = strtok(NULL, ",");
+ char *max = strtok(NULL, ",");
+ if (!type || !cur || !max) {
+ fprintf(stderr, "Bad rlimit '%s'.\n", arg);
+ exit(1);
+ }
+ if (minijail_rlimit(j, atoi(type), atoi(cur), atoi(max))) {
+ fprintf(stderr, "minijail_rlimit '%s,%s,%s' failed.\n",
+ type, cur, max);
+ exit(1);
+ }
+}
+
static void add_mount(struct minijail *j, char *arg)
{
char *src = strtok(arg, ",");
@@ -111,12 +127,12 @@ static void usage(const char *progn)
{
size_t i;
/* clang-format off */
- printf("Usage: %s [-GhHiIKlLnNprstUvyYz]\n"
+ printf("Usage: %s [-GhHiIKlLnNprRstUvyYz]\n"
" [-a <table>]\n"
" [-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[size]] [-T <type>] [-u <user>] [-V <file>]\n"
+ " [-R <type,cur,max>] [-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"
@@ -163,6 +179,7 @@ static void usage(const char *progn)
" -N: Enter a new cgroup namespace.\n"
" -p: Enter new pid namespace (implies -vr).\n"
" -r: Remount /proc read-only (implies -v).\n"
+ " -R: Set rlimits, can be specified multiple times.\n"
" -s: Use seccomp mode 1 (not the same as -S).\n"
" -S <file>: Set seccomp filter using <file>.\n"
" E.g., '-S /usr/share/filters/<prog>.$(uname -m)'.\n"
@@ -212,7 +229,7 @@ static int parse_args(struct minijail *j, int argc, char *argv[],
const char *filter_path;
const char *optstring =
- "+u:g:sS:c:C:P:b:V:f:m::M::k:a:e::T:vrGhHinNplLt::IUKwyYz";
+ "+u:g:sS:c:C:P:b:V:f:m::M::k:a:e::R:T:vrGhHinNplLt::IUKwyYz";
int longoption_index = 0;
/* clang-format off */
const struct option long_options[] = {
@@ -430,6 +447,9 @@ static int parse_args(struct minijail *j, int argc, char *argv[],
exit(1);
}
break;
+ case 'R':
+ add_rlimit(j, optarg);
+ break;
case 'T':
if (!strcmp(optarg, "static"))
*elftype = ELFSTATIC;