Roll back "die on malloc failure" behaviour a bit
After recent change, select(2^31-1, NULL, NULL, NULL) would make strace exit. This change caps fdsize so that it is always in [0, 1025*1024], IOW: we will try to allocate at most 1 megabyte, which in practice will almost always work, unlike malloc(2Gig). * desc.c (decode_select): Cap fdsize to 1024*1024. * pathtrace.c (pathtrace_match): Cap fdsize to 1024*1024. * file.c (sys_getdents): Cap len to 1024*1024. (sys_getdents64): Cap len to 1024*1024. * util.c (dumpiov): Refuse to process iov with more than 1024*1024 elements. Don't die on malloc failure. (dumpstr): Don't die on malloc failure. Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
parent
0a295bc97f
commit
79a79ea851
11
desc.c
11
desc.c
@ -490,12 +490,19 @@ static int
|
||||
decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
|
||||
{
|
||||
int i, j, nfds;
|
||||
unsigned int fdsize = ((((args[0] + 7) / 8) + sizeof(long) - 1)
|
||||
& -sizeof(long));
|
||||
unsigned nfds, fdsize;
|
||||
fd_set *fds;
|
||||
const char *sep;
|
||||
long arg;
|
||||
|
||||
fdsize = args[0];
|
||||
/* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
|
||||
if (args[0] > 1024*1024)
|
||||
fdsize = 1024*1024;
|
||||
if (args[0] < 0)
|
||||
fdsize = 0;
|
||||
fdsize = (((fdsize + 7) / 8) + sizeof(long)-1) & -sizeof(long);
|
||||
|
||||
if (entering(tcp)) {
|
||||
fds = malloc(fdsize);
|
||||
if (!fds)
|
||||
|
19
file.c
19
file.c
@ -2421,6 +2421,11 @@ sys_getdents(struct tcb *tcp)
|
||||
return 0;
|
||||
}
|
||||
len = tcp->u_rval;
|
||||
/* Beware of insanely large or negative values in tcp->u_rval */
|
||||
if (tcp->u_rval > 1024*1024)
|
||||
len = 1024*1024;
|
||||
if (tcp->u_rval < 0)
|
||||
len = 0;
|
||||
buf = len ? malloc(len) : NULL;
|
||||
if (len && !buf)
|
||||
die_out_of_memory();
|
||||
@ -2502,10 +2507,17 @@ sys_getdents64(struct tcb *tcp)
|
||||
tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = tcp->u_rval;
|
||||
/* Beware of insanely large or negative tcp->u_rval */
|
||||
if (tcp->u_rval > 1024*1024)
|
||||
len = 1024*1024;
|
||||
if (tcp->u_rval < 0)
|
||||
len = 0;
|
||||
buf = len ? malloc(len) : NULL;
|
||||
if (len && !buf)
|
||||
die_out_of_memory();
|
||||
|
||||
if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
|
||||
tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
|
||||
free(buf);
|
||||
@ -2573,10 +2585,17 @@ sys_getdirentries(struct tcb *tcp)
|
||||
tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = tcp->u_rval;
|
||||
/* Beware of insanely large or negative tcp->u_rval */
|
||||
if (tcp->u_rval > 1024*1024)
|
||||
len = 1024*1024;
|
||||
if (tcp->u_rval < 0)
|
||||
len = 0;
|
||||
buf = malloc(len);
|
||||
if (!buf)
|
||||
die_out_of_memory();
|
||||
|
||||
if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
|
||||
tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
|
||||
free(buf);
|
||||
|
@ -269,7 +269,8 @@ pathtrace_match(struct tcb *tcp)
|
||||
s->sys_func == sys_oldselect ||
|
||||
s->sys_func == sys_pselect6)
|
||||
{
|
||||
int i, j, nfds;
|
||||
int i, j;
|
||||
unsigned nfds;
|
||||
long *args, oldargs[5];
|
||||
unsigned fdsize;
|
||||
fd_set *fds;
|
||||
@ -286,10 +287,14 @@ pathtrace_match(struct tcb *tcp)
|
||||
args = tcp->u_arg;
|
||||
|
||||
nfds = args[0];
|
||||
/* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
|
||||
if (args[0] > 1024*1024)
|
||||
nfds = 1024*1024;
|
||||
if (args[0] < 0)
|
||||
nfds = 0;
|
||||
fdsize = ((((nfds + 7) / 8) + sizeof(long) - 1)
|
||||
& -sizeof(long));
|
||||
fds = malloc(fdsize);
|
||||
|
||||
if (!fds)
|
||||
die_out_of_memory();
|
||||
|
||||
|
19
util.c
19
util.c
@ -686,12 +686,14 @@ dumpiov(struct tcb *tcp, int len, long addr)
|
||||
#define iov_iov_len(i) iov[i].iov_len
|
||||
#endif
|
||||
int i;
|
||||
unsigned long size;
|
||||
unsigned size;
|
||||
|
||||
size = sizeof_iov * (unsigned long) len;
|
||||
if (size / sizeof_iov != len /* overflow? */
|
||||
size = sizeof_iov * len;
|
||||
/* Assuming no sane program has millions of iovs */
|
||||
if ((unsigned)len > 1024*1024 /* insane or negative size? */
|
||||
|| (iov = malloc(size)) == NULL) {
|
||||
die_out_of_memory();
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
return;
|
||||
}
|
||||
if (umoven(tcp, addr, size, (char *) iov) >= 0) {
|
||||
for (i = 0; i < len; i++) {
|
||||
@ -703,7 +705,7 @@ dumpiov(struct tcb *tcp, int len, long addr)
|
||||
iov_iov_len(i));
|
||||
}
|
||||
}
|
||||
free((char *) iov);
|
||||
free(iov);
|
||||
#undef sizeof_iov
|
||||
#undef iov_iov_base
|
||||
#undef iov_iov_len
|
||||
@ -722,8 +724,11 @@ dumpstr(struct tcb *tcp, long addr, int len)
|
||||
if (strsize < len) {
|
||||
free(str);
|
||||
str = malloc(len);
|
||||
if (!str)
|
||||
die_out_of_memory();
|
||||
if (!str) {
|
||||
strsize = -1;
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
return;
|
||||
}
|
||||
strsize = len;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user