Bug Summary

File:src/sbin/savecore/savecore.c
Warning:line 185, column 7
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name savecore.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 pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/savecore/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/savecore/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -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 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sbin/savecore/savecore.c
1/* $OpenBSD: savecore.c,v 1.65 2022/12/04 23:50:47 cheloha Exp $ */
2/* $NetBSD: savecore.c,v 1.26 1996/03/18 21:16:05 leo Exp $ */
3
4/*-
5 * Copyright (c) 1986, 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/param.h> /* NODEV DEV_BSIZE */
34#include <sys/stat.h>
35#include <sys/mount.h>
36#include <sys/syslog.h>
37#include <sys/time.h>
38#include <sys/resource.h>
39
40#include <dirent.h>
41#include <errno(*__errno()).h>
42#include <fcntl.h>
43#include <nlist.h>
44#include <paths.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49#include <limits.h>
50#include <kvm.h>
51#include <vis.h>
52
53#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
54
55extern FILE *zopen(const char *fname, const char *mode, int bits);
56
57#define KREAD(kd, addr, p)(kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p)
))
\
58 (kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p)))
59
60struct nlist current_nl[] = { /* Namelist for currently running system. */
61#define X_DUMPDEV0 0
62 { "_dumpdev" },
63#define X_DUMPLO1 1
64 { "_dumplo" },
65#define X_TIME2 2
66 { "_time_second" },
67#define X_DUMPSIZE3 3
68 { "_dumpsize" },
69#define X_VERSION4 4
70 { "_version" },
71#define X_PANICSTR5 5
72 { "_panicstr" },
73#define X_DUMPMAG6 6
74 { "_dumpmag" },
75 { NULL((void *)0) },
76};
77int cursyms[] = { X_DUMPDEV0, X_DUMPLO1, X_VERSION4, X_DUMPMAG6, -1 };
78int dumpsyms[] = { X_TIME2, X_DUMPSIZE3, X_VERSION4, X_PANICSTR5, X_DUMPMAG6, -1 };
79
80struct nlist dump_nl[] = { /* Name list for dumped system. */
81 { "_dumpdev" }, /* Entries MUST be the same as */
82 { "_dumplo" }, /* those in current_nl[]. */
83 { "_time_second" },
84 { "_dumpsize" },
85 { "_version" },
86 { "_panicstr" },
87 { "_dumpmag" },
88 { NULL((void *)0) },
89};
90
91#define VERSIONSIZE512 512
92
93/* Types match kernel declarations. */
94long dumplo; /* where dump starts on dumpdev (in blocks) */
95off_t dumpoff; /* where dump starts on dumpdev (in bytes) */
96u_long dumpmag; /* magic number in dump */
97int dumppages; /* amount of memory dumped (in pages) */
98u_long dumpsize; /* amount of memory dumped */
99
100char *kernel;
101char *dirn; /* directory to save dumps in */
102char *ddname; /* name of dump device */
103dev_t dumpdev; /* dump device */
104int dumpfd; /* read/write descriptor on block dev */
105kvm_t *kd_dump; /* kvm descriptor on block dev */
106time_t now; /* current date */
107char panic_mesg[1024];
108int panicstr;
109char vers[VERSIONSIZE512];
110
111int clear, zcompress, force, verbose; /* flags */
112
113void check_kmem(void);
114int check_space(void);
115void clear_dump(void);
116int dump_exists(void);
117char *find_dev(dev_t, int);
118int get_crashtime(void);
119void kmem_setup(void);
120char *rawname(char *s);
121void save_core(void);
122void usage(void);
123
124int
125main(int argc, char *argv[])
126{
127 struct rlimit rl;
128 int ch;
129
130 openlog("savecore", LOG_PERROR0x20, LOG_DAEMON(3<<3));
131
132 /* Increase our data size to the max if we can. */
133 if (getrlimit(RLIMIT_DATA2, &rl) == 0) {
1
Assuming the condition is false
2
Taking false branch
134 rl.rlim_cur = rl.rlim_max;
135 if (setrlimit(RLIMIT_DATA2, &rl) == -1)
136 syslog(LOG_WARNING4, "can't set rlimit data size: %m");
137 }
138
139 while ((ch = getopt(argc, argv, "cdfN:vz")) != -1)
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 160
140 switch(ch) {
141 case 'c':
142 clear = 1;
143 break;
144 case 'd': /* Not documented. */
145 case 'v':
146 verbose = 1;
147 break;
148 case 'f':
149 force = 1;
150 break;
151 case 'N':
152 kernel = optarg;
153 break;
154 case 'z':
155 zcompress = 1;
156 break;
157 default:
158 usage();
159 }
160 argc -= optind;
161 argv += optind;
162
163 if (!clear) {
5
Assuming 'clear' is not equal to 0
6
Taking false branch
164 if (argc != 1)
165 usage();
166 dirn = argv[0];
167 }
168
169 (void)time(&now);
170 kmem_setup();
171
172 if (!clear) {
7
Assuming 'clear' is 0
8
Taking true branch
173 if (unveil(dirn, "rwc") == -1) {
9
Assuming the condition is false
10
Taking false branch
174 syslog(LOG_ERR3, "unveil: %m");
175 exit(1);
176 }
177 if (unveil(kernel ? kernel : _PATH_UNIX"/bsd", "r") == -1) {
11
Assuming 'kernel' is null
12
'?' condition is false
13
Assuming the condition is false
14
Taking false branch
178 syslog(LOG_ERR3, "unveil: %m");
179 exit(1);
180 }
181 if (unveil(rawname(ddname), "r") == -1) {
15
Calling 'rawname'
22
Returned allocated memory
23
Assuming the condition is false
24
Taking false branch
182 syslog(LOG_ERR3, "unveil: %m");
183 exit(1);
184 }
185 if (pledge("stdio rpath wpath cpath", NULL((void *)0)) == -1) {
25
Potential memory leak
186 syslog(LOG_ERR3, "pledge: %m");
187 exit(1);
188 }
189 } else {
190 clear_dump();
191 return (0);
192 }
193
194 if (!dump_exists() && !force)
195 return (1);
196
197 check_kmem();
198
199 if (panicstr)
200 syslog(LOG_ALERT1, "reboot after panic: %s", panic_mesg);
201 else
202 syslog(LOG_ALERT1, "reboot");
203
204 if ((!get_crashtime() || !check_space()) && !force)
205 return (1);
206
207 save_core();
208
209 clear_dump();
210 return (0);
211}
212
213char *dump_sys;
214
215void
216kmem_setup(void)
217{
218 kvm_t *kd_kern;
219 char errbuf[_POSIX2_LINE_MAX2048];
220 int i, hdrsz;
221
222 /*
223 * Some names we need for the currently running system, others for
224 * the system that was running when the dump was made. The values
225 * obtained from the current system are used to look for things in
226 * /dev/kmem that cannot be found in the dump_sys namelist, but are
227 * presumed to be the same (since the disk partitions are probably
228 * the same!)
229 */
230 kd_kern = kvm_openfiles(NULL((void *)0), NULL((void *)0), NULL((void *)0), O_RDONLY0x0000, errbuf);
231 if (kd_kern == NULL((void *)0)) {
232 syslog(LOG_ERR3, "%s: kvm_openfiles: %s", _PATH_UNIX"/bsd", errbuf);
233 exit(1);
234 }
235 if (kvm_nlist(kd_kern, current_nl) == -1)
236 syslog(LOG_ERR3, "%s: kvm_nlist: %s", _PATH_UNIX"/bsd",
237 kvm_geterr(kd_kern));
238
239 for (i = 0; cursyms[i] != -1; i++)
240 if (current_nl[cursyms[i]].n_value == 0) {
241 syslog(LOG_ERR3, "%s: %s not in namelist",
242 _PATH_UNIX"/bsd", current_nl[cursyms[i]].n_name);
243 exit(1);
244 }
245
246 (void)KREAD(kd_kern, current_nl[X_DUMPDEV].n_value, &dumpdev)(kvm_read(kd_kern, current_nl[0].n_value, (char *)(&dumpdev
), sizeof(*(&dumpdev))) != sizeof(*(&dumpdev)))
;
247 if (dumpdev == NODEV(dev_t)(-1)) {
248 syslog(LOG_WARNING4, "no core dump (no dumpdev)");
249 exit(1);
250 }
251 (void)KREAD(kd_kern, current_nl[X_DUMPLO].n_value, &dumplo)(kvm_read(kd_kern, current_nl[1].n_value, (char *)(&dumplo
), sizeof(*(&dumplo))) != sizeof(*(&dumplo)))
;
252 dumpoff = (off_t)dumplo * DEV_BSIZE(1 << 9);
253 if (verbose)
254 (void)printf("dumpoff = %lld (%ld * %d)\n",
255 (long long)dumpoff, dumplo, DEV_BSIZE(1 << 9));
256 (void) KREAD(kd_kern, current_nl[X_DUMPMAG].n_value, &dumpmag)(kvm_read(kd_kern, current_nl[6].n_value, (char *)(&dumpmag
), sizeof(*(&dumpmag))) != sizeof(*(&dumpmag)))
;
257
258 if (kernel == NULL((void *)0)) {
259 if (kvm_read(kd_kern, current_nl[X_VERSION4].n_value,
260 vers, sizeof(vers)) == -1) {
261 syslog(LOG_ERR3, "%s: kvm_read: version misread", _PATH_UNIX"/bsd");
262 exit(1);
263 }
264 vers[sizeof(vers) - 1] = '\0';
265 }
266
267 ddname = find_dev(dumpdev, S_IFBLK0060000);
268 dumpfd = open(ddname, O_RDWR0x0002);
269 if (dumpfd == -1) {
270 syslog(LOG_ERR3, "%s: %m", ddname);
271 exit(1);
272 }
273
274
275 dump_sys = kernel ? kernel : _PATH_UNIX"/bsd";
276 kd_dump = kvm_openfiles(kernel, ddname, NULL((void *)0), O_RDWR0x0002, errbuf);
277 if (kd_dump == NULL((void *)0)) {
278 syslog(LOG_ERR3, "%s: kvm_openfiles: %s", dump_sys, errbuf);
279 exit(1);
280 }
281
282 if (kvm_nlist(kd_dump, dump_nl) == -1)
283 syslog(LOG_ERR3, "%s: kvm_nlist: %s", dump_sys,
284 kvm_geterr(kd_dump));
285
286 for (i = 0; dumpsyms[i] != -1; i++)
287 if (dump_nl[dumpsyms[i]].n_value == 0) {
288 syslog(LOG_ERR3, "%s: %s not in namelist",
289 dump_sys, dump_nl[dumpsyms[i]].n_name);
290 exit(1);
291 }
292 hdrsz = kvm_dump_mkheader(kd_dump, dumpoff);
293 if (hdrsz == -1) {
294 if(verbose)
295 syslog(LOG_ERR3, "%s: kvm_dump_mkheader: %s", dump_sys,
296 kvm_geterr(kd_dump));
297 syslog(LOG_WARNING4, "no core dump");
298 exit(1);
299 }
300 dumpoff += hdrsz;
301 kvm_close(kd_kern);
302}
303
304void
305check_kmem(void)
306{
307 char *cp;
308 int panicloc;
309 char core_vers[VERSIONSIZE512];
310
311 if (kvm_read(kd_dump, dump_nl[X_VERSION4].n_value, core_vers,
312 sizeof(core_vers)) != sizeof(core_vers)) {
313 syslog(LOG_ERR3, "%s: kvm_read: version misread", dump_sys);
314 exit(1);
315 }
316 core_vers[sizeof(core_vers) - 1] = '\0';
317
318 if (strcmp(vers, core_vers) && kernel == 0) {
319 vers[strcspn(vers, "\n")] = '\0';
320 core_vers[strcspn(core_vers, "\n")] = '\0';
321
322 syslog(LOG_WARNING4,
323 "warning: %s version mismatch:\n\t%s\nand\t%s\n",
324 _PATH_UNIX"/bsd", vers, core_vers);
325 }
326
327 (void)KREAD(kd_dump, dump_nl[X_PANICSTR].n_value, &panicstr)(kvm_read(kd_dump, dump_nl[5].n_value, (char *)(&panicstr
), sizeof(*(&panicstr))) != sizeof(*(&panicstr)))
;
328 if (panicstr) {
329 char c, visout[5];
330 size_t vislen;
331
332 cp = panic_mesg;
333 panicloc = panicstr;
334 for (;;) {
335 if (KREAD(kd_dump, panicloc, &c)(kvm_read(kd_dump, panicloc, (char *)(&c), sizeof(*(&
c))) != sizeof(*(&c)))
!= 0 || c == '\0')
336 break;
337 panicloc++;
338
339 vis(visout, c, VIS_SAFE0x20|VIS_NOSLASH0x40, 0);
340 vislen = strlen(visout);
341 if (cp - panic_mesg + vislen >= sizeof(panic_mesg))
342 break;
343 strlcat(cp, visout,
344 panic_mesg + sizeof panic_mesg - cp);
345 cp += strlen(cp);
346 }
347 }
348}
349
350int
351dump_exists(void)
352{
353 u_long newdumpmag;
354
355 (void)KREAD(kd_dump, dump_nl[X_DUMPMAG].n_value, &newdumpmag)(kvm_read(kd_dump, dump_nl[6].n_value, (char *)(&newdumpmag
), sizeof(*(&newdumpmag))) != sizeof(*(&newdumpmag)))
;
356
357 /* Read the dump size. */
358 (void)KREAD(kd_dump, dump_nl[X_DUMPSIZE].n_value, &dumppages)(kvm_read(kd_dump, dump_nl[3].n_value, (char *)(&dumppages
), sizeof(*(&dumppages))) != sizeof(*(&dumppages)))
;
359 dumpsize = (u_long)dumppages * getpagesize();
360
361 /*
362 * Return zero if core dump doesn't seem to be there and note
363 * it for syslog. This check and return happens after the dump size
364 * is read, so dumpsize is whether or not the core is valid (for -f).
365 */
366 if (newdumpmag != dumpmag) {
367 if (verbose)
368 syslog(LOG_WARNING4,
369 "magic number mismatch (%lx != %lx)",
370 newdumpmag, dumpmag);
371 syslog(LOG_WARNING4, "no core dump");
372 return (0);
373 }
374 return (1);
375}
376
377void
378clear_dump(void)
379{
380 if (pledge("stdio", NULL((void *)0)) == -1) {
381 syslog(LOG_ERR3, "pledge: %m");
382 exit(1);
383 }
384
385 if (kvm_dump_inval(kd_dump) == -1)
386 syslog(LOG_ERR3, "%s: kvm_clear_dump: %s", ddname,
387 kvm_geterr(kd_dump));
388
389}
390
391char buf[1024 * 1024];
392
393void
394save_core(void)
395{
396 FILE *fp;
397 int bounds, ifd, nr, nw, ofd = -1;
398 char *rawp, path[PATH_MAX1024];
399 mode_t um;
400
401 um = umask(S_IRWXG0000070|S_IRWXO0000007);
402
403 /*
404 * Get the current number and update the bounds file. Do the update
405 * now, because we may fail later and don't want to overwrite anything.
406 */
407 (void)snprintf(path, sizeof(path), "%s/bounds", dirn);
408 if ((fp = fopen(path, "r")) == NULL((void *)0))
409 goto err1;
410 if (fgets(buf, sizeof(buf), fp) == NULL((void *)0)) {
411 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
412err1: syslog(LOG_WARNING4, "%s: %s", path, strerror(errno(*__errno())));
413 bounds = 0;
414 } else {
415 const char *errstr = NULL((void *)0);
416 char *p;
417
418 if ((p = strchr(buf, '\n')) != NULL((void *)0))
419 *p = '\0';
420 bounds = strtonum(buf, 0, INT_MAX0x7fffffff, &errstr);
421 if (errstr)
422 syslog(LOG_WARNING4, "bounds was corrupt: %s", errstr);
423 }
424 if (fp != NULL((void *)0))
425 (void)fclose(fp);
426 if ((fp = fopen(path, "w")) == NULL((void *)0))
427 syslog(LOG_ERR3, "%s: %m", path);
428 else {
429 (void)fprintf(fp, "%d\n", bounds + 1);
430 (void)fclose(fp);
431 }
432
433 /* Create the core file. */
434 (void)snprintf(path, sizeof(path), "%s%s.%d.core%s",
435 dirn, _PATH_UNIX"/bsd", bounds, zcompress ? ".Z" : "");
436 if (zcompress) {
437 if ((fp = zopen(path, "w", 0)) == NULL((void *)0)) {
438 syslog(LOG_ERR3, "%s: %s", path, strerror(errno(*__errno())));
439 exit(1);
440 }
441 } else {
442 ofd = open(path, O_WRONLY0x0001 | O_CREAT0x0200 | O_TRUNC0x0400,
443 S_IRUSR0000400 | S_IWUSR0000200 | S_IRGRP0000040 | S_IROTH0000004);
444 if (ofd == -1) {
445 syslog(LOG_ERR3, "%s: %m", path);
446 exit(1);
447 }
448
449 fp = fdopen(ofd, "w");
450 if (fp == NULL((void *)0)) {
451 syslog(LOG_ERR3, "%s: fdopen: %s", path, strerror(errno(*__errno())));
452 exit(1);
453 }
454 }
455
456 /* Open the raw device. */
457 rawp = rawname(ddname);
458 if ((ifd = open(rawp, O_RDONLY0x0000)) == -1) {
459 syslog(LOG_WARNING4, "%s: %m; using block device", rawp);
460 ifd = dumpfd;
461 }
462
463 /* Seek to the start of the core. */
464 if (lseek(ifd, dumpoff, SEEK_SET0) == -1) {
465 syslog(LOG_ERR3, "lseek: %m");
466 exit(1);
467 }
468
469 if (kvm_dump_wrtheader(kd_dump, fp, dumpsize) == -1) {
470 syslog(LOG_ERR3, "kvm_dump_wrtheader: %s : %s", path,
471 kvm_geterr(kd_dump));
472 exit(1);
473 }
474
475 /* Copy the core file. */
476 syslog(LOG_NOTICE5, "writing %score to %s",
477 zcompress ? "compressed " : "", path);
478 for (; dumpsize != 0; dumpsize -= nr) {
479 (void)printf("%8luK\r", dumpsize / 1024);
480 (void)fflush(stdout(&__sF[1]));
481 nr = read(ifd, buf, MINIMUM(dumpsize, sizeof(buf))(((dumpsize) < (sizeof(buf))) ? (dumpsize) : (sizeof(buf))
)
);
482 if (nr <= 0) {
483 if (nr == 0)
484 syslog(LOG_WARNING4,
485 "WARNING: EOF on dump device");
486 else
487 syslog(LOG_ERR3, "%s: %m", rawp);
488 goto err2;
489 }
490 nw = fwrite(buf, 1, nr, fp);
491 if (nw != nr) {
492 syslog(LOG_ERR3, "%s: %s",
493 path, strerror(nw == 0 ? EIO5 : errno(*__errno())));
494err2: syslog(LOG_WARNING4,
495 "WARNING: core may be incomplete");
496 (void)printf("\n");
497 exit(1);
498 }
499 }
500 (void)close(ifd);
501 (void)fclose(fp);
502
503 /* Copy the kernel. */
504 ifd = open(kernel ? kernel : _PATH_UNIX"/bsd", O_RDONLY0x0000);
505 if (ifd == -1) {
506 syslog(LOG_ERR3, "%s: %m", kernel ? kernel : _PATH_UNIX"/bsd");
507 exit(1);
508 }
509 (void)snprintf(path, sizeof(path), "%s%s.%d%s",
510 dirn, _PATH_UNIX"/bsd", bounds, zcompress ? ".Z" : "");
511 if (zcompress) {
512 if ((fp = zopen(path, "w", 0)) == NULL((void *)0)) {
513 syslog(LOG_ERR3, "%s: %s", path, strerror(errno(*__errno())));
514 exit(1);
515 }
516 } else {
517 ofd = open(path, O_WRONLY0x0001 | O_CREAT0x0200 | O_TRUNC0x0400,
518 S_IRUSR0000400 | S_IWUSR0000200 | S_IRGRP0000040 | S_IROTH0000004);
519 if (ofd == -1) {
520 syslog(LOG_ERR3, "%s: %m", path);
521 exit(1);
522 }
523 }
524 syslog(LOG_NOTICE5, "writing %skernel to %s",
525 zcompress ? "compressed " : "", path);
526 while ((nr = read(ifd, buf, sizeof(buf))) > 0) {
527 if (zcompress)
528 nw = fwrite(buf, 1, nr, fp);
529 else
530 nw = write(ofd, buf, nr);
531 if (nw != nr) {
532 syslog(LOG_ERR3, "%s: %s",
533 path, strerror(nw == 0 ? EIO5 : errno(*__errno())));
534 syslog(LOG_WARNING4,
535 "WARNING: kernel may be incomplete");
536 exit(1);
537 }
538 }
539 if (nr == -1) {
540 syslog(LOG_ERR3, "%s: %s",
541 kernel ? kernel : _PATH_UNIX"/bsd", strerror(errno(*__errno())));
542 syslog(LOG_WARNING4,
543 "WARNING: kernel may be incomplete");
544 exit(1);
545 }
546 if (zcompress)
547 (void)fclose(fp);
548 else
549 (void)close(ofd);
550 (void)umask(um);
551}
552
553char *
554find_dev(dev_t dev, int type)
555{
556 DIR *dfd;
557 struct dirent *dir;
558 struct stat sb;
559 char *dp, devname[PATH_MAX1024];
560
561 if ((dfd = opendir(_PATH_DEV"/dev/")) == NULL((void *)0)) {
562 syslog(LOG_ERR3, "%s: %s", _PATH_DEV"/dev/", strerror(errno(*__errno())));
563 exit(1);
564 }
565 (void)strlcpy(devname, _PATH_DEV"/dev/", sizeof devname);
566 while ((dir = readdir(dfd))) {
567 (void)strlcpy(devname + sizeof(_PATH_DEV"/dev/") - 1, dir->d_name,
568 sizeof devname - (sizeof(_PATH_DEV"/dev/") - 1));
569 if (lstat(devname, &sb)) {
570 syslog(LOG_ERR3, "%s: %s", devname, strerror(errno(*__errno())));
571 continue;
572 }
573 if ((sb.st_mode & S_IFMT0170000) != type)
574 continue;
575 if (dev == sb.st_rdev) {
576 closedir(dfd);
577 if ((dp = strdup(devname)) == NULL((void *)0)) {
578 syslog(LOG_ERR3, "%s", strerror(errno(*__errno())));
579 exit(1);
580 }
581 return (dp);
582 }
583 }
584 closedir(dfd);
585 syslog(LOG_ERR3, "can't find device %u/%u", major(dev)(((unsigned)(dev) >> 8) & 0xff), minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
586 exit(1);
587}
588
589char *
590rawname(char *s)
591{
592 char *sl, name[PATH_MAX1024];
593
594 if ((sl = strrchr(s, '/')) == NULL((void *)0) || sl[1] == '0') {
16
Assuming the condition is false
17
Assuming the condition is false
18
Taking false branch
595 syslog(LOG_ERR3,
596 "can't make raw dump device name from %s", s);
597 return (s);
598 }
599 (void)snprintf(name, sizeof(name), "%.*s/r%s", (int)(sl - s), s, sl + 1);
600 if ((sl = strdup(name)) == NULL((void *)0)) {
19
Memory is allocated
20
Assuming the condition is false
21
Taking false branch
601 syslog(LOG_ERR3, "%s", strerror(errno(*__errno())));
602 exit(1);
603 }
604 return (sl);
605}
606
607int
608get_crashtime(void)
609{
610 time_t dumptime; /* Time the dump was taken. */
611
612 (void)KREAD(kd_dump, dump_nl[X_TIME].n_value, &dumptime)(kvm_read(kd_dump, dump_nl[2].n_value, (char *)(&dumptime
), sizeof(*(&dumptime))) != sizeof(*(&dumptime)))
;
613 if (dumptime == 0) {
614 if (verbose)
615 syslog(LOG_ERR3, "dump time is zero");
616 return (0);
617 }
618 (void)printf("savecore: system went down at %s", ctime(&dumptime));
619#define SECSPERDAY(24 * 60 * 60) (24 * 60 * 60)
620#define LEEWAY(7 * (24 * 60 * 60)) (7 * SECSPERDAY(24 * 60 * 60))
621 if (dumptime < now - LEEWAY(7 * (24 * 60 * 60)) || dumptime > now + LEEWAY(7 * (24 * 60 * 60))) {
622 (void)printf("dump time is unreasonable\n");
623 return (0);
624 }
625 return (1);
626}
627
628int
629check_space(void)
630{
631 FILE *fp;
632 char *tkernel;
633 off_t minfree, spacefree, kernelsize, needed;
634 struct stat st;
635 struct statfs fsbuf;
636 char buf[100], path[PATH_MAX1024];
637 int fd;
638
639 tkernel = kernel ? kernel : _PATH_UNIX"/bsd";
640 if (stat(tkernel, &st) == -1) {
641 syslog(LOG_ERR3, "%s: %m", tkernel);
642 exit(1);
643 }
644 kernelsize = st.st_blocks * S_BLKSIZE512;
645 if ((fd = open(dirn, O_RDONLY0x0000)) == -1 || fstatfs(fd, &fsbuf) == -1) {
646 syslog(LOG_ERR3, "%s: %m", dirn);
647 exit(1);
648 }
649 close(fd);
650 spacefree = ((off_t)fsbuf.f_bavail * fsbuf.f_bsize) / 1024;
651
652 (void)snprintf(path, sizeof(path), "%s/minfree", dirn);
653 if ((fp = fopen(path, "r")) == NULL((void *)0))
654 minfree = 0;
655 else {
656 if (fgets(buf, sizeof(buf), fp) == NULL((void *)0))
657 minfree = 0;
658 else {
659 const char *errstr;
660 char *p;
661
662 if ((p = strchr(buf, '\n')) != NULL((void *)0))
663 *p = '\0';
664 minfree = strtonum(buf, 0, LLONG_MAX0x7fffffffffffffffLL, &errstr);
665 if (errstr)
666 syslog(LOG_WARNING4,
667 "minfree was corrupt: %s", errstr);
668 }
669 (void)fclose(fp);
670 }
671
672 needed = (dumpsize + kernelsize) / 1024;
673 if (minfree > 0 && spacefree - needed < minfree) {
674 syslog(LOG_WARNING4,
675 "no dump, not enough free space on device");
676 return (0);
677 }
678 if (spacefree - needed < minfree)
679 syslog(LOG_WARNING4,
680 "dump performed, but free space threshold crossed");
681 return (1);
682}
683
684void
685usage(void)
686{
687 extern char *__progname;
688 fprintf(stderr(&__sF[2]), "usage: %s [-cfvz] [-N system] directory\n",
689 __progname);
690 exit(1);
691}