summaryrefslogtreecommitdiffstats
path: root/common/dotlock.c
diff options
context:
space:
mode:
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>2014-12-19 23:12:37 +0100
committerWerner Koch <wk@gnupg.org>2014-12-22 12:56:13 +0100
commit628b111fa679612e23c0d46505b1ecbbf091897d (patch)
tree7d8e5e5f396d97b47a2e3b0affdff8caf4cb38c4 /common/dotlock.c
parentgpgkey2ssh: clean up varargs (diff)
downloadgnupg2-628b111fa679612e23c0d46505b1ecbbf091897d.tar.xz
gnupg2-628b111fa679612e23c0d46505b1ecbbf091897d.zip
avoid double-close in unusual dotlock situations
* common/dotlock.c: (dotlock_create_unix) avoid double-close() in unusual situations. -- close(2) says: close() should not be retried after an EINTR since this may cause a reused descriptor from another thread to be closed. Before this patch was applied, if close(fd) failed with EINTR, it would be closed again in the write_failed: block. It could also have been closed a second time in the case that (use_hardlinks_p (h->tname)) evaluated to something other than 0 or 1. This patch avoids both of those scenarios. Note that close() could still be called twice on the same file descriptor if the first close(fd) fails but errno is not EINTR. I'm not sure the right thing to do in that scenario. An alternate resolution could be to unequivocally set fd to -1 after the first failed close(fd), avoiding the errno == EINTR test. Debian-Bug-Id: 773423
Diffstat (limited to '')
-rw-r--r--common/dotlock.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/common/dotlock.c b/common/dotlock.c
index c5520dbb4..a9963d1f7 100644
--- a/common/dotlock.c
+++ b/common/dotlock.c
@@ -680,7 +680,12 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
if ( write (fd, "\n", 1 ) != 1 )
goto write_failed;
if ( close (fd) )
- goto write_failed;
+ {
+ if ( errno == EINTR )
+ fd = -1;
+ goto write_failed;
+ }
+ fd = -1;
/* Check whether we support hard links. */
switch (use_hardlinks_p (h->tname))
@@ -718,7 +723,8 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
all_lockfiles = h->next;
UNLOCK_all_lockfiles ();
my_error_2 (_("error writing to '%s': %s\n"), h->tname, strerror (errno));
- close (fd);
+ if ( fd != -1 )
+ close (fd);
unlink (h->tname);
jnlib_free (h->tname);
jnlib_free (h);