mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-18 02:46:06 +00:00
nolibc updates for v6.4
o Add support for loongarch. o Fix stack-protector issues. o Support additional integral types and signal-related macros. o Add support for stdin, stdout, and stderr. o Add getuid() and geteuid(). o Allow S_I* macros to be overridden by program. o Defer to linux/fcntl.h and linux/stat.h to avoid duplicate definitions. o Many improvements to the self tests. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEbK7UrM+RBIrCoViJnr8S83LZ+4wFAmQsjLUTHHBhdWxtY2tA a2VybmVsLm9yZwAKCRCevxLzctn7jKuOD/9Y18ncS7+K7D9m89h5zwqBoPeNdP65 fC/kSgBeLreqO9hR7fsDegPk/pC8ZcMZj7iiLMV8dQIan0N74Hcd4mnL+Nf9LdkP KpwMfN/DG7h+p69Ug4d6qQqSr7jwEGa1NE280NguNtugs+kanSayVoSh0lhWPp7K 5t9s4oITOQNa69EgluB25b1qbaY36DibsBbt7vO2b/Rsmbw13UdgXQxKBQTgEOmQ yfNqjSYatRrl7pQQiQQDwV8xzd84jNLgNKsTDtG18kUWqYBhleMDQxt54betRFZ2 O3SNylt7pJKVFsgjAB90TcOl4SRmzXJ0+jNLIuNYJkqlQaPjQy29N4nBBUp2ciBf sSkL4OBfaegJlnBWZ4LwyV+ZTPLGQ5PZ78EhfqMpQzVbEibL5Es/pPAVuUxLVK4B U03+sh4IAr2aK4aXcxXgDWYr/HmKP6DWrlp/oH679sW1e2mUpnjghOfuGMYwLifo d+a/M2VH8++KOV/0aZf/Z4p1Jbexn6/jz4pW7DTfiARduUtlaN5F69oAr85q5vrS T1dZ84ZjmxrWJUYEJjfs5DM+fvPzsOyho8ae9TRlxnJJtW6UOZ0TTUo+mUDfgqWQ OU6XteK6zTQmE5H9aVOVwO/jl0uXWzmHAoJTAynpPgEkP01I+t6Vx8e1PAK/oPbT fJdUIEFiMo1qMg== =BS2x -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
5d77652fbf
1
tools/include/nolibc/.gitignore
vendored
Normal file
1
tools/include/nolibc/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
sysroot
|
@ -25,8 +25,8 @@ endif
|
||||
|
||||
nolibc_arch := $(patsubst arm64,aarch64,$(ARCH))
|
||||
arch_file := arch-$(nolibc_arch).h
|
||||
all_files := ctype.h errno.h nolibc.h signal.h std.h stdio.h stdlib.h string.h \
|
||||
sys.h time.h types.h unistd.h
|
||||
all_files := ctype.h errno.h nolibc.h signal.h stackprotector.h std.h stdint.h \
|
||||
stdio.h stdlib.h string.h sys.h time.h types.h unistd.h
|
||||
|
||||
# install all headers needed to support a bare-metal compiler
|
||||
all: headers
|
||||
|
@ -181,6 +181,8 @@ struct sys_stat_struct {
|
||||
char **environ __attribute__((weak));
|
||||
const unsigned long *_auxv __attribute__((weak));
|
||||
|
||||
#define __ARCH_SUPPORTS_STACK_PROTECTOR
|
||||
|
||||
/* startup code */
|
||||
/*
|
||||
* i386 System V ABI mandates:
|
||||
@ -188,9 +190,12 @@ const unsigned long *_auxv __attribute__((weak));
|
||||
* 2) The deepest stack frame should be set to zero
|
||||
*
|
||||
*/
|
||||
void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void)
|
||||
void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
#ifdef NOLIBC_STACKPROTECTOR
|
||||
"call __stack_chk_init\n" // initialize stack protector
|
||||
#endif
|
||||
"pop %eax\n" // argc (first arg, %eax)
|
||||
"mov %esp, %ebx\n" // argv[] (second arg, %ebx)
|
||||
"lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
|
||||
|
200
tools/include/nolibc/arch-loongarch.h
Normal file
200
tools/include/nolibc/arch-loongarch.h
Normal file
@ -0,0 +1,200 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* LoongArch specific definitions for NOLIBC
|
||||
* Copyright (C) 2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _NOLIBC_ARCH_LOONGARCH_H
|
||||
#define _NOLIBC_ARCH_LOONGARCH_H
|
||||
|
||||
/* Syscalls for LoongArch :
|
||||
* - stack is 16-byte aligned
|
||||
* - syscall number is passed in a7
|
||||
* - arguments are in a0, a1, a2, a3, a4, a5
|
||||
* - the system call is performed by calling "syscall 0"
|
||||
* - syscall return comes in a0
|
||||
* - the arguments are cast to long and assigned into the target
|
||||
* registers which are then simply passed as registers to the asm code,
|
||||
* so that we don't have to experience issues with register constraints.
|
||||
*
|
||||
* On LoongArch, select() is not implemented so we have to use pselect6().
|
||||
*/
|
||||
#define __ARCH_WANT_SYS_PSELECT6
|
||||
|
||||
#define my_syscall0(num) \
|
||||
({ \
|
||||
register long _num __asm__ ("a7") = (num); \
|
||||
register long _arg1 __asm__ ("a0"); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"syscall 0\n" \
|
||||
: "=r"(_arg1) \
|
||||
: "r"(_num) \
|
||||
: "memory", "$t0", "$t1", "$t2", "$t3", \
|
||||
"$t4", "$t5", "$t6", "$t7", "$t8" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall1(num, arg1) \
|
||||
({ \
|
||||
register long _num __asm__ ("a7") = (num); \
|
||||
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"syscall 0\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_num) \
|
||||
: "memory", "$t0", "$t1", "$t2", "$t3", \
|
||||
"$t4", "$t5", "$t6", "$t7", "$t8" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall2(num, arg1, arg2) \
|
||||
({ \
|
||||
register long _num __asm__ ("a7") = (num); \
|
||||
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"syscall 0\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), \
|
||||
"r"(_num) \
|
||||
: "memory", "$t0", "$t1", "$t2", "$t3", \
|
||||
"$t4", "$t5", "$t6", "$t7", "$t8" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall3(num, arg1, arg2, arg3) \
|
||||
({ \
|
||||
register long _num __asm__ ("a7") = (num); \
|
||||
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"syscall 0\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), \
|
||||
"r"(_num) \
|
||||
: "memory", "$t0", "$t1", "$t2", "$t3", \
|
||||
"$t4", "$t5", "$t6", "$t7", "$t8" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
|
||||
({ \
|
||||
register long _num __asm__ ("a7") = (num); \
|
||||
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("a3") = (long)(arg4); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"syscall 0\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), \
|
||||
"r"(_num) \
|
||||
: "memory", "$t0", "$t1", "$t2", "$t3", \
|
||||
"$t4", "$t5", "$t6", "$t7", "$t8" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
|
||||
({ \
|
||||
register long _num __asm__ ("a7") = (num); \
|
||||
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("a3") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("a4") = (long)(arg5); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"syscall 0\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
|
||||
"r"(_num) \
|
||||
: "memory", "$t0", "$t1", "$t2", "$t3", \
|
||||
"$t4", "$t5", "$t6", "$t7", "$t8" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
|
||||
({ \
|
||||
register long _num __asm__ ("a7") = (num); \
|
||||
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("a3") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("a4") = (long)(arg5); \
|
||||
register long _arg6 __asm__ ("a5") = (long)(arg6); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"syscall 0\n" \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
|
||||
"r"(_num) \
|
||||
: "memory", "$t0", "$t1", "$t2", "$t3", \
|
||||
"$t4", "$t5", "$t6", "$t7", "$t8" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
char **environ __attribute__((weak));
|
||||
const unsigned long *_auxv __attribute__((weak));
|
||||
|
||||
#if __loongarch_grlen == 32
|
||||
#define LONGLOG "2"
|
||||
#define SZREG "4"
|
||||
#define REG_L "ld.w"
|
||||
#define LONG_S "st.w"
|
||||
#define LONG_ADD "add.w"
|
||||
#define LONG_ADDI "addi.w"
|
||||
#define LONG_SLL "slli.w"
|
||||
#define LONG_BSTRINS "bstrins.w"
|
||||
#else // __loongarch_grlen == 64
|
||||
#define LONGLOG "3"
|
||||
#define SZREG "8"
|
||||
#define REG_L "ld.d"
|
||||
#define LONG_S "st.d"
|
||||
#define LONG_ADD "add.d"
|
||||
#define LONG_ADDI "addi.d"
|
||||
#define LONG_SLL "slli.d"
|
||||
#define LONG_BSTRINS "bstrins.d"
|
||||
#endif
|
||||
|
||||
/* startup code */
|
||||
void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
REG_L " $a0, $sp, 0\n" // argc (a0) was in the stack
|
||||
LONG_ADDI " $a1, $sp, "SZREG"\n" // argv (a1) = sp + SZREG
|
||||
LONG_SLL " $a2, $a0, "LONGLOG"\n" // envp (a2) = SZREG*argc ...
|
||||
LONG_ADDI " $a2, $a2, "SZREG"\n" // + SZREG (skip null)
|
||||
LONG_ADD " $a2, $a2, $a1\n" // + argv
|
||||
|
||||
"move $a3, $a2\n" // iterate a3 over envp to find auxv (after NULL)
|
||||
"0:\n" // do {
|
||||
REG_L " $a4, $a3, 0\n" // a4 = *a3;
|
||||
LONG_ADDI " $a3, $a3, "SZREG"\n" // a3 += sizeof(void*);
|
||||
"bne $a4, $zero, 0b\n" // } while (a4);
|
||||
"la.pcrel $a4, _auxv\n" // a4 = &_auxv
|
||||
LONG_S " $a3, $a4, 0\n" // store a3 into _auxv
|
||||
|
||||
"la.pcrel $a3, environ\n" // a3 = &environ
|
||||
LONG_S " $a2, $a3, 0\n" // store envp(a2) into environ
|
||||
LONG_BSTRINS " $sp, $zero, 3, 0\n" // sp must be 16-byte aligned
|
||||
"bl main\n" // main() returns the status code, we'll exit with it.
|
||||
"li.w $a7, 93\n" // NR_exit == 93
|
||||
"syscall 0\n"
|
||||
);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
#endif // _NOLIBC_ARCH_LOONGARCH_H
|
@ -181,6 +181,8 @@ struct sys_stat_struct {
|
||||
char **environ __attribute__((weak));
|
||||
const unsigned long *_auxv __attribute__((weak));
|
||||
|
||||
#define __ARCH_SUPPORTS_STACK_PROTECTOR
|
||||
|
||||
/* startup code */
|
||||
/*
|
||||
* x86-64 System V ABI mandates:
|
||||
@ -191,6 +193,9 @@ const unsigned long *_auxv __attribute__((weak));
|
||||
void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
#ifdef NOLIBC_STACKPROTECTOR
|
||||
"call __stack_chk_init\n" // initialize stack protector
|
||||
#endif
|
||||
"pop %rdi\n" // argc (first arg, %rdi)
|
||||
"mov %rsp, %rsi\n" // argv[] (second arg, %rsi)
|
||||
"lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "arch-riscv.h"
|
||||
#elif defined(__s390x__)
|
||||
#include "arch-s390.h"
|
||||
#elif defined(__loongarch__)
|
||||
#include "arch-loongarch.h"
|
||||
#endif
|
||||
|
||||
#endif /* _NOLIBC_ARCH_H */
|
||||
|
@ -104,6 +104,7 @@
|
||||
#include "string.h"
|
||||
#include "time.h"
|
||||
#include "unistd.h"
|
||||
#include "stackprotector.h"
|
||||
|
||||
/* Used by programs to avoid std includes */
|
||||
#define NOLIBC
|
||||
|
53
tools/include/nolibc/stackprotector.h
Normal file
53
tools/include/nolibc/stackprotector.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Stack protector support for NOLIBC
|
||||
* Copyright (C) 2023 Thomas Weißschuh <linux@weissschuh.net>
|
||||
*/
|
||||
|
||||
#ifndef _NOLIBC_STACKPROTECTOR_H
|
||||
#define _NOLIBC_STACKPROTECTOR_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
#if defined(NOLIBC_STACKPROTECTOR)
|
||||
|
||||
#if !defined(__ARCH_SUPPORTS_STACK_PROTECTOR)
|
||||
#error "nolibc does not support stack protectors on this arch"
|
||||
#endif
|
||||
|
||||
#include "sys.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
/* The functions in this header are using raw syscall macros to avoid
|
||||
* triggering stack protector errors themselves
|
||||
*/
|
||||
|
||||
__attribute__((weak,noreturn,section(".text.nolibc_stack_chk")))
|
||||
void __stack_chk_fail(void)
|
||||
{
|
||||
pid_t pid;
|
||||
my_syscall3(__NR_write, STDERR_FILENO, "!!Stack smashing detected!!\n", 28);
|
||||
pid = my_syscall0(__NR_getpid);
|
||||
my_syscall2(__NR_kill, pid, SIGABRT);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
__attribute__((weak,noreturn,section(".text.nolibc_stack_chk")))
|
||||
void __stack_chk_fail_local(void)
|
||||
{
|
||||
__stack_chk_fail();
|
||||
}
|
||||
|
||||
__attribute__((weak,section(".data.nolibc_stack_chk")))
|
||||
uintptr_t __stack_chk_guard;
|
||||
|
||||
__attribute__((weak,no_stack_protector,section(".text.nolibc_stack_chk")))
|
||||
void __stack_chk_init(void)
|
||||
{
|
||||
my_syscall3(__NR_getrandom, &__stack_chk_guard, sizeof(__stack_chk_guard), 0);
|
||||
/* a bit more randomness in case getrandom() fails */
|
||||
__stack_chk_guard ^= (uintptr_t) &__stack_chk_guard;
|
||||
}
|
||||
#endif // defined(NOLIBC_STACKPROTECTOR)
|
||||
|
||||
#endif // _NOLIBC_STACKPROTECTOR_H
|
@ -18,20 +18,7 @@
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
/* stdint types */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long size_t;
|
||||
typedef signed long ssize_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef signed long intptr_t;
|
||||
typedef signed long ptrdiff_t;
|
||||
#include "stdint.h"
|
||||
|
||||
/* those are commonly provided by sys/types.h */
|
||||
typedef unsigned int dev_t;
|
||||
|
99
tools/include/nolibc/stdint.h
Normal file
99
tools/include/nolibc/stdint.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Standard definitions and types for NOLIBC
|
||||
* Copyright (C) 2023 Vincent Dagonneau <v@vda.io>
|
||||
*/
|
||||
|
||||
#ifndef _NOLIBC_STDINT_H
|
||||
#define _NOLIBC_STDINT_H
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long size_t;
|
||||
typedef signed long ssize_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef signed long intptr_t;
|
||||
typedef signed long ptrdiff_t;
|
||||
|
||||
typedef int8_t int_least8_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef ssize_t int_fast16_t;
|
||||
typedef size_t uint_fast16_t;
|
||||
typedef ssize_t int_fast32_t;
|
||||
typedef size_t uint_fast32_t;
|
||||
typedef ssize_t int_fast64_t;
|
||||
typedef size_t uint_fast64_t;
|
||||
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
/* limits of integral types */
|
||||
|
||||
#define INT8_MIN (-128)
|
||||
#define INT16_MIN (-32767-1)
|
||||
#define INT32_MIN (-2147483647-1)
|
||||
#define INT64_MIN (-9223372036854775807LL-1)
|
||||
|
||||
#define INT8_MAX (127)
|
||||
#define INT16_MAX (32767)
|
||||
#define INT32_MAX (2147483647)
|
||||
#define INT64_MAX (9223372036854775807LL)
|
||||
|
||||
#define UINT8_MAX (255)
|
||||
#define UINT16_MAX (65535)
|
||||
#define UINT32_MAX (4294967295U)
|
||||
#define UINT64_MAX (18446744073709551615ULL)
|
||||
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
#define SIZE_MAX ((size_t)(__LONG_MAX__) * 2 + 1)
|
||||
#define INTPTR_MIN (-__LONG_MAX__ - 1)
|
||||
#define INTPTR_MAX __LONG_MAX__
|
||||
#define PTRDIFF_MIN INTPTR_MIN
|
||||
#define PTRDIFF_MAX INTPTR_MAX
|
||||
#define UINTPTR_MAX SIZE_MAX
|
||||
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST16_MIN INTPTR_MIN
|
||||
#define INT_FAST32_MIN INTPTR_MIN
|
||||
#define INT_FAST64_MIN INTPTR_MIN
|
||||
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MAX INTPTR_MAX
|
||||
#define INT_FAST32_MAX INTPTR_MAX
|
||||
#define INT_FAST64_MAX INTPTR_MAX
|
||||
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX SIZE_MAX
|
||||
#define UINT_FAST32_MAX SIZE_MAX
|
||||
#define UINT_FAST64_MAX SIZE_MAX
|
||||
|
||||
#endif /* _NOLIBC_STDINT_H */
|
@ -11,7 +11,6 @@
|
||||
#include "std.h"
|
||||
|
||||
/* system includes */
|
||||
#include <asm/fcntl.h> // for O_*
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/signal.h> // for SIGCHLD
|
||||
#include <asm/ioctls.h>
|
||||
@ -20,6 +19,8 @@
|
||||
#include <linux/loop.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/auxvec.h>
|
||||
#include <linux/fcntl.h> // for O_* and AT_*
|
||||
#include <linux/stat.h> // for statx()
|
||||
|
||||
#include "arch.h"
|
||||
#include "errno.h"
|
||||
@ -410,6 +411,27 @@ int getdents64(int fd, struct linux_dirent64 *dirp, int count)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* uid_t geteuid(void);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
uid_t sys_geteuid(void)
|
||||
{
|
||||
#ifdef __NR_geteuid32
|
||||
return my_syscall0(__NR_geteuid32);
|
||||
#else
|
||||
return my_syscall0(__NR_geteuid);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
uid_t geteuid(void)
|
||||
{
|
||||
return sys_geteuid();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pid_t getpgid(pid_t pid);
|
||||
*/
|
||||
@ -544,6 +566,27 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* uid_t getuid(void);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
uid_t sys_getuid(void)
|
||||
{
|
||||
#ifdef __NR_getuid32
|
||||
return my_syscall0(__NR_getuid32);
|
||||
#else
|
||||
return my_syscall0(__NR_getuid);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
uid_t getuid(void)
|
||||
{
|
||||
return sys_getuid();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int ioctl(int fd, unsigned long req, void *value);
|
||||
*/
|
||||
@ -1048,12 +1091,66 @@ pid_t setsid(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(__NR_statx)
|
||||
/*
|
||||
* int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
|
||||
{
|
||||
return my_syscall5(__NR_statx, fd, path, flags, mask, buf);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
|
||||
{
|
||||
int ret = sys_statx(fd, path, flags, mask, buf);
|
||||
|
||||
if (ret < 0) {
|
||||
SET_ERRNO(-ret);
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* int stat(const char *path, struct stat *buf);
|
||||
* Warning: the struct stat's layout is arch-dependent.
|
||||
*/
|
||||
|
||||
#if defined(__NR_statx) && !defined(__NR_newfstatat) && !defined(__NR_stat)
|
||||
/*
|
||||
* Maybe we can just use statx() when available for all architectures?
|
||||
*/
|
||||
static __attribute__((unused))
|
||||
int sys_stat(const char *path, struct stat *buf)
|
||||
{
|
||||
struct statx statx;
|
||||
long ret;
|
||||
|
||||
ret = sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx);
|
||||
buf->st_dev = ((statx.stx_dev_minor & 0xff)
|
||||
| (statx.stx_dev_major << 8)
|
||||
| ((statx.stx_dev_minor & ~0xff) << 12));
|
||||
buf->st_ino = statx.stx_ino;
|
||||
buf->st_mode = statx.stx_mode;
|
||||
buf->st_nlink = statx.stx_nlink;
|
||||
buf->st_uid = statx.stx_uid;
|
||||
buf->st_gid = statx.stx_gid;
|
||||
buf->st_rdev = ((statx.stx_rdev_minor & 0xff)
|
||||
| (statx.stx_rdev_major << 8)
|
||||
| ((statx.stx_rdev_minor & ~0xff) << 12));
|
||||
buf->st_size = statx.stx_size;
|
||||
buf->st_blksize = statx.stx_blksize;
|
||||
buf->st_blocks = statx.stx_blocks;
|
||||
buf->st_atime = statx.stx_atime.tv_sec;
|
||||
buf->st_mtime = statx.stx_mtime.tv_sec;
|
||||
buf->st_ctime = statx.stx_ctime.tv_sec;
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static __attribute__((unused))
|
||||
int sys_stat(const char *path, struct stat *buf)
|
||||
{
|
||||
@ -1083,6 +1180,7 @@ int sys_stat(const char *path, struct stat *buf)
|
||||
buf->st_ctime = stat.st_ctime;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static __attribute__((unused))
|
||||
int stat(const char *path, struct stat *buf)
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "std.h"
|
||||
#include <linux/time.h>
|
||||
#include <linux/stat.h>
|
||||
|
||||
|
||||
/* Only the generic macros and types may be defined here. The arch-specific
|
||||
@ -16,7 +17,11 @@
|
||||
* the layout of sys_stat_struct must not be defined here.
|
||||
*/
|
||||
|
||||
/* stat flags (WARNING, octal here) */
|
||||
/* stat flags (WARNING, octal here). We need to check for an existing
|
||||
* definition because linux/stat.h may omit to define those if it finds
|
||||
* that any glibc header was already included.
|
||||
*/
|
||||
#if !defined(S_IFMT)
|
||||
#define S_IFDIR 0040000
|
||||
#define S_IFCHR 0020000
|
||||
#define S_IFBLK 0060000
|
||||
@ -34,6 +39,22 @@
|
||||
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||||
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||||
|
||||
#define S_IRWXU 00700
|
||||
#define S_IRUSR 00400
|
||||
#define S_IWUSR 00200
|
||||
#define S_IXUSR 00100
|
||||
|
||||
#define S_IRWXG 00070
|
||||
#define S_IRGRP 00040
|
||||
#define S_IWGRP 00020
|
||||
#define S_IXGRP 00010
|
||||
|
||||
#define S_IRWXO 00007
|
||||
#define S_IROTH 00004
|
||||
#define S_IWOTH 00002
|
||||
#define S_IXOTH 00001
|
||||
#endif
|
||||
|
||||
/* dirent types */
|
||||
#define DT_UNKNOWN 0x0
|
||||
#define DT_FIFO 0x1
|
||||
@ -60,11 +81,6 @@
|
||||
#define MAXPATHLEN (PATH_MAX)
|
||||
#endif
|
||||
|
||||
/* Special FD used by all the *at functions */
|
||||
#ifndef AT_FDCWD
|
||||
#define AT_FDCWD (-100)
|
||||
#endif
|
||||
|
||||
/* whence values for lseek() */
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
@ -81,6 +97,8 @@
|
||||
/* Macros used on waitpid()'s return status */
|
||||
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||
#define WIFEXITED(status) (((status) & 0x7f) == 0)
|
||||
#define WTERMSIG(status) ((status) & 0x7f)
|
||||
#define WIFSIGNALED(status) ((status) - 1 < 0xff)
|
||||
|
||||
/* waitpid() flags */
|
||||
#define WNOHANG 1
|
||||
|
@ -13,6 +13,11 @@
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
int msleep(unsigned int msecs)
|
||||
{
|
||||
|
@ -1,6 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Makefile for nolibc tests
|
||||
include ../../../scripts/Makefile.include
|
||||
# We need this for the "cc-option" macro.
|
||||
include ../../../build/Build.include
|
||||
|
||||
# we're in ".../tools/testing/selftests/nolibc"
|
||||
ifeq ($(srctree),)
|
||||
@ -13,52 +15,56 @@ ARCH = $(SUBARCH)
|
||||
endif
|
||||
|
||||
# kernel image names by architecture
|
||||
IMAGE_i386 = arch/x86/boot/bzImage
|
||||
IMAGE_x86_64 = arch/x86/boot/bzImage
|
||||
IMAGE_x86 = arch/x86/boot/bzImage
|
||||
IMAGE_arm64 = arch/arm64/boot/Image
|
||||
IMAGE_arm = arch/arm/boot/zImage
|
||||
IMAGE_mips = vmlinuz
|
||||
IMAGE_riscv = arch/riscv/boot/Image
|
||||
IMAGE_s390 = arch/s390/boot/bzImage
|
||||
IMAGE = $(IMAGE_$(ARCH))
|
||||
IMAGE_NAME = $(notdir $(IMAGE))
|
||||
IMAGE_i386 = arch/x86/boot/bzImage
|
||||
IMAGE_x86_64 = arch/x86/boot/bzImage
|
||||
IMAGE_x86 = arch/x86/boot/bzImage
|
||||
IMAGE_arm64 = arch/arm64/boot/Image
|
||||
IMAGE_arm = arch/arm/boot/zImage
|
||||
IMAGE_mips = vmlinuz
|
||||
IMAGE_riscv = arch/riscv/boot/Image
|
||||
IMAGE_s390 = arch/s390/boot/bzImage
|
||||
IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi
|
||||
IMAGE = $(IMAGE_$(ARCH))
|
||||
IMAGE_NAME = $(notdir $(IMAGE))
|
||||
|
||||
# default kernel configurations that appear to be usable
|
||||
DEFCONFIG_i386 = defconfig
|
||||
DEFCONFIG_x86_64 = defconfig
|
||||
DEFCONFIG_x86 = defconfig
|
||||
DEFCONFIG_arm64 = defconfig
|
||||
DEFCONFIG_arm = multi_v7_defconfig
|
||||
DEFCONFIG_mips = malta_defconfig
|
||||
DEFCONFIG_riscv = defconfig
|
||||
DEFCONFIG_s390 = defconfig
|
||||
DEFCONFIG = $(DEFCONFIG_$(ARCH))
|
||||
DEFCONFIG_i386 = defconfig
|
||||
DEFCONFIG_x86_64 = defconfig
|
||||
DEFCONFIG_x86 = defconfig
|
||||
DEFCONFIG_arm64 = defconfig
|
||||
DEFCONFIG_arm = multi_v7_defconfig
|
||||
DEFCONFIG_mips = malta_defconfig
|
||||
DEFCONFIG_riscv = defconfig
|
||||
DEFCONFIG_s390 = defconfig
|
||||
DEFCONFIG_loongarch = defconfig
|
||||
DEFCONFIG = $(DEFCONFIG_$(ARCH))
|
||||
|
||||
# optional tests to run (default = all)
|
||||
TEST =
|
||||
|
||||
# QEMU_ARCH: arch names used by qemu
|
||||
QEMU_ARCH_i386 = i386
|
||||
QEMU_ARCH_x86_64 = x86_64
|
||||
QEMU_ARCH_x86 = x86_64
|
||||
QEMU_ARCH_arm64 = aarch64
|
||||
QEMU_ARCH_arm = arm
|
||||
QEMU_ARCH_mips = mipsel # works with malta_defconfig
|
||||
QEMU_ARCH_riscv = riscv64
|
||||
QEMU_ARCH_s390 = s390x
|
||||
QEMU_ARCH = $(QEMU_ARCH_$(ARCH))
|
||||
QEMU_ARCH_i386 = i386
|
||||
QEMU_ARCH_x86_64 = x86_64
|
||||
QEMU_ARCH_x86 = x86_64
|
||||
QEMU_ARCH_arm64 = aarch64
|
||||
QEMU_ARCH_arm = arm
|
||||
QEMU_ARCH_mips = mipsel # works with malta_defconfig
|
||||
QEMU_ARCH_riscv = riscv64
|
||||
QEMU_ARCH_s390 = s390x
|
||||
QEMU_ARCH_loongarch = loongarch64
|
||||
QEMU_ARCH = $(QEMU_ARCH_$(ARCH))
|
||||
|
||||
# QEMU_ARGS : some arch-specific args to pass to qemu
|
||||
QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS = $(QEMU_ARGS_$(ARCH))
|
||||
QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||
QEMU_ARGS = $(QEMU_ARGS_$(ARCH))
|
||||
|
||||
# OUTPUT is only set when run from the main makefile, otherwise
|
||||
# it defaults to this nolibc directory.
|
||||
@ -70,8 +76,16 @@ else
|
||||
Q=@
|
||||
endif
|
||||
|
||||
CFLAGS_STACKPROTECTOR = -DNOLIBC_STACKPROTECTOR \
|
||||
$(call cc-option,-mstack-protector-guard=global) \
|
||||
$(call cc-option,-fstack-protector-all)
|
||||
CFLAGS_STKP_i386 = $(CFLAGS_STACKPROTECTOR)
|
||||
CFLAGS_STKP_x86_64 = $(CFLAGS_STACKPROTECTOR)
|
||||
CFLAGS_STKP_x86 = $(CFLAGS_STACKPROTECTOR)
|
||||
CFLAGS_s390 = -m64
|
||||
CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables $(CFLAGS_$(ARCH))
|
||||
CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables \
|
||||
$(call cc-option,-fno-stack-protector) \
|
||||
$(CFLAGS_STKP_$(ARCH)) $(CFLAGS_$(ARCH))
|
||||
LDFLAGS := -s
|
||||
|
||||
help:
|
||||
|
@ -130,111 +130,111 @@ static int pad_spc(int llen, int cnt, const char *fmt, ...)
|
||||
*/
|
||||
|
||||
#define EXPECT_ZR(cond, expr) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0)
|
||||
|
||||
static int expect_zr(int expr, int llen)
|
||||
{
|
||||
int ret = !(expr == 0);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_NZ(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0)
|
||||
|
||||
static int expect_nz(int expr, int llen)
|
||||
{
|
||||
int ret = !(expr != 0);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_EQ(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_eq(int expr, int llen, int val)
|
||||
static int expect_eq(uint64_t expr, int llen, uint64_t val)
|
||||
{
|
||||
int ret = !(expr == val);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
llen += printf(" = %lld ", expr);
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_NE(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_ne(int expr, int llen, int val)
|
||||
{
|
||||
int ret = !(expr != val);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_GE(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_ge(int expr, int llen, int val)
|
||||
{
|
||||
int ret = !(expr >= val);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_GT(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_gt(int expr, int llen, int val)
|
||||
{
|
||||
int ret = !(expr > val);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_LE(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_le(int expr, int llen, int val)
|
||||
{
|
||||
int ret = !(expr <= val);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_LT(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_lt(int expr, int llen, int val)
|
||||
{
|
||||
int ret = !(expr < val);
|
||||
|
||||
llen += printf(" = %d ", expr);
|
||||
pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_SYSZR(cond, expr) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0)
|
||||
|
||||
static int expect_syszr(int expr, int llen)
|
||||
{
|
||||
@ -243,17 +243,17 @@ static int expect_syszr(int expr, int llen)
|
||||
if (expr) {
|
||||
ret = 1;
|
||||
llen += printf(" = %d %s ", expr, errorname(errno));
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += printf(" = %d ", expr);
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_SYSEQ(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_syseq(int expr, int llen, int val)
|
||||
{
|
||||
@ -262,17 +262,17 @@ static int expect_syseq(int expr, int llen, int val)
|
||||
if (expr != val) {
|
||||
ret = 1;
|
||||
llen += printf(" = %d %s ", expr, errorname(errno));
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += printf(" = %d ", expr);
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_SYSNE(cond, expr, val) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0)
|
||||
|
||||
static int expect_sysne(int expr, int llen, int val)
|
||||
{
|
||||
@ -281,17 +281,17 @@ static int expect_sysne(int expr, int llen, int val)
|
||||
if (expr == val) {
|
||||
ret = 1;
|
||||
llen += printf(" = %d %s ", expr, errorname(errno));
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += printf(" = %d ", expr);
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_SYSER(cond, expr, expret, experr) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0)
|
||||
|
||||
static int expect_syserr(int expr, int expret, int experr, int llen)
|
||||
{
|
||||
@ -302,16 +302,16 @@ static int expect_syserr(int expr, int expret, int experr, int llen)
|
||||
if (expr != expret || _errno != experr) {
|
||||
ret = 1;
|
||||
llen += printf(" != (%d %s) ", expret, errorname(experr));
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_PTRZR(cond, expr) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0)
|
||||
|
||||
static int expect_ptrzr(const void *expr, int llen)
|
||||
{
|
||||
@ -320,16 +320,16 @@ static int expect_ptrzr(const void *expr, int llen)
|
||||
llen += printf(" = <%p> ", expr);
|
||||
if (expr) {
|
||||
ret = 1;
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_PTRNZ(cond, expr) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0)
|
||||
|
||||
static int expect_ptrnz(const void *expr, int llen)
|
||||
{
|
||||
@ -338,16 +338,16 @@ static int expect_ptrnz(const void *expr, int llen)
|
||||
llen += printf(" = <%p> ", expr);
|
||||
if (!expr) {
|
||||
ret = 1;
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_STRZR(cond, expr) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0)
|
||||
|
||||
static int expect_strzr(const char *expr, int llen)
|
||||
{
|
||||
@ -356,16 +356,16 @@ static int expect_strzr(const char *expr, int llen)
|
||||
llen += printf(" = <%s> ", expr);
|
||||
if (expr) {
|
||||
ret = 1;
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_STRNZ(cond, expr) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0)
|
||||
|
||||
static int expect_strnz(const char *expr, int llen)
|
||||
{
|
||||
@ -374,16 +374,16 @@ static int expect_strnz(const char *expr, int llen)
|
||||
llen += printf(" = <%s> ", expr);
|
||||
if (!expr) {
|
||||
ret = 1;
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_STREQ(cond, expr, cmp) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0)
|
||||
|
||||
static int expect_streq(const char *expr, int llen, const char *cmp)
|
||||
{
|
||||
@ -392,16 +392,16 @@ static int expect_streq(const char *expr, int llen, const char *cmp)
|
||||
llen += printf(" = <%s> ", expr);
|
||||
if (strcmp(expr, cmp) != 0) {
|
||||
ret = 1;
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define EXPECT_STRNE(cond, expr, cmp) \
|
||||
do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0)
|
||||
do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0)
|
||||
|
||||
static int expect_strne(const char *expr, int llen, const char *cmp)
|
||||
{
|
||||
@ -410,9 +410,9 @@ static int expect_strne(const char *expr, int llen, const char *cmp)
|
||||
llen += printf(" = <%s> ", expr);
|
||||
if (strcmp(expr, cmp) == 0) {
|
||||
ret = 1;
|
||||
llen += pad_spc(llen, 40, "[FAIL]\n");
|
||||
llen += pad_spc(llen, 64, "[FAIL]\n");
|
||||
} else {
|
||||
llen += pad_spc(llen, 40, " [OK]\n");
|
||||
llen += pad_spc(llen, 64, " [OK]\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -477,6 +477,7 @@ static int test_getpagesize(void)
|
||||
int run_syscall(int min, int max)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int euid0;
|
||||
int proc;
|
||||
int test;
|
||||
int tmp;
|
||||
@ -486,6 +487,9 @@ int run_syscall(int min, int max)
|
||||
/* <proc> indicates whether or not /proc is mounted */
|
||||
proc = stat("/proc", &stat_buf) == 0;
|
||||
|
||||
/* this will be used to skip certain tests that can't be run unprivileged */
|
||||
euid0 = geteuid() == 0;
|
||||
|
||||
for (test = min; test >= 0 && test <= max; test++) {
|
||||
int llen = 0; // line length
|
||||
|
||||
@ -511,7 +515,7 @@ int run_syscall(int min, int max)
|
||||
CASE_TEST(chmod_net); EXPECT_SYSZR(proc, chmod("/proc/self/net", 0555)); break;
|
||||
CASE_TEST(chmod_self); EXPECT_SYSER(proc, chmod("/proc/self", 0555), -1, EPERM); break;
|
||||
CASE_TEST(chown_self); EXPECT_SYSER(proc, chown("/proc/self", 0, 0), -1, EPERM); break;
|
||||
CASE_TEST(chroot_root); EXPECT_SYSZR(1, chroot("/")); break;
|
||||
CASE_TEST(chroot_root); EXPECT_SYSZR(euid0, chroot("/")); break;
|
||||
CASE_TEST(chroot_blah); EXPECT_SYSER(1, chroot("/proc/self/blah"), -1, ENOENT); break;
|
||||
CASE_TEST(chroot_exe); EXPECT_SYSER(proc, chroot("/proc/self/exe"), -1, ENOTDIR); break;
|
||||
CASE_TEST(close_m1); EXPECT_SYSER(1, close(-1), -1, EBADF); break;
|
||||
@ -536,7 +540,7 @@ int run_syscall(int min, int max)
|
||||
CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break;
|
||||
CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break;
|
||||
CASE_TEST(link_blah); EXPECT_SYSER(1, link("/proc/self/blah", "/blah"), -1, ENOENT); break;
|
||||
CASE_TEST(link_dir); EXPECT_SYSER(1, link("/", "/blah"), -1, EPERM); break;
|
||||
CASE_TEST(link_dir); EXPECT_SYSER(euid0, link("/", "/blah"), -1, EPERM); break;
|
||||
CASE_TEST(link_cross); EXPECT_SYSER(proc, link("/proc/self/net", "/blah"), -1, EXDEV); break;
|
||||
CASE_TEST(lseek_m1); EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break;
|
||||
CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break;
|
||||
@ -602,6 +606,59 @@ int run_stdlib(int min, int max)
|
||||
CASE_TEST(memcmp_e0_20); EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x20", 4), 0); break;
|
||||
CASE_TEST(memcmp_80_e0); EXPECT_LT(1, memcmp("aaa\x80", "aaa\xe0", 4), 0); break;
|
||||
CASE_TEST(memcmp_e0_80); EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x80", 4), 0); break;
|
||||
CASE_TEST(limit_int8_max); EXPECT_EQ(1, INT8_MAX, (int8_t) 0x7f); break;
|
||||
CASE_TEST(limit_int8_min); EXPECT_EQ(1, INT8_MIN, (int8_t) 0x80); break;
|
||||
CASE_TEST(limit_uint8_max); EXPECT_EQ(1, UINT8_MAX, (uint8_t) 0xff); break;
|
||||
CASE_TEST(limit_int16_max); EXPECT_EQ(1, INT16_MAX, (int16_t) 0x7fff); break;
|
||||
CASE_TEST(limit_int16_min); EXPECT_EQ(1, INT16_MIN, (int16_t) 0x8000); break;
|
||||
CASE_TEST(limit_uint16_max); EXPECT_EQ(1, UINT16_MAX, (uint16_t) 0xffff); break;
|
||||
CASE_TEST(limit_int32_max); EXPECT_EQ(1, INT32_MAX, (int32_t) 0x7fffffff); break;
|
||||
CASE_TEST(limit_int32_min); EXPECT_EQ(1, INT32_MIN, (int32_t) 0x80000000); break;
|
||||
CASE_TEST(limit_uint32_max); EXPECT_EQ(1, UINT32_MAX, (uint32_t) 0xffffffff); break;
|
||||
CASE_TEST(limit_int64_max); EXPECT_EQ(1, INT64_MAX, (int64_t) 0x7fffffffffffffff); break;
|
||||
CASE_TEST(limit_int64_min); EXPECT_EQ(1, INT64_MIN, (int64_t) 0x8000000000000000); break;
|
||||
CASE_TEST(limit_uint64_max); EXPECT_EQ(1, UINT64_MAX, (uint64_t) 0xffffffffffffffff); break;
|
||||
CASE_TEST(limit_int_least8_max); EXPECT_EQ(1, INT_LEAST8_MAX, (int_least8_t) 0x7f); break;
|
||||
CASE_TEST(limit_int_least8_min); EXPECT_EQ(1, INT_LEAST8_MIN, (int_least8_t) 0x80); break;
|
||||
CASE_TEST(limit_uint_least8_max); EXPECT_EQ(1, UINT_LEAST8_MAX, (uint_least8_t) 0xff); break;
|
||||
CASE_TEST(limit_int_least16_max); EXPECT_EQ(1, INT_LEAST16_MAX, (int_least16_t) 0x7fff); break;
|
||||
CASE_TEST(limit_int_least16_min); EXPECT_EQ(1, INT_LEAST16_MIN, (int_least16_t) 0x8000); break;
|
||||
CASE_TEST(limit_uint_least16_max); EXPECT_EQ(1, UINT_LEAST16_MAX, (uint_least16_t) 0xffff); break;
|
||||
CASE_TEST(limit_int_least32_max); EXPECT_EQ(1, INT_LEAST32_MAX, (int_least32_t) 0x7fffffff); break;
|
||||
CASE_TEST(limit_int_least32_min); EXPECT_EQ(1, INT_LEAST32_MIN, (int_least32_t) 0x80000000); break;
|
||||
CASE_TEST(limit_uint_least32_max); EXPECT_EQ(1, UINT_LEAST32_MAX, (uint_least32_t) 0xffffffffU); break;
|
||||
CASE_TEST(limit_int_least64_min); EXPECT_EQ(1, INT_LEAST64_MIN, (int_least64_t) 0x8000000000000000LL); break;
|
||||
CASE_TEST(limit_int_least64_max); EXPECT_EQ(1, INT_LEAST64_MAX, (int_least64_t) 0x7fffffffffffffffLL); break;
|
||||
CASE_TEST(limit_uint_least64_max); EXPECT_EQ(1, UINT_LEAST64_MAX, (uint_least64_t) 0xffffffffffffffffULL); break;
|
||||
CASE_TEST(limit_int_fast8_max); EXPECT_EQ(1, INT_FAST8_MAX, (int_fast8_t) 0x7f); break;
|
||||
CASE_TEST(limit_int_fast8_min); EXPECT_EQ(1, INT_FAST8_MIN, (int_fast8_t) 0x80); break;
|
||||
CASE_TEST(limit_uint_fast8_max); EXPECT_EQ(1, UINT_FAST8_MAX, (uint_fast8_t) 0xff); break;
|
||||
CASE_TEST(limit_int_fast16_min); EXPECT_EQ(1, INT_FAST16_MIN, (int_fast16_t) INTPTR_MIN); break;
|
||||
CASE_TEST(limit_int_fast16_max); EXPECT_EQ(1, INT_FAST16_MAX, (int_fast16_t) INTPTR_MAX); break;
|
||||
CASE_TEST(limit_uint_fast16_max); EXPECT_EQ(1, UINT_FAST16_MAX, (uint_fast16_t) UINTPTR_MAX); break;
|
||||
CASE_TEST(limit_int_fast32_min); EXPECT_EQ(1, INT_FAST32_MIN, (int_fast32_t) INTPTR_MIN); break;
|
||||
CASE_TEST(limit_int_fast32_max); EXPECT_EQ(1, INT_FAST32_MAX, (int_fast32_t) INTPTR_MAX); break;
|
||||
CASE_TEST(limit_uint_fast32_max); EXPECT_EQ(1, UINT_FAST32_MAX, (uint_fast32_t) UINTPTR_MAX); break;
|
||||
CASE_TEST(limit_int_fast64_min); EXPECT_EQ(1, INT_FAST64_MIN, (int_fast64_t) INTPTR_MIN); break;
|
||||
CASE_TEST(limit_int_fast64_max); EXPECT_EQ(1, INT_FAST64_MAX, (int_fast64_t) INTPTR_MAX); break;
|
||||
CASE_TEST(limit_uint_fast64_max); EXPECT_EQ(1, UINT_FAST64_MAX, (uint_fast64_t) UINTPTR_MAX); break;
|
||||
#if __SIZEOF_LONG__ == 8
|
||||
CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x8000000000000000LL); break;
|
||||
CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffffffffffffLL); break;
|
||||
CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffffffffffULL); break;
|
||||
CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x8000000000000000LL); break;
|
||||
CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffffffffffffLL); break;
|
||||
CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffffffffffULL); break;
|
||||
#elif __SIZEOF_LONG__ == 4
|
||||
CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x80000000); break;
|
||||
CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffff); break;
|
||||
CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffU); break;
|
||||
CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x80000000); break;
|
||||
CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffff); break;
|
||||
CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffU); break;
|
||||
#else
|
||||
# warning "__SIZEOF_LONG__ is undefined"
|
||||
#endif /* __SIZEOF_LONG__ */
|
||||
case __LINE__:
|
||||
return ret; /* must be last */
|
||||
/* note: do not set any defaults so as to permit holes above */
|
||||
@ -610,6 +667,63 @@ int run_stdlib(int min, int max)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
__attribute__((optnone))
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((optimize("O0")))
|
||||
#endif
|
||||
static int smash_stack(void)
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
for (size_t i = 0; i < 200; i++)
|
||||
buf[i] = 'P';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int run_protection(int min, int max)
|
||||
{
|
||||
pid_t pid;
|
||||
int llen = 0, status;
|
||||
|
||||
llen += printf("0 -fstackprotector ");
|
||||
|
||||
#if !defined(NOLIBC_STACKPROTECTOR)
|
||||
llen += printf("not supported");
|
||||
pad_spc(llen, 64, "[SKIPPED]\n");
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
pid = -1;
|
||||
pid = fork();
|
||||
|
||||
switch (pid) {
|
||||
case -1:
|
||||
llen += printf("fork()");
|
||||
pad_spc(llen, 64, "[FAIL]\n");
|
||||
return 1;
|
||||
|
||||
case 0:
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
|
||||
smash_stack();
|
||||
return 1;
|
||||
|
||||
default:
|
||||
pid = waitpid(pid, &status, 0);
|
||||
|
||||
if (pid == -1 || !WIFSIGNALED(status) || WTERMSIG(status) != SIGABRT) {
|
||||
llen += printf("waitpid()");
|
||||
pad_spc(llen, 64, "[FAIL]\n");
|
||||
return 1;
|
||||
}
|
||||
pad_spc(llen, 64, " [OK]\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
|
||||
int prepare(void)
|
||||
{
|
||||
@ -660,10 +774,11 @@ int prepare(void)
|
||||
}
|
||||
|
||||
/* This is the definition of known test names, with their functions */
|
||||
static struct test test_names[] = {
|
||||
static const struct test test_names[] = {
|
||||
/* add new tests here */
|
||||
{ .name = "syscall", .func = run_syscall },
|
||||
{ .name = "stdlib", .func = run_stdlib },
|
||||
{ .name = "syscall", .func = run_syscall },
|
||||
{ .name = "stdlib", .func = run_stdlib },
|
||||
{ .name = "protection", .func = run_protection },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user