1*8a16b7a1SPedro F. Giffuni /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 483f9dfabSGarrett Wollman * Copyright (c) 1980, 1993 583f9dfabSGarrett Wollman * The Regents of the University of California. All rights reserved. 683f9dfabSGarrett Wollman * 783f9dfabSGarrett Wollman * Redistribution and use in source and binary forms, with or without 883f9dfabSGarrett Wollman * modification, are permitted provided that the following conditions 983f9dfabSGarrett Wollman * are met: 1083f9dfabSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 1183f9dfabSGarrett Wollman * notice, this list of conditions and the following disclaimer. 1283f9dfabSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 1383f9dfabSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 1483f9dfabSGarrett Wollman * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 1683f9dfabSGarrett Wollman * may be used to endorse or promote products derived from this software 1783f9dfabSGarrett Wollman * without specific prior written permission. 1883f9dfabSGarrett Wollman * 1983f9dfabSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2083f9dfabSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2183f9dfabSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2283f9dfabSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2383f9dfabSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2483f9dfabSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2583f9dfabSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2683f9dfabSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2783f9dfabSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2883f9dfabSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2983f9dfabSGarrett Wollman * SUCH DAMAGE. 3083f9dfabSGarrett Wollman */ 3183f9dfabSGarrett Wollman 32c69284caSDavid E. O'Brien #if 0 3383f9dfabSGarrett Wollman #ifndef lint 348f034b11SPhilippe Charnier static const char copyright[] = 3583f9dfabSGarrett Wollman "@(#) Copyright (c) 1980, 1993\n\ 3683f9dfabSGarrett Wollman The Regents of the University of California. All rights reserved.\n"; 3783f9dfabSGarrett Wollman #endif /* not lint */ 3883f9dfabSGarrett Wollman 3983f9dfabSGarrett Wollman #ifndef lint 408f034b11SPhilippe Charnier static char sccsid[] = "From: @(#)swapon.c 8.1 (Berkeley) 6/5/93"; 4183f9dfabSGarrett Wollman #endif /* not lint */ 42c69284caSDavid E. O'Brien #endif 43c69284caSDavid E. O'Brien #include <sys/cdefs.h> 44c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4583f9dfabSGarrett Wollman 4683f9dfabSGarrett Wollman #include <sys/param.h> 47480f31c2SKonrad Witaszczyk #include <sys/capsicum.h> 482dd527b3SPoul-Henning Kamp #include <sys/disk.h> 49c0046e26SDag-Erling Smørgrav #include <sys/sysctl.h> 5083f9dfabSGarrett Wollman 51480f31c2SKonrad Witaszczyk #include <assert.h> 52c0046e26SDag-Erling Smørgrav #include <err.h> 53f6848434SAlfred Perlstein #include <errno.h> 54c0046e26SDag-Erling Smørgrav #include <fcntl.h> 55c0046e26SDag-Erling Smørgrav #include <paths.h> 56480f31c2SKonrad Witaszczyk #include <stdbool.h> 57c0046e26SDag-Erling Smørgrav #include <stdint.h> 58c0046e26SDag-Erling Smørgrav #include <stdio.h> 59c0046e26SDag-Erling Smørgrav #include <stdlib.h> 60c0046e26SDag-Erling Smørgrav #include <string.h> 61c0046e26SDag-Erling Smørgrav #include <sysexits.h> 62c0046e26SDag-Erling Smørgrav #include <unistd.h> 63c0046e26SDag-Erling Smørgrav 64480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 65480f31c2SKonrad Witaszczyk #include <openssl/err.h> 66480f31c2SKonrad Witaszczyk #include <openssl/pem.h> 67480f31c2SKonrad Witaszczyk #include <openssl/rsa.h> 68480f31c2SKonrad Witaszczyk #endif 69480f31c2SKonrad Witaszczyk 70c0046e26SDag-Erling Smørgrav static int verbose; 71c0046e26SDag-Erling Smørgrav 72c0046e26SDag-Erling Smørgrav static void 73c0046e26SDag-Erling Smørgrav usage(void) 74c0046e26SDag-Erling Smørgrav { 75f6848434SAlfred Perlstein fprintf(stderr, "%s\n%s\n%s\n", 7664a16434SMark Johnston "usage: dumpon [-v] [-k public_key_file] [-z] special_file", 77f6848434SAlfred Perlstein " dumpon [-v] off", 784a790eddSAlfred Perlstein " dumpon [-v] -l"); 79c0046e26SDag-Erling Smørgrav exit(EX_USAGE); 80c0046e26SDag-Erling Smørgrav } 81c0046e26SDag-Erling Smørgrav 82c0046e26SDag-Erling Smørgrav static void 83c0046e26SDag-Erling Smørgrav check_size(int fd, const char *fn) 84c0046e26SDag-Erling Smørgrav { 85c0046e26SDag-Erling Smørgrav int name[] = { CTL_HW, HW_PHYSMEM }; 860bfc2a12SMarcelo Araujo size_t namelen = nitems(name); 87c0046e26SDag-Erling Smørgrav unsigned long physmem; 88ce893772SPaul Saab size_t len; 89c0046e26SDag-Erling Smørgrav off_t mediasize; 90ce893772SPaul Saab int minidump; 91c0046e26SDag-Erling Smørgrav 92b54a17cdSJohn Baldwin len = sizeof(minidump); 93ce893772SPaul Saab if (sysctlbyname("debug.minidump", &minidump, &len, NULL, 0) == 0 && 94ce893772SPaul Saab minidump == 1) 95ce893772SPaul Saab return; 96b54a17cdSJohn Baldwin len = sizeof(physmem); 97c0046e26SDag-Erling Smørgrav if (sysctl(name, namelen, &physmem, &len, NULL, 0) != 0) 98c0046e26SDag-Erling Smørgrav err(EX_OSERR, "can't get memory size"); 99c0046e26SDag-Erling Smørgrav if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) 100c0046e26SDag-Erling Smørgrav err(EX_OSERR, "%s: can't get size", fn); 1019872f15dSDag-Erling Smørgrav if ((uintmax_t)mediasize < (uintmax_t)physmem) { 102c0046e26SDag-Erling Smørgrav if (verbose) 103c0046e26SDag-Erling Smørgrav printf("%s is smaller than physical memory\n", fn); 104c0046e26SDag-Erling Smørgrav exit(EX_IOERR); 105c0046e26SDag-Erling Smørgrav } 106c0046e26SDag-Erling Smørgrav } 10783f9dfabSGarrett Wollman 108480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 109480f31c2SKonrad Witaszczyk static void 110480f31c2SKonrad Witaszczyk genkey(const char *pubkeyfile, struct diocskerneldump_arg *kda) 111480f31c2SKonrad Witaszczyk { 112480f31c2SKonrad Witaszczyk FILE *fp; 113480f31c2SKonrad Witaszczyk RSA *pubkey; 114480f31c2SKonrad Witaszczyk 115480f31c2SKonrad Witaszczyk assert(pubkeyfile != NULL); 116480f31c2SKonrad Witaszczyk assert(kda != NULL); 117480f31c2SKonrad Witaszczyk 118480f31c2SKonrad Witaszczyk fp = NULL; 119480f31c2SKonrad Witaszczyk pubkey = NULL; 120480f31c2SKonrad Witaszczyk 121480f31c2SKonrad Witaszczyk fp = fopen(pubkeyfile, "r"); 122480f31c2SKonrad Witaszczyk if (fp == NULL) 123480f31c2SKonrad Witaszczyk err(1, "Unable to open %s", pubkeyfile); 124480f31c2SKonrad Witaszczyk 125480f31c2SKonrad Witaszczyk if (cap_enter() < 0 && errno != ENOSYS) 126480f31c2SKonrad Witaszczyk err(1, "Unable to enter capability mode"); 127480f31c2SKonrad Witaszczyk 128480f31c2SKonrad Witaszczyk pubkey = RSA_new(); 129480f31c2SKonrad Witaszczyk if (pubkey == NULL) { 130480f31c2SKonrad Witaszczyk errx(1, "Unable to allocate an RSA structure: %s", 131480f31c2SKonrad Witaszczyk ERR_error_string(ERR_get_error(), NULL)); 132480f31c2SKonrad Witaszczyk } 133480f31c2SKonrad Witaszczyk 134480f31c2SKonrad Witaszczyk pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL); 135480f31c2SKonrad Witaszczyk fclose(fp); 136480f31c2SKonrad Witaszczyk fp = NULL; 137480f31c2SKonrad Witaszczyk if (pubkey == NULL) 138480f31c2SKonrad Witaszczyk errx(1, "Unable to read data from %s.", pubkeyfile); 139480f31c2SKonrad Witaszczyk 140480f31c2SKonrad Witaszczyk kda->kda_encryptedkeysize = RSA_size(pubkey); 141480f31c2SKonrad Witaszczyk if (kda->kda_encryptedkeysize > KERNELDUMP_ENCKEY_MAX_SIZE) { 142480f31c2SKonrad Witaszczyk errx(1, "Public key has to be at most %db long.", 143480f31c2SKonrad Witaszczyk 8 * KERNELDUMP_ENCKEY_MAX_SIZE); 144480f31c2SKonrad Witaszczyk } 145480f31c2SKonrad Witaszczyk 146480f31c2SKonrad Witaszczyk kda->kda_encryptedkey = calloc(1, kda->kda_encryptedkeysize); 147480f31c2SKonrad Witaszczyk if (kda->kda_encryptedkey == NULL) 148480f31c2SKonrad Witaszczyk err(1, "Unable to allocate encrypted key"); 149480f31c2SKonrad Witaszczyk 150480f31c2SKonrad Witaszczyk kda->kda_encryption = KERNELDUMP_ENC_AES_256_CBC; 151480f31c2SKonrad Witaszczyk arc4random_buf(kda->kda_key, sizeof(kda->kda_key)); 152480f31c2SKonrad Witaszczyk if (RSA_public_encrypt(sizeof(kda->kda_key), kda->kda_key, 153480f31c2SKonrad Witaszczyk kda->kda_encryptedkey, pubkey, 154480f31c2SKonrad Witaszczyk RSA_PKCS1_PADDING) != (int)kda->kda_encryptedkeysize) { 155480f31c2SKonrad Witaszczyk errx(1, "Unable to encrypt the one-time key."); 156480f31c2SKonrad Witaszczyk } 157480f31c2SKonrad Witaszczyk RSA_free(pubkey); 158480f31c2SKonrad Witaszczyk } 159480f31c2SKonrad Witaszczyk #endif 160480f31c2SKonrad Witaszczyk 161f6848434SAlfred Perlstein static void 162f6848434SAlfred Perlstein listdumpdev(void) 163f6848434SAlfred Perlstein { 164f6848434SAlfred Perlstein char dumpdev[PATH_MAX]; 165f6848434SAlfred Perlstein size_t len; 166f6848434SAlfred Perlstein const char *sysctlname = "kern.shutdown.dumpdevname"; 167f6848434SAlfred Perlstein 168f6848434SAlfred Perlstein len = sizeof(dumpdev); 169f6848434SAlfred Perlstein if (sysctlbyname(sysctlname, &dumpdev, &len, NULL, 0) != 0) { 170f6848434SAlfred Perlstein if (errno == ENOMEM) { 171f6848434SAlfred Perlstein err(EX_OSERR, "Kernel returned too large of a buffer for '%s'\n", 172f6848434SAlfred Perlstein sysctlname); 173f6848434SAlfred Perlstein } else { 174f6848434SAlfred Perlstein err(EX_OSERR, "Sysctl get '%s'\n", sysctlname); 175f6848434SAlfred Perlstein } 176f6848434SAlfred Perlstein } 177f6848434SAlfred Perlstein if (verbose) { 178f6848434SAlfred Perlstein printf("kernel dumps on "); 179f6848434SAlfred Perlstein } 180f6848434SAlfred Perlstein if (strlen(dumpdev) == 0) { 181f6848434SAlfred Perlstein printf("%s\n", _PATH_DEVNULL); 182f6848434SAlfred Perlstein } else { 183f6848434SAlfred Perlstein printf("%s\n", dumpdev); 184f6848434SAlfred Perlstein } 185f6848434SAlfred Perlstein } 186f6848434SAlfred Perlstein 18783f9dfabSGarrett Wollman int 188d1a939c1SWarner Losh main(int argc, char *argv[]) 18983f9dfabSGarrett Wollman { 190480f31c2SKonrad Witaszczyk struct diocskerneldump_arg kda; 191480f31c2SKonrad Witaszczyk const char *pubkeyfile; 192c0046e26SDag-Erling Smørgrav int ch; 1939e9c1cadSPoul-Henning Kamp int i, fd; 194f6848434SAlfred Perlstein int do_listdumpdev = 0; 19564a16434SMark Johnston bool enable, gzip; 19683f9dfabSGarrett Wollman 19764a16434SMark Johnston gzip = false; 198480f31c2SKonrad Witaszczyk pubkeyfile = NULL; 199480f31c2SKonrad Witaszczyk 20064a16434SMark Johnston while ((ch = getopt(argc, argv, "k:lvz")) != -1) 20183f9dfabSGarrett Wollman switch((char)ch) { 202480f31c2SKonrad Witaszczyk case 'k': 203480f31c2SKonrad Witaszczyk pubkeyfile = optarg; 204480f31c2SKonrad Witaszczyk break; 205f6848434SAlfred Perlstein case 'l': 206f6848434SAlfred Perlstein do_listdumpdev = 1; 207f6848434SAlfred Perlstein break; 20883f9dfabSGarrett Wollman case 'v': 20983f9dfabSGarrett Wollman verbose = 1; 21083f9dfabSGarrett Wollman break; 21164a16434SMark Johnston case 'z': 21264a16434SMark Johnston gzip = true; 21364a16434SMark Johnston break; 21483f9dfabSGarrett Wollman default: 21583f9dfabSGarrett Wollman usage(); 21683f9dfabSGarrett Wollman } 217c0046e26SDag-Erling Smørgrav 218c0046e26SDag-Erling Smørgrav argc -= optind; 21983f9dfabSGarrett Wollman argv += optind; 22083f9dfabSGarrett Wollman 221f6848434SAlfred Perlstein if (do_listdumpdev) { 222f6848434SAlfred Perlstein listdumpdev(); 223f6848434SAlfred Perlstein exit(EX_OK); 224f6848434SAlfred Perlstein } 225f6848434SAlfred Perlstein 226c0046e26SDag-Erling Smørgrav if (argc != 1) 22783f9dfabSGarrett Wollman usage(); 22883f9dfabSGarrett Wollman 229480f31c2SKonrad Witaszczyk enable = (strcmp(argv[0], "off") != 0); 230480f31c2SKonrad Witaszczyk #ifndef HAVE_CRYPTO 231480f31c2SKonrad Witaszczyk if (pubkeyfile != NULL) { 232480f31c2SKonrad Witaszczyk enable = false; 233480f31c2SKonrad Witaszczyk warnx("Unable to use the public key. Recompile dumpon with OpenSSL support."); 234480f31c2SKonrad Witaszczyk } 235480f31c2SKonrad Witaszczyk #endif 236480f31c2SKonrad Witaszczyk 237480f31c2SKonrad Witaszczyk if (enable) { 23845a9027dSSteven Hartland char tmp[PATH_MAX]; 23945a9027dSSteven Hartland char *dumpdev; 24045a9027dSSteven Hartland 24145a9027dSSteven Hartland if (strncmp(argv[0], _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) { 24245a9027dSSteven Hartland dumpdev = argv[0]; 24345a9027dSSteven Hartland } else { 24445a9027dSSteven Hartland i = snprintf(tmp, PATH_MAX, "%s%s", _PATH_DEV, argv[0]); 24545a9027dSSteven Hartland if (i < 0) { 24645a9027dSSteven Hartland err(EX_OSERR, "%s", argv[0]); 24745a9027dSSteven Hartland } else if (i >= PATH_MAX) { 24845a9027dSSteven Hartland errno = EINVAL; 24945a9027dSSteven Hartland err(EX_DATAERR, "%s", argv[0]); 25045a9027dSSteven Hartland } 25145a9027dSSteven Hartland dumpdev = tmp; 25245a9027dSSteven Hartland } 25345a9027dSSteven Hartland fd = open(dumpdev, O_RDONLY); 2549e9c1cadSPoul-Henning Kamp if (fd < 0) 25545a9027dSSteven Hartland err(EX_OSFILE, "%s", dumpdev); 256480f31c2SKonrad Witaszczyk 25764a16434SMark Johnston if (!gzip) 25864a16434SMark Johnston check_size(fd, dumpdev); 25964a16434SMark Johnston 26064a16434SMark Johnston bzero(&kda, sizeof(kda)); 261480f31c2SKonrad Witaszczyk kda.kda_enable = 0; 262480f31c2SKonrad Witaszczyk i = ioctl(fd, DIOCSKERNELDUMP, &kda); 263480f31c2SKonrad Witaszczyk explicit_bzero(&kda, sizeof(kda)); 264480f31c2SKonrad Witaszczyk 265480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 266480f31c2SKonrad Witaszczyk if (pubkeyfile != NULL) 267480f31c2SKonrad Witaszczyk genkey(pubkeyfile, &kda); 268480f31c2SKonrad Witaszczyk #endif 269480f31c2SKonrad Witaszczyk 270480f31c2SKonrad Witaszczyk kda.kda_enable = 1; 27164a16434SMark Johnston kda.kda_compression = gzip ? KERNELDUMP_COMP_GZIP : 27264a16434SMark Johnston KERNELDUMP_COMP_NONE; 273480f31c2SKonrad Witaszczyk i = ioctl(fd, DIOCSKERNELDUMP, &kda); 274480f31c2SKonrad Witaszczyk explicit_bzero(kda.kda_encryptedkey, kda.kda_encryptedkeysize); 275480f31c2SKonrad Witaszczyk free(kda.kda_encryptedkey); 276480f31c2SKonrad Witaszczyk explicit_bzero(&kda, sizeof(kda)); 2779e9c1cadSPoul-Henning Kamp if (i == 0 && verbose) 27845a9027dSSteven Hartland printf("kernel dumps on %s\n", dumpdev); 27983f9dfabSGarrett Wollman } else { 2809e9c1cadSPoul-Henning Kamp fd = open(_PATH_DEVNULL, O_RDONLY); 2819e9c1cadSPoul-Henning Kamp if (fd < 0) 2829e9c1cadSPoul-Henning Kamp err(EX_OSFILE, "%s", _PATH_DEVNULL); 283480f31c2SKonrad Witaszczyk 284480f31c2SKonrad Witaszczyk kda.kda_enable = 0; 285480f31c2SKonrad Witaszczyk i = ioctl(fd, DIOCSKERNELDUMP, &kda); 286480f31c2SKonrad Witaszczyk explicit_bzero(&kda, sizeof(kda)); 2879e9c1cadSPoul-Henning Kamp if (i == 0 && verbose) 2889e9c1cadSPoul-Henning Kamp printf("kernel dumps disabled\n"); 28983f9dfabSGarrett Wollman } 2909e9c1cadSPoul-Henning Kamp if (i < 0) 2917f086a08SPoul-Henning Kamp err(EX_OSERR, "ioctl(DIOCSKERNELDUMP)"); 29283f9dfabSGarrett Wollman 2939e9c1cadSPoul-Henning Kamp exit (0); 29483f9dfabSGarrett Wollman } 295