1 /* 2 * Check decoding of modify_ldt syscall. 3 * 4 * Copyright (c) 2018 The strace developers. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "tests.h" 31 32 #include <asm/unistd.h> 33 34 #if defined __NR_modify_ldt && defined HAVE_STRUCT_USER_DESC 35 36 # include <errno.h> 37 # include <stdio.h> 38 # include <unistd.h> 39 40 # include "print_user_desc.c" 41 42 void 43 printrc(long rc) 44 { 45 #ifdef __x86_64__ 46 int err = -rc; 47 48 /* Thanks, long return type of syscall(2) */ 49 printf("%lld", zero_extend_signed_to_ull(rc)); 50 51 if (err > 0 && err < 0x1000) { 52 errno = err; 53 printf(" %s (%m)", errno2name()); 54 } 55 #else 56 printf("%s", sprintrc(rc)); 57 #endif 58 59 puts(""); 60 } 61 62 int 63 main(void) 64 { 65 static const kernel_ulong_t bogus_func = 66 (kernel_ulong_t) 0xbadc0dedda7a1057ULL; 67 static const kernel_ulong_t bogus_bytecount = 68 (kernel_ulong_t) 0xdeadfacefa57beefULL; 69 70 struct user_desc *us = tail_alloc(sizeof(*us)); 71 unsigned int *bogus_int = tail_alloc(sizeof(*bogus_int)); 72 long rc; 73 74 fill_memory(us, sizeof(*us)); 75 76 rc = syscall(__NR_modify_ldt, 0, 0, 0); 77 printf("modify_ldt(0, NULL, 0) = "); 78 printrc(rc); 79 80 rc = syscall(__NR_modify_ldt, bogus_func, (kernel_long_t) -1, 81 bogus_bytecount); 82 printf("modify_ldt(%d, %#llx, %llu) = ", 83 (int) bogus_func, 84 zero_extend_signed_to_ull((kernel_long_t) -1), 85 (unsigned long long) bogus_bytecount); 86 printrc(rc); 87 88 rc = syscall(__NR_modify_ldt, bogus_func, us + 1, 0); 89 printf("modify_ldt(%d, %p, 0) = ", (int) bogus_func, us + 1); 90 printrc(rc); 91 92 rc = syscall(__NR_modify_ldt, bogus_func, us, 42); 93 printf("modify_ldt(%d, %p, 42) = ", (int) bogus_func, us); 94 printrc(rc); 95 96 rc = syscall(__NR_modify_ldt, bogus_func, us + 1, sizeof(*us)); 97 printf("modify_ldt(%d, %p, %zu) = ", 98 (int) bogus_func, us + 1, sizeof(*us)); 99 printrc(rc); 100 101 /* 102 * print_user_desc handles entry_number field in a special way for 103 * get_thread_area syscall, so let's also check here that we don't 104 * retrieve it accidentally. 105 */ 106 rc = syscall(__NR_modify_ldt, bogus_func, bogus_int, sizeof(*us)); 107 printf("modify_ldt(%d, %p, %zu) = ", 108 (int) bogus_func, bogus_int, sizeof(*us)); 109 printrc(rc); 110 111 rc = syscall(__NR_modify_ldt, bogus_func, us, sizeof(*us)); 112 printf("modify_ldt(%d, ", (int) bogus_func); 113 print_user_desc(us, NULL); 114 printf(", %zu) = ", sizeof(*us)); 115 printrc(rc); 116 117 fill_memory_ex(us, sizeof(*us), 0x55, 80); 118 us->entry_number = -1; 119 us->base_addr = 0; 120 us->limit = 0; 121 122 rc = syscall(__NR_modify_ldt, bogus_func, us, sizeof(*us)); 123 printf("modify_ldt(%d, ", (int) bogus_func); 124 print_user_desc(us, "-1"); 125 printf(", %zu) = ", sizeof(*us)); 126 printrc(rc); 127 128 puts("+++ exited with 0 +++"); 129 130 return 0; 131 } 132 133 #else 134 135 SKIP_MAIN_UNDEFINED("__NR_modify_ldt && HAVE_STRUCT_USER_DESC"); 136 137 #endif 138