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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nolibc-20260206-for-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc

Pull nolibc updates from Thomas Weißschuh:

- All time-related functionality uses 64-bit timestamps for
y2038 compatibility

- fread() and fskeek() support

- ptrace() support

- Addition of libc-test to the regular kselftests

- Smaller cleanups and fixes to the code and build system

* tag 'nolibc-20260206-for-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc: (25 commits)
tools/nolibc: Add a simple test for writing to a FILE and reading it back
tools/nolibc: Add fseek() to stdio.h
tools/nolibc: Add fread() to stdio.h
selftests/nolibc: also test libc-test through regular selftest framework
selftests/nolibc: scope custom flags to the nolibc-test target
selftests/nolibc: try to read from stdin in readv_zero test
selftests/nolibc: always build sparc32 tests with -mcpu=v8
tools/nolibc: align sys_vfork() with sys_fork()
selftests/nolibc: drop NOLIBC_SYSROOT=0 logic
selftests/nolibc: add static assertions around time types handling
tools/nolibc: add __nolibc_static_assert()
tools/nolibc: add compiler version detection macros
tools/nolibc: remove time conversions
selftests/nolibc: test compatibility of nolibc and kernel time types
tools/nolibc: always use 64-bit time types
tools/nolibc: use custom structs timespec and timeval
tools/nolibc/select: avoid libgcc 64-bit multiplications
tools/nolibc/gettimeofday: avoid libgcc 64-bit divisions
tools/nolibc: prefer explicit 64-bit time-related system calls
tools/nolibc/time: drop invocation of gettimeofday system call
...

+304 -158
+5 -1
tools/include/nolibc/Makefile
··· 54 54 sys/mman.h \ 55 55 sys/mount.h \ 56 56 sys/prctl.h \ 57 + sys/ptrace.h \ 57 58 sys/random.h \ 58 59 sys/reboot.h \ 59 60 sys/resource.h \ ··· 104 103 $(Q)$(MAKE) -C $(srctree) headers 105 104 $(Q)$(MAKE) -C $(srctree) headers_install INSTALL_HDR_PATH=$(OUTPUT)sysroot 106 105 106 + CFLAGS_s390 := -m64 107 + CFLAGS := $(CFLAGS_$(ARCH)) 108 + 107 109 headers_check: headers_standalone 108 110 $(Q)for header in $(filter-out crt.h std.h,$(all_files)); do \ 109 - $(CC) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \ 111 + $(CC) $(CFLAGS) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \ 110 112 -I$(or $(objtree),$(srctree))/usr/include -include $$header -include $$header || exit 1; \ 111 113 done 112 114
+11
tools/include/nolibc/arch-s390.h
··· 5 5 6 6 #ifndef _NOLIBC_ARCH_S390_H 7 7 #define _NOLIBC_ARCH_S390_H 8 + 9 + #include "types.h" 10 + 11 + #include <linux/sched.h> 8 12 #include <linux/signal.h> 9 13 #include <linux/unistd.h> 10 14 ··· 189 185 return my_syscall5(__NR_clone, 0, SIGCHLD, 0, 0, 0); 190 186 } 191 187 #define sys_fork sys_fork 188 + 189 + static __attribute__((unused)) 190 + pid_t sys_vfork(void) 191 + { 192 + return my_syscall5(__NR_clone, 0, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0); 193 + } 194 + #define sys_vfork sys_vfork 192 195 193 196 #endif /* _NOLIBC_ARCH_S390_H */
+24
tools/include/nolibc/compiler.h
··· 47 47 # define __nolibc_fallthrough do { } while (0) 48 48 #endif /* __nolibc_has_attribute(fallthrough) */ 49 49 50 + #define __nolibc_version(_major, _minor, _patch) ((_major) * 10000 + (_minor) * 100 + (_patch)) 51 + 52 + #ifdef __GNUC__ 53 + # define __nolibc_gnuc_version \ 54 + __nolibc_version(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 55 + #else 56 + # define __nolibc_gnuc_version 0 57 + #endif /* __GNUC__ */ 58 + 59 + #ifdef __clang__ 60 + # define __nolibc_clang_version \ 61 + __nolibc_version(__clang_major__, __clang_minor__, __clang_patchlevel__) 62 + #else 63 + # define __nolibc_clang_version 0 64 + #endif /* __clang__ */ 65 + 66 + #if __STDC_VERSION__ >= 201112L || \ 67 + __nolibc_gnuc_version >= __nolibc_version(4, 6, 0) || \ 68 + __nolibc_clang_version >= __nolibc_version(3, 0, 0) 69 + # define __nolibc_static_assert(_t) _Static_assert(_t, "") 70 + #else 71 + # define __nolibc_static_assert(_t) 72 + #endif 73 + 50 74 #endif /* _NOLIBC_COMPILER_H */
+1
tools/include/nolibc/nolibc.h
··· 101 101 #include "sys/mman.h" 102 102 #include "sys/mount.h" 103 103 #include "sys/prctl.h" 104 + #include "sys/ptrace.h" 104 105 #include "sys/random.h" 105 106 #include "sys/reboot.h" 106 107 #include "sys/resource.h"
+8 -10
tools/include/nolibc/poll.h
··· 23 23 static __attribute__((unused)) 24 24 int sys_poll(struct pollfd *fds, int nfds, int timeout) 25 25 { 26 - #if defined(__NR_ppoll) 27 - struct timespec t; 28 - 29 - if (timeout >= 0) { 30 - t.tv_sec = timeout / 1000; 31 - t.tv_nsec = (timeout % 1000) * 1000000; 32 - } 33 - return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0); 34 - #elif defined(__NR_ppoll_time64) 26 + #if defined(__NR_ppoll_time64) 35 27 struct __kernel_timespec t; 36 28 37 29 if (timeout >= 0) { ··· 32 40 } 33 41 return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0); 34 42 #else 35 - return my_syscall3(__NR_poll, fds, nfds, timeout); 43 + struct __kernel_old_timespec t; 44 + 45 + if (timeout >= 0) { 46 + t.tv_sec = timeout / 1000; 47 + t.tv_nsec = (timeout % 1000) * 1000000; 48 + } 49 + return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0); 36 50 #endif 37 51 } 38 52
+1 -1
tools/include/nolibc/std.h
··· 29 29 typedef int64_t off_t; 30 30 typedef signed long blksize_t; 31 31 typedef signed long blkcnt_t; 32 - typedef __kernel_time_t time_t; 32 + typedef __kernel_time64_t time_t; 33 33 34 34 #endif /* _NOLIBC_STD_H */
+52 -1
tools/include/nolibc/stdio.h
··· 170 170 } 171 171 172 172 173 - /* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */ 173 + /* fwrite(), fread(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */ 174 174 175 175 /* internal fwrite()-like function which only takes a size and returns 0 on 176 176 * success or EOF on error. It automatically retries on short writes. ··· 202 202 s += size; 203 203 } 204 204 return written; 205 + } 206 + 207 + /* internal fread()-like function which only takes a size and returns 0 on 208 + * success or EOF on error. It automatically retries on short reads. 209 + */ 210 + static __attribute__((unused)) 211 + int _fread(void *buf, size_t size, FILE *stream) 212 + { 213 + int fd = fileno(stream); 214 + ssize_t ret; 215 + 216 + while (size) { 217 + ret = read(fd, buf, size); 218 + if (ret <= 0) 219 + return EOF; 220 + size -= ret; 221 + buf += ret; 222 + } 223 + return 0; 224 + } 225 + 226 + static __attribute__((unused)) 227 + size_t fread(void *s, size_t size, size_t nmemb, FILE *stream) 228 + { 229 + size_t nread; 230 + 231 + for (nread = 0; nread < nmemb; nread++) { 232 + if (_fread(s, size, stream) != 0) 233 + break; 234 + s += size; 235 + } 236 + return nread; 205 237 } 206 238 207 239 static __attribute__((unused)) ··· 269 237 if (ofs < size) 270 238 s[ofs] = 0; 271 239 return ofs ? s : NULL; 240 + } 241 + 242 + 243 + /* fseek */ 244 + static __attribute__((unused)) 245 + int fseek(FILE *stream, long offset, int whence) 246 + { 247 + int fd = fileno(stream); 248 + off_t ret; 249 + 250 + ret = lseek(fd, offset, whence); 251 + 252 + /* lseek() and fseek() differ in that lseek returns the new 253 + * position or -1, fseek() returns either 0 or -1. 254 + */ 255 + if (ret >= 0) 256 + return 0; 257 + 258 + return -1; 272 259 } 273 260 274 261
+5 -13
tools/include/nolibc/sys.h
··· 22 22 #include <linux/time.h> 23 23 #include <linux/auxvec.h> 24 24 #include <linux/fcntl.h> /* for O_* and AT_* */ 25 - #include <linux/sched.h> /* for clone_args */ 25 + #include <linux/sched.h> /* for CLONE_* */ 26 26 #include <linux/stat.h> /* for statx() */ 27 27 28 28 #include "errno.h" ··· 363 363 static __attribute__((unused)) 364 364 pid_t sys_vfork(void) 365 365 { 366 - #if defined(__NR_vfork) 366 + #if defined(__NR_clone) 367 + /* See the note in sys_fork(). */ 368 + return my_syscall5(__NR_clone, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0, 0); 369 + #elif defined(__NR_vfork) 367 370 return my_syscall0(__NR_vfork); 368 - #else 369 - /* 370 - * clone() could be used but has different argument orders per 371 - * architecture. 372 - */ 373 - struct clone_args args = { 374 - .flags = CLONE_VM | CLONE_VFORK, 375 - .exit_signal = SIGCHLD, 376 - }; 377 - 378 - return my_syscall2(__NR_clone3, &args, sizeof(args)); 379 371 #endif 380 372 } 381 373 #endif
+33
tools/include/nolibc/sys/ptrace.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + /* 3 + * ptrace for NOLIBC 4 + * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu> 5 + * Copyright (C) 2025 Intel Corporation 6 + */ 7 + 8 + /* make sure to include all global symbols */ 9 + #include "../nolibc.h" 10 + 11 + #ifndef _NOLIBC_SYS_PTRACE_H 12 + #define _NOLIBC_SYS_PTRACE_H 13 + 14 + #include "../sys.h" 15 + 16 + #include <linux/ptrace.h> 17 + 18 + /* 19 + * long ptrace(int op, pid_t pid, void *addr, void *data); 20 + */ 21 + static __attribute__((unused)) 22 + long sys_ptrace(int op, pid_t pid, void *addr, void *data) 23 + { 24 + return my_syscall4(__NR_ptrace, op, pid, addr, data); 25 + } 26 + 27 + static __attribute__((unused)) 28 + ssize_t ptrace(int op, pid_t pid, void *addr, void *data) 29 + { 30 + return __sysret(sys_ptrace(op, pid, addr, data)); 31 + } 32 + 33 + #endif /* _NOLIBC_SYS_PTRACE_H */
+10 -21
tools/include/nolibc/sys/select.h
··· 63 63 static __attribute__((unused)) 64 64 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 65 65 { 66 - #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 67 - struct sel_arg_struct { 68 - unsigned long n; 69 - fd_set *r, *w, *e; 70 - struct timeval *t; 71 - } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 72 - return my_syscall1(__NR_select, &arg); 73 - #elif defined(__NR__newselect) 74 - return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 75 - #elif defined(__NR_select) 76 - return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); 77 - #elif defined(__NR_pselect6) 78 - struct timespec t; 79 - 80 - if (timeout) { 81 - t.tv_sec = timeout->tv_sec; 82 - t.tv_nsec = timeout->tv_usec * 1000; 83 - } 84 - return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 85 - #else 66 + #if defined(__NR_pselect6_time64) 86 67 struct __kernel_timespec t; 87 68 88 69 if (timeout) { 89 70 t.tv_sec = timeout->tv_sec; 90 - t.tv_nsec = timeout->tv_usec * 1000; 71 + t.tv_nsec = (uint32_t)timeout->tv_usec * 1000; 91 72 } 92 73 return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 74 + #else 75 + struct __kernel_old_timespec t; 76 + 77 + if (timeout) { 78 + t.tv_sec = timeout->tv_sec; 79 + t.tv_nsec = (uint32_t)timeout->tv_usec * 1000; 80 + } 81 + return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 93 82 #endif 94 83 } 95 84
+1 -5
tools/include/nolibc/sys/time.h
··· 22 22 static __attribute__((unused)) 23 23 int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 24 24 { 25 - #ifdef __NR_gettimeofday 26 - return my_syscall2(__NR_gettimeofday, tv, tz); 27 - #else 28 25 (void) tz; /* Non-NULL tz is undefined behaviour */ 29 26 30 27 struct timespec tp; ··· 30 33 ret = sys_clock_gettime(CLOCK_REALTIME, &tp); 31 34 if (!ret && tv) { 32 35 tv->tv_sec = tp.tv_sec; 33 - tv->tv_usec = tp.tv_nsec / 1000; 36 + tv->tv_usec = (uint32_t)tp.tv_nsec / 1000; 34 37 } 35 38 36 39 return ret; 37 - #endif 38 40 } 39 41 40 42 static __attribute__((unused))
+10 -22
tools/include/nolibc/sys/timerfd.h
··· 32 32 static __attribute__((unused)) 33 33 int sys_timerfd_gettime(int fd, struct itimerspec *curr_value) 34 34 { 35 - #if defined(__NR_timerfd_gettime) 36 - return my_syscall2(__NR_timerfd_gettime, fd, curr_value); 35 + #if defined(__NR_timerfd_gettime64) 36 + __nolibc_assert_time64_type(curr_value->it_value.tv_sec); 37 + return my_syscall2(__NR_timerfd_gettime64, fd, curr_value); 37 38 #else 38 - struct __kernel_itimerspec kcurr_value; 39 - int ret; 40 - 41 - ret = my_syscall2(__NR_timerfd_gettime64, fd, &kcurr_value); 42 - __nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval); 43 - __nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value); 44 - return ret; 39 + __nolibc_assert_native_time64(); 40 + return my_syscall2(__NR_timerfd_gettime, fd, curr_value); 45 41 #endif 46 42 } 47 43 ··· 52 56 int sys_timerfd_settime(int fd, int flags, 53 57 const struct itimerspec *new_value, struct itimerspec *old_value) 54 58 { 55 - #if defined(__NR_timerfd_settime) 56 - return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value); 59 + #if defined(__NR_timerfd_settime64) 60 + __nolibc_assert_time64_type(new_value->it_value.tv_sec); 61 + return my_syscall4(__NR_timerfd_settime64, fd, flags, new_value, old_value); 57 62 #else 58 - struct __kernel_itimerspec knew_value, kold_value; 59 - int ret; 60 - 61 - __nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value); 62 - __nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval); 63 - ret = my_syscall4(__NR_timerfd_settime64, fd, flags, &knew_value, &kold_value); 64 - if (old_value) { 65 - __nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval); 66 - __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value); 67 - } 68 - return ret; 63 + __nolibc_assert_native_time64(); 64 + return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value); 69 65 #endif 70 66 } 71 67
+34 -68
tools/include/nolibc/time.h
··· 18 18 #include <linux/signal.h> 19 19 #include <linux/time.h> 20 20 21 - static __inline__ 22 - void __nolibc_timespec_user_to_kernel(const struct timespec *ts, struct __kernel_timespec *kts) 23 - { 24 - kts->tv_sec = ts->tv_sec; 25 - kts->tv_nsec = ts->tv_nsec; 26 - } 21 + #define __nolibc_assert_time64_type(t) \ 22 + __nolibc_static_assert(sizeof(t) == 8) 27 23 28 - static __inline__ 29 - void __nolibc_timespec_kernel_to_user(const struct __kernel_timespec *kts, struct timespec *ts) 30 - { 31 - ts->tv_sec = kts->tv_sec; 32 - ts->tv_nsec = kts->tv_nsec; 33 - } 24 + #define __nolibc_assert_native_time64() \ 25 + __nolibc_assert_time64_type(__kernel_old_time_t) 34 26 35 27 /* 36 28 * int clock_getres(clockid_t clockid, struct timespec *res); ··· 35 43 static __attribute__((unused)) 36 44 int sys_clock_getres(clockid_t clockid, struct timespec *res) 37 45 { 38 - #if defined(__NR_clock_getres) 39 - return my_syscall2(__NR_clock_getres, clockid, res); 46 + #if defined(__NR_clock_getres_time64) 47 + __nolibc_assert_time64_type(res->tv_sec); 48 + return my_syscall2(__NR_clock_getres_time64, clockid, res); 40 49 #else 41 - struct __kernel_timespec kres; 42 - int ret; 43 - 44 - ret = my_syscall2(__NR_clock_getres_time64, clockid, &kres); 45 - if (res) 46 - __nolibc_timespec_kernel_to_user(&kres, res); 47 - return ret; 50 + __nolibc_assert_native_time64(); 51 + return my_syscall2(__NR_clock_getres, clockid, res); 48 52 #endif 49 53 } 50 54 ··· 53 65 static __attribute__((unused)) 54 66 int sys_clock_gettime(clockid_t clockid, struct timespec *tp) 55 67 { 56 - #if defined(__NR_clock_gettime) 57 - return my_syscall2(__NR_clock_gettime, clockid, tp); 68 + #if defined(__NR_clock_gettime64) 69 + __nolibc_assert_time64_type(tp->tv_sec); 70 + return my_syscall2(__NR_clock_gettime64, clockid, tp); 58 71 #else 59 - struct __kernel_timespec ktp; 60 - int ret; 61 - 62 - ret = my_syscall2(__NR_clock_gettime64, clockid, &ktp); 63 - if (tp) 64 - __nolibc_timespec_kernel_to_user(&ktp, tp); 65 - return ret; 72 + __nolibc_assert_native_time64(); 73 + return my_syscall2(__NR_clock_gettime, clockid, tp); 66 74 #endif 67 75 } 68 76 ··· 71 87 static __attribute__((unused)) 72 88 int sys_clock_settime(clockid_t clockid, struct timespec *tp) 73 89 { 74 - #if defined(__NR_clock_settime) 75 - return my_syscall2(__NR_clock_settime, clockid, tp); 90 + #if defined(__NR_clock_settime64) 91 + __nolibc_assert_time64_type(tp->tv_sec); 92 + return my_syscall2(__NR_clock_settime64, clockid, tp); 76 93 #else 77 - struct __kernel_timespec ktp; 78 - 79 - __nolibc_timespec_user_to_kernel(tp, &ktp); 80 - return my_syscall2(__NR_clock_settime64, clockid, &ktp); 94 + __nolibc_assert_native_time64(); 95 + return my_syscall2(__NR_clock_settime, clockid, tp); 81 96 #endif 82 97 } 83 98 ··· 90 107 int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, 91 108 struct timespec *rmtp) 92 109 { 93 - #if defined(__NR_clock_nanosleep) 94 - return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp); 110 + #if defined(__NR_clock_nanosleep_time64) 111 + __nolibc_assert_time64_type(rqtp->tv_sec); 112 + return my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, rqtp, rmtp); 95 113 #else 96 - struct __kernel_timespec krqtp, krmtp; 97 - int ret; 98 - 99 - __nolibc_timespec_user_to_kernel(rqtp, &krqtp); 100 - ret = my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, &krqtp, &krmtp); 101 - if (rmtp) 102 - __nolibc_timespec_kernel_to_user(&krmtp, rmtp); 103 - return ret; 114 + __nolibc_assert_native_time64(); 115 + return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp); 104 116 #endif 105 117 } 106 118 ··· 167 189 static __attribute__((unused)) 168 190 int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value) 169 191 { 170 - #if defined(__NR_timer_gettime) 171 - return my_syscall2(__NR_timer_gettime, timerid, curr_value); 192 + #if defined(__NR_timer_gettime64) 193 + __nolibc_assert_time64_type(curr_value->it_value.tv_sec); 194 + return my_syscall2(__NR_timer_gettime64, timerid, curr_value); 172 195 #else 173 - struct __kernel_itimerspec kcurr_value; 174 - int ret; 175 - 176 - ret = my_syscall2(__NR_timer_gettime64, timerid, &kcurr_value); 177 - __nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval); 178 - __nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value); 179 - return ret; 196 + __nolibc_assert_native_time64(); 197 + return my_syscall2(__NR_timer_gettime, timerid, curr_value); 180 198 #endif 181 199 } 182 200 ··· 186 212 int sys_timer_settime(timer_t timerid, int flags, 187 213 const struct itimerspec *new_value, struct itimerspec *old_value) 188 214 { 189 - #if defined(__NR_timer_settime) 190 - return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value); 215 + #if defined(__NR_timer_settime64) 216 + __nolibc_assert_time64_type(new_value->it_value.tv_sec); 217 + return my_syscall4(__NR_timer_settime64, timerid, flags, new_value, old_value); 191 218 #else 192 - struct __kernel_itimerspec knew_value, kold_value; 193 - int ret; 194 - 195 - __nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value); 196 - __nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval); 197 - ret = my_syscall4(__NR_timer_settime64, timerid, flags, &knew_value, &kold_value); 198 - if (old_value) { 199 - __nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval); 200 - __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value); 201 - } 202 - return ret; 219 + __nolibc_assert_native_time64(); 220 + return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value); 203 221 #endif 204 222 } 205 223
+16 -1
tools/include/nolibc/types.h
··· 13 13 #include "std.h" 14 14 #include <linux/mman.h> 15 15 #include <linux/stat.h> 16 - #include <linux/time.h> 16 + #include <linux/time_types.h> 17 17 #include <linux/wait.h> 18 18 19 + struct timespec { 20 + time_t tv_sec; 21 + int64_t tv_nsec; 22 + }; 23 + #define _STRUCT_TIMESPEC 24 + 25 + /* Never use with system calls */ 26 + struct timeval { 27 + time_t tv_sec; 28 + int64_t tv_usec; 29 + }; 30 + 31 + #define timeval __nolibc_kernel_timeval 32 + #include <linux/time.h> 33 + #undef timeval 19 34 20 35 /* Only the generic macros and types may be defined here. The arch-specific 21 36 * ones such as the O_RDONLY and related macros used by fcntl() and open()
+7 -7
tools/testing/selftests/nolibc/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 - TEST_GEN_PROGS := nolibc-test 3 + TEST_GEN_PROGS := nolibc-test libc-test 4 4 5 5 include ../lib.mk 6 6 include $(top_srcdir)/scripts/Makefile.compiler ··· 9 9 10 10 include Makefile.include 11 11 12 - CFLAGS = -nostdlib -nostdinc -static \ 12 + $(OUTPUT)/nolibc-test: CFLAGS = -nostdlib -nostdinc -static \ 13 13 -isystem $(top_srcdir)/tools/include/nolibc -isystem $(top_srcdir)/usr/include \ 14 14 $(CFLAGS_NOLIBC_TEST) 15 - 16 - ifeq ($(LLVM),) 17 - LDLIBS := -lgcc 18 - endif 19 - 15 + $(OUTPUT)/nolibc-test: LDLIBS = $(if $(LLVM),,-lgcc) 20 16 $(OUTPUT)/nolibc-test: nolibc-test.c nolibc-test-linkage.c | headers 17 + 18 + $(OUTPUT)/libc-test: nolibc-test.c nolibc-test-linkage.c 19 + $(call msg,CC,,$@) 20 + $(Q)$(LINK.c) $^ -o $@ 21 21 22 22 help: 23 23 @echo "For the custom nolibc testsuite use '$(MAKE) -f Makefile.nolibc'; available targets:"
+1 -7
tools/testing/selftests/nolibc/Makefile.nolibc
··· 226 226 CFLAGS_mips64le = -EL -mabi=64 -march=mips64r6 227 227 CFLAGS_mips64be = -EB -mabi=64 -march=mips64r2 228 228 CFLAGS_loongarch = $(if $(LLVM),-fuse-ld=lld) 229 - CFLAGS_sparc32 = $(call cc-option,-m32) 229 + CFLAGS_sparc32 = $(call cc-option,-m32) -mcpu=v8 230 230 CFLAGS_sh4 = -ml -m4 231 231 ifeq ($(origin XARCH),command line) 232 232 CFLAGS_XARCH = $(CFLAGS_$(XARCH)) ··· 302 302 $(Q)$(MAKE) -C $(srctree)/tools/include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone headers_check 303 303 $(Q)mv sysroot/sysroot sysroot/$(ARCH) 304 304 305 - ifneq ($(NOLIBC_SYSROOT),0) 306 305 nolibc-test: nolibc-test.c nolibc-test-linkage.c sysroot/$(ARCH)/include 307 306 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ 308 307 -nostdlib -nostdinc -static -Isysroot/$(ARCH)/include nolibc-test.c nolibc-test-linkage.c $(LIBGCC) 309 - else 310 - nolibc-test: nolibc-test.c nolibc-test-linkage.c 311 - $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ 312 - -nostdlib -static -include $(srctree)/tools/include/nolibc/nolibc.h nolibc-test.c nolibc-test-linkage.c $(LIBGCC) 313 - endif 314 308 315 309 libc-test: nolibc-test.c nolibc-test-linkage.c 316 310 $(QUIET_CC)$(HOSTCC) -o $@ nolibc-test.c nolibc-test-linkage.c
+85 -1
tools/testing/selftests/nolibc/nolibc-test.c
··· 17 17 #include <sys/mman.h> 18 18 #include <sys/mount.h> 19 19 #include <sys/prctl.h> 20 + #include <sys/ptrace.h> 20 21 #include <sys/random.h> 21 22 #include <sys/reboot.h> 22 23 #include <sys/resource.h> ··· 878 877 return 0; 879 878 } 880 879 880 + int test_file_stream_wsr(void) 881 + { 882 + const char dataout[] = "foo"; 883 + const size_t datasz = sizeof(dataout); 884 + char datain[datasz]; 885 + int fd, r; 886 + FILE *f; 887 + 888 + fd = open("/tmp", O_TMPFILE | O_RDWR, 0644); 889 + if (fd == -1) 890 + return -1; 891 + 892 + f = fdopen(fd, "w+"); 893 + if (!f) 894 + return -1; 895 + 896 + errno = 0; 897 + r = fwrite(dataout, 1, datasz, f); 898 + if (r != datasz) 899 + return -1; 900 + 901 + /* Attempt to read from the file without rewinding, 902 + * we should read 0 items. 903 + */ 904 + r = fread(datain, 1, datasz, f); 905 + if (r) 906 + return -1; 907 + 908 + /* Rewind the file to the start */ 909 + r = fseek(f, 0, SEEK_SET); 910 + if (r) 911 + return -1; 912 + 913 + /* Attempt to read back more than was written to 914 + * make sure we handle short reads properly. 915 + * fread() should return the number of complete items. 916 + */ 917 + r = fread(datain, 1, datasz + 1, f); 918 + if (r != datasz) 919 + return -1; 920 + 921 + /* Data we read should match the data we just wrote */ 922 + if (memcmp(datain, dataout, datasz) != 0) 923 + return -1; 924 + 925 + r = fclose(f); 926 + if (r) 927 + return -1; 928 + 929 + return 0; 930 + } 931 + 881 932 enum fork_type { 882 933 FORK_STANDARD, 883 934 FORK_VFORK, ··· 1404 1351 CASE_TEST(fchdir_stdin); EXPECT_SYSER(1, fchdir(STDIN_FILENO), -1, ENOTDIR); break; 1405 1352 CASE_TEST(fchdir_badfd); EXPECT_SYSER(1, fchdir(-1), -1, EBADF); break; 1406 1353 CASE_TEST(file_stream); EXPECT_SYSZR(1, test_file_stream()); break; 1354 + CASE_TEST(file_stream_wsr); EXPECT_SYSZR(1, test_file_stream_wsr()); break; 1407 1355 CASE_TEST(fork); EXPECT_SYSZR(1, test_fork(FORK_STANDARD)); break; 1408 1356 CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/"), -1); break; 1409 1357 CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break; ··· 1457 1403 CASE_TEST(write_badf); EXPECT_SYSER(1, write(-1, &tmp, 1), -1, EBADF); break; 1458 1404 CASE_TEST(write_zero); EXPECT_SYSZR(1, write(1, &tmp, 0)); break; 1459 1405 CASE_TEST(readv_badf); EXPECT_SYSER(1, readv(-1, &iov_one, 1), -1, EBADF); break; 1460 - CASE_TEST(readv_zero); EXPECT_SYSZR(1, readv(1, NULL, 0)); break; 1406 + CASE_TEST(readv_zero); EXPECT_SYSZR(1, readv(0, NULL, 0)); break; 1461 1407 CASE_TEST(writev_badf); EXPECT_SYSER(1, writev(-1, &iov_one, 1), -1, EBADF); break; 1462 1408 CASE_TEST(writev_zero); EXPECT_SYSZR(1, writev(1, NULL, 0)); break; 1409 + CASE_TEST(ptrace); EXPECT_SYSER(1, ptrace(PTRACE_CONT, getpid(), NULL, NULL), -1, ESRCH); break; 1463 1410 CASE_TEST(syscall_noargs); EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break; 1464 1411 CASE_TEST(syscall_args); EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break; 1465 1412 CASE_TEST(namespace); EXPECT_SYSZR(euid0 && proc, test_namespace()); break; ··· 1479 1424 1480 1425 if (difftime(100., 200.) != -100.) 1481 1426 return 1; 1427 + 1428 + return 0; 1429 + } 1430 + 1431 + int test_time_types(void) 1432 + { 1433 + #ifdef NOLIBC 1434 + struct __kernel_timespec kts; 1435 + struct timespec ts; 1436 + 1437 + if (!__builtin_types_compatible_p(time_t, __kernel_time64_t)) 1438 + return 1; 1439 + 1440 + if (sizeof(ts) != sizeof(kts)) 1441 + return 1; 1442 + 1443 + if (!__builtin_types_compatible_p(__typeof__(ts.tv_sec), __typeof__(kts.tv_sec))) 1444 + return 1; 1445 + 1446 + if (!__builtin_types_compatible_p(__typeof__(ts.tv_nsec), __typeof__(kts.tv_nsec))) 1447 + return 1; 1448 + 1449 + if (offsetof(__typeof__(ts), tv_sec) != offsetof(__typeof__(kts), tv_sec)) 1450 + return 1; 1451 + 1452 + if (offsetof(__typeof__(ts), tv_nsec) != offsetof(__typeof__(kts), tv_nsec)) 1453 + return 1; 1454 + #endif /* NOLIBC */ 1482 1455 1483 1456 return 0; 1484 1457 } ··· 1636 1553 CASE_TEST(difftime); EXPECT_ZR(1, test_difftime()); break; 1637 1554 CASE_TEST(memchr_foobar6_o); EXPECT_STREQ(1, memchr("foobar", 'o', 6), "oobar"); break; 1638 1555 CASE_TEST(memchr_foobar3_b); EXPECT_STRZR(1, memchr("foobar", 'b', 3)); break; 1556 + CASE_TEST(time_types); EXPECT_ZR(is_nolibc, test_time_types()); break; 1639 1557 1640 1558 case __LINE__: 1641 1559 return ret; /* must be last */