Package: gnupg2 / 2.0.26-6+deb8u2

0048-Avoid-double-close-in-unusual-dotlock-situations.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
From f256bab03e2f191bc2e97fd2cc579d82c440b996 Mon Sep 17 00:00:00 2001
From: Werner Koch <wk@gnupg.org>
Date: Thu, 12 Feb 2015 18:26:58 +0100
Subject: [PATCH 48/56] Avoid double-close in unusual dotlock situations.

* jnlib/dotlock.c (create_dotlock): Avoid double close due to EINTR.
--

close(2) says:

  close() should not be retried after an EINTR since this may cause a
  reused descriptor from another thread to be closed.

(backported from commit 628b111fa679612e23c0d46505b1ecbbf091897d)

Debian-Bug-Id: 773423
Signed-off-by: Werner Koch <wk@gnupg.org>
---
 jnlib/dotlock.c | 58 +++++++++++++++++++++++++++++++--------------------------
 1 file changed, 32 insertions(+), 26 deletions(-)

diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c
index 260c086..2578658 100644
--- a/jnlib/dotlock.c
+++ b/jnlib/dotlock.c
@@ -1,5 +1,5 @@
 /* dotlock.c - dotfile locking
- * Copyright (C) 1998, 2000, 2001, 2003, 2004, 
+ * Copyright (C) 1998, 2000, 2001, 2003, 2004,
  *               2005, 2006, 2008 Free Software Foundation, Inc.
  *
  * This file is part of JNLIB.
@@ -58,7 +58,7 @@
 
 
 /* The object describing a lock.  */
-struct dotlock_handle 
+struct dotlock_handle
 {
   struct dotlock_handle *next;
   char *lockname;      /* Name of the actual lockfile.          */
@@ -109,7 +109,7 @@ disable_dotlock(void)
    Calling this function with NULL does only install the atexit
    handler and may thus be used to assure that the cleanup is called
    after all other atexit handlers.
-  
+
    This function creates a lock file in the same directory as
    FILE_TO_LOCK using that name and a suffix of ".lock".  Note that on
    POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
@@ -171,7 +171,7 @@ create_dotlock (const char *file_to_lock)
     nodename = "unknown";
   else
     nodename = utsbuf.nodename;
-  
+
 #ifdef __riscos__
   {
     char *iter = (char *) nodename;
@@ -220,15 +220,15 @@ create_dotlock (const char *file_to_lock)
             "%s/%d", nodename, (int)getpid () );
 #endif /* __riscos__ */
 
-  do 
+  do
     {
       errno = 0;
       fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL,
                  S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
-    } 
+    }
   while (fd == -1 && errno == EINTR);
 
-  if ( fd == -1 ) 
+  if ( fd == -1 )
     {
       all_lockfiles = h->next;
       log_error (_("failed to create temporary file `%s': %s\n"),
@@ -244,7 +244,12 @@ create_dotlock (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;
 
 # ifdef _REENTRANT
   /* release mutex */
@@ -267,7 +272,8 @@ create_dotlock (const char *file_to_lock)
   /* fixme: release mutex */
 # endif
   log_error ( _("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);
@@ -300,7 +306,7 @@ create_dotlock (const char *file_to_lock)
      reasons why a lock file can't be created and thus the process
      would not stop as expected but spin til until Windows crashes.
      Our solution is to keep the lock file open; that does not
-     harm. */ 
+     harm. */
   h->lockhd = CreateFile (h->lockname,
                           GENERIC_READ|GENERIC_WRITE,
                           FILE_SHARE_READ|FILE_SHARE_WRITE,
@@ -339,7 +345,7 @@ destroy_dotlock ( DOTLOCK h )
         h->next = NULL;
         break;
       }
-  
+
   /* Then destroy the lock. */
   if (!h->disable)
     {
@@ -395,7 +401,7 @@ make_dotlock ( DOTLOCK h, long timeout )
   if ( h->disable )
     return 0; /* Locks are completely disabled.  Return success. */
 
-  if ( h->locked ) 
+  if ( h->locked )
     {
 #ifndef __riscos__
       log_debug ("Oops, `%s' is already locked\n", h->lockname);
@@ -419,19 +425,19 @@ make_dotlock ( DOTLOCK h, long timeout )
           return -1;
 	}
 # else /* __riscos__ */
-      if ( !renamefile(h->tname, h->lockname) ) 
+      if ( !renamefile(h->tname, h->lockname) )
         {
           h->locked = 1;
           return 0; /* okay */
         }
-      if ( errno != EEXIST ) 
+      if ( errno != EEXIST )
         {
           log_error( "lock not made: rename() failed: %s\n", strerror(errno) );
           return -1;
         }
 # endif /* __riscos__ */
 
-      if ( (pid = read_lockfile (h, &same_node)) == -1 ) 
+      if ( (pid = read_lockfile (h, &same_node)) == -1 )
         {
           if ( errno != ENOENT )
             {
@@ -461,11 +467,11 @@ make_dotlock ( DOTLOCK h, long timeout )
 # endif /* __riscos__ */
 	}
 
-      if ( timeout == -1 ) 
+      if ( timeout == -1 )
         {
           /* Wait until lock has been released. */
           struct timeval tv;
-          
+
           log_info (_("waiting for lock (held by %d%s) %s...\n"),
                     pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
 
@@ -495,7 +501,7 @@ make_dotlock ( DOTLOCK h, long timeout )
           return -1;
         }
 
-      if ( timeout == -1 ) 
+      if ( timeout == -1 )
         {
           /* Wait until lock has been released. */
           log_info (_("waiting for lock %s...\n"), h->lockname);
@@ -545,7 +551,7 @@ release_dotlock( DOTLOCK h )
 #else
 
   pid = read_lockfile (h, &same_node);
-  if ( pid == -1 ) 
+  if ( pid == -1 )
     {
       log_error( "release_dotlock: lockfile error\n");
       return -1;
@@ -566,7 +572,7 @@ release_dotlock( DOTLOCK h )
   /* Fixme: As an extra check we could check whether the link count is
      now really at 1. */
 #else /* __riscos__ */
-  if ( renamefile (h->lockname, h->tname) ) 
+  if ( renamefile (h->lockname, h->tname) )
     {
       log_error ("release_dotlock: error renaming lockfile `%s' to `%s'\n",
                  h->lockname, h->tname);
@@ -594,7 +600,7 @@ read_lockfile (DOTLOCK h, int *same_node )
   char *buffer, *p;
   size_t expected_len;
   int res, nread;
-  
+
   *same_node = 0;
   expected_len = 10 + 1 + h->nodename_len + 1;
   if ( expected_len >= sizeof buffer_space)
@@ -627,7 +633,7 @@ read_lockfile (DOTLOCK h, int *same_node )
       if (res < 0)
         {
           log_info ("error reading lockfile `%s'", h->lockname );
-          close (fd); 
+          close (fd);
           if (buffer != buffer_space)
             jnlib_free (buffer);
           errno = 0; /* Do not return an inappropriate ERRNO. */
@@ -651,7 +657,7 @@ read_lockfile (DOTLOCK h, int *same_node )
   if (buffer[10] != '\n'
       || (buffer[10] = 0, pid = atoi (buffer)) == -1
 #ifndef __riscos__
-      || !pid 
+      || !pid
 #else /* __riscos__ */
       || (!pid && riscos_getpid())
 #endif /* __riscos__ */
@@ -665,7 +671,7 @@ read_lockfile (DOTLOCK h, int *same_node )
     }
 
   if (nread == expected_len
-      && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len) 
+      && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
       && buffer[11+h->nodename_len] == '\n')
     *same_node = 1;
 
@@ -683,10 +689,10 @@ void
 dotlock_remove_lockfiles()
 {
   DOTLOCK h, h2;
-  
+
   h = all_lockfiles;
   all_lockfiles = NULL;
-    
+
   while ( h )
     {
       h2 = h->next;
-- 
2.1.4