bug-gnulib
[Top][All Lists]
Advanced

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

new module 'supersede'


From: Bruno Haible
Subject: new module 'supersede'
Date: Sun, 05 Jul 2020 12:58:05 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-179-generic; KDE/5.18.0; x86_64; ; )

Some types of files are consumed with mmap(), and partially cached in the memory
of a process. For such files, if another program (e.g. 'cp' or 'install') copies
new data into the file, the process may crash (by SIGBUS or SIGSEGV), simply
because that program assumes that the contents of the file does not change.

There are many such file types:
  - executables,
  - shared libraries,
  - .mo files,
  - ...

Writing into an executable file while it is being executed produces an error
  cp: cannot create regular file 'program': Text file busy

For shared libraries, no such protection exists. You may get a "controlled"
crash like this:
  ./program: relocation error: ./program: symbol acl_get_file, version ACL_1.0 
not defined in file libacl.so.1 with link time reference

For .mo files, no such protection exists either, and it has been reported
that a program that uses gettext() crashes when the .mo file is overwritten
while it is in use.

The fix against such crashes is to not *overwrite* the file with new data,
but to *supersede* it. (*) That is, you create the new file's contents in a new
inode, and then make the new inode appear in the place of the existing file
name. That's even possible atomically, through the 'rename()' function.

The new module 'supersede' makes it easy to supersede a file. I'll be using
it in GNU msgfmt for .mo files.

Interestingly, the 'build-aux/install-sh' uses this technique to install files,
whereas the GNU coreutils 'install' program uses a different technique: it
first does unlink() (or renameat2() if the option '-b' was specified) and
then open()s the file for writing. Thus it is not atomic: For some period
of time, the file does not exist under the given name, and for some further
period in time it exists but is truncated.

(*) The terms "overwrite" and "supersede" are defined in ANSI Common Lisp:
<http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_open.html>


2020-07-05  Bruno Haible  <bruno@clisp.org>

        supersede: Add tests.
        * tests/test-supersede.c: New file.
        * tests/test-supersede-open.h: New file.
        * tests/test-supersede-fopen.h: New file.
        * modules/supersede-tests: New file.

        supersede: New module.
        * lib/supersede.h: New file.
        * lib/supersede.c: New file.
        * m4/supersede.m4: New file.
        * modules/supersede: New file.

Attachment: 0001-supersede-New-module.patch
Description: Text Data

Attachment: 0002-supersede-Add-tests.patch
Description: Text Data


reply via email to

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