Fixes for nolibc for v6.2

This series addresses the following bugs:
 
 o	The fd_set structure was incorrectly defined as arrays of u32
 	instead of long, which breaks BE64. Fix courtesy of Sven Schnelle.
 
 o	S_ISxxx macros were incorrectly testing the bits after applying
 	them instead of bitwise ANDing S_FMT with the value. Fix from
 	Warner Losh.
 
 o	The mips code was randomly broken due to an unprotected
 	"noreorder" directive in the _start code that could prevent the
 	assembler from filling delayed slots.  This in turn resulted
 	in random other instructions being placed into those slots.
 	Fix courtesy of Willy Tarreau.
 
 o	The current nolibc header layout refrains from including files
 	that are not explicitly included by the code using nolibc.
 	Unfortunately, this causes build failures when such files
 	contain definitions that are used (for example) by libgcc.
 	Example definitions include raise() and memset(), which are called
 	by some architectures, but only at certain optimization levels.
 	Fix courtesy of Willy Tarreau.
 
 o	gcc 11.3 in ARM thumb2 mode at -O2 recognized a memset()
 	construction inside the memset() definition.  The compiler
 	replaced this construction with a call to... memset().	Userland
 	cannot be forced to build with -ffreestanding, so an empty asm()
 	statement was introduced into the loop the loop in order to
 	prevent the compiler from making this unproductive transformation.
 	Fix courtesy of Willy Tarreau.
 
 o	Most of the O_* macros were wrong on RISCV because their
 	octal values were coded as hexadecimal.  This resulted in the
 	getdents64() selftest failing.	Fix courtesy of Willy Tarreau.
 
 The series was tested on x86_64, i386, armv5, armv7, thumb1, thumb2,
 mips and riscv, all at -O0, -Os and -O3.
 -----BEGIN PGP SIGNATURE-----
 
 iQJHBAABCgAxFiEEbK7UrM+RBIrCoViJnr8S83LZ+4wFAmO8ZPsTHHBhdWxtY2tA
 a2VybmVsLm9yZwAKCRCevxLzctn7jDqUD/4zymVYzv0Pfbr3gHiZAgWCr+FwHz46
 SGK4KVvSPn3L0MMT0JW+Ws6tB/WKwOFzK4dtvhU+z1ClLZEhLgQVVjo9lwLvUorj
 QvxubMnRLJCZjyvgCOJ2mbJCGLMSoOceSrNgl4xEeQ1gu6wrmjLu8erDJvBCyTMX
 4Io7tv1ddO3xJuptrJzB1jZpFl/OvJkrSuB3fHAtCcc/YcXy59imp690lawyWfLL
 ryiwVgep0XRPLTiEm+Jd0iMsTFJaJEEvkt2aQ9yd6C92z27/+erJ7SsrWcXHZAjD
 Ck7h4EX2SpJliRFW4QeGdC5/16/7EIGs2WUTuGnwB4uIleD4vGwwvNJkclhKi2au
 vKfcy5/soFuaWfOOUthfHAA0OX4DXHGFWP9BhEljGTG0F9bbGqqXnsZm37qrq2cQ
 Ns2tQ2BXvm6qY1TGsv3usMch8xF3Gy521iO5qMQ1YYMeB8Jw6IZJnT6w0gHSqo8O
 mR8i2zgnsvc3a2KTs45djdN4cu7ARzwwGDXc+ZgEhOsVGp5k93MGoixdYjZkIzCp
 Zoy/p9sr66OTeUXfxVOJvJcnXzAlWTUgWu92+tlDDrhu2S+YWRGDqhjUfjnqM+dt
 q7EYj/tVmXsy5B/f/ndmjTUwCxQ7oDM3v72YqGbrUFdA7lHeNSkWY1kjM4PmRJsr
 aZBwnA0Utly0VQ==
 =bR/q
 -----END PGP SIGNATURE-----

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

Pull nolibc fixes from Paul McKenney:

 - The fd_set structure was incorrectly defined as arrays of u32 instead
   of long, which breaks BE64. Fix courtesy of Sven Schnelle.

 - S_ISxxx macros were incorrectly testing the bits after applying them
   instead of bitwise ANDing S_FMT with the value. Fix from Warner Losh.

 - The mips code was randomly broken due to an unprotected "noreorder"
   directive in the _start code that could prevent the assembler from
   filling delayed slots. This in turn resulted in random other
   instructions being placed into those slots. Fix courtesy of Willy
   Tarreau.

 - The current nolibc header layout refrains from including files that
   are not explicitly included by the code using nolibc. Unfortunately,
   this causes build failures when such files contain definitions that
   are used (for example) by libgcc. Example definitions include raise()
   and memset(), which are called by some architectures, but only at
   certain optimization levels. Fix courtesy of Willy Tarreau.

 - gcc 11.3 in ARM thumb2 mode at -O2 recognized a memset() construction
   inside the memset() definition. The compiler replaced this
   construction with a call to... memset(). Userland cannot be forced to
   build with -ffreestanding, so an empty asm() statement was introduced
   into the loop the loop in order to prevent the compiler from making
   this unproductive transformation. Fix courtesy of Willy Tarreau.

 - Most of the O_* macros were wrong on RISCV because their octal values
   were coded as hexadecimal. This resulted in the getdents64() selftest
   failing. Fix courtesy of Willy Tarreau.

This was tested on x86_64, i386, armv5, armv7, thumb1, thumb2, mips and
riscv, all at -O0, -Os and -O3.

* tag 'urgent-nolibc.2023.01.09a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu:
  tools/nolibc: fix the O_* fcntl/open macro definitions for riscv
  tools/nolibc: prevent gcc from making memset() loop over itself
  tools/nolibc: fix missing includes causing build issues at -O0
  tools/nolibc: restore mips branch ordering in the _start block
  tools/nolibc: Fix S_ISxxx macros
  nolibc: fix fd_set type
This commit is contained in:
Linus Torvalds 2023-01-12 14:38:22 -06:00
commit f129b61612
12 changed files with 79 additions and 38 deletions

View file

@ -192,6 +192,7 @@ struct sys_stat_struct {
__asm__ (".section .text\n"
".weak __start\n"
".set nomips16\n"
".set push\n"
".set noreorder\n"
".option pic0\n"
".ent __start\n"
@ -210,6 +211,7 @@ __asm__ (".section .text\n"
"li $v0, 4001\n" // NR_exit == 4001
"syscall\n"
".end __start\n"
".set pop\n"
"");
#endif // _NOLIBC_ARCH_MIPS_H

View file

@ -11,13 +11,13 @@
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#define O_CREAT 0x100
#define O_EXCL 0x200
#define O_NOCTTY 0x400
#define O_TRUNC 0x1000
#define O_APPEND 0x2000
#define O_NONBLOCK 0x4000
#define O_DIRECTORY 0x200000
#define O_CREAT 0x40
#define O_EXCL 0x80
#define O_NOCTTY 0x100
#define O_TRUNC 0x200
#define O_APPEND 0x400
#define O_NONBLOCK 0x800
#define O_DIRECTORY 0x10000
struct sys_stat_struct {
unsigned long st_dev; /* Device. */

View file

@ -96,4 +96,7 @@ int ispunct(int c)
return isgraph(c) && !isalnum(c);
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_CTYPE_H */

View file

@ -24,4 +24,7 @@ static int errno;
*/
#define MAX_ERRNO 4095
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_ERRNO_H */

View file

@ -19,4 +19,7 @@ int raise(int signal)
return sys_kill(sys_getpid(), signal);
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_SIGNAL_H */

View file

@ -303,4 +303,7 @@ void perror(const char *msg)
fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno);
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_STDIO_H */

View file

@ -419,4 +419,7 @@ char *u64toa(uint64_t in)
return itoa_buffer;
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_STDLIB_H */

View file

@ -88,8 +88,11 @@ void *memset(void *dst, int b, size_t len)
{
char *p = dst;
while (len--)
while (len--) {
/* prevent gcc from recognizing memset() here */
asm volatile("");
*(p++) = b;
}
return dst;
}
@ -285,4 +288,7 @@ char *strrchr(const char *s, int c)
return (char *)ret;
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_STRING_H */

View file

@ -1243,5 +1243,7 @@ ssize_t write(int fd, const void *buf, size_t count)
return ret;
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_SYS_H */

View file

@ -25,4 +25,7 @@ time_t time(time_t *tptr)
return tv.tv_sec;
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_TIME_H */

View file

@ -26,13 +26,13 @@
#define S_IFSOCK 0140000
#define S_IFMT 0170000
#define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFCHR) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFBLK) == S_IFBLK)
#define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
#define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
/* dirent types */
#define DT_UNKNOWN 0x0
@ -89,39 +89,46 @@
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#define FD_SETIDXMASK (8 * sizeof(unsigned long))
#define FD_SETBITMASK (8 * sizeof(unsigned long)-1)
/* for select() */
typedef struct {
uint32_t fd32[(FD_SETSIZE + 31) / 32];
unsigned long fds[(FD_SETSIZE + FD_SETBITMASK) / FD_SETIDXMASK];
} fd_set;
#define FD_CLR(fd, set) do { \
fd_set *__set = (set); \
int __fd = (fd); \
if (__fd >= 0) \
__set->fd32[__fd / 32] &= ~(1U << (__fd & 31)); \
#define FD_CLR(fd, set) do { \
fd_set *__set = (set); \
int __fd = (fd); \
if (__fd >= 0) \
__set->fds[__fd / FD_SETIDXMASK] &= \
~(1U << (__fd & FX_SETBITMASK)); \
} while (0)
#define FD_SET(fd, set) do { \
fd_set *__set = (set); \
int __fd = (fd); \
if (__fd >= 0) \
__set->fd32[__fd / 32] |= 1U << (__fd & 31); \
#define FD_SET(fd, set) do { \
fd_set *__set = (set); \
int __fd = (fd); \
if (__fd >= 0) \
__set->fds[__fd / FD_SETIDXMASK] |= \
1 << (__fd & FD_SETBITMASK); \
} while (0)
#define FD_ISSET(fd, set) ({ \
fd_set *__set = (set); \
int __fd = (fd); \
int __r = 0; \
if (__fd >= 0) \
__r = !!(__set->fd32[__fd / 32] & 1U << (__fd & 31)); \
__r; \
#define FD_ISSET(fd, set) ({ \
fd_set *__set = (set); \
int __fd = (fd); \
int __r = 0; \
if (__fd >= 0) \
__r = !!(__set->fds[__fd / FD_SETIDXMASK] & \
1U << (__fd & FD_SET_BITMASK)); \
__r; \
})
#define FD_ZERO(set) do { \
fd_set *__set = (set); \
int __idx; \
for (__idx = 0; __idx < (FD_SETSIZE+31) / 32; __idx ++) \
__set->fd32[__idx] = 0; \
#define FD_ZERO(set) do { \
fd_set *__set = (set); \
int __idx; \
int __size = (FD_SETSIZE+FD_SETBITMASK) / FD_SETIDXMASK;\
for (__idx = 0; __idx < __size; __idx++) \
__set->fds[__idx] = 0; \
} while (0)
/* for poll() */
@ -202,4 +209,7 @@ struct stat {
})
#endif
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_TYPES_H */

View file

@ -51,4 +51,7 @@ int tcsetpgrp(int fd, pid_t pid)
return ioctl(fd, TIOCSPGRP, &pid);
}
/* make sure to include all global symbols */
#include "nolibc.h"
#endif /* _NOLIBC_UNISTD_H */