1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include "mtlib.h"
27 #include <sys/types.h>
28 #include <libscf.h>
29 #include <sys/uadmin.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <zone.h>
33 #include <thread.h>
34 #include <dlfcn.h>
35 #include <atomic.h>
36
37 /*
38 * Pull in the following three interfaces from libscf without introducing
39 * a dependency on it, which since libscf depends on libc would be circular:
40 *
41 * scf_simple_prop_get
42 * scf_simple_prop_next_boolean
43 * scf_simple_prop_free
44 */
45 typedef scf_simple_prop_t *(*scf_simple_prop_get_t)(scf_handle_t *,
46 const char *, const char *, const char *);
47 static scf_simple_prop_get_t real_scf_simple_prop_get = NULL;
48 typedef uint8_t *(*scf_simple_prop_next_boolean_t)(scf_simple_prop_t *);
49 static scf_simple_prop_next_boolean_t real_scf_simple_prop_next_boolean = NULL;
50 typedef void (*scf_simple_prop_free_t)(scf_simple_prop_t *);
51 static scf_simple_prop_free_t real_scf_simple_prop_free = NULL;
52 static mutex_t scf_lock = DEFAULTMUTEX;
53
54 static void
load_scf(void)55 load_scf(void)
56 {
57 void *scf_handle = dlopen("libscf.so.1", RTLD_LAZY);
58 scf_simple_prop_get_t scf_simple_prop_get = (scf_handle == NULL)? NULL :
59 (scf_simple_prop_get_t)dlsym(scf_handle, "scf_simple_prop_get");
60 scf_simple_prop_next_boolean_t scf_simple_prop_next_boolean =
61 (scf_handle == NULL)? NULL :
62 (scf_simple_prop_next_boolean_t)dlsym(scf_handle,
63 "scf_simple_prop_next_boolean");
64 scf_simple_prop_free_t scf_simple_prop_free =
65 (scf_handle == NULL)? NULL :
66 (scf_simple_prop_free_t)dlsym(scf_handle, "scf_simple_prop_free");
67
68 lmutex_lock(&scf_lock);
69 if (real_scf_simple_prop_get == NULL ||
70 real_scf_simple_prop_next_boolean == NULL ||
71 real_scf_simple_prop_free == NULL) {
72 if (scf_simple_prop_get == NULL)
73 real_scf_simple_prop_get = (scf_simple_prop_get_t)(-1);
74 else {
75 real_scf_simple_prop_get = scf_simple_prop_get;
76 scf_handle = NULL; /* don't dlclose it */
77 }
78 if (scf_simple_prop_next_boolean == NULL)
79 real_scf_simple_prop_next_boolean =
80 (scf_simple_prop_next_boolean_t)(-1);
81 else {
82 real_scf_simple_prop_next_boolean =
83 scf_simple_prop_next_boolean;
84 scf_handle = NULL; /* don't dlclose it */
85 }
86 if (scf_simple_prop_free == NULL)
87 real_scf_simple_prop_free =
88 (scf_simple_prop_free_t)(-1);
89 else {
90 real_scf_simple_prop_free = scf_simple_prop_free;
91 scf_handle = NULL; /* don't dlclose it */
92 }
93 membar_producer();
94 }
95 lmutex_unlock(&scf_lock);
96
97 if (scf_handle)
98 (void) dlclose(scf_handle);
99 }
100
101 static void
check_archive_update(void)102 check_archive_update(void)
103 {
104 scf_simple_prop_t *prop = NULL;
105 boolean_t update_flag = B_FALSE;
106 char *fmri = "svc:/system/boot-config:default";
107 uint8_t *ret_val = NULL;
108
109 if (real_scf_simple_prop_get == NULL ||
110 real_scf_simple_prop_next_boolean == NULL ||
111 real_scf_simple_prop_free == NULL) {
112 load_scf();
113 }
114 if (real_scf_simple_prop_get == (scf_simple_prop_get_t)(-1) ||
115 real_scf_simple_prop_next_boolean ==
116 (scf_simple_prop_next_boolean_t)(-1) ||
117 real_scf_simple_prop_free == (scf_simple_prop_free_t)(-1)) {
118 return;
119 }
120
121 prop = real_scf_simple_prop_get(NULL, fmri, "config",
122 "uadmin_boot_archive_sync");
123 if (prop) {
124 if ((ret_val = real_scf_simple_prop_next_boolean(prop)) !=
125 NULL)
126 update_flag = (*ret_val == 0) ? B_FALSE :
127 B_TRUE;
128 real_scf_simple_prop_free(prop);
129 }
130
131 if (update_flag == B_TRUE)
132 (void) system("/sbin/bootadm update-archive");
133 }
134
135 int
uadmin(int cmd,int fcn,uintptr_t mdep)136 uadmin(int cmd, int fcn, uintptr_t mdep)
137 {
138 extern int __uadmin(int cmd, int fcn, uintptr_t mdep);
139
140 if (geteuid() == 0 && getzoneid() == GLOBAL_ZONEID &&
141 (cmd == A_SHUTDOWN || cmd == A_REBOOT)) {
142 check_archive_update();
143 }
144
145 return (__uadmin(cmd, fcn, mdep));
146 }
147