1e71ca95cSGerald Jelinek /*
2e71ca95cSGerald Jelinek * CDDL HEADER START
3e71ca95cSGerald Jelinek *
4e71ca95cSGerald Jelinek * The contents of this file are subject to the terms of the
5e71ca95cSGerald Jelinek * Common Development and Distribution License (the "License").
6e71ca95cSGerald Jelinek * You may not use this file except in compliance with the License.
7e71ca95cSGerald Jelinek *
8e71ca95cSGerald Jelinek * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e71ca95cSGerald Jelinek * or http://www.opensolaris.org/os/licensing.
10e71ca95cSGerald Jelinek * See the License for the specific language governing permissions
11e71ca95cSGerald Jelinek * and limitations under the License.
12e71ca95cSGerald Jelinek *
13e71ca95cSGerald Jelinek * When distributing Covered Code, include this CDDL HEADER in each
14e71ca95cSGerald Jelinek * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e71ca95cSGerald Jelinek * If applicable, add the following below this CDDL HEADER, with the
16e71ca95cSGerald Jelinek * fields enclosed by brackets "[]" replaced with your own identifying
17e71ca95cSGerald Jelinek * information: Portions Copyright [yyyy] [name of copyright owner]
18e71ca95cSGerald Jelinek *
19e71ca95cSGerald Jelinek * CDDL HEADER END
20e71ca95cSGerald Jelinek */
21e71ca95cSGerald Jelinek /*
22*98f4f4f6Sjv * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23e71ca95cSGerald Jelinek */
24e71ca95cSGerald Jelinek
25e71ca95cSGerald Jelinek /*
26e71ca95cSGerald Jelinek * s10_support is a small cli utility used to perform some brand-specific
27e71ca95cSGerald Jelinek * tasks when verifying a zone. This utility is not intended to be called
28e71ca95cSGerald Jelinek * by users - it is intended to be invoked by the zones utilities.
29e71ca95cSGerald Jelinek */
30e71ca95cSGerald Jelinek
31e71ca95cSGerald Jelinek #include <ctype.h>
32e71ca95cSGerald Jelinek #include <errno.h>
33e71ca95cSGerald Jelinek #include <fcntl.h>
34e71ca95cSGerald Jelinek #include <libgen.h>
35e71ca95cSGerald Jelinek #include <limits.h>
36e71ca95cSGerald Jelinek #include <s10_brand.h>
37e71ca95cSGerald Jelinek #include <stdarg.h>
38e71ca95cSGerald Jelinek #include <stdio.h>
39e71ca95cSGerald Jelinek #include <stdlib.h>
40e71ca95cSGerald Jelinek #include <string.h>
41e71ca95cSGerald Jelinek #include <strings.h>
42e71ca95cSGerald Jelinek #include <stropts.h>
43e71ca95cSGerald Jelinek #include <sys/stat.h>
44e71ca95cSGerald Jelinek #include <sys/types.h>
45e71ca95cSGerald Jelinek #include <sys/utsname.h>
46e71ca95cSGerald Jelinek #include <sys/varargs.h>
47e71ca95cSGerald Jelinek #include <unistd.h>
48e71ca95cSGerald Jelinek #include <libintl.h>
49e71ca95cSGerald Jelinek #include <locale.h>
50e71ca95cSGerald Jelinek #include <dirent.h>
51e71ca95cSGerald Jelinek #include <sys/systeminfo.h>
52e71ca95cSGerald Jelinek
53e71ca95cSGerald Jelinek #include <libzonecfg.h>
54e71ca95cSGerald Jelinek
55e71ca95cSGerald Jelinek static void s10_err(char *msg, ...) __NORETURN;
56e71ca95cSGerald Jelinek static void usage(void) __NORETURN;
57e71ca95cSGerald Jelinek
58e71ca95cSGerald Jelinek /*
59e71ca95cSGerald Jelinek * XXX This is a temporary flag for the initial release to enable the
60e71ca95cSGerald Jelinek * use of features which are not yet tested or fully implemented.
61e71ca95cSGerald Jelinek */
62e71ca95cSGerald Jelinek static boolean_t override = B_FALSE;
63e71ca95cSGerald Jelinek
64e71ca95cSGerald Jelinek static char *bname = NULL;
65e71ca95cSGerald Jelinek
66*98f4f4f6Sjv /*
67*98f4f4f6Sjv * DELETE_LIST_PATH represents the path to a solaris10-branded zone's "delete
68*98f4f4f6Sjv * list", which is generated by patchrm when it needs to remove files after
69*98f4f4f6Sjv * the zone reboots. See set_zone_emul_bitmap() below for additional details.
70*98f4f4f6Sjv */
71*98f4f4f6Sjv #define DELETE_LIST_PATH "/var/sadm/patch/.delete_list"
72*98f4f4f6Sjv
73e71ca95cSGerald Jelinek #define PKGINFO_RD_LEN 128
74e71ca95cSGerald Jelinek #define PATCHLIST "PATCHLIST="
75e71ca95cSGerald Jelinek
76e71ca95cSGerald Jelinek #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
77e71ca95cSGerald Jelinek #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
78e71ca95cSGerald Jelinek #endif
79e71ca95cSGerald Jelinek
80e71ca95cSGerald Jelinek /*PRINTFLIKE1*/
81e71ca95cSGerald Jelinek static void
s10_err(char * msg,...)82e71ca95cSGerald Jelinek s10_err(char *msg, ...)
83e71ca95cSGerald Jelinek {
84e71ca95cSGerald Jelinek char buf[1024];
85e71ca95cSGerald Jelinek va_list ap;
86e71ca95cSGerald Jelinek
87e71ca95cSGerald Jelinek va_start(ap, msg);
88e71ca95cSGerald Jelinek (void) vsnprintf(buf, sizeof (buf), msg, ap);
89e71ca95cSGerald Jelinek va_end(ap);
90e71ca95cSGerald Jelinek
91e71ca95cSGerald Jelinek /* This needs go to stdout so the msgs show up through zoneadm. */
92e71ca95cSGerald Jelinek (void) printf("Error: %s\n", buf);
93e71ca95cSGerald Jelinek
94e71ca95cSGerald Jelinek exit(1);
95e71ca95cSGerald Jelinek /*NOTREACHED*/
96e71ca95cSGerald Jelinek }
97e71ca95cSGerald Jelinek
98e71ca95cSGerald Jelinek static int
s10_verify(char * xmlfile)99e71ca95cSGerald Jelinek s10_verify(char *xmlfile)
100e71ca95cSGerald Jelinek {
101e71ca95cSGerald Jelinek zone_dochandle_t handle;
102e71ca95cSGerald Jelinek struct zone_devtab devtab;
103e71ca95cSGerald Jelinek
104e71ca95cSGerald Jelinek if ((handle = zonecfg_init_handle()) == NULL)
105e71ca95cSGerald Jelinek s10_err(gettext("internal libzonecfg.so.1 error"), 0);
106e71ca95cSGerald Jelinek
107e71ca95cSGerald Jelinek if (zonecfg_get_xml_handle(xmlfile, handle) != Z_OK) {
108e71ca95cSGerald Jelinek zonecfg_fini_handle(handle);
109e71ca95cSGerald Jelinek s10_err(gettext("zonecfg provided an invalid XML file"));
110e71ca95cSGerald Jelinek }
111e71ca95cSGerald Jelinek
112e71ca95cSGerald Jelinek /*
113e71ca95cSGerald Jelinek * Check to see whether the zone has any unsupported devices
114e71ca95cSGerald Jelinek * configured.
115e71ca95cSGerald Jelinek *
116e71ca95cSGerald Jelinek * The audio framework has changed in Solaris Next as compared to
117e71ca95cSGerald Jelinek * S10. Data indicates the less than 1/10 of 1 percent of zones
118e71ca95cSGerald Jelinek * are using /dev/sound. Given the low usage vs. the effort to
119e71ca95cSGerald Jelinek * provide emulation, /dev/sound is currently disallowed. We can
120e71ca95cSGerald Jelinek * revisit this if there is enough demand.
121e71ca95cSGerald Jelinek */
122e71ca95cSGerald Jelinek if (zonecfg_setdevent(handle) != Z_OK) {
123e71ca95cSGerald Jelinek zonecfg_fini_handle(handle);
124e71ca95cSGerald Jelinek s10_err(gettext("zonecfg provided an invalid XML file"));
125e71ca95cSGerald Jelinek }
126e71ca95cSGerald Jelinek if (zonecfg_getdevent(handle, &devtab) == Z_OK) {
127e71ca95cSGerald Jelinek if (strncmp(devtab.zone_dev_match, "/dev/sound", 10) == 0 &&
128e71ca95cSGerald Jelinek !override) {
129e71ca95cSGerald Jelinek zonecfg_fini_handle(handle);
130e71ca95cSGerald Jelinek s10_err(gettext("solaris10 zones do not currently "
131e71ca95cSGerald Jelinek "support /dev/sound"));
132e71ca95cSGerald Jelinek }
133e71ca95cSGerald Jelinek }
134e71ca95cSGerald Jelinek (void) zonecfg_enddevent(handle);
135e71ca95cSGerald Jelinek
136e71ca95cSGerald Jelinek zonecfg_fini_handle(handle);
137e71ca95cSGerald Jelinek return (0);
138e71ca95cSGerald Jelinek }
139e71ca95cSGerald Jelinek
140e71ca95cSGerald Jelinek /*
141e71ca95cSGerald Jelinek * Read an entry from a pkginfo file. Some of these lines can
142e71ca95cSGerald Jelinek * either be arbitrarily long or be continued by a backslash at the end of
143e71ca95cSGerald Jelinek * the line. This function coalesces lines that are longer than the read
144e71ca95cSGerald Jelinek * buffer, and lines that are continued, into one buffer which is returned.
145e71ca95cSGerald Jelinek * The caller must free this memory. NULL is returned when we hit EOF or
146e71ca95cSGerald Jelinek * if we run out of memory (errno is set to ENOMEM).
147e71ca95cSGerald Jelinek */
148e71ca95cSGerald Jelinek static char *
read_pkg_data(FILE * fp)149e71ca95cSGerald Jelinek read_pkg_data(FILE *fp)
150e71ca95cSGerald Jelinek {
151e71ca95cSGerald Jelinek char *start;
152e71ca95cSGerald Jelinek char *inp;
153e71ca95cSGerald Jelinek char *p;
154e71ca95cSGerald Jelinek int char_cnt = 0;
155e71ca95cSGerald Jelinek
156e71ca95cSGerald Jelinek errno = 0;
157e71ca95cSGerald Jelinek if ((start = (char *)malloc(PKGINFO_RD_LEN)) == NULL) {
158e71ca95cSGerald Jelinek errno = ENOMEM;
159e71ca95cSGerald Jelinek return (NULL);
160e71ca95cSGerald Jelinek }
161e71ca95cSGerald Jelinek
162e71ca95cSGerald Jelinek inp = start;
163e71ca95cSGerald Jelinek while ((p = fgets(inp, PKGINFO_RD_LEN, fp)) != NULL) {
164e71ca95cSGerald Jelinek int len;
165e71ca95cSGerald Jelinek
166e71ca95cSGerald Jelinek len = strlen(inp);
167e71ca95cSGerald Jelinek if (inp[len - 1] == '\n' &&
168e71ca95cSGerald Jelinek (len == 1 || inp[len - 2] != '\\')) {
169e71ca95cSGerald Jelinek char_cnt = len;
170e71ca95cSGerald Jelinek break;
171e71ca95cSGerald Jelinek }
172e71ca95cSGerald Jelinek
173e71ca95cSGerald Jelinek if (inp[len - 1] == '\n' && inp[len - 2] == '\\')
174e71ca95cSGerald Jelinek char_cnt += len - 2;
175e71ca95cSGerald Jelinek else
176e71ca95cSGerald Jelinek char_cnt += PKGINFO_RD_LEN - 1;
177e71ca95cSGerald Jelinek
178e71ca95cSGerald Jelinek if ((p = realloc(start, char_cnt + PKGINFO_RD_LEN)) == NULL) {
179e71ca95cSGerald Jelinek errno = ENOMEM;
180e71ca95cSGerald Jelinek break;
181e71ca95cSGerald Jelinek }
182e71ca95cSGerald Jelinek
183e71ca95cSGerald Jelinek start = p;
184e71ca95cSGerald Jelinek inp = start + char_cnt;
185e71ca95cSGerald Jelinek }
186e71ca95cSGerald Jelinek
187e71ca95cSGerald Jelinek if (errno == ENOMEM || (p == NULL && char_cnt == 0)) {
188e71ca95cSGerald Jelinek free(start);
189e71ca95cSGerald Jelinek start = NULL;
190e71ca95cSGerald Jelinek }
191e71ca95cSGerald Jelinek
192e71ca95cSGerald Jelinek return (start);
193e71ca95cSGerald Jelinek }
194e71ca95cSGerald Jelinek
195e71ca95cSGerald Jelinek /*
196e71ca95cSGerald Jelinek * Read the SUNWcakr pkginfo file and get the PATCHLIST for the pkg.
197e71ca95cSGerald Jelinek */
198e71ca95cSGerald Jelinek static int
get_ku_patchlist(char * zonepath,char ** patchlist)1991c604ca7SGerald Jelinek get_ku_patchlist(char *zonepath, char **patchlist)
200e71ca95cSGerald Jelinek {
201e71ca95cSGerald Jelinek char pkginfo[MAXPATHLEN];
202e71ca95cSGerald Jelinek FILE *fp;
203e71ca95cSGerald Jelinek char *buf;
204e71ca95cSGerald Jelinek int err = 0;
205e71ca95cSGerald Jelinek
206e71ca95cSGerald Jelinek if (snprintf(pkginfo, sizeof (pkginfo),
207e71ca95cSGerald Jelinek "%s/root/var/sadm/pkg/SUNWcakr/pkginfo", zonepath)
208e71ca95cSGerald Jelinek >= sizeof (pkginfo))
209e71ca95cSGerald Jelinek s10_err(gettext("error formating pkg path"));
210e71ca95cSGerald Jelinek
211e71ca95cSGerald Jelinek if ((fp = fopen(pkginfo, "r")) == NULL)
212e71ca95cSGerald Jelinek return (errno);
213e71ca95cSGerald Jelinek
214e71ca95cSGerald Jelinek while ((buf = read_pkg_data(fp)) != NULL) {
215e71ca95cSGerald Jelinek if (strncmp(buf, PATCHLIST, sizeof (PATCHLIST) - 1) == 0) {
216e71ca95cSGerald Jelinek int len;
217e71ca95cSGerald Jelinek
218e71ca95cSGerald Jelinek /* remove trailing newline */
219e71ca95cSGerald Jelinek len = strlen(buf);
220e71ca95cSGerald Jelinek buf[len - 1] = '\0';
221e71ca95cSGerald Jelinek
222e71ca95cSGerald Jelinek if ((*patchlist =
223e71ca95cSGerald Jelinek strdup(buf + sizeof (PATCHLIST) - 1)) == NULL)
224e71ca95cSGerald Jelinek err = ENOMEM;
225e71ca95cSGerald Jelinek
226e71ca95cSGerald Jelinek free(buf);
227e71ca95cSGerald Jelinek break;
228e71ca95cSGerald Jelinek }
229e71ca95cSGerald Jelinek
230e71ca95cSGerald Jelinek free(buf);
231e71ca95cSGerald Jelinek }
232e71ca95cSGerald Jelinek (void) fclose(fp);
233e71ca95cSGerald Jelinek
234e71ca95cSGerald Jelinek return (err);
235e71ca95cSGerald Jelinek }
236e71ca95cSGerald Jelinek
237e71ca95cSGerald Jelinek /*
238e71ca95cSGerald Jelinek * Verify that we have the minimum KU needed.
239e71ca95cSGerald Jelinek * Note that KU patches are accumulative so future KUs will still deliver
240e71ca95cSGerald Jelinek * 141444 or 141445.
241e71ca95cSGerald Jelinek */
242e71ca95cSGerald Jelinek static boolean_t
have_valid_ku(char * zonename)243e71ca95cSGerald Jelinek have_valid_ku(char *zonename)
244e71ca95cSGerald Jelinek {
245e71ca95cSGerald Jelinek char *p;
246e71ca95cSGerald Jelinek char *lastp;
247e71ca95cSGerald Jelinek char *pstr;
248e71ca95cSGerald Jelinek char *patchlist = NULL;
2491c604ca7SGerald Jelinek char zonepath[MAXPATHLEN];
2501c604ca7SGerald Jelinek char sanity_skip[MAXPATHLEN];
2511c604ca7SGerald Jelinek struct stat64 buf;
252ab5dfd5eS boolean_t is_xpv = B_FALSE;
253ab5dfd5eS char platform[80];
254ab5dfd5eS char *xpv_vers = "142910";
255e71ca95cSGerald Jelinek char *vers_table[] = {
256e71ca95cSGerald Jelinek "141444-09",
257ab5dfd5eS "141445-09"};
258e71ca95cSGerald Jelinek
2591c604ca7SGerald Jelinek if (zone_get_zonepath(zonename, zonepath, sizeof (zonepath)) != Z_OK)
2601c604ca7SGerald Jelinek s10_err(gettext("error getting zone's path"));
2611c604ca7SGerald Jelinek
2621c604ca7SGerald Jelinek /*
2631c604ca7SGerald Jelinek * If the zone was installed to bypass sanity checking for internal
2641c604ca7SGerald Jelinek * testing purposes, just return success.
2651c604ca7SGerald Jelinek */
2661c604ca7SGerald Jelinek if (snprintf(sanity_skip, sizeof (sanity_skip), "%s/root/.sanity_skip",
2671c604ca7SGerald Jelinek zonepath) >= sizeof (sanity_skip))
2681c604ca7SGerald Jelinek s10_err(gettext("error formating file path"));
2691c604ca7SGerald Jelinek
2701c604ca7SGerald Jelinek if (stat64(sanity_skip, &buf) == 0)
2711c604ca7SGerald Jelinek return (B_TRUE);
2721c604ca7SGerald Jelinek
2731c604ca7SGerald Jelinek if (get_ku_patchlist(zonepath, &patchlist) != 0 || patchlist == NULL)
274e71ca95cSGerald Jelinek return (B_FALSE);
275e71ca95cSGerald Jelinek
276ab5dfd5eS /*
277ab5dfd5eS * Check if we're running on the i86xpv platform. If so, the zone
278ab5dfd5eS * needs a different ku patch to work properly.
279ab5dfd5eS */
280ab5dfd5eS if (sysinfo(SI_PLATFORM, platform, sizeof (platform)) != -1 &&
281ab5dfd5eS strcmp(platform, "i86xpv") == 0)
282ab5dfd5eS is_xpv = B_TRUE;
283ab5dfd5eS
284e71ca95cSGerald Jelinek pstr = patchlist;
285e71ca95cSGerald Jelinek while ((p = strtok_r(pstr, " ", &lastp)) != NULL) {
286ab5dfd5eS if (is_xpv) {
287ab5dfd5eS if (strncmp(p, xpv_vers, 6) == 0)
288e71ca95cSGerald Jelinek return (B_TRUE);
289ab5dfd5eS } else {
290ab5dfd5eS if (strcmp(p, vers_table[0]) == 0 ||
291ab5dfd5eS strcmp(p, vers_table[1]) == 0)
292ab5dfd5eS return (B_TRUE);
293ab5dfd5eS }
294e71ca95cSGerald Jelinek
295e71ca95cSGerald Jelinek pstr = NULL;
296e71ca95cSGerald Jelinek }
297e71ca95cSGerald Jelinek
298ab5dfd5eS if (is_xpv)
299ab5dfd5eS s10_err(gettext("the zone must have patch 142910 installed "
300ab5dfd5eS "when running in a paravirtualized domain"));
301ab5dfd5eS
302ab5dfd5eS
303e71ca95cSGerald Jelinek return (B_FALSE);
304e71ca95cSGerald Jelinek }
305e71ca95cSGerald Jelinek
306*98f4f4f6Sjv /*
307*98f4f4f6Sjv * Convert the specified file basename into an unsigned integer. If the
308*98f4f4f6Sjv * basename contains characters that cannot be converted into digits or the
309*98f4f4f6Sjv * basename isn't NULL or newline-terminated, then this function returns
310*98f4f4f6Sjv * the unsigned equivalent of -1.
311*98f4f4f6Sjv */
312*98f4f4f6Sjv static unsigned int
basename_to_uint(const char * basenamep)313*98f4f4f6Sjv basename_to_uint(const char *basenamep)
314*98f4f4f6Sjv {
315*98f4f4f6Sjv char *filename_endptr;
316*98f4f4f6Sjv unsigned int bit_index;
317*98f4f4f6Sjv
318*98f4f4f6Sjv errno = 0;
319*98f4f4f6Sjv bit_index = (unsigned int)strtoul(basenamep, &filename_endptr, 10);
320*98f4f4f6Sjv if (errno != 0 || (*filename_endptr != '\n' &&
321*98f4f4f6Sjv *filename_endptr != '\0') || filename_endptr == basenamep)
322*98f4f4f6Sjv return ((unsigned int)-1);
323*98f4f4f6Sjv return (bit_index);
324*98f4f4f6Sjv }
325*98f4f4f6Sjv
326e71ca95cSGerald Jelinek /*
327ad601a05Sjv * Determine which features/behaviors should be emulated and construct a bitmap
328ad601a05Sjv * representing the results. Associate the bitmap with the zone so that
329ad601a05Sjv * the brand's emulation library will be able to retrieve the bitmap and
330ad601a05Sjv * determine how the zone's process' behaviors should be emulated.
331ad601a05Sjv *
332ad601a05Sjv * This function does not return if an error occurs.
333e71ca95cSGerald Jelinek */
334ad601a05Sjv static void
set_zone_emul_bitmap(char * zonename)335ad601a05Sjv set_zone_emul_bitmap(char *zonename)
336e71ca95cSGerald Jelinek {
337*98f4f4f6Sjv char zoneroot[MAXPATHLEN];
338*98f4f4f6Sjv char path[MAXPATHLEN];
339ad601a05Sjv DIR *req_emulation_dirp;
340ad601a05Sjv struct dirent *emul_feature_filep;
341ad601a05Sjv s10_emul_bitmap_t bitmap;
342ad601a05Sjv unsigned int bit_index;
343ad601a05Sjv zoneid_t zoneid;
344*98f4f4f6Sjv FILE *delete_listp;
345e71ca95cSGerald Jelinek
346ad601a05Sjv /*
347ad601a05Sjv * If the Solaris 10 directory containing emulation feature files
348ad601a05Sjv * doesn't exist in the zone, then assume that it only needs the
349ad601a05Sjv * most basic emulation and, therefore, doesn't need a bitmap.
350ad601a05Sjv */
351*98f4f4f6Sjv if (zone_get_rootpath(zonename, zoneroot, sizeof (zoneroot)) != Z_OK)
352ad601a05Sjv s10_err(gettext("error getting zone's path"));
353*98f4f4f6Sjv if (snprintf(path, sizeof (path), "%s" S10_REQ_EMULATION_DIR,
354*98f4f4f6Sjv zoneroot) >= sizeof (path))
355*98f4f4f6Sjv s10_err(gettext("zone's emulation versioning directory's path "
356*98f4f4f6Sjv "%s" S10_REQ_EMULATION_DIR " is too long"), zoneroot);
357*98f4f4f6Sjv if ((req_emulation_dirp = opendir(path)) == NULL)
358ad601a05Sjv return;
359ad601a05Sjv bzero(bitmap, sizeof (bitmap));
360e71ca95cSGerald Jelinek
361ad601a05Sjv /*
362ad601a05Sjv * Iterate over the contents of the directory and determine which
363ad601a05Sjv * features the brand should emulate for this zone.
364ad601a05Sjv */
365ad601a05Sjv while ((emul_feature_filep = readdir(req_emulation_dirp)) != NULL) {
366ad601a05Sjv if (strcmp(emul_feature_filep->d_name, ".") == 0 ||
367ad601a05Sjv strcmp(emul_feature_filep->d_name, "..") == 0)
368e71ca95cSGerald Jelinek continue;
369e71ca95cSGerald Jelinek
370ad601a05Sjv /*
371ad601a05Sjv * Convert the file's name to an unsigned integer. Ignore
372ad601a05Sjv * files whose names aren't unsigned integers.
373ad601a05Sjv */
374*98f4f4f6Sjv bit_index = basename_to_uint(emul_feature_filep->d_name);
375*98f4f4f6Sjv if (bit_index == (unsigned int)-1)
376ad601a05Sjv continue;
377ad601a05Sjv
378ad601a05Sjv /*
379ad601a05Sjv * Determine if the brand can emulate the feature specified
380ad601a05Sjv * by bit_index.
381ad601a05Sjv */
382ad601a05Sjv if (bit_index >= S10_NUM_EMUL_FEATURES) {
383ad601a05Sjv /*
384ad601a05Sjv * The zone requires emulation that the brand can't
385ad601a05Sjv * provide. Notify the user by displaying an error
386ad601a05Sjv * message.
387ad601a05Sjv */
388ad601a05Sjv s10_err(gettext("The zone's version of Solaris 10 is "
389ad601a05Sjv "incompatible with the\ncurrent version of the "
390ad601a05Sjv "solaris10 brand.\nPlease update your Solaris "
391ad601a05Sjv "system to the latest release."));
392ad601a05Sjv } else {
393ad601a05Sjv /*
394ad601a05Sjv * Set the feature's flag in the bitmap.
395ad601a05Sjv */
396ad601a05Sjv bitmap[(bit_index >> 3)] |= (1 << (bit_index & 0x7));
397e71ca95cSGerald Jelinek }
398e71ca95cSGerald Jelinek }
399*98f4f4f6Sjv (void) closedir(req_emulation_dirp);
400*98f4f4f6Sjv
401*98f4f4f6Sjv /*
402*98f4f4f6Sjv * The zone's administrator might have removed a patch that delivered
403*98f4f4f6Sjv * an emulation feature file the last time the zone ran. If so, then
404*98f4f4f6Sjv * the zone's patch utilities won't delete the file until the zone's
405*98f4f4f6Sjv * svc:/system/patch-finish:delete SMF service runs. This is
406*98f4f4f6Sjv * problematic because the zone will be using system libraries whose
407*98f4f4f6Sjv * ioctl structures and syscall invocations will differ from those
408*98f4f4f6Sjv * expected by the emulation library. For example, if an administrator
409*98f4f4f6Sjv * removes a patch that affects the formats of MNTFS ioctls, then the
410*98f4f4f6Sjv * administrator's zone will use a version of libc.so.1 that issues
411*98f4f4f6Sjv * MNTFS ioctls that use older structure versions than the zone's
412*98f4f4f6Sjv * emulation library will expect.
413*98f4f4f6Sjv *
414*98f4f4f6Sjv * Fortunately, the patchrm utility creates a hidden file,
415*98f4f4f6Sjv * /var/sadm/patch/.delete_list, which lists all files that
416*98f4f4f6Sjv * svc:/system/patch-finish:delete will delete. We'll determine whether
417*98f4f4f6Sjv * this file exists in the zone and disable the emulation bits
418*98f4f4f6Sjv * associated with the emulation feature files that will be deleted.
419*98f4f4f6Sjv *
420*98f4f4f6Sjv * NOTE: The patch tools lofs mount backup copies of critical system
421*98f4f4f6Sjv * libraries, such as /lib/libc.so.1, over their replacements whenever
422*98f4f4f6Sjv * administrators add or remove DAP patches. Consequently, there isn't
423*98f4f4f6Sjv * a window of vulnerability between patch addition or removal and
424*98f4f4f6Sjv * zone reboot. The aforementioned problem only occurs after a zone
425*98f4f4f6Sjv * reboots.
426*98f4f4f6Sjv */
427*98f4f4f6Sjv if (snprintf(path, sizeof (path), "%s" DELETE_LIST_PATH, zoneroot) >=
428*98f4f4f6Sjv sizeof (path))
429*98f4f4f6Sjv s10_err(gettext("zone's delete list's path %s" DELETE_LIST_PATH
430*98f4f4f6Sjv " is too long"), zoneroot);
431*98f4f4f6Sjv if ((delete_listp = fopen(path, "r")) != NULL) {
432*98f4f4f6Sjv while (fgets(path, sizeof (path), delete_listp) != NULL) {
433*98f4f4f6Sjv char *const basenamep = path +
434*98f4f4f6Sjv sizeof (S10_REQ_EMULATION_DIR);
435*98f4f4f6Sjv
436*98f4f4f6Sjv /*
437*98f4f4f6Sjv * Make sure that the file is in the directory
438*98f4f4f6Sjv * containing emulation feature files. If it is,
439*98f4f4f6Sjv * then basenamep should refer to the basename of
440*98f4f4f6Sjv * the file.
441*98f4f4f6Sjv */
442*98f4f4f6Sjv if (strncmp(path, S10_REQ_EMULATION_DIR,
443*98f4f4f6Sjv sizeof (S10_REQ_EMULATION_DIR) - 1) != 0)
444*98f4f4f6Sjv continue;
445*98f4f4f6Sjv if (*(basenamep - 1) != '/')
446*98f4f4f6Sjv continue;
447*98f4f4f6Sjv
448*98f4f4f6Sjv /*
449*98f4f4f6Sjv * Convert the file's basename into a bit index in
450*98f4f4f6Sjv * the emulation bitmap. If the file's basename isn't
451*98f4f4f6Sjv * integral, then skip the file. Otherwise, clear the
452*98f4f4f6Sjv * corresponding bit in the bitmap.
453*98f4f4f6Sjv */
454*98f4f4f6Sjv bit_index = basename_to_uint(basenamep);
455*98f4f4f6Sjv if (bit_index == (unsigned int)-1)
456*98f4f4f6Sjv continue;
457*98f4f4f6Sjv if (bit_index < S10_NUM_EMUL_FEATURES)
458*98f4f4f6Sjv bitmap[(bit_index >> 3)] &=
459*98f4f4f6Sjv ~(1 << (bit_index & 0x7));
460*98f4f4f6Sjv }
461*98f4f4f6Sjv if (ferror(delete_listp) != 0 || feof(delete_listp) == 0)
462*98f4f4f6Sjv s10_err(gettext("The program encountered an error while"
463*98f4f4f6Sjv " reading from %s" DELETE_LIST_PATH "."), zoneroot);
464*98f4f4f6Sjv (void) fclose(delete_listp);
465*98f4f4f6Sjv } else if (errno != ENOENT) {
466*98f4f4f6Sjv /*
467*98f4f4f6Sjv * The delete list exists but couldn't be opened. Warn the
468*98f4f4f6Sjv * administrator.
469*98f4f4f6Sjv */
470*98f4f4f6Sjv s10_err(gettext("Unable to open %s" DELETE_LIST_PATH ": %s"),
471*98f4f4f6Sjv zoneroot, strerror(errno));
472*98f4f4f6Sjv }
473e71ca95cSGerald Jelinek
474ad601a05Sjv /*
475ad601a05Sjv * We're done scanning files. Set the zone's emulation bitmap.
476ad601a05Sjv */
477ad601a05Sjv if ((zoneid = getzoneidbyname(zonename)) < 0)
478ad601a05Sjv s10_err(gettext("unable to get zoneid"));
479ad601a05Sjv if (zone_setattr(zoneid, S10_EMUL_BITMAP, bitmap, sizeof (bitmap)) != 0)
480ad601a05Sjv s10_err(gettext("error setting zone's emulation bitmap"));
481e71ca95cSGerald Jelinek }
482e71ca95cSGerald Jelinek
483e71ca95cSGerald Jelinek static int
s10_boot(char * zonename)484e71ca95cSGerald Jelinek s10_boot(char *zonename)
485e71ca95cSGerald Jelinek {
486e71ca95cSGerald Jelinek if (!have_valid_ku(zonename))
487e71ca95cSGerald Jelinek s10_err(gettext("The installed version of Solaris 10 is "
488e71ca95cSGerald Jelinek "not supported"));
489e71ca95cSGerald Jelinek
490ad601a05Sjv set_zone_emul_bitmap(zonename);
491e71ca95cSGerald Jelinek
492e71ca95cSGerald Jelinek return (0);
493e71ca95cSGerald Jelinek }
494e71ca95cSGerald Jelinek
495e71ca95cSGerald Jelinek static void
usage()496e71ca95cSGerald Jelinek usage()
497e71ca95cSGerald Jelinek {
498e71ca95cSGerald Jelinek (void) fprintf(stderr, gettext(
499e71ca95cSGerald Jelinek "usage:\t%s verify <xml file>\n"
500e71ca95cSGerald Jelinek "\t%s boot\n"),
501e71ca95cSGerald Jelinek bname, bname);
502e71ca95cSGerald Jelinek exit(1);
503e71ca95cSGerald Jelinek }
504e71ca95cSGerald Jelinek
505e71ca95cSGerald Jelinek int
main(int argc,char * argv[])506e71ca95cSGerald Jelinek main(int argc, char *argv[])
507e71ca95cSGerald Jelinek {
508e71ca95cSGerald Jelinek (void) setlocale(LC_ALL, "");
509e71ca95cSGerald Jelinek (void) textdomain(TEXT_DOMAIN);
510e71ca95cSGerald Jelinek
511e71ca95cSGerald Jelinek bname = basename(argv[0]);
512e71ca95cSGerald Jelinek
513e71ca95cSGerald Jelinek if (argc != 3)
514e71ca95cSGerald Jelinek usage();
515e71ca95cSGerald Jelinek
516e71ca95cSGerald Jelinek /*
517e71ca95cSGerald Jelinek * XXX This is a temporary env variable for the initial release to
518e71ca95cSGerald Jelinek * enable the use of features which are not yet tested or fully
519e71ca95cSGerald Jelinek * implemented.
520e71ca95cSGerald Jelinek */
521e71ca95cSGerald Jelinek if (getenv("S10BRAND_TEST") != NULL)
522e71ca95cSGerald Jelinek override = B_TRUE;
523e71ca95cSGerald Jelinek
524e71ca95cSGerald Jelinek if (strcmp(argv[1], "verify") == 0)
525e71ca95cSGerald Jelinek return (s10_verify(argv[2]));
526e71ca95cSGerald Jelinek
527e71ca95cSGerald Jelinek if (strcmp(argv[1], "boot") == 0)
528e71ca95cSGerald Jelinek return (s10_boot(argv[2]));
529e71ca95cSGerald Jelinek
530e71ca95cSGerald Jelinek usage();
531e71ca95cSGerald Jelinek /*NOTREACHED*/
532e71ca95cSGerald Jelinek }
533