Skip site navigation (1)Skip section navigation (2)
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>