Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250702141853.GH1827@brightrain.aerifal.cx>
Date: Wed, 2 Jul 2025 10:18:53 -0400
From: Rich Felker <dalias@...c.org>
To: "Zhang, Huilin (Rebecca) (CN)" <Rebecca.Zhang.CN@...driver.com>
Cc: Markus Wichmann <nullplan@....net>,
	"musl@...ts.openwall.com" <musl@...ts.openwall.com>,
	"Deng, Wenbin (CN)" <Wenbin.Deng.CN@...driver.com>
Subject: Re: [PATCH] __libc_exit_fini forgets to do
 pthread_mutex_unlock

On Wed, Jul 02, 2025 at 06:06:11AM +0000, Zhang, Huilin (Rebecca) (CN) wrote:
> Hello, Markus,
> 
> Please see attached test code main.c. Assume we compile it with MUSL and generate the executable program named myApp.
> This myApp needs an input parameter which is an another executable program. If this parameter pointed to a nonexistent
> program, this myApp will get stuck.
> 
> For example: (aaa is a nonexistent program)
> ./myApp aaa
> 
> 
> The attached .png file is the snapshot that I ran myApp on ubutntu 22.04.3.
> 
> Thanks,
> Rebecca
> 
> 
> -----Original Message-----
> From: Markus Wichmann <nullplan@....net> 
> Sent: Wednesday, July 2, 2025 12:31 PM
> To: musl@...ts.openwall.com
> Cc: Zhang, Huilin (Rebecca) (CN) <Rebecca.Zhang.CN@...driver.com>; Deng, Wenbin (CN) <Wenbin.Deng.CN@...driver.com>
> Subject: Re: [musl] [PATCH] __libc_exit_fini forgets to do pthread_mutex_unlock
> 
> CAUTION: This email comes from a non Wind River email account!
> Do not click links or open attachments unless you recognize the sender and know the content is safe.
> 
> Am Wed, Jul 02, 2025 at 10:28:54AM +0800 schrieb rebecca.zhang.cn@...driver.com:
> > From: Rebecca Zhang <rebecca.zhang.cn@...driver.com>
> >
> > This commit fixes the issue that __libc_exit_fini only do 
> > pthread_mutex_lock, but forget to do pthread_mutex_unlock.
> > ---
> >  ldso/dynlink.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/ldso/dynlink.c b/ldso/dynlink.c index ceca3c9..7885675 
> > 100644
> > --- a/ldso/dynlink.c
> > +++ b/ldso/dynlink.c
> > @@ -1492,6 +1492,7 @@ void __libc_exit_fini()
> >                       fpaddr(p, dyn[DT_FINI])();  #endif
> >       }
> > +     pthread_mutex_unlock(&init_fini_lock);
> >  }
> >
> >  void __ldso_atfork(int who)
> > --
> > 2.34.1
> >
> I think that is a deliberate omision. __libc_exit_fini() is called
> on process exit. After it runs, it must not run again, and no new
> initializer must run at all. The process will exit very soon anyway.
> The only way to deadlock here is if a destructor calls exit(), which
> they aren't allowed to do.
> 
> Ciao,
> Markus

> #include <errno.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/types.h>
> #include <sys/wait.h>
> #include <unistd.h>
> 
> void main(int argc, char *argv[]) {
>   if (argc < 2) {
>     fprintf(stderr, "usage: %s <program> [args...]\n", argv[0]);
>     exit(EXIT_FAILURE);
>   }
> 
>   printf("parent process PID=%d is starting\n", getpid());
> 
>   pid_t pid = vfork(); // use vfork to create child process
> 
>   if (pid < 0) {
>     // vfork fail
>     perror("vfork fail");
>     exit(EXIT_FAILURE);
>   } else if (pid == 0) {
>     // child process
>     printf("child process PID=%d will start: %s\n", getpid(), argv[1]);
> 
>     // execute program which is pass in via argv
>     execvp(argv[1], &argv[1]);
> 
>     perror("execvp fail");
>     exit(EXIT_FAILURE);
>   } else {
>     // parent process
>     printf("parent process PID=%d wait for child process PID=%d\n", getpid(), pid);
> 
>     int status;
>     pid_t wait_pid = waitpid(pid, &status, 0); // wait for child process terminating
> 
>     if (wait_pid < 0) {
>       perror("waitpid fail");
>     } else if (WIFEXITED(status)) {
>       printf("child process exit???exit code: %d\n", WEXITSTATUS(status));
>     } else if (WIFSIGNALED(status)) {
>       printf("child process is terminated by signal???signal is: %d\n", WTERMSIG(status));
>     }
> 
>     printf("parent process exit\n");
>   }
> 
>   exit(0);
> }

This is completely expected. You cannot call exit in the child after
vfork. The only permissible actions are execve (and variants) and
_exit.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.