diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index a2d3a7267..9ba08981f 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -10,6 +10,7 @@ All notable changes to the project are documented in this file. - Upgrade Buildroot to 2025.02.4 (LTS) - Upgrade Linux kernel to 6.12.34 (LTS) - Upgrade curiOS built-in containers to v25.06.0 +- Add support for setting mode of a container content mount, issue #1070 - Add Wi-Fi client support and add support for some USB-Wi-Fi cards - New slogan: Infix OS — Immutable.Friendly.Secure diff --git a/src/confd/src/infix-containers.c b/src/confd/src/infix-containers.c index 29285b13e..22736992f 100644 --- a/src/confd/src/infix-containers.c +++ b/src/confd/src/infix-containers.c @@ -113,10 +113,25 @@ static int add(const char *name, struct lyd_node *cif) /* Content mount: create a unique file with 'content' and bind mount */ if (data) { + const char *mode = lydx_get_cattr(node, "mode"); const char *contdir = "/run/containers/files"; + mode_t file_mode = 0644; char cmd[256]; + int pos, fd; FILE *pp; - int pos; + + if (mode) { + unsigned long val; + char *endptr; + + val = strtoul(mode, &endptr, 8); + if (*endptr != '\0' || val > 07777) { + ERROR("%s: invalid file mode '%s'", nm, mode); + continue; + } + + file_mode = (mode_t)val; + } /* * prefix file name with container name, shared namespace, @@ -129,6 +144,27 @@ static int add(const char *name, struct lyd_node *cif) nm[i] = '-'; } + /* + * Always create with secure permissions, then immediately + * set final mode. This takes care of both new files and + * updates to existing files atomically. + */ + fd = open(nm, O_CREAT | O_WRONLY | O_TRUNC, 0600); + if (fd < 0) { + ERRNO("%s: failed creating file %s", name, nm); + continue; + } + + /* Set final permissions */ + if (fchmod(fd, file_mode) < 0) { + ERRNO("%s: failed setting file mode %s", nm, mode); + close(fd); + unlink(nm); + continue; + } + close(fd); + + /* Now decode base64 content into the properly secured file */ snprintf(cmd, sizeof(cmd), "base64 -d > %s", nm); pp = popen(cmd, "w"); if (!pp || fputs(data, pp) < 0) { @@ -137,8 +173,8 @@ static int add(const char *name, struct lyd_node *cif) pclose(pp); continue; } - pclose(pp); + type = "bind"; /* discard any configured setting */ src = nm; /* discard any source, not used for content mounts */ } diff --git a/src/confd/yang/confd/infix-containers.yang b/src/confd/yang/confd/infix-containers.yang index 18974e579..9226bc243 100644 --- a/src/confd/yang/confd/infix-containers.yang +++ b/src/confd/yang/confd/infix-containers.yang @@ -22,6 +22,11 @@ module infix-containers { prefix infix-sys; } + revision 2025-06-25 { + description "Add file mode option to content mounts, allows creating scripts."; + reference "internal"; + } + revision 2025-05-14 { description "Validation improvement: @@ -390,6 +395,16 @@ module infix-containers { } } + leaf mode { + description "File permissions for content mounts (not used for source mounts). + + Octal notation (e.g., '755', '0644', '4755'). When not specified, + the mode will be '0644'."; + type string { + pattern '0?[0-7]{3,4}'; + } + } + leaf read-only { description "All mounts are read-only by default. Use this option to allow containers to write to files diff --git a/src/confd/yang/confd/infix-containers@2025-05-14.yang b/src/confd/yang/confd/infix-containers@2025-06-25.yang similarity index 100% rename from src/confd/yang/confd/infix-containers@2025-05-14.yang rename to src/confd/yang/confd/infix-containers@2025-06-25.yang diff --git a/src/confd/yang/containers.inc b/src/confd/yang/containers.inc index 50447cf87..4b2e3f30c 100644 --- a/src/confd/yang/containers.inc +++ b/src/confd/yang/containers.inc @@ -1,5 +1,5 @@ # -*- sh -*- MODULES=( "infix-interfaces -e containers" - "infix-containers@2025-05-14.yang" + "infix-containers@2025-06-25.yang" )