From: Filip Schauer <f.schauer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH lxc v4 05/15] lxc: conf: split `lxc.environment` into `runtime` and `hooks`
Date: Mon, 8 Sep 2025 17:02:08 +0200 [thread overview]
Message-ID: <20250908150224.155373-6-f.schauer@proxmox.com> (raw)
In-Reply-To: <20250908150224.155373-1-f.schauer@proxmox.com>
Introduce `lxc.environment.runtime` to set environment variables only
for the container init process and `lxc.environment.hooks` to set
environement variables only for hooks. Leave the original
`lxc.environment` unchanged. It still applies to everything.
This will be needed by containers created from OCI images with custom
environment variables that could interfere with hooks.
Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
Introduced in v4
...c.environment-into-runtime-and-hooks.patch | 324 ++++++++++++++++++
debian/patches/series | 1 +
2 files changed, 325 insertions(+)
create mode 100644 debian/patches/pve/0003-PVE-conf-split-lxc.environment-into-runtime-and-hooks.patch
diff --git a/debian/patches/pve/0003-PVE-conf-split-lxc.environment-into-runtime-and-hooks.patch b/debian/patches/pve/0003-PVE-conf-split-lxc.environment-into-runtime-and-hooks.patch
new file mode 100644
index 0000000..93e81f3
--- /dev/null
+++ b/debian/patches/pve/0003-PVE-conf-split-lxc.environment-into-runtime-and-hooks.patch
@@ -0,0 +1,324 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Filip Schauer <f.schauer@proxmox.com>
+Date: Mon, 8 Sep 2025 11:11:31 +0200
+Subject: [PATCH] PVE: conf: split `lxc.environment` into `runtime` and `hooks`
+
+Introduce `lxc.environment.runtime` to set environment variables only
+for the container init process and `lxc.environment.hooks` to set
+environement variables only for hooks. Leave the original
+`lxc.environment` unchanged. It still applies to everything.
+
+Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
+---
+ src/lxc/attach.c | 6 +++-
+ src/lxc/conf.c | 14 +++++----
+ src/lxc/conf.h | 15 +++++++---
+ src/lxc/confile.c | 72 +++++++++++++++++++++++++++++++++++++++++------
+ src/lxc/start.c | 12 ++++++--
+ 5 files changed, 98 insertions(+), 21 deletions(-)
+
+diff --git a/src/lxc/attach.c b/src/lxc/attach.c
+index 8f2f7a37c..f22f83f0d 100644
+--- a/src/lxc/attach.c
++++ b/src/lxc/attach.c
+@@ -879,7 +879,11 @@ static int lxc_attach_set_environment(struct attach_context *ctx,
+
+ /* Set container environment variables.*/
+ if (ctx->container->lxc_conf) {
+- ret = lxc_set_environment(ctx->container->lxc_conf);
++ ret = lxc_set_environment(&ctx->container->lxc_conf->environment);
++ if (ret < 0)
++ return -1;
++
++ ret = lxc_set_environment(&ctx->container->lxc_conf->environment_runtime);
+ if (ret < 0)
+ return -1;
+ }
+diff --git a/src/lxc/conf.c b/src/lxc/conf.c
+index 1899b2806..7533e2830 100644
+--- a/src/lxc/conf.c
++++ b/src/lxc/conf.c
+@@ -3209,6 +3209,8 @@ struct lxc_conf *lxc_conf_init(void)
+ new->root_nsuid_map = NULL;
+ new->root_nsgid_map = NULL;
+ INIT_LIST_HEAD(&new->environment);
++ INIT_LIST_HEAD(&new->environment_runtime);
++ INIT_LIST_HEAD(&new->environment_hooks);
+ INIT_LIST_HEAD(&new->limits);
+ INIT_LIST_HEAD(&new->sysctls);
+ INIT_LIST_HEAD(&new->procs);
+@@ -4239,18 +4241,18 @@ int lxc_clear_groups(struct lxc_conf *c)
+ return 0;
+ }
+
+-int lxc_clear_environment(struct lxc_conf *c)
++int lxc_clear_environment(struct list_head *environment)
+ {
+ struct environment_entry *env, *nenv;
+
+- list_for_each_entry_safe(env, nenv, &c->environment, head) {
++ list_for_each_entry_safe(env, nenv, environment, head) {
+ list_del(&env->head);
+ free(env->key);
+ free(env->val);
+ free(env);
+ }
+
+- INIT_LIST_HEAD(&c->environment);
++ INIT_LIST_HEAD(environment);
+ return 0;
+ }
+
+@@ -4359,7 +4361,7 @@ void lxc_conf_free(struct lxc_conf *conf)
+ lxc_clear_mount_entries(conf);
+ lxc_clear_idmaps(conf);
+ lxc_clear_groups(conf);
+- lxc_clear_environment(conf);
++ lxc_clear_environment(&conf->environment);
+ lxc_clear_limits(conf, "lxc.prlimit");
+ lxc_clear_sysctls(conf, "lxc.sysctl");
+ lxc_clear_procs(conf, "lxc.proc");
+@@ -5210,11 +5212,11 @@ void suggest_default_idmap(void)
+ ERROR("lxc.idmap = g 0 %u %u", gid, grange);
+ }
+
+-int lxc_set_environment(const struct lxc_conf *conf)
++int lxc_set_environment(const struct list_head *environment)
+ {
+ struct environment_entry *env;
+
+- list_for_each_entry(env, &conf->environment, head) {
++ list_for_each_entry(env, environment, head) {
+ int ret;
+
+ ret = setenv(env->key, env->val, 1);
+diff --git a/src/lxc/conf.h b/src/lxc/conf.h
+index 31cd39e3f..d16564f10 100644
+--- a/src/lxc/conf.h
++++ b/src/lxc/conf.h
+@@ -506,10 +506,17 @@ struct lxc_conf {
+ unsigned int monitor_unshare;
+ unsigned int monitor_signal_pdeath;
+
+- /* list of environment variables we'll add to the container when
+- * started */
++ /* list of environment variables to provide to both the container's init
++ * process and hooks */
+ struct list_head environment;
+
++ /* list of environment variables to provide to the container's init
++ * process */
++ struct list_head environment_runtime;
++
++ /* list of environment variables to provide to container hooks */
++ struct list_head environment_hooks;
++
+ /* text representation of the config file */
+ char *unexpanded_config;
+ size_t unexpanded_len;
+@@ -599,7 +606,7 @@ __hidden extern int lxc_clear_automounts(struct lxc_conf *c);
+ __hidden extern int lxc_clear_hooks(struct lxc_conf *c, const char *key);
+ __hidden extern int lxc_clear_idmaps(struct lxc_conf *c);
+ __hidden extern int lxc_clear_groups(struct lxc_conf *c);
+-__hidden extern int lxc_clear_environment(struct lxc_conf *c);
++__hidden extern int lxc_clear_environment(struct list_head *environment);
+ __hidden extern int lxc_clear_limits(struct lxc_conf *c, const char *key);
+ __hidden extern int lxc_delete_autodev(struct lxc_handler *handler);
+ __hidden extern int lxc_clear_autodev_tmpfs_size(struct lxc_conf *c);
+@@ -710,7 +717,7 @@ static inline int lxc_personality(personality_t persona)
+ return personality(persona);
+ }
+
+-__hidden extern int lxc_set_environment(const struct lxc_conf *conf);
++__hidden extern int lxc_set_environment(const struct list_head *environment);
+ __hidden extern int parse_cap(const char *cap_name, __u32 *cap);
+
+ #endif /* __LXC_CONF_H */
+diff --git a/src/lxc/confile.c b/src/lxc/confile.c
+index 5045741bb..875418792 100644
+--- a/src/lxc/confile.c
++++ b/src/lxc/confile.c
+@@ -80,6 +80,8 @@ lxc_config_define(console_rotate);
+ lxc_config_define(console_size);
+ lxc_config_define(unsupported_key);
+ lxc_config_define(environment);
++lxc_config_define(environment_runtime);
++lxc_config_define(environment_hooks);
+ lxc_config_define(ephemeral);
+ lxc_config_define(execute_cmd);
+ lxc_config_define(group);
+@@ -211,6 +213,8 @@ static struct lxc_config_t config_jump_table[] = {
+ { "lxc.console.rotate", true, set_config_console_rotate, get_config_console_rotate, clr_config_console_rotate, },
+ { "lxc.console.size", true, set_config_console_size, get_config_console_size, clr_config_console_size, },
+ { "lxc.sched.core", true, set_config_sched_core, get_config_sched_core, clr_config_sched_core, },
++ { "lxc.environment.runtime", true, set_config_environment_runtime, get_config_environment_runtime, clr_config_environment_runtime },
++ { "lxc.environment.hooks", true, set_config_environment_hooks, get_config_environment_hooks, clr_config_environment_hooks },
+ { "lxc.environment", true, set_config_environment, get_config_environment, clr_config_environment, },
+ { "lxc.ephemeral", true, set_config_ephemeral, get_config_ephemeral, clr_config_ephemeral, },
+ { "lxc.execute.cmd", true, set_config_execute_cmd, get_config_execute_cmd, clr_config_execute_cmd, },
+@@ -1574,15 +1578,15 @@ static int set_config_group(const char *key, const char *value,
+ return 0;
+ }
+
+-static int set_config_environment(const char *key, const char *value,
+- struct lxc_conf *lxc_conf, void *data)
++static int set_config_environment_impl(const char *value,
++ struct list_head *environment)
+ {
+ __do_free char *dup = NULL, *val = NULL;
+ __do_free struct environment_entry *new_env = NULL;
+ char *env_val;
+
+ if (lxc_config_value_empty(value))
+- return lxc_clear_environment(lxc_conf);
++ return lxc_clear_environment(environment);
+
+ new_env = zalloc(sizeof(struct environment_entry));
+ if (!new_env)
+@@ -1609,12 +1613,30 @@ static int set_config_environment(const char *key, const char *value,
+ new_env->key = move_ptr(dup);
+ new_env->val = move_ptr(val);
+
+- list_add_tail(&new_env->head, &lxc_conf->environment);
++ list_add_tail(&new_env->head, environment);
+ move_ptr(new_env);
+
+ return 0;
+ }
+
++static int set_config_environment(const char *key, const char *value,
++ struct lxc_conf *lxc_conf, void *data)
++{
++ return set_config_environment_impl(value, &lxc_conf->environment);
++}
++
++static int set_config_environment_runtime(const char *key, const char* value,
++ struct lxc_conf *lxc_conf, void *data)
++{
++ return set_config_environment_impl(value, &lxc_conf->environment_runtime);
++}
++
++static int set_config_environment_hooks(const char *key, const char* value,
++ struct lxc_conf *lxc_conf, void *data)
++{
++ return set_config_environment_impl(value, &lxc_conf->environment_hooks);
++}
++
+ static int set_config_tty_max(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+ {
+@@ -4473,8 +4495,8 @@ static int get_config_group(const char *key, char *retv, int inlen,
+ return fulllen;
+ }
+
+-static int get_config_environment(const char *key, char *retv, int inlen,
+- struct lxc_conf *c, void *data)
++static int get_config_environment_impl(char *retv, int inlen,
++ struct list_head *environment)
+ {
+ int len, fulllen = 0;
+ struct environment_entry *env;
+@@ -4484,13 +4506,32 @@ static int get_config_environment(const char *key, char *retv, int inlen,
+ else
+ memset(retv, 0, inlen);
+
+- list_for_each_entry(env, &c->environment, head) {
++ list_for_each_entry(env, environment, head) {
+ strprint(retv, inlen, "%s=%s\n", env->key, env->val);
+ }
+
+ return fulllen;
+ }
+
++static int get_config_environment(const char *key, char *retv, int inlen,
++ struct lxc_conf *c, void *data)
++{
++ return get_config_environment_impl(retv, inlen, &c->environment);
++}
++
++static int get_config_environment_runtime(const char *key, char *retv,
++ int inlen, struct lxc_conf *c,
++ void *data)
++{
++ return get_config_environment_impl(retv, inlen, &c->environment_runtime);
++}
++
++static int get_config_environment_hooks(const char *key, char *retv, int inlen,
++ struct lxc_conf *c, void *data)
++{
++ return get_config_environment_impl(retv, inlen, &c->environment_hooks);
++}
++
+ static int get_config_execute_cmd(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+ {
+@@ -5211,7 +5252,19 @@ static inline int clr_config_group(const char *key, struct lxc_conf *c,
+ static inline int clr_config_environment(const char *key, struct lxc_conf *c,
+ void *data)
+ {
+- return lxc_clear_environment(c);
++ return lxc_clear_environment(&c->environment);
++}
++
++static inline int clr_config_environment_runtime(const char *key,
++ struct lxc_conf *c, void *data)
++{
++ return lxc_clear_environment(&c->environment_runtime);
++}
++
++static inline int clr_config_environment_hooks(const char *key,
++ struct lxc_conf *c, void *data)
++{
++ return lxc_clear_environment(&c->environment_hooks);
+ }
+
+ static inline int clr_config_execute_cmd(const char *key, struct lxc_conf *c,
+@@ -6607,6 +6660,9 @@ int lxc_list_subkeys(struct lxc_conf *conf, const char *key, char *retv,
+ } else if (strequal(key, "lxc.console")) {
+ strprint(retv, inlen, "logfile\n");
+ strprint(retv, inlen, "path\n");
++ } else if (strequal(key, "lxc.environment")) {
++ strprint(retv, inlen, "runtime\n");
++ strprint(retv, inlen, "hooks\n");
+ } else if (strequal(key, "lxc.seccomp")) {
+ strprint(retv, inlen, "profile\n");
+ } else if (strequal(key, "lxc.signal")) {
+diff --git a/src/lxc/start.c b/src/lxc/start.c
+index 3160459b4..fc6ca147a 100644
+--- a/src/lxc/start.c
++++ b/src/lxc/start.c
+@@ -1260,10 +1260,14 @@ static int do_start(void *data)
+ * to allow them to be used by the various hooks, such as the start
+ * hook below.
+ */
+- ret = lxc_set_environment(handler->conf);
++ ret = lxc_set_environment(&handler->conf->environment);
+ if (ret < 0)
+ goto out_warn_father;
+
++ ret = lxc_set_environment(&handler->conf->environment_hooks);
++ if (ret < 0)
++ goto out_warn_father;
++
+ if (!lxc_sync_wait_parent(handler, START_SYNC_POST_CONFIGURE))
+ goto out_warn_father;
+
+@@ -1361,10 +1365,14 @@ static int do_start(void *data)
+ if (ret < 0)
+ SYSERROR("Failed to clear environment.");
+
+- ret = lxc_set_environment(handler->conf);
++ ret = lxc_set_environment(&handler->conf->environment);
+ if (ret < 0)
+ goto out_warn_father;
+
++ ret = lxc_set_environment(&handler->conf->environment_runtime);
++ if (ret < 0)
++ goto out_warn_father;
++
+ ret = putenv("container=lxc");
+ if (ret < 0) {
+ SYSERROR("Failed to set environment variable: container=lxc");
+--
+2.47.2
+
diff --git a/debian/patches/series b/debian/patches/series
index 5f3f0b6..b1353eb 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,4 @@ apparmor/0001-apparmor-allow-lxc-start-to-create-user-namespaces.patch
apparmor/0002-apparmor-use-abi-directive-in-apparmor-profiles.patch
pve/0001-PVE-Config-deny-rw-mounting-of-sys-and-proc.patch
pve/0002-PVE-Config-attach-always-use-getent.patch
+pve/0003-PVE-conf-split-lxc.environment-into-runtime-and-hooks.patch
--
2.47.2
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-09-08 15:05 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-08 15:02 [pve-devel] [PATCH container/docs/lxc/manager/proxmox{, -perl-rs}/storage v4 00/15] support OCI images as container templates Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH proxmox v4 01/15] io: introduce RangeReader for bounded reads Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH proxmox v4 02/15] add proxmox-oci crate Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH proxmox v4 03/15] proxmox-oci: add tests for whiteout handling Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH proxmox-perl-rs v4 04/15] add Perl mapping for OCI container image parser/extractor Filip Schauer
2025-09-08 15:02 ` Filip Schauer [this message]
2025-09-08 15:02 ` [pve-devel] [PATCH container v4 06/15] config: add `lxc.environment.runtime`/`hooks` Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH container v4 07/15] add support for OCI images as container templates Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH container v4 08/15] config: add entrypoint parameter Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH container v4 09/15] configure static IP in LXC config for custom entrypoint Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH container v4 10/15] setup: debian: create /etc/network path if missing Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH container v4 11/15] setup: recursively mkdir /etc/systemd/{network, system-preset} Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH container v4 12/15] implement host-managed DHCP for containers with `ipmanagehost` Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH storage v4 13/15] allow .tar container templates Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH manager v4 14/15] ui: storage upload: accept *.tar files as vztmpl Filip Schauer
2025-09-08 15:02 ` [pve-devel] [PATCH docs v4 15/15] ct: add OCI image docs Filip Schauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250908150224.155373-6-f.schauer@proxmox.com \
--to=f.schauer@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox