Date: Fri, 6 Feb 1998 23:44:17 +0100 (CET) From: Pierre Beyssac <pb@fasterix.freenix.org> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: bin/5669: rarpd is seriously broken Message-ID: <199802062244.XAA04004@fasterix.frmug.org>
next in thread | raw e-mail | index | archive | help
>Number: 5669 >Category: bin >Synopsis: rarpd is seriously broken >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Feb 6 14:50:00 PST 1998 >Last-Modified: >Originator: Pierre Beyssac >Organization: individual >Release: FreeBSD 3.0-CURRENT i386 >Environment: FreeBSD-current server with a diskless (OpenBSD/sparc) machine booting from it. This might apply to 2.2-STABLE rarpd too, please check if it uses the routing socket like -current does (I don't have 2.2-STABLE sources handy). >Description: rarpd works for a while (at least once), then hangs (doesn't die). Explanation of the bug: when processing its first request, rarpd opens a routing socket to send requests to the arp table. It keeps that socket open afterwards, while waiting for new RARP requests. Meanwhile, the data received on the routing socket fill up until they are about 8Kbytes in size. Any additional data is lost. When rarpd receives its next RARP request, it tries to access the ARP table via a routing socket call, then waits for the answer to its own request. This answer is lost because the received data is already filled: when looking for the reply, rarpd receives only 8kbytes worth of data, then loops waiting forever. >How-To-Repeat: 1) start rarpd on the FreeBSD server 2) boot a diskless machine 3) wait for about 10 minutes (more or less, depending on routing socket traffic on the FreeBSD machine). Just enough time for at least 8kbytes of data to accumulate on the routing socket. 4) try to boot the diskless machine again -> timeouts on RARP requests. >Fix: Proposed (partial) fix: close the routing socket when unused. Note: this isn't 100% robust as it won't cover the cases where the routing socket is flooded by over 8kbytes data between the time we open the socket and the time we get a reply. This might provide for interesting deny-of-service attacks. "arp" (and possibly others) seems to suffer the same kind of problem, but it's less anoying as it doesn't run as a daemon. A 100% robust solution (for example, through use of a timeout + repeated requests) might be a good idea. --- rarpd.c.orig Tue Jan 20 22:24:16 1998 +++ rarpd.c Fri Feb 6 23:13:30 1998 @@ -766,18 +766,15 @@ register struct rt_msghdr *rt; register int xtype, xindex; static pid_t pid; - static int r, seq; - static init = 0; + int r; + static seq; - if (!init) { - r = socket(PF_ROUTE, SOCK_RAW, 0); - if (r < 0) { - syslog(LOG_ERR, "raw route socket: %m"); - exit(1); - } - pid = getpid(); - ++init; + r = socket(PF_ROUTE, SOCK_RAW, 0); + if (r < 0) { + syslog(LOG_ERR, "raw route socket: %m"); + exit(1); } + pid = getpid(); ar = &sin_inarp; ar->sin_addr.s_addr = ipaddr; @@ -797,6 +794,7 @@ errno = 0; if (write(r, rt, rt->rtm_msglen) < 0 && errno != ESRCH) { syslog(LOG_ERR, "rtmsg get write: %m"); + close(r); return; } do { @@ -804,6 +802,7 @@ } while (cc > 0 && (rt->rtm_seq != seq || rt->rtm_pid != pid)); if (cc < 0) { syslog(LOG_ERR, "rtmsg get read: %m"); + close(r); return; } ll2 = (struct sockaddr_dl *)((u_char *)ar2 + ar2->sin_len); @@ -815,6 +814,7 @@ */ syslog(LOG_ERR, "bogus link family (%d) wrong net for %08X?\n", ll2->sdl_family, ipaddr); + close(r); return; } xtype = ll2->sdl_type; @@ -841,11 +841,13 @@ errno = 0; if (write(r, rt, rt->rtm_msglen) < 0 && errno != EEXIST) { syslog(LOG_ERR, "rtmsg add write: %m"); + close(r); return; } do { cc = read(r, rt, sizeof(rtmsg)); } while (cc > 0 && (rt->rtm_seq != seq || rt->rtm_pid != pid)); + close(r); if (cc < 0) { syslog(LOG_ERR, "rtmsg add read: %m"); return; >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802062244.XAA04004>