Commit 64f26a89 by Christian Brauner Committed by GitHub

Merge pull request #1276 from Blub/limits

Resource Limits
parents 359f86f9 a6390f01
...@@ -639,7 +639,7 @@ AC_CHECK_DECLS([PR_SET_NO_NEW_PRIVS], [], [], [#include <sys/prctl.h>]) ...@@ -639,7 +639,7 @@ AC_CHECK_DECLS([PR_SET_NO_NEW_PRIVS], [], [], [#include <sys/prctl.h>])
AC_CHECK_DECLS([PR_GET_NO_NEW_PRIVS], [], [], [#include <sys/prctl.h>]) AC_CHECK_DECLS([PR_GET_NO_NEW_PRIVS], [], [], [#include <sys/prctl.h>])
# Check for some headers # Check for some headers
AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/memfd.h sys/personality.h utmpx.h sys/timerfd.h]) AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/memfd.h sys/personality.h utmpx.h sys/timerfd.h sys/resource.h])
# lookup major()/minor()/makedev() # lookup major()/minor()/makedev()
AC_HEADER_MAJOR AC_HEADER_MAJOR
......
...@@ -1184,6 +1184,40 @@ proc proc proc nodev,noexec,nosuid 0 0 ...@@ -1184,6 +1184,40 @@ proc proc proc nodev,noexec,nosuid 0 0
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Resource limits</title>
<para>
The soft and hard resource limits for the container can be changed.
Unprivileged containers can only lower them. Resources which are not
explicitly specified will be inherited.
</para>
<variablelist>
<varlistentry>
<term>
<option>lxc.limit.[limit name]</option>
</term>
<listitem>
<para>
Specify the resource limit to be set. A limit is specified as two
colon separated values which are either numeric or the word
'unlimited'. A single value can be used as a shortcut to set both
soft and hard limit to the same value. The permitted names the
"RLIMIT_" resource names in lowercase without the "RLIMIT_"
prefix, eg. RLIMIT_NOFILE should be specified as "nofile". See
<citerefentry>
<refentrytitle><command>setrlimit</command></refentrytitle>
<manvolnum>2</manvolnum>
</citerefentry>.
If used with no value, lxc will clear the resource limit
specified up to this point. A resource with no explicitly
configured limitation will be inherited from the process starting
up the container.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect2>
<refsect2>
<title>Apparmor profile</title> <title>Apparmor profile</title>
<para> <para>
If lxc was compiled and installed with apparmor support, and the host If lxc was compiled and installed with apparmor support, and the host
......
...@@ -894,6 +894,11 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun ...@@ -894,6 +894,11 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
goto on_error; goto on_error;
} }
/* Setup resource limits */
if (!lxc_list_empty(&init_ctx->container->lxc_conf->limits) && setup_resource_limits(&init_ctx->container->lxc_conf->limits, pid)) {
goto on_error;
}
/* Open /proc before setns() to the containers namespace so we /* Open /proc before setns() to the containers namespace so we
* don't rely on any information from inside the container. * don't rely on any information from inside the container.
*/ */
......
...@@ -239,6 +239,11 @@ struct caps_opt { ...@@ -239,6 +239,11 @@ struct caps_opt {
int value; int value;
}; };
struct limit_opt {
char *name;
int value;
};
/* /*
* The lxc_conf of the container currently being worked on in an * The lxc_conf of the container currently being worked on in an
* API call * API call
...@@ -371,6 +376,57 @@ static struct caps_opt caps_opt[] = { ...@@ -371,6 +376,57 @@ static struct caps_opt caps_opt[] = {
static struct caps_opt caps_opt[] = {}; static struct caps_opt caps_opt[] = {};
#endif #endif
static struct limit_opt limit_opt[] = {
#ifdef RLIMIT_AS
{ "as", RLIMIT_AS },
#endif
#ifdef RLIMIT_CORE
{ "core", RLIMIT_CORE },
#endif
#ifdef RLIMIT_CPU
{ "cpu", RLIMIT_CPU },
#endif
#ifdef RLIMIT_DATA
{ "data", RLIMIT_DATA },
#endif
#ifdef RLIMIT_FSIZE
{ "fsize", RLIMIT_FSIZE },
#endif
#ifdef RLIMIT_LOCKS
{ "locks", RLIMIT_LOCKS },
#endif
#ifdef RLIMIT_MEMLOCK
{ "memlock", RLIMIT_MEMLOCK },
#endif
#ifdef RLIMIT_MSGQUEUE
{ "msgqueue", RLIMIT_MSGQUEUE },
#endif
#ifdef RLIMIT_NICE
{ "nice", RLIMIT_NICE },
#endif
#ifdef RLIMIT_NOFILE
{ "nofile", RLIMIT_NOFILE },
#endif
#ifdef RLIMIT_NPROC
{ "nproc", RLIMIT_NPROC },
#endif
#ifdef RLIMIT_RSS
{ "rss", RLIMIT_RSS },
#endif
#ifdef RLIMIT_RTPRIO
{ "rtprio", RLIMIT_RTPRIO },
#endif
#ifdef RLIMIT_RTTIME
{ "rttime", RLIMIT_RTTIME },
#endif
#ifdef RLIMIT_SIGPENDING
{ "sigpending", RLIMIT_SIGPENDING },
#endif
#ifdef RLIMIT_STACK
{ "stack", RLIMIT_STACK },
#endif
};
static int run_buffer(char *buffer) static int run_buffer(char *buffer)
{ {
struct lxc_popen_FILE *f; struct lxc_popen_FILE *f;
...@@ -2473,6 +2529,45 @@ static int setup_network(struct lxc_list *network) ...@@ -2473,6 +2529,45 @@ static int setup_network(struct lxc_list *network)
return 0; return 0;
} }
static int parse_resource(const char *res) {
size_t i;
int resid = -1;
for (i = 0; i < sizeof(limit_opt)/sizeof(limit_opt[0]); ++i) {
if (strcmp(res, limit_opt[i].name) == 0)
return limit_opt[i].value;
}
/* try to see if it's numeric, so the user may specify
* resources that the running kernel knows about but
* we don't */
if (lxc_safe_int(res, &resid) == 0)
return resid;
return -1;
}
int setup_resource_limits(struct lxc_list *limits, pid_t pid) {
struct lxc_list *it;
struct lxc_limit *lim;
int resid;
lxc_list_for_each(it, limits) {
lim = it->elem;
resid = parse_resource(lim->resource);
if (resid < 0) {
ERROR("unknown resource %s", lim->resource);
return -1;
}
if (prlimit(pid, resid, &lim->limit, NULL) != 0) {
ERROR("failed to set limit %s: %s", lim->resource, strerror(errno));
return -1;
}
}
return 0;
}
/* try to move physical nics to the init netns */ /* try to move physical nics to the init netns */
void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf) void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
{ {
...@@ -2559,6 +2654,7 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2559,6 +2654,7 @@ struct lxc_conf *lxc_conf_init(void)
lxc_list_init(&new->includes); lxc_list_init(&new->includes);
lxc_list_init(&new->aliens); lxc_list_init(&new->aliens);
lxc_list_init(&new->environment); lxc_list_init(&new->environment);
lxc_list_init(&new->limits);
for (i=0; i<NUM_LXC_HOOKS; i++) for (i=0; i<NUM_LXC_HOOKS; i++)
lxc_list_init(&new->hooks[i]); lxc_list_init(&new->hooks[i]);
lxc_list_init(&new->groups); lxc_list_init(&new->groups);
...@@ -4160,10 +4256,14 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key) ...@@ -4160,10 +4256,14 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
{ {
struct lxc_list *it,*next; struct lxc_list *it,*next;
bool all = false; bool all = false;
const char *k = key + 11; const char *k = NULL;
if (strcmp(key, "lxc.cgroup") == 0) if (strcmp(key, "lxc.cgroup") == 0)
all = true; all = true;
else if (strncmp(key, "lxc.cgroup.", sizeof("lxc.cgroup.")-1) == 0)
k = key + sizeof("lxc.cgroup.")-1;
else
return -1;
lxc_list_for_each_safe(it, &c->cgroup, next) { lxc_list_for_each_safe(it, &c->cgroup, next) {
struct lxc_cgroup *cg = it->elem; struct lxc_cgroup *cg = it->elem;
...@@ -4178,6 +4278,31 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key) ...@@ -4178,6 +4278,31 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
return 0; return 0;
} }
int lxc_clear_limits(struct lxc_conf *c, const char *key)
{
struct lxc_list *it, *next;
bool all = false;
const char *k = NULL;
if (strcmp(key, "lxc.limit") == 0)
all = true;
else if (strncmp(key, "lxc.limit.", sizeof("lxc.limit.")-1) == 0)
k = key + sizeof("lxc.limit.")-1;
else
return -1;
lxc_list_for_each_safe(it, &c->limits, next) {
struct lxc_limit *lim = it->elem;
if (!all && strcmp(lim->resource, k) != 0)
continue;
lxc_list_del(it);
free(lim->resource);
free(lim);
free(it);
}
return 0;
}
int lxc_clear_groups(struct lxc_conf *c) int lxc_clear_groups(struct lxc_conf *c)
{ {
struct lxc_list *it,*next; struct lxc_list *it,*next;
...@@ -4225,11 +4350,15 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key) ...@@ -4225,11 +4350,15 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key)
{ {
struct lxc_list *it,*next; struct lxc_list *it,*next;
bool all = false, done = false; bool all = false, done = false;
const char *k = key + 9; const char *k = NULL;
int i; int i;
if (strcmp(key, "lxc.hook") == 0) if (strcmp(key, "lxc.hook") == 0)
all = true; all = true;
else if (strncmp(key, "lxc.hook.", sizeof("lxc.hook.")-1) == 0)
k = key + sizeof("lxc.hook.")-1;
else
return -1;
for (i=0; i<NUM_LXC_HOOKS; i++) { for (i=0; i<NUM_LXC_HOOKS; i++) {
if (all || strcmp(k, lxchook_names[i]) == 0) { if (all || strcmp(k, lxchook_names[i]) == 0) {
...@@ -4320,6 +4449,7 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -4320,6 +4449,7 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_includes(conf); lxc_clear_includes(conf);
lxc_clear_aliens(conf); lxc_clear_aliens(conf);
lxc_clear_environment(conf); lxc_clear_environment(conf);
lxc_clear_limits(conf, "lxc.limit");
free(conf); free(conf);
} }
......
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
#include <net/if.h> #include <net/if.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <stdbool.h> #include <stdbool.h>
#include "list.h" #include "list.h"
...@@ -149,6 +152,23 @@ struct lxc_cgroup { ...@@ -149,6 +152,23 @@ struct lxc_cgroup {
char *value; char *value;
}; };
#if !HAVE_SYS_RESOURCE_H
# define RLIM_INFINITY ((unsigned long)-1)
struct rlimit {
unsigned long rlim_cur;
unsigned long rlim_max;
};
#endif
/*
* Defines a structure to configure resource limits to set via setrlimit().
* @resource : the resource name in lowercase without the RLIMIT_ prefix
* @limit : the limit to set
*/
struct lxc_limit {
char *resource;
struct rlimit limit;
};
enum idtype { enum idtype {
ID_TYPE_UID, ID_TYPE_UID,
ID_TYPE_GID ID_TYPE_GID
...@@ -385,6 +405,9 @@ struct lxc_conf { ...@@ -385,6 +405,9 @@ struct lxc_conf {
/* Whether PR_SET_NO_NEW_PRIVS will be set for the container. */ /* Whether PR_SET_NO_NEW_PRIVS will be set for the container. */
bool no_new_privs; bool no_new_privs;
/* RLIMIT_* limits */
struct lxc_list limits;
}; };
#ifdef HAVE_TLS #ifdef HAVE_TLS
...@@ -428,6 +451,7 @@ extern int lxc_clear_hooks(struct lxc_conf *c, const char *key); ...@@ -428,6 +451,7 @@ extern int lxc_clear_hooks(struct lxc_conf *c, const char *key);
extern int lxc_clear_idmaps(struct lxc_conf *c); extern int lxc_clear_idmaps(struct lxc_conf *c);
extern int lxc_clear_groups(struct lxc_conf *c); extern int lxc_clear_groups(struct lxc_conf *c);
extern int lxc_clear_environment(struct lxc_conf *c); extern int lxc_clear_environment(struct lxc_conf *c);
extern int lxc_clear_limits(struct lxc_conf *c, const char *key);
extern int lxc_delete_autodev(struct lxc_handler *handler); extern int lxc_delete_autodev(struct lxc_handler *handler);
extern int do_rootfs_setup(struct lxc_conf *conf, const char *name, extern int do_rootfs_setup(struct lxc_conf *conf, const char *name,
...@@ -440,6 +464,8 @@ extern int do_rootfs_setup(struct lxc_conf *conf, const char *name, ...@@ -440,6 +464,8 @@ extern int do_rootfs_setup(struct lxc_conf *conf, const char *name,
struct cgroup_process_info; struct cgroup_process_info;
extern int lxc_setup(struct lxc_handler *handler); extern int lxc_setup(struct lxc_handler *handler);
extern int setup_resource_limits(struct lxc_list *limits, pid_t pid);
extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf); extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf);
extern int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype); extern int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype);
......
...@@ -121,6 +121,7 @@ static int config_init_uid(const char *, const char *, struct lxc_conf *); ...@@ -121,6 +121,7 @@ static int config_init_uid(const char *, const char *, struct lxc_conf *);
static int config_init_gid(const char *, const char *, struct lxc_conf *); static int config_init_gid(const char *, const char *, struct lxc_conf *);
static int config_ephemeral(const char *, const char *, struct lxc_conf *); static int config_ephemeral(const char *, const char *, struct lxc_conf *);
static int config_no_new_privs(const char *, const char *, struct lxc_conf *); static int config_no_new_privs(const char *, const char *, struct lxc_conf *);
static int config_limit(const char *, const char *, struct lxc_conf *);
static struct lxc_config_t config[] = { static struct lxc_config_t config[] = {
...@@ -195,6 +196,7 @@ static struct lxc_config_t config[] = { ...@@ -195,6 +196,7 @@ static struct lxc_config_t config[] = {
{ "lxc.ephemeral", config_ephemeral }, { "lxc.ephemeral", config_ephemeral },
{ "lxc.syslog", config_syslog }, { "lxc.syslog", config_syslog },
{ "lxc.no_new_privs", config_no_new_privs }, { "lxc.no_new_privs", config_no_new_privs },
{ "lxc.limit", config_limit },
}; };
struct signame { struct signame {
...@@ -1580,6 +1582,110 @@ out: ...@@ -1580,6 +1582,110 @@ out:
return -1; return -1;
} }
static bool parse_limit_value(const char **value, unsigned long *res) {
char *endptr = NULL;
if (strncmp(*value, "unlimited", sizeof("unlimited")-1) == 0) {
*res = RLIM_INFINITY;
*value += sizeof("unlimited")-1;
return true;
}
errno = 0;
*res = strtoul(*value, &endptr, 10);
if (errno || !endptr)
return false;
*value = endptr;
return true;
}
static int config_limit(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
struct lxc_list *limlist = NULL;
struct lxc_limit *limelem = NULL;
struct lxc_list *iter;
struct rlimit limit;
unsigned long limit_value;
if (!value || strlen(value) == 0)
return lxc_clear_limits(lxc_conf, key);
if (strncmp(key, "lxc.limit.", sizeof("lxc.limit.")-1) != 0)
return -1;
key += sizeof("lxc.limit.")-1;
/* soft limit comes first in the value */
if (!parse_limit_value(&value, &limit_value))
return -1;
limit.rlim_cur = limit_value;
/* skip spaces and a colon */
while (isspace(*value))
++value;
if (*value == ':')
++value;
else if (*value) /* any other character is an error here */
return -1;
while (isspace(*value))
++value;
/* optional hard limit */
if (*value) {
if (!parse_limit_value(&value, &limit_value))
return -1;
limit.rlim_max = limit_value;
/* check for trailing garbage */
while (isspace(*value))
++value;
if (*value)
return -1;
} else {
/* a single value sets both hard and soft limit */
limit.rlim_max = limit.rlim_cur;
}
/* find existing list element */
lxc_list_for_each(iter, &lxc_conf->limits) {
limelem = iter->elem;
if (!strcmp(key, limelem->resource)) {
limelem->limit = limit;
return 0;
}
}
/* allocate list element */
limlist = malloc(sizeof(*limlist));
if (!limlist)
goto out;
limelem = malloc(sizeof(*limelem));
if (!limelem)
goto out;
memset(limelem, 0, sizeof(*limelem));
limelem->resource = strdup(key);
if (!limelem->resource)
goto out;
limelem->limit = limit;
limlist->elem = limelem;
lxc_list_add_tail(&lxc_conf->limits, limlist);
return 0;
out:
free(limlist);
if (limelem) {
free(limelem->resource);
free(limelem);
}
return -1;
}
static int config_idmap(const char *key, const char *value, struct lxc_conf *lxc_conf) static int config_idmap(const char *key, const char *value, struct lxc_conf *lxc_conf)
{ {
char *token = "lxc.id_map"; char *token = "lxc.id_map";
...@@ -2313,6 +2419,55 @@ static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen, ...@@ -2313,6 +2419,55 @@ static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
return fulllen; return fulllen;
} }
/*
* If you ask for a specific value, i.e. lxc.limit.nofile, then just the value
* will be printed. If you ask for 'lxc.limit', then all limit entries will be
* printed, in 'lxc.limit.resource = value' format.
*/
static int lxc_get_limit_entry(struct lxc_conf *c, char *retv, int inlen,
const char *key)
{
int fulllen = 0, len;
int all = 0;
struct lxc_list *it;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
if (strcmp(key, "all") == 0)
all = 1;
lxc_list_for_each(it, &c->limits) {
char buf[LXC_NUMSTRLEN64*2+2]; /* 2 colon separated 64 bit integers or the word 'unlimited' */
int partlen;
struct lxc_limit *lim = it->elem;
if (lim->limit.rlim_cur == RLIM_INFINITY) {
memcpy(buf, "unlimited", sizeof("unlimited"));
partlen = sizeof("unlimited")-1;
} else {
partlen = sprintf(buf, "%lu", lim->limit.rlim_cur);
}
if (lim->limit.rlim_cur != lim->limit.rlim_max) {
if (lim->limit.rlim_max == RLIM_INFINITY) {
memcpy(buf+partlen, ":unlimited", sizeof(":unlimited"));
} else {
sprintf(buf+partlen, ":%lu", lim->limit.rlim_max);
}
}
if (all) {
strprint(retv, inlen, "lxc.limit.%s = %s\n", lim->resource, buf);
} else if (strcmp(lim->resource, key) == 0) {
strprint(retv, inlen, "%s", buf);
}
}
return fulllen;
}
static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen, static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen,
const char *key) const char *key)
{ {
...@@ -2678,6 +2833,10 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv, ...@@ -2678,6 +2833,10 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
v = c->syslog; v = c->syslog;
else if (strcmp(key, "lxc.no_new_privs") == 0) else if (strcmp(key, "lxc.no_new_privs") == 0)
return lxc_get_conf_int(c, retv, inlen, c->no_new_privs); return lxc_get_conf_int(c, retv, inlen, c->no_new_privs);
else if (strcmp(key, "lxc.limit") == 0) // all limits
return lxc_get_limit_entry(c, retv, inlen, "all");
else if (strncmp(key, "lxc.limit.", 10) == 0) // specific limit
return lxc_get_limit_entry(c, retv, inlen, key + 10);
else return -1; else return -1;
if (!v) if (!v)
...@@ -2711,6 +2870,8 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key) ...@@ -2711,6 +2870,8 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key)
return lxc_clear_environment(c); return lxc_clear_environment(c);
else if (strncmp(key, "lxc.id_map", 10) == 0) else if (strncmp(key, "lxc.id_map", 10) == 0)
return lxc_clear_idmaps(c); return lxc_clear_idmaps(c);
else if (strncmp(key, "lxc.limit", 9) == 0)
return lxc_clear_limits(c, key);
return -1; return -1;
} }
......
...@@ -1261,6 +1261,11 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1261,6 +1261,11 @@ static int lxc_spawn(struct lxc_handler *handler)
if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE)) if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
goto out_delete_net; goto out_delete_net;
if (!lxc_list_empty(&handler->conf->limits) && setup_resource_limits(&handler->conf->limits, handler->pid)) {
ERROR("failed to setup resource limits for '%s'", name);
return -1;
}
if (!cgroup_setup_limits(handler, true)) { if (!cgroup_setup_limits(handler, true)) {
ERROR("Failed to setup the devices cgroup for container \"%s\".", name); ERROR("Failed to setup the devices cgroup for container \"%s\".", name);
goto out_delete_net; goto out_delete_net;
......
...@@ -174,6 +174,70 @@ int main(int argc, char *argv[]) ...@@ -174,6 +174,70 @@ int main(int argc, char *argv[])
} }
printf("lxc.mount.entry returned %d %s\n", ret, v2); printf("lxc.mount.entry returned %d %s\n", ret, v2);
ret = c->get_config_item(c, "lxc.limit", v3, 2047);
if (ret != 0) {
fprintf(stderr, "%d: get_config_item(limit) returned %d\n", __LINE__, ret);
goto out;
}
if (!c->set_config_item(c, "lxc.limit.nofile", "1234:unlimited")) {
fprintf(stderr, "%d: failed to set limit.nofile\n", __LINE__);
goto out;
}
ret = c->get_config_item(c, "lxc.limit.nofile", v2, 255);
if (ret < 0) {
fprintf(stderr, "%d: get_config_item(lxc.limit.nofile) returned %d\n", __LINE__, ret);
goto out;
}
if (strcmp(v2, "1234:unlimited")) {
fprintf(stderr, "%d: lxc.limit.nofile returned wrong value: %d %s not 14 1234:unlimited\n", __LINE__, ret, v2);
goto out;
}
printf("lxc.limit.nofile returned %d %s\n", ret, v2);
if (!c->set_config_item(c, "lxc.limit.stack", "unlimited")) {
fprintf(stderr, "%d: failed to set limit.stack\n", __LINE__);
goto out;
}
ret = c->get_config_item(c, "lxc.limit.stack", v2, 255);
if (ret < 0) {
fprintf(stderr, "%d: get_config_item(lxc.limit.stack) returned %d\n", __LINE__, ret);
goto out;
}
if (strcmp(v2, "unlimited")) {
fprintf(stderr, "%d: lxc.limit.stack returned wrong value: %d %s not 9 unlimited\n", __LINE__, ret, v2);
goto out;
}
printf("lxc.limit.stack returned %d %s\n", ret, v2);
#define LIMIT_STACK "lxc.limit.stack = unlimited\n"
#define ALL_LIMITS "lxc.limit.nofile = 1234:unlimited\n" LIMIT_STACK
ret = c->get_config_item(c, "lxc.limit", v3, 2047);
if (ret != sizeof(ALL_LIMITS)-1) {
fprintf(stderr, "%d: get_config_item(limit) returned %d\n", __LINE__, ret);
goto out;
}
if (strcmp(v3, ALL_LIMITS)) {
fprintf(stderr, "%d: lxc.limit returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(ALL_LIMITS)-1, ALL_LIMITS);
goto out;
}
printf("lxc.limit returned %d %s\n", ret, v3);
if (!c->clear_config_item(c, "lxc.limit.nofile")) {
fprintf(stderr, "%d: failed clearing limit.nofile\n", __LINE__);
goto out;
}
ret = c->get_config_item(c, "lxc.limit", v3, 2047);
if (ret != sizeof(LIMIT_STACK)-1) {
fprintf(stderr, "%d: get_config_item(limit) returned %d\n", __LINE__, ret);
goto out;
}
if (strcmp(v3, LIMIT_STACK)) {
fprintf(stderr, "%d: lxc.limit returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(LIMIT_STACK)-1, LIMIT_STACK);
goto out;
}
printf("lxc.limit returned %d %s\n", ret, v3);
if (!c->set_config_item(c, "lxc.aa_profile", "unconfined")) { if (!c->set_config_item(c, "lxc.aa_profile", "unconfined")) {
fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__); fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__);
goto out; goto out;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment