Subject: NetBSD Security Advisory 2000-002
To: None <netbsd-announce@netbsd.org>
From: Daniel Carosone <dan@geek.com.au>
List: netbsd-announce
Date: 05/07/2000 10:18:25
-----BEGIN PGP SIGNED MESSAGE-----


                 NetBSD Security Advisory 2000-002
                 =================================

Topic:          IP options processing Denial of Service
Version:        NetBSD 1.4.2 and prior; NetBSD-current until 20000507.
Severity:       Network-connected systems can be crashed remotely.
 

Abstract
========

Receipt of IP packets with certain sequences of malformed IP options
can cause an unaligned access in kernel mode (on many architectures),
or data corruption, resulting in a panic or other problems.

There are two problems:

One is the result of an interaction between a relatively new
optimization performed by GCC and a code fragment which violates ANSI
C, as well as insufficient protection of some data structures from
alignment changes by the compiler.

The second problem (uncovered while testing fixes to the first)
involves several incorrect range checks due to a computation involving
a mix of signed and unsigned values.  

Either or both of these problems may be present in other
4.4BSD-derived systems.

Technical Details
=================

IP packets can contain optional processing directives, which may be
examined both by the destination system of the packet, as well as by
intermediate routers.  These options can be malformed, if constructed
randomly or maliciously. Tools to construct such packets are widely
available and in common use.

1) Alignment problems

The first problem arises because more aggressive optimisations added
in recent compilers made previously marginal code unsafe:

 * In ip_input.c, in the code fragment that processes the IP Timestamp
   option, an illegal type cast was performed from an unaligned
   pointer to something needing more strict alignment; this is
   disallowed by the ANSI C standard.  This interacted poorly with an
   optimization that GCC performed on the code fragment; the compiler
   inlined a call to memcpy(), and due to the illegal type cast,
   emitted a load-store of a single 32-bit value.

 * In ip.h, several structures used to describe over-the-wire data
   required "__attribute__((__packed__))" to prevent the compiler
   making unwarranted assumptions about the alignment of the
   structures.

Either of these may cause the kernel to make an unaligned access.
This unaligned access will result in a fault and a panic or other
problems on many architectures:

 * It is known to produce alignment fault panics on the alpha, sparc
   and sparc64 architectures; others affected may include mips and sh3.

 * On some architectures, for example the arm32, misaligned accesses
   do not produce faults, instead they produce incorrect data; these
   systems will not panic, but instead suffer other problems, such as
   exhaustion of the mbuf cluster pool.

 * Other platforms, including the i386, m68k, pc532 and vax do not
   have alignment checking requirements and so are unaffected by this
   issue.

Because this involves an interaction with compiler optimisations, its
appearance and behaviour depend on the compiler flags used.  For
example, the second problem (ip.h) does not occur when the code is
compiled specifically for Alpha 21164a or higher processors with bwx
extensions; in that case the compiler uses the added byte load/store
instructions and there is no alignment problem.  As a result, it took
some additional time for this problem to be found and fixed;
unfortunately this was after the release of NetBSD 1.4.2.

2) Incorrect range-checking

In the course of exhaustively testing the fix and related code, the
second problem cited above was uncovered.  

A malformed option can induce the system to overwrite four bytes of
memory near the packet.  This may quietly corrupt user data or cause a
crash depending on exactly what is overwritten.  

In order to sanity-check incoming messages, range checks of the
following general form were used:

	if (off > len - sizeof(...)) 
		goto error;

Because sizeof() yields an unsigned value, C requires "len - sizeof()"
to be computed as an unsigned value.  If len is less than the value of
sizeof(), the subtraction silently underflows and yields a large
positive value.  As a result, the options processing code may continue
on to overwrite 4 bytes of memory near the packet buffer with one of
its ip addresses. 

This problem was detected when internal consistency checks within the
NetBSD pool memory allocator (which are enabled by default) determined
that a free mbuf had been overwritten.

All architectures are vulnerable to this problem. Because of
differences in type sizes and structure layout, the exact offsets
which cause trouble, and therefore the packet contents that can be
used to exploit the problem, will vary from architecture to
architecture.


Solutions and Workarounds
=========================

The fix involves changes to two files.  Because part of the fix was
included in NetBSD 1.4.2, different patch files have been made
available for NetBSD 1.4.1 and NetBSD 1.4.2.  

For all NetBSD versions, you need to download the source patch, apply
it to your kernel source tree using the patch(1) command, and rebuild,
install the kernel, and reboot. For more information on how to do
this, see:

    http://www.netbsd.org/Documentation/kernel/#building_a_kernel 

For NetBSD 1.4.1 (and earlier):

 A patch is available which contains changes to ip_input.c and ip.h,
 located at:

    ftp://ftp.NetBSD.ORG/pub/NetBSD/misc/security/patches/20000507-ipopt141

For NetBSD 1.4.2:

 A patch is available which contains changes to ip_input.c and ip.h,
 located at:

    ftp://ftp.NetBSD.ORG/pub/NetBSD/misc/security/patches/20000507-ipopt142

 These changes have been pulled up to the 1.4.x release branch; users
 tracking this branch via cvs should update to a source tree dated
 20000507 or later.

For NetBSD-current:

 NetBSD-current since 20000506 contains all the fixes, and is not
 vulnerable.  Users of NetBSD-current should upgrade to a source tree
 dated 20000507 or later.

Thanks To
=========

Matt Hargett and Erik Fair for discovering and reporting the first
problem, Jason Thorpe for analysing the problem and implementing the
fixes for it, and Bill Sommerfeld for finding and fixing the second
problem.

Revision History
================

	2000/02/29 - initial version
	2000/03/11 - updated after analysis
	2000/05/04 - updated for ip.h changes 
	2000/05/06 - updated to add range checking bug.

More Information
================

Information about NetBSD and NetBSD security can be found at
http://www.NetBSD.ORG/ and http://www.NetBSD.ORG/Security/.


Copyright 2000, The NetBSD Foundation, Inc.  All Rights Reserved.

$NetBSD: NetBSD-SA2000-002.txt,v 1.8 2000/05/06 23:33:56 dan Exp $


-----BEGIN PGP SIGNATURE-----
Version: 2.6.3ia
Charset: noconv

iQCVAwUBORSr6D5Ru2/4N2IFAQEz4QQAiPTzn+hSFCSD0YF5j4iJnYxAjmhZ27bw
aWALZQlH6Ny9DWodspPb43nlQFXEEQyuVxgp24KaLq5kPYLNAJS5Q+gyAU/vKVh6
jgRQRhuM1jbD0ATQ4se/bgpkId0pGvUAjEZO9aLx9vEU6oltJIlhyws4pkFUQJ9Z
y4ZaOre4J1o=
=Y18N
-----END PGP SIGNATURE-----