Description
Hi,
I would like to report other potential vulnerabilities in the current version of RT-Thread. Please let me know if you plan to ask for a CVE ID in case the vulnerabilities are confirmed. I'm available if you need further clarifications.
Potential heap buffer overflows in RT-Thread dfs_v2 dfs_file
Summary
I spotted some potential heap buffer overflow vulnerabilities at the following locations in the RT-Thread dfs_v2 dfs_file source code:
https://github.com/RT-Thread/rt-thread/blob/master/components/dfs/dfs_v2/src/dfs_file.c#L234
https://github.com/RT-Thread/rt-thread/blob/master/components/dfs/dfs_v2/src/dfs_file.c#L262
https://github.com/RT-Thread/rt-thread/blob/master/components/dfs/dfs_v2/src/dfs_file.c#L284
https://github.com/RT-Thread/rt-thread/blob/master/components/dfs/dfs_v2/src/dfs_file.c#L314
Details
Lack of length check in the the dfs_nolink_path()
function could lead to heap buffer overflows at the marked lines:
static char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode)
{
int index = 0;
char *path = RT_NULL;
char link_fn[DFS_PATH_MAX] = {0};
struct dfs_dentry *dentry = RT_NULL;
path = (char *)rt_malloc((DFS_PATH_MAX * 2) + 1); // path + syslink + \0
if (!path)
{
return path;
}
if (*mnt && fullpath)
{
int i = 0;
char *fp = fullpath;
while (*fp != '\0')
{
fp++;
i++;
if (*fp == '/')
{
rt_memcpy(path + index, fp - i, i); /* VULN: if fullpath has components large enough so that i+index becomes larger than DFS_PATH_MAX*2+1, we could overflow past the path buffer */
path[index + i] = '\0';
dentry = dfs_dentry_lookup(*mnt, path, 0);
if (dentry && dentry->vnode->type == FT_SYMLINK)
{
int ret = -1;
if ((*mnt)->fs_ops->readlink)
{
if (dfs_is_mounted((*mnt)) == 0)
{
ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
}
}
if (ret > 0)
{
int len = rt_strlen(link_fn);
if (link_fn[0] == '/')
{
rt_memcpy(path, link_fn, len);
index = len;
}
else
{
path[index] = '/';
index++;
rt_memcpy(path + index, link_fn, len); /* VULN: len can be DFS_PATH_MAX; if index can become larger than DFS_PATH_MAX+1, we can overflow past the path buffer */
index += len;
}
path[index] = '\0';
*mnt = dfs_mnt_lookup(path);
}
else
{
rt_kprintf("link error: %s\n", path);
}
}
else
{
index += i;
}
dfs_dentry_unref(dentry);
i = 0;
}
}
if (i)
{
rt_memcpy(path + index, fp - i, i); /* VULN: if fullpath has components large enough so that i+index becomes larger than DFS_PATH_MAX*2+1, we could overflow past the path buffer */
path[index + i] = '\0';
if (mode)
{
dentry = dfs_dentry_lookup(*mnt, path, 0);
if (dentry && dentry->vnode->type == FT_SYMLINK)
{
int ret = -1;
if ((*mnt)->fs_ops->readlink)
{
if (dfs_is_mounted((*mnt)) == 0)
{
ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
}
}
if (ret > 0)
{
int len = rt_strlen(link_fn);
if (link_fn[0] == '/')
{
rt_memcpy(path, link_fn, len);
index = len;
}
else
{
path[index] = '/';
index++;
rt_memcpy(path + index, link_fn, len); /* VULN: len can be DFS_PATH_MAX; if index can become larger than DFS_PATH_MAX+1, we can overflow past the path buffer */
index += len;
}
path[index] = '\0';
*mnt = dfs_mnt_lookup(path);
}
else
{
rt_kprintf("link error: %s\n", path);
}
char *_fullpath = dfs_normalize_path(RT_NULL, path);
if (_fullpath)
{
strncpy(path, _fullpath, DFS_PATH_MAX);
rt_free(_fullpath);
}
}
dfs_dentry_unref(dentry);
}
}
}
else
{
rt_free(path);
path = RT_NULL;
}
//rt_kprintf("%s: %s => %s\n", __FUNCTION__, fullpath, path);
return path;
}
Impact
If an attacker is able to control fullpath
above and craft it as required to trigger the reported heap buffer overflow vulnerabilities, their impact could range from denial of service to arbitrary code execution.