clang -cc1 -cc1 -triple i386-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cmd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -target-cpu i586 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/stand/cdboot/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -D MDRANDOM -D _STANDALONE -D __INTERNAL_LIBSA_CREAD -D OSREV="7.0" -D MACHINE="amd64" -D KERNEL="/7.0/amd64/bsd.rd" -I /usr/src/sys/arch/amd64/stand/cdboot/../../../.. -I /usr/src/sys/arch/amd64/stand/cdboot/../libsa -I . -I /usr/src/sys/arch/amd64/stand/cdboot -D SOFTRAID -D BOOTMAGIC=0xc001d00d -D LINKADDR=0x40120 -D SLOW -D SMALL -D NOBYFOUR -D NO_GZIP -D DYNAMIC_CRC_TABLE -D BUILDFIXED -I /usr/src/sys/arch/amd64/stand/cdboot/../../../../stand/boot -Oz -fdebug-compilation-dir=/usr/src/sys/arch/amd64/stand/cdboot/obj -ferror-limit 19 -fwrapv -fno-builtin -fgnuc-version=4.2.1 -fpack-struct=1 -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sys/arch/amd64/stand/cdboot/../../../../stand/boot/cmd.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | #include <sys/param.h> |
30 | #include <sys/reboot.h> |
31 | |
32 | #include <libsa.h> |
33 | #include <lib/libkern/funcs.h> |
34 | |
35 | #include "cmd.h" |
36 | |
37 | #define CTRL(c) ((c)&0x1f) |
38 | |
39 | static int Xboot(void); |
40 | static int Xecho(void); |
41 | static int Xhelp(void); |
42 | static int Xhexdump(void); |
43 | static int Xls(void); |
44 | static int Xnop(void); |
45 | static int Xreboot(void); |
46 | static int Xstty(void); |
47 | static int Xtime(void); |
48 | #ifdef MACHINE_CMD |
49 | static int Xmachine(void); |
50 | extern const struct cmd_table MACHINE_CMD[]; |
51 | #endif |
52 | extern int Xset(void); |
53 | extern int Xenv(void); |
54 | |
55 | #ifdef CHECK_SKIP_CONF |
56 | extern int CHECK_SKIP_CONF(void); |
57 | #endif |
58 | |
59 | extern const struct cmd_table cmd_set[]; |
60 | const struct cmd_table cmd_table[] = { |
61 | {"#", CMDT_CMD, Xnop}, |
62 | {"boot", CMDT_CMD, Xboot}, |
63 | {"echo", CMDT_CMD, Xecho}, |
64 | {"env", CMDT_CMD, Xenv}, |
65 | {"help", CMDT_CMD, Xhelp}, |
66 | {"hexdump",CMDT_CMD, Xhexdump}, |
67 | {"ls", CMDT_CMD, Xls}, |
68 | #ifdef MACHINE_CMD |
69 | {"machine",CMDT_MDC, Xmachine}, |
70 | #endif |
71 | {"reboot", CMDT_CMD, Xreboot}, |
72 | {"set", CMDT_SET, Xset}, |
73 | {"stty", CMDT_CMD, Xstty}, |
74 | {"time", CMDT_CMD, Xtime}, |
75 | {NULL, 0}, |
76 | }; |
77 | |
78 | static void ls(char *, struct stat *); |
79 | static int readline(char *, size_t, int); |
80 | char *nextword(char *); |
81 | static char *whatcmd(const struct cmd_table **ct, char *); |
82 | static char *qualify(char *); |
83 | |
84 | char cmd_buf[CMD_BUFF_SIZE]; |
85 | |
86 | int |
87 | getcmd(void) |
88 | { |
89 | cmd.cmd = NULL; |
90 | |
91 | if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout)) |
92 | cmd.cmd = cmd_table; |
93 | |
94 | return docmd(); |
95 | } |
96 | |
97 | int |
98 | read_conf(void) |
99 | { |
100 | #ifndef INSECURE |
101 | struct stat sb; |
102 | #endif |
103 | int fd, rc = 0; |
104 | |
105 | #ifdef CHECK_SKIP_CONF |
106 | if (CHECK_SKIP_CONF()) { |
107 | printf("boot.conf processing skipped at operator request\n"); |
108 | cmd.timeout = 0; |
109 | return -1; |
110 | } |
111 | #endif |
112 | |
113 | if ((fd = open(qualify(cmd.conf), O_RDONLY)) < 0) { |
114 | if (errno != ENOENT && errno != ENXIO) { |
115 | printf("open(%s): %s\n", cmd.path, strerror(errno)); |
116 | return 0; |
117 | } |
118 | return -1; |
119 | } |
120 | |
121 | #ifndef INSECURE |
122 | (void) fstat(fd, &sb); |
123 | if (sb.st_uid || (sb.st_mode & 2)) { |
124 | printf("non-secure %s, will not proceed\n", cmd.path); |
125 | close(fd); |
126 | return -1; |
127 | } |
128 | #endif |
129 | |
130 | do { |
131 | char *p = cmd_buf; |
132 | |
133 | cmd.cmd = NULL; |
134 | do { |
135 | rc = read(fd, p, 1); |
136 | } while (rc > 0 && *p++ != '\n' && |
137 | (p-cmd_buf) < sizeof(cmd_buf)); |
138 | |
139 | if (rc < 0) { |
140 | printf("%s: %s\n", cmd.path, strerror(errno)); |
141 | break; |
142 | } |
143 | |
144 | if (rc == 0) { |
145 | if (p != cmd_buf) { |
146 | *p = '\0'; |
147 | rc = docmd(); |
148 | break; |
149 | } |
150 | } else { |
151 | p--; |
152 | |
153 | if (*p != '\n') { |
154 | printf("%s: line too long\n", cmd.path); |
155 | |
156 | |
157 | rc = -1; |
158 | } |
159 | *p = '\0'; |
160 | } |
161 | } while (rc > 0 && !(rc = docmd())); |
162 | |
163 | close(fd); |
164 | return rc; |
165 | } |
166 | |
167 | int |
168 | docmd(void) |
169 | { |
170 | char *p = NULL; |
171 | const struct cmd_table *ct = cmd_table, *cs; |
172 | |
173 | cmd.argc = 1; |
174 | if (cmd.cmd == NULL) { |
175 | |
176 | |
177 | for (p = cmd_buf; *p == ' ' || *p == '\t'; p++) |
178 | ; |
179 | if (*p == '#' || *p == '\0') { |
180 | #ifdef DEBUG |
181 | printf("rem\n"); |
182 | #endif |
183 | return 0; |
184 | } |
185 | ct = cmd_table; |
186 | cs = NULL; |
187 | cmd.argv[cmd.argc] = p; |
188 | p = whatcmd(&ct, p); |
189 | if (ct == NULL) { |
190 | cmd.argc++; |
191 | ct = cmd_table; |
192 | } else if (ct->cmd_type == CMDT_SET && p != NULL) { |
193 | cs = cmd_set; |
194 | #ifdef MACHINE_CMD |
195 | } else if (ct->cmd_type == CMDT_MDC && p != NULL) { |
196 | cs = MACHINE_CMD; |
197 | #endif |
198 | } |
199 | |
200 | if (cs != NULL) { |
201 | p = whatcmd(&cs, p); |
202 | if (cs == NULL) { |
203 | printf("%s: syntax error\n", ct->cmd_name); |
204 | return 0; |
205 | } |
206 | ct = cs; |
207 | } |
208 | cmd.cmd = ct; |
209 | } |
210 | |
211 | cmd.argv[0] = ct->cmd_name; |
212 | while (p && cmd.argc+1 < sizeof(cmd.argv) / sizeof(cmd.argv[0])) { |
213 | cmd.argv[cmd.argc++] = p; |
214 | p = nextword(p); |
215 | } |
216 | cmd.argv[cmd.argc] = NULL; |
217 | |
218 | return (*cmd.cmd->cmd_exec)(); |
219 | } |
220 | |
221 | static char * |
222 | whatcmd(const struct cmd_table **ct, char *p) |
223 | { |
224 | char *q; |
225 | int l; |
226 | |
227 | q = nextword(p); |
228 | |
229 | for (l = 0; p[l]; l++) |
230 | ; |
231 | |
232 | while ((*ct)->cmd_name != NULL && strncmp(p, (*ct)->cmd_name, l)) |
233 | (*ct)++; |
234 | |
235 | if ((*ct)->cmd_name == NULL) |
236 | *ct = NULL; |
237 | |
238 | return q; |
239 | } |
240 | |
241 | static int |
242 | readline(char *buf, size_t n, int to) |
243 | { |
244 | #ifdef DEBUG |
245 | extern int debug; |
246 | #endif |
247 | char *p = buf, ch; |
248 | |
249 | |
250 | if (to > 0) { |
251 | u_long i = 0; |
252 | time_t tt = getsecs() + to; |
253 | #ifdef DEBUG |
254 | if (debug > 2) |
255 | printf ("readline: timeout(%d) at %u\n", to, tt); |
256 | #endif |
257 | |
258 | |
259 | while (!cnischar()) |
260 | if (!(i++ % 1000) && (getsecs() >= tt)) |
261 | break; |
262 | |
263 | if (!cnischar()) { |
264 | strlcpy(buf, "boot", 5); |
265 | putchar('\n'); |
266 | return strlen(buf); |
267 | } |
268 | } else |
269 | while (!cnischar()) |
270 | ; |
271 | |
272 | |
273 | cmd.timeout = 0; |
274 | |
275 | while (1) { |
276 | switch ((ch = getchar())) { |
277 | case CTRL('u'): |
278 | while (p > buf) { |
279 | putchar('\177'); |
280 | p--; |
281 | } |
282 | continue; |
283 | case '\n': |
284 | case '\r': |
285 | *p = '\0'; |
286 | break; |
287 | case '\b': |
288 | case '\177': |
289 | if (p > buf) { |
290 | putchar('\177'); |
291 | p--; |
292 | } |
293 | continue; |
294 | default: |
295 | if (ch >= ' ' && ch < '\177') { |
296 | if (p - buf < n-1) |
297 | *p++ = ch; |
298 | else { |
299 | putchar('\007'); |
300 | putchar('\177'); |
301 | } |
302 | } |
303 | continue; |
304 | } |
305 | break; |
306 | } |
307 | |
308 | return p - buf; |
309 | } |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | char * |
317 | nextword(char *p) |
318 | { |
319 | |
320 | while (*p && *p != '\t' && *p != ' ') |
321 | p++; |
322 | if (*p) { |
323 | *p++ = '\0'; |
324 | while (*p == '\t' || *p == ' ') |
325 | p++; |
326 | } |
327 | if (*p == '\0') |
328 | p = NULL; |
329 | return p; |
330 | } |
331 | |
332 | static void |
333 | print_help(const struct cmd_table *ct) |
334 | { |
335 | for (; ct->cmd_name != NULL; ct++) |
336 | printf(" %s", ct->cmd_name); |
337 | putchar('\n'); |
338 | } |
339 | |
340 | static int |
341 | Xhelp(void) |
342 | { |
343 | printf("commands:"); |
344 | print_help(cmd_table); |
345 | #ifdef MACHINE_CMD |
346 | return Xmachine(); |
347 | #else |
348 | return 0; |
349 | #endif |
350 | } |
351 | |
352 | static int |
353 | Xhexdump(void) |
354 | { |
355 | long long val[2]; |
356 | char *ep; |
357 | int i; |
358 | |
359 | if (cmd.argc != 3) { |
| 1 | Assuming field 'argc' is equal to 3 | |
|
| |
360 | printf("hexdump addr size\n"); |
361 | return 0; |
362 | } |
363 | |
364 | for (i = 1; i < cmd.argc; i++) { |
| 3 | | Loop condition is true. Entering loop body | |
|
| 7 | | Assuming 'i' is >= field 'argc' | |
|
| 8 | | Loop condition is false. Execution continues on line 371 | |
|
365 | val[i-1] = strtoll(cmd.argv[i], &ep, 0); |
366 | if (cmd.argv[i][0] == '\0' || *ep != '\0') { |
| 4 | | Assuming the condition is false | |
|
| 5 | | Assuming the condition is false | |
|
| |
367 | printf("bad '%c' in \"%s\"\n", *ep, cmd.argv[i]); |
368 | return 0; |
369 | } |
370 | } |
371 | hexdump((void *)(unsigned long)val[0], val[1]); |
| 9 | | 2nd function call argument is an uninitialized value |
|
372 | return 0; |
373 | } |
374 | |
375 | #ifdef MACHINE_CMD |
376 | static int |
377 | Xmachine(void) |
378 | { |
379 | printf("machine:"); |
380 | print_help(MACHINE_CMD); |
381 | return 0; |
382 | } |
383 | #endif |
384 | |
385 | static int |
386 | Xecho(void) |
387 | { |
388 | int i; |
389 | |
390 | for (i = 1; i < cmd.argc; i++) |
391 | printf("%s ", cmd.argv[i]); |
392 | putchar('\n'); |
393 | return 0; |
394 | } |
395 | |
396 | static int |
397 | Xstty(void) |
398 | { |
399 | int sp; |
400 | char *cp; |
401 | dev_t dev; |
402 | |
403 | if (cmd.argc == 1) { |
404 | printf("%s speed is %d\n", ttyname(0), cnspeed(0, -1)); |
405 | return 0; |
406 | } |
407 | dev = ttydev(cmd.argv[1]); |
408 | if (dev == NODEV) { |
409 | printf("%s not a console device\n", cmd.argv[1]); |
410 | return 0; |
411 | } |
412 | |
413 | if (cmd.argc == 2) |
414 | printf("%s speed is %d\n", cmd.argv[1], |
415 | cnspeed(dev, -1)); |
416 | else { |
417 | sp = 0; |
418 | for (cp = cmd.argv[2]; isdigit(*cp); cp++) |
419 | sp = sp * 10 + (*cp - '0'); |
420 | cnspeed(dev, sp); |
421 | } |
422 | return 0; |
423 | } |
424 | |
425 | static int |
426 | Xtime(void) |
427 | { |
428 | time_t tt = getsecs(); |
429 | |
430 | if (cmd.argc == 1) |
431 | printf(ctime(&tt)); |
432 | |
433 | return 0; |
434 | } |
435 | |
436 | static int |
437 | Xls(void) |
438 | { |
439 | struct stat sb; |
440 | char *p; |
441 | int fd; |
442 | |
443 | if (stat(qualify((cmd.argv[1]? cmd.argv[1]: "/.")), &sb) < 0) { |
444 | printf("stat(%s): %s\n", cmd.path, strerror(errno)); |
445 | return 0; |
446 | } |
447 | |
448 | if ((sb.st_mode & S_IFMT) != S_IFDIR) |
449 | ls(cmd.path, &sb); |
450 | else { |
451 | if ((fd = opendir(cmd.path)) < 0) { |
452 | printf("opendir(%s): %s\n", cmd.path, |
453 | strerror(errno)); |
454 | return 0; |
455 | } |
456 | |
457 | |
458 | for (p = cmd.path; *p; p++) |
459 | ; |
460 | *p++ = '/'; |
461 | *p = '\0'; |
462 | |
463 | while (readdir(fd, p) >= 0) { |
464 | if (stat(cmd.path, &sb) < 0) |
465 | printf("stat(%s): %s\n", cmd.path, |
466 | strerror(errno)); |
467 | else |
468 | ls(p, &sb); |
469 | } |
470 | closedir (fd); |
471 | } |
472 | return 0; |
473 | } |
474 | |
475 | #define lsrwx(mode,s) \ |
476 | putchar ((mode) & S_IROTH? 'r' : '-'); \ |
477 | putchar ((mode) & S_IWOTH? 'w' : '-'); \ |
478 | putchar ((mode) & S_IXOTH? *(s): (s)[1]); |
479 | |
480 | static void |
481 | ls(char *name, struct stat *sb) |
482 | { |
483 | putchar("-fc-d-b---l-s-w-"[(sb->st_mode & S_IFMT) >> 12]); |
484 | lsrwx(sb->st_mode >> 6, (sb->st_mode & S_ISUID? "sS" : "x-")); |
485 | lsrwx(sb->st_mode >> 3, (sb->st_mode & S_ISGID? "sS" : "x-")); |
486 | lsrwx(sb->st_mode , (sb->st_mode & S_ISTXT? "tT" : "x-")); |
487 | |
488 | printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid, |
489 | (u_long)sb->st_size, name); |
490 | } |
491 | #undef lsrwx |
492 | |
493 | int doboot = 1; |
494 | |
495 | static int |
496 | Xnop(void) |
497 | { |
498 | if (doboot) { |
499 | doboot = 0; |
500 | return (Xboot()); |
501 | } |
502 | |
503 | return 0; |
504 | } |
505 | |
506 | static int |
507 | Xboot(void) |
508 | { |
509 | if (cmd.argc > 1 && cmd.argv[1][0] != '-') { |
510 | qualify((cmd.argv[1]? cmd.argv[1]: cmd.image)); |
511 | if (bootparse(2)) |
512 | return 0; |
513 | } else { |
514 | if (bootparse(1)) |
515 | return 0; |
516 | snprintf(cmd.path, sizeof cmd.path, "%s:%s", |
517 | cmd.bootdev, cmd.image); |
518 | } |
519 | |
520 | return 1; |
521 | } |
522 | |
523 | |
524 | |
525 | |
526 | |
527 | static char * |
528 | qualify(char *name) |
529 | { |
530 | char *p; |
531 | |
532 | for (p = name; *p; p++) |
533 | if (*p == ':') |
534 | break; |
535 | if (*p == ':') |
536 | strlcpy(cmd.path, name, sizeof(cmd.path)); |
537 | else |
538 | snprintf(cmd.path, sizeof cmd.path, "%s:%s", |
539 | cmd.bootdev, name); |
540 | return cmd.path; |
541 | } |
542 | |
543 | static int |
544 | Xreboot(void) |
545 | { |
546 | printf("Rebooting...\n"); |
547 | exit(); |
548 | return 0; |
549 | } |
550 | |
551 | int |
552 | upgrade(void) |
553 | { |
554 | struct stat sb; |
555 | |
556 | if (stat(qualify(("/bsd.upgrade")), &sb) < 0) |
557 | return 0; |
558 | if ((sb.st_mode & S_IXUSR) == 0) { |
559 | printf("/bsd.upgrade is not u+x\n"); |
560 | return 0; |
561 | } |
562 | return 1; |
563 | } |