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:
parent
7395ab25d1
commit
ccdf81b558
@ -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>
|
||||
---
|
||||
|
@ -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>
|
||||
---
|
||||
|
@ -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?
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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`
|
||||
|
@ -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>
|
||||
---
|
||||
|
@ -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.
|
||||
|
513
debian/patches/0009-conf-implement-resource-limits.patch
vendored
Normal file
513
debian/patches/0009-conf-implement-resource-limits.patch
vendored
Normal 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
|
||||
|
58
debian/patches/0010-doc-add-lxc.limit-to-lxc.container.conf.patch
vendored
Normal file
58
debian/patches/0010-doc-add-lxc.limit-to-lxc.container.conf.patch
vendored
Normal 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
|
||||
|
88
debian/patches/0011-test-resource-limit-config-entries.patch
vendored
Normal file
88
debian/patches/0011-test-resource-limit-config-entries.patch
vendored
Normal 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
|
||||
|
29
debian/patches/0012-start-fix-error-handling-when-limits-fail-to-apply.patch
vendored
Normal file
29
debian/patches/0012-start-fix-error-handling-when-limits-fail-to-apply.patch
vendored
Normal 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
|
||||
|
70
debian/patches/0013-start-don-t-call-lxc_map_ids-without-id-map.patch
vendored
Normal file
70
debian/patches/0013-start-don-t-call-lxc_map_ids-without-id-map.patch
vendored
Normal 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
|
||||
|
29
debian/patches/0014-Fix-the-bug-of-ts-stdoutfd-did-not-fill-with-paramet.patch
vendored
Normal file
29
debian/patches/0014-Fix-the-bug-of-ts-stdoutfd-did-not-fill-with-paramet.patch
vendored
Normal 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user