J-Security Center

Title: FreeBSD Kernel Readv() Integer Overflow Vulnerability

Severity: MODERATE

Description:

A local integer overflow vulnerability has been discovered within the FreeBSD kernel. The problem occurs within the readv() system call, which is used to read data and scatter it into an arbitrary number of buffers specified by an argument.

When a file is accessed by a system call in FreeBSD, the file is represented internally in the FreeBSD kernel memory space by a file structure. This structure contains members such as offsets. Included in this structure is a reference counter named f_count, f_count is a signed long integer data type. System calls like readv() that block operations on a file that is being used, invoke an fhold() procedure which increments f_count to create an extra reference and thereby prevent the closure of the target file mid-operation. When the system call is complete, f_count is decremented again using an fdrop() call (Eliminating the extra reference). The f_count variable is also decremented when close() is called on the file descriptor in question. If the value of f_count is zero the file structure is de-allocated from kernel memory.

It has been discovered that, under certain circumstances, the readv() system call may return prematurely. This will occur after a call to fhold() has been made and prior to invoking fdrop() resulting in a failure to decrement f_count. As a result, by invoking a large number of calls to fhold() via a properly formatted readv() syscall, it is possible to cause the f_count value to wrap and be represented as a negative value.

An attacker may trigger this issue by supplying a value for the readv() iovcnt argument that exceeds UIO_MAXIOV(1024). As a result, readv() will take the following execution path:
if (uap->iovcnt > UIO_MAXIOV)
return (EINVAL);
This will ensure that readv() returns without decrementing the f_count integer value via fdrop():

The attacker may invoke readv() in this manner iteratively upwards of 2147483648 times until the f_count integer has wrapped, then when a subsequent close() operation is performed on the active file descriptor, kernel memory corruption will be triggered. The memory corruption will likely occur when the misrepresented f_count integer is employed during memory management routines. This could ultimately result in a system panic or could possibly be leveraged to elevate local privileges to that of the root user.

Affected Products:

  • FreeBSD FreeBSD 4.3.0
  • FreeBSD FreeBSD 4.4.0
  • FreeBSD FreeBSD 4.5.0
  • FreeBSD FreeBSD 4.6.0
  • FreeBSD FreeBSD 4.6.2
  • FreeBSD FreeBSD 4.7.0
  • FreeBSD FreeBSD 4.8.0

References:

Juniper Networks provides this content via a wide variety of sources and production methods. If notified of errors or omissions in the content of this page, Juniper Networks, at its discretion, will modify or remove the page or leave the content as is, depending on various factors including but not limited to the reputation and authority of the party providing the notification. Please use the contact information displayed elsewhere on this page to report any errors or omissions regarding the content on this page.