Package: arpwatch Version: 2.1a15-1.2 Severity: important Tags: patch Dear Maintainer,
after upgrading from squeeze I noticed arpwatch aborts upon start: | arpwatch: *** buffer overflow detected ***: /usr/sbin/arpwatch terminated Starting arpwatch manually shows: *** buffer overflow detected ***: /usr/sbin/arpwatch terminated ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f977f0232a7] /lib/x86_64-linux-gnu/libc.so.6(+0xee160)[0x7f977f022160] /usr/sbin/arpwatch[0x4038ba] /usr/sbin/arpwatch[0x403f1f] /usr/sbin/arpwatch[0x40489f] /usr/sbin/arpwatch[0x404f47] /usr/sbin/arpwatch[0x4025ad] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7f977ef52ead] /usr/sbin/arpwatch[0x402925] ======= Memory map: ======== 00400000-00408000 r-xp 00000000 08:05 25900 /usr/sbin/arpwatch 00607000-00608000 r--p 00007000 08:05 25900 /usr/sbin/arpwatch 00608000-00609000 rw-p 00008000 08:05 25900 /usr/sbin/arpwatch 00609000-00809000 rw-p 00000000 00:00 0 01d29000-01d6b000 rw-p 00000000 00:00 0 [heap] 7f977e2e7000-7f977e2fc000 r-xp 00000000 08:05 1208 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f977e2fc000-7f977e4fc000 ---p 00015000 08:05 1208 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f977e4fc000-7f977e4fd000 rw-p 00015000 08:05 1208 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f977e4fd000-7f977e508000 r-xp 00000000 08:05 7417 /lib/x86_64-linux-gnu/libnss_files-2.13.so 7f977e508000-7f977e707000 ---p 0000b000 08:05 7417 /lib/x86_64-linux-gnu/libnss_files-2.13.so 7f977e707000-7f977e708000 r--p 0000a000 08:05 7417 /lib/x86_64-linux-gnu/libnss_files-2.13.so 7f977e708000-7f977e709000 rw-p 0000b000 08:05 7417 /lib/x86_64-linux-gnu/libnss_files-2.13.so 7f977e709000-7f977e713000 r-xp 00000000 08:05 7429 /lib/x86_64-linux-gnu/libnss_nis-2.13.so 7f977e713000-7f977e912000 ---p 0000a000 08:05 7429 /lib/x86_64-linux-gnu/libnss_nis-2.13.so 7f977e912000-7f977e913000 r--p 00009000 08:05 7429 /lib/x86_64-linux-gnu/libnss_nis-2.13.so 7f977e913000-7f977e914000 rw-p 0000a000 08:05 7429 /lib/x86_64-linux-gnu/libnss_nis-2.13.so 7f977e914000-7f977e929000 r-xp 00000000 08:05 7427 /lib/x86_64-linux-gnu/libnsl-2.13.so 7f977e929000-7f977eb28000 ---p 00015000 08:05 7427 /lib/x86_64-linux-gnu/libnsl-2.13.so 7f977eb28000-7f977eb29000 r--p 00014000 08:05 7427 /lib/x86_64-linux-gnu/libnsl-2.13.so 7f977eb29000-7f977eb2a000 rw-p 00015000 08:05 7427 /lib/x86_64-linux-gnu/libnsl-2.13.so 7f977eb2a000-7f977eb2c000 rw-p 00000000 00:00 0 7f977eb2c000-7f977eb33000 r-xp 00000000 08:05 7419 /lib/x86_64-linux-gnu/libnss_compat-2.13.so 7f977eb33000-7f977ed32000 ---p 00007000 08:05 7419 /lib/x86_64-linux-gnu/libnss_compat-2.13.so 7f977ed32000-7f977ed33000 r--p 00006000 08:05 7419 /lib/x86_64-linux-gnu/libnss_compat-2.13.so 7f977ed33000-7f977ed34000 rw-p 00007000 08:05 7419 /lib/x86_64-linux-gnu/libnss_compat-2.13.so 7f977ed34000-7f977ef34000 rw-s 00000000 00:06 12829 socket:[12829] 7f977ef34000-7f977f0b4000 r-xp 00000000 08:05 7423 /lib/x86_64-linux-gnu/libc-2.13.so 7f977f0b4000-7f977f2b4000 ---p 00180000 08:05 7423 /lib/x86_64-linux-gnu/libc-2.13.so 7f977f2b4000-7f977f2b8000 r--p 00180000 08:05 7423 /lib/x86_64-linux-gnu/libc-2.13.so 7f977f2b8000-7f977f2b9000 rw-p 00184000 08:05 7423 /lib/x86_64-linux-gnu/libc-2.13.so 7f977f2b9000-7f977f2be000 rw-p 00000000 00:00 0 7f977f2be000-7f977f2de000 r-xp 00000000 08:05 7426 /lib/x86_64-linux-gnu/ld-2.13.so 7f977f495000-7f977f498000 rw-p 00000000 00:00 0 7f977f498000-7f977f4d0000 r-xp 00000000 08:05 25790 /usr/lib/x86_64-linux-gnu/libpcap.so.1.3.0 7f977f4d0000-7f977f4d2000 r--p 00037000 08:05 25790 /usr/lib/x86_64-linux-gnu/libpcap.so.1.3.0 7f977f4d2000-7f977f4d3000 rw-p 00039000 08:05 25790 /usr/lib/x86_64-linux-gnu/libpcap.so.1.3.0 7f977f4d3000-7f977f4d4000 rw-p 00000000 00:00 0 7f977f4da000-7f977f4dd000 rw-p 00000000 00:00 0 7f977f4dd000-7f977f4de000 r--p 0001f000 08:05 7426 /lib/x86_64-linux-gnu/ld-2.13.so 7f977f4de000-7f977f4df000 rw-p 00020000 08:05 7426 /lib/x86_64-linux-gnu/ld-2.13.so 7f977f4df000-7f977f4e0000 rw-p 00000000 00:00 0 7ffff0d01000-7ffff0d22000 rw-p 00000000 00:00 0 [stack] 7ffff0dff000-7ffff0e00000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Aborted Using a self-compiled arpwatch and gdb led to (gdb) bt #0 0x00007ffff7a85475 in raise () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff7a886f0 in abort () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x00007ffff7ac052b in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #3 0x00007ffff7b422a7 in __fortify_fail () from /lib/x86_64-linux-gnu/libc.so.6 #4 0x00007ffff7b41160 in __chk_fail () from /lib/x86_64-linux-gnu/libc.so.6 #5 0x0000000000403909 in strcpy (__src=0x7fffffffe00b "a-hostname-longer-than-34-characters", __dest=0x82c0f6 "a-hostname-longer-than-34-characte") at /usr/include/x86_64-linux-gnu/bits/string3.h:105 #6 elist_alloc (a=a@entry=2490776406, e=e@entry=0x7fffffffdfd0 "\002", t=1366566013, h=h@entry=0x7fffffffe00b "a-hostname-longer-than-34-characters", interface=interface@entry=0x7fffffffe030 "eth0") at ./db.c:297 #7 0x0000000000403f6d in ent_add (a=a@entry=2490776406, e=e@entry=0x7fffffffdfd0 "\002", t=t@entry=1366566013, h=0x7fffffffe00b "a-hostname-longer-than-34-characters", interface=interface@entry=0x7fffffffe030 "eth0") at ./db.c:125 #8 0x000000000040487a in file_loop (f=f@entry=0x82bdf0, fn=0x403bb0 <ent_add>, name=0x7fffffffe90e "eth0.dat") at ./file.c:145 #9 0x0000000000404f57 in readdata () at ./util.c:163 #10 0x00000000004025f7 in main (argc=<optimized out>, argv=<optimized out>) at ./arpwatch.c:445 (gdb) which is the strcpy in elist_alloc in ec.c: if (h != NULL && !isdigit((int)*h)) strcpy(ep->h, h); ep->t = t; Analysis: In earlier versions, arpwatch would more or less happily handle hostnames returned in IP lookups that are longer than 33 octets, resulting in /var/lib/arpwatch/eth0.dat hostnames records longer that arpwatch can handle. In wheezy, at least on amd64, reading that file upon start now triggers the error above. Earlier, you could probably overwrite memory in the arpwatch process, although exploiting that doesn't look like an easy job. How to repeat: * stop arpwatch * add a line with a long hostname to /var/lib/arpwatch/eth0.dat, for example (note: MUST be tab separated): 02:00:de:ad:be:ef 86.59.118.148 1366566013 a-hostname-longer-than-34-characters eth0 * Start arpwatch /usr/sbin/arpwatch -d -i eth0 -f eth0.dat -N -u arpwatch -p How to repair: On an affected installation: Stop arpwatch and remove the offending lines from /var/lib/arpwatch/*.dat How to fix: The patch below uses strncpy (in one case: fixes strncpy usage) in three places that seem to be vulnerable. Interface names with more than 16 characters might be a bit unusual but playing safe is the better idea. The other usages of strcpy and strncat in the sources look somewhat OK, although the constraints are well hidden. Note: A previous analysis of that error had been done in https://bugs.launchpad.net/ubuntu/+source/arpwatch/+bug/1097289 Christoph -- System Information: Debian Release: 7.0 APT prefers testing APT policy: (500, 'testing') Architecture: amd64 (x86_64) Kernel: Linux 3.4.38 Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages arpwatch depends on: ii adduser 3.113+nmu3 ii libc6 2.13-38 ii libpcap0.8 1.3.0-1 arpwatch recommends no packages. arpwatch suggests no packages. -- Configuration Files: /etc/arpwatch.conf changed [not included] -- no debconf information commit 3a56bb6499ea57de9711e9c53280d94601d2de18 Author: Christoph Biedl <debian.a...@manchmal.in-ulm.de> Date: Sun Apr 21 20:38:44 2013 +0200 Protect some string copy operations diff --git a/db.c b/db.c index 03089dc..bdfcff3 100644 --- a/db.c +++ b/db.c @@ -293,11 +293,15 @@ elist_alloc(register u_int32_t a, register u_char *e, register time_t t, BCOPY(e, ep->e, 6); if (h == NULL && !initializing) h = getsname(a); - if (h != NULL && !isdigit((int)*h)) - strcpy(ep->h, h); + if (h != NULL && !isdigit((int)*h)) { + strncpy(ep->h, h, 34); + ep->h[33] = '\0'; + } ep->t = t; - if (interface != NULL) + if (interface != NULL) { strncpy(ep->i, interface, 16); + ep->i[15] = '\0'; + } return (ep); } @@ -316,7 +320,8 @@ check_hname(register struct ainfo *ap) if (!isdigit((int)*h) && strcmp(h, ep->h) != 0) { syslog(LOG_INFO, "hostname changed %s %s %s -> %s", intoa(ap->a), e2str(ep->e), ep->h, h); - strcpy(ep->h, h); + strncpy(ep->h, h, 34); + ep->h[33] = '\0'; } }
signature.asc
Description: Digital signature