diff options
author | Dylan Reid <dgreid@chromium.org> | 2017-06-29 22:57:05 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-06-29 22:57:05 +0000 |
commit | 04db2854a766df8273ca48e5d4f1763e634098f2 (patch) | |
tree | cc351c6d924ed880274295055f49dd11995b34b0 | |
parent | 262d381364c7b630ef7d979ae04653c3e688702d (diff) | |
parent | f0635d12ec1dd2caa17826601db57f28220ddbe7 (diff) | |
download | minijail-04db2854a766df8273ca48e5d4f1763e634098f2.tar.gz |
Add the ability to set rlimits on the jailed process am: 0f72ef4240 am: b27ba66cd5
am: f0635d12ec
Change-Id: I4daaf61ea5ea5615f69b88b113b1b32d5f9778c0
-rw-r--r-- | libminijail.c | 47 | ||||
-rw-r--r-- | libminijail.h | 3 | ||||
-rw-r--r-- | minijail0.1 | 3 | ||||
-rw-r--r-- | minijail0.c | 26 |
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; |