diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-12-09 00:46:44 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-12-09 00:46:44 +0000 |
commit | b67f44165c3559e9554f5540df1e41adb4b9cdaf (patch) | |
tree | 6dc37392661fabb315193ed5aefab875382dbbd6 /usr.bin | |
parent | d4fbfb0d8780ad1597236e77f08a27b32babd929 (diff) |
Add some additional sanity checks to kdump.
Fixes a variety of crashes found with the afl fuzzer.
ok miod@ on an earlier version.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/kdump/kdump.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index b8f884383a5..7b2a6406428 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kdump.c,v 1.92 2014/12/08 21:23:44 guenther Exp $ */ +/* $OpenBSD: kdump.c,v 1.93 2014/12/09 00:46:43 jsg Exp $ */ /*- * Copyright (c) 1988, 1993 @@ -142,7 +142,7 @@ static void ktremul(char *, size_t); static void ktrgenio(struct ktr_genio *, size_t); static void ktrnamei(const char *, size_t); static void ktrpsig(struct ktr_psig *); -static void ktrsyscall(struct ktr_syscall *); +static void ktrsyscall(struct ktr_syscall *, size_t); static const char *kresolvsysctl(int, int *, int); static void ktrsysret(struct ktr_sysret *); static void ktruser(struct ktr_user *, size_t); @@ -262,7 +262,7 @@ main(int argc, char *argv[]) current = findemul(ktr_header.ktr_pid); switch (ktr_header.ktr_type) { case KTR_SYSCALL: - ktrsyscall((struct ktr_syscall *)m); + ktrsyscall((struct ktr_syscall *)m, ktrlen); break; case KTR_SYSRET: ktrsysret((struct ktr_sysret *)m); @@ -878,12 +878,16 @@ static const formatter scargs[][8] = { static void -ktrsyscall(struct ktr_syscall *ktr) +ktrsyscall(struct ktr_syscall *ktr, size_t ktrlen) { register_t *ap; int narg; char sep; + if (ktr->ktr_argsize > ktrlen) + errx(1, "syscall argument length %d > ktr header length %zu", + ktr->ktr_argsize, ktrlen); + narg = ktr->ktr_argsize / sizeof(register_t); sep = '\0'; @@ -906,6 +910,8 @@ ktrsyscall(struct ktr_syscall *ktr) n = ap[1]; if (n > CTL_MAXNAME) n = CTL_MAXNAME; + if (n < 0) + errx(1, "invalid sysctl length %d", n); np = top = (int *)(ap + 6); for (i = 0; n--; np++, i++) { if (sep) @@ -941,7 +947,7 @@ ktrsyscall(struct ktr_syscall *ktr) } nonnative: - while (narg) { + while (narg > 0) { if (sep) putchar(sep); if (decimal) @@ -1250,7 +1256,12 @@ static void ktrgenio(struct ktr_genio *ktr, size_t len) { unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio); - size_t datalen = len - sizeof(struct ktr_genio); + size_t datalen; + + if (len < sizeof(struct ktr_genio)) + errx(1, "invalid ktr genio length %zu", len); + + datalen = len - sizeof(struct ktr_genio); printf("fd %d %s %zu bytes\n", ktr->ktr_fd, ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen); @@ -1266,7 +1277,7 @@ ktrgenio(struct ktr_genio *ktr, size_t len) static void ktrpsig(struct ktr_psig *psig) { - (void)printf("SIG%s ", sys_signame[psig->signo]); + signame(psig->signo); if (psig->action == SIG_DFL) (void)printf("SIG_DFL"); else { @@ -1328,6 +1339,8 @@ ktrcsw(struct ktr_csw *cs) static void ktruser(struct ktr_user *usr, size_t len) { + if (len < sizeof(struct ktr_user)) + errx(1, "invalid ktr user length %zu", len); len -= sizeof(struct ktr_user); printf("%.*s:", KTR_USER_MAXIDLEN, usr->ktr_id); printf(" %zu bytes\n", len); |