fix dfs path name overflow. (#8305)

This commit is contained in:
geniusgogo 2023-11-28 17:16:21 +08:00 committed by GitHub
parent 249871cbbc
commit 74925f43ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 116 additions and 105 deletions

View File

@ -346,7 +346,7 @@ static int dfs_win32_getdents(struct dfs_file *file, struct dirent *dirp, rt_uin
else else
d->d_type = DT_REG; d->d_type = DT_REG;
d->d_namlen = (rt_uint8_t)strlen(wdirp->curr); d->d_namlen = (rt_uint8_t)strlen(wdirp->curr);
strncpy(d->d_name, wdirp->curr, DFS_PATH_MAX); strncpy(d->d_name, wdirp->curr, DIRENT_NAME_MAX);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent); d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
wdirp->curr += (strlen(wdirp->curr) + 1); wdirp->curr += (strlen(wdirp->curr) + 1);
file->pos = wdirp->curr - wdirp->start + sizeof(struct dirent);//NOTE! file->pos = wdirp->curr - wdirp->start + sizeof(struct dirent);//NOTE!

View File

@ -674,7 +674,7 @@ int dfs_elm_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
d->d_namlen = (rt_uint8_t)rt_strlen(fn); d->d_namlen = (rt_uint8_t)rt_strlen(fn);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent); d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, fn, DFS_PATH_MAX); rt_strncpy(d->d_name, fn, DIRENT_NAME_MAX);
index ++; index ++;
if (index * sizeof(struct dirent) >= count) if (index * sizeof(struct dirent) >= count)

View File

@ -1144,7 +1144,7 @@ int nfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
d->d_namlen = rt_strlen(name); d->d_namlen = rt_strlen(name);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent); d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, name, DFS_PATH_MAX); rt_strncpy(d->d_name, name, DIRENT_NAME_MAX);
index ++; index ++;
if (index * sizeof(struct dirent) >= count) if (index * sizeof(struct dirent) >= count)

View File

@ -337,7 +337,7 @@ int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t coun
RT_ASSERT(len <= RT_UINT8_MAX); RT_ASSERT(len <= RT_UINT8_MAX);
d->d_namlen = (rt_uint8_t)len; d->d_namlen = (rt_uint8_t)len;
d->d_reclen = (rt_uint16_t)sizeof(struct dirent); d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, name, DFS_PATH_MAX); rt_strncpy(d->d_name, name, DIRENT_NAME_MAX);
/* move to next position */ /* move to next position */
++ file->pos; ++ file->pos;

View File

@ -742,7 +742,7 @@ int dfs_elm_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
d->d_namlen = (rt_uint8_t)rt_strlen(fn); d->d_namlen = (rt_uint8_t)rt_strlen(fn);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent); d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, fn, DFS_PATH_MAX); rt_strncpy(d->d_name, fn, DIRENT_NAME_MAX);
index ++; index ++;
if (index * sizeof(struct dirent) >= count) if (index * sizeof(struct dirent) >= count)

View File

@ -589,7 +589,8 @@ static int dfs_tmpfs_rename(struct dfs_dentry *old_dentry, struct dfs_dentry *ne
struct tmpfs_file *d_file, *p_file; struct tmpfs_file *d_file, *p_file;
struct tmpfs_sb *superblock; struct tmpfs_sb *superblock;
rt_size_t size; rt_size_t size;
char parent_path[DFS_PATH_MAX], file_name[TMPFS_NAME_MAX]; char *parent_path;
char file_name[TMPFS_NAME_MAX];
superblock = (struct tmpfs_sb *)old_dentry->mnt->data; superblock = (struct tmpfs_sb *)old_dentry->mnt->data;
RT_ASSERT(superblock != NULL); RT_ASSERT(superblock != NULL);
@ -602,10 +603,19 @@ static int dfs_tmpfs_rename(struct dfs_dentry *old_dentry, struct dfs_dentry *ne
if (d_file == NULL) if (d_file == NULL)
return -ENOENT; return -ENOENT;
parent_path = rt_malloc(DFS_PATH_MAX);
if (!parent_path)
{
return -ENOMEM;
}
/* find parent file */ /* find parent file */
_path_separate(new_dentry->pathname, parent_path, file_name); _path_separate(new_dentry->pathname, parent_path, file_name);
if (file_name[0] == '\0') /* it's root dir */ if (file_name[0] == '\0') /* it's root dir */
{
rt_free(parent_path);
return -ENOENT; return -ENOENT;
}
/* open parent directory */ /* open parent directory */
p_file = dfs_tmpfs_lookup(superblock, parent_path, &size); p_file = dfs_tmpfs_lookup(superblock, parent_path, &size);
RT_ASSERT(p_file != NULL); RT_ASSERT(p_file != NULL);
@ -620,6 +630,8 @@ static int dfs_tmpfs_rename(struct dfs_dentry *old_dentry, struct dfs_dentry *ne
rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling)); rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling));
rt_spin_unlock(&superblock->lock); rt_spin_unlock(&superblock->lock);
rt_free(parent_path);
return RT_EOK; return RT_EOK;
} }
@ -672,7 +684,8 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
rt_size_t size; rt_size_t size;
struct tmpfs_sb *superblock; struct tmpfs_sb *superblock;
struct tmpfs_file *d_file, *p_file; struct tmpfs_file *d_file, *p_file;
char parent_path[DFS_PATH_MAX], file_name[TMPFS_NAME_MAX]; char *parent_path;
char file_name[TMPFS_NAME_MAX];
if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL) if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
{ {
@ -682,6 +695,12 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
superblock = (struct tmpfs_sb *)dentry->mnt->data; superblock = (struct tmpfs_sb *)dentry->mnt->data;
RT_ASSERT(superblock != NULL); RT_ASSERT(superblock != NULL);
parent_path = rt_malloc(DFS_PATH_MAX);
if (!parent_path)
{
return NULL;
}
vnode = dfs_vnode_create(); vnode = dfs_vnode_create();
if (vnode) if (vnode)
{ {
@ -689,6 +708,7 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
_path_separate(dentry->pathname, parent_path, file_name); _path_separate(dentry->pathname, parent_path, file_name);
if (file_name[0] == '\0') /* it's root dir */ if (file_name[0] == '\0') /* it's root dir */
{ {
rt_free(parent_path);
dfs_vnode_destroy(vnode); dfs_vnode_destroy(vnode);
return NULL; return NULL;
} }
@ -697,6 +717,7 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
p_file = dfs_tmpfs_lookup(superblock, parent_path, &size); p_file = dfs_tmpfs_lookup(superblock, parent_path, &size);
if (p_file == NULL) if (p_file == NULL)
{ {
rt_free(parent_path);
dfs_vnode_destroy(vnode); dfs_vnode_destroy(vnode);
return NULL; return NULL;
} }
@ -705,6 +726,7 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
d_file = (struct tmpfs_file *)rt_calloc(1, sizeof(struct tmpfs_file)); d_file = (struct tmpfs_file *)rt_calloc(1, sizeof(struct tmpfs_file));
if (d_file == NULL) if (d_file == NULL)
{ {
rt_free(parent_path);
dfs_vnode_destroy(vnode); dfs_vnode_destroy(vnode);
return NULL; return NULL;
} }
@ -743,6 +765,8 @@ static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int t
vnode->size = d_file->size; vnode->size = d_file->size;
} }
rt_free(parent_path);
return vnode; return vnode;
} }

View File

@ -53,15 +53,15 @@
* skip stdin/stdout/stderr normally * skip stdin/stdout/stderr normally
*/ */
#ifndef DFS_STDIO_OFFSET #ifndef DFS_STDIO_OFFSET
#define DFS_STDIO_OFFSET 3 #define DFS_STDIO_OFFSET 3
#endif #endif
#ifndef DFS_PATH_MAX #ifndef DFS_PATH_MAX
#define DFS_PATH_MAX DIRENT_NAME_MAX #define DFS_PATH_MAX 4096
#endif #endif
#ifndef SECTOR_SIZE #ifndef SECTOR_SIZE
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
#endif #endif
#define DFS_FS_FLAG_DEFAULT 0x00 /* default flag */ #define DFS_FS_FLAG_DEFAULT 0x00 /* default flag */

View File

@ -583,10 +583,19 @@ char *dfs_normalize_path(const char *directory, const char *filename)
if (filename[0] != '/') /* it's a absolute path, use it directly */ if (filename[0] != '/') /* it's a absolute path, use it directly */
{ {
fullpath = (char *)rt_malloc(strlen(directory) + strlen(filename) + 2); int path_len;
if (fullpath == NULL) path_len = strlen(directory) + strlen(filename) + 2;
if (path_len > DFS_PATH_MAX)
{
return NULL; return NULL;
}
fullpath = (char *)rt_malloc(path_len);
if (fullpath == NULL)
{
return NULL;
}
/* join path and file name */ /* join path and file name */
rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2, rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2,

View File

@ -27,9 +27,24 @@
#define DBG_LVL DBG_WARNING #define DBG_LVL DBG_WARNING
#include <rtdbg.h> #include <rtdbg.h>
#define MAX_RW_COUNT 0xfffc0000 #define MAX_RW_COUNT 0xfffc0000
rt_inline int _find_path_node(const char *path)
{
int i = 0;
while (path[i] != '\0')
{
if ('/' == path[i++])
{
break;
}
}
/* return path-note length */
return i;
}
/* /*
* rw_verify_area doesn't like huge counts. We limit * rw_verify_area doesn't like huge counts. We limit
* them to something that fits in "int" so that others * them to something that fits in "int" so that others
@ -143,7 +158,7 @@ struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry)
{ {
char *buf = NULL; char *buf = NULL;
buf = (char *) rt_malloc (DFS_PATH_MAX); buf = (char *)rt_malloc(DFS_PATH_MAX);
if (buf) if (buf)
{ {
do do
@ -211,130 +226,83 @@ char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode)
{ {
int index = 0; int index = 0;
char *path = RT_NULL; char *path = RT_NULL;
char link_fn[DFS_PATH_MAX] = {0}; char *link_fn;
struct dfs_dentry *dentry = RT_NULL; struct dfs_dentry *dentry = RT_NULL;
path = (char *)rt_malloc((DFS_PATH_MAX * 2) + 1); // path + syslink + \0 path = (char *)rt_malloc((DFS_PATH_MAX * 2) + 2); // path + \0 + link_fn + \0
if (!path) if (!path)
{ {
return path; return path;
} }
link_fn = path + DFS_PATH_MAX + 1;
if (*mnt && fullpath) if (*mnt && fullpath)
{ {
int i = 0; int i = 0;
char *fp = fullpath; char *fp = fullpath;
while (*fp != '\0') while ((i = _find_path_node(fp)) > 0)
{ {
fp++; if (i + index > DFS_PATH_MAX)
i++;
if (*fp == '/')
{ {
rt_memcpy(path + index, fp - i, i); goto _ERR_RET;
path[index + i] = '\0'; }
dentry = dfs_dentry_lookup(*mnt, path, 0); rt_memcpy(path + index, fp, i);
if (dentry && dentry->vnode->type == FT_SYMLINK) path[index + i] = '\0';
fp += i;
dentry = dfs_dentry_lookup(*mnt, path, 0);
if (dentry && dentry->vnode->type == FT_SYMLINK)
{
int ret = -1;
if ((*mnt)->fs_ops->readlink)
{ {
int ret = -1; if (dfs_is_mounted((*mnt)) == 0)
if ((*mnt)->fs_ops->readlink)
{ {
if (dfs_is_mounted((*mnt)) == 0) ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
{
ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
}
} }
}
if (ret > 0) if (ret > 0)
{
int len = rt_strlen(link_fn);
if (link_fn[0] != '/')
{ {
int len = rt_strlen(link_fn); path[index] = '/';
if (link_fn[0] == '/')
{
rt_memcpy(path, link_fn, len);
index = len;
}
else
{
path[index] = '/';
index++;
rt_memcpy(path + index, link_fn, len);
index += len;
}
path[index] = '\0';
*mnt = dfs_mnt_lookup(path);
} }
else else
{ {
rt_kprintf("link error: %s\n", path); index = 0;
} }
if (len + index + 1 >= DFS_PATH_MAX)
{
goto _ERR_RET;
}
rt_memcpy(path + index, link_fn, len);
index += len;
path[index] = '\0';
*mnt = dfs_mnt_lookup(path);
} }
else else
{ {
index += i; goto _ERR_RET;
} }
dfs_dentry_unref(dentry);
i = 0;
} }
} else
if (i)
{
rt_memcpy(path + index, fp - i, i);
path[index + i] = '\0';
if (mode)
{ {
dentry = dfs_dentry_lookup(*mnt, path, 0); index += i;
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);
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);
} }
dfs_dentry_unref(dentry);
} }
} }
else else
{ {
_ERR_RET:
rt_free(path); rt_free(path);
path = RT_NULL; path = RT_NULL;
} }
@ -1837,7 +1805,7 @@ void ls(const char *pathname)
DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_open(%s, O_DIRECTORY, 0)", path); DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_open(%s, O_DIRECTORY, 0)", path);
if (dfs_file_open(&file, path, O_DIRECTORY, 0) >= 0) if (dfs_file_open(&file, path, O_DIRECTORY, 0) >= 0)
{ {
char *link_fn = (char *) rt_malloc (DFS_PATH_MAX); char *link_fn = (char *)rt_malloc(DFS_PATH_MAX);
if (link_fn) if (link_fn)
{ {
rt_kprintf("Directory %s:\n", path); rt_kprintf("Directory %s:\n", path);

View File

@ -343,6 +343,11 @@ static void directory_delete_for_msh(const char *pathname, char f, char v)
if (rt_strcmp(".", dirent->d_name) != 0 && if (rt_strcmp(".", dirent->d_name) != 0 &&
rt_strcmp("..", dirent->d_name) != 0) rt_strcmp("..", dirent->d_name) != 0)
{ {
if (strlen(pathname) + 1 + strlen(dirent->d_name) > DFS_PATH_MAX)
{
rt_kprintf("cannot remove '%s/%s', path too long.\n", pathname, dirent->d_name);
continue;
}
rt_sprintf(full_path, "%s/%s", pathname, dirent->d_name); rt_sprintf(full_path, "%s/%s", pathname, dirent->d_name);
if (dirent->d_type != DT_DIR) if (dirent->d_type != DT_DIR)
{ {
@ -862,6 +867,11 @@ static void directory_setattr(const char *pathname, struct dfs_attr *attr, char
if (rt_strcmp(".", dirent->d_name) != 0 && if (rt_strcmp(".", dirent->d_name) != 0 &&
rt_strcmp("..", dirent->d_name) != 0) rt_strcmp("..", dirent->d_name) != 0)
{ {
if (strlen(pathname) + 1 + strlen(dirent->d_name) > DFS_PATH_MAX)
{
rt_kprintf("'%s/%s' setattr failed, path too long.\n", pathname, dirent->d_name);
continue;
}
rt_sprintf(full_path, "%s/%s", pathname, dirent->d_name); rt_sprintf(full_path, "%s/%s", pathname, dirent->d_name);
if (dirent->d_type == DT_REG) if (dirent->d_type == DT_REG)
{ {

View File

@ -4874,7 +4874,7 @@ struct libc_dirent {
off_t d_off; off_t d_off;
unsigned short d_reclen; unsigned short d_reclen;
unsigned char d_type; unsigned char d_type;
char d_name[256]; char d_name[DIRENT_NAME_MAX];
}; };
sysret_t sys_getdents(int fd, struct libc_dirent *dirp, size_t nbytes) sysret_t sys_getdents(int fd, struct libc_dirent *dirp, size_t nbytes)