Vulnerabilities in udev

Ken Moffat ken at linuxfromscratch.org
Mon Apr 27 14:45:40 PDT 2009


On Mon, Apr 27, 2009 at 02:28:39PM -0500, Mike McCarty wrote:
> 
> Well, you see there are two exposures involved, the obvious one
> 
> 	possible exploit of known vulnerability
> 
> and the less obvious one
> 
> 	replacing working code with with defective code
> 
> The first exposure is relatively easy to evaluate; the latter is less
> so, but exists nonetheless. I like to hear that a given patch or other
> fix has "burnt in" for a while, especially where exposure due to
> the know vulnerability has low or even nonexistent possibility of
> exploit.

 All I can say about burn-in is that I've used it on 3 LFS-6.4-based
systems on 2 boxes (one box has both 6.4-rc1 and a later build using
the release and sometimes different dekstop packages.  All the
expected devices (including my custom symlinks for a usb stick and
my camera) appear.  I've been told of a build on a server where it
also seems to work.  More review would have been nice, but nobody
felt able.

 The most likely breakage would probably be in the dbus and hal area
(but it would imply hal was doing something wrong).  I don't build
hal, and for me dbus is really only there as a build-time dependency
for certain gnome or kde packages.

 The nastiest would be if I've b0rken the fix.  For that, you really
need to spend time reviewing the patch, and how I arrived at it.
The buffer overflow is straightforward, I copied the full git patch
from upstream into the combined patch (which is why it applies with
fuzz), so I don't believe review of that part is needed.  For the
more important netlink fix, I started with the fedora backport, then
applied it by hand.  The original expand's Kay Siever's first fix and the word
is that either of the two upstream patches will do (see e.g. last
week's lwn.net - for the moment the article is subscribers only - or
just look at what fedora have chosen to include.

 I'll attach Scott's patch, and also the version for udev-12x from
fedora.  URI's are
http://git.kernel.org/?p=linux/hotplug/udev.git;a=commitdiff;h=e86a923d508c2aed371cdd958ce82489cf2ab615
and
http://cvs.fedoraproject.org/viewvc/rpms/udev/F-10/udev-CVE-2009-1185.patch?view=markup

ĸen
-- 
das eine Mal als Tragödie, das andere Mal als Farce
-------------- next part --------------
diff -ruNp udev-124~/udevd.c udev-124/udevd.c
--- udev-124~/udev/udevd.c	2008-06-11 22:24:30.000000000 -0700
+++ udev-124/udev/udevd.c	2009-04-08 16:30:06.000000000 -0700
@@ -753,16 +753,34 @@ static struct udevd_uevent_msg *get_netl
 	struct udevd_uevent_msg *msg;
 	int bufpos;
 	ssize_t size;
+	struct sockaddr_nl snl;
+	struct msghdr smsg;
+	struct iovec iov;
 	static char buffer[UEVENT_BUFFER_SIZE+512];
 	char *pos;
 
-	size = recv(uevent_netlink_sock, &buffer, sizeof(buffer), 0);
+	iov.iov_base = buffer;
+	iov.iov_len = sizeof(buffer);
+
+	memset(&smsg, 0x00, sizeof(struct msghdr));
+	smsg.msg_name = &snl;
+	smsg.msg_namelen = sizeof(struct sockaddr_nl);
+	smsg.msg_iov = &iov;
+	smsg.msg_iovlen = 1;
+
+	size = recvmsg(uevent_netlink_sock, &smsg, 0);
 	if (size <  0) {
 		if (errno != EINTR)
 			err("unable to receive kernel netlink message: %s\n", strerror(errno));
 		return NULL;
 	}
 
+	if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) {
+		info("ignored netlink message from invalid group/sender %d/%d\n",
+		     snl.nl_groups, snl.nl_pid);
+		return NULL;
+	}
+
 	if ((size_t)size > sizeof(buffer)-1)
 		size = sizeof(buffer)-1;
 	buffer[size] = '\0';
-------------- next part --------------
From: Scott James Remnant <scott at ubuntu.com>
Date: Wed, 8 Apr 2009 23:16:14 +0000 (-0700)
Subject: libudev: monitor - ignore messages from unusual sources
X-Git-Tag: 141~1
X-Git-Url: http://git.kernel.org/?p=linux%2Fhotplug%2Fudev.git;a=commitdiff_plain;h=e86a923d508c2aed371cdd958ce82489cf2ab615

libudev: monitor - ignore messages from unusual sources

For added protection, ignore any unicast message received on the
netlink socket or any multicast message on the kernel group not
received from the kernel.

Signed-off-by: Scott James Remnant <scott at ubuntu.com>
---

diff --git a/udev/lib/libudev-monitor.c b/udev/lib/libudev-monitor.c
index 21bd19b..79627ed 100644
--- a/udev/lib/libudev-monitor.c
+++ b/udev/lib/libudev-monitor.c
@@ -260,6 +260,7 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito
 	struct iovec iov;
 	char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
 	struct cmsghdr *cmsg;
+	struct sockaddr_nl snl;
 	struct ucred *cred;
 	char buf[4096];
 	size_t bufpos;
@@ -280,34 +281,50 @@ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monito
 	smsg.msg_control = cred_msg;
 	smsg.msg_controllen = sizeof(cred_msg);
 
+	if (udev_monitor->snl.nl_family != 0) {
+		smsg.msg_name = &snl;
+		smsg.msg_namelen = sizeof snl;
+	}
+
 	if (recvmsg(udev_monitor->sock, &smsg, 0) < 0) {
 		if (errno != EINTR)
-			info(udev_monitor->udev, "unable to receive message");
+			info(udev_monitor->udev, "unable to receive message\n");
 		return NULL;
 	}
 
+	if (udev_monitor->snl.nl_family != 0) {
+		if (snl.nl_groups == 0) {
+			info(udev_monitor->udev, "unicast netlink message ignored\n");
+			return NULL;
+		}
+		if ((snl.nl_groups == UDEV_MONITOR_KERNEL) && (snl.nl_pid > 0)) {
+			info(udev_monitor->udev, "multicast kernel netlink message from pid %d ignored\n", snl.nl_pid);
+			return NULL;
+		}
+	}
+
 	cmsg = CMSG_FIRSTHDR(&smsg);
 	if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
-		info(udev_monitor->udev, "no sender credentials received, message ignored");
+		info(udev_monitor->udev, "no sender credentials received, message ignored\n");
 		return NULL;
 	}
 
 	cred = (struct ucred *)CMSG_DATA(cmsg);
 	if (cred->uid != 0) {
-		info(udev_monitor->udev, "sender uid=%d, message ignored", cred->uid);
+		info(udev_monitor->udev, "sender uid=%d, message ignored\n", cred->uid);
 		return NULL;
 	}
 
 	/* skip header */
 	bufpos = strlen(buf) + 1;
 	if (bufpos < sizeof("a@/d") || bufpos >= sizeof(buf)) {
-		info(udev_monitor->udev, "invalid message length");
+		info(udev_monitor->udev, "invalid message length\n");
 		return NULL;
 	}
 
 	/* check message header */
 	if (strstr(buf, "@/") == NULL) {
-		info(udev_monitor->udev, "unrecognized message header");
+		info(udev_monitor->udev, "unrecognized message header\n");
 		return NULL;
 	}
 
@@ -414,6 +431,6 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_devi
 	else
 		return -1;
 
-	info(udev_monitor->udev, "passed %zi bytes to monitor %p, \n", count, udev_monitor);
+	info(udev_monitor->udev, "passed %zi bytes to monitor %p\n", count, udev_monitor);
 	return count;
 }


More information about the lfs-support mailing list