1/* 2 * Check decoding of kexec_load syscall. 3 * 4 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com> 5 * Copyright (c) 2016-2017 The strace developers. 6 * 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. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "tests.h" 32 33#include <asm/unistd.h> 34 35#ifdef __NR_kexec_load 36 37# include <stdio.h> 38# include <unistd.h> 39 40struct strval { 41 kernel_ulong_t val; 42 const char *str64; 43 const char *str32; 44 const char *str; 45}; 46 47struct segm { 48 void *buf; 49 size_t bufsz; 50 void *mem; 51 size_t memsz; 52}; 53 54int 55main(void) 56{ 57 enum { 58 NUM_SEGMS = 17, 59 NUM_SEGMS_UNCUT = 5, 60 NUM_SEGMS_UNCUT_MAX = 9, 61 NUM_SEGMS_CUT = 12, 62 SEGMS_ARRAY_SIZE = sizeof(struct segm) * NUM_SEGMS, 63 }; 64 65 static const kernel_ulong_t bogus_zero = 66 sizeof(long) < sizeof(kernel_long_t) ? F8ILL_KULONG_MASK : 0; 67 static const kernel_ulong_t bogus_entry = 68 (kernel_ulong_t) 0xdeadca57badda7a1ULL; 69 static const kernel_ulong_t bogus_nsegs = 70 (kernel_ulong_t) 0xdec0ded1defaced2ULL; 71 72 static const struct strval flags[] = { 73 { (kernel_ulong_t) 0xbadc0dedda7a1054ULL, 74 "0xda7a0000 /* KEXEC_ARCH_??? */|0xbadc0ded0000", 75 "0xda7a0000 /* KEXEC_ARCH_??? */|0x", 76 "1054 /* KEXEC_??? */" }, 77 { 0, "", "", "KEXEC_ARCH_DEFAULT" }, 78 { 0x2a0003, "", "", 79 "KEXEC_ARCH_SH|KEXEC_ON_CRASH|KEXEC_PRESERVE_CONTEXT" }, 80 { 0xdead0000, "", "", "0xdead0000 /* KEXEC_ARCH_??? */" }, 81 }; 82 83 const char *errstr; 84 long rc; 85 struct segm *segms = tail_alloc(SEGMS_ARRAY_SIZE); 86 unsigned int i; 87 88 fill_memory(segms, SEGMS_ARRAY_SIZE); 89 segms[0].buf = segms[0].mem = NULL; 90 91 rc = syscall(__NR_kexec_load, bogus_zero, bogus_zero, bogus_zero, 92 flags[0].val); 93 printf("kexec_load(NULL, 0, NULL, %s%s) = %s\n", 94 sizeof(long) == 8 ? flags[0].str64 : flags[0].str32, 95 flags[0].str, sprintrc(rc)); 96 97 rc = syscall(__NR_kexec_load, bogus_entry, bogus_nsegs, 98 segms + SEGMS_ARRAY_SIZE, flags[1].val); 99 printf("kexec_load(%#lx, %lu, %p, %s) = %s\n", 100 (unsigned long) bogus_entry, (unsigned long) bogus_nsegs, 101 segms + SEGMS_ARRAY_SIZE, flags[1].str, sprintrc(rc)); 102 103 rc = syscall(__NR_kexec_load, bogus_entry, NUM_SEGMS, 104 segms, flags[2].val); 105 printf("kexec_load(%#lx, %lu, %p, %s) = %s\n", 106 (unsigned long) bogus_entry, (unsigned long) NUM_SEGMS, 107 segms, flags[2].str, sprintrc(rc)); 108 109 rc = syscall(__NR_kexec_load, bogus_entry, NUM_SEGMS_CUT, 110 segms, flags[3].val); 111 errstr = sprintrc(rc); 112 printf("kexec_load(%#lx, %lu, [{buf=NULL, bufsz=%zu, mem=NULL, " 113 "memsz=%zu}, ", 114 (unsigned long) bogus_entry, (unsigned long) NUM_SEGMS_CUT, 115 segms[0].bufsz, segms[0].memsz); 116 for (i = 1; i < NUM_SEGMS_UNCUT_MAX; i++) 117 printf("{buf=%p, bufsz=%zu, mem=%p, memsz=%zu}, ", 118 segms[i].buf, segms[i].bufsz, 119 segms[i].mem, segms[i].memsz); 120 printf("...], %s) = %s\n", flags[3].str, errstr); 121 122 rc = syscall(__NR_kexec_load, bogus_entry, NUM_SEGMS_CUT, 123 segms + (NUM_SEGMS - NUM_SEGMS_UNCUT_MAX), 124 flags[0].val); 125 errstr = sprintrc(rc); 126 printf("kexec_load(%#lx, %lu, [", 127 (unsigned long) bogus_entry, (unsigned long) NUM_SEGMS_CUT); 128 for (i = NUM_SEGMS - NUM_SEGMS_UNCUT_MAX; i < NUM_SEGMS; i++) 129 printf("{buf=%p, bufsz=%zu, mem=%p, memsz=%zu}, ", 130 segms[i].buf, segms[i].bufsz, 131 segms[i].mem, segms[i].memsz); 132 printf("%p], %s%s) = %s\n", 133 segms + NUM_SEGMS, 134 sizeof(long) == 8 ? flags[0].str64 : flags[0].str32, 135 flags[0].str, errstr); 136 137 rc = syscall(__NR_kexec_load, bogus_entry, NUM_SEGMS_UNCUT, 138 segms + (NUM_SEGMS - NUM_SEGMS_UNCUT), 139 flags[1].val); 140 errstr = sprintrc(rc); 141 printf("kexec_load(%#lx, %lu, [", 142 (unsigned long) bogus_entry, (unsigned long) NUM_SEGMS_UNCUT); 143 for (i = NUM_SEGMS - NUM_SEGMS_UNCUT; i < NUM_SEGMS; i++) 144 printf("{buf=%p, bufsz=%zu, mem=%p, memsz=%zu}%s", 145 segms[i].buf, segms[i].bufsz, 146 segms[i].mem, segms[i].memsz, 147 (i == NUM_SEGMS - 1) ? "" : ", "); 148 printf("], %s) = %s\n", flags[1].str, errstr); 149 150 rc = syscall(__NR_kexec_load, bogus_entry, NUM_SEGMS_CUT, 151 segms + 1, flags[2].val); 152 errstr = sprintrc(rc); 153 printf("kexec_load(%#lx, %lu, [", 154 (unsigned long) bogus_entry, (unsigned long) NUM_SEGMS_CUT); 155 for (i = 1; i < NUM_SEGMS_UNCUT_MAX + 1; i++) 156 printf("{buf=%p, bufsz=%zu, mem=%p, memsz=%zu}, ", 157 segms[i].buf, segms[i].bufsz, 158 segms[i].mem, segms[i].memsz); 159 printf("...], %s) = %s\n", flags[2].str, errstr); 160 161 puts("+++ exited with 0 +++"); 162 163 return 0; 164} 165 166#else 167 168SKIP_MAIN_UNDEFINED("__NR_kexec_load"); 169 170#endif 171