Bug 29624 - errno is not cleared when entering main
Summary: errno is not cleared when entering main
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: malloc (show other bugs)
Version: 2.35
: P2 normal
Target Milestone: 2.37
Assignee: Adhemerval Zanella
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-09-28 10:31 UTC by Leo Liang
Modified: 2024-11-02 03:53 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Leo Liang 2022-09-28 10:31:56 UTC
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
Comment 1 Adhemerval Zanella 2022-09-30 18:27:11 UTC
Fixed on 2.37.
Comment 2 Sourceware Commits 2024-01-12 13:24:36 UTC
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>