Skip to content

Commit

Permalink
cli: make --limit also use a key=value syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Snaipe committed Oct 17, 2020
1 parent 5dac5a3 commit 3e5cddc
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 383 deletions.
132 changes: 51 additions & 81 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "kvlist.h"
#include "util.h"
#include "path.h"
#include "util.h"

enum {
OPTION_VERSION = 128,
Expand All @@ -35,25 +36,7 @@ enum {
OPTION_GROUPS,
OPTION_WORKDIR,
OPTION_ARCH,
OPTION_LIMIT_AS,
_OPTION_LIMIT_START = OPTION_LIMIT_AS,
OPTION_LIMIT_CORE,
OPTION_LIMIT_CPU,
OPTION_LIMIT_DATA,
OPTION_LIMIT_FSIZE,
OPTION_LIMIT_LOCKS,
OPTION_LIMIT_MEMLOCK,
OPTION_LIMIT_MSGQUEUE,
OPTION_LIMIT_NICE,
OPTION_LIMIT_NOFILE,
OPTION_LIMIT_NPROC,
OPTION_LIMIT_RSS,
OPTION_LIMIT_RTPRIO,
OPTION_LIMIT_RTTIME,
OPTION_LIMIT_SIGPENDING,
OPTION_LIMIT_STACK,
_OPTION_LIMIT_END = OPTION_LIMIT_STACK,
OPTION_LIMIT_NO_COPY,
OPTION_LIMIT,
OPTION_SHARE,
OPTION_ARGV0,
OPTION_HOSTNAME,
Expand All @@ -73,6 +56,7 @@ enum {
OPTION_NO_LOOPBACK_SETUP,
OPTION_NO_INIT,
OPTION_NO_ENV,
OPTION_NO_COPY_HARD_LIMITS,
};

static void process_nslist_entry(const char **out, const char *share, const char *path, int multiple)
Expand Down Expand Up @@ -165,42 +149,58 @@ static void process_persist(const char **out, const char *optarg)
}
}

static void handle_limit_arg(int option_num, struct entry_settings *opts, char *arg)
static void handle_limit_arg(struct entry_settings *opts, char *optarg)
{
struct opt {
int option_num;
int resource;
char const *name;
};
static const struct opt option_map[] = {
{ OPTION_LIMIT_AS, BST_RLIMIT_AS, "as" },
{ OPTION_LIMIT_CORE, BST_RLIMIT_CORE, "core" },
{ OPTION_LIMIT_CPU, BST_RLIMIT_CPU, "cpu" },
{ OPTION_LIMIT_DATA, BST_RLIMIT_DATA, "data" },
{ OPTION_LIMIT_FSIZE, BST_RLIMIT_FSIZE, "fsize" },
{ OPTION_LIMIT_LOCKS, BST_RLIMIT_LOCKS, "locks" },
{ OPTION_LIMIT_MEMLOCK, BST_RLIMIT_MEMLOCK, "memlock" },
{ OPTION_LIMIT_MSGQUEUE, BST_RLIMIT_MSGQUEUE, "msgqueue" },
{ OPTION_LIMIT_NICE, BST_RLIMIT_NICE, "nice" },
{ OPTION_LIMIT_NOFILE, BST_RLIMIT_NOFILE, "nofile" },
{ OPTION_LIMIT_NPROC, BST_RLIMIT_NPROC, "nproc" },
{ OPTION_LIMIT_RSS, BST_RLIMIT_RSS, "rss" },
{ OPTION_LIMIT_RTPRIO, BST_RLIMIT_RTPRIO, "rtprio" },
{ OPTION_LIMIT_RTTIME, BST_RLIMIT_RTTIME, "rttime" },
{ OPTION_LIMIT_SIGPENDING, BST_RLIMIT_SIGPENDING, "sigpending" },
{ OPTION_LIMIT_STACK, BST_RLIMIT_STACK, "stack" },
{ BST_RLIMIT_AS, "as" },
{ BST_RLIMIT_CORE, "core" },
{ BST_RLIMIT_CPU, "cpu" },
{ BST_RLIMIT_DATA, "data" },
{ BST_RLIMIT_FSIZE, "fsize" },
{ BST_RLIMIT_LOCKS, "locks" },
{ BST_RLIMIT_MEMLOCK, "memlock" },
{ BST_RLIMIT_MSGQUEUE, "msgqueue" },
{ BST_RLIMIT_NICE, "nice" },
{ BST_RLIMIT_NOFILE, "nofile" },
{ BST_RLIMIT_NPROC, "nproc" },
{ BST_RLIMIT_RSS, "rss" },
{ BST_RLIMIT_RTPRIO, "rtprio" },
{ BST_RLIMIT_RTTIME, "rttime" },
{ BST_RLIMIT_SIGPENDING, "sigpending" },
{ BST_RLIMIT_STACK, "stack" },
};

assert(option_num >= _OPTION_LIMIT_START && option_num <= _OPTION_LIMIT_END);
char *name = strtok(optarg, "=");
char *arg = strtok(NULL, "");

size_t index = (size_t)(option_num - _OPTION_LIMIT_START);
assert(index < sizeof (option_map) / sizeof (*option_map));
if (arg == NULL) {
err(2, "--limit takes an argument in the form resource=value");
}

struct opt const * opt_ent = option_map + index;
assert(opt_ent->option_num == option_num);
const struct opt *opt_ent = NULL;
for (const struct opt *opt = option_map; opt < option_map + lengthof(option_map); ++opt) {
if (strcmp(opt->name, name) == 0) {
opt_ent = opt;
}
}

if (opt_ent == NULL) {
fprintf(stderr, "--limit: `%s` is not a valid resource name.\n", name);
fprintf(stderr, "valid resources are: ");

for (const struct opt *opt = option_map; opt < option_map + lengthof(option_map); ++opt) {
fprintf(stderr, "%s%s", opt == option_map ? "" : ", ", opt->name);
}
fprintf(stderr, ".\n");
exit(2);
}

if (parse_rlimit(opt_ent->resource, &opts->limits[opt_ent->resource].rlim, arg)) {
err(1, "error in --limit-%s value", opt_ent->name);
err(1, "error in --limit %s value", opt_ent->name);
}
opts->limits[opt_ent->resource].present = true;
}
Expand Down Expand Up @@ -243,22 +243,7 @@ int main(int argc, char *argv[], char *envp[])
{ "gid", required_argument, NULL, OPTION_GID },
{ "groups", required_argument, NULL, OPTION_GROUPS },
{ "arch", required_argument, NULL, OPTION_ARCH },
{ "limit-as", required_argument, NULL, OPTION_LIMIT_AS },
{ "limit-core", required_argument, NULL, OPTION_LIMIT_CORE },
{ "limit-cpu", required_argument, NULL, OPTION_LIMIT_CPU },
{ "limit-data", required_argument, NULL, OPTION_LIMIT_DATA },
{ "limit-fsize", required_argument, NULL, OPTION_LIMIT_FSIZE },
{ "limit-locks", required_argument, NULL, OPTION_LIMIT_LOCKS },
{ "limit-memlock", required_argument, NULL, OPTION_LIMIT_MEMLOCK },
{ "limit-msgqueue", required_argument, NULL, OPTION_LIMIT_MSGQUEUE },
{ "limit-nice", required_argument, NULL, OPTION_LIMIT_NICE },
{ "limit-nofile", required_argument, NULL, OPTION_LIMIT_NOFILE },
{ "limit-nproc", required_argument, NULL, OPTION_LIMIT_NPROC },
{ "limit-rss", required_argument, NULL, OPTION_LIMIT_RSS },
{ "limit-rtprio", required_argument, NULL, OPTION_LIMIT_RTPRIO },
{ "limit-rttime", required_argument, NULL, OPTION_LIMIT_RTTIME },
{ "limit-sigpending", required_argument, NULL, OPTION_LIMIT_SIGPENDING},
{ "limit-stack", required_argument, NULL, OPTION_LIMIT_STACK },
{ "limit", required_argument, NULL, OPTION_LIMIT },
{ "share", required_argument, NULL, OPTION_SHARE },
{ "argv0", required_argument, NULL, OPTION_ARGV0 },
{ "hostname", required_argument, NULL, OPTION_HOSTNAME },
Expand All @@ -274,7 +259,7 @@ int main(int argc, char *argv[], char *envp[])
{ "nic", required_argument, NULL, OPTION_NIC },

/* Opt-out feature flags */
{ "no-copy-hard-limits", no_argument, NULL, OPTION_LIMIT_NO_COPY },
{ "no-copy-hard-limits", no_argument, NULL, OPTION_NO_COPY_HARD_LIMITS },
{ "no-fake-devtmpfs", no_argument, NULL, OPTION_NO_FAKE_DEVTMPFS },
{ "no-derandomize", no_argument, NULL, OPTION_NO_DERANDOMIZE },
{ "no-proc-remount", no_argument, NULL, OPTION_NO_PROC_REMOUNT },
Expand Down Expand Up @@ -370,27 +355,8 @@ int main(int argc, char *argv[], char *envp[])
opts.arch = optarg;
break;

case OPTION_LIMIT_AS:
case OPTION_LIMIT_CORE:
case OPTION_LIMIT_CPU:
case OPTION_LIMIT_DATA:
case OPTION_LIMIT_FSIZE:
case OPTION_LIMIT_LOCKS:
case OPTION_LIMIT_MEMLOCK:
case OPTION_LIMIT_MSGQUEUE:
case OPTION_LIMIT_NICE:
case OPTION_LIMIT_NOFILE:
case OPTION_LIMIT_NPROC:
case OPTION_LIMIT_RSS:
case OPTION_LIMIT_RTPRIO:
case OPTION_LIMIT_RTTIME:
case OPTION_LIMIT_SIGPENDING:
case OPTION_LIMIT_STACK:
handle_limit_arg(c, &opts, optarg);
break;

case OPTION_LIMIT_NO_COPY:
opts.no_copy_hard_limits = 1;
case OPTION_LIMIT:
handle_limit_arg(&opts, optarg);
break;

case OPTION_SHARE:
Expand Down Expand Up @@ -543,6 +509,10 @@ int main(int argc, char *argv[], char *envp[])
opts.no_proc_remount = 1;
break;

case OPTION_NO_COPY_HARD_LIMITS:
opts.no_copy_hard_limits = 1;
break;

case OPTION_INIT:
opts.init = optarg;
break;
Expand Down
75 changes: 31 additions & 44 deletions man/bst.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -205,44 +205,31 @@ _VAR=value_ before the executable to run.
Supported interface types and valid options are described in more detail
in the *NETWORKING* section.

|[ --limit-as <arg>
:< size of virtual memory
|[ --limit-core <arg>
:< maximum size of core files created
|[ --limit-cpu <arg>
:< maximum amount of CPU time in seconds
|[ --limit-data <arg>
:< maximum size of a process's data segment
|[ --limit-fsize <arg>
:< maximum size of files written by the shell and its children
|[ --limit-locks <arg>
:< maximum number of file locks
|[ --limit-memlock <arg>
:< maximum size a process may lock into memory
|[ --limit-msgqueue <arg>
:< maximum number of bytes in POSIX message queues
|[ --limit-nice <arg>
:< maximum scheduling priority (`nice')
|[ --limit-nofile <arg>
:< maximum number of open file descriptors
|[ --limit-nproc <arg>
:< maximum number of user processes
|[ --limit-rss <arg>
:< maximum resident set size
|[ --limit-rtprio <arg>
:< maximum real-time scheduling priority
|[ --limit-rttime <arg>
:< limit (in microseconds) of real-time-scheduled CPU time before making a blocking system call
|[ --limit-sigpending <arg>
:< maximum number of pending signals
|[ --limit-stack <arg>
:< maximum stack size

The *--limit-<limit>* options set the specified hard and soft
resource limits based on <arg>.

Format of <arg>:
- Single numerical value: set both hard and soft limits to <arg>.
\--limit <resource>=<value>++
\--limit <resource>=[hard]:[soft]
Set the specified hard and soft resource limits of the specified resource
based on *<value>*.

Accepted values for *<resource>* are:
- *as*: size of virtual memory
- *core*: maximum size of core files created
- *cpu*: maximum amount of CPU time in seconds
- *data*: maximum size of a process's data segment
- *fsize*: maximum size of files written by the shell and its children
- *locks*: maximum number of file locks
- *memlock*: maximum size a process may lock into memory
- *msgqueue*: maximum number of bytes in POSIX message queues
- *nice*: maximum scheduling priority (`nice')
- *nofile*: maximum number of open file descriptors
- *nproc*: maximum number of user processes
- *rss*: maximum resident set size
- *rtprio*: maximum real-time scheduling priority
- *rttime*: limit (in microseconds) of real-time-scheduled CPU time before making a blocking system call
- *sigpending*: maximum number of pending signals
- *stack*: maximum stack size

Format of *<value>*:
- Single numerical value: set both hard and soft limits to <value>.
- Colon-separated hard:soft values.

When either limit is not provided (empty string), use the
Expand All @@ -251,13 +238,13 @@ _VAR=value_ before the executable to run.
soft resource limit to the current hard limit value.

Examples:++
\--limit-nproc 100 hard=100, soft=100++
\--limit-nproc 200:100 hard=200, soft=100++
\--limit-nproc :100 hard=(unchanged), soft=100++
\--limit-nproc 100: hard=100, soft=(unchanged)++
\--limit-nproc : hard=(unchanged), soft=(hard limit)
\--limit nproc=100 hard=100, soft=100++
\--limit nproc=200:100 hard=200, soft=100++
\--limit nproc=:100 hard=(unchanged), soft=100++
\--limit nproc=100: hard=100, soft=(unchanged)++
\--limit nproc=: hard=(unchanged), soft=(hard limit)

If a value is not provided using a --limit-<limit> option for a given resource,
If a value is not provided using a --limit option for a given resource,
the hard limit will be used as the soft limit, unless *--no-copy-hard-limits* has
been provided.

Expand Down
Loading

0 comments on commit 3e5cddc

Please sign in to comment.