[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#21913: sed/utils.c temporary file handling code review

From: Stanislav Brabec
Subject: bug#21913: sed/utils.c temporary file handling code review
Date: Fri, 13 Nov 2015 20:06:17 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0

While trying to reproduce an obscure crash with temporary file experiencing
file system error, I looked deeper into sed/utils.c. I found several strange

The code handling temporary file seems to be fragile and contains dead chunks.

See end of this mail and please advise what way to fix you propose?

1. ck_fclose() is (theoretically) vulnerable into a double close, because
open_files still contains file being closed while calling do_ck_fclose(). In
some error conditions, do_ck_fclose() can call panic(), which manipulates with
open_files and tries to fclose() all files there, including that one just 

However, it seems to never happen, as there are other issues.

Partial fix for that was sent to the bug-sed list last year [1], but it is not
in the sed GIT.

2.  register_open_file() defines third argument temp (which is actually set to
true e. g. in ck_mkstemp()). But the argument is never used, and p->temp is
always set to false.

3. 2. makes panic() part inside "if (open_files->temp)" completely void and
never called.

4. However it is never called, it has no side effects, as the whole
open_file.temp looks completely obsolete. The functionality of it was moved to
atexit() cleanup(), and depends on register_cleanup_file(). And
register_cleanup_file() is really called in the only place, where
register_open_file() would use temp=true (the only use is ck_mkstemp(), and the
only use of ck_mkstemp() uses register_cleanup_file() as well).

Note that register_open_file() can handle (if it will work) arbitrary number of
temporary files, but register_cleanup_file() can handle only one. But it seems
to be no problem.

5. The dead code in panic() uses fclose(); unlink() and it would (if it will be
ever called) trigger crash caused by a code mentioned in 1. The new cleanup()
code in calls unlink() without fclose(), and dues not use open_files list, so
it could not trigger the crash.

What I think should be done with the code?

a1. Completely remove third argument of register_open_file().
a2. Fix register_open_file().

b1. Completely remove code that expected open_files->temp being true.
b2. Must apply c.

c. Study the code, and if there is still a chance to out-of-sync mentioned in
1., prevent it by reordering of lines to a safe order:
prev->link = cur->link;
open_files = r.link;
do_ck_fclose (cur->fp);

d. (optional) As register_open_file() and register_cleanup_file() do nearly
the same, it is possible to convert cleanup() to use open_files, and remove
register_cleanup_file() completely.

Date: Tue, 3 Jun 2014 09:27:28 +1000
From: NeilBrown <address@hidden>
To: address@hidden
Subject: [PATCH sed] ck_fclose should unlink *before* calling do_ck_fclose.

Best Regards / S pozdravem,

Stanislav Brabec
software developer
SUSE LINUX, s. r. o.                         e-mail: address@hidden
Lihovarsk√° 1060/12                            tel: +49 911 7405384547
190 00 Praha 9                                 fax:  +420 284 084 001
Czech Republic                                    http://www.suse.cz/
PGP: 830B 40D5 9E05 35D8 5E27 6FA3 717C 209F A04F CD76

reply via email to

[Prev in Thread] Current Thread [Next in Thread]