NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/59608: compat_linux should ignore LINUX_CLONE_SYSVSEM and assume stack grows down



>Number:         59608
>Category:       kern
>Synopsis:       compat_linux should ignore LINUX_CLONE_SYSVSEM and assume stack grows down
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 25 19:20:00 +0000 2025
>Originator:     csaba mate
>Release:        11.0-beta
>Organization:
freertr.org
>Environment:
NetBSD  11.0_BETA NetBSD 11.0_BETA (GENERIC) #0: Mon Aug 25 20:56:36 CEST 2025  mc36@noti:/home/mc36/obj/sys/arch/amd64/compile/GENERIC amd64

>Description:
running a simple 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

void doNativeLoop() {
    printf("running\n");
}

void main() {
    pthread_t threadUdp;
    printf("start\n");
    if (pthread_create(&threadUdp, NULL, (void*) & doNativeLoop, NULL)) printf("error\n");
    printf("done\n");
    sleep(1);
    printf("exit\n");
}


results in a non-running thread on the latest netbsd-11-beta + latest glibc.


>How-To-Repeat:
compile the above c code and run it with glibc 2.42 and you'll get "error" and not "running"

in glibc source (clone-internal.c) i see this:

int
__clone_internal_fallback (struct clone_args *cl_args,
<------><------><------>   int (*func) (void *arg), void *arg)
{
  /* Map clone3 arguments to clone arguments.  NB: No need to check
     invalid clone3 specific bits in flags nor exit_signal since this
     is an internal function.  */
  int flags = cl_args->flags | cl_args->exit_signal;
  void *stack = cast_to_pointer (cl_args->stack);
  int ret;

#if !_STACK_GROWS_DOWN && !_STACK_GROWS_UP
# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
#endif

#if _STACK_GROWS_DOWN
  stack += cl_args->stack_size;
#endif
  ret = __clone (func, stack, flags, arg,
<------><------> cast_to_pointer (cl_args->parent_tid),
<------><------> cast_to_pointer (cl_args->tls),
<------><------> cast_to_pointer (cl_args->child_tid));
  return ret;
}


thats how i came up with the below stack arithmetic...

they set stack_grows_down everywhere except hppa, which is not a target of compat-linux at the time of writing...

>Fix:
--- src.bad/sys/compat/linux/common/linux_sched.h	2024-09-28 21:35:56.000000000 +0200
+++ src.ok/sys/compat/linux/common/linux_sched.h	2025-08-25 20:48:10.531115738 +0200
@@ -85,7 +85,7 @@
     LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
     LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD | LINUX_CLONE_VFORK | \
     LINUX_CLONE_PARENT_SETTID | LINUX_CLONE_CHILD_CLEARTID | \
-    LINUX_CLONE_CHILD_SETTID | LINUX_CLONE_SETTLS)
+    LINUX_CLONE_CHILD_SETTID | LINUX_CLONE_SETTLS | LINUX_CLONE_SYSVSEM)
 
 #define LINUX_CLONE_UNIMPLEMENTED_FLAGS ( \
     LINUX_CLONE_NEWNS | LINUX_CLONE_NEWUTS | LINUX_CLONE_NEWIPC | \


--- src.bad/sys/compat/linux/common/linux_sched.c	2024-10-03 14:56:49.000000000 +0200
+++ src.ok/sys/compat/linux/common/linux_sched.c	2025-08-25 21:01:34.107972657 +0200
@@ -230,7 +230,7 @@
 	// XXX: clone3 has stacksize, instead implement clone as a clone3
 	// wrapper.
 	SCARG(&clone_args, flags) = flags;
-	SCARG(&clone_args, stack) = (void *)(uintptr_t)cl_args.stack;
+	SCARG(&clone_args, stack) = (void *)((uintptr_t)cl_args.stack + (uintptr_t)cl_args.stack_size);
 	SCARG(&clone_args, parent_tidptr) =
 	    (void *)(intptr_t)cl_args.parent_tid;
 	SCARG(&clone_args, tls) =




Home | Main Index | Thread Index | Old Index