Merge lp:~gandelman-a/ubuntu/quantal/liblockfile/lp941968 into lp:ubuntu/quantal/liblockfile
- Quantal (12.10)
- lp941968
- Merge into quantal
Proposed by
Adam Gandelman
Status: | Merged |
---|---|
Merge reported by: | Adam Gandelman |
Merged at revision: | not available |
Proposed branch: | lp:~gandelman-a/ubuntu/quantal/liblockfile/lp941968 |
Merge into: | lp:ubuntu/quantal/liblockfile |
Diff against target: |
790 lines (+686/-10) 6 files modified
.pc/applied-patches (+1/-0) .pc/fix-buffer-overflows.patch/lockfile.c (+542/-0) debian/changelog (+9/-0) debian/patches/fix-buffer-overflows.patch (+113/-0) debian/patches/series (+1/-0) lockfile.c (+20/-10) |
To merge this branch: | bzr merge lp:~gandelman-a/ubuntu/quantal/liblockfile/lp941968 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Page | Approve | ||
Ubuntu branches | Pending | ||
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
James Page (james-page) : | # |
review:
Approve
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
James Page (james-page) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.pc/applied-patches' | |||
2 | --- .pc/applied-patches 2012-06-13 21:28:38 +0000 | |||
3 | +++ .pc/applied-patches 2013-06-24 18:31:42 +0000 | |||
4 | @@ -1,1 +1,2 @@ | |||
5 | 1 | Makefile.in.patch | 1 | Makefile.in.patch |
6 | 2 | fix-buffer-overflows.patch | ||
7 | 2 | 3 | ||
8 | === added directory '.pc/fix-buffer-overflows.patch' | |||
9 | === added file '.pc/fix-buffer-overflows.patch/.timestamp' | |||
10 | === added file '.pc/fix-buffer-overflows.patch/lockfile.c' | |||
11 | --- .pc/fix-buffer-overflows.patch/lockfile.c 1970-01-01 00:00:00 +0000 | |||
12 | +++ .pc/fix-buffer-overflows.patch/lockfile.c 2013-06-24 18:31:42 +0000 | |||
13 | @@ -0,0 +1,542 @@ | |||
14 | 1 | /* | ||
15 | 2 | * lockfile.c Safely creates a lockfile, also over NFS. | ||
16 | 3 | * This file also holds the implementation for | ||
17 | 4 | * the Svr4 maillock functions. | ||
18 | 5 | * | ||
19 | 6 | * Version: @(#)lockfile.c 1.06 04-Jun-2004 miquels@cistron.nl | ||
20 | 7 | * | ||
21 | 8 | * Copyright (C) Miquel van Smoorenburg 1997,1998,1999,2004. | ||
22 | 9 | * | ||
23 | 10 | * This library is free software; you can redistribute it and/or | ||
24 | 11 | * modify it under the terms of the GNU Library General Public | ||
25 | 12 | * License as published by the Free Software Foundation; either | ||
26 | 13 | * version 2 of the License, or (at your option) any later version. | ||
27 | 14 | */ | ||
28 | 15 | |||
29 | 16 | #include "autoconf.h" | ||
30 | 17 | |||
31 | 18 | #include <sys/types.h> | ||
32 | 19 | #if HAVE_SYS_PARAM_H | ||
33 | 20 | #include <sys/param.h> | ||
34 | 21 | #endif | ||
35 | 22 | #include <sys/stat.h> | ||
36 | 23 | #include <sys/wait.h> | ||
37 | 24 | #include <stdio.h> | ||
38 | 25 | #include <string.h> | ||
39 | 26 | #include <signal.h> | ||
40 | 27 | #include <fcntl.h> | ||
41 | 28 | #include <stdlib.h> | ||
42 | 29 | #include <unistd.h> | ||
43 | 30 | #include <time.h> | ||
44 | 31 | #include <errno.h> | ||
45 | 32 | #include <lockfile.h> | ||
46 | 33 | #include <maillock.h> | ||
47 | 34 | |||
48 | 35 | #ifdef HAVE_UTIME | ||
49 | 36 | #include <utime.h> | ||
50 | 37 | #endif | ||
51 | 38 | |||
52 | 39 | #ifdef LIB | ||
53 | 40 | static char *mlockfile; | ||
54 | 41 | static int islocked = 0; | ||
55 | 42 | #endif | ||
56 | 43 | |||
57 | 44 | #ifndef LIB | ||
58 | 45 | extern int check_sleep(int); | ||
59 | 46 | #endif | ||
60 | 47 | |||
61 | 48 | #if !defined(LIB) || defined(MAILGROUP) | ||
62 | 49 | /* | ||
63 | 50 | * See if we can write to the directory. | ||
64 | 51 | * Returns: -1 fail | ||
65 | 52 | * 0 OK writable | ||
66 | 53 | */ | ||
67 | 54 | #ifdef LIB | ||
68 | 55 | static | ||
69 | 56 | #endif | ||
70 | 57 | int eaccess_write(char *fn, gid_t gid, struct stat *st) | ||
71 | 58 | { | ||
72 | 59 | struct stat tmp; | ||
73 | 60 | uid_t uid = geteuid(); | ||
74 | 61 | gid_t *aux; | ||
75 | 62 | int n, i; | ||
76 | 63 | |||
77 | 64 | if (st == NULL) st = &tmp; | ||
78 | 65 | |||
79 | 66 | if (stat(fn, st) != 0) | ||
80 | 67 | return -1; | ||
81 | 68 | errno = EPERM; | ||
82 | 69 | |||
83 | 70 | if (uid == 0) return 0; | ||
84 | 71 | |||
85 | 72 | if (st->st_uid == uid) | ||
86 | 73 | return (st->st_mode & 0200) ? 0 : -1; | ||
87 | 74 | |||
88 | 75 | if (st->st_gid == gid) | ||
89 | 76 | return (st->st_mode & 0020) ? 0 : -1; | ||
90 | 77 | |||
91 | 78 | if ((n = getgroups(0, NULL)) > 0) { | ||
92 | 79 | aux = malloc(n * sizeof(gid_t)); | ||
93 | 80 | if (aux && getgroups(n, aux) == 0) { | ||
94 | 81 | for (i = 0; i < n; i++) | ||
95 | 82 | if (st->st_gid == aux[i]) { | ||
96 | 83 | free(aux); | ||
97 | 84 | return (st->st_mode & 0020) ? 0 : -1; | ||
98 | 85 | } | ||
99 | 86 | } | ||
100 | 87 | free(aux); | ||
101 | 88 | } | ||
102 | 89 | |||
103 | 90 | return (st->st_mode & 0002) ? 0 : -1; | ||
104 | 91 | } | ||
105 | 92 | #endif | ||
106 | 93 | |||
107 | 94 | #if defined(LIB) && defined(MAILGROUP) | ||
108 | 95 | /* | ||
109 | 96 | * Can we write to the directory of the lockfile ? | ||
110 | 97 | */ | ||
111 | 98 | static int need_extern(const char *file) | ||
112 | 99 | { | ||
113 | 100 | gid_t egid = getegid(); | ||
114 | 101 | struct stat st; | ||
115 | 102 | static gid_t mailgid = -1; | ||
116 | 103 | char *dir; | ||
117 | 104 | char *p; | ||
118 | 105 | int ret; | ||
119 | 106 | |||
120 | 107 | /* | ||
121 | 108 | * Find directory. | ||
122 | 109 | */ | ||
123 | 110 | if ((dir = (char *)malloc(strlen(file) + 1)) == NULL) | ||
124 | 111 | return L_ERROR; | ||
125 | 112 | strcpy(dir, file); | ||
126 | 113 | if ((p = strrchr(dir, '/')) != NULL) | ||
127 | 114 | *p = 0; | ||
128 | 115 | else | ||
129 | 116 | strcpy(dir, "."); | ||
130 | 117 | if (eaccess_write(dir, egid, NULL) >= 0) { | ||
131 | 118 | free(dir); | ||
132 | 119 | return 0; | ||
133 | 120 | } | ||
134 | 121 | |||
135 | 122 | /* | ||
136 | 123 | * See if accessible for group mail. We find out what | ||
137 | 124 | * "group mail" is by statting LOCKPROG, that saves us | ||
138 | 125 | * from having to call getgrgid() in a library. | ||
139 | 126 | */ | ||
140 | 127 | if (mailgid == (gid_t)-1) { | ||
141 | 128 | if (stat(LOCKPROG, &st) < 0 || !(st.st_mode & S_ISGID)) | ||
142 | 129 | return 0; | ||
143 | 130 | mailgid = st.st_gid; | ||
144 | 131 | } | ||
145 | 132 | ret = eaccess_write(dir, mailgid, NULL) >= 0; | ||
146 | 133 | free (dir); | ||
147 | 134 | return ret; | ||
148 | 135 | } | ||
149 | 136 | |||
150 | 137 | /* | ||
151 | 138 | * Call external program to do the actual locking. | ||
152 | 139 | */ | ||
153 | 140 | static int do_extern(char *opt, const char *lockfile, int retries, int flags) | ||
154 | 141 | { | ||
155 | 142 | sigset_t set, oldset; | ||
156 | 143 | char buf[4]; | ||
157 | 144 | pid_t pid, n; | ||
158 | 145 | int st; | ||
159 | 146 | |||
160 | 147 | /* | ||
161 | 148 | * Block SIGCHLD. The main program might have installed | ||
162 | 149 | * handlers we don't want to call. | ||
163 | 150 | */ | ||
164 | 151 | sigemptyset(&set); | ||
165 | 152 | sigaddset(&set, SIGCHLD); | ||
166 | 153 | sigprocmask(SIG_BLOCK, &set, &oldset); | ||
167 | 154 | |||
168 | 155 | /* | ||
169 | 156 | * Fork, execute locking program and wait. | ||
170 | 157 | */ | ||
171 | 158 | if ((pid = fork()) < 0) | ||
172 | 159 | return L_ERROR; | ||
173 | 160 | if (pid == 0) { | ||
174 | 161 | sprintf(buf, "%d", retries % 1000); | ||
175 | 162 | execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q", | ||
176 | 163 | (flags & L_PID) ? "-p" : "-N", lockfile, NULL); | ||
177 | 164 | _exit(L_ERROR); | ||
178 | 165 | } | ||
179 | 166 | |||
180 | 167 | /* | ||
181 | 168 | * Wait for return status - do something appropriate | ||
182 | 169 | * if program died or returned L_ERROR. | ||
183 | 170 | */ | ||
184 | 171 | while ((n = waitpid(pid, &st, 0)) != pid) | ||
185 | 172 | if (n < 0 && errno != EINTR) | ||
186 | 173 | break; | ||
187 | 174 | if (!sigismember(&oldset, SIGCHLD)) | ||
188 | 175 | sigprocmask(SIG_UNBLOCK, &set, NULL); | ||
189 | 176 | if (n < 0) | ||
190 | 177 | return L_ERROR; | ||
191 | 178 | if (!WIFEXITED(st) || WEXITSTATUS(st) == L_ERROR) { | ||
192 | 179 | errno = EINTR; | ||
193 | 180 | return L_ERROR; | ||
194 | 181 | } | ||
195 | 182 | |||
196 | 183 | return WEXITSTATUS(st); | ||
197 | 184 | } | ||
198 | 185 | |||
199 | 186 | #endif | ||
200 | 187 | |||
201 | 188 | /* | ||
202 | 189 | * Create a lockfile. | ||
203 | 190 | */ | ||
204 | 191 | #ifdef LIB | ||
205 | 192 | static | ||
206 | 193 | #endif | ||
207 | 194 | int lockfile_create_save_tmplock(const char *lockfile, | ||
208 | 195 | char *tmplock, int tmplocksz, int retries, int flags) | ||
209 | 196 | { | ||
210 | 197 | struct stat st, st1; | ||
211 | 198 | char sysname[256]; | ||
212 | 199 | char buf[8]; | ||
213 | 200 | char *p; | ||
214 | 201 | int sleeptime = 0; | ||
215 | 202 | int statfailed = 0; | ||
216 | 203 | int fd; | ||
217 | 204 | int i, e, len; | ||
218 | 205 | int dontsleep = 1; | ||
219 | 206 | int tries = retries + 1; | ||
220 | 207 | |||
221 | 208 | #ifdef MAXPATHLEN | ||
222 | 209 | /* | ||
223 | 210 | * Safety measure. | ||
224 | 211 | */ | ||
225 | 212 | if (strlen(lockfile) + 32 > MAXPATHLEN) { | ||
226 | 213 | errno = ENAMETOOLONG; | ||
227 | 214 | return L_ERROR; | ||
228 | 215 | } | ||
229 | 216 | #endif | ||
230 | 217 | |||
231 | 218 | if (strlen(lockfile) + 32 + 1 > tmplocksz) { | ||
232 | 219 | errno = EINVAL; | ||
233 | 220 | return L_ERROR; | ||
234 | 221 | } | ||
235 | 222 | |||
236 | 223 | #if defined(LIB) && defined(MAILGROUP) | ||
237 | 224 | if (need_extern(lockfile)) | ||
238 | 225 | return do_extern("-l", lockfile, retries, flags); | ||
239 | 226 | #endif | ||
240 | 227 | |||
241 | 228 | /* | ||
242 | 229 | * Create a temp lockfile (hopefully unique) and write | ||
243 | 230 | * either our pid/ppid in it, or 0\0 for svr4 compatibility. | ||
244 | 231 | */ | ||
245 | 232 | if (gethostname(sysname, sizeof(sysname)) < 0) | ||
246 | 233 | return L_ERROR; | ||
247 | 234 | if ((p = strchr(sysname, '.')) != NULL) | ||
248 | 235 | *p = 0; | ||
249 | 236 | /* strcpy is safe: length-check above, limited at sprintf below */ | ||
250 | 237 | strcpy(tmplock, lockfile); | ||
251 | 238 | if ((p = strrchr(tmplock, '/')) == NULL) | ||
252 | 239 | p = tmplock; | ||
253 | 240 | else | ||
254 | 241 | p++; | ||
255 | 242 | sprintf(p, ".lk%05d%x%s", | ||
256 | 243 | (int)getpid(), (int)time(NULL) & 15, sysname); | ||
257 | 244 | i = umask(022); | ||
258 | 245 | fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644); | ||
259 | 246 | e = errno; | ||
260 | 247 | umask(i); | ||
261 | 248 | if (fd < 0) { | ||
262 | 249 | tmplock[0] = 0; | ||
263 | 250 | errno = e; | ||
264 | 251 | return L_TMPLOCK; | ||
265 | 252 | } | ||
266 | 253 | if (flags & (L_PID | L_PPID)) { | ||
267 | 254 | sprintf(buf, "%d\n", | ||
268 | 255 | (flags & L_PID) ? (int)getpid() : (int)getppid()); | ||
269 | 256 | p = buf; | ||
270 | 257 | len = strlen(buf); | ||
271 | 258 | } else { | ||
272 | 259 | p = "0\n"; | ||
273 | 260 | len = 2; | ||
274 | 261 | } | ||
275 | 262 | i = write(fd, p, len); | ||
276 | 263 | e = errno; | ||
277 | 264 | if (close(fd) != 0) { | ||
278 | 265 | e = errno; | ||
279 | 266 | i = -1; | ||
280 | 267 | } | ||
281 | 268 | if (i != len) { | ||
282 | 269 | unlink(tmplock); | ||
283 | 270 | tmplock[0] = 0; | ||
284 | 271 | errno = i < 0 ? e : EAGAIN; | ||
285 | 272 | return L_TMPWRITE; | ||
286 | 273 | } | ||
287 | 274 | |||
288 | 275 | /* | ||
289 | 276 | * Now try to link the temporary lock to the lock. | ||
290 | 277 | */ | ||
291 | 278 | for (i = 0; i < tries && tries > 0; i++) { | ||
292 | 279 | |||
293 | 280 | if (!dontsleep) { | ||
294 | 281 | sleeptime += 5; | ||
295 | 282 | if (sleeptime > 60) sleeptime = 60; | ||
296 | 283 | #ifdef LIB | ||
297 | 284 | sleep(sleeptime); | ||
298 | 285 | #else | ||
299 | 286 | if ((e = check_sleep(sleeptime)) != 0) { | ||
300 | 287 | unlink(tmplock); | ||
301 | 288 | tmplock[0] = 0; | ||
302 | 289 | return e; | ||
303 | 290 | } | ||
304 | 291 | #endif | ||
305 | 292 | } | ||
306 | 293 | dontsleep = 0; | ||
307 | 294 | |||
308 | 295 | |||
309 | 296 | /* | ||
310 | 297 | * Now lock by linking the tempfile to the lock. | ||
311 | 298 | * | ||
312 | 299 | * KLUDGE: some people say the return code of | ||
313 | 300 | * link() over NFS can't be trusted. | ||
314 | 301 | * EXTRA FIX: the value of the nlink field | ||
315 | 302 | * can't be trusted (may be cached). | ||
316 | 303 | */ | ||
317 | 304 | (void)link(tmplock, lockfile); | ||
318 | 305 | |||
319 | 306 | if (lstat(tmplock, &st1) < 0) { | ||
320 | 307 | tmplock[0] = 0; | ||
321 | 308 | return L_ERROR; /* Can't happen */ | ||
322 | 309 | } | ||
323 | 310 | |||
324 | 311 | if (lstat(lockfile, &st) < 0) { | ||
325 | 312 | if (statfailed++ > 5) { | ||
326 | 313 | /* | ||
327 | 314 | * Normally, this can't happen; either | ||
328 | 315 | * another process holds the lockfile or | ||
329 | 316 | * we do. So if this error pops up | ||
330 | 317 | * repeatedly, just exit... | ||
331 | 318 | */ | ||
332 | 319 | e = errno; | ||
333 | 320 | (void)unlink(tmplock); | ||
334 | 321 | tmplock[0] = 0; | ||
335 | 322 | errno = e; | ||
336 | 323 | return L_MAXTRYS; | ||
337 | 324 | } | ||
338 | 325 | continue; | ||
339 | 326 | } | ||
340 | 327 | |||
341 | 328 | /* | ||
342 | 329 | * See if we got the lock. | ||
343 | 330 | */ | ||
344 | 331 | if (st.st_rdev == st1.st_rdev && | ||
345 | 332 | st.st_ino == st1.st_ino) { | ||
346 | 333 | (void)unlink(tmplock); | ||
347 | 334 | tmplock[0] = 0; | ||
348 | 335 | return L_SUCCESS; | ||
349 | 336 | } | ||
350 | 337 | statfailed = 0; | ||
351 | 338 | |||
352 | 339 | /* | ||
353 | 340 | * If there is a lockfile and it is invalid, | ||
354 | 341 | * remove the lockfile. | ||
355 | 342 | */ | ||
356 | 343 | if (lockfile_check(lockfile, flags) == -1) { | ||
357 | 344 | unlink(lockfile); | ||
358 | 345 | dontsleep = 1; | ||
359 | 346 | /* | ||
360 | 347 | * If the lockfile was invalid, then the first | ||
361 | 348 | * try wasn't valid either - make sure we | ||
362 | 349 | * try at least once more. | ||
363 | 350 | */ | ||
364 | 351 | if (tries == 1) tries++; | ||
365 | 352 | } | ||
366 | 353 | |||
367 | 354 | } | ||
368 | 355 | (void)unlink(tmplock); | ||
369 | 356 | tmplock[0] = 0; | ||
370 | 357 | errno = EAGAIN; | ||
371 | 358 | return L_MAXTRYS; | ||
372 | 359 | } | ||
373 | 360 | |||
374 | 361 | int lockfile_create(const char *lockfile, int retries, int flags) | ||
375 | 362 | { | ||
376 | 363 | char *tmplock; | ||
377 | 364 | int l, r, e; | ||
378 | 365 | |||
379 | 366 | l = strlen(lockfile)+32+1; | ||
380 | 367 | if ((tmplock = (char *)malloc(l)) == NULL) | ||
381 | 368 | return L_ERROR; | ||
382 | 369 | tmplock[0] = 0; | ||
383 | 370 | r = lockfile_create_save_tmplock(lockfile, | ||
384 | 371 | tmplock, l, retries, flags); | ||
385 | 372 | e = errno; | ||
386 | 373 | free(tmplock); | ||
387 | 374 | errno = e; | ||
388 | 375 | return r; | ||
389 | 376 | } | ||
390 | 377 | |||
391 | 378 | /* | ||
392 | 379 | * See if a valid lockfile is present. | ||
393 | 380 | * Returns 0 if so, -1 if not. | ||
394 | 381 | */ | ||
395 | 382 | int lockfile_check(const char *lockfile, int flags) | ||
396 | 383 | { | ||
397 | 384 | struct stat st, st2; | ||
398 | 385 | char buf[16]; | ||
399 | 386 | time_t now; | ||
400 | 387 | pid_t pid; | ||
401 | 388 | int fd, len, r; | ||
402 | 389 | |||
403 | 390 | if (stat(lockfile, &st) < 0) | ||
404 | 391 | return -1; | ||
405 | 392 | |||
406 | 393 | /* | ||
407 | 394 | * Get the contents and mtime of the lockfile. | ||
408 | 395 | */ | ||
409 | 396 | time(&now); | ||
410 | 397 | pid = 0; | ||
411 | 398 | if ((fd = open(lockfile, O_RDONLY)) >= 0) { | ||
412 | 399 | /* | ||
413 | 400 | * Try to use 'atime after read' as now, this is | ||
414 | 401 | * the time of the filesystem. Should not get | ||
415 | 402 | * confused by 'atime' or 'noatime' mount options. | ||
416 | 403 | */ | ||
417 | 404 | len = 0; | ||
418 | 405 | if (fstat(fd, &st) == 0 && | ||
419 | 406 | (len = read(fd, buf, sizeof(buf))) >= 0 && | ||
420 | 407 | fstat(fd, &st2) == 0 && | ||
421 | 408 | st.st_atime != st2.st_atime) | ||
422 | 409 | now = st.st_atime; | ||
423 | 410 | close(fd); | ||
424 | 411 | if (len > 0 && (flags & (L_PID|L_PPID))) { | ||
425 | 412 | buf[len] = 0; | ||
426 | 413 | pid = atoi(buf); | ||
427 | 414 | } | ||
428 | 415 | } | ||
429 | 416 | |||
430 | 417 | if (pid > 0) { | ||
431 | 418 | /* | ||
432 | 419 | * If we have a pid, see if the process | ||
433 | 420 | * owning the lockfile is still alive. | ||
434 | 421 | */ | ||
435 | 422 | r = kill(pid, 0); | ||
436 | 423 | if (r == 0 || errno == EPERM) | ||
437 | 424 | return 0; | ||
438 | 425 | if (r < 0 && errno == ESRCH) | ||
439 | 426 | return -1; | ||
440 | 427 | /* EINVAL - FALLTHRU */ | ||
441 | 428 | } | ||
442 | 429 | |||
443 | 430 | /* | ||
444 | 431 | * Without a pid in the lockfile, the lock | ||
445 | 432 | * is valid if it is newer than 5 mins. | ||
446 | 433 | */ | ||
447 | 434 | |||
448 | 435 | if (now < st.st_mtime + 300) | ||
449 | 436 | return 0; | ||
450 | 437 | |||
451 | 438 | return -1; | ||
452 | 439 | } | ||
453 | 440 | |||
454 | 441 | /* | ||
455 | 442 | * Remove a lock. | ||
456 | 443 | */ | ||
457 | 444 | int lockfile_remove(const char *lockfile) | ||
458 | 445 | { | ||
459 | 446 | #if defined(LIB) && defined(MAILGROUP) | ||
460 | 447 | if (need_extern(lockfile)) | ||
461 | 448 | return do_extern("-u", lockfile, 0, 0); | ||
462 | 449 | #endif | ||
463 | 450 | return (unlink(lockfile) < 0 && errno != ENOENT) ? -1 : 0; | ||
464 | 451 | } | ||
465 | 452 | |||
466 | 453 | /* | ||
467 | 454 | * Touch a lock. | ||
468 | 455 | */ | ||
469 | 456 | int lockfile_touch(const char *lockfile) | ||
470 | 457 | { | ||
471 | 458 | #ifdef HAVE_UTIME | ||
472 | 459 | return utime(lockfile, NULL); | ||
473 | 460 | #else | ||
474 | 461 | return utimes(lockfile, NULL); | ||
475 | 462 | #endif | ||
476 | 463 | } | ||
477 | 464 | |||
478 | 465 | #ifdef LIB | ||
479 | 466 | /* | ||
480 | 467 | * Lock a mailfile. This looks a lot like the SVR4 function. | ||
481 | 468 | * Arguments: lusername, retries. | ||
482 | 469 | */ | ||
483 | 470 | int maillock(const char *name, int retries) | ||
484 | 471 | { | ||
485 | 472 | char *p, *mail; | ||
486 | 473 | char *newlock; | ||
487 | 474 | int i, e; | ||
488 | 475 | int len, newlen; | ||
489 | 476 | |||
490 | 477 | if (islocked) return 0; | ||
491 | 478 | |||
492 | 479 | #ifdef MAXPATHLEN | ||
493 | 480 | if (strlen(name) + sizeof(MAILDIR) + 6 > MAXPATHLEN) { | ||
494 | 481 | errno = ENAMETOOLONG; | ||
495 | 482 | return L_NAMELEN; | ||
496 | 483 | } | ||
497 | 484 | #endif | ||
498 | 485 | |||
499 | 486 | /* | ||
500 | 487 | * If $MAIL is for the same username as "name" | ||
501 | 488 | * then use $MAIL instead. | ||
502 | 489 | */ | ||
503 | 490 | |||
504 | 491 | len = strlen(name)+strlen(MAILDIR)+6; | ||
505 | 492 | mlockfile = (char *)malloc(len); | ||
506 | 493 | if (!mlockfile) | ||
507 | 494 | return L_ERROR; | ||
508 | 495 | sprintf(mlockfile, "%s%s.lock", MAILDIR, name); | ||
509 | 496 | if ((mail = getenv("MAIL")) != NULL) { | ||
510 | 497 | if ((p = strrchr(mail, '/')) != NULL) | ||
511 | 498 | p++; | ||
512 | 499 | else | ||
513 | 500 | p = mail; | ||
514 | 501 | if (strcmp(p, name) == 0) { | ||
515 | 502 | newlen = strlen(mail)+6; | ||
516 | 503 | #ifdef MAXPATHLEN | ||
517 | 504 | if (newlen > MAXPATHLEN) { | ||
518 | 505 | errno = ENAMETOOLONG; | ||
519 | 506 | return L_NAMELEN; | ||
520 | 507 | } | ||
521 | 508 | #endif | ||
522 | 509 | if (newlen > len) { | ||
523 | 510 | newlock = (char *)realloc (mlockfile, newlen); | ||
524 | 511 | if (newlock == NULL) { | ||
525 | 512 | e = errno; | ||
526 | 513 | free (mlockfile); | ||
527 | 514 | mlockfile = NULL; | ||
528 | 515 | errno = e; | ||
529 | 516 | return L_ERROR; | ||
530 | 517 | } | ||
531 | 518 | mlockfile = newlock; | ||
532 | 519 | } | ||
533 | 520 | sprintf(mlockfile, "%s.lock", mail); | ||
534 | 521 | } | ||
535 | 522 | } | ||
536 | 523 | i = lockfile_create(mlockfile, retries, 0); | ||
537 | 524 | if (i == 0) islocked = 1; | ||
538 | 525 | |||
539 | 526 | return i; | ||
540 | 527 | } | ||
541 | 528 | |||
542 | 529 | void mailunlock(void) | ||
543 | 530 | { | ||
544 | 531 | if (!islocked) return; | ||
545 | 532 | lockfile_remove(mlockfile); | ||
546 | 533 | free (mlockfile); | ||
547 | 534 | islocked = 0; | ||
548 | 535 | } | ||
549 | 536 | |||
550 | 537 | void touchlock(void) | ||
551 | 538 | { | ||
552 | 539 | lockfile_touch(mlockfile); | ||
553 | 540 | } | ||
554 | 541 | #endif | ||
555 | 542 | |||
556 | 0 | 543 | ||
557 | === modified file 'debian/changelog' | |||
558 | --- debian/changelog 2012-06-13 21:28:38 +0000 | |||
559 | +++ debian/changelog 2013-06-24 18:31:42 +0000 | |||
560 | @@ -1,3 +1,12 @@ | |||
561 | 1 | liblockfile (1.09-4.1) quantal-proposed; urgency=low | ||
562 | 2 | |||
563 | 3 | * debian/patches/fix-buffer-overflows.patch: Fix buffer overflows when | ||
564 | 4 | building strings | ||
565 | 5 | - Protect against overflows caused by long hostnames (LP: #941968) | ||
566 | 6 | - Protect against overflows caused by large PID numbers (LP: #1011477) | ||
567 | 7 | |||
568 | 8 | -- Adam Gandelman <adamg@ubuntu.com> Thu, 20 Jun 2013 12:49:40 -0700 | ||
569 | 9 | |||
570 | 1 | liblockfile (1.09-4) unstable; urgency=low | 10 | liblockfile (1.09-4) unstable; urgency=low |
571 | 2 | 11 | ||
572 | 3 | * Multiarch issues | 12 | * Multiarch issues |
573 | 4 | 13 | ||
574 | === added file 'debian/patches/fix-buffer-overflows.patch' | |||
575 | --- debian/patches/fix-buffer-overflows.patch 1970-01-01 00:00:00 +0000 | |||
576 | +++ debian/patches/fix-buffer-overflows.patch 2013-06-24 18:31:42 +0000 | |||
577 | @@ -0,0 +1,113 @@ | |||
578 | 1 | Description: Fix buffer overflows when building strings | ||
579 | 2 | The first occurs in lockfile_create_save_tmplock() when building the | ||
580 | 3 | filename for the temporary lock file. The p buffer may not be large enough to | ||
581 | 4 | hold large pid numbers or long hostnames. This issue is fixed by using | ||
582 | 5 | snprintf(), rather than sprintf(), and adding appropriate field widths to the | ||
583 | 6 | conversion string. Long hostnames will be truncated to fit in the remainder of | ||
584 | 7 | the buffer length. | ||
585 | 8 | . | ||
586 | 9 | The second occurs in lockfile_create_save_tmplock() when buf is not long | ||
587 | 10 | enough to store large pid numbers. This issue is fixed by using snprintf(). | ||
588 | 11 | Also, the length of buf is increased to 40, which is enough to hold a 128 bit | ||
589 | 12 | signed int. This will be sufficient for holding pid values for quite some time | ||
590 | 13 | into the future. | ||
591 | 14 | . | ||
592 | 15 | Additionally, the sprintf() in do_extern() is changed to snprintf() for | ||
593 | 16 | general security hardening. An overflow of buf is not currently possible. | ||
594 | 17 | Bug-Debian: http://bugs.debian.org/677225 | ||
595 | 18 | Bug-Ubuntu: https://launchpad.net/bugs/941968 | ||
596 | 19 | Bug-Ubuntu: https://launchpad.net/bugs/1011477 | ||
597 | 20 | Author: Tyler Hicks <tyhicks@canonical.com> | ||
598 | 21 | Index: liblockfile-1.09/lockfile.c | ||
599 | 22 | =================================================================== | ||
600 | 23 | --- liblockfile-1.09.orig/lockfile.c 2013-01-09 10:54:49.948588615 -0800 | ||
601 | 24 | +++ liblockfile-1.09/lockfile.c 2013-01-09 12:19:07.328708811 -0800 | ||
602 | 25 | @@ -158,7 +158,7 @@ | ||
603 | 26 | if ((pid = fork()) < 0) | ||
604 | 27 | return L_ERROR; | ||
605 | 28 | if (pid == 0) { | ||
606 | 29 | - sprintf(buf, "%d", retries % 1000); | ||
607 | 30 | + snprintf(buf, sizeof(buf), "%d", retries % 1000); | ||
608 | 31 | execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q", | ||
609 | 32 | (flags & L_PID) ? "-p" : "-N", lockfile, NULL); | ||
610 | 33 | _exit(L_ERROR); | ||
611 | 34 | @@ -185,6 +185,14 @@ | ||
612 | 35 | |||
613 | 36 | #endif | ||
614 | 37 | |||
615 | 38 | +#define TMPLOCKSTR ".lk" | ||
616 | 39 | +#define TMPLOCKSTRSZ strlen(TMPLOCKSTR) | ||
617 | 40 | +#define TMPLOCKPIDSZ 5 | ||
618 | 41 | +#define TMPLOCKTIMESZ 1 | ||
619 | 42 | +#define TMPLOCKSYSNAMESZ 23 | ||
620 | 43 | +#define TMPLOCKFILENAMESZ (TMPLOCKSTRSZ + TMPLOCKPIDSZ + \ | ||
621 | 44 | + TMPLOCKTIMESZ + TMPLOCKSYSNAMESZ) | ||
622 | 45 | + | ||
623 | 46 | /* | ||
624 | 47 | * Create a lockfile. | ||
625 | 48 | */ | ||
626 | 49 | @@ -196,7 +204,7 @@ | ||
627 | 50 | { | ||
628 | 51 | struct stat st, st1; | ||
629 | 52 | char sysname[256]; | ||
630 | 53 | - char buf[8]; | ||
631 | 54 | + char buf[40]; | ||
632 | 55 | char *p; | ||
633 | 56 | int sleeptime = 0; | ||
634 | 57 | int statfailed = 0; | ||
635 | 58 | @@ -209,13 +217,13 @@ | ||
636 | 59 | /* | ||
637 | 60 | * Safety measure. | ||
638 | 61 | */ | ||
639 | 62 | - if (strlen(lockfile) + 32 > MAXPATHLEN) { | ||
640 | 63 | + if (strlen(lockfile) + TMPLOCKFILENAMESZ > MAXPATHLEN) { | ||
641 | 64 | errno = ENAMETOOLONG; | ||
642 | 65 | return L_ERROR; | ||
643 | 66 | } | ||
644 | 67 | #endif | ||
645 | 68 | |||
646 | 69 | - if (strlen(lockfile) + 32 + 1 > tmplocksz) { | ||
647 | 70 | + if (strlen(lockfile) + TMPLOCKFILENAMESZ + 1 > tmplocksz) { | ||
648 | 71 | errno = EINVAL; | ||
649 | 72 | return L_ERROR; | ||
650 | 73 | } | ||
651 | 74 | @@ -233,14 +241,16 @@ | ||
652 | 75 | return L_ERROR; | ||
653 | 76 | if ((p = strchr(sysname, '.')) != NULL) | ||
654 | 77 | *p = 0; | ||
655 | 78 | - /* strcpy is safe: length-check above, limited at sprintf below */ | ||
656 | 79 | + /* strcpy is safe: length-check above, limited at snprintf below */ | ||
657 | 80 | strcpy(tmplock, lockfile); | ||
658 | 81 | if ((p = strrchr(tmplock, '/')) == NULL) | ||
659 | 82 | p = tmplock; | ||
660 | 83 | else | ||
661 | 84 | p++; | ||
662 | 85 | - sprintf(p, ".lk%05d%x%s", | ||
663 | 86 | - (int)getpid(), (int)time(NULL) & 15, sysname); | ||
664 | 87 | + snprintf(p, TMPLOCKFILENAMESZ, "%s%0*d%0*x%s", TMPLOCKSTR, | ||
665 | 88 | + TMPLOCKPIDSZ, (int)getpid(), | ||
666 | 89 | + TMPLOCKTIMESZ, (int)time(NULL) & 15, | ||
667 | 90 | + sysname); | ||
668 | 91 | i = umask(022); | ||
669 | 92 | fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644); | ||
670 | 93 | e = errno; | ||
671 | 94 | @@ -251,8 +261,8 @@ | ||
672 | 95 | return L_TMPLOCK; | ||
673 | 96 | } | ||
674 | 97 | if (flags & (L_PID | L_PPID)) { | ||
675 | 98 | - sprintf(buf, "%d\n", | ||
676 | 99 | - (flags & L_PID) ? (int)getpid() : (int)getppid()); | ||
677 | 100 | + snprintf(buf, sizeof(buf), "%d\n", | ||
678 | 101 | + (flags & L_PID) ? (int)getpid() : (int)getppid()); | ||
679 | 102 | p = buf; | ||
680 | 103 | len = strlen(buf); | ||
681 | 104 | } else { | ||
682 | 105 | @@ -363,7 +373,7 @@ | ||
683 | 106 | char *tmplock; | ||
684 | 107 | int l, r, e; | ||
685 | 108 | |||
686 | 109 | - l = strlen(lockfile)+32+1; | ||
687 | 110 | + l = strlen(lockfile)+TMPLOCKFILENAMESZ+1; | ||
688 | 111 | if ((tmplock = (char *)malloc(l)) == NULL) | ||
689 | 112 | return L_ERROR; | ||
690 | 113 | tmplock[0] = 0; | ||
691 | 0 | 114 | ||
692 | === modified file 'debian/patches/series' | |||
693 | --- debian/patches/series 2012-06-13 21:28:38 +0000 | |||
694 | +++ debian/patches/series 2013-06-24 18:31:42 +0000 | |||
695 | @@ -1,1 +1,2 @@ | |||
696 | 1 | Makefile.in.patch | 1 | Makefile.in.patch |
697 | 2 | fix-buffer-overflows.patch | ||
698 | 2 | 3 | ||
699 | === modified file 'lockfile.c' | |||
700 | --- lockfile.c 2011-08-10 18:44:10 +0000 | |||
701 | +++ lockfile.c 2013-06-24 18:31:42 +0000 | |||
702 | @@ -158,7 +158,7 @@ | |||
703 | 158 | if ((pid = fork()) < 0) | 158 | if ((pid = fork()) < 0) |
704 | 159 | return L_ERROR; | 159 | return L_ERROR; |
705 | 160 | if (pid == 0) { | 160 | if (pid == 0) { |
707 | 161 | sprintf(buf, "%d", retries % 1000); | 161 | snprintf(buf, sizeof(buf), "%d", retries % 1000); |
708 | 162 | execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q", | 162 | execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q", |
709 | 163 | (flags & L_PID) ? "-p" : "-N", lockfile, NULL); | 163 | (flags & L_PID) ? "-p" : "-N", lockfile, NULL); |
710 | 164 | _exit(L_ERROR); | 164 | _exit(L_ERROR); |
711 | @@ -185,6 +185,14 @@ | |||
712 | 185 | 185 | ||
713 | 186 | #endif | 186 | #endif |
714 | 187 | 187 | ||
715 | 188 | #define TMPLOCKSTR ".lk" | ||
716 | 189 | #define TMPLOCKSTRSZ strlen(TMPLOCKSTR) | ||
717 | 190 | #define TMPLOCKPIDSZ 5 | ||
718 | 191 | #define TMPLOCKTIMESZ 1 | ||
719 | 192 | #define TMPLOCKSYSNAMESZ 23 | ||
720 | 193 | #define TMPLOCKFILENAMESZ (TMPLOCKSTRSZ + TMPLOCKPIDSZ + \ | ||
721 | 194 | TMPLOCKTIMESZ + TMPLOCKSYSNAMESZ) | ||
722 | 195 | |||
723 | 188 | /* | 196 | /* |
724 | 189 | * Create a lockfile. | 197 | * Create a lockfile. |
725 | 190 | */ | 198 | */ |
726 | @@ -196,7 +204,7 @@ | |||
727 | 196 | { | 204 | { |
728 | 197 | struct stat st, st1; | 205 | struct stat st, st1; |
729 | 198 | char sysname[256]; | 206 | char sysname[256]; |
731 | 199 | char buf[8]; | 207 | char buf[40]; |
732 | 200 | char *p; | 208 | char *p; |
733 | 201 | int sleeptime = 0; | 209 | int sleeptime = 0; |
734 | 202 | int statfailed = 0; | 210 | int statfailed = 0; |
735 | @@ -209,13 +217,13 @@ | |||
736 | 209 | /* | 217 | /* |
737 | 210 | * Safety measure. | 218 | * Safety measure. |
738 | 211 | */ | 219 | */ |
740 | 212 | if (strlen(lockfile) + 32 > MAXPATHLEN) { | 220 | if (strlen(lockfile) + TMPLOCKFILENAMESZ > MAXPATHLEN) { |
741 | 213 | errno = ENAMETOOLONG; | 221 | errno = ENAMETOOLONG; |
742 | 214 | return L_ERROR; | 222 | return L_ERROR; |
743 | 215 | } | 223 | } |
744 | 216 | #endif | 224 | #endif |
745 | 217 | 225 | ||
747 | 218 | if (strlen(lockfile) + 32 + 1 > tmplocksz) { | 226 | if (strlen(lockfile) + TMPLOCKFILENAMESZ + 1 > tmplocksz) { |
748 | 219 | errno = EINVAL; | 227 | errno = EINVAL; |
749 | 220 | return L_ERROR; | 228 | return L_ERROR; |
750 | 221 | } | 229 | } |
751 | @@ -233,14 +241,16 @@ | |||
752 | 233 | return L_ERROR; | 241 | return L_ERROR; |
753 | 234 | if ((p = strchr(sysname, '.')) != NULL) | 242 | if ((p = strchr(sysname, '.')) != NULL) |
754 | 235 | *p = 0; | 243 | *p = 0; |
756 | 236 | /* strcpy is safe: length-check above, limited at sprintf below */ | 244 | /* strcpy is safe: length-check above, limited at snprintf below */ |
757 | 237 | strcpy(tmplock, lockfile); | 245 | strcpy(tmplock, lockfile); |
758 | 238 | if ((p = strrchr(tmplock, '/')) == NULL) | 246 | if ((p = strrchr(tmplock, '/')) == NULL) |
759 | 239 | p = tmplock; | 247 | p = tmplock; |
760 | 240 | else | 248 | else |
761 | 241 | p++; | 249 | p++; |
764 | 242 | sprintf(p, ".lk%05d%x%s", | 250 | snprintf(p, TMPLOCKFILENAMESZ, "%s%0*d%0*x%s", TMPLOCKSTR, |
765 | 243 | (int)getpid(), (int)time(NULL) & 15, sysname); | 251 | TMPLOCKPIDSZ, (int)getpid(), |
766 | 252 | TMPLOCKTIMESZ, (int)time(NULL) & 15, | ||
767 | 253 | sysname); | ||
768 | 244 | i = umask(022); | 254 | i = umask(022); |
769 | 245 | fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644); | 255 | fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644); |
770 | 246 | e = errno; | 256 | e = errno; |
771 | @@ -251,8 +261,8 @@ | |||
772 | 251 | return L_TMPLOCK; | 261 | return L_TMPLOCK; |
773 | 252 | } | 262 | } |
774 | 253 | if (flags & (L_PID | L_PPID)) { | 263 | if (flags & (L_PID | L_PPID)) { |
777 | 254 | sprintf(buf, "%d\n", | 264 | snprintf(buf, sizeof(buf), "%d\n", |
778 | 255 | (flags & L_PID) ? (int)getpid() : (int)getppid()); | 265 | (flags & L_PID) ? (int)getpid() : (int)getppid()); |
779 | 256 | p = buf; | 266 | p = buf; |
780 | 257 | len = strlen(buf); | 267 | len = strlen(buf); |
781 | 258 | } else { | 268 | } else { |
782 | @@ -363,7 +373,7 @@ | |||
783 | 363 | char *tmplock; | 373 | char *tmplock; |
784 | 364 | int l, r, e; | 374 | int l, r, e; |
785 | 365 | 375 | ||
787 | 366 | l = strlen(lockfile)+32+1; | 376 | l = strlen(lockfile)+TMPLOCKFILENAMESZ+1; |
788 | 367 | if ((tmplock = (char *)malloc(l)) == NULL) | 377 | if ((tmplock = (char *)malloc(l)) == NULL) |
789 | 368 | return L_ERROR; | 378 | return L_ERROR; |
790 | 369 | tmplock[0] = 0; | 379 | tmplock[0] = 0; |
Uploaded to quantal - MP needs marking as merged.