aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2017-06-06 15:42:49 -0700
committerDylan Reid <dgreid@google.com>2017-06-29 12:46:46 -0700
commit0f72ef4240eede66e73f380d5fd7e1e9104de6ce (patch)
treecc351c6d924ed880274295055f49dd11995b34b0
parente61fd6681305084ac5bf97a8043882cd6d4370e2 (diff)
downloadminijail-0f72ef4240eede66e73f380d5fd7e1e9104de6ce.tar.gz
Add the ability to set rlimits on the jailed process
Currently Chrome OS relies on upstart to configure these limits but that isn't available when using libminijail from session manager. Add it so runtime limits can be configured for Android and other containers. BUG=none TEST=updated security_Minijail0 and manually check /proc/xxx/limits of jailed process. Change-Id: I62ed63c89c9c5196b7d9873520b396c9524e5855 Signed-off-by: Dylan Reid <dgreid@chromium.org>
-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;