nolibc changes for v6.18

Only contains small bugfixes and cleanups.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQTg4lxklFHAidmUs57B+h1jyw5bOAUCaNmibgAKCRDB+h1jyw5b
 OP8VAQDzrMGp77iFvfAFRsFuGYXLpWgNd8aWzFVMmPz/Kts3yAD/X1RnJsak5l5g
 iiuZTPijrZeyQaO0uX4UV/XVHzxU2Ac=
 =IenX
 -----END PGP SIGNATURE-----

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

Pull nolibc updates from Thomas Weißschuh:
 "Only small bugfixes and cleanups"

* tag 'nolibc-20250928-for-6.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc:
  tools/nolibc: add stdbool.h to nolibc includes
  tools/nolibc: make time_t robust if __kernel_old_time_t is missing in host headers
  selftests/nolibc: remove outdated comment about construct order
  selftests/nolibc: fix EXPECT_NZ macro
  tools/nolibc: drop wait4() support
  kselftest/arm64: tpidr2: Switch to waitpid() over wait4()
  tools/nolibc: fold llseek fallback into lseek()
  tools/nolibc: remove __nolibc_enosys() fallback from fork functions
  tools/nolibc: remove __nolibc_enosys() fallback from dup2()
  tools/nolibc: remove __nolibc_enosys() fallback from *at() functions
  tools/nolibc: remove __nolibc_enosys() fallback from time64-related functions
  tools/nolibc: use tabs instead of spaces for indentation
  tools/nolibc: avoid error in dup2() if old fd equals new fd
  selftests/nolibc: always compile the kernel with GCC
  selftests/nolibc: don't pass CC to toplevel Makefile
  selftests/nolibc: deduplicate invocations of toplevel Makefile
  selftests/nolibc: be more specific about variables affecting nolibc-test
  tools/nolibc: fix error return value of clock_nanosleep()
pull/1354/merge
Linus Torvalds 2025-09-30 19:18:17 -07:00
commit 50c19e20ed
12 changed files with 69 additions and 116 deletions

View File

@ -116,6 +116,7 @@
#include "sched.h"
#include "signal.h"
#include "unistd.h"
#include "stdbool.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

View File

@ -39,10 +39,8 @@ int sys_poll(struct pollfd *fds, int nfds, int timeout)
t.tv_nsec = (timeout % 1000) * 1000000;
}
return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
#elif defined(__NR_poll)
return my_syscall3(__NR_poll, fds, nfds, timeout);
#else
return __nolibc_enosys(__func__, fds, nfds, timeout);
return my_syscall3(__NR_poll, fds, nfds, timeout);
#endif
}

View File

@ -29,6 +29,6 @@ typedef unsigned long nlink_t;
typedef signed long off_t;
typedef signed long blksize_t;
typedef signed long blkcnt_t;
typedef __kernel_old_time_t time_t;
typedef __kernel_time_t time_t;
#endif /* _NOLIBC_STD_H */

View File

@ -142,10 +142,8 @@ int sys_chmod(const char *path, mode_t mode)
{
#if defined(__NR_fchmodat)
return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0);
#elif defined(__NR_chmod)
return my_syscall2(__NR_chmod, path, mode);
#else
return __nolibc_enosys(__func__, path, mode);
return my_syscall2(__NR_chmod, path, mode);
#endif
}
@ -165,10 +163,8 @@ int sys_chown(const char *path, uid_t owner, gid_t group)
{
#if defined(__NR_fchownat)
return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0);
#elif defined(__NR_chown)
return my_syscall3(__NR_chown, path, owner, group);
#else
return __nolibc_enosys(__func__, path, owner, group);
return my_syscall3(__NR_chown, path, owner, group);
#endif
}
@ -238,11 +234,22 @@ static __attribute__((unused))
int sys_dup2(int old, int new)
{
#if defined(__NR_dup3)
return my_syscall3(__NR_dup3, old, new, 0);
#elif defined(__NR_dup2)
return my_syscall2(__NR_dup2, old, new);
int ret, nr_fcntl;
#ifdef __NR_fcntl64
nr_fcntl = __NR_fcntl64;
#else
return __nolibc_enosys(__func__, old, new);
nr_fcntl = __NR_fcntl;
#endif
if (old == new) {
ret = my_syscall2(nr_fcntl, old, F_GETFD);
return ret < 0 ? ret : old;
}
return my_syscall3(__NR_dup3, old, new, 0);
#else
return my_syscall2(__NR_dup2, old, new);
#endif
}
@ -327,10 +334,8 @@ pid_t sys_fork(void)
* will not use the rest with no other flag.
*/
return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0);
#elif defined(__NR_fork)
return my_syscall0(__NR_fork);
#else
return __nolibc_enosys(__func__);
return my_syscall0(__NR_fork);
#endif
}
#endif
@ -347,7 +352,7 @@ pid_t sys_vfork(void)
{
#if defined(__NR_vfork)
return my_syscall0(__NR_vfork);
#elif defined(__NR_clone3)
#else
/*
* clone() could be used but has different argument orders per
* architecture.
@ -358,8 +363,6 @@ pid_t sys_vfork(void)
};
return my_syscall2(__NR_clone3, &args, sizeof(args));
#else
return __nolibc_enosys(__func__);
#endif
}
#endif
@ -569,10 +572,8 @@ int sys_link(const char *old, const char *new)
{
#if defined(__NR_linkat)
return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0);
#elif defined(__NR_link)
return my_syscall2(__NR_link, old, new);
#else
return __nolibc_enosys(__func__, old, new);
return my_syscall2(__NR_link, old, new);
#endif
}
@ -593,41 +594,27 @@ off_t sys_lseek(int fd, off_t offset, int whence)
#if defined(__NR_lseek)
return my_syscall3(__NR_lseek, fd, offset, whence);
#else
return __nolibc_enosys(__func__, fd, offset, whence);
#endif
}
__kernel_loff_t loff = 0;
off_t result;
int ret;
static __attribute__((unused))
int sys_llseek(int fd, unsigned long offset_high, unsigned long offset_low,
__kernel_loff_t *result, int whence)
{
#if defined(__NR_llseek)
return my_syscall5(__NR_llseek, fd, offset_high, offset_low, result, whence);
#else
return __nolibc_enosys(__func__, fd, offset_high, offset_low, result, whence);
/* Only exists on 32bit where nolibc off_t is also 32bit */
ret = my_syscall5(__NR_llseek, fd, 0, offset, &loff, whence);
if (ret < 0)
result = ret;
else if (loff != (off_t)loff)
result = -EOVERFLOW;
else
result = loff;
return result;
#endif
}
static __attribute__((unused))
off_t lseek(int fd, off_t offset, int whence)
{
__kernel_loff_t loff = 0;
off_t result;
int ret;
result = sys_lseek(fd, offset, whence);
if (result == -ENOSYS) {
/* Only exists on 32bit where nolibc off_t is also 32bit */
ret = sys_llseek(fd, 0, offset, &loff, whence);
if (ret < 0)
result = ret;
else if (loff != (off_t)loff)
result = -EOVERFLOW;
else
result = loff;
}
return __sysret(result);
return __sysret(sys_lseek(fd, offset, whence));
}
@ -640,10 +627,8 @@ int sys_mkdir(const char *path, mode_t mode)
{
#if defined(__NR_mkdirat)
return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode);
#elif defined(__NR_mkdir)
return my_syscall2(__NR_mkdir, path, mode);
#else
return __nolibc_enosys(__func__, path, mode);
return my_syscall2(__NR_mkdir, path, mode);
#endif
}
@ -662,10 +647,8 @@ int sys_rmdir(const char *path)
{
#if defined(__NR_rmdir)
return my_syscall1(__NR_rmdir, path);
#elif defined(__NR_unlinkat)
return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR);
#else
return __nolibc_enosys(__func__, path);
return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR);
#endif
}
@ -685,10 +668,8 @@ long sys_mknod(const char *path, mode_t mode, dev_t dev)
{
#if defined(__NR_mknodat)
return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev);
#elif defined(__NR_mknod)
return my_syscall3(__NR_mknod, path, mode, dev);
#else
return __nolibc_enosys(__func__, path, mode, dev);
return my_syscall3(__NR_mknod, path, mode, dev);
#endif
}
@ -801,7 +782,7 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva
t.tv_nsec = timeout->tv_usec * 1000;
}
return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#elif defined(__NR_pselect6_time64)
#else
struct __kernel_timespec t;
if (timeout) {
@ -809,8 +790,6 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva
t.tv_nsec = timeout->tv_usec * 1000;
}
return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#else
return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout);
#endif
}
@ -874,10 +853,8 @@ int sys_symlink(const char *old, const char *new)
{
#if defined(__NR_symlinkat)
return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new);
#elif defined(__NR_symlink)
return my_syscall2(__NR_symlink, old, new);
#else
return __nolibc_enosys(__func__, old, new);
return my_syscall2(__NR_symlink, old, new);
#endif
}
@ -931,10 +908,8 @@ int sys_unlink(const char *path)
{
#if defined(__NR_unlinkat)
return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0);
#elif defined(__NR_unlink)
return my_syscall1(__NR_unlink, path);
#else
return __nolibc_enosys(__func__, path);
return my_syscall1(__NR_unlink, path);
#endif
}

View File

@ -22,13 +22,13 @@
static __attribute__((unused))
ssize_t sys_getrandom(void *buf, size_t buflen, unsigned int flags)
{
return my_syscall3(__NR_getrandom, buf, buflen, flags);
return my_syscall3(__NR_getrandom, buf, buflen, flags);
}
static __attribute__((unused))
ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
{
return __sysret(sys_getrandom(buf, buflen, flags));
return __sysret(sys_getrandom(buf, buflen, flags));
}
#endif /* _NOLIBC_SYS_RANDOM_H */

View File

@ -34,7 +34,7 @@ int sys_timerfd_gettime(int fd, struct itimerspec *curr_value)
{
#if defined(__NR_timerfd_gettime)
return my_syscall2(__NR_timerfd_gettime, fd, curr_value);
#elif defined(__NR_timerfd_gettime64)
#else
struct __kernel_itimerspec kcurr_value;
int ret;
@ -42,8 +42,6 @@ int sys_timerfd_gettime(int fd, struct itimerspec *curr_value)
__nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
__nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
return ret;
#else
return __nolibc_enosys(__func__, fd, curr_value);
#endif
}
@ -60,7 +58,7 @@ int sys_timerfd_settime(int fd, int flags,
{
#if defined(__NR_timerfd_settime)
return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
#elif defined(__NR_timerfd_settime64)
#else
struct __kernel_itimerspec knew_value, kold_value;
int ret;
@ -72,8 +70,6 @@ int sys_timerfd_settime(int fd, int flags,
__nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
}
return ret;
#else
return __nolibc_enosys(__func__, fd, flags, new_value, old_value);
#endif
}

View File

@ -16,27 +16,10 @@
/*
* pid_t wait(int *status);
* pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
* pid_t waitpid(pid_t pid, int *status, int options);
* int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
*/
static __attribute__((unused))
pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
{
#ifdef __NR_wait4
return my_syscall4(__NR_wait4, pid, status, options, rusage);
#else
return __nolibc_enosys(__func__, pid, status, options, rusage);
#endif
}
static __attribute__((unused))
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
{
return __sysret(sys_wait4(pid, status, options, rusage));
}
static __attribute__((unused))
int sys_waitid(int which, pid_t pid, siginfo_t *infop, int options, struct rusage *rusage)
{

View File

@ -45,7 +45,7 @@ int sys_clock_getres(clockid_t clockid, struct timespec *res)
{
#if defined(__NR_clock_getres)
return my_syscall2(__NR_clock_getres, clockid, res);
#elif defined(__NR_clock_getres_time64)
#else
struct __kernel_timespec kres;
int ret;
@ -53,8 +53,6 @@ int sys_clock_getres(clockid_t clockid, struct timespec *res)
if (res)
__nolibc_timespec_kernel_to_user(&kres, res);
return ret;
#else
return __nolibc_enosys(__func__, clockid, res);
#endif
}
@ -69,7 +67,7 @@ int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
{
#if defined(__NR_clock_gettime)
return my_syscall2(__NR_clock_gettime, clockid, tp);
#elif defined(__NR_clock_gettime64)
#else
struct __kernel_timespec ktp;
int ret;
@ -77,8 +75,6 @@ int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
if (tp)
__nolibc_timespec_kernel_to_user(&ktp, tp);
return ret;
#else
return __nolibc_enosys(__func__, clockid, tp);
#endif
}
@ -133,7 +129,8 @@ static __attribute__((unused))
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
struct timespec *rmtp)
{
return __sysret(sys_clock_nanosleep(clockid, flags, rqtp, rmtp));
/* Directly return a positive error number */
return -sys_clock_nanosleep(clockid, flags, rqtp, rmtp);
}
static __inline__
@ -145,7 +142,7 @@ double difftime(time_t time1, time_t time2)
static __inline__
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
return clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rmtp);
return __sysret(sys_clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rmtp));
}

View File

@ -33,7 +33,7 @@
static __attribute__((unused))
int sys_faccessat(int fd, const char *path, int amode, int flag)
{
return my_syscall4(__NR_faccessat, fd, path, amode, flag);
return my_syscall4(__NR_faccessat, fd, path, amode, flag);
}
static __attribute__((unused))

View File

@ -182,16 +182,16 @@ static int write_clone_read(void)
}
for (;;) {
waiting = wait4(ret, &status, __WCLONE, NULL);
waiting = waitpid(ret, &status, __WCLONE);
if (waiting < 0) {
if (errno == EINTR)
continue;
ksft_print_msg("wait4() failed: %d\n", errno);
ksft_print_msg("waitpid() failed: %d\n", errno);
return 0;
}
if (waiting != ret) {
ksft_print_msg("wait4() returned wrong PID %d\n",
ksft_print_msg("waitpid() returned wrong PID %d\n",
waiting);
return 0;
}

View File

@ -262,19 +262,22 @@ REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++
if (f || !p || !done) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
printf("\nSee all results in %s\n", ARGV[1]); }'
# Execute the toplevel kernel Makefile
KBUILD_MAKE = $(MAKE) -C $(srctree) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) LLVM=
help:
@echo "Supported targets under selftests/nolibc:"
@echo " all call the \"run\" target below"
@echo " help this help"
@echo " sysroot create the nolibc sysroot here (uses \$$ARCH)"
@echo " nolibc-test build the executable (uses \$$CC and \$$CROSS_COMPILE)"
@echo " nolibc-test build the executable (uses \$$CC or \$$CROSS_COMPILE)"
@echo " libc-test build an executable using the compiler's default libc instead"
@echo " run-user runs the executable under QEMU (uses \$$XARCH, \$$TEST)"
@echo " initramfs.cpio prepare the initramfs archive with nolibc-test"
@echo " initramfs prepare the initramfs tree with nolibc-test"
@echo " defconfig create a fresh new default config (uses \$$XARCH)"
@echo " kernel (re)build the kernel (uses \$$XARCH)"
@echo " kernel-standalone (re)build the kernel with the initramfs (uses \$$XARCH)"
@echo " kernel (re)build the kernel (uses \$$XARCH, \$$CROSS_COMPILE)"
@echo " kernel-standalone (re)build the kernel with the initramfs (uses \$$XARCH, \$$CROSS_COMPILE)"
@echo " run runs the kernel in QEMU after building it (uses \$$XARCH, \$$TEST)"
@echo " rerun runs a previously prebuilt kernel in QEMU (uses \$$XARCH, \$$TEST)"
@echo " clean clean the sysroot, initramfs, build and output files"
@ -340,17 +343,17 @@ initramfs: nolibc-test
$(Q)cp nolibc-test initramfs/init
defconfig:
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(DEFCONFIG)
$(Q)$(KBUILD_MAKE) $(DEFCONFIG)
$(Q)if [ -n "$(EXTRACONFIG)" ]; then \
$(srctree)/scripts/config --file $(objtree)/.config $(EXTRACONFIG); \
$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) olddefconfig < /dev/null; \
$(KBUILD_MAKE) olddefconfig < /dev/null; \
fi
kernel:
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) < /dev/null
$(Q)$(KBUILD_MAKE) $(IMAGE_NAME) < /dev/null
kernel-standalone: initramfs
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs < /dev/null
$(Q)$(KBUILD_MAKE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs < /dev/null
# run the tests after building the kernel
run: kernel initramfs.cpio

View File

@ -196,8 +196,8 @@ int expect_zr(int expr, int llen)
}
#define EXPECT_NZ(cond, expr, val) \
do { if (!(cond)) result(llen, SKIPPED); else ret += expect_nz(expr, llen; } while (0)
#define EXPECT_NZ(cond, expr) \
do { if (!(cond)) result(llen, SKIPPED); else ret += expect_nz(expr, llen); } while (0)
static __attribute__((unused))
int expect_nz(int expr, int llen)
@ -686,7 +686,6 @@ int expect_strtox(int llen, void *func, const char *input, int base, intmax_t ex
#define CASE_TEST(name) \
case __LINE__: llen += printf("%d %s", test, #name);
/* constructors validate that they are executed in definition order */
__attribute__((constructor))
static void constructor1(void)
{
@ -1334,6 +1333,7 @@ int run_syscall(int min, int max)
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(1, chroot(argv0), -1, ENOTDIR); break;
CASE_TEST(clock_nanosleep); ts.tv_nsec = -1; EXPECT_EQ(1, EINVAL, clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL)); break;
CASE_TEST(close_m1); EXPECT_SYSER(1, close(-1), -1, EBADF); break;
CASE_TEST(close_dup); EXPECT_SYSZR(1, close(dup(0))); break;
CASE_TEST(dup_0); tmp = dup(0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break;