Skip to content

Commit 6011b1f

Browse files
committed
daemon: Don't use files with fixed names in /tmp (thanks Steve Kemp).
Although this doesn't matter for the ordinary (appliance) case, it matters for the libguestfs live case. In that case it could cause the guest to be exploited by a tmp/symlink attack.
1 parent f93e8db commit 6011b1f

File tree

2 files changed

+46
-20
lines changed

2 files changed

+46
-20
lines changed

daemon/inotify.c

+20-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* libguestfs - the guestfsd daemon
2-
* Copyright (C) 2009 Red Hat Inc.
2+
* Copyright (C) 2009-2011 Red Hat Inc.
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU General Public License as published by
@@ -317,10 +317,21 @@ do_inotify_files (void)
317317
FILE *fp = NULL;
318318
guestfs_int_inotify_event_list *events;
319319
char buf[PATH_MAX];
320+
char tempfile[] = "/tmp/inotifyXXXXXX";
321+
int fd;
322+
char cmd[64];
320323

321324
NEED_INOTIFY (NULL);
322325

323-
fp = popen ("sort -u > /tmp/inotify", "w");
326+
fd = mkstemp (tempfile);
327+
if (fd == -1) {
328+
reply_with_perror ("mkstemp");
329+
return NULL;
330+
}
331+
332+
snprintf (cmd, sizeof cmd, "sort -u > %s", tempfile);
333+
334+
fp = popen (cmd, "w");
324335
if (fp == NULL) {
325336
reply_with_perror ("sort");
326337
return NULL;
@@ -349,9 +360,11 @@ do_inotify_files (void)
349360

350361
pclose (fp);
351362

352-
fp = fopen ("/tmp/inotify", "r");
363+
fp = fdopen (fd, "r");
353364
if (fp == NULL) {
354-
reply_with_perror ("/tmp/inotify");
365+
reply_with_perror ("%s", tempfile);
366+
unlink (tempfile);
367+
close (fd);
355368
return NULL;
356369
}
357370

@@ -365,20 +378,20 @@ do_inotify_files (void)
365378
goto error;
366379
}
367380

368-
fclose (fp);
381+
fclose (fp); /* implicitly closes fd */
369382
fp = NULL;
370383

371384
if (add_string (&ret, &size, &alloc, NULL) == -1)
372385
goto error;
373386

374-
unlink ("/tmp/inotify");
387+
unlink (tempfile);
375388
return ret;
376389

377390
error:
378391
if (fp != NULL)
379392
fclose (fp);
380393

381-
unlink ("/tmp/inotify");
394+
unlink (tempfile);
382395
return NULL;
383396
#else
384397
NOT_AVAILABLE (NULL);

daemon/tar.c

+26-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* libguestfs - the guestfsd daemon
2-
* Copyright (C) 2009-2010 Red Hat Inc.
2+
* Copyright (C) 2009-2011 Red Hat Inc.
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU General Public License as published by
@@ -36,18 +36,14 @@ optgroup_xz_available (void)
3636
return prog_exists ("xz");
3737
}
3838

39-
/* Redirect errors from the tar command to the error file, then
40-
* provide functions for reading it in. We overwrite the file each
41-
* time, and since it's small and stored on the appliance we don't
42-
* bother to delete it.
43-
*/
44-
static const char *error_file = "/tmp/error";
45-
39+
/* Read the error file. Returns a string that the caller must free. */
4640
static char *
47-
read_error_file (void)
41+
read_error_file (char *error_file)
4842
{
4943
size_t len;
50-
char *str = read_file (error_file, &len);
44+
char *str;
45+
46+
str = read_file (error_file, &len);
5147
if (str == NULL) {
5248
str = strdup ("(no error)");
5349
if (str == NULL) {
@@ -78,6 +74,16 @@ do_tXz_in (const char *dir, const char *filter)
7874
int err, r;
7975
FILE *fp;
8076
char *cmd;
77+
char error_file[] = "/tmp/tarXXXXXX";
78+
int fd;
79+
80+
fd = mkstemp (error_file);
81+
if (fd == -1) {
82+
reply_with_perror ("mkstemp");
83+
return -1;
84+
}
85+
86+
close (fd);
8187

8288
/* "tar -C /sysroot%s -xf -" but we have to quote the dir. */
8389
if (asprintf_nowarn (&cmd, "tar -C %R -%sxf - 2> %s",
@@ -86,6 +92,7 @@ do_tXz_in (const char *dir, const char *filter)
8692
r = cancel_receive ();
8793
errno = err;
8894
reply_with_perror ("asprintf");
95+
unlink (error_file);
8996
return -1;
9097
}
9198

@@ -98,6 +105,7 @@ do_tXz_in (const char *dir, const char *filter)
98105
r = cancel_receive ();
99106
errno = err;
100107
reply_with_perror ("%s", cmd);
108+
unlink (error_file);
101109
free (cmd);
102110
return -1;
103111
}
@@ -106,14 +114,15 @@ do_tXz_in (const char *dir, const char *filter)
106114
/* The semantics of fwrite are too undefined, so write to the
107115
* file descriptor directly instead.
108116
*/
109-
int fd = fileno (fp);
117+
fd = fileno (fp);
110118

111119
r = receive_file (write_cb, &fd);
112120
if (r == -1) { /* write error */
113121
cancel_receive ();
114-
char *errstr = read_error_file ();
122+
char *errstr = read_error_file (error_file);
115123
reply_with_error ("write error on directory: %s: %s", dir, errstr);
116124
free (errstr);
125+
unlink (error_file);
117126
pclose (fp);
118127
return -1;
119128
}
@@ -123,17 +132,21 @@ do_tXz_in (const char *dir, const char *filter)
123132
*/
124133
reply_with_error ("file upload cancelled");
125134
pclose (fp);
135+
unlink (error_file);
126136
return -1;
127137
}
128138

129139
if (pclose (fp) != 0) {
130-
char *errstr = read_error_file ();
140+
char *errstr = read_error_file (error_file);
131141
reply_with_error ("tar subcommand failed on directory: %s: %s",
132142
dir, errstr);
133143
free (errstr);
144+
unlink (error_file);
134145
return -1;
135146
}
136147

148+
unlink (error_file);
149+
137150
return 0;
138151
}
139152

0 commit comments

Comments
 (0)