lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Mon, 23 Feb 2009 15:22:13 +0100 From: Eric Sesterhenn <snakebyte@....de> To: netdev@...r.kernel.org Subject: VM_BUG_ON triggered with udp6fuzz hi, first of all, i am not able to replicate this after a clean boot, running the command sudo -u snakebyte lf6/udp6fuzz -n 100 -r 9343 produced the following BUG on my test box Not sure where the get_page was triggered from, could not find it in udp6.c ... [ 7410.317001] ------------[ cut here ]------------ [ 7410.317033] Kernel BUG at c0683663 [verbose debug info unavailable] [ 7410.317033] invalid opcode: 0000 [#1] PREEMPT DEBUG_PAGEALLOC [ 7410.317033] last sysfs file: /sys/class/vc/vcs11/dev [ 7410.317033] Modules linked in: [last unloaded: rcutorture] [ 7410.317033] [ 7410.317033] Pid: 9343, comm: udp6fuzz Not tainted (2.6.29-rc6 #7) System Name [ 7410.317033] EIP: 0060:[<c0683663>] EFLAGS: 00010246 CPU: 0 [ 7410.317033] EIP is at ip6_append_data+0x7df/0x9d5 [ 7410.317033] EAX: 00000000 EBX: 00000000 ECX: 00000004 EDX: c12668a0 [ 7410.317033] ESI: c47889ec EDI: cd5319a0 EBP: cbc2ccc4 ESP: cbc2cc70 [ 7410.317033] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 [ 7410.317033] Process udp6fuzz (pid: 9343, ti=cbc2c000 task=c4630000 task.ti=cbc2c000) [ 7410.317033] Stack: [ 7410.317033] cbc2cf50 c063fbf2 cd434000 00000000 00000028 00000000 00000010 00004034 [ 7410.317033] 00000000 cbc2cc9c c013e492 cbc2cca8 c12668a0 00000cee 00004028 00000000 [ 7410.317033] 00000000 00000002 00000cee cbc2cf34 cd434000 cbc2cdb4 c0693ba6 00000cee [ 7410.317033] Call Trace: [ 7410.317033] [<c063fbf2>] ? ip_generic_getfrag+0x0/0x8f [ 7410.317033] [<c013e492>] ? trace_hardirqs_on+0xb/0xd [ 7410.317033] [<c0693ba6>] ? udpv6_sendmsg+0x751/0x9ee [ 7410.317033] [<c013fc3d>] ? __lock_acquire+0x6a8/0x6fe [ 7410.317033] [<c0106d88>] ? native_sched_clock+0x41/0x68 [ 7410.317033] [<c012582c>] ? local_bh_enable_ip+0xa0/0xb8 [ 7410.317033] [<c013e449>] ? trace_hardirqs_on_caller+0x10d/0x14b [ 7410.317033] [<c0613b8c>] ? release_sock+0xb1/0xb9 [ 7410.317033] [<c013e492>] ? trace_hardirqs_on+0xb/0xd [ 7410.317033] [<c012582c>] ? local_bh_enable_ip+0xa0/0xb8 [ 7410.317033] [<c065e0d7>] ? inet_sendmsg+0x3b/0x48 [ 7410.317033] [<c061218f>] ? sock_sendmsg+0xc9/0xe0 [ 7410.317033] [<c013bcfd>] ? put_lock_stats+0xd/0x21 [ 7410.317033] [<c01315c9>] ? autoremove_wake_function+0x0/0x30 [ 7410.317033] [<c013fdba>] ? lock_release_non_nested+0xb0/0x1f8 [ 7410.317033] [<c0174812>] ? might_fault+0x4a/0x86 [ 7410.317033] [<c0174812>] ? might_fault+0x4a/0x86 [ 7410.317033] [<c0612a88>] ? sys_sendto+0xa4/0xc3 [ 7410.317033] [<c0106d88>] ? native_sched_clock+0x41/0x68 [ 7410.317033] [<c013bcfd>] ? put_lock_stats+0xd/0x21 [ 7410.317033] [<c013bdb0>] ? lock_release_holdtime+0x9f/0xa7 [ 7410.317033] [<c013fdba>] ? lock_release_non_nested+0xb0/0x1f8 [ 7410.317033] [<c0174812>] ? might_fault+0x4a/0x86 [ 7410.317033] [<c06131d7>] ? sys_socketcall+0xe6/0x17b [ 7410.317033] [<c0102dc1>] ? sysenter_do_call+0x12/0x31 [ 7410.317033] Code: 74 02 0c 8b 55 dc 3b 16 0f 84 e9 00 00 00 66 83 fb 12 0f 84 d6 00 00 00 8b 55 dc f6 42 01 40 74 03 8b 52 0c 8b 42 04 85 c0 75 04 <0f> 0b eb fe ff 42 04 8b 75 b4 6b 55 b8 0c 8b 87 94 00 00 00 8b [ 7410.317033] EIP: [<c0683663>] ip6_append_data+0x7df/0x9d5 SS:ESP 0068:cbc2cc70 [ 7410.408156] ---[ end trace 228f803a591a2d43 ]--- 0xc0683663 is in ip6_append_data (include/linux/mm.h:302). 297 } 298 299 static inline void get_page(struct page *page) 300 { 301 page = compound_head(page); 302 VM_BUG_ON(atomic_read(&page->_count) == 0); 303 atomic_inc(&page->_count); 304 } 305 306 static inline struct page *virt_to_head_page(const void *x) The fuzzer used: ---------------------------8<----------------------------- /* * UDP/IPv6 or UDP/IPv6 socket fuzzer. * * Copyright (C) 2006, Clément Lecigne */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/param.h> #include <net/if.h> //#include <net/if_var.h> #include <sys/uio.h> //#include <netinet6/ip6_mroute.h> //#include <netinet6/in6_var.h> #define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */ #define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1) #define SIOCGETRPF (SIOCPROTOPRIVATE+2) unsigned int randaddr(void); void randsoopt(int); void randgoopt(int); void randioctl(int); void usage(char *); void fuzzlog(char *func, char *fmt, ...); unsigned int count = 0; /* * boucle until we hit a valid socket option */ void randsoopt(int sock) { unsigned int optval; int optlen, optname, level, ret, on = rand() % 2; do { switch (rand() % 5) { case 0: level = IPPROTO_IPV6; break; case 1: level = SOL_SOCKET; break; case 2: level = IPPROTO_UDP; break; case 3: level = rand() & 0xFF; break; case 4: level = IPPROTO_IP; break; } if (rand() % 6) { optlen = rand(); optval = (unsigned int)randaddr(); } else { /* * In some cases, kernel excepts that * optlen == sizeof (int) and that's * generally the first bound checking. */ optlen = sizeof (int); on = rand(); optval = (unsigned int)&on; } if (rand() % 8) optname = rand() % 255; else optname = rand(); #if 0 /* * anti well know mbufs exhaustion. (FreeBSD) */ if (optname == 25 || optname == IPV6_IPSEC_POLICY || optname == IPV6_FW_ADD || optname == IPV6_FW_FLUSH || optname == IPV6_FW_DEL || optname == IPV6_FW_ZERO) continue; #endif ret = setsockopt(sock, level, optname, (void *)optval, optlen); }while(ret == -1); } /* * ioctl fuzzer. */ void randioctl(int sock) { unsigned long reqs[] = { SIOCGETSGCNT_IN6, SIOCGETMIFCNT_IN6, SIOCGETRPF}; /* SIOCGSCOPE6DEF, SIOCGLIFADDR, SIOCSIFPHYADDR_IN6, SIOCGIFNETMASK_IN6, SIOCAIFADDR_IN6, SIOCGIFDSTADDR_IN6, SIOCSIFALIFETIME_IN6, SIOCGIFADDR_IN6, SIOCGIFDSTADDR_IN6, SIOCGIFNETMASK_IN6, SIOCGIFAFLAG_IN6, SIOCGIFSTAT_IN6, SIOCGIFSTAT_ICMP6, SIOCGIFALIFETIME_IN6, SIOCSIFALIFETIME_IN6, SIOCAIFADDR_IN6, SIOCDIFADDR_IN6 }; */ unsigned int arg; int ret; unsigned long request; if (rand() % 8) request = reqs[rand() % (sizeof (reqs) / sizeof (reqs[0]))]; else request = rand() + rand(); if (rand() % 2) { arg = randaddr(); ret = ioctl(sock, request, (caddr_t)arg); } else { arg = rand(); ret = ioctl(sock, request, (int)arg); } } /* * return a possible random mapped address */ unsigned int randaddr(void) { char *p = malloc(1); unsigned int heap = (unsigned int)p; free(p); switch (rand() % 4) { case 0: return (heap + (rand() & 0xFFF)); case 1: return ((unsigned int)&heap + (rand() & 0xFFF)); case 2: return (0xc0000000 + (rand() & 0xFFFF)); case 3: return (rand()); } return (0); } int main(int ac, char **av) { int32_t cc, s, occ, i, j, try, count, opts; u_int32_t seed, maxsize; u_int8_t ip6; char c, *buf, *port = "1337"; struct addrinfo *res, hints; struct sockaddr_in6 from; socklen_t fromlen; struct msghdr msg; struct cmsghdr *cmsg = NULL; struct iovec iov; /* default values */ seed = getpid(); count = 50; occ = 1000; maxsize = 4096; opts = 50; ip6 = 1; fromlen = sizeof(from); while ((c = getopt(ac, av, "r:n:c:p:m:o:f:l:46")) != EOF) { switch (c) { case '6': ip6 = 1; break; case '4': ip6 = 0; break; case 'r': seed = atoi(optarg); break; case 'n': occ = atoi(optarg); break; case 'c': count = atoi(optarg); break; case 'p': port = optarg; break; case 'm': maxsize = atoi(optarg); break; case 'o': opts = atoi(optarg); break; default: usage(av[0]); break; } } printf("seeding with %u\n", seed); srand(seed); buf = malloc(maxsize); if (buf == NULL) { printf("%s: out of memory.\n", av[0]); exit(1); } memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; if(ip6) { hints.ai_family = AF_INET6; getaddrinfo("::1", port, &hints, &res); } else { hints.ai_family = AF_INET; getaddrinfo("127.0.0.1", port, &hints, &res); } for (i = 0; i < occ; i++) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); cc = bind(s, res->ai_addr, res->ai_addrlen); for (j = 0; j < opts; j++) { randsoopt(s); randioctl(s); try = 0; do { switch(rand() % 3) { case 0: cc = sendto(s, &buf, rand() % maxsize, rand() % 8, (struct sockaddr *)res->ai_addr, res->ai_addrlen); break; case 1: case 2: msg.msg_controllen = (rand() % 2) ? rand() & maxsize : 0; if (msg.msg_controllen) { if (msg.msg_controllen < sizeof (struct cmsghdr)) cmsg = (struct cmsghdr *)malloc(sizeof (struct cmsghdr)); else cmsg = (struct cmsghdr *)malloc(msg.msg_controllen); if (cmsg == NULL) goto nocmsghdr; msg.msg_control = cmsg; cmsg->cmsg_level = (rand() % 2) ? IPPROTO_IPV6 : rand(); cmsg->cmsg_type = (rand() % 2) ? rand() % 255 : rand(); cmsg->cmsg_len = (rand() % 2) ? msg.msg_controllen : rand(); } else { nocmsghdr: msg.msg_control = (rand() % 5) ? NULL : (void*)randaddr(); msg.msg_controllen = (rand() % 2) ? rand() : 0; } iov.iov_len = (rand() % 2) ? rand() : rand() & maxsize; iov.iov_base = (rand() % 2) ? (void*)randaddr() : &s; msg.msg_iov = (rand() % 2) ? (void*)randaddr() : &iov; if (rand() % 10) { msg.msg_name = res->ai_addr; msg.msg_namelen = res->ai_addrlen; } else { msg.msg_name = (caddr_t)randaddr(); msg.msg_namelen = rand(); } msg.msg_flags = rand(); cc = sendmsg (s, &msg, rand()); } if (cmsg != NULL) { //free(cmsg); //cmsg = NULL; } try++; } while(cc == -1 && try != count); recvmsg(s, &msg, MSG_DONTWAIT); } close(s); } free(buf); freeaddrinfo(res); exit(0); } /* * usage */ void usage(char *prog) { printf("usage: %s [-4] [-6] [-r seed] [-c sendto-timeout]\n" " [-m maxsize] [-o maxsetsockopt] [-n occ]\n" " [-p udp-port]\n", prog); exit(1); } -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists