--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: /usr/sbin/cupsd: Denial of service via UDP socket
- From: Colin Phipps <cph@cph.demon.co.uk>
- Date: Mon, 6 Dec 2004 20:39:26 +0000
- Message-id: <20041206203926.GA2934@cph.demon.co.uk>
Package: cupsys
Version: 1.1.20final+rc1-10
Severity: normal
File: /usr/sbin/cupsd
Tags: security patch
Linux select(2) is not POSIX compliant; select can report that a socket
has data to read when it does not. This is so in kernel series 2.6.x and
possibly earlier versions. If an application wants non-blocking
behaviour on Linux, it must set O_NONBLOCK on the file handle. See the
thread on LKML <http://marc.theaimsgroup.com/?t=109707457000003&r=7> .
select can return true but there is no data available if e.g. a packet
with a bad checksum is received from the network. So cupsd can be easily
hung by sending a UDP packet with a bad checksum to UDP port 631:
(from a remote machine)
# hping2 -2 -c 1 -p 631 -b -d 4 <target-machine>
and cupsd does:
select(1024, [0 2 3], [], NULL, {31, 0}) = 1 (in [2], left {8, 913000})
recvfrom(2,
...and hangs, waiting for data that isn't there. It can then be easily
checked that cupsd is completely unresponsive, and remains so until a
UDP packet is received or the service is restarted.
If cupsd wants not to block on UDP traffic, it should mark the UDP
socket as non-blocking:
--- cupsys-1.1.20final+rc1/scheduler/dirsvc.c 2004-05-27 19:04:32.000000000 +0100
+++ cupsys-1.1.20final+rc1-cph1/scheduler/dirsvc.c 2004-12-06 20:31:14.000000000 +0000
@@ -776,6 +776,29 @@ StartBrowsing(void)
return;
}
+ /* cph 2004/12/06 - set non-blocking, we want to use multiplex using select(2) and must never get stuck reading this socket. */
+ {
+ int flags = fcntl(BrowseSocket, F_GETFL);
+ if (flags != -1) {
+ flags |= O_NONBLOCK;
+ flags = fcntl(BrowseSocket, F_SETFL, flags);
+ }
+ if (flags == -1) {
+ LogMessage(L_ERROR, "StartBrowsing: Unable to set non-blocking mode - %s.",
+ strerror(errno));
+
+#ifdef WIN32
+ closesocket(BrowseSocket);
+#else
+ close(BrowseSocket);
+#endif /* WIN32 */
+
+ BrowseSocket = -1;
+ BrowseProtocols &= ~BROWSE_CUPS;
+ return;
+ }
+ }
+
/*
* Bind the socket to browse port...
*/
@@ -1127,7 +1150,7 @@ UpdateCUPSBrowse(void)
* error here and ignore it for now...
*/
- if (errno != ECONNREFUSED)
+ if (errno != ECONNREFUSED && errno != EAGAIN)
{
LogMessage(L_ERROR, "Browse recv failed - %s.", strerror(errno));
LogMessage(L_ERROR, "Browsing turned off.");
(given only limited testing, to verify that it fixes the bug - I haven't
verified the error path.)
-- System Information:
Debian Release: 3.1
APT prefers testing
APT policy: (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.6.8.1-cph2
Locale: LANG=en_GB, LC_CTYPE=en_GB (charmap=ISO-8859-1)
Versions of packages cupsys depends on:
ii adduser 3.59 Add and remove users and groups
ii debconf 1.4.30.10 Debian configuration management sy
ii gs-esp 7.07.1-9 The Ghostscript PostScript interpr
ii libc6 2.3.2.ds1-18 GNU C Library: Shared libraries an
ii libcupsimage2 1.1.20final+rc1-10 Common UNIX Printing System(tm) -
ii libcupsys2-gnutls10 1.1.20final+rc1-10 Common UNIX Printing System(tm) -
ii libgcc1 1:3.4.2-2 GCC support library
ii libgnutls11 1.0.16-9 GNU TLS library - runtime library
ii libpam0g 0.76-22 Pluggable Authentication Modules l
ii libpaper1 1.1.14-3 Library for handling paper charact
ii libslp1 1.0.11-7 OpenSLP libraries
ii patch 2.5.9-2 Apply a diff file to an original
ii zlib1g 1:1.2.2-3 compression library - runtime
-- debconf information:
cupsys/raw-print: true
cupsys/backend: ipp, lpd, parallel, socket, usb
--
Colin Phipps <cph@cph.demon.co.uk>
--- End Message ---