clang -cc1 -cc1 -triple i386-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cmd.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -target-cpu i586 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/stand/boot/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -D MDRANDOM -D BOOT_STTY -D _STANDALONE -D __INTERNAL_LIBSA_CREAD -I /usr/src/sys/arch/amd64/stand/boot/../../../.. -I /usr/src/sys/arch/amd64/stand/boot/../libsa -I . -I /usr/src/sys/arch/amd64/stand/boot -D SOFTRAID -D BOOTMAGIC=0xc001d00d -D LINKADDR=0x40120 -D SLOW -D SMALL -D NOBYFOUR -D NO_GZIP -D DYNAMIC_CRC_TABLE -D BUILDFIXED -D HIBERNATE -D HEAP_LIMIT=0xA0000 -I /usr/src/sys/arch/amd64/stand/boot/../../../../stand/boot -Oz -fdebug-compilation-dir=/usr/src/sys/arch/amd64/stand/boot/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/scan/2024-01-11-140451-98009-1 -x c /usr/src/sys/arch/amd64/stand/boot/../../../../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 | #ifdef BOOT_STTY |
47 | static int Xstty(void); |
48 | #endif |
49 | static int Xtime(void); |
50 | #ifdef MACHINE_CMD |
51 | static int Xmachine(void); |
52 | extern const struct cmd_table MACHINE_CMD[]; |
53 | #endif |
54 | extern int Xset(void); |
55 | extern int Xenv(void); |
56 | |
57 | #ifdef CHECK_SKIP_CONF |
58 | extern int CHECK_SKIP_CONF(void); |
59 | #endif |
60 | |
61 | extern const struct cmd_table cmd_set[]; |
62 | const struct cmd_table cmd_table[] = { |
63 | {"#", CMDT_CMD, Xnop}, |
64 | {"boot", CMDT_CMD, Xboot}, |
65 | {"echo", CMDT_CMD, Xecho}, |
66 | {"env", CMDT_CMD, Xenv}, |
67 | {"help", CMDT_CMD, Xhelp}, |
68 | {"hexdump",CMDT_CMD, Xhexdump}, |
69 | {"ls", CMDT_CMD, Xls}, |
70 | #ifdef MACHINE_CMD |
71 | {"machine",CMDT_MDC, Xmachine}, |
72 | #endif |
73 | {"reboot", CMDT_CMD, Xreboot}, |
74 | {"set", CMDT_SET, Xset}, |
75 | #ifdef BOOT_STTY |
76 | {"stty", CMDT_CMD, Xstty}, |
77 | #endif |
78 | {"time", CMDT_CMD, Xtime}, |
79 | {NULL, 0}, |
80 | }; |
81 | |
82 | static void ls(char *, struct stat *); |
83 | static int readline(char *, size_t, int); |
84 | char *nextword(char *); |
85 | static char *whatcmd(const struct cmd_table **ct, char *); |
86 | static char *qualify(char *); |
87 | |
88 | char cmd_buf[CMD_BUFF_SIZE]; |
89 | |
90 | int |
91 | getcmd(void) |
92 | { |
93 | cmd.cmd = NULL; |
94 | |
95 | if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout)) |
96 | cmd.cmd = cmd_table; |
97 | |
98 | return docmd(); |
99 | } |
100 | |
101 | int |
102 | read_conf(void) |
103 | { |
104 | #ifndef INSECURE |
105 | struct stat sb; |
106 | #endif |
107 | int fd, rc = 0; |
108 | |
109 | #ifdef CHECK_SKIP_CONF |
110 | if (CHECK_SKIP_CONF()) { |
111 | printf("boot.conf processing skipped at operator request\n"); |
112 | cmd.timeout = 0; |
113 | return -1; |
114 | } |
115 | #endif |
116 | |
117 | if ((fd = open(qualify(cmd.conf), O_RDONLY)) < 0) { |
118 | if (errno != ENOENT && errno != ENXIO) { |
119 | printf("open(%s): %s\n", cmd.path, strerror(errno)); |
120 | return 0; |
121 | } |
122 | return -1; |
123 | } |
124 | |
125 | #ifndef INSECURE |
126 | (void) fstat(fd, &sb); |
127 | if (sb.st_uid || (sb.st_mode & 2)) { |
128 | printf("non-secure %s, will not proceed\n", cmd.path); |
129 | close(fd); |
130 | return -1; |
131 | } |
132 | #endif |
133 | |
134 | do { |
135 | char *p = cmd_buf; |
136 | |
137 | cmd.cmd = NULL; |
138 | do { |
139 | rc = read(fd, p, 1); |
140 | } while (rc > 0 && *p++ != '\n' && |
141 | (p-cmd_buf) < sizeof(cmd_buf)); |
142 | |
143 | if (rc < 0) { |
144 | printf("%s: %s\n", cmd.path, strerror(errno)); |
145 | break; |
146 | } |
147 | |
148 | if (rc == 0) { |
149 | if (p != cmd_buf) { |
150 | *p = '\0'; |
151 | rc = docmd(); |
152 | break; |
153 | } |
154 | } else { |
155 | p--; |
156 | |
157 | if (*p != '\n') { |
158 | printf("%s: line too long\n", cmd.path); |
159 | |
160 | |
161 | rc = -1; |
162 | } |
163 | *p = '\0'; |
164 | } |
165 | } while (rc > 0 && !(rc = docmd())); |
166 | |
167 | close(fd); |
168 | return rc; |
169 | } |
170 | |
171 | int |
172 | docmd(void) |
173 | { |
174 | char *p = NULL; |
175 | const struct cmd_table *ct = cmd_table, *cs; |
176 | |
177 | cmd.argc = 1; |
178 | if (cmd.cmd == NULL) { |
179 | |
180 | |
181 | for (p = cmd_buf; *p == ' ' || *p == '\t'; p++) |
182 | ; |
183 | if (*p == '#' || *p == '\0') { |
184 | #ifdef DEBUG |
185 | printf("rem\n"); |
186 | #endif |
187 | return 0; |
188 | } |
189 | ct = cmd_table; |
190 | cs = NULL; |
191 | cmd.argv[cmd.argc] = p; |
192 | p = whatcmd(&ct, p); |
193 | if (ct == NULL) { |
194 | cmd.argc++; |
195 | ct = cmd_table; |
196 | } else if (ct->cmd_type == CMDT_SET && p != NULL) { |
197 | cs = cmd_set; |
198 | #ifdef MACHINE_CMD |
199 | } else if (ct->cmd_type == CMDT_MDC && p != NULL) { |
200 | cs = MACHINE_CMD; |
201 | #endif |
202 | } |
203 | |
204 | if (cs != NULL) { |
205 | p = whatcmd(&cs, p); |
206 | if (cs == NULL) { |
207 | printf("%s: syntax error\n", ct->cmd_name); |
208 | return 0; |
209 | } |
210 | ct = cs; |
211 | } |
212 | cmd.cmd = ct; |
213 | } |
214 | |
215 | cmd.argv[0] = ct->cmd_name; |
216 | while (p && cmd.argc+1 < sizeof(cmd.argv) / sizeof(cmd.argv[0])) { |
217 | cmd.argv[cmd.argc++] = p; |
218 | p = nextword(p); |
219 | } |
220 | cmd.argv[cmd.argc] = NULL; |
221 | |
222 | return (*cmd.cmd->cmd_exec)(); |
223 | } |
224 | |
225 | static char * |
226 | whatcmd(const struct cmd_table **ct, char *p) |
227 | { |
228 | char *q; |
229 | int l; |
230 | |
231 | q = nextword(p); |
232 | |
233 | for (l = 0; p[l]; l++) |
234 | ; |
235 | |
236 | while ((*ct)->cmd_name != NULL && strncmp(p, (*ct)->cmd_name, l)) |
237 | (*ct)++; |
238 | |
239 | if ((*ct)->cmd_name == NULL) |
240 | *ct = NULL; |
241 | |
242 | return q; |
243 | } |
244 | |
245 | static int |
246 | readline(char *buf, size_t n, int to) |
247 | { |
248 | #ifdef DEBUG |
249 | extern int debug; |
250 | #endif |
251 | char *p = buf, ch; |
252 | |
253 | |
254 | if (to > 0) { |
255 | time_t tt = getsecs() + to; |
256 | #ifdef DEBUG |
257 | if (debug > 2) |
258 | printf ("readline: timeout(%d) at %u\n", to, tt); |
259 | #endif |
260 | while (!cnischar() && getsecs() < tt) |
261 | continue; |
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 | #ifdef BOOT_STTY |
397 | static int |
398 | Xstty(void) |
399 | { |
400 | int sp; |
401 | char *cp; |
402 | dev_t dev; |
403 | |
404 | if (cmd.argc == 1) { |
405 | printf("%s speed is %d\n", ttyname(0), cnspeed(0, -1)); |
406 | return 0; |
407 | } |
408 | dev = ttydev(cmd.argv[1]); |
409 | if (dev == NODEV) { |
410 | printf("%s not a console device\n", cmd.argv[1]); |
411 | return 0; |
412 | } |
413 | |
414 | if (cmd.argc == 2) |
415 | printf("%s speed is %d\n", cmd.argv[1], |
416 | cnspeed(dev, -1)); |
417 | else { |
418 | sp = 0; |
419 | for (cp = cmd.argv[2]; isdigit(*cp); cp++) |
420 | sp = sp * 10 + (*cp - '0'); |
421 | cnspeed(dev, sp); |
422 | } |
423 | return 0; |
424 | } |
425 | #endif |
426 | |
427 | static int |
428 | Xtime(void) |
429 | { |
430 | time_t tt = getsecs(); |
431 | |
432 | if (cmd.argc == 1) |
433 | printf(ctime(&tt)); |
434 | |
435 | return 0; |
436 | } |
437 | |
438 | static int |
439 | Xls(void) |
440 | { |
441 | struct stat sb; |
442 | char *p; |
443 | int fd; |
444 | |
445 | if (stat(qualify((cmd.argv[1]? cmd.argv[1]: "/.")), &sb) < 0) { |
446 | printf("stat(%s): %s\n", cmd.path, strerror(errno)); |
447 | return 0; |
448 | } |
449 | |
450 | if ((sb.st_mode & S_IFMT) != S_IFDIR) |
451 | ls(cmd.path, &sb); |
452 | else { |
453 | if ((fd = opendir(cmd.path)) < 0) { |
454 | printf("opendir(%s): %s\n", cmd.path, |
455 | strerror(errno)); |
456 | return 0; |
457 | } |
458 | |
459 | |
460 | for (p = cmd.path; *p; p++) |
461 | ; |
462 | *p++ = '/'; |
463 | *p = '\0'; |
464 | |
465 | while (readdir(fd, p) >= 0) { |
466 | if (stat(cmd.path, &sb) < 0) |
467 | printf("stat(%s): %s\n", cmd.path, |
468 | strerror(errno)); |
469 | else |
470 | ls(p, &sb); |
471 | } |
472 | closedir (fd); |
473 | } |
474 | return 0; |
475 | } |
476 | |
477 | #define lsrwx(mode,s) \ |
478 | putchar ((mode) & S_IROTH? 'r' : '-'); \ |
479 | putchar ((mode) & S_IWOTH? 'w' : '-'); \ |
480 | putchar ((mode) & S_IXOTH? *(s): (s)[1]); |
481 | |
482 | static void |
483 | ls(char *name, struct stat *sb) |
484 | { |
485 | putchar("-fc-d-b---l-s-w-"[(sb->st_mode & S_IFMT) >> 12]); |
486 | lsrwx(sb->st_mode >> 6, (sb->st_mode & S_ISUID? "sS" : "x-")); |
487 | lsrwx(sb->st_mode >> 3, (sb->st_mode & S_ISGID? "sS" : "x-")); |
488 | lsrwx(sb->st_mode , (sb->st_mode & S_ISTXT? "tT" : "x-")); |
489 | |
490 | printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid, |
491 | (u_long)sb->st_size, name); |
492 | } |
493 | #undef lsrwx |
494 | |
495 | int doboot = 1; |
496 | |
497 | static int |
498 | Xnop(void) |
499 | { |
500 | if (doboot) { |
501 | doboot = 0; |
502 | return (Xboot()); |
503 | } |
504 | |
505 | return 0; |
506 | } |
507 | |
508 | static int |
509 | Xboot(void) |
510 | { |
511 | if (cmd.argc > 1 && cmd.argv[1][0] != '-') { |
512 | qualify((cmd.argv[1]? cmd.argv[1]: cmd.image)); |
513 | if (bootparse(2)) |
514 | return 0; |
515 | } else { |
516 | if (bootparse(1)) |
517 | return 0; |
518 | snprintf(cmd.path, sizeof cmd.path, "%s:%s", |
519 | cmd.bootdev, cmd.image); |
520 | } |
521 | |
522 | return 1; |
523 | } |
524 | |
525 | |
526 | |
527 | |
528 | |
529 | static char * |
530 | qualify(char *name) |
531 | { |
532 | char *p; |
533 | |
534 | for (p = name; *p; p++) |
535 | if (*p == ':') |
536 | break; |
537 | if (*p == ':') |
538 | strlcpy(cmd.path, name, sizeof(cmd.path)); |
539 | else |
540 | snprintf(cmd.path, sizeof cmd.path, "%s:%s", |
541 | cmd.bootdev, name); |
542 | return cmd.path; |
543 | } |
544 | |
545 | static int |
546 | Xreboot(void) |
547 | { |
548 | printf("Rebooting...\n"); |
549 | exit(); |
550 | return 0; |
551 | } |
552 | |
553 | int |
554 | upgrade(void) |
555 | { |
556 | struct stat sb; |
557 | |
558 | if (stat(qualify(("/bsd.upgrade")), &sb) < 0) |
559 | return 0; |
560 | if ((sb.st_mode & S_IXUSR) == 0) { |
561 | printf("/bsd.upgrade is not u+x\n"); |
562 | return 0; |
563 | } |
564 | return 1; |
565 | } |