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 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 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 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