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
=== modified file '.pc/applied-patches'
--- .pc/applied-patches 2012-06-13 21:28:38 +0000
+++ .pc/applied-patches 2013-06-24 18:31:42 +0000
@@ -1,1 +1,2 @@
1Makefile.in.patch1Makefile.in.patch
2fix-buffer-overflows.patch
23
=== added directory '.pc/fix-buffer-overflows.patch'
=== added file '.pc/fix-buffer-overflows.patch/.timestamp'
=== added file '.pc/fix-buffer-overflows.patch/lockfile.c'
--- .pc/fix-buffer-overflows.patch/lockfile.c 1970-01-01 00:00:00 +0000
+++ .pc/fix-buffer-overflows.patch/lockfile.c 2013-06-24 18:31:42 +0000
@@ -0,0 +1,542 @@
1/*
2 * lockfile.c Safely creates a lockfile, also over NFS.
3 * This file also holds the implementation for
4 * the Svr4 maillock functions.
5 *
6 * Version: @(#)lockfile.c 1.06 04-Jun-2004 miquels@cistron.nl
7 *
8 * Copyright (C) Miquel van Smoorenburg 1997,1998,1999,2004.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 */
15
16#include "autoconf.h"
17
18#include <sys/types.h>
19#if HAVE_SYS_PARAM_H
20#include <sys/param.h>
21#endif
22#include <sys/stat.h>
23#include <sys/wait.h>
24#include <stdio.h>
25#include <string.h>
26#include <signal.h>
27#include <fcntl.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <time.h>
31#include <errno.h>
32#include <lockfile.h>
33#include <maillock.h>
34
35#ifdef HAVE_UTIME
36#include <utime.h>
37#endif
38
39#ifdef LIB
40static char *mlockfile;
41static int islocked = 0;
42#endif
43
44#ifndef LIB
45extern int check_sleep(int);
46#endif
47
48#if !defined(LIB) || defined(MAILGROUP)
49/*
50 * See if we can write to the directory.
51 * Returns: -1 fail
52 * 0 OK writable
53 */
54#ifdef LIB
55static
56#endif
57int eaccess_write(char *fn, gid_t gid, struct stat *st)
58{
59 struct stat tmp;
60 uid_t uid = geteuid();
61 gid_t *aux;
62 int n, i;
63
64 if (st == NULL) st = &tmp;
65
66 if (stat(fn, st) != 0)
67 return -1;
68 errno = EPERM;
69
70 if (uid == 0) return 0;
71
72 if (st->st_uid == uid)
73 return (st->st_mode & 0200) ? 0 : -1;
74
75 if (st->st_gid == gid)
76 return (st->st_mode & 0020) ? 0 : -1;
77
78 if ((n = getgroups(0, NULL)) > 0) {
79 aux = malloc(n * sizeof(gid_t));
80 if (aux && getgroups(n, aux) == 0) {
81 for (i = 0; i < n; i++)
82 if (st->st_gid == aux[i]) {
83 free(aux);
84 return (st->st_mode & 0020) ? 0 : -1;
85 }
86 }
87 free(aux);
88 }
89
90 return (st->st_mode & 0002) ? 0 : -1;
91}
92#endif
93
94#if defined(LIB) && defined(MAILGROUP)
95/*
96 * Can we write to the directory of the lockfile ?
97 */
98static int need_extern(const char *file)
99{
100 gid_t egid = getegid();
101 struct stat st;
102 static gid_t mailgid = -1;
103 char *dir;
104 char *p;
105 int ret;
106
107 /*
108 * Find directory.
109 */
110 if ((dir = (char *)malloc(strlen(file) + 1)) == NULL)
111 return L_ERROR;
112 strcpy(dir, file);
113 if ((p = strrchr(dir, '/')) != NULL)
114 *p = 0;
115 else
116 strcpy(dir, ".");
117 if (eaccess_write(dir, egid, NULL) >= 0) {
118 free(dir);
119 return 0;
120 }
121
122 /*
123 * See if accessible for group mail. We find out what
124 * "group mail" is by statting LOCKPROG, that saves us
125 * from having to call getgrgid() in a library.
126 */
127 if (mailgid == (gid_t)-1) {
128 if (stat(LOCKPROG, &st) < 0 || !(st.st_mode & S_ISGID))
129 return 0;
130 mailgid = st.st_gid;
131 }
132 ret = eaccess_write(dir, mailgid, NULL) >= 0;
133 free (dir);
134 return ret;
135}
136
137/*
138 * Call external program to do the actual locking.
139 */
140static int do_extern(char *opt, const char *lockfile, int retries, int flags)
141{
142 sigset_t set, oldset;
143 char buf[4];
144 pid_t pid, n;
145 int st;
146
147 /*
148 * Block SIGCHLD. The main program might have installed
149 * handlers we don't want to call.
150 */
151 sigemptyset(&set);
152 sigaddset(&set, SIGCHLD);
153 sigprocmask(SIG_BLOCK, &set, &oldset);
154
155 /*
156 * Fork, execute locking program and wait.
157 */
158 if ((pid = fork()) < 0)
159 return L_ERROR;
160 if (pid == 0) {
161 sprintf(buf, "%d", retries % 1000);
162 execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q",
163 (flags & L_PID) ? "-p" : "-N", lockfile, NULL);
164 _exit(L_ERROR);
165 }
166
167 /*
168 * Wait for return status - do something appropriate
169 * if program died or returned L_ERROR.
170 */
171 while ((n = waitpid(pid, &st, 0)) != pid)
172 if (n < 0 && errno != EINTR)
173 break;
174 if (!sigismember(&oldset, SIGCHLD))
175 sigprocmask(SIG_UNBLOCK, &set, NULL);
176 if (n < 0)
177 return L_ERROR;
178 if (!WIFEXITED(st) || WEXITSTATUS(st) == L_ERROR) {
179 errno = EINTR;
180 return L_ERROR;
181 }
182
183 return WEXITSTATUS(st);
184}
185
186#endif
187
188/*
189 * Create a lockfile.
190 */
191#ifdef LIB
192static
193#endif
194int lockfile_create_save_tmplock(const char *lockfile,
195 char *tmplock, int tmplocksz, int retries, int flags)
196{
197 struct stat st, st1;
198 char sysname[256];
199 char buf[8];
200 char *p;
201 int sleeptime = 0;
202 int statfailed = 0;
203 int fd;
204 int i, e, len;
205 int dontsleep = 1;
206 int tries = retries + 1;
207
208#ifdef MAXPATHLEN
209 /*
210 * Safety measure.
211 */
212 if (strlen(lockfile) + 32 > MAXPATHLEN) {
213 errno = ENAMETOOLONG;
214 return L_ERROR;
215 }
216#endif
217
218 if (strlen(lockfile) + 32 + 1 > tmplocksz) {
219 errno = EINVAL;
220 return L_ERROR;
221 }
222
223#if defined(LIB) && defined(MAILGROUP)
224 if (need_extern(lockfile))
225 return do_extern("-l", lockfile, retries, flags);
226#endif
227
228 /*
229 * Create a temp lockfile (hopefully unique) and write
230 * either our pid/ppid in it, or 0\0 for svr4 compatibility.
231 */
232 if (gethostname(sysname, sizeof(sysname)) < 0)
233 return L_ERROR;
234 if ((p = strchr(sysname, '.')) != NULL)
235 *p = 0;
236 /* strcpy is safe: length-check above, limited at sprintf below */
237 strcpy(tmplock, lockfile);
238 if ((p = strrchr(tmplock, '/')) == NULL)
239 p = tmplock;
240 else
241 p++;
242 sprintf(p, ".lk%05d%x%s",
243 (int)getpid(), (int)time(NULL) & 15, sysname);
244 i = umask(022);
245 fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644);
246 e = errno;
247 umask(i);
248 if (fd < 0) {
249 tmplock[0] = 0;
250 errno = e;
251 return L_TMPLOCK;
252 }
253 if (flags & (L_PID | L_PPID)) {
254 sprintf(buf, "%d\n",
255 (flags & L_PID) ? (int)getpid() : (int)getppid());
256 p = buf;
257 len = strlen(buf);
258 } else {
259 p = "0\n";
260 len = 2;
261 }
262 i = write(fd, p, len);
263 e = errno;
264 if (close(fd) != 0) {
265 e = errno;
266 i = -1;
267 }
268 if (i != len) {
269 unlink(tmplock);
270 tmplock[0] = 0;
271 errno = i < 0 ? e : EAGAIN;
272 return L_TMPWRITE;
273 }
274
275 /*
276 * Now try to link the temporary lock to the lock.
277 */
278 for (i = 0; i < tries && tries > 0; i++) {
279
280 if (!dontsleep) {
281 sleeptime += 5;
282 if (sleeptime > 60) sleeptime = 60;
283#ifdef LIB
284 sleep(sleeptime);
285#else
286 if ((e = check_sleep(sleeptime)) != 0) {
287 unlink(tmplock);
288 tmplock[0] = 0;
289 return e;
290 }
291#endif
292 }
293 dontsleep = 0;
294
295
296 /*
297 * Now lock by linking the tempfile to the lock.
298 *
299 * KLUDGE: some people say the return code of
300 * link() over NFS can't be trusted.
301 * EXTRA FIX: the value of the nlink field
302 * can't be trusted (may be cached).
303 */
304 (void)link(tmplock, lockfile);
305
306 if (lstat(tmplock, &st1) < 0) {
307 tmplock[0] = 0;
308 return L_ERROR; /* Can't happen */
309 }
310
311 if (lstat(lockfile, &st) < 0) {
312 if (statfailed++ > 5) {
313 /*
314 * Normally, this can't happen; either
315 * another process holds the lockfile or
316 * we do. So if this error pops up
317 * repeatedly, just exit...
318 */
319 e = errno;
320 (void)unlink(tmplock);
321 tmplock[0] = 0;
322 errno = e;
323 return L_MAXTRYS;
324 }
325 continue;
326 }
327
328 /*
329 * See if we got the lock.
330 */
331 if (st.st_rdev == st1.st_rdev &&
332 st.st_ino == st1.st_ino) {
333 (void)unlink(tmplock);
334 tmplock[0] = 0;
335 return L_SUCCESS;
336 }
337 statfailed = 0;
338
339 /*
340 * If there is a lockfile and it is invalid,
341 * remove the lockfile.
342 */
343 if (lockfile_check(lockfile, flags) == -1) {
344 unlink(lockfile);
345 dontsleep = 1;
346 /*
347 * If the lockfile was invalid, then the first
348 * try wasn't valid either - make sure we
349 * try at least once more.
350 */
351 if (tries == 1) tries++;
352 }
353
354 }
355 (void)unlink(tmplock);
356 tmplock[0] = 0;
357 errno = EAGAIN;
358 return L_MAXTRYS;
359}
360
361int lockfile_create(const char *lockfile, int retries, int flags)
362{
363 char *tmplock;
364 int l, r, e;
365
366 l = strlen(lockfile)+32+1;
367 if ((tmplock = (char *)malloc(l)) == NULL)
368 return L_ERROR;
369 tmplock[0] = 0;
370 r = lockfile_create_save_tmplock(lockfile,
371 tmplock, l, retries, flags);
372 e = errno;
373 free(tmplock);
374 errno = e;
375 return r;
376}
377
378/*
379 * See if a valid lockfile is present.
380 * Returns 0 if so, -1 if not.
381 */
382int lockfile_check(const char *lockfile, int flags)
383{
384 struct stat st, st2;
385 char buf[16];
386 time_t now;
387 pid_t pid;
388 int fd, len, r;
389
390 if (stat(lockfile, &st) < 0)
391 return -1;
392
393 /*
394 * Get the contents and mtime of the lockfile.
395 */
396 time(&now);
397 pid = 0;
398 if ((fd = open(lockfile, O_RDONLY)) >= 0) {
399 /*
400 * Try to use 'atime after read' as now, this is
401 * the time of the filesystem. Should not get
402 * confused by 'atime' or 'noatime' mount options.
403 */
404 len = 0;
405 if (fstat(fd, &st) == 0 &&
406 (len = read(fd, buf, sizeof(buf))) >= 0 &&
407 fstat(fd, &st2) == 0 &&
408 st.st_atime != st2.st_atime)
409 now = st.st_atime;
410 close(fd);
411 if (len > 0 && (flags & (L_PID|L_PPID))) {
412 buf[len] = 0;
413 pid = atoi(buf);
414 }
415 }
416
417 if (pid > 0) {
418 /*
419 * If we have a pid, see if the process
420 * owning the lockfile is still alive.
421 */
422 r = kill(pid, 0);
423 if (r == 0 || errno == EPERM)
424 return 0;
425 if (r < 0 && errno == ESRCH)
426 return -1;
427 /* EINVAL - FALLTHRU */
428 }
429
430 /*
431 * Without a pid in the lockfile, the lock
432 * is valid if it is newer than 5 mins.
433 */
434
435 if (now < st.st_mtime + 300)
436 return 0;
437
438 return -1;
439}
440
441/*
442 * Remove a lock.
443 */
444int lockfile_remove(const char *lockfile)
445{
446#if defined(LIB) && defined(MAILGROUP)
447 if (need_extern(lockfile))
448 return do_extern("-u", lockfile, 0, 0);
449#endif
450 return (unlink(lockfile) < 0 && errno != ENOENT) ? -1 : 0;
451}
452
453/*
454 * Touch a lock.
455 */
456int lockfile_touch(const char *lockfile)
457{
458#ifdef HAVE_UTIME
459 return utime(lockfile, NULL);
460#else
461 return utimes(lockfile, NULL);
462#endif
463}
464
465#ifdef LIB
466/*
467 * Lock a mailfile. This looks a lot like the SVR4 function.
468 * Arguments: lusername, retries.
469 */
470int maillock(const char *name, int retries)
471{
472 char *p, *mail;
473 char *newlock;
474 int i, e;
475 int len, newlen;
476
477 if (islocked) return 0;
478
479#ifdef MAXPATHLEN
480 if (strlen(name) + sizeof(MAILDIR) + 6 > MAXPATHLEN) {
481 errno = ENAMETOOLONG;
482 return L_NAMELEN;
483 }
484#endif
485
486 /*
487 * If $MAIL is for the same username as "name"
488 * then use $MAIL instead.
489 */
490
491 len = strlen(name)+strlen(MAILDIR)+6;
492 mlockfile = (char *)malloc(len);
493 if (!mlockfile)
494 return L_ERROR;
495 sprintf(mlockfile, "%s%s.lock", MAILDIR, name);
496 if ((mail = getenv("MAIL")) != NULL) {
497 if ((p = strrchr(mail, '/')) != NULL)
498 p++;
499 else
500 p = mail;
501 if (strcmp(p, name) == 0) {
502 newlen = strlen(mail)+6;
503#ifdef MAXPATHLEN
504 if (newlen > MAXPATHLEN) {
505 errno = ENAMETOOLONG;
506 return L_NAMELEN;
507 }
508#endif
509 if (newlen > len) {
510 newlock = (char *)realloc (mlockfile, newlen);
511 if (newlock == NULL) {
512 e = errno;
513 free (mlockfile);
514 mlockfile = NULL;
515 errno = e;
516 return L_ERROR;
517 }
518 mlockfile = newlock;
519 }
520 sprintf(mlockfile, "%s.lock", mail);
521 }
522 }
523 i = lockfile_create(mlockfile, retries, 0);
524 if (i == 0) islocked = 1;
525
526 return i;
527}
528
529void mailunlock(void)
530{
531 if (!islocked) return;
532 lockfile_remove(mlockfile);
533 free (mlockfile);
534 islocked = 0;
535}
536
537void touchlock(void)
538{
539 lockfile_touch(mlockfile);
540}
541#endif
542
0543
=== modified file 'debian/changelog'
--- debian/changelog 2012-06-13 21:28:38 +0000
+++ debian/changelog 2013-06-24 18:31:42 +0000
@@ -1,3 +1,12 @@
1liblockfile (1.09-4.1) quantal-proposed; urgency=low
2
3 * debian/patches/fix-buffer-overflows.patch: Fix buffer overflows when
4 building strings
5 - Protect against overflows caused by long hostnames (LP: #941968)
6 - Protect against overflows caused by large PID numbers (LP: #1011477)
7
8 -- Adam Gandelman <adamg@ubuntu.com> Thu, 20 Jun 2013 12:49:40 -0700
9
1liblockfile (1.09-4) unstable; urgency=low10liblockfile (1.09-4) unstable; urgency=low
211
3 * Multiarch issues12 * Multiarch issues
413
=== added file 'debian/patches/fix-buffer-overflows.patch'
--- debian/patches/fix-buffer-overflows.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/fix-buffer-overflows.patch 2013-06-24 18:31:42 +0000
@@ -0,0 +1,113 @@
1Description: Fix buffer overflows when building strings
2 The first occurs in lockfile_create_save_tmplock() when building the
3 filename for the temporary lock file. The p buffer may not be large enough to
4 hold large pid numbers or long hostnames. This issue is fixed by using
5 snprintf(), rather than sprintf(), and adding appropriate field widths to the
6 conversion string. Long hostnames will be truncated to fit in the remainder of
7 the buffer length.
8 .
9 The second occurs in lockfile_create_save_tmplock() when buf is not long
10 enough to store large pid numbers. This issue is fixed by using snprintf().
11 Also, the length of buf is increased to 40, which is enough to hold a 128 bit
12 signed int. This will be sufficient for holding pid values for quite some time
13 into the future.
14 .
15 Additionally, the sprintf() in do_extern() is changed to snprintf() for
16 general security hardening. An overflow of buf is not currently possible.
17Bug-Debian: http://bugs.debian.org/677225
18Bug-Ubuntu: https://launchpad.net/bugs/941968
19Bug-Ubuntu: https://launchpad.net/bugs/1011477
20Author: Tyler Hicks <tyhicks@canonical.com>
21Index: liblockfile-1.09/lockfile.c
22===================================================================
23--- liblockfile-1.09.orig/lockfile.c 2013-01-09 10:54:49.948588615 -0800
24+++ liblockfile-1.09/lockfile.c 2013-01-09 12:19:07.328708811 -0800
25@@ -158,7 +158,7 @@
26 if ((pid = fork()) < 0)
27 return L_ERROR;
28 if (pid == 0) {
29- sprintf(buf, "%d", retries % 1000);
30+ snprintf(buf, sizeof(buf), "%d", retries % 1000);
31 execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q",
32 (flags & L_PID) ? "-p" : "-N", lockfile, NULL);
33 _exit(L_ERROR);
34@@ -185,6 +185,14 @@
35
36 #endif
37
38+#define TMPLOCKSTR ".lk"
39+#define TMPLOCKSTRSZ strlen(TMPLOCKSTR)
40+#define TMPLOCKPIDSZ 5
41+#define TMPLOCKTIMESZ 1
42+#define TMPLOCKSYSNAMESZ 23
43+#define TMPLOCKFILENAMESZ (TMPLOCKSTRSZ + TMPLOCKPIDSZ + \
44+ TMPLOCKTIMESZ + TMPLOCKSYSNAMESZ)
45+
46 /*
47 * Create a lockfile.
48 */
49@@ -196,7 +204,7 @@
50 {
51 struct stat st, st1;
52 char sysname[256];
53- char buf[8];
54+ char buf[40];
55 char *p;
56 int sleeptime = 0;
57 int statfailed = 0;
58@@ -209,13 +217,13 @@
59 /*
60 * Safety measure.
61 */
62- if (strlen(lockfile) + 32 > MAXPATHLEN) {
63+ if (strlen(lockfile) + TMPLOCKFILENAMESZ > MAXPATHLEN) {
64 errno = ENAMETOOLONG;
65 return L_ERROR;
66 }
67 #endif
68
69- if (strlen(lockfile) + 32 + 1 > tmplocksz) {
70+ if (strlen(lockfile) + TMPLOCKFILENAMESZ + 1 > tmplocksz) {
71 errno = EINVAL;
72 return L_ERROR;
73 }
74@@ -233,14 +241,16 @@
75 return L_ERROR;
76 if ((p = strchr(sysname, '.')) != NULL)
77 *p = 0;
78- /* strcpy is safe: length-check above, limited at sprintf below */
79+ /* strcpy is safe: length-check above, limited at snprintf below */
80 strcpy(tmplock, lockfile);
81 if ((p = strrchr(tmplock, '/')) == NULL)
82 p = tmplock;
83 else
84 p++;
85- sprintf(p, ".lk%05d%x%s",
86- (int)getpid(), (int)time(NULL) & 15, sysname);
87+ snprintf(p, TMPLOCKFILENAMESZ, "%s%0*d%0*x%s", TMPLOCKSTR,
88+ TMPLOCKPIDSZ, (int)getpid(),
89+ TMPLOCKTIMESZ, (int)time(NULL) & 15,
90+ sysname);
91 i = umask(022);
92 fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644);
93 e = errno;
94@@ -251,8 +261,8 @@
95 return L_TMPLOCK;
96 }
97 if (flags & (L_PID | L_PPID)) {
98- sprintf(buf, "%d\n",
99- (flags & L_PID) ? (int)getpid() : (int)getppid());
100+ snprintf(buf, sizeof(buf), "%d\n",
101+ (flags & L_PID) ? (int)getpid() : (int)getppid());
102 p = buf;
103 len = strlen(buf);
104 } else {
105@@ -363,7 +373,7 @@
106 char *tmplock;
107 int l, r, e;
108
109- l = strlen(lockfile)+32+1;
110+ l = strlen(lockfile)+TMPLOCKFILENAMESZ+1;
111 if ((tmplock = (char *)malloc(l)) == NULL)
112 return L_ERROR;
113 tmplock[0] = 0;
0114
=== modified file 'debian/patches/series'
--- debian/patches/series 2012-06-13 21:28:38 +0000
+++ debian/patches/series 2013-06-24 18:31:42 +0000
@@ -1,1 +1,2 @@
1Makefile.in.patch1Makefile.in.patch
2fix-buffer-overflows.patch
23
=== modified file 'lockfile.c'
--- lockfile.c 2011-08-10 18:44:10 +0000
+++ lockfile.c 2013-06-24 18:31:42 +0000
@@ -158,7 +158,7 @@
158 if ((pid = fork()) < 0)158 if ((pid = fork()) < 0)
159 return L_ERROR;159 return L_ERROR;
160 if (pid == 0) {160 if (pid == 0) {
161 sprintf(buf, "%d", retries % 1000);161 snprintf(buf, sizeof(buf), "%d", retries % 1000);
162 execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q",162 execl(LOCKPROG, LOCKPROG, opt, "-r", buf, "-q",
163 (flags & L_PID) ? "-p" : "-N", lockfile, NULL);163 (flags & L_PID) ? "-p" : "-N", lockfile, NULL);
164 _exit(L_ERROR);164 _exit(L_ERROR);
@@ -185,6 +185,14 @@
185185
186#endif186#endif
187187
188#define TMPLOCKSTR ".lk"
189#define TMPLOCKSTRSZ strlen(TMPLOCKSTR)
190#define TMPLOCKPIDSZ 5
191#define TMPLOCKTIMESZ 1
192#define TMPLOCKSYSNAMESZ 23
193#define TMPLOCKFILENAMESZ (TMPLOCKSTRSZ + TMPLOCKPIDSZ + \
194 TMPLOCKTIMESZ + TMPLOCKSYSNAMESZ)
195
188/*196/*
189 * Create a lockfile.197 * Create a lockfile.
190 */198 */
@@ -196,7 +204,7 @@
196{204{
197 struct stat st, st1;205 struct stat st, st1;
198 char sysname[256];206 char sysname[256];
199 char buf[8];207 char buf[40];
200 char *p;208 char *p;
201 int sleeptime = 0;209 int sleeptime = 0;
202 int statfailed = 0;210 int statfailed = 0;
@@ -209,13 +217,13 @@
209 /*217 /*
210 * Safety measure.218 * Safety measure.
211 */219 */
212 if (strlen(lockfile) + 32 > MAXPATHLEN) {220 if (strlen(lockfile) + TMPLOCKFILENAMESZ > MAXPATHLEN) {
213 errno = ENAMETOOLONG;221 errno = ENAMETOOLONG;
214 return L_ERROR;222 return L_ERROR;
215 }223 }
216#endif224#endif
217225
218 if (strlen(lockfile) + 32 + 1 > tmplocksz) {226 if (strlen(lockfile) + TMPLOCKFILENAMESZ + 1 > tmplocksz) {
219 errno = EINVAL;227 errno = EINVAL;
220 return L_ERROR;228 return L_ERROR;
221 }229 }
@@ -233,14 +241,16 @@
233 return L_ERROR;241 return L_ERROR;
234 if ((p = strchr(sysname, '.')) != NULL)242 if ((p = strchr(sysname, '.')) != NULL)
235 *p = 0;243 *p = 0;
236 /* strcpy is safe: length-check above, limited at sprintf below */244 /* strcpy is safe: length-check above, limited at snprintf below */
237 strcpy(tmplock, lockfile);245 strcpy(tmplock, lockfile);
238 if ((p = strrchr(tmplock, '/')) == NULL)246 if ((p = strrchr(tmplock, '/')) == NULL)
239 p = tmplock;247 p = tmplock;
240 else248 else
241 p++;249 p++;
242 sprintf(p, ".lk%05d%x%s",250 snprintf(p, TMPLOCKFILENAMESZ, "%s%0*d%0*x%s", TMPLOCKSTR,
243 (int)getpid(), (int)time(NULL) & 15, sysname);251 TMPLOCKPIDSZ, (int)getpid(),
252 TMPLOCKTIMESZ, (int)time(NULL) & 15,
253 sysname);
244 i = umask(022);254 i = umask(022);
245 fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644);255 fd = open(tmplock, O_WRONLY|O_CREAT|O_EXCL, 0644);
246 e = errno;256 e = errno;
@@ -251,8 +261,8 @@
251 return L_TMPLOCK;261 return L_TMPLOCK;
252 }262 }
253 if (flags & (L_PID | L_PPID)) {263 if (flags & (L_PID | L_PPID)) {
254 sprintf(buf, "%d\n",264 snprintf(buf, sizeof(buf), "%d\n",
255 (flags & L_PID) ? (int)getpid() : (int)getppid());265 (flags & L_PID) ? (int)getpid() : (int)getppid());
256 p = buf;266 p = buf;
257 len = strlen(buf);267 len = strlen(buf);
258 } else {268 } else {
@@ -363,7 +373,7 @@
363 char *tmplock;373 char *tmplock;
364 int l, r, e;374 int l, r, e;
365375
366 l = strlen(lockfile)+32+1;376 l = strlen(lockfile)+TMPLOCKFILENAMESZ+1;
367 if ((tmplock = (char *)malloc(l)) == NULL)377 if ((tmplock = (char *)malloc(l)) == NULL)
368 return L_ERROR;378 return L_ERROR;
369 tmplock[0] = 0;379 tmplock[0] = 0;

Subscribers

People subscribed via source and target branches