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