Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nolibc.2023.04.04a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu

Pull nolibc updates from Paul McKenney:

- Add support for loongarch

- Fix stack-protector issues

- Support additional integral types and signal-related macros

- Add support for stdin, stdout, and stderr

- Add getuid() and geteuid()

- Allow S_I* macros to be overridden by program

- Defer to linux/fcntl.h and linux/stat.h to avoid duplicate
definitions

- Many improvements to the selftests

* tag 'nolibc.2023.04.04a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: (22 commits)
tools/nolibc: x86_64: add stackprotector support
tools/nolibc: i386: add stackprotector support
tools/nolibc: tests: add test for -fstack-protector
tools/nolibc: tests: fold in no-stack-protector cflags
tools/nolibc: add support for stack protector
tools/nolibc: tests: constify test_names
tools/nolibc: add helpers for wait() signal exits
tools/nolibc: add definitions for standard fds
selftests/nolibc: Adjust indentation for Makefile
selftests/nolibc: Add support for LoongArch
tools/nolibc: Add support for LoongArch
tools/nolibc: Add statx() and make stat() rely on statx() if necessary
tools/nolibc: Include linux/fcntl.h and remove duplicate code
tools/nolibc: check for S_I* macros before defining them
selftests/nolibc: skip the chroot_root and link_dir tests when not privileged
tools/nolibc: add getuid() and geteuid()
tools/nolibc: add tests for the integer limits in stdint.h
tools/nolibc: enlarge column width of tests
tools/nolibc: add integer types and integer limit macros
tools/nolibc: add stdint.h
...

+718 -115
+1
tools/include/nolibc/.gitignore
··· 1 + sysroot
+2 -2
tools/include/nolibc/Makefile
··· 25 25 26 26 nolibc_arch := $(patsubst arm64,aarch64,$(ARCH)) 27 27 arch_file := arch-$(nolibc_arch).h 28 - all_files := ctype.h errno.h nolibc.h signal.h std.h stdio.h stdlib.h string.h \ 29 - sys.h time.h types.h unistd.h 28 + all_files := ctype.h errno.h nolibc.h signal.h stackprotector.h std.h stdint.h \ 29 + stdio.h stdlib.h string.h sys.h time.h types.h unistd.h 30 30 31 31 # install all headers needed to support a bare-metal compiler 32 32 all: headers
+6 -1
tools/include/nolibc/arch-i386.h
··· 181 181 char **environ __attribute__((weak)); 182 182 const unsigned long *_auxv __attribute__((weak)); 183 183 184 + #define __ARCH_SUPPORTS_STACK_PROTECTOR 185 + 184 186 /* startup code */ 185 187 /* 186 188 * i386 System V ABI mandates: ··· 190 188 * 2) The deepest stack frame should be set to zero 191 189 * 192 190 */ 193 - void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) 191 + void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void) 194 192 { 195 193 __asm__ volatile ( 194 + #ifdef NOLIBC_STACKPROTECTOR 195 + "call __stack_chk_init\n" // initialize stack protector 196 + #endif 196 197 "pop %eax\n" // argc (first arg, %eax) 197 198 "mov %esp, %ebx\n" // argv[] (second arg, %ebx) 198 199 "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
+200
tools/include/nolibc/arch-loongarch.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + /* 3 + * LoongArch specific definitions for NOLIBC 4 + * Copyright (C) 2023 Loongson Technology Corporation Limited 5 + */ 6 + 7 + #ifndef _NOLIBC_ARCH_LOONGARCH_H 8 + #define _NOLIBC_ARCH_LOONGARCH_H 9 + 10 + /* Syscalls for LoongArch : 11 + * - stack is 16-byte aligned 12 + * - syscall number is passed in a7 13 + * - arguments are in a0, a1, a2, a3, a4, a5 14 + * - the system call is performed by calling "syscall 0" 15 + * - syscall return comes in a0 16 + * - the arguments are cast to long and assigned into the target 17 + * registers which are then simply passed as registers to the asm code, 18 + * so that we don't have to experience issues with register constraints. 19 + * 20 + * On LoongArch, select() is not implemented so we have to use pselect6(). 21 + */ 22 + #define __ARCH_WANT_SYS_PSELECT6 23 + 24 + #define my_syscall0(num) \ 25 + ({ \ 26 + register long _num __asm__ ("a7") = (num); \ 27 + register long _arg1 __asm__ ("a0"); \ 28 + \ 29 + __asm__ volatile ( \ 30 + "syscall 0\n" \ 31 + : "=r"(_arg1) \ 32 + : "r"(_num) \ 33 + : "memory", "$t0", "$t1", "$t2", "$t3", \ 34 + "$t4", "$t5", "$t6", "$t7", "$t8" \ 35 + ); \ 36 + _arg1; \ 37 + }) 38 + 39 + #define my_syscall1(num, arg1) \ 40 + ({ \ 41 + register long _num __asm__ ("a7") = (num); \ 42 + register long _arg1 __asm__ ("a0") = (long)(arg1); \ 43 + \ 44 + __asm__ volatile ( \ 45 + "syscall 0\n" \ 46 + : "+r"(_arg1) \ 47 + : "r"(_num) \ 48 + : "memory", "$t0", "$t1", "$t2", "$t3", \ 49 + "$t4", "$t5", "$t6", "$t7", "$t8" \ 50 + ); \ 51 + _arg1; \ 52 + }) 53 + 54 + #define my_syscall2(num, arg1, arg2) \ 55 + ({ \ 56 + register long _num __asm__ ("a7") = (num); \ 57 + register long _arg1 __asm__ ("a0") = (long)(arg1); \ 58 + register long _arg2 __asm__ ("a1") = (long)(arg2); \ 59 + \ 60 + __asm__ volatile ( \ 61 + "syscall 0\n" \ 62 + : "+r"(_arg1) \ 63 + : "r"(_arg2), \ 64 + "r"(_num) \ 65 + : "memory", "$t0", "$t1", "$t2", "$t3", \ 66 + "$t4", "$t5", "$t6", "$t7", "$t8" \ 67 + ); \ 68 + _arg1; \ 69 + }) 70 + 71 + #define my_syscall3(num, arg1, arg2, arg3) \ 72 + ({ \ 73 + register long _num __asm__ ("a7") = (num); \ 74 + register long _arg1 __asm__ ("a0") = (long)(arg1); \ 75 + register long _arg2 __asm__ ("a1") = (long)(arg2); \ 76 + register long _arg3 __asm__ ("a2") = (long)(arg3); \ 77 + \ 78 + __asm__ volatile ( \ 79 + "syscall 0\n" \ 80 + : "+r"(_arg1) \ 81 + : "r"(_arg2), "r"(_arg3), \ 82 + "r"(_num) \ 83 + : "memory", "$t0", "$t1", "$t2", "$t3", \ 84 + "$t4", "$t5", "$t6", "$t7", "$t8" \ 85 + ); \ 86 + _arg1; \ 87 + }) 88 + 89 + #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 90 + ({ \ 91 + register long _num __asm__ ("a7") = (num); \ 92 + register long _arg1 __asm__ ("a0") = (long)(arg1); \ 93 + register long _arg2 __asm__ ("a1") = (long)(arg2); \ 94 + register long _arg3 __asm__ ("a2") = (long)(arg3); \ 95 + register long _arg4 __asm__ ("a3") = (long)(arg4); \ 96 + \ 97 + __asm__ volatile ( \ 98 + "syscall 0\n" \ 99 + : "+r"(_arg1) \ 100 + : "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 101 + "r"(_num) \ 102 + : "memory", "$t0", "$t1", "$t2", "$t3", \ 103 + "$t4", "$t5", "$t6", "$t7", "$t8" \ 104 + ); \ 105 + _arg1; \ 106 + }) 107 + 108 + #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 109 + ({ \ 110 + register long _num __asm__ ("a7") = (num); \ 111 + register long _arg1 __asm__ ("a0") = (long)(arg1); \ 112 + register long _arg2 __asm__ ("a1") = (long)(arg2); \ 113 + register long _arg3 __asm__ ("a2") = (long)(arg3); \ 114 + register long _arg4 __asm__ ("a3") = (long)(arg4); \ 115 + register long _arg5 __asm__ ("a4") = (long)(arg5); \ 116 + \ 117 + __asm__ volatile ( \ 118 + "syscall 0\n" \ 119 + : "+r"(_arg1) \ 120 + : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 121 + "r"(_num) \ 122 + : "memory", "$t0", "$t1", "$t2", "$t3", \ 123 + "$t4", "$t5", "$t6", "$t7", "$t8" \ 124 + ); \ 125 + _arg1; \ 126 + }) 127 + 128 + #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 129 + ({ \ 130 + register long _num __asm__ ("a7") = (num); \ 131 + register long _arg1 __asm__ ("a0") = (long)(arg1); \ 132 + register long _arg2 __asm__ ("a1") = (long)(arg2); \ 133 + register long _arg3 __asm__ ("a2") = (long)(arg3); \ 134 + register long _arg4 __asm__ ("a3") = (long)(arg4); \ 135 + register long _arg5 __asm__ ("a4") = (long)(arg5); \ 136 + register long _arg6 __asm__ ("a5") = (long)(arg6); \ 137 + \ 138 + __asm__ volatile ( \ 139 + "syscall 0\n" \ 140 + : "+r"(_arg1) \ 141 + : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \ 142 + "r"(_num) \ 143 + : "memory", "$t0", "$t1", "$t2", "$t3", \ 144 + "$t4", "$t5", "$t6", "$t7", "$t8" \ 145 + ); \ 146 + _arg1; \ 147 + }) 148 + 149 + char **environ __attribute__((weak)); 150 + const unsigned long *_auxv __attribute__((weak)); 151 + 152 + #if __loongarch_grlen == 32 153 + #define LONGLOG "2" 154 + #define SZREG "4" 155 + #define REG_L "ld.w" 156 + #define LONG_S "st.w" 157 + #define LONG_ADD "add.w" 158 + #define LONG_ADDI "addi.w" 159 + #define LONG_SLL "slli.w" 160 + #define LONG_BSTRINS "bstrins.w" 161 + #else // __loongarch_grlen == 64 162 + #define LONGLOG "3" 163 + #define SZREG "8" 164 + #define REG_L "ld.d" 165 + #define LONG_S "st.d" 166 + #define LONG_ADD "add.d" 167 + #define LONG_ADDI "addi.d" 168 + #define LONG_SLL "slli.d" 169 + #define LONG_BSTRINS "bstrins.d" 170 + #endif 171 + 172 + /* startup code */ 173 + void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) 174 + { 175 + __asm__ volatile ( 176 + REG_L " $a0, $sp, 0\n" // argc (a0) was in the stack 177 + LONG_ADDI " $a1, $sp, "SZREG"\n" // argv (a1) = sp + SZREG 178 + LONG_SLL " $a2, $a0, "LONGLOG"\n" // envp (a2) = SZREG*argc ... 179 + LONG_ADDI " $a2, $a2, "SZREG"\n" // + SZREG (skip null) 180 + LONG_ADD " $a2, $a2, $a1\n" // + argv 181 + 182 + "move $a3, $a2\n" // iterate a3 over envp to find auxv (after NULL) 183 + "0:\n" // do { 184 + REG_L " $a4, $a3, 0\n" // a4 = *a3; 185 + LONG_ADDI " $a3, $a3, "SZREG"\n" // a3 += sizeof(void*); 186 + "bne $a4, $zero, 0b\n" // } while (a4); 187 + "la.pcrel $a4, _auxv\n" // a4 = &_auxv 188 + LONG_S " $a3, $a4, 0\n" // store a3 into _auxv 189 + 190 + "la.pcrel $a3, environ\n" // a3 = &environ 191 + LONG_S " $a2, $a3, 0\n" // store envp(a2) into environ 192 + LONG_BSTRINS " $sp, $zero, 3, 0\n" // sp must be 16-byte aligned 193 + "bl main\n" // main() returns the status code, we'll exit with it. 194 + "li.w $a7, 93\n" // NR_exit == 93 195 + "syscall 0\n" 196 + ); 197 + __builtin_unreachable(); 198 + } 199 + 200 + #endif // _NOLIBC_ARCH_LOONGARCH_H
+5
tools/include/nolibc/arch-x86_64.h
··· 181 181 char **environ __attribute__((weak)); 182 182 const unsigned long *_auxv __attribute__((weak)); 183 183 184 + #define __ARCH_SUPPORTS_STACK_PROTECTOR 185 + 184 186 /* startup code */ 185 187 /* 186 188 * x86-64 System V ABI mandates: ··· 193 191 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) 194 192 { 195 193 __asm__ volatile ( 194 + #ifdef NOLIBC_STACKPROTECTOR 195 + "call __stack_chk_init\n" // initialize stack protector 196 + #endif 196 197 "pop %rdi\n" // argc (first arg, %rdi) 197 198 "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) 198 199 "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
+2
tools/include/nolibc/arch.h
··· 29 29 #include "arch-riscv.h" 30 30 #elif defined(__s390x__) 31 31 #include "arch-s390.h" 32 + #elif defined(__loongarch__) 33 + #include "arch-loongarch.h" 32 34 #endif 33 35 34 36 #endif /* _NOLIBC_ARCH_H */
+1
tools/include/nolibc/nolibc.h
··· 104 104 #include "string.h" 105 105 #include "time.h" 106 106 #include "unistd.h" 107 + #include "stackprotector.h" 107 108 108 109 /* Used by programs to avoid std includes */ 109 110 #define NOLIBC
+53
tools/include/nolibc/stackprotector.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + /* 3 + * Stack protector support for NOLIBC 4 + * Copyright (C) 2023 Thomas Weißschuh <linux@weissschuh.net> 5 + */ 6 + 7 + #ifndef _NOLIBC_STACKPROTECTOR_H 8 + #define _NOLIBC_STACKPROTECTOR_H 9 + 10 + #include "arch.h" 11 + 12 + #if defined(NOLIBC_STACKPROTECTOR) 13 + 14 + #if !defined(__ARCH_SUPPORTS_STACK_PROTECTOR) 15 + #error "nolibc does not support stack protectors on this arch" 16 + #endif 17 + 18 + #include "sys.h" 19 + #include "stdlib.h" 20 + 21 + /* The functions in this header are using raw syscall macros to avoid 22 + * triggering stack protector errors themselves 23 + */ 24 + 25 + __attribute__((weak,noreturn,section(".text.nolibc_stack_chk"))) 26 + void __stack_chk_fail(void) 27 + { 28 + pid_t pid; 29 + my_syscall3(__NR_write, STDERR_FILENO, "!!Stack smashing detected!!\n", 28); 30 + pid = my_syscall0(__NR_getpid); 31 + my_syscall2(__NR_kill, pid, SIGABRT); 32 + for (;;); 33 + } 34 + 35 + __attribute__((weak,noreturn,section(".text.nolibc_stack_chk"))) 36 + void __stack_chk_fail_local(void) 37 + { 38 + __stack_chk_fail(); 39 + } 40 + 41 + __attribute__((weak,section(".data.nolibc_stack_chk"))) 42 + uintptr_t __stack_chk_guard; 43 + 44 + __attribute__((weak,no_stack_protector,section(".text.nolibc_stack_chk"))) 45 + void __stack_chk_init(void) 46 + { 47 + my_syscall3(__NR_getrandom, &__stack_chk_guard, sizeof(__stack_chk_guard), 0); 48 + /* a bit more randomness in case getrandom() fails */ 49 + __stack_chk_guard ^= (uintptr_t) &__stack_chk_guard; 50 + } 51 + #endif // defined(NOLIBC_STACKPROTECTOR) 52 + 53 + #endif // _NOLIBC_STACKPROTECTOR_H
+1 -14
tools/include/nolibc/std.h
··· 18 18 #define NULL ((void *)0) 19 19 #endif 20 20 21 - /* stdint types */ 22 - typedef unsigned char uint8_t; 23 - typedef signed char int8_t; 24 - typedef unsigned short uint16_t; 25 - typedef signed short int16_t; 26 - typedef unsigned int uint32_t; 27 - typedef signed int int32_t; 28 - typedef unsigned long long uint64_t; 29 - typedef signed long long int64_t; 30 - typedef unsigned long size_t; 31 - typedef signed long ssize_t; 32 - typedef unsigned long uintptr_t; 33 - typedef signed long intptr_t; 34 - typedef signed long ptrdiff_t; 21 + #include "stdint.h" 35 22 36 23 /* those are commonly provided by sys/types.h */ 37 24 typedef unsigned int dev_t;
+99
tools/include/nolibc/stdint.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + /* 3 + * Standard definitions and types for NOLIBC 4 + * Copyright (C) 2023 Vincent Dagonneau <v@vda.io> 5 + */ 6 + 7 + #ifndef _NOLIBC_STDINT_H 8 + #define _NOLIBC_STDINT_H 9 + 10 + typedef unsigned char uint8_t; 11 + typedef signed char int8_t; 12 + typedef unsigned short uint16_t; 13 + typedef signed short int16_t; 14 + typedef unsigned int uint32_t; 15 + typedef signed int int32_t; 16 + typedef unsigned long long uint64_t; 17 + typedef signed long long int64_t; 18 + typedef unsigned long size_t; 19 + typedef signed long ssize_t; 20 + typedef unsigned long uintptr_t; 21 + typedef signed long intptr_t; 22 + typedef signed long ptrdiff_t; 23 + 24 + typedef int8_t int_least8_t; 25 + typedef uint8_t uint_least8_t; 26 + typedef int16_t int_least16_t; 27 + typedef uint16_t uint_least16_t; 28 + typedef int32_t int_least32_t; 29 + typedef uint32_t uint_least32_t; 30 + typedef int64_t int_least64_t; 31 + typedef uint64_t uint_least64_t; 32 + 33 + typedef int8_t int_fast8_t; 34 + typedef uint8_t uint_fast8_t; 35 + typedef ssize_t int_fast16_t; 36 + typedef size_t uint_fast16_t; 37 + typedef ssize_t int_fast32_t; 38 + typedef size_t uint_fast32_t; 39 + typedef ssize_t int_fast64_t; 40 + typedef size_t uint_fast64_t; 41 + 42 + typedef int64_t intmax_t; 43 + typedef uint64_t uintmax_t; 44 + 45 + /* limits of integral types */ 46 + 47 + #define INT8_MIN (-128) 48 + #define INT16_MIN (-32767-1) 49 + #define INT32_MIN (-2147483647-1) 50 + #define INT64_MIN (-9223372036854775807LL-1) 51 + 52 + #define INT8_MAX (127) 53 + #define INT16_MAX (32767) 54 + #define INT32_MAX (2147483647) 55 + #define INT64_MAX (9223372036854775807LL) 56 + 57 + #define UINT8_MAX (255) 58 + #define UINT16_MAX (65535) 59 + #define UINT32_MAX (4294967295U) 60 + #define UINT64_MAX (18446744073709551615ULL) 61 + 62 + #define INT_LEAST8_MIN INT8_MIN 63 + #define INT_LEAST16_MIN INT16_MIN 64 + #define INT_LEAST32_MIN INT32_MIN 65 + #define INT_LEAST64_MIN INT64_MIN 66 + 67 + #define INT_LEAST8_MAX INT8_MAX 68 + #define INT_LEAST16_MAX INT16_MAX 69 + #define INT_LEAST32_MAX INT32_MAX 70 + #define INT_LEAST64_MAX INT64_MAX 71 + 72 + #define UINT_LEAST8_MAX UINT8_MAX 73 + #define UINT_LEAST16_MAX UINT16_MAX 74 + #define UINT_LEAST32_MAX UINT32_MAX 75 + #define UINT_LEAST64_MAX UINT64_MAX 76 + 77 + #define SIZE_MAX ((size_t)(__LONG_MAX__) * 2 + 1) 78 + #define INTPTR_MIN (-__LONG_MAX__ - 1) 79 + #define INTPTR_MAX __LONG_MAX__ 80 + #define PTRDIFF_MIN INTPTR_MIN 81 + #define PTRDIFF_MAX INTPTR_MAX 82 + #define UINTPTR_MAX SIZE_MAX 83 + 84 + #define INT_FAST8_MIN INT8_MIN 85 + #define INT_FAST16_MIN INTPTR_MIN 86 + #define INT_FAST32_MIN INTPTR_MIN 87 + #define INT_FAST64_MIN INTPTR_MIN 88 + 89 + #define INT_FAST8_MAX INT8_MAX 90 + #define INT_FAST16_MAX INTPTR_MAX 91 + #define INT_FAST32_MAX INTPTR_MAX 92 + #define INT_FAST64_MAX INTPTR_MAX 93 + 94 + #define UINT_FAST8_MAX UINT8_MAX 95 + #define UINT_FAST16_MAX SIZE_MAX 96 + #define UINT_FAST32_MAX SIZE_MAX 97 + #define UINT_FAST64_MAX SIZE_MAX 98 + 99 + #endif /* _NOLIBC_STDINT_H */
+99 -1
tools/include/nolibc/sys.h
··· 11 11 #include "std.h" 12 12 13 13 /* system includes */ 14 - #include <asm/fcntl.h> // for O_* 15 14 #include <asm/unistd.h> 16 15 #include <asm/signal.h> // for SIGCHLD 17 16 #include <asm/ioctls.h> ··· 19 20 #include <linux/loop.h> 20 21 #include <linux/time.h> 21 22 #include <linux/auxvec.h> 23 + #include <linux/fcntl.h> // for O_* and AT_* 24 + #include <linux/stat.h> // for statx() 22 25 23 26 #include "arch.h" 24 27 #include "errno.h" ··· 412 411 413 412 414 413 /* 414 + * uid_t geteuid(void); 415 + */ 416 + 417 + static __attribute__((unused)) 418 + uid_t sys_geteuid(void) 419 + { 420 + #ifdef __NR_geteuid32 421 + return my_syscall0(__NR_geteuid32); 422 + #else 423 + return my_syscall0(__NR_geteuid); 424 + #endif 425 + } 426 + 427 + static __attribute__((unused)) 428 + uid_t geteuid(void) 429 + { 430 + return sys_geteuid(); 431 + } 432 + 433 + 434 + /* 415 435 * pid_t getpgid(pid_t pid); 416 436 */ 417 437 ··· 563 541 ret = -1; 564 542 } 565 543 return ret; 544 + } 545 + 546 + 547 + /* 548 + * uid_t getuid(void); 549 + */ 550 + 551 + static __attribute__((unused)) 552 + uid_t sys_getuid(void) 553 + { 554 + #ifdef __NR_getuid32 555 + return my_syscall0(__NR_getuid32); 556 + #else 557 + return my_syscall0(__NR_getuid); 558 + #endif 559 + } 560 + 561 + static __attribute__((unused)) 562 + uid_t getuid(void) 563 + { 564 + return sys_getuid(); 566 565 } 567 566 568 567 ··· 1091 1048 return ret; 1092 1049 } 1093 1050 1051 + #if defined(__NR_statx) 1052 + /* 1053 + * int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf); 1054 + */ 1055 + 1056 + static __attribute__((unused)) 1057 + int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1058 + { 1059 + return my_syscall5(__NR_statx, fd, path, flags, mask, buf); 1060 + } 1061 + 1062 + static __attribute__((unused)) 1063 + int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1064 + { 1065 + int ret = sys_statx(fd, path, flags, mask, buf); 1066 + 1067 + if (ret < 0) { 1068 + SET_ERRNO(-ret); 1069 + ret = -1; 1070 + } 1071 + return ret; 1072 + } 1073 + #endif 1094 1074 1095 1075 /* 1096 1076 * int stat(const char *path, struct stat *buf); 1097 1077 * Warning: the struct stat's layout is arch-dependent. 1098 1078 */ 1099 1079 1080 + #if defined(__NR_statx) && !defined(__NR_newfstatat) && !defined(__NR_stat) 1081 + /* 1082 + * Maybe we can just use statx() when available for all architectures? 1083 + */ 1084 + static __attribute__((unused)) 1085 + int sys_stat(const char *path, struct stat *buf) 1086 + { 1087 + struct statx statx; 1088 + long ret; 1089 + 1090 + ret = sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx); 1091 + buf->st_dev = ((statx.stx_dev_minor & 0xff) 1092 + | (statx.stx_dev_major << 8) 1093 + | ((statx.stx_dev_minor & ~0xff) << 12)); 1094 + buf->st_ino = statx.stx_ino; 1095 + buf->st_mode = statx.stx_mode; 1096 + buf->st_nlink = statx.stx_nlink; 1097 + buf->st_uid = statx.stx_uid; 1098 + buf->st_gid = statx.stx_gid; 1099 + buf->st_rdev = ((statx.stx_rdev_minor & 0xff) 1100 + | (statx.stx_rdev_major << 8) 1101 + | ((statx.stx_rdev_minor & ~0xff) << 12)); 1102 + buf->st_size = statx.stx_size; 1103 + buf->st_blksize = statx.stx_blksize; 1104 + buf->st_blocks = statx.stx_blocks; 1105 + buf->st_atime = statx.stx_atime.tv_sec; 1106 + buf->st_mtime = statx.stx_mtime.tv_sec; 1107 + buf->st_ctime = statx.stx_ctime.tv_sec; 1108 + return ret; 1109 + } 1110 + #else 1100 1111 static __attribute__((unused)) 1101 1112 int sys_stat(const char *path, struct stat *buf) 1102 1113 { ··· 1180 1083 buf->st_ctime = stat.st_ctime; 1181 1084 return ret; 1182 1085 } 1086 + #endif 1183 1087 1184 1088 static __attribute__((unused)) 1185 1089 int stat(const char *path, struct stat *buf)
+24 -6
tools/include/nolibc/types.h
··· 9 9 10 10 #include "std.h" 11 11 #include <linux/time.h> 12 + #include <linux/stat.h> 12 13 13 14 14 15 /* Only the generic macros and types may be defined here. The arch-specific ··· 17 16 * the layout of sys_stat_struct must not be defined here. 18 17 */ 19 18 20 - /* stat flags (WARNING, octal here) */ 19 + /* stat flags (WARNING, octal here). We need to check for an existing 20 + * definition because linux/stat.h may omit to define those if it finds 21 + * that any glibc header was already included. 22 + */ 23 + #if !defined(S_IFMT) 21 24 #define S_IFDIR 0040000 22 25 #define S_IFCHR 0020000 23 26 #define S_IFBLK 0060000 ··· 38 33 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 39 34 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 40 35 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 36 + 37 + #define S_IRWXU 00700 38 + #define S_IRUSR 00400 39 + #define S_IWUSR 00200 40 + #define S_IXUSR 00100 41 + 42 + #define S_IRWXG 00070 43 + #define S_IRGRP 00040 44 + #define S_IWGRP 00020 45 + #define S_IXGRP 00010 46 + 47 + #define S_IRWXO 00007 48 + #define S_IROTH 00004 49 + #define S_IWOTH 00002 50 + #define S_IXOTH 00001 51 + #endif 41 52 42 53 /* dirent types */ 43 54 #define DT_UNKNOWN 0x0 ··· 81 60 #define MAXPATHLEN (PATH_MAX) 82 61 #endif 83 62 84 - /* Special FD used by all the *at functions */ 85 - #ifndef AT_FDCWD 86 - #define AT_FDCWD (-100) 87 - #endif 88 - 89 63 /* whence values for lseek() */ 90 64 #define SEEK_SET 0 91 65 #define SEEK_CUR 1 ··· 97 81 /* Macros used on waitpid()'s return status */ 98 82 #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) 99 83 #define WIFEXITED(status) (((status) & 0x7f) == 0) 84 + #define WTERMSIG(status) ((status) & 0x7f) 85 + #define WIFSIGNALED(status) ((status) - 1 < 0xff) 100 86 101 87 /* waitpid() flags */ 102 88 #define WNOHANG 1
+5
tools/include/nolibc/unistd.h
··· 13 13 #include "sys.h" 14 14 15 15 16 + #define STDIN_FILENO 0 17 + #define STDOUT_FILENO 1 18 + #define STDERR_FILENO 2 19 + 20 + 16 21 static __attribute__((unused)) 17 22 int msleep(unsigned int msecs) 18 23 {
+52 -38
tools/testing/selftests/nolibc/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 # Makefile for nolibc tests 3 3 include ../../../scripts/Makefile.include 4 + # We need this for the "cc-option" macro. 5 + include ../../../build/Build.include 4 6 5 7 # we're in ".../tools/testing/selftests/nolibc" 6 8 ifeq ($(srctree),) ··· 15 13 endif 16 14 17 15 # kernel image names by architecture 18 - IMAGE_i386 = arch/x86/boot/bzImage 19 - IMAGE_x86_64 = arch/x86/boot/bzImage 20 - IMAGE_x86 = arch/x86/boot/bzImage 21 - IMAGE_arm64 = arch/arm64/boot/Image 22 - IMAGE_arm = arch/arm/boot/zImage 23 - IMAGE_mips = vmlinuz 24 - IMAGE_riscv = arch/riscv/boot/Image 25 - IMAGE_s390 = arch/s390/boot/bzImage 26 - IMAGE = $(IMAGE_$(ARCH)) 27 - IMAGE_NAME = $(notdir $(IMAGE)) 16 + IMAGE_i386 = arch/x86/boot/bzImage 17 + IMAGE_x86_64 = arch/x86/boot/bzImage 18 + IMAGE_x86 = arch/x86/boot/bzImage 19 + IMAGE_arm64 = arch/arm64/boot/Image 20 + IMAGE_arm = arch/arm/boot/zImage 21 + IMAGE_mips = vmlinuz 22 + IMAGE_riscv = arch/riscv/boot/Image 23 + IMAGE_s390 = arch/s390/boot/bzImage 24 + IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi 25 + IMAGE = $(IMAGE_$(ARCH)) 26 + IMAGE_NAME = $(notdir $(IMAGE)) 28 27 29 28 # default kernel configurations that appear to be usable 30 - DEFCONFIG_i386 = defconfig 31 - DEFCONFIG_x86_64 = defconfig 32 - DEFCONFIG_x86 = defconfig 33 - DEFCONFIG_arm64 = defconfig 34 - DEFCONFIG_arm = multi_v7_defconfig 35 - DEFCONFIG_mips = malta_defconfig 36 - DEFCONFIG_riscv = defconfig 37 - DEFCONFIG_s390 = defconfig 38 - DEFCONFIG = $(DEFCONFIG_$(ARCH)) 29 + DEFCONFIG_i386 = defconfig 30 + DEFCONFIG_x86_64 = defconfig 31 + DEFCONFIG_x86 = defconfig 32 + DEFCONFIG_arm64 = defconfig 33 + DEFCONFIG_arm = multi_v7_defconfig 34 + DEFCONFIG_mips = malta_defconfig 35 + DEFCONFIG_riscv = defconfig 36 + DEFCONFIG_s390 = defconfig 37 + DEFCONFIG_loongarch = defconfig 38 + DEFCONFIG = $(DEFCONFIG_$(ARCH)) 39 39 40 40 # optional tests to run (default = all) 41 41 TEST = 42 42 43 43 # QEMU_ARCH: arch names used by qemu 44 - QEMU_ARCH_i386 = i386 45 - QEMU_ARCH_x86_64 = x86_64 46 - QEMU_ARCH_x86 = x86_64 47 - QEMU_ARCH_arm64 = aarch64 48 - QEMU_ARCH_arm = arm 49 - QEMU_ARCH_mips = mipsel # works with malta_defconfig 50 - QEMU_ARCH_riscv = riscv64 51 - QEMU_ARCH_s390 = s390x 52 - QEMU_ARCH = $(QEMU_ARCH_$(ARCH)) 44 + QEMU_ARCH_i386 = i386 45 + QEMU_ARCH_x86_64 = x86_64 46 + QEMU_ARCH_x86 = x86_64 47 + QEMU_ARCH_arm64 = aarch64 48 + QEMU_ARCH_arm = arm 49 + QEMU_ARCH_mips = mipsel # works with malta_defconfig 50 + QEMU_ARCH_riscv = riscv64 51 + QEMU_ARCH_s390 = s390x 52 + QEMU_ARCH_loongarch = loongarch64 53 + QEMU_ARCH = $(QEMU_ARCH_$(ARCH)) 53 54 54 55 # QEMU_ARGS : some arch-specific args to pass to qemu 55 - QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 56 - QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 57 - QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 58 - QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 59 - QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 60 - QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 61 - QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 62 - QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 63 - QEMU_ARGS = $(QEMU_ARGS_$(ARCH)) 56 + QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 57 + QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 58 + QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 59 + QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 60 + QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 61 + QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 62 + QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 63 + QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 64 + QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 65 + QEMU_ARGS = $(QEMU_ARGS_$(ARCH)) 64 66 65 67 # OUTPUT is only set when run from the main makefile, otherwise 66 68 # it defaults to this nolibc directory. ··· 76 70 Q=@ 77 71 endif 78 72 73 + CFLAGS_STACKPROTECTOR = -DNOLIBC_STACKPROTECTOR \ 74 + $(call cc-option,-mstack-protector-guard=global) \ 75 + $(call cc-option,-fstack-protector-all) 76 + CFLAGS_STKP_i386 = $(CFLAGS_STACKPROTECTOR) 77 + CFLAGS_STKP_x86_64 = $(CFLAGS_STACKPROTECTOR) 78 + CFLAGS_STKP_x86 = $(CFLAGS_STACKPROTECTOR) 79 79 CFLAGS_s390 = -m64 80 - CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables $(CFLAGS_$(ARCH)) 80 + CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables \ 81 + $(call cc-option,-fno-stack-protector) \ 82 + $(CFLAGS_STKP_$(ARCH)) $(CFLAGS_$(ARCH)) 81 83 LDFLAGS := -s 82 84 83 85 help:
+168 -53
tools/testing/selftests/nolibc/nolibc-test.c
··· 130 130 */ 131 131 132 132 #define EXPECT_ZR(cond, expr) \ 133 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0) 133 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0) 134 134 135 135 static int expect_zr(int expr, int llen) 136 136 { 137 137 int ret = !(expr == 0); 138 138 139 139 llen += printf(" = %d ", expr); 140 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 140 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 141 141 return ret; 142 142 } 143 143 144 144 145 145 #define EXPECT_NZ(cond, expr, val) \ 146 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0) 146 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0) 147 147 148 148 static int expect_nz(int expr, int llen) 149 149 { 150 150 int ret = !(expr != 0); 151 151 152 152 llen += printf(" = %d ", expr); 153 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 153 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 154 154 return ret; 155 155 } 156 156 157 157 158 158 #define EXPECT_EQ(cond, expr, val) \ 159 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0) 159 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0) 160 160 161 - static int expect_eq(int expr, int llen, int val) 161 + static int expect_eq(uint64_t expr, int llen, uint64_t val) 162 162 { 163 163 int ret = !(expr == val); 164 164 165 - llen += printf(" = %d ", expr); 166 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 165 + llen += printf(" = %lld ", expr); 166 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 167 167 return ret; 168 168 } 169 169 170 170 171 171 #define EXPECT_NE(cond, expr, val) \ 172 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0) 172 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0) 173 173 174 174 static int expect_ne(int expr, int llen, int val) 175 175 { 176 176 int ret = !(expr != val); 177 177 178 178 llen += printf(" = %d ", expr); 179 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 179 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 180 180 return ret; 181 181 } 182 182 183 183 184 184 #define EXPECT_GE(cond, expr, val) \ 185 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0) 185 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0) 186 186 187 187 static int expect_ge(int expr, int llen, int val) 188 188 { 189 189 int ret = !(expr >= val); 190 190 191 191 llen += printf(" = %d ", expr); 192 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 192 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 193 193 return ret; 194 194 } 195 195 196 196 197 197 #define EXPECT_GT(cond, expr, val) \ 198 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0) 198 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0) 199 199 200 200 static int expect_gt(int expr, int llen, int val) 201 201 { 202 202 int ret = !(expr > val); 203 203 204 204 llen += printf(" = %d ", expr); 205 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 205 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 206 206 return ret; 207 207 } 208 208 209 209 210 210 #define EXPECT_LE(cond, expr, val) \ 211 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0) 211 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0) 212 212 213 213 static int expect_le(int expr, int llen, int val) 214 214 { 215 215 int ret = !(expr <= val); 216 216 217 217 llen += printf(" = %d ", expr); 218 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 218 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 219 219 return ret; 220 220 } 221 221 222 222 223 223 #define EXPECT_LT(cond, expr, val) \ 224 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0) 224 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0) 225 225 226 226 static int expect_lt(int expr, int llen, int val) 227 227 { 228 228 int ret = !(expr < val); 229 229 230 230 llen += printf(" = %d ", expr); 231 - pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n"); 231 + pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); 232 232 return ret; 233 233 } 234 234 235 235 236 236 #define EXPECT_SYSZR(cond, expr) \ 237 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0) 237 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0) 238 238 239 239 static int expect_syszr(int expr, int llen) 240 240 { ··· 243 243 if (expr) { 244 244 ret = 1; 245 245 llen += printf(" = %d %s ", expr, errorname(errno)); 246 - llen += pad_spc(llen, 40, "[FAIL]\n"); 246 + llen += pad_spc(llen, 64, "[FAIL]\n"); 247 247 } else { 248 248 llen += printf(" = %d ", expr); 249 - llen += pad_spc(llen, 40, " [OK]\n"); 249 + llen += pad_spc(llen, 64, " [OK]\n"); 250 250 } 251 251 return ret; 252 252 } 253 253 254 254 255 255 #define EXPECT_SYSEQ(cond, expr, val) \ 256 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0) 256 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0) 257 257 258 258 static int expect_syseq(int expr, int llen, int val) 259 259 { ··· 262 262 if (expr != val) { 263 263 ret = 1; 264 264 llen += printf(" = %d %s ", expr, errorname(errno)); 265 - llen += pad_spc(llen, 40, "[FAIL]\n"); 265 + llen += pad_spc(llen, 64, "[FAIL]\n"); 266 266 } else { 267 267 llen += printf(" = %d ", expr); 268 - llen += pad_spc(llen, 40, " [OK]\n"); 268 + llen += pad_spc(llen, 64, " [OK]\n"); 269 269 } 270 270 return ret; 271 271 } 272 272 273 273 274 274 #define EXPECT_SYSNE(cond, expr, val) \ 275 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0) 275 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0) 276 276 277 277 static int expect_sysne(int expr, int llen, int val) 278 278 { ··· 281 281 if (expr == val) { 282 282 ret = 1; 283 283 llen += printf(" = %d %s ", expr, errorname(errno)); 284 - llen += pad_spc(llen, 40, "[FAIL]\n"); 284 + llen += pad_spc(llen, 64, "[FAIL]\n"); 285 285 } else { 286 286 llen += printf(" = %d ", expr); 287 - llen += pad_spc(llen, 40, " [OK]\n"); 287 + llen += pad_spc(llen, 64, " [OK]\n"); 288 288 } 289 289 return ret; 290 290 } 291 291 292 292 293 293 #define EXPECT_SYSER(cond, expr, expret, experr) \ 294 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0) 294 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0) 295 295 296 296 static int expect_syserr(int expr, int expret, int experr, int llen) 297 297 { ··· 302 302 if (expr != expret || _errno != experr) { 303 303 ret = 1; 304 304 llen += printf(" != (%d %s) ", expret, errorname(experr)); 305 - llen += pad_spc(llen, 40, "[FAIL]\n"); 305 + llen += pad_spc(llen, 64, "[FAIL]\n"); 306 306 } else { 307 - llen += pad_spc(llen, 40, " [OK]\n"); 307 + llen += pad_spc(llen, 64, " [OK]\n"); 308 308 } 309 309 return ret; 310 310 } 311 311 312 312 313 313 #define EXPECT_PTRZR(cond, expr) \ 314 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0) 314 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0) 315 315 316 316 static int expect_ptrzr(const void *expr, int llen) 317 317 { ··· 320 320 llen += printf(" = <%p> ", expr); 321 321 if (expr) { 322 322 ret = 1; 323 - llen += pad_spc(llen, 40, "[FAIL]\n"); 323 + llen += pad_spc(llen, 64, "[FAIL]\n"); 324 324 } else { 325 - llen += pad_spc(llen, 40, " [OK]\n"); 325 + llen += pad_spc(llen, 64, " [OK]\n"); 326 326 } 327 327 return ret; 328 328 } 329 329 330 330 331 331 #define EXPECT_PTRNZ(cond, expr) \ 332 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0) 332 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0) 333 333 334 334 static int expect_ptrnz(const void *expr, int llen) 335 335 { ··· 338 338 llen += printf(" = <%p> ", expr); 339 339 if (!expr) { 340 340 ret = 1; 341 - llen += pad_spc(llen, 40, "[FAIL]\n"); 341 + llen += pad_spc(llen, 64, "[FAIL]\n"); 342 342 } else { 343 - llen += pad_spc(llen, 40, " [OK]\n"); 343 + llen += pad_spc(llen, 64, " [OK]\n"); 344 344 } 345 345 return ret; 346 346 } 347 347 348 348 349 349 #define EXPECT_STRZR(cond, expr) \ 350 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0) 350 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0) 351 351 352 352 static int expect_strzr(const char *expr, int llen) 353 353 { ··· 356 356 llen += printf(" = <%s> ", expr); 357 357 if (expr) { 358 358 ret = 1; 359 - llen += pad_spc(llen, 40, "[FAIL]\n"); 359 + llen += pad_spc(llen, 64, "[FAIL]\n"); 360 360 } else { 361 - llen += pad_spc(llen, 40, " [OK]\n"); 361 + llen += pad_spc(llen, 64, " [OK]\n"); 362 362 } 363 363 return ret; 364 364 } 365 365 366 366 367 367 #define EXPECT_STRNZ(cond, expr) \ 368 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0) 368 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0) 369 369 370 370 static int expect_strnz(const char *expr, int llen) 371 371 { ··· 374 374 llen += printf(" = <%s> ", expr); 375 375 if (!expr) { 376 376 ret = 1; 377 - llen += pad_spc(llen, 40, "[FAIL]\n"); 377 + llen += pad_spc(llen, 64, "[FAIL]\n"); 378 378 } else { 379 - llen += pad_spc(llen, 40, " [OK]\n"); 379 + llen += pad_spc(llen, 64, " [OK]\n"); 380 380 } 381 381 return ret; 382 382 } 383 383 384 384 385 385 #define EXPECT_STREQ(cond, expr, cmp) \ 386 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0) 386 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0) 387 387 388 388 static int expect_streq(const char *expr, int llen, const char *cmp) 389 389 { ··· 392 392 llen += printf(" = <%s> ", expr); 393 393 if (strcmp(expr, cmp) != 0) { 394 394 ret = 1; 395 - llen += pad_spc(llen, 40, "[FAIL]\n"); 395 + llen += pad_spc(llen, 64, "[FAIL]\n"); 396 396 } else { 397 - llen += pad_spc(llen, 40, " [OK]\n"); 397 + llen += pad_spc(llen, 64, " [OK]\n"); 398 398 } 399 399 return ret; 400 400 } 401 401 402 402 403 403 #define EXPECT_STRNE(cond, expr, cmp) \ 404 - do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0) 404 + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0) 405 405 406 406 static int expect_strne(const char *expr, int llen, const char *cmp) 407 407 { ··· 410 410 llen += printf(" = <%s> ", expr); 411 411 if (strcmp(expr, cmp) == 0) { 412 412 ret = 1; 413 - llen += pad_spc(llen, 40, "[FAIL]\n"); 413 + llen += pad_spc(llen, 64, "[FAIL]\n"); 414 414 } else { 415 - llen += pad_spc(llen, 40, " [OK]\n"); 415 + llen += pad_spc(llen, 64, " [OK]\n"); 416 416 } 417 417 return ret; 418 418 } ··· 477 477 int run_syscall(int min, int max) 478 478 { 479 479 struct stat stat_buf; 480 + int euid0; 480 481 int proc; 481 482 int test; 482 483 int tmp; ··· 486 485 487 486 /* <proc> indicates whether or not /proc is mounted */ 488 487 proc = stat("/proc", &stat_buf) == 0; 488 + 489 + /* this will be used to skip certain tests that can't be run unprivileged */ 490 + euid0 = geteuid() == 0; 489 491 490 492 for (test = min; test >= 0 && test <= max; test++) { 491 493 int llen = 0; // line length ··· 515 511 CASE_TEST(chmod_net); EXPECT_SYSZR(proc, chmod("/proc/self/net", 0555)); break; 516 512 CASE_TEST(chmod_self); EXPECT_SYSER(proc, chmod("/proc/self", 0555), -1, EPERM); break; 517 513 CASE_TEST(chown_self); EXPECT_SYSER(proc, chown("/proc/self", 0, 0), -1, EPERM); break; 518 - CASE_TEST(chroot_root); EXPECT_SYSZR(1, chroot("/")); break; 514 + CASE_TEST(chroot_root); EXPECT_SYSZR(euid0, chroot("/")); break; 519 515 CASE_TEST(chroot_blah); EXPECT_SYSER(1, chroot("/proc/self/blah"), -1, ENOENT); break; 520 516 CASE_TEST(chroot_exe); EXPECT_SYSER(proc, chroot("/proc/self/exe"), -1, ENOTDIR); break; 521 517 CASE_TEST(close_m1); EXPECT_SYSER(1, close(-1), -1, EBADF); break; ··· 540 536 CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; 541 537 CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break; 542 538 CASE_TEST(link_blah); EXPECT_SYSER(1, link("/proc/self/blah", "/blah"), -1, ENOENT); break; 543 - CASE_TEST(link_dir); EXPECT_SYSER(1, link("/", "/blah"), -1, EPERM); break; 539 + CASE_TEST(link_dir); EXPECT_SYSER(euid0, link("/", "/blah"), -1, EPERM); break; 544 540 CASE_TEST(link_cross); EXPECT_SYSER(proc, link("/proc/self/net", "/blah"), -1, EXDEV); break; 545 541 CASE_TEST(lseek_m1); EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break; 546 542 CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break; ··· 606 602 CASE_TEST(memcmp_e0_20); EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x20", 4), 0); break; 607 603 CASE_TEST(memcmp_80_e0); EXPECT_LT(1, memcmp("aaa\x80", "aaa\xe0", 4), 0); break; 608 604 CASE_TEST(memcmp_e0_80); EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x80", 4), 0); break; 605 + CASE_TEST(limit_int8_max); EXPECT_EQ(1, INT8_MAX, (int8_t) 0x7f); break; 606 + CASE_TEST(limit_int8_min); EXPECT_EQ(1, INT8_MIN, (int8_t) 0x80); break; 607 + CASE_TEST(limit_uint8_max); EXPECT_EQ(1, UINT8_MAX, (uint8_t) 0xff); break; 608 + CASE_TEST(limit_int16_max); EXPECT_EQ(1, INT16_MAX, (int16_t) 0x7fff); break; 609 + CASE_TEST(limit_int16_min); EXPECT_EQ(1, INT16_MIN, (int16_t) 0x8000); break; 610 + CASE_TEST(limit_uint16_max); EXPECT_EQ(1, UINT16_MAX, (uint16_t) 0xffff); break; 611 + CASE_TEST(limit_int32_max); EXPECT_EQ(1, INT32_MAX, (int32_t) 0x7fffffff); break; 612 + CASE_TEST(limit_int32_min); EXPECT_EQ(1, INT32_MIN, (int32_t) 0x80000000); break; 613 + CASE_TEST(limit_uint32_max); EXPECT_EQ(1, UINT32_MAX, (uint32_t) 0xffffffff); break; 614 + CASE_TEST(limit_int64_max); EXPECT_EQ(1, INT64_MAX, (int64_t) 0x7fffffffffffffff); break; 615 + CASE_TEST(limit_int64_min); EXPECT_EQ(1, INT64_MIN, (int64_t) 0x8000000000000000); break; 616 + CASE_TEST(limit_uint64_max); EXPECT_EQ(1, UINT64_MAX, (uint64_t) 0xffffffffffffffff); break; 617 + CASE_TEST(limit_int_least8_max); EXPECT_EQ(1, INT_LEAST8_MAX, (int_least8_t) 0x7f); break; 618 + CASE_TEST(limit_int_least8_min); EXPECT_EQ(1, INT_LEAST8_MIN, (int_least8_t) 0x80); break; 619 + CASE_TEST(limit_uint_least8_max); EXPECT_EQ(1, UINT_LEAST8_MAX, (uint_least8_t) 0xff); break; 620 + CASE_TEST(limit_int_least16_max); EXPECT_EQ(1, INT_LEAST16_MAX, (int_least16_t) 0x7fff); break; 621 + CASE_TEST(limit_int_least16_min); EXPECT_EQ(1, INT_LEAST16_MIN, (int_least16_t) 0x8000); break; 622 + CASE_TEST(limit_uint_least16_max); EXPECT_EQ(1, UINT_LEAST16_MAX, (uint_least16_t) 0xffff); break; 623 + CASE_TEST(limit_int_least32_max); EXPECT_EQ(1, INT_LEAST32_MAX, (int_least32_t) 0x7fffffff); break; 624 + CASE_TEST(limit_int_least32_min); EXPECT_EQ(1, INT_LEAST32_MIN, (int_least32_t) 0x80000000); break; 625 + CASE_TEST(limit_uint_least32_max); EXPECT_EQ(1, UINT_LEAST32_MAX, (uint_least32_t) 0xffffffffU); break; 626 + CASE_TEST(limit_int_least64_min); EXPECT_EQ(1, INT_LEAST64_MIN, (int_least64_t) 0x8000000000000000LL); break; 627 + CASE_TEST(limit_int_least64_max); EXPECT_EQ(1, INT_LEAST64_MAX, (int_least64_t) 0x7fffffffffffffffLL); break; 628 + CASE_TEST(limit_uint_least64_max); EXPECT_EQ(1, UINT_LEAST64_MAX, (uint_least64_t) 0xffffffffffffffffULL); break; 629 + CASE_TEST(limit_int_fast8_max); EXPECT_EQ(1, INT_FAST8_MAX, (int_fast8_t) 0x7f); break; 630 + CASE_TEST(limit_int_fast8_min); EXPECT_EQ(1, INT_FAST8_MIN, (int_fast8_t) 0x80); break; 631 + CASE_TEST(limit_uint_fast8_max); EXPECT_EQ(1, UINT_FAST8_MAX, (uint_fast8_t) 0xff); break; 632 + CASE_TEST(limit_int_fast16_min); EXPECT_EQ(1, INT_FAST16_MIN, (int_fast16_t) INTPTR_MIN); break; 633 + CASE_TEST(limit_int_fast16_max); EXPECT_EQ(1, INT_FAST16_MAX, (int_fast16_t) INTPTR_MAX); break; 634 + CASE_TEST(limit_uint_fast16_max); EXPECT_EQ(1, UINT_FAST16_MAX, (uint_fast16_t) UINTPTR_MAX); break; 635 + CASE_TEST(limit_int_fast32_min); EXPECT_EQ(1, INT_FAST32_MIN, (int_fast32_t) INTPTR_MIN); break; 636 + CASE_TEST(limit_int_fast32_max); EXPECT_EQ(1, INT_FAST32_MAX, (int_fast32_t) INTPTR_MAX); break; 637 + CASE_TEST(limit_uint_fast32_max); EXPECT_EQ(1, UINT_FAST32_MAX, (uint_fast32_t) UINTPTR_MAX); break; 638 + CASE_TEST(limit_int_fast64_min); EXPECT_EQ(1, INT_FAST64_MIN, (int_fast64_t) INTPTR_MIN); break; 639 + CASE_TEST(limit_int_fast64_max); EXPECT_EQ(1, INT_FAST64_MAX, (int_fast64_t) INTPTR_MAX); break; 640 + CASE_TEST(limit_uint_fast64_max); EXPECT_EQ(1, UINT_FAST64_MAX, (uint_fast64_t) UINTPTR_MAX); break; 641 + #if __SIZEOF_LONG__ == 8 642 + CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x8000000000000000LL); break; 643 + CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffffffffffffLL); break; 644 + CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffffffffffULL); break; 645 + CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x8000000000000000LL); break; 646 + CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffffffffffffLL); break; 647 + CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffffffffffULL); break; 648 + #elif __SIZEOF_LONG__ == 4 649 + CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x80000000); break; 650 + CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffff); break; 651 + CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffU); break; 652 + CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x80000000); break; 653 + CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffff); break; 654 + CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffU); break; 655 + #else 656 + # warning "__SIZEOF_LONG__ is undefined" 657 + #endif /* __SIZEOF_LONG__ */ 609 658 case __LINE__: 610 659 return ret; /* must be last */ 611 660 /* note: do not set any defaults so as to permit holes above */ 612 661 } 613 662 } 614 663 return ret; 664 + } 665 + 666 + #if defined(__clang__) 667 + __attribute__((optnone)) 668 + #elif defined(__GNUC__) 669 + __attribute__((optimize("O0"))) 670 + #endif 671 + static int smash_stack(void) 672 + { 673 + char buf[100]; 674 + 675 + for (size_t i = 0; i < 200; i++) 676 + buf[i] = 'P'; 677 + 678 + return 1; 679 + } 680 + 681 + static int run_protection(int min, int max) 682 + { 683 + pid_t pid; 684 + int llen = 0, status; 685 + 686 + llen += printf("0 -fstackprotector "); 687 + 688 + #if !defined(NOLIBC_STACKPROTECTOR) 689 + llen += printf("not supported"); 690 + pad_spc(llen, 64, "[SKIPPED]\n"); 691 + return 0; 692 + #endif 693 + 694 + pid = -1; 695 + pid = fork(); 696 + 697 + switch (pid) { 698 + case -1: 699 + llen += printf("fork()"); 700 + pad_spc(llen, 64, "[FAIL]\n"); 701 + return 1; 702 + 703 + case 0: 704 + close(STDOUT_FILENO); 705 + close(STDERR_FILENO); 706 + 707 + smash_stack(); 708 + return 1; 709 + 710 + default: 711 + pid = waitpid(pid, &status, 0); 712 + 713 + if (pid == -1 || !WIFSIGNALED(status) || WTERMSIG(status) != SIGABRT) { 714 + llen += printf("waitpid()"); 715 + pad_spc(llen, 64, "[FAIL]\n"); 716 + return 1; 717 + } 718 + pad_spc(llen, 64, " [OK]\n"); 719 + return 0; 720 + } 615 721 } 616 722 617 723 /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */ ··· 774 660 } 775 661 776 662 /* This is the definition of known test names, with their functions */ 777 - static struct test test_names[] = { 663 + static const struct test test_names[] = { 778 664 /* add new tests here */ 779 - { .name = "syscall", .func = run_syscall }, 780 - { .name = "stdlib", .func = run_stdlib }, 665 + { .name = "syscall", .func = run_syscall }, 666 + { .name = "stdlib", .func = run_stdlib }, 667 + { .name = "protection", .func = run_protection }, 781 668 { 0 } 782 669 }; 783 670