diff options
author | carlsonj <none@none> | 2006-02-13 11:54:12 -0800 |
---|---|---|
committer | carlsonj <none@none> | 2006-02-13 11:54:12 -0800 |
commit | eb8bc87559eb2a3f971b8ebb3eff91ca35ae6093 (patch) | |
tree | 50199edd0049b729247e3763c752f699c0cdbaf9 | |
parent | 00ab1250ca6296131437f41e529d52b2a88a2501 (diff) | |
download | illumos-joyent-eb8bc87559eb2a3f971b8ebb3eff91ca35ae6093.tar.gz |
6379341 zones in /etc/zones/index has non-unique UUID
-rw-r--r-- | usr/src/lib/libzonecfg/common/getzoneent.c | 202 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWzoner/postinstall | 54 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWzoner/prototype_com | 8 | ||||
-rw-r--r-- | usr/src/tools/scripts/bfu.sh | 28 |
4 files changed, 198 insertions, 94 deletions
diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c index 64d5ff8b33..c75ce2f096 100644 --- a/usr/src/lib/libzonecfg/common/getzoneent.c +++ b/usr/src/lib/libzonecfg/common/getzoneent.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -272,15 +271,14 @@ int 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]; - char line[MAX_INDEX_LEN]; + char *tmp_file_name, buf[MAX_INDEX_LEN]; int tmp_file_desc, lock_fd, err; - boolean_t exists = B_FALSE, need_quotes; - char *cp, *p; + boolean_t exist, need_quotes; + char *cp; char path[MAXPATHLEN]; char uuidstr[UUID_PRINTABLE_STRING_LENGTH]; - size_t tlen; + size_t tlen, namelen; + const char *zone_name, *zone_state, *zone_path, *zone_uuid; assert(ze != NULL); if (operation == PZE_ADD && @@ -324,104 +322,128 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) goto error; } - /* - * We need to quote a path which contains a ":"; this should only - * affect the zonepath, as zone names do not allow such characters, - * and zone states do not have them either. 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. - */ - need_quotes = (strchr(ze->zone_path, ':') != NULL); - - /* - * 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); + exist = B_FALSE; + zone_name = ze->zone_name; + namelen = strlen(zone_name); for (;;) { if (fgets(buf, sizeof (buf), index_file) == NULL) { - if (operation == PZE_ADD && !exists) - (void) fputs(line, tmp_file); + if (operation == PZE_ADD && !exist) { + zone_state = zone_state_str(ze->zone_state); + zone_path = ze->zone_path; + zone_uuid = ""; + goto add_entry; + } + /* + * It's not considered an error to delete something + * that doesn't exist, but we can't modify a missing + * record. + */ + if (operation == PZE_MODIFY && !exist) { + err = Z_UPDATING_INDEX; + goto error; + } break; } - (void) strlcpy(orig_buf, buf, sizeof (orig_buf)); - if ((cp = strpbrk(buf, "\r\n")) == NULL) { - /* this represents a line that's too long */ + if (buf[0] == '#') { + /* skip and preserve comment lines */ + (void) fputs(buf, tmp_file); continue; } - *cp = '\0'; - cp = buf; - if (*cp == '#') { - /* skip comment lines */ - (void) fputs(orig_buf, tmp_file); + + if (strncmp(buf, zone_name, namelen) != 0 || + buf[namelen] != ':') { + /* skip and preserve non-target lines */ + (void) fputs(buf, tmp_file); continue; } - p = gettok(&cp); - if (*p == '\0' || strlen(p) >= ZONENAME_MAX) { - /* - * empty or very long zone names are not allowed - */ + + if ((cp = strpbrk(buf, "\r\n")) == NULL) { + /* this represents a line that's too long; delete */ continue; } - (void) strlcpy(zone, p, ZONENAME_MAX); + *cp = '\0'; - if (strcmp(zone, ze->zone_name) == 0) { - 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]; - char *tmp_name; - - if (ze->zone_state >= 0 && - strlen(ze->zone_path) > 0) { - /* use specified values */ - (void) fputs(line, tmp_file); - continue; - } - /* use existing value for state */ - p = gettok(&cp); - if (*p == '\0') { - /* state field should not be empty */ - err = Z_UPDATING_INDEX; - goto error; - } - (void) strlcpy(tmp_state, - (ze->zone_state < 0) ? p : - zone_state_str(ze->zone_state), - sizeof (tmp_state)); - - p = gettok(&cp); + /* + * Skip over the zone name. Because we've already matched the + * target zone (above), we know for certain here that the zone + * name is present and correctly formed. No need to check. + */ + cp = strchr(buf, ':') + 1; + + zone_state = gettok(&cp); + if (*zone_state == '\0') { + /* state field should not be empty */ + err = Z_UPDATING_INDEX; + goto error; + } + zone_path = gettok(&cp); + zone_uuid = gettok(&cp); + + switch (operation) { + case PZE_ADD: + /* can't add same zone */ + err = Z_UPDATING_INDEX; + goto error; + + case PZE_MODIFY: + /* + * If the caller specified a new state for the zone, + * then use that. Otherwise, use the current state. + */ + if (ze->zone_state >= 0) { + zone_state = zone_state_str(ze->zone_state); /* - * If a new name is supplied, use it. + * If the caller is uninstalling this zone, + * then wipe out the uuid. The zone's contents + * are no longer known. */ - if (strlen(ze->zone_newname) != 0) - tmp_name = ze->zone_newname; - else - tmp_name = ze->zone_name; - - (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 ? "\"" : "", - uuidstr); + if (ze->zone_state < ZONE_STATE_INSTALLED) + zone_uuid = ""; } - /* else if (operation == PZE_REMOVE) { no-op } */ - } else { - (void) fputs(orig_buf, tmp_file); + + /* If a new name is supplied, use it. */ + if (ze->zone_newname[0] != '\0') + zone_name = ze->zone_newname; + + if (ze->zone_path[0] != '\0') + zone_path = ze->zone_path; + break; + + case PZE_REMOVE: + default: + continue; + } + + add_entry: + /* + * If the entry in the file is in greater than configured + * state, then we must have a UUID. Make sure that we do. + * (Note that the file entry is only tokenized, not fully + * parsed, so we need to do a string comparison here.) + */ + if (strcmp(zone_state, ZONE_STATE_STR_CONFIGURED) != 0 && + *zone_uuid == '\0') { + if (uuid_is_null(ze->zone_uuid)) + uuid_generate(ze->zone_uuid); + uuid_unparse(ze->zone_uuid, uuidstr); + zone_uuid = uuidstr; } + /* + * We need to quote a path that contains a ":"; this should + * only affect the zonepath, as zone names do not allow such + * characters, and zone states do not have them either. 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. + */ + need_quotes = (strchr(zone_path, ':') != NULL); + (void) fprintf(tmp_file, "%s:%s:%s%s%s:%s\n", zone_name, + zone_state, need_quotes ? "\"" : "", zone_path, + need_quotes ? "\"" : "", zone_uuid); + exist = B_TRUE; } (void) fclose(index_file); diff --git a/usr/src/pkgdefs/SUNWzoner/postinstall b/usr/src/pkgdefs/SUNWzoner/postinstall new file mode 100644 index 0000000000..864f7f129b --- /dev/null +++ b/usr/src/pkgdefs/SUNWzoner/postinstall @@ -0,0 +1,54 @@ +#!/usr/bin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# Detect and repair any UUID duplicates. +index=$BASEDIR/etc/zones/index +if [ -f $index ]; then + if nawk -F: ' + /^\#/ || NF != 4 { print $0; next; } + { + if (flags[$4]) + sub(/:[-0-9a-z]*$/,":"); + print $0; + flags[$4]=1; + } + ' < $index > ${index}.pkg.$$; then + if cmp -s $index ${index}.pkg.$$; then + rm -f ${index}.pkg.$$ + else + chown root:sys ${index}.pkg.$$ + chmod 644 ${index}.pkg.$$ + mv ${index}.pkg.$$ $index + fi + else + rm -f ${index}.pkg.$$ + fi +fi + +exit 0 diff --git a/usr/src/pkgdefs/SUNWzoner/prototype_com b/usr/src/pkgdefs/SUNWzoner/prototype_com index 3b81942c4c..e2c70b4240 100644 --- a/usr/src/pkgdefs/SUNWzoner/prototype_com +++ b/usr/src/pkgdefs/SUNWzoner/prototype_com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -40,6 +39,7 @@ i pkginfo i copyright i depend +i postinstall i i.preserve i i.manifest i r.manifest diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index dc15a45252..423dbabc88 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -6089,6 +6089,34 @@ mondo_loop() { disable_boot_service fi fi + + # Check for damage due to CR 6379341. This was actually fixed + # back in snv_24, but users BFUing from an S10 build up to + # Nevada can still encounter it. + rzi=$root/etc/zones/index + if [ -f $rzi ]; then + # Look for duplicated UUIDs. If there are any, then + # just wipe them out. + if nawk -F: ' + /^\#/ || NF != 4 { print $0; next; } + { + if (flags[$4]) + sub(/:[-0-9a-z]*$/,":"); + print $0; + flags[$4]=1; + } + ' < $rzi > ${rzi}.bfu.$$; then + if cmp -s $rzi ${rzi}.bfu.$$; then + rm -f ${rzi}.bfu.$$ + else + chown root:sys ${rzi}.bfu.$$ + chmod 644 ${rzi}.bfu.$$ + mv ${rzi}.bfu.$$ $rzi + fi + else + rm -f ${rzi}.bfu.$$ + fi + fi fi |