183f9dfabSGarrett Wollman /* 283f9dfabSGarrett Wollman * Copyright (c) 1980, 1993 383f9dfabSGarrett Wollman * The Regents of the University of California. All rights reserved. 483f9dfabSGarrett Wollman * 583f9dfabSGarrett Wollman * Redistribution and use in source and binary forms, with or without 683f9dfabSGarrett Wollman * modification, are permitted provided that the following conditions 783f9dfabSGarrett Wollman * are met: 883f9dfabSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 983f9dfabSGarrett Wollman * notice, this list of conditions and the following disclaimer. 1083f9dfabSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 1183f9dfabSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 1283f9dfabSGarrett Wollman * documentation and/or other materials provided with the distribution. 13*fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 1483f9dfabSGarrett Wollman * may be used to endorse or promote products derived from this software 1583f9dfabSGarrett Wollman * without specific prior written permission. 1683f9dfabSGarrett Wollman * 1783f9dfabSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1883f9dfabSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1983f9dfabSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2083f9dfabSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2183f9dfabSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2283f9dfabSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2383f9dfabSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2483f9dfabSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2583f9dfabSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2683f9dfabSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2783f9dfabSGarrett Wollman * SUCH DAMAGE. 2883f9dfabSGarrett Wollman */ 2983f9dfabSGarrett Wollman 30c69284caSDavid E. O'Brien #if 0 3183f9dfabSGarrett Wollman #ifndef lint 328f034b11SPhilippe Charnier static const char copyright[] = 3383f9dfabSGarrett Wollman "@(#) Copyright (c) 1980, 1993\n\ 3483f9dfabSGarrett Wollman The Regents of the University of California. All rights reserved.\n"; 3583f9dfabSGarrett Wollman #endif /* not lint */ 3683f9dfabSGarrett Wollman 3783f9dfabSGarrett Wollman #ifndef lint 388f034b11SPhilippe Charnier static char sccsid[] = "From: @(#)swapon.c 8.1 (Berkeley) 6/5/93"; 3983f9dfabSGarrett Wollman #endif /* not lint */ 40c69284caSDavid E. O'Brien #endif 41c69284caSDavid E. O'Brien #include <sys/cdefs.h> 42c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4383f9dfabSGarrett Wollman 4483f9dfabSGarrett Wollman #include <sys/param.h> 45480f31c2SKonrad Witaszczyk #include <sys/capsicum.h> 462dd527b3SPoul-Henning Kamp #include <sys/disk.h> 47c0046e26SDag-Erling Smørgrav #include <sys/sysctl.h> 4883f9dfabSGarrett Wollman 49480f31c2SKonrad Witaszczyk #include <assert.h> 50c0046e26SDag-Erling Smørgrav #include <err.h> 51f6848434SAlfred Perlstein #include <errno.h> 52c0046e26SDag-Erling Smørgrav #include <fcntl.h> 53c0046e26SDag-Erling Smørgrav #include <paths.h> 54480f31c2SKonrad Witaszczyk #include <stdbool.h> 55c0046e26SDag-Erling Smørgrav #include <stdint.h> 56c0046e26SDag-Erling Smørgrav #include <stdio.h> 57c0046e26SDag-Erling Smørgrav #include <stdlib.h> 58c0046e26SDag-Erling Smørgrav #include <string.h> 59c0046e26SDag-Erling Smørgrav #include <sysexits.h> 60c0046e26SDag-Erling Smørgrav #include <unistd.h> 61c0046e26SDag-Erling Smørgrav 62480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 63480f31c2SKonrad Witaszczyk #include <openssl/err.h> 64480f31c2SKonrad Witaszczyk #include <openssl/pem.h> 65480f31c2SKonrad Witaszczyk #include <openssl/rsa.h> 66480f31c2SKonrad Witaszczyk #endif 67480f31c2SKonrad Witaszczyk 68c0046e26SDag-Erling Smørgrav static int verbose; 69c0046e26SDag-Erling Smørgrav 70c0046e26SDag-Erling Smørgrav static void 71c0046e26SDag-Erling Smørgrav usage(void) 72c0046e26SDag-Erling Smørgrav { 73f6848434SAlfred Perlstein fprintf(stderr, "%s\n%s\n%s\n", 74480f31c2SKonrad Witaszczyk "usage: dumpon [-v] [-k public_key_file] special_file", 75f6848434SAlfred Perlstein " dumpon [-v] off", 764a790eddSAlfred Perlstein " dumpon [-v] -l"); 77c0046e26SDag-Erling Smørgrav exit(EX_USAGE); 78c0046e26SDag-Erling Smørgrav } 79c0046e26SDag-Erling Smørgrav 80c0046e26SDag-Erling Smørgrav static void 81c0046e26SDag-Erling Smørgrav check_size(int fd, const char *fn) 82c0046e26SDag-Erling Smørgrav { 83c0046e26SDag-Erling Smørgrav int name[] = { CTL_HW, HW_PHYSMEM }; 840bfc2a12SMarcelo Araujo size_t namelen = nitems(name); 85c0046e26SDag-Erling Smørgrav unsigned long physmem; 86ce893772SPaul Saab size_t len; 87c0046e26SDag-Erling Smørgrav off_t mediasize; 88ce893772SPaul Saab int minidump; 89c0046e26SDag-Erling Smørgrav 90b54a17cdSJohn Baldwin len = sizeof(minidump); 91ce893772SPaul Saab if (sysctlbyname("debug.minidump", &minidump, &len, NULL, 0) == 0 && 92ce893772SPaul Saab minidump == 1) 93ce893772SPaul Saab return; 94b54a17cdSJohn Baldwin len = sizeof(physmem); 95c0046e26SDag-Erling Smørgrav if (sysctl(name, namelen, &physmem, &len, NULL, 0) != 0) 96c0046e26SDag-Erling Smørgrav err(EX_OSERR, "can't get memory size"); 97c0046e26SDag-Erling Smørgrav if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) 98c0046e26SDag-Erling Smørgrav err(EX_OSERR, "%s: can't get size", fn); 999872f15dSDag-Erling Smørgrav if ((uintmax_t)mediasize < (uintmax_t)physmem) { 100c0046e26SDag-Erling Smørgrav if (verbose) 101c0046e26SDag-Erling Smørgrav printf("%s is smaller than physical memory\n", fn); 102c0046e26SDag-Erling Smørgrav exit(EX_IOERR); 103c0046e26SDag-Erling Smørgrav } 104c0046e26SDag-Erling Smørgrav } 10583f9dfabSGarrett Wollman 106480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 107480f31c2SKonrad Witaszczyk static void 108480f31c2SKonrad Witaszczyk genkey(const char *pubkeyfile, struct diocskerneldump_arg *kda) 109480f31c2SKonrad Witaszczyk { 110480f31c2SKonrad Witaszczyk FILE *fp; 111480f31c2SKonrad Witaszczyk RSA *pubkey; 112480f31c2SKonrad Witaszczyk 113480f31c2SKonrad Witaszczyk assert(pubkeyfile != NULL); 114480f31c2SKonrad Witaszczyk assert(kda != NULL); 115480f31c2SKonrad Witaszczyk 116480f31c2SKonrad Witaszczyk fp = NULL; 117480f31c2SKonrad Witaszczyk pubkey = NULL; 118480f31c2SKonrad Witaszczyk 119480f31c2SKonrad Witaszczyk fp = fopen(pubkeyfile, "r"); 120480f31c2SKonrad Witaszczyk if (fp == NULL) 121480f31c2SKonrad Witaszczyk err(1, "Unable to open %s", pubkeyfile); 122480f31c2SKonrad Witaszczyk 123480f31c2SKonrad Witaszczyk if (cap_enter() < 0 && errno != ENOSYS) 124480f31c2SKonrad Witaszczyk err(1, "Unable to enter capability mode"); 125480f31c2SKonrad Witaszczyk 126480f31c2SKonrad Witaszczyk pubkey = RSA_new(); 127480f31c2SKonrad Witaszczyk if (pubkey == NULL) { 128480f31c2SKonrad Witaszczyk errx(1, "Unable to allocate an RSA structure: %s", 129480f31c2SKonrad Witaszczyk ERR_error_string(ERR_get_error(), NULL)); 130480f31c2SKonrad Witaszczyk } 131480f31c2SKonrad Witaszczyk 132480f31c2SKonrad Witaszczyk pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL); 133480f31c2SKonrad Witaszczyk fclose(fp); 134480f31c2SKonrad Witaszczyk fp = NULL; 135480f31c2SKonrad Witaszczyk if (pubkey == NULL) 136480f31c2SKonrad Witaszczyk errx(1, "Unable to read data from %s.", pubkeyfile); 137480f31c2SKonrad Witaszczyk 138480f31c2SKonrad Witaszczyk kda->kda_encryptedkeysize = RSA_size(pubkey); 139480f31c2SKonrad Witaszczyk if (kda->kda_encryptedkeysize > KERNELDUMP_ENCKEY_MAX_SIZE) { 140480f31c2SKonrad Witaszczyk errx(1, "Public key has to be at most %db long.", 141480f31c2SKonrad Witaszczyk 8 * KERNELDUMP_ENCKEY_MAX_SIZE); 142480f31c2SKonrad Witaszczyk } 143480f31c2SKonrad Witaszczyk 144480f31c2SKonrad Witaszczyk kda->kda_encryptedkey = calloc(1, kda->kda_encryptedkeysize); 145480f31c2SKonrad Witaszczyk if (kda->kda_encryptedkey == NULL) 146480f31c2SKonrad Witaszczyk err(1, "Unable to allocate encrypted key"); 147480f31c2SKonrad Witaszczyk 148480f31c2SKonrad Witaszczyk kda->kda_encryption = KERNELDUMP_ENC_AES_256_CBC; 149480f31c2SKonrad Witaszczyk arc4random_buf(kda->kda_key, sizeof(kda->kda_key)); 150480f31c2SKonrad Witaszczyk if (RSA_public_encrypt(sizeof(kda->kda_key), kda->kda_key, 151480f31c2SKonrad Witaszczyk kda->kda_encryptedkey, pubkey, 152480f31c2SKonrad Witaszczyk RSA_PKCS1_PADDING) != (int)kda->kda_encryptedkeysize) { 153480f31c2SKonrad Witaszczyk errx(1, "Unable to encrypt the one-time key."); 154480f31c2SKonrad Witaszczyk } 155480f31c2SKonrad Witaszczyk RSA_free(pubkey); 156480f31c2SKonrad Witaszczyk } 157480f31c2SKonrad Witaszczyk #endif 158480f31c2SKonrad Witaszczyk 159f6848434SAlfred Perlstein static void 160f6848434SAlfred Perlstein listdumpdev(void) 161f6848434SAlfred Perlstein { 162f6848434SAlfred Perlstein char dumpdev[PATH_MAX]; 163f6848434SAlfred Perlstein size_t len; 164f6848434SAlfred Perlstein const char *sysctlname = "kern.shutdown.dumpdevname"; 165f6848434SAlfred Perlstein 166f6848434SAlfred Perlstein len = sizeof(dumpdev); 167f6848434SAlfred Perlstein if (sysctlbyname(sysctlname, &dumpdev, &len, NULL, 0) != 0) { 168f6848434SAlfred Perlstein if (errno == ENOMEM) { 169f6848434SAlfred Perlstein err(EX_OSERR, "Kernel returned too large of a buffer for '%s'\n", 170f6848434SAlfred Perlstein sysctlname); 171f6848434SAlfred Perlstein } else { 172f6848434SAlfred Perlstein err(EX_OSERR, "Sysctl get '%s'\n", sysctlname); 173f6848434SAlfred Perlstein } 174f6848434SAlfred Perlstein } 175f6848434SAlfred Perlstein if (verbose) { 176f6848434SAlfred Perlstein printf("kernel dumps on "); 177f6848434SAlfred Perlstein } 178f6848434SAlfred Perlstein if (strlen(dumpdev) == 0) { 179f6848434SAlfred Perlstein printf("%s\n", _PATH_DEVNULL); 180f6848434SAlfred Perlstein } else { 181f6848434SAlfred Perlstein printf("%s\n", dumpdev); 182f6848434SAlfred Perlstein } 183f6848434SAlfred Perlstein } 184f6848434SAlfred Perlstein 18583f9dfabSGarrett Wollman int 186d1a939c1SWarner Losh main(int argc, char *argv[]) 18783f9dfabSGarrett Wollman { 188480f31c2SKonrad Witaszczyk struct diocskerneldump_arg kda; 189480f31c2SKonrad Witaszczyk const char *pubkeyfile; 190c0046e26SDag-Erling Smørgrav int ch; 1919e9c1cadSPoul-Henning Kamp int i, fd; 192f6848434SAlfred Perlstein int do_listdumpdev = 0; 193480f31c2SKonrad Witaszczyk bool enable; 19483f9dfabSGarrett Wollman 195480f31c2SKonrad Witaszczyk pubkeyfile = NULL; 196480f31c2SKonrad Witaszczyk 197480f31c2SKonrad Witaszczyk while ((ch = getopt(argc, argv, "k:lv")) != -1) 19883f9dfabSGarrett Wollman switch((char)ch) { 199480f31c2SKonrad Witaszczyk case 'k': 200480f31c2SKonrad Witaszczyk pubkeyfile = optarg; 201480f31c2SKonrad Witaszczyk break; 202f6848434SAlfred Perlstein case 'l': 203f6848434SAlfred Perlstein do_listdumpdev = 1; 204f6848434SAlfred Perlstein break; 20583f9dfabSGarrett Wollman case 'v': 20683f9dfabSGarrett Wollman verbose = 1; 20783f9dfabSGarrett Wollman break; 20883f9dfabSGarrett Wollman default: 20983f9dfabSGarrett Wollman usage(); 21083f9dfabSGarrett Wollman } 211c0046e26SDag-Erling Smørgrav 212c0046e26SDag-Erling Smørgrav argc -= optind; 21383f9dfabSGarrett Wollman argv += optind; 21483f9dfabSGarrett Wollman 215f6848434SAlfred Perlstein if (do_listdumpdev) { 216f6848434SAlfred Perlstein listdumpdev(); 217f6848434SAlfred Perlstein exit(EX_OK); 218f6848434SAlfred Perlstein } 219f6848434SAlfred Perlstein 220c0046e26SDag-Erling Smørgrav if (argc != 1) 22183f9dfabSGarrett Wollman usage(); 22283f9dfabSGarrett Wollman 223480f31c2SKonrad Witaszczyk enable = (strcmp(argv[0], "off") != 0); 224480f31c2SKonrad Witaszczyk #ifndef HAVE_CRYPTO 225480f31c2SKonrad Witaszczyk if (pubkeyfile != NULL) { 226480f31c2SKonrad Witaszczyk enable = false; 227480f31c2SKonrad Witaszczyk warnx("Unable to use the public key. Recompile dumpon with OpenSSL support."); 228480f31c2SKonrad Witaszczyk } 229480f31c2SKonrad Witaszczyk #endif 230480f31c2SKonrad Witaszczyk 231480f31c2SKonrad Witaszczyk if (enable) { 23245a9027dSSteven Hartland char tmp[PATH_MAX]; 23345a9027dSSteven Hartland char *dumpdev; 23445a9027dSSteven Hartland 23545a9027dSSteven Hartland if (strncmp(argv[0], _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) { 23645a9027dSSteven Hartland dumpdev = argv[0]; 23745a9027dSSteven Hartland } else { 23845a9027dSSteven Hartland i = snprintf(tmp, PATH_MAX, "%s%s", _PATH_DEV, argv[0]); 23945a9027dSSteven Hartland if (i < 0) { 24045a9027dSSteven Hartland err(EX_OSERR, "%s", argv[0]); 24145a9027dSSteven Hartland } else if (i >= PATH_MAX) { 24245a9027dSSteven Hartland errno = EINVAL; 24345a9027dSSteven Hartland err(EX_DATAERR, "%s", argv[0]); 24445a9027dSSteven Hartland } 24545a9027dSSteven Hartland dumpdev = tmp; 24645a9027dSSteven Hartland } 24745a9027dSSteven Hartland fd = open(dumpdev, O_RDONLY); 2489e9c1cadSPoul-Henning Kamp if (fd < 0) 24945a9027dSSteven Hartland err(EX_OSFILE, "%s", dumpdev); 25045a9027dSSteven Hartland check_size(fd, dumpdev); 251480f31c2SKonrad Witaszczyk bzero(&kda, sizeof(kda)); 252480f31c2SKonrad Witaszczyk 253480f31c2SKonrad Witaszczyk kda.kda_enable = 0; 254480f31c2SKonrad Witaszczyk i = ioctl(fd, DIOCSKERNELDUMP, &kda); 255480f31c2SKonrad Witaszczyk explicit_bzero(&kda, sizeof(kda)); 256480f31c2SKonrad Witaszczyk 257480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 258480f31c2SKonrad Witaszczyk if (pubkeyfile != NULL) 259480f31c2SKonrad Witaszczyk genkey(pubkeyfile, &kda); 260480f31c2SKonrad Witaszczyk #endif 261480f31c2SKonrad Witaszczyk 262480f31c2SKonrad Witaszczyk kda.kda_enable = 1; 263480f31c2SKonrad Witaszczyk i = ioctl(fd, DIOCSKERNELDUMP, &kda); 264480f31c2SKonrad Witaszczyk explicit_bzero(kda.kda_encryptedkey, kda.kda_encryptedkeysize); 265480f31c2SKonrad Witaszczyk free(kda.kda_encryptedkey); 266480f31c2SKonrad Witaszczyk explicit_bzero(&kda, sizeof(kda)); 2679e9c1cadSPoul-Henning Kamp if (i == 0 && verbose) 26845a9027dSSteven Hartland printf("kernel dumps on %s\n", dumpdev); 26983f9dfabSGarrett Wollman } else { 2709e9c1cadSPoul-Henning Kamp fd = open(_PATH_DEVNULL, O_RDONLY); 2719e9c1cadSPoul-Henning Kamp if (fd < 0) 2729e9c1cadSPoul-Henning Kamp err(EX_OSFILE, "%s", _PATH_DEVNULL); 273480f31c2SKonrad Witaszczyk 274480f31c2SKonrad Witaszczyk kda.kda_enable = 0; 275480f31c2SKonrad Witaszczyk i = ioctl(fd, DIOCSKERNELDUMP, &kda); 276480f31c2SKonrad Witaszczyk explicit_bzero(&kda, sizeof(kda)); 2779e9c1cadSPoul-Henning Kamp if (i == 0 && verbose) 2789e9c1cadSPoul-Henning Kamp printf("kernel dumps disabled\n"); 27983f9dfabSGarrett Wollman } 2809e9c1cadSPoul-Henning Kamp if (i < 0) 2817f086a08SPoul-Henning Kamp err(EX_OSERR, "ioctl(DIOCSKERNELDUMP)"); 28283f9dfabSGarrett Wollman 2839e9c1cadSPoul-Henning Kamp exit (0); 28483f9dfabSGarrett Wollman } 285