}
int
-do_exists (const char *path)
-{
- int r;
-
- CHROOT_IN;
- r = access (path, F_OK);
- CHROOT_OUT;
-
- return r == 0;
-}
-
-int
-do_is_file (const char *path)
+do_write_file (const char *path, const char *content, int size)
{
- int r;
- struct stat buf;
-
- CHROOT_IN;
- r = lstat (path, &buf);
- CHROOT_OUT;
+ int fd;
- if (r == -1) {
- if (errno != ENOENT && errno != ENOTDIR) {
- reply_with_perror ("stat: %s", path);
- return -1;
- }
- else
- return 0; /* Not a file. */
+ /* This call is deprecated, and it has a broken interface. New code
+ * should use the 'guestfs_write' call instead. Because we used an
+ * XDR string type, 'content' cannot contain ASCII NUL and 'size'
+ * must never be longer than the string. We must check this to
+ * ensure random stuff from XDR or daemon memory isn't written to
+ * the file (RHBZ#597135).
+ */
+ if (size < 0) {
+ reply_with_error ("size cannot be negative");
+ return -1;
}
- return S_ISREG (buf.st_mode);
-}
-
-int
-do_write_file (const char *path, const char *content, int size)
-{
- int fd;
+ /* Note content_len must be small because of the limits on protocol
+ * message size.
+ */
+ int content_len = (int) strlen (content);
if (size == 0)
- size = strlen (content);
+ size = content_len;
+ else if (size > content_len) {
+ reply_with_error ("size parameter is larger than string content");
+ return -1;
+ }
CHROOT_IN;
fd = open (path, O_WRONLY | O_TRUNC | O_CREAT | O_NOCTTY, 0666);
return NULL;
}
- *size_r = statbuf.st_size;
/* The actual limit on messages is smaller than this. This
* check just limits the amount of memory we'll try and allocate
* here. If the message is larger than the real limit, that will
* be caught later when we try to serialize the message.
*/
- if (*size_r >= GUESTFS_MESSAGE_MAX) {
+ if (statbuf.st_size >= GUESTFS_MESSAGE_MAX) {
reply_with_error ("%s: file is too large for the protocol, use guestfs_download instead", path);
close (fd);
return NULL;
}
- r = malloc (*size_r);
+ r = malloc (statbuf.st_size);
if (r == NULL) {
reply_with_perror ("malloc");
close (fd);
return NULL;
}
- if (xread (fd, r, *size_r) == -1) {
+ if (xread (fd, r, statbuf.st_size) == -1) {
reply_with_perror ("read: %s", path);
close (fd);
free (r);
return NULL;
}
+ /* Mustn't touch *size_r until we are sure that we won't return any
+ * error (RHBZ#589039).
+ */
+ *size_r = statbuf.st_size;
return r;
}
return NULL;
}
+ /* Mustn't touch *size_r until we are sure that we won't return any
+ * error (RHBZ#589039).
+ */
*size_r = r;
return buf;
}