From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.1 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,HTML_MESSAGE,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 14993 invoked from network); 25 Jun 2022 11:09:13 -0000 Received: from mother.openwall.net (195.42.179.200) by inbox.vuxu.org with ESMTPUTF8; 25 Jun 2022 11:09:13 -0000 Received: (qmail 12210 invoked by uid 550); 25 Jun 2022 11:09:09 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 24109 invoked from network); 25 Jun 2022 03:40:40 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:from:date:message-id:subject:to; bh=P067WSyUSTC2cTj+Y5BvHBoasI50vSvWpeAeS3+gijk=; b=BxX24EtjHo3H3hx2SJJez33s1V/n8SzJoobKoVA5xKbmvSntI4Q1+efSM1THDJZtML N8CRLyH8HLmcpRjbtzLsyUHS8Gs0arcGEqj+SL83mvX1YUwq/ODVbgSXj17fC8z3jnjw vgbDH5p/ME3SDTGPqoYq47TqIlFbwVzT2LiChI7GO/GV7+IreEt04bMczwAYEHvg/2g7 uk2Dkra+QkLQvL9F8pfkQCHs+zAFKhbLvtwpaf7Ti0U9a631nVvckflJ3xD79+ZdGK/F WMwWOkcLi7lou4mZYFmK8edy7593c3nPuYpYmGSckJ+y0nx1jdiG6moVykXOco8pP/Na Afvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=P067WSyUSTC2cTj+Y5BvHBoasI50vSvWpeAeS3+gijk=; b=mYvTh+mnj7NxwEyvK6mCWa10t3k2bBrzS5siUaHMLcMsXyP155lmiahi1SvUHMx+Si cy9/p4FKMQjI9fxG5zXdtLZKRuMa8UaPVB086++dIB7Za9AiTjxCrhpdl8FeKzxFX+tR LNqX4uoxqSPtOTay+HCcIyU1JIpZXzBfPxUJqnLZNRpoZTAJ/Flne/bsS3iHt47WBYrP GCcXksUrn4kD94HxcJrTZ9NpU9MNyGBrUdxoZjQJLqnpYemyELmCgdIugaj/StyM3JcY 3cmLcUcMeX/9ha958SmreCZInPs6BHFJsrU5m9cvKOJ3zGuccnpb59ZAMVXPpUFAxnzI BZPw== X-Gm-Message-State: AJIora8lFlM8dcTDuJAM6NBY0fb9NfQRH/TU3KcHt5Q9nVWjLjKNippW CpfUBOin/ZapNXYh8AB5QijL5LvRCIs8XKCaHwn0cglk2G03Dw== X-Google-Smtp-Source: AGRyM1sDVGKdhpsb11i/096aHCa9ElmSVPCkABW/SHa1pgeBFQAQxeU7EYDnHwB6F9TIOIuWrpmgHDISDNkD0iTVsNA= X-Received: by 2002:a05:6102:15a4:b0:354:6370:333b with SMTP id g36-20020a05610215a400b003546370333bmr883057vsv.29.1656128428686; Fri, 24 Jun 2022 20:40:28 -0700 (PDT) MIME-Version: 1.0 From: Nick Peng Date: Sat, 25 Jun 2022 11:40:17 +0800 Message-ID: To: musl@lists.openwall.com Content-Type: multipart/alternative; boundary="000000000000b1c47305e23d726b" Subject: [musl] BUG: Calling readdir/dirfd after vfork will cause deadlock. --000000000000b1c47305e23d726b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Description: After vfork, calling functions such as readdir/dirfd may cause deadlock. GNU C is OK. Also tested on x86-64 with musl, no deadlock, but seems never exit, slower than GNU C. Version: latest, musl-1.2.3 OS: debian bullseye 64bit OS. and asus router CPU: raspberrypi aarch64=EF=BC=8C mips32 Reproduce Code: #include #include #include #include #include #include #include #include #include pthread_mutex_t lock =3D PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond =3D PTHREAD_COND_INITIALIZER; struct tlog_log *logs =3D NULL; int do_exit =3D 0; void *test(void *arg) { int i =3D 0; for (i =3D 0; i < 10000000; i++) { char *b =3D malloc(4096); memset(b, 0, 4096); free(b); } do_exit =3D 1; return NULL; } void lockfunc() { char path_name[4096]; DIR *dir =3D NULL; struct dirent *ent; snprintf(path_name, sizeof(path_name), "/proc/self/fd/"); dir =3D opendir(path_name); if (dir =3D=3D NULL) { goto errout; } while ((ent =3D readdir(dir)) !=3D NULL) { } closedir(dir); return; errout: if (dir) { closedir(dir); } return; } void *test_fork(void *arg) { int count =3D 0; while (do_exit =3D=3D 0) { printf("test fork count %d\n", count++); int pid =3D vfork(); if (pid < 0) { return NULL; } else if (pid =3D=3D 0) { lockfunc(); _exit(0); } int status; waitpid(pid, &status, 0); } return NULL; } int main(int argc, char *argv[]) { pthread_attr_t attr; pthread_t threads[10]; pthread_t fork_test; int i; int ret; pthread_attr_init(&attr); ret =3D pthread_create(&fork_test, &attr, test_fork, NULL); for (i =3D 0; i < 10; i++) { ret =3D pthread_create(&threads[i], &attr, test, NULL); if (ret !=3D 0) { return 1; } } for (i =3D 0; i < 10; i++) { void *retval =3D NULL; pthread_join(threads[i], &retval); } void *retval =3D NULL; pthread_join(fork_test, &retval); printf("exit\n"); getchar(); return 0; } Log=EF=BC=9A pi@raspberrypi:~/code/tinylog/test $ ./test test fork count 0 test fork count 1 <-- lock here ^C gdb backtrace: x0000000000409524 in __lock () (gdb) bt #0 0x0000000000409524 in __lock () #1 0x0000000000406278 in __libc_malloc_impl () --000000000000b1c47305e23d726b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Description:=C2=A0 After vfork, calling functions such as = readdir/dirfd may cause deadlock. GNU C is OK.
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Also tested on x86-64 w= ith musl, no deadlock, but seems never exit, slower than GNU C.
Ver= sion: latest, musl-1.2.3
OS: debian bullseye 64bit OS. and asus router<= /div>
CPU: raspberrypi aarch64=EF=BC=8C mips32
Reproduce Code= :

#include <dirent.h>
#include <pthrea= d.h>
#include <stdint.h>
#include <stdio.h>
#includ= e <stdlib.h>
#include <sys/types.h>
#include <sys/wait= .h>
#include <unistd.h>
#include <string.h>

pth= read_mutex_t lock =3D PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond =3D= PTHREAD_COND_INITIALIZER;

struct tlog_log *logs =3D NULL;
int do= _exit =3D 0;

void *test(void *arg)
{
=C2=A0 =C2=A0 int i =3D 0= ;

=C2=A0 =C2=A0 for (i =3D 0; i < 10000000; i++) {
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 char *b =3D malloc(4096);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = memset(b, 0, 4096);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 free(b);
=C2=A0 =C2= =A0 }
=C2=A0 =C2=A0 do_exit =3D 1;
=C2=A0 =C2=A0 return NULL;
}
void lockfunc()
{
=C2=A0 =C2=A0 char path_name[4096];
=C2=A0 = =C2=A0 DIR *dir =3D NULL;
=C2=A0 =C2=A0 struct dirent *ent;

=C2= =A0 =C2=A0 snprintf(path_name, sizeof(path_name), "/proc/self/fd/"= ;);
=C2=A0 =C2=A0 dir =3D opendir(path_name);
=C2=A0 =C2=A0 if (dir = =3D=3D NULL) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 goto errout;
=C2=A0 =C2=A0= }

=C2=A0 =C2=A0 while ((ent =3D readdir(dir)) !=3D NULL) {
=C2= =A0 =C2=A0 }

=C2=A0 =C2=A0 closedir(dir);

=C2=A0 =C2=A0 retur= n;
errout:
=C2=A0 =C2=A0 if (dir) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 cl= osedir(dir);
=C2=A0 =C2=A0 }

=C2=A0 =C2=A0 return;
}

vo= id *test_fork(void *arg)
{
=C2=A0 =C2=A0 int count =3D 0;
=C2=A0 = =C2=A0 while (do_exit =3D=3D 0) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 printf(&qu= ot;test fork count %d\n", count++);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 int= pid =3D vfork();
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (pid < 0) {
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return NULL;
=C2=A0 =C2=A0 =C2=A0= =C2=A0 } else if (pid =3D=3D 0) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 lockfunc();
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _exit(0);=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

=C2=A0 =C2=A0 =C2=A0 =C2=A0 int stat= us;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 waitpid(pid, &status, 0);
=C2=A0 = =C2=A0 }

=C2=A0 =C2=A0 return NULL;
}

int main(int argc, c= har *argv[])
{
=C2=A0 =C2=A0 pthread_attr_t attr;
=C2=A0 =C2=A0 pt= hread_t threads[10];
=C2=A0 =C2=A0 pthread_t fork_test;
=C2=A0 =C2=A0= int i;
=C2=A0 =C2=A0 int ret;

=C2=A0 =C2=A0 pthread_attr_init(&a= mp;attr);

=C2=A0 =C2=A0 ret =3D pthread_create(&fork_test, &= attr, test_fork, NULL);

=C2=A0 =C2=A0 for (i =3D 0; i < 10; i++) = {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ret =3D pthread_create(&threads[i], &a= mp;attr, test, NULL);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (ret !=3D 0) {
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;
=C2=A0 =C2=A0 =C2=A0= =C2=A0 }
=C2=A0 =C2=A0 }

=C2=A0 =C2=A0 for (i =3D 0; i < 10; = i++) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 void *retval =3D NULL;
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 pthread_join(threads[i], &retval);
=C2=A0 =C2=A0 }=

=C2=A0 =C2=A0 void *retval =3D NULL;
=C2=A0 =C2=A0 pthread_join(= fork_test, &retval);
=C2=A0 =C2=A0 printf("exit\n");
= =C2=A0 =C2=A0 getchar();
=C2=A0 =C2=A0 return 0;
}

=

Log=EF=BC=9A
pi@raspberrypi:~/code/tiny= log/test $ ./test
test fork count 0
test fork count 1=C2=A0 =C2=A0&l= t;-- lock here
^C

gdb backtrace:
x0000000000409524 in __lock ()
(gdb) bt
#0 =C2=A00x000000000040= 9524 in __lock ()
#1 =C2=A00x0000000000406278 in __libc_malloc_impl ()
--000000000000b1c47305e23d726b--