mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
gen_init_cpio: fix short read file handling
When processing a "file" entry, gen_init_cpio attempts to allocate a buffer large enough to stage the entire contents of the source file. It then attempts to fill the buffer via a single read() call and subsequently writes out the entire buffer length, without checking that read() returned the full length, potentially writing uninitialized buffer memory. Fix this by breaking up file I/O into 64k chunks and only writing the length returned by the prior read() call. Link: https://lkml.kernel.org/r/20220404093429.27570-5-ddiss@suse.de Signed-off-by: David Disseldorp <ddiss@suse.de> Reviewed-by: Martin Wilck <mwilck@suse.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christian Brauner <christian.brauner@ubuntu.com> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
1274aea127
commit
3a2699cfbe
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#define xstr(s) #s
|
#define xstr(s) #s
|
||||||
#define str(s) xstr(s)
|
#define str(s) xstr(s)
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
static unsigned int offset;
|
static unsigned int offset;
|
||||||
static unsigned int ino = 721;
|
static unsigned int ino = 721;
|
||||||
@ -297,9 +298,8 @@ static int cpio_mkfile(const char *name, const char *location,
|
|||||||
unsigned int nlinks)
|
unsigned int nlinks)
|
||||||
{
|
{
|
||||||
char s[256];
|
char s[256];
|
||||||
char *filebuf = NULL;
|
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
long size;
|
unsigned long size;
|
||||||
int file = -1;
|
int file = -1;
|
||||||
int retval;
|
int retval;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
@ -326,22 +326,17 @@ static int cpio_mkfile(const char *name, const char *location,
|
|||||||
buf.st_mtime = 0xffffffff;
|
buf.st_mtime = 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
filebuf = malloc(buf.st_size);
|
if (buf.st_size > 0xffffffff) {
|
||||||
if (!filebuf) {
|
fprintf(stderr, "%s: Size exceeds maximum cpio file size\n",
|
||||||
fprintf (stderr, "out of memory\n");
|
location);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = read (file, filebuf, buf.st_size);
|
|
||||||
if (retval < 0) {
|
|
||||||
fprintf (stderr, "Can not read %s file\n", location);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
for (i = 1; i <= nlinks; i++) {
|
for (i = 1; i <= nlinks; i++) {
|
||||||
/* data goes on last link */
|
/* data goes on last link */
|
||||||
if (i == nlinks) size = buf.st_size;
|
if (i == nlinks)
|
||||||
|
size = buf.st_size;
|
||||||
|
|
||||||
if (name[0] == '/')
|
if (name[0] == '/')
|
||||||
name++;
|
name++;
|
||||||
@ -366,14 +361,25 @@ static int cpio_mkfile(const char *name, const char *location,
|
|||||||
push_string(name);
|
push_string(name);
|
||||||
push_pad();
|
push_pad();
|
||||||
|
|
||||||
if (size) {
|
while (size) {
|
||||||
if (fwrite(filebuf, size, 1, stdout) != 1) {
|
unsigned char filebuf[65536];
|
||||||
|
ssize_t this_read;
|
||||||
|
size_t this_size = MIN(size, sizeof(filebuf));
|
||||||
|
|
||||||
|
this_read = read(file, filebuf, this_size);
|
||||||
|
if (this_read <= 0 || this_read > this_size) {
|
||||||
|
fprintf(stderr, "Can not read %s file\n", location);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite(filebuf, this_read, 1, stdout) != 1) {
|
||||||
fprintf(stderr, "writing filebuf failed\n");
|
fprintf(stderr, "writing filebuf failed\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
offset += size;
|
offset += this_read;
|
||||||
push_pad();
|
size -= this_read;
|
||||||
}
|
}
|
||||||
|
push_pad();
|
||||||
|
|
||||||
name += namesize;
|
name += namesize;
|
||||||
}
|
}
|
||||||
@ -381,8 +387,8 @@ static int cpio_mkfile(const char *name, const char *location,
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (filebuf) free(filebuf);
|
if (file >= 0)
|
||||||
if (file >= 0) close(file);
|
close(file);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user