5
0
mirror of git://git.proxmox.com/git/lxc.git synced 2025-03-22 06:50:41 +03:00

merge resource limits and additional fixes

This commit is contained in:
Wolfgang Bumiller 2017-05-31 14:00:13 +02:00
parent 7395ab25d1
commit ccdf81b558
14 changed files with 796 additions and 8 deletions

View File

@ -1,7 +1,7 @@
From a070120ceba622b1834ad2693376256ba177f249 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 10 Feb 2017 09:13:40 +0100
Subject: [PATCH 1/8] lxc.service: start after a potential syslog.service
Subject: [PATCH 01/14] lxc.service: start after a potential syslog.service
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---

View File

@ -1,7 +1,8 @@
From de03e2bff16699c10f1c3a80e4c84a44c0a32bc0 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 10 Feb 2017 09:14:55 +0100
Subject: [PATCH 2/8] jessie/systemd: remove Delegate flag to silence warnings
Subject: [PATCH 02/14] jessie/systemd: remove Delegate flag to silence
warnings
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---

View File

@ -1,7 +1,7 @@
From 405bcb676e3eb07e2e2efab45b15cdc8b799b15c Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 10 Feb 2017 09:15:37 +0100
Subject: [PATCH 3/8] pve: run lxcnetaddbr when instantiating veths
Subject: [PATCH 03/14] pve: run lxcnetaddbr when instantiating veths
FIXME: Why aren't we using regular up-scripts?

View File

@ -1,7 +1,7 @@
From 05337fbce533630e978904db57601eedf498b776 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
Date: Wed, 9 Nov 2016 09:14:26 +0100
Subject: [PATCH 4/8] deny rw mounting of /sys and /proc
Subject: [PATCH 04/14] deny rw mounting of /sys and /proc
this would allow root in a privileged container to change
the permissions of /sys on the host, which could lock out

View File

@ -1,7 +1,7 @@
From 5ceb26ec765edb81aba25b9db4fc5ede0d7a0375 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Tue, 15 Nov 2016 09:20:24 +0100
Subject: [PATCH 5/8] separate the limiting from the namespaced cgroup root
Subject: [PATCH 05/14] separate the limiting from the namespaced cgroup root
When cgroup namespaces are enabled a privileged container
with mixed cgroups has full write access to its own root

View File

@ -1,7 +1,7 @@
From 2b4c8a851ae299a840af3e5e0cdf128ea205b5a4 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 16 Nov 2016 09:53:42 +0100
Subject: [PATCH 6/8] start/initutils: make cgroupns separation level
Subject: [PATCH 06/14] start/initutils: make cgroupns separation level
configurable
Adds a new global config variable `lxc.cgroup.separate`

View File

@ -1,7 +1,7 @@
From adf5f6720c85fe7059ff98942c136846b16880eb Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 23 Dec 2016 15:57:24 +0100
Subject: [PATCH 7/8] rename cgroup namespace directory to ns
Subject: [PATCH 07/14] rename cgroup namespace directory to ns
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---

View File

@ -1,7 +1,7 @@
From eea36cafdc53b5ed2200ea0910f4222bc4e7891f Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 10 Feb 2017 10:23:36 +0100
Subject: [PATCH 8/8] possibility to run lxc-monitord as a regular daemon
Subject: [PATCH 08/14] possibility to run lxc-monitord as a regular daemon
This includes an lxc-monitord.service, required by
lxc@.service which is now of Type=forking.

View File

@ -0,0 +1,513 @@
From 67a23f3f3fa65f1646ad20a8591b15895cada0a4 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 4 Nov 2016 10:19:07 +0100
Subject: [PATCH 09/14] conf: implement resource limits
This adds lxc.limit.<name> options consisting of one or two
colon separated numerical values (soft and optional hard
limit). If only one number is specified it'll be used for
both soft and hard limit. Additionally the word 'unlimited'
can be used instead of numbers.
Eg.
lxc.limit.nofile = 30000:32768
lxc.limit.stack = unlimited
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
configure.ac | 2 +-
src/lxc/attach.c | 5 ++
src/lxc/conf.c | 122 +++++++++++++++++++++++++++++++++++++++++
src/lxc/conf.h | 26 +++++++++
src/lxc/confile.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/lxc/start.c | 5 ++
6 files changed, 320 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index fa3926a9..2857d5ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -633,7 +633,7 @@ AM_CONDITIONAL([IS_BIONIC], [test "x$is_bionic" = "xyes"])
AC_CHECK_DECLS([PR_CAPBSET_DROP], [], [], [#include <sys/prctl.h>])
# 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()
AC_HEADER_MAJOR
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 119b9c14..6fdc6e8a 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -854,6 +854,11 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
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
* don't rely on any information from inside the container.
*/
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 3bedcf0f..d68ab2e2 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -243,6 +243,11 @@ struct caps_opt {
int value;
};
+struct limit_opt {
+ char *name;
+ int value;
+};
+
/*
* The lxc_conf of the container currently being worked on in an
* API call
@@ -376,6 +381,57 @@ static struct caps_opt caps_opt[] = {
static struct caps_opt caps_opt[] = {};
#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)
{
struct lxc_popen_FILE *f;
@@ -2534,6 +2590,45 @@ static int setup_network(struct lxc_list *network)
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 */
void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
{
@@ -2620,6 +2715,7 @@ struct lxc_conf *lxc_conf_init(void)
lxc_list_init(&new->includes);
lxc_list_init(&new->aliens);
lxc_list_init(&new->environment);
+ lxc_list_init(&new->limits);
for (i=0; i<NUM_LXC_HOOKS; i++)
lxc_list_init(&new->hooks[i]);
lxc_list_init(&new->groups);
@@ -4317,6 +4413,31 @@ int lxc_clear_cgroups(struct lxc_conf *c, const char *key)
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)
{
struct lxc_list *it,*next;
@@ -4462,6 +4583,7 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_includes(conf);
lxc_clear_aliens(conf);
lxc_clear_environment(conf);
+ lxc_clear_limits(conf, "lxc.limit");
free(conf);
}
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index c790bf7c..7dc05288 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -30,6 +30,9 @@
#include <net/if.h>
#include <sys/param.h>
#include <sys/types.h>
+#if HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
#include <stdbool.h>
#include "list.h"
@@ -149,6 +152,23 @@ struct lxc_cgroup {
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 {
ID_TYPE_UID,
ID_TYPE_GID
@@ -378,6 +398,9 @@ struct lxc_conf {
/* indicator if the container will be destroyed on shutdown */
unsigned int ephemeral;
+
+ /* RLIMIT_* limits */
+ struct lxc_list limits;
};
#ifdef HAVE_TLS
@@ -421,6 +444,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_groups(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 do_rootfs_setup(struct lxc_conf *conf, const char *name,
@@ -433,6 +457,8 @@ extern int do_rootfs_setup(struct lxc_conf *conf, const char *name,
struct cgroup_process_info;
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 int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype);
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 9b22c6d3..89f8c625 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -112,6 +112,7 @@ static int config_init_cmd(const char *, const char *, struct lxc_conf *);
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_ephemeral(const char *, const char *, struct lxc_conf *);
+static int config_limit(const char *, const char *, struct lxc_conf *);
static struct lxc_config_t config[] = {
@@ -184,6 +185,7 @@ static struct lxc_config_t config[] = {
{ "lxc.init_uid", config_init_uid },
{ "lxc.init_gid", config_init_gid },
{ "lxc.ephemeral", config_ephemeral },
+ { "lxc.limit", config_limit },
};
struct signame {
@@ -1500,6 +1502,110 @@ out:
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)
{
char *token = "lxc.id_map";
@@ -2233,6 +2339,55 @@ static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen,
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,
const char *key)
{
@@ -2594,6 +2749,10 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
return lxc_get_conf_int(c, retv, inlen, c->init_gid);
else if (strcmp(key, "lxc.ephemeral") == 0)
return lxc_get_conf_int(c, retv, inlen, c->ephemeral);
+ 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;
if (!v)
@@ -2627,6 +2786,8 @@ int lxc_clear_config_item(struct lxc_conf *c, const char *key)
return lxc_clear_environment(c);
else if (strncmp(key, "lxc.id_map", 10) == 0)
return lxc_clear_idmaps(c);
+ else if (strncmp(key, "lxc.limit", 9) == 0)
+ return lxc_clear_limits(c, key);
return -1;
}
diff --git a/src/lxc/start.c b/src/lxc/start.c
index a909c631..29edb8f7 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1244,6 +1244,11 @@ static int lxc_spawn(struct lxc_handler *handler)
if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
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)) {
ERROR("Failed to setup the devices cgroup for container \"%s\".", name);
goto out_delete_net;
--
2.11.0

View File

@ -0,0 +1,58 @@
From cd637b14e945486fb5be97b89102f679487584b5 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 4 Nov 2016 12:03:28 +0100
Subject: [PATCH 10/14] doc: add lxc.limit to lxc.container.conf
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
doc/lxc.container.conf.sgml.in | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in
index a4ef46d6..13e0d66c 100644
--- a/doc/lxc.container.conf.sgml.in
+++ b/doc/lxc.container.conf.sgml.in
@@ -1189,6 +1189,40 @@ proc proc proc nodev,noexec,nosuid 0 0
</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>
<para>
If lxc was compiled and installed with apparmor support, and the host
--
2.11.0

View File

@ -0,0 +1,88 @@
From fd224d9bff0b269ea1524cf7546314488014c018 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Fri, 4 Nov 2016 11:45:47 +0100
Subject: [PATCH 11/14] test: resource limit config entries
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
src/tests/get_item.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/src/tests/get_item.c b/src/tests/get_item.c
index 9750f312..93f2d965 100644
--- a/src/tests/get_item.c
+++ b/src/tests/get_item.c
@@ -149,6 +149,70 @@ int main(int argc, char *argv[])
}
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")) {
fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__);
goto out;
--
2.11.0

View File

@ -0,0 +1,29 @@
From 4b5238d5a7422f71abc4dbe8a7f01ab54dc9599b Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Tue, 11 Apr 2017 16:42:01 +0200
Subject: [PATCH 12/14] start: fix error handling when limits fail to apply
(The code was moved here from the child side of the startup
without adapting the error case.)
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
src/lxc/start.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 29edb8f7..8c2d2182 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1246,7 +1246,7 @@ static int lxc_spawn(struct lxc_handler *handler)
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;
+ goto out_delete_net;
}
if (!cgroup_setup_limits(handler, true)) {
--
2.11.0

View File

@ -0,0 +1,70 @@
From c1cf0e26f6dee988d73b4da760dc3f52f9c9a83b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner@ubuntu.com>
Date: Sat, 13 May 2017 17:16:25 +0200
Subject: [PATCH 13/14] start: don't call lxc_map_ids() without id map
So far, we somehow always called lxc_map_ids(), even when no id map was
configured. Let's not do this.
Closes #1555.
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Conflicts:
namespace spearation patches
Squashed:
0ee3505984e (start: pin rootfs when privileged)
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
src/lxc/start.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 8c2d2182..c8947f18 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1061,9 +1061,12 @@ static int lxc_spawn(struct lxc_handler *handler)
int saved_ns_fd[LXC_NS_MAX];
int preserve_mask = 0, i, flags;
int netpipepair[2], nveths;
- bool privileged = lxc_list_empty(&handler->conf->id_map);
+ bool wants_to_map_ids;
+ struct lxc_list *id_map;
netpipe = -1;
+ id_map = &handler->conf->id_map;
+ wants_to_map_ids = !lxc_list_empty(id_map);
for (i = 0; i < LXC_NS_MAX; i++)
if (handler->conf->inherit_ns_fd[i] != -1)
@@ -1125,7 +1128,7 @@ static int lxc_spawn(struct lxc_handler *handler)
* it readonly.
* If the container is unprivileged then skip rootfs pinning.
*/
- if (privileged) {
+ if (!wants_to_map_ids) {
handler->pinfd = pin_rootfs(handler->conf->rootfs.path);
if (handler->pinfd == -1)
INFO("Failed to pin the rootfs for container \"%s\".", handler->name);
@@ -1179,7 +1182,7 @@ static int lxc_spawn(struct lxc_handler *handler)
* mapped to something else on the host.) later to become a valid uid
* again.
*/
- if (lxc_map_ids(&handler->conf->id_map, handler->pid)) {
+ if (wants_to_map_ids && lxc_map_ids(id_map, handler->pid)) {
ERROR("Failed to set up id mapping.");
goto out_delete_net;
}
@@ -1256,7 +1259,7 @@ static int lxc_spawn(struct lxc_handler *handler)
if (cgns_supported()) {
const char *tmp = lxc_global_config_value("lxc.cgroup.protect_limits");
- if (!strcmp(tmp, "both") || !strcmp(tmp, privileged ? "privileged" : "unprivileged")) {
+ if (!strcmp(tmp, "both") || !strcmp(tmp, wants_to_map_ids ? "unprivileged" : "privileged")) {
if (!cgroup_create(handler, true)) {
ERROR("failed to create inner cgroup separation layer");
goto out_delete_net;
--
2.11.0

View File

@ -0,0 +1,29 @@
From c29c4928c88cf5bf88115b787f04cccc1664bfd1 Mon Sep 17 00:00:00 2001
From: Li Feng <lifeng68@huawei.com>
Date: Fri, 19 May 2017 22:40:07 +0800
Subject: [PATCH 14/14] Fix the bug of 'ts->stdoutfd' did not fill with
parameters 'stdoutfd'
Signed-off-by: Li Feng <lifeng68@huawei.com>
---
src/lxc/console.c | 1 +
1 file changed, 1 insertion(+)
mode change 100644 => 100755 src/lxc/console.c
diff --git a/src/lxc/console.c b/src/lxc/console.c
old mode 100644
new mode 100755
index 3baaed49..ad88a0ba
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -697,6 +697,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
ts->escape = escape;
ts->winch_proxy = c->name;
ts->winch_proxy_lxcpath = c->config_path;
+ ts->stdoutfd = stdoutfd;
lxc_console_winsz(stdinfd, masterfd);
lxc_cmd_console_winch(ts->winch_proxy, ts->winch_proxy_lxcpath);
--
2.11.0