Print this page
OS-1574 libzdoor checks for NULL that cannot be
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libzdoor/common/zdoor-int.c
+++ new/usr/src/lib/libzdoor/common/zdoor-int.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2011 Joyent, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #pragma ident "%Z%%M% %I% %E% SMI"
27 27
28 28 #include <errno.h>
29 29 #include <fcntl.h>
30 30 #include <sys/fork.h>
31 31 #include <libcontract.h>
32 32 #include <libzonecfg.h>
33 33 #include <sys/contract/process.h>
34 34 #include <sys/ctfs.h>
35 35 #include <sys/types.h>
36 36 #include <sys/stat.h>
37 37 #include <sys/wait.h>
38 38 #include <stdlib.h>
39 39 #include <string.h>
40 40 #include <unistd.h>
41 41
42 42 #include "zdoor-int.h"
43 43 #include "zerror.h"
44 44
45 45 #define ZDOOR_FMT_STR "/var/tmp/.%s"
46 46
47 47
48 48 static int
49 49 init_template(void)
50 50 {
51 51 int fd = 0;
52 52 int err = 0;
53 53
54 54 fd = open64(CTFS_ROOT "/process/template", O_RDWR);
55 55 if (fd == -1)
56 56 return (-1);
57 57
58 58 err |= ct_tmpl_set_critical(fd, 0);
59 59 err |= ct_tmpl_set_informative(fd, 0);
60 60 err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
61 61 err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT);
62 62 if (err || ct_tmpl_activate(fd)) {
63 63 (void) close(fd);
64 64 return (-1);
65 65 }
66 66
67 67 return (fd);
68 68 }
69 69
70 70 static int
71 71 contract_latest(ctid_t *id)
72 72 {
73 73 int cfd = 0;
74 74 int r = 0;
75 75 ct_stathdl_t st = {0};
76 76 ctid_t result = {0};
77 77
78 78 if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1)
79 79 return (errno);
80 80 if ((r = ct_status_read(cfd, CTD_COMMON, &st)) != 0) {
81 81 (void) close(cfd);
82 82 return (r);
83 83 }
84 84
85 85 result = ct_status_get_id(st);
86 86 ct_status_free(st);
87 87 (void) close(cfd);
88 88
89 89 *id = result;
90 90 return (0);
91 91 }
92 92
93 93 static int
94 94 close_on_exec(int fd)
95 95 {
96 96 int flags = fcntl(fd, F_GETFD, 0);
97 97 if ((flags != -1) && (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1))
98 98 return (0);
99 99 return (-1);
100 100 }
101 101
102 102 static int
103 103 contract_open(ctid_t ctid, const char *type, const char *file, int oflag)
104 104 {
105 105 char path[PATH_MAX];
106 106 int n = 0;
107 107 int fd = 0;
108 108
109 109 if (type == NULL)
110 110 type = "all";
111 111
112 112 n = snprintf(path, PATH_MAX, CTFS_ROOT "/%s/%ld/%s", type, ctid, file);
113 113 if (n >= sizeof (path)) {
114 114 errno = ENAMETOOLONG;
115 115 return (-1);
116 116 }
117 117
118 118 fd = open64(path, oflag);
119 119 if (fd != -1) {
120 120 if (close_on_exec(fd) == -1) {
121 121 int err = errno;
122 122 (void) close(fd);
123 123 errno = err;
124 124 return (-1);
125 125 }
126 126 }
127 127 return (fd);
128 128 }
129 129
130 130 static int
131 131 contract_abandon_id(ctid_t ctid)
132 132 {
133 133 int fd = 0;
134 134 int err = 0;
135 135
136 136 fd = contract_open(ctid, "all", "ctl", O_WRONLY);
137 137 if (fd == -1)
138 138 return (errno);
139 139
140 140 err = ct_ctl_abandon(fd);
141 141 (void) close(fd);
142 142
143 143 return (err);
144 144 }
145 145
146 146 /*
147 147 * zdoor_fattach(zone,service,door,detach_only) is heavily borrowed from
148 148 * zonestatd. Basically this forks, zone_enter's the targeted zone,
149 149 * fattaches to /var/tmp/.<service> with the door you've opened.
150 150 * detach_only gets passed in on door_stop to fdetach in the targeted zone.
151 151 * Note that this code really does require all the contract calls, which are
152 152 * all the static functions preceding this (have a look at zone_enter; without
↓ open down ↓ |
152 lines elided |
↑ open up ↑ |
153 153 * that code zone_enter will kick back EINVAL).
154 154 */
155 155 int
156 156 zdoor_fattach(zoneid_t zoneid, const char *service, int door, int detach_only)
157 157 {
158 158 int fd = 0;
159 159 int len = 0;
160 160 int pid = 0;
161 161 int stat = 0;
162 162 int tmpl_fd = 0;
163 - char path[MAXPATHLEN] = {0};
163 + char path[MAXPATHLEN] = {0};
164 164 ctid_t ct = -1;
165 165
166 166 if (zoneid < 0) {
167 167 zdoor_debug("zdoor_fattach: zoneid < 0");
168 168 return (ZDOOR_ARGS_ERROR);
169 169 }
170 170
171 - if (path == NULL) {
172 - zdoor_debug("zdoor_fattach: NULL PATH");
171 + if (service == NULL) {
172 + zdoor_debug("zdoor_fattach: NULL service");
173 173 return (ZDOOR_ARGS_ERROR);
174 174 }
175 175
176 176 if ((tmpl_fd = init_template()) < 0) {
177 177 zdoor_warn("zdoor_fattach: init contract for %d:%s failed",
178 178 zoneid, service);
179 179 return (ZDOOR_ERROR);
180 180 }
181 181
182 182 len = snprintf(NULL, 0, ZDOOR_FMT_STR, service) + 1;
183 183 if (len > MAXPATHLEN)
184 184 return (ZDOOR_ARGS_ERROR);
185 185 (void) snprintf(path, len, ZDOOR_FMT_STR, service);
186 186
187 187 zdoor_info("zdoor_fattach: ensuring %s", path);
188 188
189 189 pid = fork();
190 190 if (pid < 0) {
191 191 (void) ct_tmpl_clear(tmpl_fd);
192 192 zdoor_error("zdoor_fattach: unable to fork for zone_enter: %s",
193 193 strerror(errno));
194 194 return (ZDOOR_OK);
195 195 }
196 196
197 197 if (pid == 0) {
198 198 zdoor_debug("zdoor_fattach(CHILD): starting");
199 199 (void) ct_tmpl_clear(tmpl_fd);
200 200 (void) close(tmpl_fd);
201 201 if (zone_enter(zoneid) != 0) {
202 202 zdoor_debug("zdoor_fattach(CHILD): zone_enter fail %s",
203 203 strerror(errno));
204 204 if (errno == EINVAL) {
205 205 _exit(0);
206 206 }
207 207 _exit(1);
208 208 }
209 209 (void) fdetach(path);
210 210 (void) unlink(path);
211 211 if (detach_only) {
212 212 zdoor_debug("zdoor_fattach(CHILD): detach only, done");
213 213 _exit(0);
214 214 }
215 215 fd = open(path, O_CREAT|O_RDWR, 0644);
216 216 if (fd < 0) {
217 217 zdoor_debug("zdoor_fattach(CHILD): open failed: %s",
218 218 strerror(errno));
219 219 _exit(2);
220 220 }
221 221 if (fattach(door, path) != 0) {
222 222 zdoor_debug("zdoor_fattach(CHILD): fattach failed: %s",
223 223 strerror(errno));
224 224 _exit(3);
225 225 }
226 226 _exit(0);
227 227 }
228 228 if (contract_latest(&ct) == -1)
229 229 ct = -1;
230 230 (void) ct_tmpl_clear(tmpl_fd);
231 231 (void) close(tmpl_fd);
232 232 (void) contract_abandon_id(ct);
233 233
234 234 zdoor_debug("zdoor_fattach: waiting for child...");
235 235 while (waitpid(pid, &stat, 0) != pid)
236 236 ;
237 237 if (WIFEXITED(stat) && WEXITSTATUS(stat) == 0) {
238 238 zdoor_debug(" child exited with success");
239 239 zdoor_debug("zdoor_fattach: returning ZDOOR_OK");
240 240 return (ZDOOR_OK);
241 241 }
242 242
243 243 zdoor_debug(" child exited with %d", WEXITSTATUS(stat));
244 244 zdoor_debug("zdoor_fattach: returning ZDOOR_ERROR");
245 245 return (ZDOOR_ERROR);
246 246 }
247 247
248 248 /*
249 249 * zdoor_zone_is_running(zone) returns 1 if the specified zone is running, or 0
250 250 * if it is any other state. It additionally eats any other errors it
251 251 * encounters and returns 0 upon encountering them.
252 252 */
253 253 boolean_t
254 254 zdoor_zone_is_running(zoneid_t zoneid)
255 255 {
256 256 zone_state_t state;
257 257 char zone[ZONENAME_MAX];
258 258 if (zoneid < 0)
259 259 return (B_FALSE);
260 260
261 261 if (getzonenamebyid(zoneid, zone, ZONENAME_MAX) < 0)
262 262 return (B_FALSE);
263 263
264 264 if (!zone_get_state((char *)zone, &state) == Z_OK)
265 265 return (B_FALSE);
266 266
267 267 return (state == ZONE_STATE_RUNNING);
268 268 }
269 269
270 270 /*
271 271 * zdoor_cookie_create simply allocates and initializes
272 272 * memory. Returns NULL on any error.
273 273 */
274 274 zdoor_cookie_t *
275 275 zdoor_cookie_create(const char *zonename, const char *service,
276 276 const void *biscuit)
277 277 {
278 278 zdoor_cookie_t *cookie = NULL;
279 279
280 280 if (zonename == NULL || service == NULL)
281 281 return (NULL);
282 282
283 283 cookie = (zdoor_cookie_t *)calloc(1, sizeof (zdoor_cookie_t));
284 284 if (cookie == NULL) {
285 285 OUT_OF_MEMORY();
286 286 return (NULL);
287 287 }
288 288 cookie->zdc_biscuit = (void *)biscuit;
289 289 cookie->zdc_zonename = strdup((char *)zonename);
290 290 if (cookie->zdc_zonename == NULL) {
291 291 zdoor_cookie_free(cookie);
292 292 OUT_OF_MEMORY();
293 293 return (NULL);
294 294 }
295 295 cookie->zdc_service = strdup((char *)service);
296 296 if (cookie->zdc_service == NULL) {
297 297 zdoor_cookie_free(cookie);
298 298 OUT_OF_MEMORY();
299 299 return (NULL);
300 300 }
301 301
302 302 return (cookie);
303 303 }
304 304
305 305 /*
306 306 * zdoor_cookie_free(cookie) cleans up any memory associated with the
307 307 * specified cookie.
308 308 */
309 309 void
310 310 zdoor_cookie_free(zdoor_cookie_t *cookie)
311 311 {
312 312 if (cookie == NULL)
313 313 return;
314 314
315 315 if (cookie->zdc_zonename != NULL) {
316 316 free(cookie->zdc_zonename);
317 317 cookie->zdc_zonename = NULL;
318 318 }
319 319
320 320 if (cookie->zdc_service != NULL) {
321 321 free(cookie->zdc_service);
322 322 cookie->zdc_service = NULL;
323 323 }
324 324
325 325 free(cookie);
326 326 }
↓ open down ↓ |
144 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX