Fix decoding of execve and execveat syscalls with invalid input
* execve.c (printargv): Fix decoding of inaccessible or partially inaccessible array. (printargc): Diagnose inaccessible or partially inaccessible array. (decode_execve, SYS_FUNC(execv)): Update printargv and printargc callers.
This commit is contained in:
111
execve.c
111
execve.c
@ -36,41 +36,72 @@
|
|||||||
static void
|
static void
|
||||||
printargv(struct tcb *tcp, long addr)
|
printargv(struct tcb *tcp, long addr)
|
||||||
{
|
{
|
||||||
union {
|
if (!addr || !verbose(tcp)) {
|
||||||
unsigned int p32;
|
printaddr(addr);
|
||||||
unsigned long p64;
|
return;
|
||||||
char data[sizeof(long)];
|
|
||||||
} cp;
|
|
||||||
const char *sep;
|
|
||||||
unsigned int n = 0;
|
|
||||||
const unsigned wordsize = current_wordsize;
|
|
||||||
|
|
||||||
cp.p64 = 1;
|
|
||||||
for (sep = ""; !abbrev(tcp) || n < max_strlen / 2; sep = ", ", ++n) {
|
|
||||||
if (umoven_or_printaddr(tcp, addr, wordsize, cp.data))
|
|
||||||
return;
|
|
||||||
if (wordsize == 4)
|
|
||||||
cp.p64 = cp.p32;
|
|
||||||
if (cp.p64 == 0)
|
|
||||||
break;
|
|
||||||
tprints(sep);
|
|
||||||
printstr(tcp, cp.p64, -1);
|
|
||||||
addr += wordsize;
|
|
||||||
}
|
}
|
||||||
if (cp.p64)
|
|
||||||
tprintf("%s...", sep);
|
const char *const start_sep = "[";
|
||||||
|
const char *sep = start_sep;
|
||||||
|
const unsigned int wordsize = current_wordsize;
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
for (n = 0; addr; sep = ", ", addr += wordsize, ++n) {
|
||||||
|
union {
|
||||||
|
unsigned int p32;
|
||||||
|
unsigned long p64;
|
||||||
|
char data[sizeof(long)];
|
||||||
|
} cp;
|
||||||
|
|
||||||
|
if (umoven(tcp, addr, wordsize, cp.data)) {
|
||||||
|
if (sep == start_sep)
|
||||||
|
printaddr(addr);
|
||||||
|
else
|
||||||
|
tprints(", ???]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(wordsize < sizeof(cp.p64) ? cp.p32 : cp.p64)) {
|
||||||
|
if (sep == start_sep)
|
||||||
|
tprints(start_sep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (abbrev(tcp) && n >= max_strlen) {
|
||||||
|
tprintf("%s...", sep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tprints(sep);
|
||||||
|
printstr(tcp, wordsize < sizeof(cp.p64) ? cp.p32 : cp.p64, -1);
|
||||||
|
}
|
||||||
|
tprints("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
printargc(const char *fmt, struct tcb *tcp, long addr)
|
printargc(struct tcb *tcp, long addr)
|
||||||
{
|
{
|
||||||
int count;
|
if (!addr || !verbose(tcp)) {
|
||||||
|
printaddr(addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unterminated = false;
|
||||||
|
unsigned int count = 0;
|
||||||
char *cp = NULL;
|
char *cp = NULL;
|
||||||
|
|
||||||
for (count = 0; !umoven(tcp, addr, current_wordsize, &cp) && cp; count++) {
|
for (; addr; addr += current_wordsize, ++count) {
|
||||||
addr += current_wordsize;
|
if (umoven(tcp, addr, current_wordsize, &cp)) {
|
||||||
|
if (count) {
|
||||||
|
unterminated = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printaddr(addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!cp)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
tprintf(fmt, count, count == 1 ? "" : "s");
|
tprintf("[/* %u var%s%s */]",
|
||||||
|
count, count == 1 ? "" : "s",
|
||||||
|
unterminated ? ", unterminated" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -79,24 +110,10 @@ decode_execve(struct tcb *tcp, const unsigned int index)
|
|||||||
printpath(tcp, tcp->u_arg[index + 0]);
|
printpath(tcp, tcp->u_arg[index + 0]);
|
||||||
tprints(", ");
|
tprints(", ");
|
||||||
|
|
||||||
if (!tcp->u_arg[index + 1] || !verbose(tcp))
|
printargv(tcp, tcp->u_arg[index + 1]);
|
||||||
printaddr(tcp->u_arg[index + 1]);
|
|
||||||
else {
|
|
||||||
tprints("[");
|
|
||||||
printargv(tcp, tcp->u_arg[index + 1]);
|
|
||||||
tprints("]");
|
|
||||||
}
|
|
||||||
tprints(", ");
|
tprints(", ");
|
||||||
|
|
||||||
if (!tcp->u_arg[index + 2] || !verbose(tcp))
|
(abbrev(tcp) ? printargc : printargv) (tcp, tcp->u_arg[index + 2]);
|
||||||
printaddr(tcp->u_arg[index + 2]);
|
|
||||||
else if (abbrev(tcp))
|
|
||||||
printargc("[/* %d var%s */]", tcp, tcp->u_arg[index + 2]);
|
|
||||||
else {
|
|
||||||
tprints("[");
|
|
||||||
printargv(tcp, tcp->u_arg[index + 2]);
|
|
||||||
tprints("]");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYS_FUNC(execve)
|
SYS_FUNC(execve)
|
||||||
@ -121,13 +138,7 @@ SYS_FUNC(execv)
|
|||||||
{
|
{
|
||||||
printpath(tcp, tcp->u_arg[0]);
|
printpath(tcp, tcp->u_arg[0]);
|
||||||
tprints(", ");
|
tprints(", ");
|
||||||
if (!tcp->u_arg[1] || !verbose(tcp))
|
printargv(tcp, tcp->u_arg[1]);
|
||||||
printaddr(tcp->u_arg[1]);
|
|
||||||
else {
|
|
||||||
tprints("[");
|
|
||||||
printargv(tcp, tcp->u_arg[1]);
|
|
||||||
tprints("]");
|
|
||||||
}
|
|
||||||
|
|
||||||
return RVAL_DECODED;
|
return RVAL_DECODED;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user