summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzonecfg/common/getzoneent.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libzonecfg/common/getzoneent.c')
-rw-r--r--usr/src/lib/libzonecfg/common/getzoneent.c158
1 files changed, 101 insertions, 57 deletions
diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c
index 4a62bddaa9..2decb372a9 100644
--- a/usr/src/lib/libzonecfg/common/getzoneent.c
+++ b/usr/src/lib/libzonecfg/common/getzoneent.c
@@ -35,7 +35,6 @@
*/
#include <stdlib.h>
-#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <libzonecfg.h>
@@ -43,6 +42,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <assert.h>
+#include <uuid/uuid.h>
#include "zonecfg_impl.h"
@@ -56,6 +56,8 @@
* Same with double-quotes themselves: they are not allowed in zone names,
* and do not occur in zone states, and in theory should never occur in a
* zonepath since zonecfg does not support a method for escaping them.
+ *
+ * It never returns NULL.
*/
static char *
@@ -129,7 +131,7 @@ getzoneent_private(FILE *cookie)
continue;
}
p = gettok(&cp);
- if (p == NULL || *p == '\0' || strlen(p) > ZONENAME_MAX) {
+ if (*p == '\0' || strlen(p) >= ZONENAME_MAX) {
/*
* empty or very long zone names are not allowed
*/
@@ -138,7 +140,7 @@ getzoneent_private(FILE *cookie)
(void) strlcpy(ze->zone_name, p, ZONENAME_MAX);
p = gettok(&cp);
- if (p == NULL || *p == '\0') {
+ if (*p == '\0') {
/* state field should not be empty */
continue;
}
@@ -149,30 +151,44 @@ getzoneent_private(FILE *cookie)
ze->zone_state = ZONE_STATE_INCOMPLETE;
} else if (strcmp(p, ZONE_STATE_STR_INSTALLED) == 0) {
ze->zone_state = ZONE_STATE_INSTALLED;
- } else
+ } else {
continue;
+ }
p = gettok(&cp);
- if (strlen(p) > MAXPATHLEN) {
+ if (strlen(p) >= MAXPATHLEN) {
/* very long paths are not allowed */
continue;
}
- if (p == NULL) {
- /* empty paths accepted for backwards compatibility */
- p = "";
- }
(void) strlcpy(ze->zone_path, p, MAXPATHLEN);
+ p = gettok(&cp);
+ if (uuid_parse(p, ze->zone_uuid) == -1)
+ uuid_clear(ze->zone_uuid);
+
break;
}
return (ze);
}
+static boolean_t
+get_index_path(char *path)
+{
+ return (snprintf(path, MAXPATHLEN, "%s%s", zonecfg_root,
+ ZONE_INDEX_FILE) < MAXPATHLEN);
+}
+
FILE *
setzoneent(void)
{
- return (fopen(ZONE_INDEX_FILE, "r"));
+ char path[MAXPATHLEN];
+
+ if (!get_index_path(path)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ return (fopen(path, "r"));
}
void
@@ -183,25 +199,35 @@ endzoneent(FILE *cookie)
}
static int
-lock_index_file(int *lock_fd)
+lock_index_file(void)
{
+ int lock_fd;
struct flock lock;
-
- if ((mkdir(ZONE_SNAPSHOT_ROOT, S_IRWXU) == -1) && errno != EEXIST)
- return (Z_LOCKING_FILE);
- *lock_fd = open(ZONE_INDEX_LOCK_FILE, O_CREAT|O_RDWR, 0644);
- if (*lock_fd < 0)
- return (Z_LOCKING_FILE);
+ char path[MAXPATHLEN];
+
+ if (snprintf(path, sizeof (path), "%s%s", zonecfg_root,
+ ZONE_INDEX_LOCK_DIR) >= sizeof (path))
+ return (-1);
+ if ((mkdir(path, S_IRWXU) == -1) && errno != EEXIST)
+ return (-1);
+ if (strlcat(path, ZONE_INDEX_LOCK_FILE, sizeof (path)) >=
+ sizeof (path))
+ return (-1);
+ lock_fd = open(path, O_CREAT|O_RDWR, 0644);
+ if (lock_fd == -1)
+ return (-1);
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
- if (fcntl(*lock_fd, F_SETLKW, &lock) == -1)
- return (Z_LOCKING_FILE);
+ if (fcntl(lock_fd, F_SETLKW, &lock) == -1) {
+ (void) close(lock_fd);
+ return (-1);
+ }
- return (Z_OK);
+ return (lock_fd);
}
static int
@@ -247,11 +273,14 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
{
FILE *index_file, *tmp_file;
char *tmp_file_name, buf[MAX_INDEX_LEN], orig_buf[MAX_INDEX_LEN];
- char zone[ZONENAME_MAX + 1]; /* name plus newline */
+ char zone[ZONENAME_MAX];
char line[MAX_INDEX_LEN];
int tmp_file_desc, lock_fd, err;
boolean_t exists = B_FALSE, need_quotes;
char *cp, *p;
+ char path[MAXPATHLEN];
+ char uuidstr[37]; /* hard-coded because of CR 6305641 */
+ size_t tlen;
assert(ze != NULL);
if (operation == PZE_ADD &&
@@ -261,13 +290,19 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
if (operation != PZE_MODIFY && strlen(ze->zone_newname) != 0)
return (Z_INVAL);
- if ((err = lock_index_file(&lock_fd)) != Z_OK)
- return (err);
- tmp_file_name = strdup(_PATH_TMPFILE);
+ if ((lock_fd = lock_index_file()) == -1)
+ return (Z_LOCKING_FILE);
+
+ /* using sizeof gives us room for the terminating NUL byte as well */
+ tlen = sizeof (_PATH_TMPFILE) + strlen(zonecfg_root);
+ tmp_file_name = malloc(tlen);
if (tmp_file_name == NULL) {
(void) unlock_index_file(lock_fd);
return (Z_NOMEM);
}
+ (void) snprintf(tmp_file_name, tlen, "%s%s", zonecfg_root,
+ _PATH_TMPFILE);
+
tmp_file_desc = mkstemp(tmp_file_name);
if (tmp_file_desc == -1) {
(void) unlink(tmp_file_name);
@@ -277,17 +312,16 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
}
if ((tmp_file = fdopen(tmp_file_desc, "w")) == NULL) {
(void) close(tmp_file_desc);
- (void) unlink(tmp_file_name);
- free(tmp_file_name);
- (void) unlock_index_file(lock_fd);
- return (Z_MISC_FS);
+ err = Z_MISC_FS;
+ goto error;
}
- if ((index_file = fopen(ZONE_INDEX_FILE, "r")) == NULL) {
- (void) fclose(tmp_file);
- (void) unlink(tmp_file_name);
- free(tmp_file_name);
- (void) unlock_index_file(lock_fd);
- return (Z_MISC_FS);
+ if (!get_index_path(path)) {
+ err = Z_MISC_FS;
+ goto error;
+ }
+ if ((index_file = fopen(path, "r")) == NULL) {
+ err = Z_MISC_FS;
+ goto error;
}
/*
@@ -300,9 +334,17 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
*/
need_quotes = (strchr(ze->zone_path, ':') != NULL);
- (void) snprintf(line, sizeof (line), "%s:%s:%s%s%s\n", ze->zone_name,
- zone_state_str(ze->zone_state), need_quotes ? "\"" : "",
- ze->zone_path, need_quotes ? "\"" : "");
+ /*
+ * If this zone doesn't yet have a unique identifier, then give it one.
+ */
+ if (uuid_is_null(ze->zone_uuid))
+ uuid_generate(ze->zone_uuid);
+ uuid_unparse(ze->zone_uuid, uuidstr);
+
+ (void) snprintf(line, sizeof (line), "%s:%s:%s%s%s:%s\n",
+ ze->zone_name, zone_state_str(ze->zone_state),
+ need_quotes ? "\"" : "", ze->zone_path, need_quotes ? "\"" : "",
+ uuidstr);
for (;;) {
if (fgets(buf, sizeof (buf), index_file) == NULL) {
if (operation == PZE_ADD && !exists)
@@ -323,7 +365,7 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
continue;
}
p = gettok(&cp);
- if (p == NULL || *p == '\0' || strlen(p) > ZONENAME_MAX) {
+ if (*p == '\0' || strlen(p) >= ZONENAME_MAX) {
/*
* empty or very long zone names are not allowed
*/
@@ -335,6 +377,7 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
exists = B_TRUE; /* already there */
if (operation == PZE_ADD) {
/* can't add same zone */
+ err = Z_UPDATING_INDEX;
goto error;
} else if (operation == PZE_MODIFY) {
char tmp_state[ZONE_STATE_MAXSTRLEN + 1];
@@ -348,8 +391,9 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
}
/* use existing value for state */
p = gettok(&cp);
- if (p == NULL || *p == '\0') {
+ if (*p == '\0') {
/* state field should not be empty */
+ err = Z_UPDATING_INDEX;
goto error;
}
(void) strlcpy(tmp_state,
@@ -367,11 +411,12 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
else
tmp_name = ze->zone_name;
- (void) fprintf(tmp_file, "%s:%s:%s%s%s\n",
+ (void) fprintf(tmp_file, "%s:%s:%s%s%s:%s\n",
tmp_name, tmp_state,
need_quotes ? "\"" : "",
(strlen(ze->zone_path) == 0) ? p :
- ze->zone_path, need_quotes ? "\"" : "");
+ ze->zone_path, need_quotes ? "\"" : "",
+ uuidstr);
}
/* else if (operation == PZE_REMOVE) { no-op } */
} else {
@@ -380,31 +425,30 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation)
}
(void) fclose(index_file);
+ index_file = NULL;
if (fclose(tmp_file) != 0) {
- (void) unlink(tmp_file_name);
- free(tmp_file_name);
- (void) unlock_index_file(lock_fd);
- return (Z_MISC_FS);
+ tmp_file = NULL;
+ err = Z_MISC_FS;
+ goto error;
}
+ tmp_file = NULL;
(void) chmod(tmp_file_name, 0644);
- if (rename(tmp_file_name, ZONE_INDEX_FILE) == -1) {
- (void) unlink(tmp_file_name);
- free(tmp_file_name);
- (void) unlock_index_file(lock_fd);
- if (errno == EACCES)
- return (Z_ACCES);
- return (Z_MISC_FS);
+ if (rename(tmp_file_name, path) == -1) {
+ err = errno == EACCES ? Z_ACCES : Z_MISC_FS;
+ goto error;
}
free(tmp_file_name);
if (unlock_index_file(lock_fd) != Z_OK)
return (Z_UNLOCKING_FILE);
return (Z_OK);
+
error:
- (void) fclose(index_file);
- (void) fclose(tmp_file);
+ if (index_file != NULL)
+ (void) fclose(index_file);
+ if (tmp_file != NULL)
+ (void) fclose(tmp_file);
(void) unlink(tmp_file_name);
free(tmp_file_name);
- if (unlock_index_file(lock_fd) != Z_OK)
- return (Z_UNLOCKING_FILE);
- return (Z_UPDATING_INDEX);
+ (void) unlock_index_file(lock_fd);
+ return (err);
}