summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzonecfg/common/libzonecfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libzonecfg/common/libzonecfg.c')
-rw-r--r--usr/src/lib/libzonecfg/common/libzonecfg.c149
1 files changed, 132 insertions, 17 deletions
diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c
index b4eade5826..2149c546a1 100644
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c
@@ -24,6 +24,7 @@
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, Joyent, Inc.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
*/
#include <libsysevent.h>
@@ -60,6 +61,7 @@
#include <secdb.h>
#include <user_attr.h>
#include <prof_attr.h>
+#include <definit.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -1173,26 +1175,26 @@ zonecfg_refresh_index_file(zone_dochandle_t handle)
* Strategy:
*
* New zone 'foo' configuration:
- * Create tmpfile (zonecfg.xxxxxx)
- * Write XML to tmpfile
- * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
- * Add entry to index file
- * If it fails, delete foo.xml, leaving nothing behind.
+ * Create tmpfile (zonecfg.xxxxxx)
+ * Write XML to tmpfile
+ * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
+ * Add entry to index file
+ * If it fails, delete foo.xml, leaving nothing behind.
*
* Save existing zone 'foo':
- * Make backup of foo.xml -> .backup
- * Create tmpfile (zonecfg.xxxxxx)
- * Write XML to tmpfile
- * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
- * Modify index file as needed
- * If it fails, recover from .backup -> foo.xml
+ * Make backup of foo.xml -> .backup
+ * Create tmpfile (zonecfg.xxxxxx)
+ * Write XML to tmpfile
+ * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> foo.xml)
+ * Modify index file as needed
+ * If it fails, recover from .backup -> foo.xml
*
* Rename 'foo' to 'bar':
- * Create tmpfile (zonecfg.xxxxxx)
- * Write XML to tmpfile
- * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml)
- * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh)
- * If it fails, delete bar.xml; foo.xml is left behind.
+ * Create tmpfile (zonecfg.xxxxxx)
+ * Write XML to tmpfile
+ * Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml)
+ * Add entry for 'bar' to index file, Remove entry for 'foo' (refresh)
+ * If it fails, delete bar.xml; foo.xml is left behind.
*/
static int
zonecfg_save_impl(zone_dochandle_t handle, char *filename)
@@ -7521,6 +7523,110 @@ prepare_audit_context(const char *zone_name)
(void) adt_end_session(ah);
}
+static const char **
+get_zoneadmd_envp(void)
+{
+ const char **envp = NULL;
+ size_t envlen;
+ size_t envslot = 0;
+ const char *tok;
+ void *dstate = NULL;
+
+ /*
+ * This initial array size is enough to hold the two variables
+ * set below, up to five additional entries from /etc/default/init,
+ * and the NULL terminator. /etc/default/init commonly includes only
+ * TZ, LANG and LC_ALL. The array will be grown if necessary by
+ * doubling the size whenever it is full.
+ */
+ envlen = 8;
+
+ if ((envp = recallocarray(NULL, 0, envlen, sizeof (char *))) == NULL)
+ return (NULL);
+
+ /*
+ * See the comment above zonecfg_init_lock_file() for details on the
+ * implementation of the locking mechanism.
+ * zoneadmd is started with an inherited lock, indicated by the
+ * environment variable being set. Once the starting zoneadm exits,
+ * zoneadmd may persist and will continue to believe that it has the
+ * lock. This is okay as long as the only things that connect to the
+ * zoneadmd door and cause it to do work that requires a lock have
+ * grabbed the lock in advance, which zoneadm does in all cases today.
+ */
+ envp[envslot++] = zoneadm_lock_held;
+
+ if (asprintf((char **)&tok, "PATH=%s", ZONEADMD_PATH) == -1) {
+ free(envp);
+ return (NULL);
+ }
+ envp[envslot++] = tok;
+
+ if (definit_open(DEFINIT_DEFAULT_FILE, &dstate) != 0) {
+ if (errno == ENOENT) {
+ /*
+ * If the configuration file does not exist, return the
+ * environment populated so far (with PATH and the
+ * zoneadm lock).
+ */
+ envp[envslot] = NULL;
+ return (envp);
+ }
+ goto err;
+ }
+
+ while ((tok = definit_token(dstate)) != NULL) {
+
+ if (strncmp(tok, "CMASK=", 6) == 0) {
+ long t;
+
+ t = strtol(tok + 6, NULL, 8);
+
+ if (t >= DEFINIT_MIN_UMASK && t <= DEFINIT_MAX_UMASK)
+ (void) umask((int)t);
+ continue;
+ }
+
+ /*
+ * Always ensure there is space for a terminating
+ * NULL in addition to the new entry being added.
+ */
+ if (envslot + 2 >= envlen) {
+ const char **newenvp;
+
+ newenvp = recallocarray(envp, envlen, envlen * 2,
+ sizeof (char *));
+ if (newenvp == NULL)
+ goto err;
+ envp = newenvp;
+ envlen *= 2;
+ }
+
+ envp[envslot] = strdup(tok);
+ if (envp[envslot] == NULL)
+ goto err;
+ envslot++;
+ }
+
+ definit_close(dstate);
+ envp[envslot] = NULL;
+ return (envp);
+
+err:
+ if (dstate != NULL)
+ definit_close(dstate);
+
+ /*
+ * The first slot in envp is 'zoneadm_lock_held' and should not be
+ * freed.
+ */
+ while (--envslot > 0)
+ free((void *)envp[envslot]);
+ free(envp);
+
+ return (NULL);
+}
+
static int
start_zoneadmd(const char *zone_name, boolean_t lock)
{
@@ -7564,6 +7670,7 @@ start_zoneadmd(const char *zone_name, boolean_t lock)
if (child_pid == 0) {
const char *argv[6], **ap;
+ const char **envp;
/* child process */
prepare_audit_context(zone_name);
@@ -7578,7 +7685,15 @@ start_zoneadmd(const char *zone_name, boolean_t lock)
}
*ap = NULL;
- (void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv);
+ envp = get_zoneadmd_envp();
+ if (envp == NULL) {
+ zperror(gettext(
+ "could not build environment for zoneadmd"));
+ _exit(1);
+ }
+
+ (void) execve("/usr/lib/zones/zoneadmd",
+ (char * const *)argv, (char * const *)envp);
/*
* TRANSLATION_NOTE
* zoneadmd is a literal that should not be translated.