Subject: bin/19849: Race conditions in compress
To: None <gnats-bugs@gnats.netbsd.org>
From: Christian Biere <christianbiere@gmx.de>
List: netbsd-bugs
Date: 01/14/2003 11:35:43
>Number: 19849
>Category: bin
>Synopsis: Race conditions in compress
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Jan 14 02:36:00 PST 2003
>Closed-Date:
>Last-Modified:
>Originator: Christian Biere
>Release: NetBSD 1.6K
>Organization:
>Environment:
>Description:
By reading PR bin/19722 I discovered
/usr/src/usr.bin/compress/compress.c:
In compress:
if (!isstdout) {
exists = !stat(out, &sb);
if (!force && exists && S_ISREG(sb.st_mode) &&
!permission(out)) return;
oreg = !exists || S_ISREG(sb.st_mode);
} else
oreg = 0;
IMHO, it's better to open the file and use ENOENT == errno to decide
whether the file exists or not.
if ((ifp = fopen(in, "r")) == NULL) {
cwarn("%s", in);
return;
}
IMO here's a real race condition:
if (!isstdin) {
if (stat(in, &isb)) { /* DON'T FSTAT! */
cwarn("%s", in);
goto err;
}
Why "DON'T FSTAT"? This would be the only way to prevent a race
condition. What's the reason for not using "fstat(fileno(ifp), &isb)"?
If you don't, there's no guarantee that you stat() the same file you've
opened with fopen() before.
Another example for the same kind of race condition:
if (fclose(ofp)) {
cwarn("%s", out);
goto err;
}
ofp = NULL;
if (isreg && oreg) {
if (stat(out, &sb)) {
cwarn("%s", out);
goto err;
[...]
Here, compress might modify the mode for the wrong file as it's only
identified by its name:
setfile(out, &isb);
In decompress:
Again, the file used with ofp is not guaranteed to be the same out
points to.
if (isreg && oreg) {
setfile(out, &sb);
>How-To-Repeat:
>Fix:
Giorgos Keramidas suggested to add a function zstat() to the zopen
interface. This would keep the code clean and wouldn't break the
interface.
>Release-Note:
>Audit-Trail:
>Unformatted: