* [PATCH, RFC] Add public function syscall_no_errno @ 2024-01-28 16:39 Askar Safin 2024-02-01 17:53 ` Adhemerval Zanella Netto 2024-02-07 1:57 ` Mike Frysinger 0 siblings, 2 replies; 23+ messages in thread From: Askar Safin @ 2024-01-28 16:39 UTC (permalink / raw) To: libc-alpha; +Cc: carlos Hi! I want glibc to have function "syscall_no_errno" on Linux. It should do the same "syscall" does, but it should not interpret return value and set errno. This is useful for calling syscalls such as getuid. I. e. now the user can call directly all syscalls including getuid and similar. I add example patch. It is quick-and-dirty. I was unable to figure out how to add function to headers. So, please, don't apply it as-is. I just want to know do you agree with my proposal. If yes, I will try to write better patch. I will repeat: currently glibc is simply incomplete, because it does not provide a way to call directly syscalls, such as getuid. So the user have to craft assembly, which is very difficult. The patch is against current master, i. e. ae49a7b29acc184b03c2a6bd6ac01b5e08efd54f -- diff --git a/misc/Versions b/misc/Versions index d5b348e8..ad37a4c2 100644 --- a/misc/Versions +++ b/misc/Versions @@ -71,7 +71,7 @@ libc { # s* sbrk; select; setdomainname; setfsent; sethostent; sethostid; sethostname; setlogmask; setmntent; setregid; setreuid; setttyent; setusershell; sstk; - stty; sync; syscall; syslog; + stty; sync; syscall; syslog; syscall_no_errno; # t* tdelete; tfind; truncate; tsearch; ttyslot; twalk; diff --git a/posix/unistd.h b/posix/unistd.h index 54d7d752..2f0f6e79 100644 --- a/posix/unistd.h +++ b/posix/unistd.h @@ -1089,6 +1089,7 @@ extern void *sbrk (intptr_t __delta) __THROW; In Mach, all system calls take normal arguments and always return an error code (zero for success). */ extern long int syscall (long int __sysno, ...) __THROW; +extern long int syscall_no_errno (long int __sysno, ...) __THROW; #endif /* Use misc. */ diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list index aac065e7..dac4d78e 100644 --- a/sysdeps/unix/sysv/linux/syscall-names.list +++ b/sysdeps/unix/sysv/linux/syscall-names.list @@ -612,6 +612,7 @@ sys_epoll_create sys_epoll_ctl sys_epoll_wait syscall +syscall_no_errno sysfs sysinfo syslog diff --git a/sysdeps/unix/sysv/linux/syscall.c b/sysdeps/unix/sysv/linux/syscall.c index 3cff1d97..481b18a4 100644 --- a/sysdeps/unix/sysv/linux/syscall.c +++ b/sysdeps/unix/sysv/linux/syscall.c @@ -41,3 +41,20 @@ syscall (long int number, ...) } return r; } +long int +syscall_no_errno (long int number, ...) +{ + va_list args; + + va_start (args, number); + long int a0 = va_arg (args, long int); + long int a1 = va_arg (args, long int); + long int a2 = va_arg (args, long int); + long int a3 = va_arg (args, long int); + long int a4 = va_arg (args, long int); + long int a5 = va_arg (args, long int); + va_end (args); + + long int r = INTERNAL_SYSCALL_NCS_CALL (number, a0, a1, a2, a3, a4, a5); + return r; +} diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index aea7848e..55d9dadd 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -1761,6 +1761,7 @@ GLIBC_2.2.5 sys_nerr D 0x4 GLIBC_2.2.5 sys_sigabbrev D 0x200 GLIBC_2.2.5 sys_siglist D 0x200 GLIBC_2.2.5 syscall F +GLIBC_2.2.5 syscall_no_errno F GLIBC_2.2.5 sysconf F GLIBC_2.2.5 sysctl F GLIBC_2.2.5 sysinfo F diff --git a/sysdeps/unix/sysv/linux/x86_64/syscall.S b/sysdeps/unix/sysv/linux/x86_64/syscall.S index 43af8087..04483251 100644 --- a/sysdeps/unix/sysv/linux/x86_64/syscall.S +++ b/sysdeps/unix/sysv/linux/x86_64/syscall.S @@ -26,6 +26,18 @@ .text +ENTRY (syscall_no_errno) + movq %rdi, %rax /* Syscall number -> rax. */ + movq %rsi, %rdi /* shift arg1 - arg5. */ + movq %rdx, %rsi + movq %rcx, %rdx + movq %r8, %r10 + movq %r9, %r8 + movq 8(%rsp),%r9 /* arg6 is on the stack. */ + syscall /* Do the system call. */ + ret /* Return to caller. */ + +PSEUDO_END_NOERRNO (syscall_no_errno) ENTRY (syscall) movq %rdi, %rax /* Syscall number -> rax. */ movq %rsi, %rdi /* shift arg1 - arg5. */ ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-01-28 16:39 [PATCH, RFC] Add public function syscall_no_errno Askar Safin @ 2024-02-01 17:53 ` Adhemerval Zanella Netto 2024-02-01 18:18 ` Rich Felker 2024-02-01 19:32 ` Askar Safin 2024-02-07 1:57 ` Mike Frysinger 1 sibling, 2 replies; 23+ messages in thread From: Adhemerval Zanella Netto @ 2024-02-01 17:53 UTC (permalink / raw) To: Askar Safin, libc-alpha, Rich Felker; +Cc: carlos On 28/01/24 13:39, Askar Safin wrote: > Hi! I want glibc to have function "syscall_no_errno" on Linux. > It should do the same "syscall" does, but it should not interpret > return value and set errno. This is useful for calling syscalls > such as getuid. I. e. now the user can call directly all syscalls > including getuid and similar. > > I add example patch. It is quick-and-dirty. I was unable to figure out > how to add function to headers. So, please, don't apply it as-is. > > I just want to know do you agree with my proposal. If yes, I will try > to write better patch. > > I will repeat: currently glibc is simply incomplete, because it > does not provide a way to call directly syscalls, such as getuid. > So the user have to craft assembly, which is very difficult. Indeed there some old syscalls where trying to issue them directly with syscall is problematic (like 'time' and 'brk' for some ABIs), but getuid is not one of them. Also, recent Linux kABI is trying to avoid such problematic interfaces to return the value as the return code and make the invalid value similar to all cases. So these are not very compeling reason to add a non-standard symbol to issue syscalls. CCing Rich, maybe he has a different view about this. > > The patch is against current master, i. e. ae49a7b29acc184b03c2a6bd6ac01b5e08efd54f > > -- > > diff --git a/misc/Versions b/misc/Versions > index d5b348e8..ad37a4c2 100644 > --- a/misc/Versions > +++ b/misc/Versions > @@ -71,7 +71,7 @@ libc { > # s* > sbrk; select; setdomainname; setfsent; sethostent; sethostid; sethostname; > setlogmask; setmntent; setregid; setreuid; setttyent; setusershell; sstk; > - stty; sync; syscall; syslog; > + stty; sync; syscall; syslog; syscall_no_errno; > > # t* > tdelete; tfind; truncate; tsearch; ttyslot; twalk; > diff --git a/posix/unistd.h b/posix/unistd.h > index 54d7d752..2f0f6e79 100644 > --- a/posix/unistd.h > +++ b/posix/unistd.h > @@ -1089,6 +1089,7 @@ extern void *sbrk (intptr_t __delta) __THROW; > In Mach, all system calls take normal arguments and always return an > error code (zero for success). */ > extern long int syscall (long int __sysno, ...) __THROW; > +extern long int syscall_no_errno (long int __sysno, ...) __THROW; > > #endif /* Use misc. */ > > diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list > index aac065e7..dac4d78e 100644 > --- a/sysdeps/unix/sysv/linux/syscall-names.list > +++ b/sysdeps/unix/sysv/linux/syscall-names.list > @@ -612,6 +612,7 @@ sys_epoll_create > sys_epoll_ctl > sys_epoll_wait > syscall > +syscall_no_errno > sysfs > sysinfo > syslog > diff --git a/sysdeps/unix/sysv/linux/syscall.c b/sysdeps/unix/sysv/linux/syscall.c > index 3cff1d97..481b18a4 100644 > --- a/sysdeps/unix/sysv/linux/syscall.c > +++ b/sysdeps/unix/sysv/linux/syscall.c > @@ -41,3 +41,20 @@ syscall (long int number, ...) > } > return r; > } > +long int > +syscall_no_errno (long int number, ...) > +{ > + va_list args; > + > + va_start (args, number); > + long int a0 = va_arg (args, long int); > + long int a1 = va_arg (args, long int); > + long int a2 = va_arg (args, long int); > + long int a3 = va_arg (args, long int); > + long int a4 = va_arg (args, long int); > + long int a5 = va_arg (args, long int); > + va_end (args); > + > + long int r = INTERNAL_SYSCALL_NCS_CALL (number, a0, a1, a2, a3, a4, a5); > + return r; > +} > diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > index aea7848e..55d9dadd 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > @@ -1761,6 +1761,7 @@ GLIBC_2.2.5 sys_nerr D 0x4 > GLIBC_2.2.5 sys_sigabbrev D 0x200 > GLIBC_2.2.5 sys_siglist D 0x200 > GLIBC_2.2.5 syscall F > +GLIBC_2.2.5 syscall_no_errno F > GLIBC_2.2.5 sysconf F > GLIBC_2.2.5 sysctl F > GLIBC_2.2.5 sysinfo F > diff --git a/sysdeps/unix/sysv/linux/x86_64/syscall.S b/sysdeps/unix/sysv/linux/x86_64/syscall.S > index 43af8087..04483251 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/syscall.S > +++ b/sysdeps/unix/sysv/linux/x86_64/syscall.S > @@ -26,6 +26,18 @@ > > > .text > +ENTRY (syscall_no_errno) > + movq %rdi, %rax /* Syscall number -> rax. */ > + movq %rsi, %rdi /* shift arg1 - arg5. */ > + movq %rdx, %rsi > + movq %rcx, %rdx > + movq %r8, %r10 > + movq %r9, %r8 > + movq 8(%rsp),%r9 /* arg6 is on the stack. */ > + syscall /* Do the system call. */ > + ret /* Return to caller. */ > + > +PSEUDO_END_NOERRNO (syscall_no_errno) > ENTRY (syscall) > movq %rdi, %rax /* Syscall number -> rax. */ > movq %rsi, %rdi /* shift arg1 - arg5. */ ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-01 17:53 ` Adhemerval Zanella Netto @ 2024-02-01 18:18 ` Rich Felker 2024-02-01 19:32 ` Askar Safin 1 sibling, 0 replies; 23+ messages in thread From: Rich Felker @ 2024-02-01 18:18 UTC (permalink / raw) To: Adhemerval Zanella Netto; +Cc: Askar Safin, libc-alpha, carlos On Thu, Feb 01, 2024 at 02:53:44PM -0300, Adhemerval Zanella Netto wrote: > > > On 28/01/24 13:39, Askar Safin wrote: > > Hi! I want glibc to have function "syscall_no_errno" on Linux. > > It should do the same "syscall" does, but it should not interpret > > return value and set errno. This is useful for calling syscalls > > such as getuid. I. e. now the user can call directly all syscalls > > including getuid and similar. > > > > I add example patch. It is quick-and-dirty. I was unable to figure out > > how to add function to headers. So, please, don't apply it as-is. > > > > I just want to know do you agree with my proposal. If yes, I will try > > to write better patch. > > > > I will repeat: currently glibc is simply incomplete, because it > > does not provide a way to call directly syscalls, such as getuid. > > So the user have to craft assembly, which is very difficult. > > Indeed there some old syscalls where trying to issue them directly with > syscall is problematic (like 'time' and 'brk' for some ABIs), but getuid > is not one of them. Also, recent Linux kABI is trying to avoid such > problematic interfaces to return the value as the return code and make > the invalid value similar to all cases. So these are not very compeling > reason to add a non-standard symbol to issue syscalls. > > CCing Rich, maybe he has a different view about this. That would be my view too. In general, it's rarely useful to make a raw syscall() to begin with. For the majority of syscalls that are ingredients in implementing standard or almost-standard functions provided by libc, going around libc to call it directly risks creating inconsistent state (brk), having inconsistent types (stat, etc.), missing fallback cases (direct use of time64 syscalls), etc. and really should not be encouraged by making unneeded new ways to do it. Indeed the only syscalls I'm aware of for which there's ambiguity about the result are of this sort. I don't even think brk is an affected one; values >=4095UL are not valid brk boundaries. Similarly, I don't think Linux supports setting system clock to before the epoch (and doing so would not be accurate anyway), so time is arguably not affected either. Even if it were, it's superseded by clock_gettime or gettimeofday, which don't have the problem, and might not even be available on future archs. There is also fcntl with F_GETOWN, which was not mentioned above, but it is superseded by F_GETOWN_EX, which the libc fcntl function automatically uses when available instead of using F_GETOWN directly. So I don't think it has modern relevance either. In any case, back to my original point, the use case for syscall() should be seen as calling newly-added extensions that don't yet have, or that aren't suitable to have, libc functions for them. Use of it as a means to "poke behind libc" should not be encouraged, as that tends to break things. If someone really wants to write code that's independent of libc -- like to run in a vforked child or CLONE_VM context or something without a valid thread pointer/TLS state/etc. -- it can't be using libc at all, and that includes the libc syscall() function (which not only may write errno, but might inspect TLS to determine how to make the syscall). For this level of "raw" syscall access, you need to write your own asm. Rich ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-01 17:53 ` Adhemerval Zanella Netto 2024-02-01 18:18 ` Rich Felker @ 2024-02-01 19:32 ` Askar Safin 2024-02-01 20:16 ` dalias 1 sibling, 1 reply; 23+ messages in thread From: Askar Safin @ 2024-02-01 19:32 UTC (permalink / raw) To: Adhemerval Zanella Netto, dalias; +Cc: libc-alpha, carlos Hi, Rich and Adhemerval! ---- On Thu, 01 Feb 2024 21:53:44 +0400 Adhemerval Zanella Netto wrote --- > Indeed there some old syscalls where trying to issue them directly with > syscall is problematic (like 'time' and 'brk' for some ABIs), but getuid > is not one of them. It *is* one of them! Keep in mind that Linux supports 32-bit uids. Run this code as root as 32-bit i386 binary (my letter continues after code). It is okay to run it on 64-bit amd64 kernel, you just have to make sure the binary itself is compiled as i386 =*=*=*=*= #if !defined(__i386__) #error #endif #include <stdint.h> #include <stdio.h> #include <sys/syscall.h> #include <unistd.h> int main (void) { // 4294967286 is (2^32)-10 uint32_t a = 4294967286U; if (syscall (SYS_setuid32, a) == -1) { perror("setuid"); return 1; } uint32_t b = syscall (SYS_getuid32); // Now b is equal to (uint32_t)-1 instead of wanted 4294967286 (i. e. (uint32_t)-10) printf("%u (wanted)\n", a); printf("%u (got)\n", b); return 0; } =*=*=*=*= (Also, when I said "getuid", I meant "SYS_getuid32".) I see this output: =*=*=*=*= 4294967286 (wanted) 4294967295 (got) =*=*=*=*= So, yes, function "syscall" is incompatible with SYS_getuid32. I'm nearly sure the same is true about getpid. Rich: > If someone really wants to write code that's > independent of libc -- like to run in a vforked child or CLONE_VM This is another use case I want to support. I. e. I want to have portable function (i. e. independent of arch) for issuing syscall in such case. And I don't want to write assembly. > but might inspect TLS to > determine how to make the syscall Okay, so syscall_no_errno should not do this. I. e. it should always do some way to make syscall, which always works, even if it is slow. For i386 it is "int 0x80" as well as I understand. Also, even if we read TLS to determine how to make syscall, what will go wrong? Child shares TLS with its parent after CLONE_VM, so we simply will read parent's TLS ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-01 19:32 ` Askar Safin @ 2024-02-01 20:16 ` dalias 2024-02-01 20:57 ` Adhemerval Zanella Netto 2024-02-07 0:59 ` [PATCH, RFC] " Askar Safin 0 siblings, 2 replies; 23+ messages in thread From: dalias @ 2024-02-01 20:16 UTC (permalink / raw) To: Askar Safin; +Cc: Adhemerval Zanella Netto, libc-alpha, carlos On Thu, Feb 01, 2024 at 11:32:41PM +0400, Askar Safin wrote: > Hi, Rich and Adhemerval! > > ---- On Thu, 01 Feb 2024 21:53:44 +0400 Adhemerval Zanella Netto wrote --- > > Indeed there some old syscalls where trying to issue them directly with > > syscall is problematic (like 'time' and 'brk' for some ABIs), but getuid > > is not one of them. > It *is* one of them! > > Keep in mind that Linux supports 32-bit uids. > > Run this code as root as 32-bit i386 binary (my letter continues > after code). It is okay to run it on 64-bit amd64 kernel, you just > have to make sure the binary itself is compiled as i386 > =*=*=*=*= > #if !defined(__i386__) > #error > #endif > > #include <stdint.h> > #include <stdio.h> > #include <sys/syscall.h> > #include <unistd.h> > > int > main (void) > { > // 4294967286 is (2^32)-10 > uint32_t a = 4294967286U; > if (syscall (SYS_setuid32, a) == -1) > { > perror("setuid"); > return 1; > } > > uint32_t b = syscall (SYS_getuid32); > > // Now b is equal to (uint32_t)-1 instead of wanted 4294967286 (i. e. (uint32_t)-10) > printf("%u (wanted)\n", a); > printf("%u (got)\n", b); > return 0; > } > =*=*=*=*= > > (Also, when I said "getuid", I meant "SYS_getuid32".) > > I see this output: > =*=*=*=*= > 4294967286 (wanted) > 4294967295 (got) > =*=*=*=*= > > So, yes, function "syscall" is incompatible with SYS_getuid32. OK, but this falls under "poking around behind libc's back". If you call getuid() you'll find you get the right answer (at least on musl; not sure about glibc). > I'm nearly sure the same is true about getpid. It's not. PIDs are a 29- or 30-bit space (which is a matter of a bug I currently have open) on Linux. At least the high two bits are banned from ever being usable as a consequence of the futex interface. > Rich: > > If someone really wants to write code that's > > independent of libc -- like to run in a vforked child or CLONE_VM > > This is another use case I want to support. I. e. I want to > have portable function (i. e. independent of arch) for issuing > syscall in such case. And I don't > want to write assembly. Well that's not something syscall() gives you and it's not something syscall_no_errno() would reliably give you either unless it was specifically documented to be callable from such a context. If that's what you want, maybe that's what should be discussed. > > but might inspect TLS to > > determine how to make the syscall > > Okay, so syscall_no_errno should not do this. I. e. it should > always do some way to make syscall, which always works, > even if it is slow. For i386 it is "int 0x80" as well as I understand. > > Also, even if we read TLS to determine how to make syscall, > what will go wrong? Child shares TLS with its parent after CLONE_VM, > so we simply will read parent's TLS At least on glibc, you can pass clone flags that setup a new thread pointer in the child, which you may be intending to use for your own purposes in 'bare, no libc' code in the child. On musl this is not possible; the flags are rejected and you have to write your own asm to call clone if you want that. In any case, "what will go wrong?" is not the right question. The question is whether there's a contract for the thing you want to do to work, and there isn't. Rich ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-01 20:16 ` dalias @ 2024-02-01 20:57 ` Adhemerval Zanella Netto 2024-02-08 15:02 ` [PATCH v2] " Askar Safin 2024-02-07 0:59 ` [PATCH, RFC] " Askar Safin 1 sibling, 1 reply; 23+ messages in thread From: Adhemerval Zanella Netto @ 2024-02-01 20:57 UTC (permalink / raw) To: dalias, Askar Safin; +Cc: libc-alpha, carlos On 01/02/24 17:16, dalias wrote: > On Thu, Feb 01, 2024 at 11:32:41PM +0400, Askar Safin wrote: >> Hi, Rich and Adhemerval! >> >> ---- On Thu, 01 Feb 2024 21:53:44 +0400 Adhemerval Zanella Netto wrote --- >> > Indeed there some old syscalls where trying to issue them directly with >> > syscall is problematic (like 'time' and 'brk' for some ABIs), but getuid >> > is not one of them. >> It *is* one of them! >> >> Keep in mind that Linux supports 32-bit uids. >> >> Run this code as root as 32-bit i386 binary (my letter continues >> after code). It is okay to run it on 64-bit amd64 kernel, you just >> have to make sure the binary itself is compiled as i386 >> =*=*=*=*= >> #if !defined(__i386__) >> #error >> #endif >> >> #include <stdint.h> >> #include <stdio.h> >> #include <sys/syscall.h> >> #include <unistd.h> >> >> int >> main (void) >> { >> // 4294967286 is (2^32)-10 >> uint32_t a = 4294967286U; >> if (syscall (SYS_setuid32, a) == -1) >> { >> perror("setuid"); >> return 1; >> } >> >> uint32_t b = syscall (SYS_getuid32); >> >> // Now b is equal to (uint32_t)-1 instead of wanted 4294967286 (i. e. (uint32_t)-10) >> printf("%u (wanted)\n", a); >> printf("%u (got)\n", b); >> return 0; >> } >> =*=*=*=*= >> >> (Also, when I said "getuid", I meant "SYS_getuid32".) >> >> I see this output: >> =*=*=*=*= >> 4294967286 (wanted) >> 4294967295 (got) >> =*=*=*=*= >> >> So, yes, function "syscall" is incompatible with SYS_getuid32. > > OK, but this falls under "poking around behind libc's back". If you > call getuid() you'll find you get the right answer (at least on musl; > not sure about glibc). It works as expected on glibc as well. > >> I'm nearly sure the same is true about getpid. > > It's not. PIDs are a 29- or 30-bit space (which is a matter of a bug I > currently have open) on Linux. At least the high two bits are banned > from ever being usable as a consequence of the futex interface. > >> Rich: >>> If someone really wants to write code that's >>> independent of libc -- like to run in a vforked child or CLONE_VM >> >> This is another use case I want to support. I. e. I want to >> have portable function (i. e. independent of arch) for issuing >> syscall in such case. And I don't >> want to write assembly. > > Well that's not something syscall() gives you and it's not something > syscall_no_errno() would reliably give you either unless it was > specifically documented to be callable from such a context. If that's > what you want, maybe that's what should be discussed. There is another potential issue where you have multiple syscall with slight different kABI (like the ones that have 64 bit arguments on 32 bit architectures) and, at least for glibc, where the user exported argument does not really match the kernel (stat/fstat/etc.). > >>> but might inspect TLS to >>> determine how to make the syscall >> >> Okay, so syscall_no_errno should not do this. I. e. it should >> always do some way to make syscall, which always works, >> even if it is slow. For i386 it is "int 0x80" as well as I understand. >> >> Also, even if we read TLS to determine how to make syscall, >> what will go wrong? Child shares TLS with its parent after CLONE_VM, >> so we simply will read parent's TLS > > At least on glibc, you can pass clone flags that setup a new thread > pointer in the child, which you may be intending to use for your own > purposes in 'bare, no libc' code in the child. On musl this is not > possible; the flags are rejected and you have to write your own asm to > call clone if you want that. > > In any case, "what will go wrong?" is not the right question. The > question is whether there's a contract for the thing you want to do to > work, and there isn't. And I am not very found of this possible slight different contract for a non-standard interface. ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2] Add public function syscall_no_errno 2024-02-01 20:57 ` Adhemerval Zanella Netto @ 2024-02-08 15:02 ` Askar Safin 2024-02-08 17:48 ` Szabolcs Nagy 2024-02-12 14:24 ` Florian Weimer 0 siblings, 2 replies; 23+ messages in thread From: Askar Safin @ 2024-02-08 15:02 UTC (permalink / raw) To: libc-alpha, adhemerval.zanella, carlos; +Cc: dalias Add public function syscall_no_errno. Linux-specific. It is the same as syscall, but it doesn't interpret value, returned by Linux. So it is okay for issuing syscalls, such as SYS_getuid. Example: #define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <sys/syscall.h> int main () { long int rc; rc = syscall_no_errno(SYS_getuid); printf("uid = %ld\n", rc); } --- This is second version of my patch. This time I did everything right. I. e. this is not quick-and-dirty patch, this is patch ready for inclusion in glibc. My code works for all Linux archs. The patch includes docs. You can see motivation in my previous letters in this thread. Let me quickly repeat my main argument: glibc in its current form is incomplete. It contains "syscall", but it will not work with SYS_getuid32 on i386. Thus we need "syscall_no_errno" NEWS | 2 + manual/startup.texi | 39 ++++++++++++++++++- sysdeps/unix/sysv/linux/Makefile | 1 + sysdeps/unix/sysv/linux/Versions | 3 ++ sysdeps/unix/sysv/linux/aarch64/libc.abilist | 1 + sysdeps/unix/sysv/linux/alpha/libc.abilist | 1 + sysdeps/unix/sysv/linux/arc/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/le/libc.abilist | 1 + sysdeps/unix/sysv/linux/bits/unistd_ext.h | 4 ++ sysdeps/unix/sysv/linux/csky/libc.abilist | 1 + sysdeps/unix/sysv/linux/hppa/libc.abilist | 1 + sysdeps/unix/sysv/linux/i386/libc.abilist | 1 + .../sysv/linux/loongarch/lp64/libc.abilist | 1 + .../sysv/linux/m68k/coldfire/libc.abilist | 1 + .../unix/sysv/linux/m68k/m680x0/libc.abilist | 1 + .../sysv/linux/microblaze/be/libc.abilist | 1 + .../sysv/linux/microblaze/le/libc.abilist | 1 + .../sysv/linux/mips/mips32/fpu/libc.abilist | 1 + .../sysv/linux/mips/mips32/nofpu/libc.abilist | 1 + .../sysv/linux/mips/mips64/n32/libc.abilist | 1 + .../sysv/linux/mips/mips64/n64/libc.abilist | 1 + sysdeps/unix/sysv/linux/nios2/libc.abilist | 1 + sysdeps/unix/sysv/linux/or1k/libc.abilist | 1 + .../linux/powerpc/powerpc32/fpu/libc.abilist | 1 + .../powerpc/powerpc32/nofpu/libc.abilist | 1 + .../linux/powerpc/powerpc64/be/libc.abilist | 1 + .../linux/powerpc/powerpc64/le/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv32/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv64/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-32/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-64/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/le/libc.abilist | 1 + .../sysv/linux/sparc/sparc32/libc.abilist | 1 + .../sysv/linux/sparc/sparc64/libc.abilist | 1 + sysdeps/unix/sysv/linux/syscall_no_errno.c | 38 ++++++++++++++++++ .../unix/sysv/linux/x86_64/64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/x32/libc.abilist | 1 + 39 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/syscall_no_errno.c diff --git a/NEWS b/NEWS index 2d8eaffc58..98b8064cc5 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,8 @@ Major new features: by _GNU_SOURCE, or by compiling with the GCC options -std=c23, -std=gnu23, -std=c2x or -std=gnu2x. +* On Linux, the function syscall_no_errno have been added. + Deprecated and removed features, and other changes affecting compatibility: [Add deprecations, removals and changes affecting compatibility here] diff --git a/manual/startup.texi b/manual/startup.texi index 9bf24123f5..59893232a9 100644 --- a/manual/startup.texi +++ b/manual/startup.texi @@ -713,7 +713,7 @@ library source code as a specification of the interface between them anyway. -@code{syscall} is declared in @file{unistd.h}. +@code{syscall} and @code{syscall_no_errno} are declared in @file{unistd.h}. @deftypefun {long int} syscall (long int @var{sysno}, @dots{}) @standards{???, unistd.h} @@ -735,7 +735,11 @@ the right are ignored. The return value is the return value from the system call, unless the system call failed. In that case, @code{syscall} returns @code{-1} and sets @code{errno} to an error code that the system call returned. Note -that system calls do not return @code{-1} when they succeed. +that system calls do not return @code{-1} when they succeed (there is +an exception here: few Linux syscalls, such as @code{SYS_getuid32} on i386 +may return @code{-1}, when no error happened; so do not pass @code{SYS_getuid32} +to @code{syscall} on Linux; you should use @code{syscall_no_errno} instead, +which is described below). @cindex errno If you specify an invalid @var{sysno}, @code{syscall} returns @code{-1} @@ -781,6 +785,37 @@ if (rc == -1) @end deftypefun +@deftypefun {long int} syscall_no_errno (long int @var{sysno}, @dots{}) +@standards{GNU, unistd.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} + +@code{syscall_no_errno} is Linux-specific GNU extension. It does the same +as @code{syscall}, but does not interpret return value, returned by Linux +kernel, and doesn't set @code{errno}. This makes @code{syscall_no_errno} +suitable for performing Linux syscalls, which never fail, such as +@code{SYS_getuid}. + +Example: + +@smallexample + +#define _GNU_SOURCE +#include <stdio.h> +#include <unistd.h> +#include <sys/syscall.h> + +@dots{} + +long int rc; + +rc = syscall_no_errno(SYS_getuid); + +printf("uid = %ld\n", rc); + +@end smallexample + +@end deftypefun + @node Program Termination @section Program Termination diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 415aa1f14d..3be40dd0fc 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -100,6 +100,7 @@ sysdep_routines += \ setvmaname \ signalfd \ splice \ + syscall_no_errno \ sysctl \ tee \ timerfd_gettime \ diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index 268ba1b6ac..398b2d31be 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -328,6 +328,9 @@ libc { posix_spawnattr_getcgroup_np; posix_spawnattr_setcgroup_np; } + GLIBC_2.40 { + syscall_no_errno; + } GLIBC_PRIVATE { # functions used in other libraries __syscall_rt_sigqueueinfo; diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index 68eeca1c08..b2760fb686 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2748,3 +2748,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index 34c187b721..7592e1f71f 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -3095,6 +3095,7 @@ GLIBC_2.4 wcstold F GLIBC_2.4 wcstold_l F GLIBC_2.4 wprintf F GLIBC_2.4 wscanf F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist index 916c18ea94..63d39ebc3b 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -2509,3 +2509,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist index ea95de282a..c5081bdec9 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -2801,6 +2801,7 @@ GLIBC_2.4 xdrstdio_create F GLIBC_2.4 xencrypt F GLIBC_2.4 xprt_register F GLIBC_2.4 xprt_unregister F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist index 1cdbc983e1..90d3181cbb 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -2798,6 +2798,7 @@ GLIBC_2.4 xdrstdio_create F GLIBC_2.4 xencrypt F GLIBC_2.4 xprt_register F GLIBC_2.4 xprt_unregister F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/bits/unistd_ext.h b/sysdeps/unix/sysv/linux/bits/unistd_ext.h index 2ce1d45138..a5149b0c4c 100644 --- a/sysdeps/unix/sysv/linux/bits/unistd_ext.h +++ b/sysdeps/unix/sysv/linux/bits/unistd_ext.h @@ -47,4 +47,8 @@ extern __pid_t gettid (void) __THROW; # define CLOSE_RANGE_CLOEXEC (1U << 2) #endif +/* Same as syscall, but doesn't try to interpret raw return value. + Never sets errno. */ +extern long int syscall_no_errno (long int __sysno, ...) __THROW; + #endif /* __USE_GNU */ diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index 96d45961e2..76d8df8616 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2785,3 +2785,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index fbcd60c2b3..1abdb4ccf9 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2821,6 +2821,7 @@ GLIBC_2.4 sys_errlist D 0x400 GLIBC_2.4 sys_nerr D 0x4 GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index c989b433c0..9cafcd4ca8 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -3005,6 +3005,7 @@ GLIBC_2.4 sys_errlist D 0x210 GLIBC_2.4 sys_nerr D 0x4 GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist index 0023ec1fa1..b5151baeaf 100644 --- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist +++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist @@ -2269,3 +2269,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index d9bd6a9b56..0d6972747c 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -2781,6 +2781,7 @@ GLIBC_2.4 xdrstdio_create F GLIBC_2.4 xencrypt F GLIBC_2.4 xprt_register F GLIBC_2.4 xprt_unregister F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index 439796d693..5d55addb44 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2948,6 +2948,7 @@ GLIBC_2.4 sys_errlist D 0x210 GLIBC_2.4 sys_nerr D 0x4 GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist index 1069d3252c..fb460f8223 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2834,3 +2834,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist index 17abe08c8b..d5e271ad23 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2831,3 +2831,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index 799e508950..bdd852481a 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2909,6 +2909,7 @@ GLIBC_2.4 renameat F GLIBC_2.4 symlinkat F GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index 1c10996cbc..8d4ed14ad5 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2907,6 +2907,7 @@ GLIBC_2.4 renameat F GLIBC_2.4 symlinkat F GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index 03d9655f26..b15d38bcde 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2915,6 +2915,7 @@ GLIBC_2.4 renameat F GLIBC_2.4 symlinkat F GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index 05e402ed30..0c2ddd1fa0 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2817,6 +2817,7 @@ GLIBC_2.4 renameat F GLIBC_2.4 symlinkat F GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist index 3aa81766aa..91d9e86823 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2873,3 +2873,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist index c40c843aaf..ff93694aa0 100644 --- a/sysdeps/unix/sysv/linux/or1k/libc.abilist +++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist @@ -2255,3 +2255,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index 9714305608..0f6685a9e4 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -3138,6 +3138,7 @@ GLIBC_2.4 wcstold F GLIBC_2.4 wcstold_l F GLIBC_2.4 wprintf F GLIBC_2.4 wscanf F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index 0beb52c542..53450512e0 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -3183,6 +3183,7 @@ GLIBC_2.4 wcstold F GLIBC_2.4 wcstold_l F GLIBC_2.4 wprintf F GLIBC_2.4 wscanf F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist index cfc2ebd3ec..121f8dd555 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2892,6 +2892,7 @@ GLIBC_2.4 wcstold F GLIBC_2.4 wcstold_l F GLIBC_2.4 wprintf F GLIBC_2.4 wscanf F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist index 8c9efc5a16..8654cdf60c 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2968,3 +2968,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist index f90c94bc35..2f21912ce7 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -2511,3 +2511,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index e04ff93bd2..f8f5952878 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2711,3 +2711,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist index a7467e2850..6c76ea2f04 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -3136,6 +3136,7 @@ GLIBC_2.4 wcstold F GLIBC_2.4 wcstold_l F GLIBC_2.4 wprintf F GLIBC_2.4 wscanf F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist index fd1cb2972d..8c16869b3f 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2929,6 +2929,7 @@ GLIBC_2.4 wcstold F GLIBC_2.4 wcstold_l F GLIBC_2.4 wprintf F GLIBC_2.4 wscanf F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist index ff6e6b1a13..1a6af130de 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2828,6 +2828,7 @@ GLIBC_2.4 sys_errlist D 0x210 GLIBC_2.4 sys_nerr D 0x4 GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist index 449d92bbc5..f2ce488fb2 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2825,6 +2825,7 @@ GLIBC_2.4 sys_errlist D 0x210 GLIBC_2.4 sys_nerr D 0x4 GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index e615be759a..55d6df917a 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -3157,6 +3157,7 @@ GLIBC_2.4 wcstold F GLIBC_2.4 wcstold_l F GLIBC_2.4 wprintf F GLIBC_2.4 wscanf F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index bd36431dd7..620efd5adf 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2793,6 +2793,7 @@ GLIBC_2.4 sys_errlist D 0x430 GLIBC_2.4 sys_nerr D 0x4 GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/syscall_no_errno.c b/sysdeps/unix/sysv/linux/syscall_no_errno.c new file mode 100644 index 0000000000..15aeb1c4c0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/syscall_no_errno.c @@ -0,0 +1,38 @@ +/* syscall_no_errno - Same as syscall, but doesn't try to interpret + raw return value. Never sets errno. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdarg.h> +#include <sysdep.h> + +long int +syscall_no_errno (long int number, ...) +{ + va_list args; + + va_start (args, number); + long int a0 = va_arg (args, long int); + long int a1 = va_arg (args, long int); + long int a2 = va_arg (args, long int); + long int a3 = va_arg (args, long int); + long int a4 = va_arg (args, long int); + long int a5 = va_arg (args, long int); + va_end (args); + + return INTERNAL_SYSCALL_NCS_CALL (number, a0, a1, a2, a3, a4, a5); +} diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index aea7848ed6..093348529a 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2744,6 +2744,7 @@ GLIBC_2.4 sys_errlist D 0x420 GLIBC_2.4 sys_nerr D 0x4 GLIBC_2.4 unlinkat F GLIBC_2.4 unshare F +GLIBC_2.40 syscall_no_errno F GLIBC_2.5 __readlinkat_chk F GLIBC_2.5 inet6_opt_append F GLIBC_2.5 inet6_opt_find F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index 4ab3681914..77ef1b678f 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2763,3 +2763,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F GLIBC_2.39 stdc_trailing_zeros_ul F GLIBC_2.39 stdc_trailing_zeros_ull F GLIBC_2.39 stdc_trailing_zeros_us F +GLIBC_2.40 syscall_no_errno F -- 2.43.0 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-08 15:02 ` [PATCH v2] " Askar Safin @ 2024-02-08 17:48 ` Szabolcs Nagy 2024-02-12 14:24 ` Florian Weimer 1 sibling, 0 replies; 23+ messages in thread From: Szabolcs Nagy @ 2024-02-08 17:48 UTC (permalink / raw) To: Askar Safin, libc-alpha, adhemerval.zanella, carlos; +Cc: dalias The 02/08/2024 18:02, Askar Safin wrote: > Add public function syscall_no_errno. Linux-specific. It is the same as syscall, > but it doesn't interpret value, returned by Linux. So it is > okay for issuing syscalls, such as SYS_getuid. Example: > > #define _GNU_SOURCE > #include <stdio.h> > #include <unistd.h> > #include <sys/syscall.h> > > int > main () > { > long int rc; > rc = syscall_no_errno(SYS_getuid); > printf("uid = %ld\n", rc); > } > the commit message has to explain why this is added and how do we expect users to use this api. it has to address why do we care about this use-case more than the long list of other cases on linux that don't work with the existing syscall api. the patch needs tests for the new api. i think the variadic nature of syscall and the libc vs linux type differences are problematic enough that we should discourage its use with or without errno. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-08 15:02 ` [PATCH v2] " Askar Safin 2024-02-08 17:48 ` Szabolcs Nagy @ 2024-02-12 14:24 ` Florian Weimer 2024-02-12 14:44 ` Rich Felker 1 sibling, 1 reply; 23+ messages in thread From: Florian Weimer @ 2024-02-12 14:24 UTC (permalink / raw) To: Askar Safin; +Cc: libc-alpha, adhemerval.zanella, carlos, dalias * Askar Safin: > +@code{syscall_no_errno} is Linux-specific GNU extension. It does the same > +as @code{syscall}, but does not interpret return value, returned by Linux > +kernel, and doesn't set @code{errno}. This makes @code{syscall_no_errno} > +suitable for performing Linux syscalls, which never fail, such as > +@code{SYS_getuid}. Are there really any system calls which return a value in the range -4095 to -1, and it's still considered a success? Thanks, Florian ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 14:24 ` Florian Weimer @ 2024-02-12 14:44 ` Rich Felker 2024-02-12 16:16 ` Askar Safin 0 siblings, 1 reply; 23+ messages in thread From: Rich Felker @ 2024-02-12 14:44 UTC (permalink / raw) To: Florian Weimer; +Cc: Askar Safin, libc-alpha, adhemerval.zanella, carlos On Mon, Feb 12, 2024 at 03:24:52PM +0100, Florian Weimer wrote: > * Askar Safin: > > > +@code{syscall_no_errno} is Linux-specific GNU extension. It does the same > > +as @code{syscall}, but does not interpret return value, returned by Linux > > +kernel, and doesn't set @code{errno}. This makes @code{syscall_no_errno} > > +suitable for performing Linux syscalls, which never fail, such as > > +@code{SYS_getuid}. > > Are there really any system calls which return a value in the range > -4095 to -1, and it's still considered a success? Yes, there are a very small number of such syscalls -- getuid and getgid are the only relevant ones AFAICT -- but the author of this proposal is missing the point. They want to avoid using libc, but then have a libc function to make their raw syscalls for them, rather than just doing that themselves. And apparently this function is supposed to have an undocumented contract that you can call it from contexts where calling other libc functions might not be valid..? Or not? It was never really clarified. They also seem to be under the mistaken impression that you can just add arbitrary pet functions to libc as long as you follow some procedures for doing it the right way, rather than understanding that the maintainer's job is to say no, and that functions don't go in libc unless there's some sort of consensus that they belong there. Rich ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 14:44 ` Rich Felker @ 2024-02-12 16:16 ` Askar Safin 2024-02-12 17:25 ` Zack Weinberg 0 siblings, 1 reply; 23+ messages in thread From: Askar Safin @ 2024-02-12 16:16 UTC (permalink / raw) To: Rich Felker; +Cc: Florian Weimer, libc-alpha, adhemerval.zanella, carlos ---- On Mon, 12 Feb 2024 18:44:31 +0400 Rich Felker wrote --- > Yes, there are a very small number of such syscalls -- getuid and > getgid are the only relevant ones AFAICT -- but the author of this > proposal is missing the point Okay, I declare defeat -- Askar Safin https://types.pl/@safinaskar ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 16:16 ` Askar Safin @ 2024-02-12 17:25 ` Zack Weinberg 2024-02-12 17:43 ` Andreas Schwab ` (2 more replies) 0 siblings, 3 replies; 23+ messages in thread From: Zack Weinberg @ 2024-02-12 17:25 UTC (permalink / raw) To: Askar Safin; +Cc: GNU libc development On Mon, Feb 12, 2024, at 11:16 AM, Askar Safin wrote: > ---- On Mon, 12 Feb 2024 18:44:31 +0400 Rich Felker wrote --- > > Yes, there are a very small number of such syscalls -- getuid and > > getgid are the only relevant ones AFAICT -- but the author of this > > proposal is missing the point > > Okay, I declare defeat I have a question for you: Do glibc's existing getuid() and getgid() functions correctly handle IDs in the [-4095, -1] range (perhaps better described as the [4294963201, 4294967295] range) ? It appears to me from binary code inspection that they do -- here's the assembly dump of getuid() on x86-64: (gdb) disas getuid Dump of assembler code for function __GI_getuid: 0x00000000000cf940 <+0>: mov $0x66,%eax 0x00000000000cf945 <+5>: syscall 0x00000000000cf947 <+7>: ret End of assembler dump. But I am not having any luck figuring out what bit of glibc's *source* code tells the syscall stub generator not to emit the code to check for error returns for these syscalls, so it's plausible to me that there is a bug in here somewhere, possibly only on lesser-used architectures. If you know of a case where we get this wrong, please tell us about it so we can fix it. zw ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 17:25 ` Zack Weinberg @ 2024-02-12 17:43 ` Andreas Schwab 2024-02-12 18:22 ` Zack Weinberg 2024-02-12 17:55 ` Adhemerval Zanella Netto 2024-02-12 18:34 ` Askar Safin 2 siblings, 1 reply; 23+ messages in thread From: Andreas Schwab @ 2024-02-12 17:43 UTC (permalink / raw) To: Zack Weinberg; +Cc: Askar Safin, GNU libc development On Feb 12 2024, Zack Weinberg wrote: > But I am not having any luck figuring out what bit of glibc's *source* > code tells the syscall stub generator not to emit the code to check for > error returns for these syscalls, It's the E flag in the syscalls.list which sets SYSCALL_NOERRNO to nonzero. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 17:43 ` Andreas Schwab @ 2024-02-12 18:22 ` Zack Weinberg 2024-02-13 9:10 ` Andreas Schwab 0 siblings, 1 reply; 23+ messages in thread From: Zack Weinberg @ 2024-02-12 18:22 UTC (permalink / raw) To: Andreas Schwab; +Cc: GNU libc development On Mon, Feb 12, 2024, at 12:43 PM, Andreas Schwab wrote: > On Feb 12 2024, Zack Weinberg wrote: > >> But I am not having any luck figuring out what bit of glibc's *source* >> code tells the syscall stub generator not to emit the code to check for >> error returns for these syscalls, > > It's the E flag in the syscalls.list which sets SYSCALL_NOERRNO to > nonzero. Ah, thank you. I didn't think to look above sysdeps/unix/sysv/linux for the stub generator. These system calls are consistently tagged with 'E' in all syscalls.list files where they appear, and all of the non-syscalls.list implementations also don't look for an error code or set errno (except for Hurd, which is noted as a bug in the relevant files). I believe this is correct for all of them. getegid geteuid getgid getpgrp getpid getppid gettid getuid umask These system calls are *inconsistently* tagged with 'E'. clock_gettime personality setfsgid setfsuid Based on the manpages, I believe clock_gettime and personality should _not_ have the E tag, but setfsgid and setfsuid should. I am not presently able to develop patches. zw ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 18:22 ` Zack Weinberg @ 2024-02-13 9:10 ` Andreas Schwab 2024-02-13 11:57 ` Adhemerval Zanella Netto 0 siblings, 1 reply; 23+ messages in thread From: Andreas Schwab @ 2024-02-13 9:10 UTC (permalink / raw) To: Zack Weinberg; +Cc: GNU libc development On Feb 12 2024, Zack Weinberg wrote: > These system calls are *inconsistently* tagged with 'E'. > > clock_gettime > personality > setfsgid > setfsuid > > Based on the manpages, I believe clock_gettime and personality > should _not_ have the E tag, but setfsgid and setfsuid should. See commit e0043e17df for the history of the personality syscall. The clock_gettime entry is only for the internal __syscall_clock_gettime call which deliberately does not want errno checking. For setfs[gu]id only archs using the setfs[gu]id32 syscall need the E flag. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-13 9:10 ` Andreas Schwab @ 2024-02-13 11:57 ` Adhemerval Zanella Netto 0 siblings, 0 replies; 23+ messages in thread From: Adhemerval Zanella Netto @ 2024-02-13 11:57 UTC (permalink / raw) To: Andreas Schwab, Zack Weinberg; +Cc: GNU libc development On 13/02/24 06:10, Andreas Schwab wrote: > On Feb 12 2024, Zack Weinberg wrote: > >> These system calls are *inconsistently* tagged with 'E'. >> >> clock_gettime >> personality >> setfsgid >> setfsuid >> >> Based on the manpages, I believe clock_gettime and personality >> should _not_ have the E tag, but setfsgid and setfsuid should. > > See commit e0043e17df for the history of the personality syscall. The > clock_gettime entry is only for the internal __syscall_clock_gettime > call which deliberately does not want errno checking. For setfs[gu]id > only archs using the setfs[gu]id32 syscall need the E flag. > And the __syscall_clock_gettime is not really used anywhere. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 17:25 ` Zack Weinberg 2024-02-12 17:43 ` Andreas Schwab @ 2024-02-12 17:55 ` Adhemerval Zanella Netto 2024-02-12 18:34 ` Askar Safin 2 siblings, 0 replies; 23+ messages in thread From: Adhemerval Zanella Netto @ 2024-02-12 17:55 UTC (permalink / raw) To: libc-alpha On 12/02/24 14:25, Zack Weinberg wrote: > On Mon, Feb 12, 2024, at 11:16 AM, Askar Safin wrote: >> ---- On Mon, 12 Feb 2024 18:44:31 +0400 Rich Felker wrote --- >> > Yes, there are a very small number of such syscalls -- getuid and >> > getgid are the only relevant ones AFAICT -- but the author of this >> > proposal is missing the point >> >> Okay, I declare defeat > > I have a question for you: Do glibc's existing getuid() and getgid() > functions correctly handle IDs in the [-4095, -1] range (perhaps better > described as the [4294963201, 4294967295] range) ? It appears to me > from binary code inspection that they do -- here's the assembly dump of > getuid() on x86-64: > > (gdb) disas getuid > Dump of assembler code for function __GI_getuid: > 0x00000000000cf940 <+0>: mov $0x66,%eax > 0x00000000000cf945 <+5>: syscall > 0x00000000000cf947 <+7>: ret > End of assembler dump. Afaiu this is not an issue for x86_64, or any other 64-bit architecture, because uid_t/gid_t are exported as an uint32_t (__UID_T_TYPE/__U32_TYPE), and the invalid return valid are in the range of [-4096UL,-1UL]. > > But I am not having any luck figuring out what bit of glibc's *source* > code tells the syscall stub generator not to emit the code to check for > error returns for these syscalls, so it's plausible to me that there is > a bug in here somewhere, possibly only on lesser-used architectures. If > you know of a case where we get this wrong, please tell us about it so > we can fix it. > > zw ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] Add public function syscall_no_errno 2024-02-12 17:25 ` Zack Weinberg 2024-02-12 17:43 ` Andreas Schwab 2024-02-12 17:55 ` Adhemerval Zanella Netto @ 2024-02-12 18:34 ` Askar Safin 2 siblings, 0 replies; 23+ messages in thread From: Askar Safin @ 2024-02-12 18:34 UTC (permalink / raw) To: Zack Weinberg; +Cc: GNU libc development ---- On Mon, 12 Feb 2024 21:25:27 +0400 Zack Weinberg wrote --- > I have a question for you: Do glibc's existing getuid() and getgid() > functions correctly handle IDs in the [-4095, -1] range (perhaps better > described as the [4294963201, 4294967295] range) ? Yes. > here's the assembly dump of > getuid() on x86-64: Even "incorrect" getuid implementation will work correctly on x86_64, because uids are 32 bit on Linux. Whole this problem matters for 32-bit architectures, not 64-bit ones. > But I am not having any luck figuring out what bit of glibc's *source* > code tells the syscall stub generator not to emit the code to check for > error returns for these syscalls, so it's plausible to me that there is > a bug in here somewhere, possibly only on lesser-used architectures. If > you know of a case where we get this wrong, please tell us about it so > we can fix it. getuid is defined in ./sysdeps/unix/sysv/linux/i386/syscalls.list (and similar files). In 4th column we see "E". This means that getuid never fails and we should pass raw syscall result to userspace. "E" gets processed here: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/make-syscalls.sh;h=4f6c3490a20bc3eb34f11f1e7aab0ddec7e82e5d;hb=155bb9d036646138348fee0ac045de601811e0c5#l169 Then here: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/make-syscalls.sh;h=4f6c3490a20bc3eb34f11f1e7aab0ddec7e82e5d;hb=155bb9d036646138348fee0ac045de601811e0c5#l273 -- Askar Safin https://types.pl/@safinaskar ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-01 20:16 ` dalias 2024-02-01 20:57 ` Adhemerval Zanella Netto @ 2024-02-07 0:59 ` Askar Safin 2024-02-07 20:59 ` dalias 1 sibling, 1 reply; 23+ messages in thread From: Askar Safin @ 2024-02-07 0:59 UTC (permalink / raw) To: dalias, Adhemerval Zanella Netto; +Cc: libc-alpha, carlos Hi, Rich and Adhemerval! ---- On Fri, 02 Feb 2024 00:16:26 +0400 dalias wrote --- > OK, but this falls under "poking around behind libc's back". Function "syscall" exists in glibc. So it is assumed to be useful. Thus it is okay to have "syscall_no_errno", too. "syscall" in its current form has a problem: you cannot correctly call SYS_getuid32. Thus there is need for "syscall_no_errno". So I will write next version of my patch. I hope in several days, when I have time. "syscall_no_errno" will be simple wrapper for "INTERNAL_SYSCALL_NCS_CALL". > Well that's not something syscall() gives you and it's not something > syscall_no_errno() would reliably give you either unless it was > specifically documented to be callable from such a context. If that's > what you want, maybe that's what should be discussed. I did some research. I have read all places where glibc calls "clone". And I see that in all these places if CLONE_VM specified, then CLONE_SETTLS or CLONE_VFORK is specified. In fact, there is 2 places only, where glibc calls clone (in Linux x86_64). One is implementation of pthread_create. We pass CLONE_VM and CLONE_SETTLS. Thus (as well as I understand) TLS is set up in child right from the beginning. There is no time gap, when TLS is not initialized yet. Second place is implementation of posix_spawn. We pass CLONE_VM and CLONE_VFORK. CLONE_VFORK means that parent is suspended, and thus it is okay to access its TLS. Thus glibc absolutely always (even internally!) maintains invariant "TLS is safe to access". I. e. glibc itself does not need a way to perform syscalls when TLS is not set up. Thus if I want syscall_no_errno to provide such guarantee, this will be absolutely unique guarantee, which is not needed even by glibc authors themselves. So I think this will be very hard to provide it, and benefits will be small. Yes, small time gap when TLS is not initialized, still exists. Before "main". But in this case we have one thread only, so everything is simple. For all these reasons I think that guarantee "you may call syscall_no_errno even after clone(CLONE_VM) without CLONE_VFORK and without CLONE_SETTLS" should not be provided. (Correct me if I wrong.) So I go back to my original proposal: add function, which will be able to call directly syscalls, such as SYS_getuid32. Adhemerval Zanella Netto: > There is another potential issue where you have multiple syscall > with slight different kABI In fact my original use case is so: I want to parse true kernel ABI from files /sys/kernel/debug/tracing/events/syscalls/sys_enter_*/format and then generate a library based on the ABI. Such library will provide syscall wrappers with correct types. These wrappers will call functions "syscall" and "syscall_no_errno". (In fact, this will be Rust library, not C one, but I don't think this is important for our discussion. You may say: "Then why you want to add syscall_no_errno to upstream glibc?" Well, because I want it to be available to everyone. To Rust programmers, to C programmers and to everyone else. Without the need to write assembly.) So, I will read proper kernel ABI from /sys/kernel/..., so I will get ABI right. > at least for glibc, where the user > exported argument does not really match the kernel (stat/fstat/etc.). I will use Linux headers, so all will be okay. (Well, correction: I will use Rust's crate "linux-raw-sys", which is based on Linux headers.) You may say: "Well, I still think you should find Rust library, which does what you want, and stop bothering upstream glibc". I will answer: I don't trust Rust libs! Yes, there exist multiple Rust crates, which provide something similar to syscall_no_errno. They are implemented using hand-coded assembly. Why should I trust that they got this assembly correct? On the other hand, glibc already has high quality INTERNAL_SYSCALL_NCS_CALL, which I trust. It is more likely to be correct, than all these buggy Rust crates. We just need to export it. So I propose to export simple wrapper for INTERNAL_SYSCALL_NCS_CALL called "syscall_no_errno". And everybody will use it. C devs, Rust devs, etc. Big benefits for everybody. For low cost on glibc side. Also, I have a question. It seems that function "syscall" uses TLS and nothing else. This means that it is okay to call it in a child, created using "clone", assuming that one of these holds: - We didn't specify CLONE_VM - We specified CLONE_VM and CLONE_VFORK (thus parent is suspended and it is okay to use its TLS) So may I also write a patch for documentation, which will document this guarantee? It surely already holds, because glibc uses it in implementation of posix_spawn. I just want to document it, and this will mean that now it will hold in the future. Moreover, such guarantee holds if we call clone using this code without specifiying new stack: if (syscall(SYS_clone, ...) == 0){ /* we are in child */ } ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-07 0:59 ` [PATCH, RFC] " Askar Safin @ 2024-02-07 20:59 ` dalias 2024-02-08 17:08 ` Askar Safin 0 siblings, 1 reply; 23+ messages in thread From: dalias @ 2024-02-07 20:59 UTC (permalink / raw) To: Askar Safin; +Cc: Adhemerval Zanella Netto, libc-alpha, carlos On Wed, Feb 07, 2024 at 04:59:54AM +0400, Askar Safin wrote: > Hi, Rich and Adhemerval! > > ---- On Fri, 02 Feb 2024 00:16:26 +0400 dalias wrote --- > > OK, but this falls under "poking around behind libc's back". > > Function "syscall" exists in glibc. So it is assumed to be useful. > Thus it is okay to have "syscall_no_errno", too. "syscall" in > its current form has a problem: you cannot correctly call > SYS_getuid32. Thus there is need for "syscall_no_errno". > > So I will write next version of my patch. I hope in several days, > when I have time. > "syscall_no_errno" will be simple wrapper for "INTERNAL_SYSCALL_NCS_CALL". > > > Well that's not something syscall() gives you and it's not something > > syscall_no_errno() would reliably give you either unless it was > > specifically documented to be callable from such a context. If that's > > what you want, maybe that's what should be discussed. > > I did some research. I have read all places where glibc calls "clone". > And I see that in all these places if CLONE_VM specified, then > CLONE_SETTLS or CLONE_VFORK is specified. > > In fact, there is 2 places only, where glibc calls clone (in Linux x86_64). > > One is implementation of pthread_create. We pass CLONE_VM and > CLONE_SETTLS. Thus (as well as I understand) TLS is set up > in child right from the beginning. > There is no time gap, when TLS is not initialized yet. > > Second place is implementation of posix_spawn. We pass CLONE_VM > and CLONE_VFORK. CLONE_VFORK means that parent is suspended, > and thus it is okay to access its TLS. > > Thus glibc absolutely always (even internally!) maintains invariant > "TLS is safe to access". I. e. glibc itself does not need a way to perform > syscalls when TLS is not set up. You're missing the point. Of course glibc maintains that invariant because it's providing a consistent platform to applications. If you have application code that uses clone() itself, it may not be meeting those invariants necessary to be able to call into libc. > In fact my original use case is so: I want to parse true kernel ABI > from files /sys/kernel/debug/tracing/events/syscalls/sys_enter_*/format > and then generate a library based on the ABI. > > Such library will provide syscall wrappers with correct types. These > wrappers will call functions "syscall" and "syscall_no_errno". > > (In fact, this will be Rust library, not C one, but I don't think > this is important for our discussion. You may say: "Then why > you want to add syscall_no_errno to upstream glibc?" > Well, because I want it to be available to everyone. To Rust > programmers, to C programmers and to everyone else. > Without the need to write assembly.) > > So, I will read proper kernel ABI from /sys/kernel/..., so > I will get ABI right. Can you clarify *why* you want to do that? Making raw syscalls like this is ill-advised and *will* run into mismatched ABI for certain types (where the kernel and user types differ), poor compatibility with kernel versions that aren't the same you expected, time64 issues on 32-bit archs, etc. Based on our conversations in this thread, I do not think you're prepared to handle all that right. It most certainly cannot be handled in an automated way by parsing the data you have in mind; doing it right requires knowing semantic relationships between syscalls. It sounds like you plan to hand Rust programmers a big footgun. Rich ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-07 20:59 ` dalias @ 2024-02-08 17:08 ` Askar Safin 0 siblings, 0 replies; 23+ messages in thread From: Askar Safin @ 2024-02-08 17:08 UTC (permalink / raw) To: dalias; +Cc: Adhemerval Zanella Netto, libc-alpha, carlos ---- On Thu, 08 Feb 2024 00:59:02 +0400 dalias wrote --- > You're missing the point. Of course glibc maintains that invariant > because it's providing a consistent platform to applications. If you > have application code that uses clone() itself, it may not be meeting > those invariants necessary to be able to call into libc. Let me try to explain in other way. I tried to understand what guarantees of "syscall" and "syscall_no_errno" functions will be easy for glibc maintainers to provide, and what will be hard. Let's begin with guarantee "it is okay to call 'syscall_no_errno', when TLS is possibly not initialized properly, for example in child created by clone(CLONE_VM)". Such guarantee will be hard to provide, because it seems that it is not provided currently. I. e. additional work will be needed to provide it. It seems to be not provided, because glibc nearly never uses it. glibc seems to never use it, because in glibc TLS is nearly always initialized. Now let's consider another possible guarantee "it is okay to call 'syscall' and 'syscall_no_errno' in child created by clone(CLONE_VM | CLONE_VFORK)". It will be easy to provide, because (as of current master) it is already provided, but not documented. I see that it is provided, because I see that glibc internally uses this guarantee. glibc uses it in spawn implementation. glibc creates child in posix_spawn using CLONE_VM | CLONE_VFORK. And then issues syscalls using something very close to "syscall". So it is very easy to provide such guarantee. We just need to document it. If it is broken, glibc developers will notice this, because they depend on this guarantee in spawn implementation. So I don't propose to add that guarantee about TLS. But I do propose to add (i. e. to document) guarantee about CLONE_VM | CLONE_VFORK. > Can you clarify *why* you want to do that? As I already told I want to write that Rust library. I don't want to publish it. Just for personal use. I need it to expirement with Linux. I. e. no any serious use. Just a playground. I want to have full control over what syscalls I issue. And I want to send syscall_no_errno to upstream glibc (and ideally to upstream musl, too), because other developers may have similar needs. I. e. because they sometimes want to have full control over syscalls they issue. Currently, if someone wants to issue syscall, such as SYS_getuid32 on i386, they must either use assembly (which is hard to do right), either use some third-party library. But I don't trust third-party libraries, as I already told in this thread. So I suggest other people not to use them. For example, there exists https://chromium.googlesource.com/linux-syscall-support/ , which is intended to be way to make raw syscalls. But as I said previously, it doesn't provide way to call getuid, and also it had a bug, which was not fixed until *I* noticed it. So I propose to export battle-tested trusted glibc implementation as a public symbol. And everyone will be able to use it. > Making raw syscalls like > this is ill-advised and *will* run into mismatched ABI for certain > types (where the kernel and user types differ) It will not, because I will use Rust crate "linux-raw-sys", which is based on Linux uapi headers, i. e. headers from dir "include/uapi" from Linux source tree. > poor compatibility > with kernel versions that aren't the same you expected What you mean? Newer kernel versions are ABI compatible with older ones. And yes, if you write program for newer kernel and try to run it on older, you may get some issues. But the same applies to usual programs written with glibc and musl. Yes, glibc and musl know how to fail back to older syscalls. So, what? I can manually write such fail back code if needed. Again: I'm aware of all these issues. Of course, I know that issuing syscalls directly is harder than using libc wrappers. > time64 issues > on 32-bit archs, etc. As I said, I will use prototypes parsed from /sys/... with types got from Linux uapi headers. This will remove all time64 and similar problems. Yes, this will mean that I will have to manually write fail back code, i. e. "try time64, if it fails, then do time32". But I'm aware about this. > It most certainly cannot be handled > in an automated way by parsing the data you have in mind As I said, it *can* be done it automated way. Just use prototypes from /sys/... and type definitions from uapi headers. Feel free to steal this idea and use it in musl. :) Also you may consider this project https://syscalls.mebeim.net/ instead of parsing /sys/... . They get prototypes from kernel ELF binary. And, yes, I know that when I see, say, "pid_t" in /sys/... , this really means __kernel_pid_t from uapi headers. (Also I plan to parse files from strace project, such as this: https://github.com/strace/strace/blob/eb6014c510d663938db331fef5ac4ef78fdcf583/src/linux/i386/syscallent.h . Because they mark functions, which cannot fail, as "NF". So I will know when I should check errors, and when not.) Of course, this process will produce not-so-usable functions. So I then will manually write for them wrappers. For example, this process may automatically produce this Rust prototype for "write": fn write(fd: c_int, buf: *const c_void, len: usize) -> Result<isize, Errno> And then I will futher manually wrap it and will make something like this: fn write(fd: c_int, buf: &[u8]) -> Result<usize, Errno> And of course, all these functions will be marked as "unsafe". I have no plans for creating safe (in Rust sense) interface for Linux syscalls. I do not plan to publish code, but if you want, I can show it to you, when it is ready. > doing it > right requires knowing semantic relationships between syscalls. Knowing semantic relationship may be required if I want to add extra type data not present in /sys/... . For example if I want to have separated type for "int", which means file descriptor, and for other "int"s. Yes, I know that this cannot be done in automated way. Yes, I know that generated code will simply have "int"s everywhere and I will have to write manual wrapper if I want something more type-safe. Also semantic relationship may be needed if I want to present safe interface (in Rust sense). I have no such plans. -- Askar Safin https://types.pl/@safinaskar ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-01-28 16:39 [PATCH, RFC] Add public function syscall_no_errno Askar Safin 2024-02-01 17:53 ` Adhemerval Zanella Netto @ 2024-02-07 1:57 ` Mike Frysinger 2024-02-07 12:55 ` Askar Safin 1 sibling, 1 reply; 23+ messages in thread From: Mike Frysinger @ 2024-02-07 1:57 UTC (permalink / raw) To: Askar Safin; +Cc: libc-alpha [-- Attachment #1: Type: text/plain, Size: 98 bytes --] sounds like you want this project: https://chromium.googlesource.com/linux-syscall-support/ -mike [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH, RFC] Add public function syscall_no_errno 2024-02-07 1:57 ` Mike Frysinger @ 2024-02-07 12:55 ` Askar Safin 0 siblings, 0 replies; 23+ messages in thread From: Askar Safin @ 2024-02-07 12:55 UTC (permalink / raw) To: Mike Frysinger; +Cc: libc-alpha, dalias, adhemervalzanella, Carlos ---- On Wed, 07 Feb 2024 05:57:49 +0400 Mike Frysinger wrote --- > sounds like you want this project: > https://chromium.googlesource.com/linux-syscall-support/ This project has exactly the problem I'm talking abort! Exactly problem I'm trying to fix using syscall_no_errno! linux-syscall-support always unconditionally checks syscall result and sets errno based on it: https://chromium.googlesource.com/linux-syscall-support/+/ed31caa60f20a4f6569883b2d752ef7522de51e0/linux_syscall_support.h#2175 You can verify that this happens in all code paths by carefully reading the source. Fortunately, the project doesn't provide "getuid" at all. I think this is because authors aware of the problem. Also, the project is simply buggy. Look at this (my!) commit: https://chromium.googlesource.com/linux-syscall-support/+/e1e7b0ad8ee99a875b272c8e33e308472e897660 If I didn't notice this bug and didn't fix it, the bug would stay forever! So, after my expirence with this project I conclude: I don't trust such projects. I. e. small project claiming to support performing direct syscalls. I don't trust C libraries for this purpose and I don't trust Rust libraries for this purpose. The only libraries I trust are glibc and musl. But both don't export anything like syscall_no_errno. And this is what I'm trying to change. I'm aware of existance of "nolibc" project inside Linux source tree. But (based on my expirence with linux-syscall-support) I don't trust it, either. But... well, I *will* trust some of these projects if I carefully read sources. So, yes, I can fix problem for me personally: just carefully read sources of linux-syscall-support and use it! Or some similar C or Rust library. Moreover: my task is even simpler! The only architectures I want to support in my project are x86_64 and i386. So I can simply copy needed assembly from glibc sources and all will be done! But I'm not trying to fix the problem for me personally. I want to fix it for everyone! I want anyone to be able just to use universally available trusted function from glibc. Without the need for assembly or third party projects such as linux-syscall-support. glibc already provides "syscall", thus it should provide "syscall_no_errno", too! Askar Safin https://types.pl/@safinaskar ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2024-02-13 11:57 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-01-28 16:39 [PATCH, RFC] Add public function syscall_no_errno Askar Safin 2024-02-01 17:53 ` Adhemerval Zanella Netto 2024-02-01 18:18 ` Rich Felker 2024-02-01 19:32 ` Askar Safin 2024-02-01 20:16 ` dalias 2024-02-01 20:57 ` Adhemerval Zanella Netto 2024-02-08 15:02 ` [PATCH v2] " Askar Safin 2024-02-08 17:48 ` Szabolcs Nagy 2024-02-12 14:24 ` Florian Weimer 2024-02-12 14:44 ` Rich Felker 2024-02-12 16:16 ` Askar Safin 2024-02-12 17:25 ` Zack Weinberg 2024-02-12 17:43 ` Andreas Schwab 2024-02-12 18:22 ` Zack Weinberg 2024-02-13 9:10 ` Andreas Schwab 2024-02-13 11:57 ` Adhemerval Zanella Netto 2024-02-12 17:55 ` Adhemerval Zanella Netto 2024-02-12 18:34 ` Askar Safin 2024-02-07 0:59 ` [PATCH, RFC] " Askar Safin 2024-02-07 20:59 ` dalias 2024-02-08 17:08 ` Askar Safin 2024-02-07 1:57 ` Mike Frysinger 2024-02-07 12:55 ` Askar Safin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).