lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Fri, 29 May 2009 11:04:30 +0900
From:	KAMEZAWA Hiroyuki <kamezawa.hiroyu@...fujitsu.com>
To:	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
Subject: [BUG?] pipe close v.s. poll() can cause hang.


Hi, a user reporetd following issue.
==
  1. Assume there are 2 threads. Thread-A and Thread-B.
  2. Thread-A creats pipe() => fd-for-read and fd-for-write are created.
  3-a. Thread-A close fd-fow-write.
  3-b. Thread-B wait for fd-for-read via poll().
  4. Thread-A close fd-for-read.
  5. thread-B's poll() cannot be waken up by event "4", sometimes.
==
It seems 3-a and 3-b occurs in racy condition.

IIUC, following code
==
 638 static int
 639 pipe_release(struct inode *inode, int decr, int decw)
 640 {
 641         struct pipe_inode_info *pipe;
 642 
 643         mutex_lock(&inode->i_mutex);
 644         pipe = inode->i_pipe;
 645         pipe->readers -= decr;
 646         pipe->writers -= decw;
 647 
 648         if (!pipe->readers && !pipe->writers) {
 649                 free_pipe_info(inode);
 650         } else {
 651                 wake_up_interruptible_sync(&pipe->wait);
 652                 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 653                 kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 654         }
 655         mutex_unlock(&inode->i_mutex);
 656 
 657         return 0;
 658 }
==
Doesn't call any wake_up() if readers==0 && writers==0 even if
there is a poll() waiter.

Eeasy test program is below. hang_thread() will hang soon on SMP.
This behavior seems to be from very old age...

strace of sample program is below.
==
[pid 21616] pipe([3, 4])                = 0
[pid 21616] futex(0x600cc0, FUTEX_WAKE_PRIVATE, 2147483647 <unfinished ...>
[pid 21617] <... futex resumed> )       = 0
[pid 21616] <... futex resumed> )       = 1
[pid 21617] write(2, "!"..., 1!)         = 1
[pid 21616] close(4 <unfinished ...>
[pid 21617] poll([{fd=3, events=POLLIN}], 1, -1 <unfinished ...>
[pid 21616] <... close resumed> )       = 0
[pid 21616] close(3)                    = 0
[pid 21616] write(2, "@"..., 1@)         = 1
[pid 21616] pipe([3, 4])                = 0
==
Thread-A as pid 21616
Thread-B as pid 21617 

fd=3 is reused but Thread-B just waits.


Thanks,
-Kame
==
#include <stdio.h>
#include <pthread.h>
#include <poll.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>

int fds[2];
pthread_barrier_t barrier;

void *hang_thread(void*data)
{
        struct pollfd pollfds;
        int ret;
        char buf[32];

        while (1) {
                pthread_barrier_wait(&barrier);
                fprintf(stderr, "!");
                pollfds.fd = fds[0];
                pollfds.events = POLLIN;
                ret = poll(&pollfds, 1, -1);

                if (pollfds.revents & POLLIN) {
                        ret = read(fds[0], buf, sizeof(buf));
                }
        }
}

int main(int argc, char *argv[])
{
        pthread_t thread;
        char buf[20];

        pthread_barrier_init(&barrier, NULL, 2);
        pthread_create(&thread, NULL, hang_thread, NULL);

        while (1) {
                pipe(fds);
                pthread_barrier_wait(&barrier);
                close(fds[1]);
                close(fds[0]);
                fprintf(stderr, "@");
        }
}


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ