NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/53904: popen function is not thread safe
>Number: 53904
>Category: lib
>Synopsis: popen function is not thread safe
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jan 24 15:00:00 +0000 2019
>Originator: Jintao Zhu
>Release: v 1.35
>Organization:
GM
>Environment:
v 1.35
>Description:
subject: popen() function is not thread safe
source code file : https://nxr.netbsd.org/xref/src/lib/libc/gen/popen.c
version : /* $NetBSD: popen.c,v 1.35 2015/02/02 22:07:05 christos Exp $ */
Bug description:
In the following code snippet, at line 187, acquiring read-lock, that means, at line 162, multiple thread may possibly write "pidlist" at the same time. This race condition may make some "node" not able to be inserted to that list "pidlist", and thereafter, pclose may fail due to it not able to find the "node" in that list(at line 278); therefore, the FILE* iop not able to be closed(at line 290) and the child process not able to be reaped(at line 303)
//-----------------------------------------------------------------------
66 static struct pid {
67 struct pid *next;
68 FILE *fp;
69 #ifdef _REENTRANT
70 int fd;
71 #endif
72 pid_t pid;
73 } *pidlist; // the list
76 static rwlock_t pidlist_lock = RWLOCK_INITIALIZER; // the lock
//-----------------------------------------------------------------------
173 FILE *
174 popen(const char *cmd, const char *type)
175 {
187 (void)rwlock_rdlock(&pidlist_lock); // acquiring read-lock
....
209 pdes_parent(pdes, cur, pid, type);
210 ...
212 (void)rwlock_unlock(&pidlist_lock);
...
//-----------------------------------------------------------------------
138 static void
139 pdes_parent(int *pdes, struct pid *cur, pid_t pid, const char *type)
140 {
...
158 /* Link into list of file descriptors. */
159 cur->fp = iop;
160 cur->pid = pid;
161 cur->next = pidlist;
162 pidlist = cur; // write to pidlist
163 }
//-----------------------------------------------------------------------
265 int
266 pclose(FILE *iop)
267 {
...
278 /* Find the appropriate file pointer. */ // searching file pointer
279 for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
280 if (cur->fp == iop)
281 break;
282 if (cur == NULL) {
...
286 errno = ESRCH;
287 return -1;
288 }
289
290 (void)fclose(iop);
...
303 pid = waitpid(cur->pid, &pstat, 0);
...
309 }
>How-To-Repeat:
unit test code
>Fix:
Use a normal mutex(lock) instead of a read-write lock.
Home |
Main Index |
Thread Index |
Old Index