According to the ANSI C standard "7.5 Errors <errno.h>" section 3[1], "The value of errno is zero at program startup, but is never set to zero by any library function." The "program startup" is also defined in ANSI C standard "5.1.2.2.1 Program startup" section 1[2], "The function called at program startup is named main." Therefore, it should be reasonable to expect errno be zero when main is executed. However, we found that the following program would get non-zero errno under some circumstances. ``` /* errno.c */ #include <errno.h> #include <stdio.h> int main() { printf("errno: %d\n", errno); return 0; } $ riscv64-linux-gcc -O0 -g -static -o errno_st errno.c [ 51.968765] random: fast init done /mnt # ./errno errno: 11 [ 51.968765] random: fast init done [ 262.517056] crng init done /mnt # ./errno errno: 0 ``` If the above program is statically-linked, and if the program is executed before "crng init done", the errno will not be zero when entering main. There seems to be syscall (__getrandom) before main is entered, and if the crng is not initialized, the syscall will fail causing the errno to be set. (_dl_get_origin -> __libc_malloc -> ptmalloc_init -> tcache_key_initialize -> __getrandom) Thanks to Florian's suggestion: "Hiding the getrandom failure is probably sufficient. All other failures in malloc will lead to the process failing to start, so those errors don't need to be masked." We should clear the errno for the getrandom failure Related discussion: https://sourceware.org/pipermail/libc-help/2022-September/006301.html
Fixed on 2.37.
The master branch has been updated by Andreas K. Huttel <dilfridge@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=5a85786a9005722be7cb9e70f8874a5f1130daea commit 5a85786a9005722be7cb9e70f8874a5f1130daea Author: Xi Ruoyao <xry111@xry111.site> Date: Thu Jan 4 21:41:20 2024 +0800 Make __getrandom_nocancel set errno and add a _nostatus version The __getrandom_nocancel function returns errors as negative values instead of errno. This is inconsistent with other _nocancel functions and it breaks "TEMP_FAILURE_RETRY (__getrandom_nocancel (p, n, 0))" in __arc4random_buf. Use INLINE_SYSCALL_CALL instead of INTERNAL_SYSCALL_CALL to fix this issue. But __getrandom_nocancel has been avoiding from touching errno for a reason, see BZ 29624. So add a __getrandom_nocancel_nostatus function and use it in tcache_key_initialize. Signed-off-by: Xi Ruoyao <xry111@xry111.site> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>