Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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