Print this page
10133 smatch fixes for usr/src/cmd/fs.d
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fs.d/reparsed/reparsed.c
+++ new/usr/src/cmd/fs.d/reparsed/reparsed.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
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 + * Copyright (c) 2018, Joyent, Inc.
28 + */
29 +
30 +/*
27 31 * Reparsed daemon
28 32 */
29 33
30 34 #include <stdio.h>
31 35 #include <stdio_ext.h>
32 36 #include <stdlib.h>
33 37 #include <unistd.h>
34 38 #include <signal.h>
35 39 #include <sys/types.h>
36 40 #include <sys/stat.h>
37 41 #include <fcntl.h>
38 42 #include <memory.h>
39 43 #include <alloca.h>
40 44 #include <ucontext.h>
41 45 #include <errno.h>
42 46 #include <syslog.h>
43 47 #include <string.h>
44 48 #include <strings.h>
45 49 #include <door.h>
46 50 #include <wait.h>
47 51 #include <libintl.h>
48 52 #include <locale.h>
49 53 #include <sys/param.h>
50 54 #include <sys/systeminfo.h>
51 55 #include <sys/thread.h>
52 56 #include <rpc/xdr.h>
53 57 #include <priv.h>
54 58 #include <sys/fs_reparse.h>
55 59 #include <priv_utils.h>
56 60 #include <rpcsvc/daemon_utils.h>
57 61
58 62 #define REPARSED_CMD_OPTS "v"
59 63 #define DOOR_RESULT_BUFSZ (MAXPATHLEN + sizeof (reparsed_door_res_t))
60 64 #define SAFETY_BUFFER 8*1024
61 65
62 66 static char *MyName;
63 67 static int verbose = 0;
64 68
65 69 static int start_reparsed_svcs();
66 70 static void daemonize(void);
67 71 static void reparsed_door_call_error(int error, int buflen);
68 72 static void reparsed_doorfunc(void *cookie, char *argp, size_t arg_size,
69 73 door_desc_t *dp, uint_t n_desc);
70 74
71 75 static void
72 76 usage()
73 77 {
74 78 syslog(LOG_ERR, "Usage: %s", MyName);
75 79 syslog(LOG_ERR, "\t[-v]\t\tverbose error messages)");
76 80 exit(1);
77 81 }
78 82
79 83 static void
80 84 warn_hup(int i)
81 85 {
82 86 syslog(LOG_ERR, "SIGHUP received: ignored");
83 87 (void) signal(SIGHUP, warn_hup);
84 88 }
85 89
86 90 /*
87 91 * Processing for daemonization
88 92 */
89 93 static void
90 94 daemonize(void)
91 95 {
92 96 switch (fork()) {
93 97 case -1:
94 98 syslog(LOG_ERR, "reparsed: can't fork - errno %d", errno);
95 99 exit(2);
96 100 /* NOTREACHED */
97 101 case 0: /* child */
98 102 break;
99 103
100 104 default: /* parent */
101 105 _exit(0);
102 106 }
103 107 (void) chdir("/");
104 108
105 109 /*
106 110 * Close stdin, stdout, and stderr.
107 111 * Open again to redirect input+output
108 112 */
109 113 (void) close(0);
110 114 (void) close(1);
111 115 (void) close(2);
112 116 (void) open("/dev/null", O_RDONLY);
113 117 (void) open("/dev/null", O_WRONLY);
114 118 (void) dup(1);
115 119 (void) setsid();
116 120 }
117 121
118 122 int
119 123 main(int argc, char *argv[])
120 124 {
121 125 pid_t pid;
122 126 int c, error;
123 127 struct rlimit rlset;
124 128 char *defval;
125 129
126 130 /*
127 131 * There is no check for non-global zone and Trusted Extensions.
128 132 * Reparsed works in both of these environments as long as the
129 133 * services that use reparsed are supported.
130 134 */
131 135
132 136 MyName = argv[0];
133 137 if (geteuid() != 0) {
134 138 syslog(LOG_ERR, "%s must be run as root", MyName);
135 139 exit(1);
136 140 }
137 141
138 142 while ((c = getopt(argc, argv, REPARSED_CMD_OPTS)) != EOF) {
139 143 switch (c) {
140 144 case 'v':
141 145 verbose++;
142 146 break;
143 147 default:
144 148 usage();
145 149 }
146 150 }
147 151
148 152 daemonize();
149 153 openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);
150 154
151 155 (void) _create_daemon_lock(REPARSED, DAEMON_UID, DAEMON_GID);
152 156 (void) enable_extended_FILE_stdio(-1, -1);
153 157 switch (_enter_daemon_lock(REPARSED)) {
154 158 case 0:
155 159 break;
156 160 case -1:
157 161 syslog(LOG_ERR, "Error locking for %s", REPARSED);
158 162 exit(2);
159 163 default:
160 164 /* daemon was already running */
161 165 exit(0);
162 166 }
163 167
164 168 (void) signal(SIGHUP, warn_hup);
165 169
166 170 /*
167 171 * Make the process a privilege aware daemon.
168 172 * Only "basic" privileges are required.
169 173 *
170 174 */
171 175 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
172 176 (char *)NULL) == -1) {
173 177 syslog(LOG_ERR, "should be run with sufficient privileges");
174 178 exit(3);
175 179 }
176 180
177 181 /*
178 182 * Clear basic privileges not required by reparsed.
179 183 */
180 184 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
181 185 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);
182 186
183 187 return (start_reparsed_svcs());
↓ open down ↓ |
147 lines elided |
↑ open up ↑ |
184 188 }
185 189
186 190 static void
187 191 reparsed_door_call_error(int error, int buflen)
188 192 {
189 193 reparsed_door_res_t rpd_res;
190 194
191 195 memset(&rpd_res, 0, sizeof (reparsed_door_res_t));
192 196 rpd_res.res_status = error;
193 197 rpd_res.res_len = buflen;
194 - door_return((char *)&rpd_res, sizeof (reparsed_door_res_t), NULL, 0);
198 + (void) door_return((char *)&rpd_res,
199 + sizeof (reparsed_door_res_t), NULL, 0);
195 200
196 201 (void) door_return(NULL, 0, NULL, 0);
197 - /* NOTREACHED */
202 + abort();
198 203 }
199 204
200 205 /*
201 206 * reparsed_doorfunc
202 207 *
203 208 * argp: "service_type:service_data" string
204 209 * dp & n_desc: not used.
205 210 */
206 211 static void
207 212 reparsed_doorfunc(void *cookie, char *argp, size_t arg_size,
208 213 door_desc_t *dp, uint_t n_desc)
209 214 {
210 215 int err;
211 216 size_t bufsz;
212 217 char *svc_type, *svc_data;
213 218 char *cp, *buf, *sbuf, res_buf[DOOR_RESULT_BUFSZ];
214 219 reparsed_door_res_t *resp;
215 220
216 221 if ((argp == NULL) || (arg_size == 0)) {
217 222 reparsed_door_call_error(EINVAL, 0);
218 223 /* NOTREACHED */
219 224 }
220 225
221 226 if (verbose)
222 227 syslog(LOG_NOTICE, "reparsed_door: [%s, %d]", argp, arg_size);
223 228
224 229 if ((svc_type = strdup(argp)) == NULL) {
225 230 reparsed_door_call_error(ENOMEM, 0);
226 231 /* NOTREACHED */
227 232 }
228 233
229 234 /*
230 235 * Door argument string comes in "service_type:service_data" format.
231 236 * Need to break it into separate "service_type" and "service_data"
232 237 * string before passing them to reparse_deref() to process them.
233 238 */
234 239 if ((cp = strchr(svc_type, ':')) == NULL) {
235 240 free(svc_type);
236 241 reparsed_door_call_error(EINVAL, 0);
237 242 /* NOTREACHED */
238 243 }
239 244 *cp++ = '\0';
240 245 svc_data = cp;
241 246
242 247 /*
243 248 * Setup buffer for reparse_deref(). 'bufsz' is the actual
244 249 * buffer size to hold the result returned by reparse_deref().
245 250 */
246 251 resp = (reparsed_door_res_t *)res_buf;
247 252 buf = resp->res_data;
248 253 bufsz = sizeof (res_buf) - sizeof (reparsed_door_res_t);
249 254
250 255 /*
251 256 * reparse_deref() calls the service type plugin library to process
252 257 * the service data. The plugin library function should understand
253 258 * the context of the service data and should be the one to XDR the
254 259 * results before returning it to the caller.
255 260 */
256 261 err = reparse_deref(svc_type, svc_data, buf, &bufsz);
257 262
258 263 if (verbose)
259 264 syslog(LOG_NOTICE,
260 265 "reparsed_deref(svc_type: %s, data: %s, size: %d) -> %d",
261 266 svc_type, svc_data, bufsz, err);
262 267
263 268 switch (err) {
264 269 case 0:
265 270 break;
266 271
267 272 case EOVERFLOW:
268 273 /*
269 274 * bufsz was returned with size needed by reparse_deref().
270 275 *
271 276 * We cannot use malloc() here because door_return() never
272 277 * returns, and memory allocated by malloc() would get leaked.
273 278 */
274 279 sbuf = alloca(bufsz + sizeof (reparsed_door_res_t));
275 280 if (sbuf == NULL || stack_inbounds(buf) == 0 ||
276 281 stack_inbounds(buf + sizeof (reparsed_door_res_t) +
277 282 SAFETY_BUFFER - 1) == 0) {
278 283 free(svc_type);
279 284 reparsed_door_call_error(ENOMEM, 0);
280 285 /* NOTREACHED */
281 286 }
282 287
283 288 resp = (reparsed_door_res_t *)sbuf;
284 289 if ((err = reparse_deref(svc_type, svc_data, resp->res_data,
285 290 &bufsz)) == 0)
286 291 break;
287 292
288 293 /* fall through */
289 294
290 295 default:
291 296 free(svc_type);
292 297 reparsed_door_call_error(err, 0);
293 298 /* NOTREACHED */
294 299 }
295 300
296 301 free(svc_type);
297 302
298 303 if (verbose)
299 304 syslog(LOG_NOTICE, "reparsed_door_return <buf=%s> size=%d",
300 305 buf, bufsz);
301 306
302 307 resp->res_status = 0;
303 308 resp->res_len = bufsz;
304 309 (void) door_return((char *)resp, bufsz + sizeof (reparsed_door_res_t),
305 310 NULL, 0);
306 311
307 312 (void) door_return(NULL, 0, NULL, 0);
308 313 /* NOTREACHED */
309 314 }
310 315
311 316 static int
312 317 start_reparsed_svcs()
313 318 {
314 319 int doorfd;
315 320 int dfd;
316 321
317 322 if ((doorfd = door_create(reparsed_doorfunc, NULL,
318 323 DOOR_REFUSE_DESC|DOOR_NO_CANCEL)) == -1) {
319 324 syslog(LOG_ERR, "Unable to create door");
320 325 return (1);
321 326 }
322 327
323 328 /*
324 329 * Create a file system path for the door
325 330 */
326 331 if ((dfd = open(REPARSED_DOOR, O_RDWR|O_CREAT|O_TRUNC,
327 332 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
328 333 syslog(LOG_ERR, "unable to open %s", REPARSED_DOOR);
329 334 (void) close(doorfd);
330 335 return (1);
331 336 }
332 337
333 338 /*
334 339 * Clean up any stale associations
335 340 */
336 341 (void) fdetach(REPARSED_DOOR);
337 342
338 343 /*
339 344 * Register in the kernel namespace for door_ki_open().
340 345 */
341 346 if (fattach(doorfd, REPARSED_DOOR) == -1) {
342 347 syslog(LOG_ERR, "Unable to fattach door %s", REPARSED_DOOR);
343 348 (void) close(doorfd);
344 349 (void) close(dfd);
345 350 return (1);
346 351 }
347 352 (void) close(dfd);
348 353
349 354 /*
350 355 * Wait for incoming calls
351 356 */
352 357 /*CONSTCOND*/
353 358 while (1)
354 359 (void) pause();
355 360
356 361 syslog(LOG_ERR, "Door server exited");
357 362 return (10);
358 363 }
↓ open down ↓ |
151 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX