if (size >= alloc) {
alloc += 8192;
if (alloc > max) {
- reply_with_error ("cat: %s: file is too large for message buffer",
+ reply_with_error ("%s: file is too large for message buffer",
path);
free (buf);
close (fd);
CHROOT_OUT;
if (r == -1) {
- reply_with_perror ("unlink: %s", path);
+ reply_with_perror ("%s", path);
return -1;
}
{
int r;
+ if (mode < 0) {
+ reply_with_error ("%s: mode is negative", path);
+ return -1;
+ }
+
CHROOT_IN;
r = chmod (path, mode);
CHROOT_OUT;
if (r == -1) {
- reply_with_perror ("chmod: %s: 0%o", path, mode);
+ reply_with_perror ("%s: 0%o", path, mode);
return -1;
}
CHROOT_OUT;
if (r == -1) {
- reply_with_perror ("chown: %s: %d.%d", path, owner, group);
+ reply_with_perror ("%s: %d.%d", path, owner, group);
return -1;
}
CHROOT_OUT;
if (r == -1) {
- reply_with_perror ("lchown: %s: %d.%d", path, owner, group);
+ reply_with_perror ("%s: %d.%d", path, owner, group);
return -1;
}
}
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) {
- reply_with_error ("read_file: %s: file is too large for the protocol, use guestfs_download instead", path);
+ 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;
}
* will be caught later when we try to serialize the message.
*/
if (count >= GUESTFS_MESSAGE_MAX) {
- reply_with_error ("pread: %s: count is too large for the protocol, use smaller reads", path);
+ reply_with_error ("%s: count is too large for the protocol, use smaller reads", path);
return NULL;
}
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;
}
if (r == -1) {
free (out);
- reply_with_error ("file: %s: %s", path, err);
+ reply_with_error ("%s: %s", path, err);
free (err);
return NULL;
}
else if (STREQ (method, "bzip2"))
zcat = "bzcat";
else {
- reply_with_error ("zfile: unknown method");
+ reply_with_error ("unknown method");
return NULL;
}
free (cmd);
if (fgets (line, sizeof line, fp) == NULL) {
- reply_with_perror ("zfile: fgets");
+ reply_with_perror ("fgets");
fclose (fp);
return NULL;
}
if (fclose (fp) == -1) {
- reply_with_perror ("zfile: fclose");
+ reply_with_perror ("fclose");
return NULL;
}
CHROOT_OUT;
if (r == -1) {
- reply_with_perror ("filesize: %s", path);
+ reply_with_perror ("%s", path);
return -1;
}