[v6,3/3] nptl: Use direct syscall numbers in setxid

Message ID 20230424150353.1469397-4-josimmon@redhat.com
State Rejected
Headers
Series x86_64: aarch64: Set call number just before syscall |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Joe Simmons-Talbott April 24, 2023, 3:03 p.m. UTC
  Make all internal glibc syscalls use direct compile time numeric values
rather than variables.  This will make the syscall number easier to
identify during static analysis.
---
 nptl/nptl_setxid.c | 136 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 132 insertions(+), 4 deletions(-)
  

Comments

Xi Ruoyao April 24, 2023, 3:17 p.m. UTC | #1
On Mon, 2023-04-24 at 11:03 -0400, Joe Simmons-Talbott via Libc-alpha
wrote:
> Make all internal glibc syscalls use direct compile time numeric values
> rather than variables.  This will make the syscall number easier to
> identify during static analysis.

This is making the code much more bloated and slower.  Do we really want
to make everyone's system slower for some debug tools?

> ---
>  nptl/nptl_setxid.c | 136 +++++++++++++++++++++++++++++++++++++++++++-
> -
>  1 file changed, 132 insertions(+), 4 deletions(-)
> 
> diff --git a/nptl/nptl_setxid.c b/nptl/nptl_setxid.c
> index 4bfcfe4188..797015def1 100644
> --- a/nptl/nptl_setxid.c
> +++ b/nptl/nptl_setxid.c
> @@ -66,8 +66,72 @@ __nptl_setxid_sighandler (int sig, siginfo_t *si,
> void *ctx)
>        || si->si_code != SI_TKILL)
>      return;
>  
> -  result = INTERNAL_SYSCALL_NCS (xidcmd->syscall_no, 3, xidcmd-
> >id[0],
> -                                xidcmd->id[1], xidcmd->id[2]);
> +  switch(xidcmd->syscall_no)
> +  {
> +#ifdef __NR_setuid32
> +    case __NR_setuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid32, 3, xidcmd->id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setuid32 */
> +    case __NR_setuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid, 3, xidcmd->id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setreuid32
> +    case __NR_setreuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid32, 3, xidcmd-
> >id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setreuid32 */
> +    case __NR_setreuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid, 3, xidcmd->id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setresgid32
> +    case __NR_setresgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid32, 3, xidcmd-
> >id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setresgid32 */
> +    case __NR_setresgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid, 3, xidcmd-
> >id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setregid32
> +    case __NR_setregid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid32, 3, xidcmd-
> >id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setregid32 */
> +    case __NR_setregid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid, 3, xidcmd->id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setgid32
> +    case __NR_setgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid32, 3, xidcmd->id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setgid32 */
> +    case __NR_setgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid, 3, xidcmd->id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setgroups32
> +    case __NR_setgroups32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups32, 3, xidcmd-
> >id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setgroups32 */
> +    case __NR_setgroups:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups, 3, xidcmd-
> >id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +   default:
> +      result = INTERNAL_SYSCALL_NCS (xidcmd->syscall_no, 3, xidcmd-
> >id[0],
> +                                    xidcmd->id[1], xidcmd->id[2]);
> +  }
>    int error = 0;
>    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result)))
>      error = INTERNAL_SYSCALL_ERRNO (result);
> @@ -262,8 +326,72 @@ __nptl_setxid (struct xid_command *cmdp)
>  
>    /* This must be last, otherwise the current thread might not have
>       permissions to send SIGSETXID syscall to the other threads.  */
> -  result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, 3,
> -                                 cmdp->id[0], cmdp->id[1], cmdp-
> >id[2]);
> +  switch(cmdp->syscall_no)
> +  {
> +#ifdef __NR_setuid32
> +    case __NR_setuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid32, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setuid32 */
> +    case __NR_setuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setreuid32
> +    case __NR_setreuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid32, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setreuid32 */
> +    case __NR_setreuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setresgid32
> +    case __NR_setresgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid32, 3, cmdp-
> >id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setresgid32 */
> +    case __NR_setresgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setregid32
> +    case __NR_setregid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid32, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setregid32 */
> +    case __NR_setregid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setgid32
> +    case __NR_setgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid32, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setgid32 */
> +    case __NR_setgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setgroups32
> +    case __NR_setgroups32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups32, 3, cmdp-
> >id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setgroups32 */
> +    case __NR_setgroups:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups, 3, cmdp->id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +      break;
> +   default:
> +      result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, 3, cmdp-
> >id[0],
> +                                    cmdp->id[1], cmdp->id[2]);
> +  }
>    int error = 0;
>    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result)))
>      {
  
Szabolcs Nagy April 26, 2023, 9:46 a.m. UTC | #2
The 04/24/2023 23:17, Xi Ruoyao via Libc-alpha wrote:
> On Mon, 2023-04-24 at 11:03 -0400, Joe Simmons-Talbott via Libc-alpha
> wrote:
> > Make all internal glibc syscalls use direct compile time numeric values
> > rather than variables.  This will make the syscall number easier to
> > identify during static analysis.
> 
> This is making the code much more bloated and slower.  Do we really want
> to make everyone's system slower for some debug tools?

the switch statement overhead is many orders of magnitude smaller
than sending a signal to a thread and executing a syscall there
(which is where the switch statement happens).

i dont know if the change is justified, but from a target port
perspective it's useful if inline syscalls are guaranteed to use
a syscall name that can expand to an integer constant or named
function.
  
Cristian Rodríguez April 26, 2023, 12:39 p.m. UTC | #3
On Mon, Apr 24, 2023 at 11:17 AM Xi Ruoyao via Libc-alpha <
libc-alpha@sourceware.org> wrote:

> On Mon, 2023-04-24 at 11:03 -0400, Joe Simmons-Talbott via Libc-alpha
> wrote:
> > Make all internal glibc syscalls use direct compile time numeric values
> > rather than variables.  This will make the syscall number easier to
> > identify during static analysis.
>
> This is making the code much more bloated and slower.  Do we really want
> to make everyone's system slower for some debug tools?
>
>
The switch statement will add little overhead. my concern with this is that
it looks ugly and error prone for no other reason than help some
limited debug tool.. there must be a nicer, less verbose  way to get what
you want..
  
Szabolcs Nagy April 26, 2023, 1:24 p.m. UTC | #4
The 04/26/2023 08:39, Cristian Rodríguez via Libc-alpha wrote:
> On Mon, Apr 24, 2023 at 11:17 AM Xi Ruoyao via Libc-alpha <
> libc-alpha@sourceware.org> wrote:
> 
> > On Mon, 2023-04-24 at 11:03 -0400, Joe Simmons-Talbott via Libc-alpha
> > wrote:
> > > Make all internal glibc syscalls use direct compile time numeric values
> > > rather than variables.  This will make the syscall number easier to
> > > identify during static analysis.
> >
> > This is making the code much more bloated and slower.  Do we really want
> > to make everyone's system slower for some debug tools?
> >
> >
> The switch statement will add little overhead. my concern with this is that
> it looks ugly and error prone for no other reason than help some
> limited debug tool.. there must be a nicer, less verbose  way to get what
> you want..

it allows glibc to drop the INTERNAL_SYSCALL_NCS code.
which can clean up some target code.
  
Florian Weimer April 28, 2023, 10:52 a.m. UTC | #5
* Szabolcs Nagy via Libc-alpha:

> The 04/24/2023 23:17, Xi Ruoyao via Libc-alpha wrote:
>> On Mon, 2023-04-24 at 11:03 -0400, Joe Simmons-Talbott via Libc-alpha
>> wrote:
>> > Make all internal glibc syscalls use direct compile time numeric values
>> > rather than variables.  This will make the syscall number easier to
>> > identify during static analysis.
>> 
>> This is making the code much more bloated and slower.  Do we really want
>> to make everyone's system slower for some debug tools?
>
> the switch statement overhead is many orders of magnitude smaller
> than sending a signal to a thread and executing a syscall there
> (which is where the switch statement happens).
>
> i dont know if the change is justified, but from a target port
> perspective it's useful if inline syscalls are guaranteed to use
> a syscall name that can expand to an integer constant or named
> function.

If the only place we have dynamic system calls in glibc is the syscall
function, we can add a check there to block system calls using it unless
the symbol has been bound before.  Together with BTI/IBT, this would
prevent issuing arbitrary system calls using machine code fragments from
glibc.

Not sure if that is important consideration.  If it does not matter, we
could change the pthread code to call an internal alias of the syscall
function instead.

Thanks,
Florian
  
Joe Simmons-Talbott May 25, 2023, 6:07 p.m. UTC | #6
ping.

Thanks,
Joe

On Mon, Apr 24, 2023 at 11:03:53AM -0400, Joe Simmons-Talbott wrote:
> Make all internal glibc syscalls use direct compile time numeric values
> rather than variables.  This will make the syscall number easier to
> identify during static analysis.
> ---
>  nptl/nptl_setxid.c | 136 +++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 132 insertions(+), 4 deletions(-)
> 
> diff --git a/nptl/nptl_setxid.c b/nptl/nptl_setxid.c
> index 4bfcfe4188..797015def1 100644
> --- a/nptl/nptl_setxid.c
> +++ b/nptl/nptl_setxid.c
> @@ -66,8 +66,72 @@ __nptl_setxid_sighandler (int sig, siginfo_t *si, void *ctx)
>        || si->si_code != SI_TKILL)
>      return;
>  
> -  result = INTERNAL_SYSCALL_NCS (xidcmd->syscall_no, 3, xidcmd->id[0],
> -				 xidcmd->id[1], xidcmd->id[2]);
> +  switch(xidcmd->syscall_no)
> +  {
> +#ifdef __NR_setuid32
> +    case __NR_setuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid32, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setuid32 */
> +    case __NR_setuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setreuid32
> +    case __NR_setreuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid32, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setreuid32 */
> +    case __NR_setreuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setresgid32
> +    case __NR_setresgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid32, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setresgid32 */
> +    case __NR_setresgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setregid32
> +    case __NR_setregid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid32, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setregid32 */
> +    case __NR_setregid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setgid32
> +    case __NR_setgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid32, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setgid32 */
> +    case __NR_setgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#ifdef __NR_setgroups32
> +    case __NR_setgroups32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups32, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +#endif /* __NR_setgroups32 */
> +    case __NR_setgroups:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +      break;
> +   default:
> +      result = INTERNAL_SYSCALL_NCS (xidcmd->syscall_no, 3, xidcmd->id[0],
> +				     xidcmd->id[1], xidcmd->id[2]);
> +  }
>    int error = 0;
>    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result)))
>      error = INTERNAL_SYSCALL_ERRNO (result);
> @@ -262,8 +326,72 @@ __nptl_setxid (struct xid_command *cmdp)
>  
>    /* This must be last, otherwise the current thread might not have
>       permissions to send SIGSETXID syscall to the other threads.  */
> -  result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, 3,
> -                                 cmdp->id[0], cmdp->id[1], cmdp->id[2]);
> +  switch(cmdp->syscall_no)
> +  {
> +#ifdef __NR_setuid32
> +    case __NR_setuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid32, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setuid32 */
> +    case __NR_setuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setuid, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setreuid32
> +    case __NR_setreuid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid32, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setreuid32 */
> +    case __NR_setreuid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setreuid, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setresgid32
> +    case __NR_setresgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid32, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setresgid32 */
> +    case __NR_setresgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setresgid, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setregid32
> +    case __NR_setregid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid32, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setregid32 */
> +    case __NR_setregid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setregid, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setgid32
> +    case __NR_setgid32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid32, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setgid32 */
> +    case __NR_setgid:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgid, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#ifdef __NR_setgroups32
> +    case __NR_setgroups32:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups32, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +#endif /* __NR_setgroups32 */
> +    case __NR_setgroups:
> +      result = INTERNAL_SYSCALL_NCS (__NR_setgroups, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +      break;
> +   default:
> +      result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, 3, cmdp->id[0],
> +				     cmdp->id[1], cmdp->id[2]);
> +  }
>    int error = 0;
>    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result)))
>      {
> -- 
> 2.39.2
>
  

Patch

diff --git a/nptl/nptl_setxid.c b/nptl/nptl_setxid.c
index 4bfcfe4188..797015def1 100644
--- a/nptl/nptl_setxid.c
+++ b/nptl/nptl_setxid.c
@@ -66,8 +66,72 @@  __nptl_setxid_sighandler (int sig, siginfo_t *si, void *ctx)
       || si->si_code != SI_TKILL)
     return;
 
-  result = INTERNAL_SYSCALL_NCS (xidcmd->syscall_no, 3, xidcmd->id[0],
-				 xidcmd->id[1], xidcmd->id[2]);
+  switch(xidcmd->syscall_no)
+  {
+#ifdef __NR_setuid32
+    case __NR_setuid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setuid32, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#endif /* __NR_setuid32 */
+    case __NR_setuid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setuid, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#ifdef __NR_setreuid32
+    case __NR_setreuid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setreuid32, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#endif /* __NR_setreuid32 */
+    case __NR_setreuid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setreuid, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#ifdef __NR_setresgid32
+    case __NR_setresgid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setresgid32, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#endif /* __NR_setresgid32 */
+    case __NR_setresgid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setresgid, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#ifdef __NR_setregid32
+    case __NR_setregid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setregid32, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#endif /* __NR_setregid32 */
+    case __NR_setregid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setregid, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#ifdef __NR_setgid32
+    case __NR_setgid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgid32, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#endif /* __NR_setgid32 */
+    case __NR_setgid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgid, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#ifdef __NR_setgroups32
+    case __NR_setgroups32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgroups32, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+#endif /* __NR_setgroups32 */
+    case __NR_setgroups:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgroups, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+      break;
+   default:
+      result = INTERNAL_SYSCALL_NCS (xidcmd->syscall_no, 3, xidcmd->id[0],
+				     xidcmd->id[1], xidcmd->id[2]);
+  }
   int error = 0;
   if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result)))
     error = INTERNAL_SYSCALL_ERRNO (result);
@@ -262,8 +326,72 @@  __nptl_setxid (struct xid_command *cmdp)
 
   /* This must be last, otherwise the current thread might not have
      permissions to send SIGSETXID syscall to the other threads.  */
-  result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, 3,
-                                 cmdp->id[0], cmdp->id[1], cmdp->id[2]);
+  switch(cmdp->syscall_no)
+  {
+#ifdef __NR_setuid32
+    case __NR_setuid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setuid32, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#endif /* __NR_setuid32 */
+    case __NR_setuid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setuid, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#ifdef __NR_setreuid32
+    case __NR_setreuid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setreuid32, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#endif /* __NR_setreuid32 */
+    case __NR_setreuid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setreuid, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#ifdef __NR_setresgid32
+    case __NR_setresgid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setresgid32, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#endif /* __NR_setresgid32 */
+    case __NR_setresgid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setresgid, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#ifdef __NR_setregid32
+    case __NR_setregid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setregid32, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#endif /* __NR_setregid32 */
+    case __NR_setregid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setregid, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#ifdef __NR_setgid32
+    case __NR_setgid32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgid32, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#endif /* __NR_setgid32 */
+    case __NR_setgid:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgid, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#ifdef __NR_setgroups32
+    case __NR_setgroups32:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgroups32, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+#endif /* __NR_setgroups32 */
+    case __NR_setgroups:
+      result = INTERNAL_SYSCALL_NCS (__NR_setgroups, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+      break;
+   default:
+      result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, 3, cmdp->id[0],
+				     cmdp->id[1], cmdp->id[2]);
+  }
   int error = 0;
   if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result)))
     {