Merge lp:~gandelman-a/ubuntu/quantal/liblockfile/lp941968 into lp:ubuntu/quantal/liblockfile

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
Reviewer Review Type Date Requested Status
James Page Approve
Ubuntu branches Pending
Review via email: mp+171150@code.launchpad.net
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 :

Uploaded to quantal - MP needs marking as merged.

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;

Subscribers

People subscribed via source and target branches