From owner-freebsd-bugs Fri Feb 6 14:50:02 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id OAA16322 for freebsd-bugs-outgoing; Fri, 6 Feb 1998 14:50:02 -0800 (PST) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: (from gnats@localhost) by hub.freebsd.org (8.8.8/8.8.8) id OAA16311; Fri, 6 Feb 1998 14:50:01 -0800 (PST) (envelope-from gnats) Received: from frmug.org (frmug-gw.frmug.org [193.56.58.252]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id OAA15973 for ; Fri, 6 Feb 1998 14:47:04 -0800 (PST) (envelope-from pb@fasterix.frmug.org) Received: (from uucp@localhost) by frmug.org (8.8.8/frmug-2.2/nospam) with UUCP id XAA09694 for FreeBSD-gnats-submit@freebsd.org; Fri, 6 Feb 1998 23:46:53 +0100 (CET) (envelope-from pb@fasterix.frmug.org) Received: (from pb@localhost) by fasterix.frmug.org (8.8.8/8.8.5/pb-19970302) id XAA04004; Fri, 6 Feb 1998 23:44:17 +0100 (CET) Message-Id: <199802062244.XAA04004@fasterix.frmug.org> Date: Fri, 6 Feb 1998 23:44:17 +0100 (CET) From: Pierre Beyssac Reply-To: pb@fasterix.freenix.org To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.2 Subject: bin/5669: rarpd is seriously broken Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org X-To-Unsubscribe: mail to majordomo@FreeBSD.org "unsubscribe freebsd-bugs" >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: