[lxc-devel] [PATCH 1/1] support shmmax/shmall KEY for lxc-execute

jian at linux.vnet.ibm.com jian at linux.vnet.ibm.com
Fri Jul 6 14:15:01 UTC 2012


From: Jian Xiao <jian at linux.vnet.ibm.com>

Signed-off-by: Jian Xiao <jian at linux.vnet.ibm.com>
---
 src/lxc/conf.c    |  123 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/conf.h    |    2 +
 src/lxc/confile.c |   32 ++++++++++++++
 3 files changed, 157 insertions(+), 0 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index e8088bb..d59731c 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1285,6 +1285,119 @@ static int setup_caps(struct lxc_list *caps)
 	return 0;
 }
 
+static int setup_shmmax(unsigned long shmmax)
+{
+	int rc, fd;
+	uid_t euid = geteuid();
+	char shmmax_str[64];
+
+	if (!shmmax)
+		return 0;
+
+	snprintf(shmmax_str, sizeof(shmmax_str), "%lu", shmmax);
+
+	/* Process has all the capabilities set, but cannot open shmmax
+	 * to write. Temporarily set euid to root to get around this.
+	 * This is only done for non-root uid.
+	 */
+	if (euid && seteuid(0)) {
+		SYSERROR("failed to change euid to 0\n");
+		return -1;
+	}
+
+	fd = open("/proc/sys/kernel/shmmax", O_WRONLY);
+	if (fd < 0) {
+		SYSERROR("fail to open /proc/sys/kernel/shmmax");
+		return -1;
+        }
+
+	rc = write(fd, shmmax_str, strlen(shmmax_str));
+        if (rc < 0) {
+		SYSERROR("fail to write /proc/sys/kernel/shmmax");
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+
+	/* set euid back */
+	if (euid) {
+		if (seteuid(euid)) {
+			ERROR("failed to change euid to '%d': %m", euid);
+			return -1;
+		}
+
+		/* seteuid() to non-zero clears effective capabilities
+		 * so we need to restore them
+		 */
+		if (lxc_caps_up()) {
+			ERROR("failed to restore capabilities: %m");
+			return -1;
+		}
+	}
+
+	DEBUG("shmmax has been setup to %lu\n", shmmax);
+
+	return 0;
+}
+
+static int setup_shmall(unsigned long shmall)
+{
+	int rc, fd;
+	uid_t euid = geteuid();
+	char shmall_str[64];
+
+	if (!shmall)
+		return 0;
+
+	snprintf(shmall_str, sizeof(shmall_str), "%lu", shmall);
+
+	/* Process has all the capabilities set, but cannot open shmall
+	 * to write. Temporarily set euid to root to get around this.
+	 * This is only done for non-root uid.
+	 */
+	if (euid && seteuid(0)) {
+		SYSERROR("failed to change euid to 0\n");
+		return -1;
+	}
+
+	fd = open("/proc/sys/kernel/shmall", O_WRONLY);
+	if (fd < 0) {
+		SYSERROR("fail to open /proc/sys/kernel/shmall");
+		return -1;
+        }
+
+	rc = write(fd, shmall_str, strlen(shmall_str));
+        if (rc < 0) {
+		SYSERROR("fail to write /proc/sys/kernel/shmall");
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+
+	/* set euid back */
+	if (euid) {
+		if (seteuid(euid)) {
+			ERROR("failed to change euid to '%d': %m", euid);
+			return -1;
+		}
+
+		/* seteuid() to non-zero clears effective capabilities
+		 * so we need to restore them
+		 */
+		if (lxc_caps_up()) {
+			ERROR("failed to restore capabilities: %m");
+			return -1;
+		}
+	}
+
+	DEBUG("shmall has been setup to %lu\n", shmall);
+
+	return 0;
+}
+
+
 static int setup_hw_addr(char *hwaddr, const char *ifname)
 {
 	struct sockaddr sockaddr;
@@ -2047,6 +2160,16 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
 		return -1;
 	}
 
+	if (setup_shmmax(lxc_conf->shmmax)) {
+		ERROR("failed to set shmmax");
+		return -1;
+	}
+
+	if (setup_shmall(lxc_conf->shmall)) {
+		ERROR("failed to set shmall");
+		return -1;
+	}
+
 	NOTICE("'%s' is setup.", name);
 
 	return 0;
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 09f55cb..347521e 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -216,6 +216,8 @@ struct lxc_conf {
 	struct lxc_rootfs rootfs;
 	char *ttydir;
 	int close_all_fds;
+	unsigned long shmmax;
+	unsigned long shmall;
 };
 
 /*
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index b305aef..f71f4c7 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -71,6 +71,8 @@ static int config_network_ipv6(const char *, char *, struct lxc_conf *);
 static int config_network_ipv6_gateway(const char *, char *, struct lxc_conf *);
 static int config_cap_drop(const char *, char *, struct lxc_conf *);
 static int config_console(const char *, char *, struct lxc_conf *);
+static int config_shmmax(const char *, char *, struct lxc_conf *);
+static int config_shmall(const char *, char *, struct lxc_conf *);
 
 typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
 
@@ -107,6 +109,8 @@ static struct config config[] = {
 	{ "lxc.network.ipv6",         config_network_ipv6         },
 	{ "lxc.cap.drop",             config_cap_drop             },
 	{ "lxc.console",              config_console              },
+	{ "lxc.shmmax",               config_shmmax               },
+	{ "lxc.shmall",               config_shmall               },
 };
 
 static const size_t config_size = sizeof(config)/sizeof(struct config);
@@ -876,6 +880,34 @@ static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_con
 	return 0;
 }
 
+static int config_shmmax(const char *key, char *value, struct lxc_conf *lxc_conf)
+{
+	if (!strlen(value))
+		return -1;
+
+	errno = 0;
+	lxc_conf->shmmax = strtoul(value, NULL, 0);
+	if (errno) {
+		SYSERROR("failed to strtoul '%s'", value);
+		return -1;
+	}
+	return 0;
+}
+
+static int config_shmall(const char *key, char *value, struct lxc_conf *lxc_conf)
+{
+	if (!strlen(value))
+		return -1;
+
+	errno = 0;
+	lxc_conf->shmall = strtoul(value, NULL, 0);
+	if (errno) {
+		SYSERROR("failed to strtoul '%s'", value);
+		return -1;
+	}
+	return 0;
+}
+
 static int parse_line(char *buffer, void *data)
 {
 	struct config *config;
-- 
1.7.1





More information about the lxc-devel mailing list