Explorar o código

fix dfs path name overflow. (#8305)

geniusgogo hai 1 ano
pai
achega
74925f43ed

+ 1 - 1
bsp/simulator/drivers/dfs_win32.c

@@ -346,7 +346,7 @@ static int dfs_win32_getdents(struct dfs_file *file, struct dirent *dirp, rt_uin
     else
         d->d_type = DT_REG;
     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);
     wdirp->curr += (strlen(wdirp->curr) + 1);
     file->pos = wdirp->curr - wdirp->start + sizeof(struct dirent);//NOTE!

+ 1 - 1
components/dfs/dfs_v1/filesystems/elmfat/dfs_elm.c

@@ -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_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 ++;
         if (index * sizeof(struct dirent) >= count)

+ 1 - 1
components/dfs/dfs_v1/filesystems/nfs/dfs_nfs.c

@@ -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_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 ++;
         if (index * sizeof(struct dirent) >= count)

+ 1 - 1
components/dfs/dfs_v1/filesystems/romfs/dfs_romfs.c

@@ -337,7 +337,7 @@ int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t coun
         RT_ASSERT(len <= RT_UINT8_MAX);
         d->d_namlen = (rt_uint8_t)len;
         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 */
         ++ file->pos;

+ 1 - 1
components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c

@@ -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_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 ++;
         if (index * sizeof(struct dirent) >= count)

+ 26 - 2
components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c

@@ -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_sb *superblock;
     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;
     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)
         return -ENOENT;
 
+    parent_path = rt_malloc(DFS_PATH_MAX);
+    if (!parent_path)
+    {
+        return -ENOMEM;
+    }
+
     /* find parent file */
     _path_separate(new_dentry->pathname, parent_path, file_name);
     if (file_name[0] == '\0') /* it's root dir */
+    {
+        rt_free(parent_path);
         return -ENOENT;
+    }
     /* open parent directory */
     p_file = dfs_tmpfs_lookup(superblock, parent_path, &size);
     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_spin_unlock(&superblock->lock);
 
+    rt_free(parent_path);
+
     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;
     struct tmpfs_sb *superblock;
     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)
     {
@@ -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;
     RT_ASSERT(superblock != NULL);
 
+    parent_path = rt_malloc(DFS_PATH_MAX);
+    if (!parent_path)
+    {
+        return NULL;
+    }
+
     vnode = dfs_vnode_create();
     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);
         if (file_name[0] == '\0') /* it's root dir */
         {
+            rt_free(parent_path);
             dfs_vnode_destroy(vnode);
             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);
         if (p_file == NULL)
         {
+            rt_free(parent_path);
             dfs_vnode_destroy(vnode);
             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));
         if (d_file == NULL)
         {
+            rt_free(parent_path);
             dfs_vnode_destroy(vnode);
             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;
     }
 
+    rt_free(parent_path);
+
     return vnode;
 }
 

+ 3 - 3
components/dfs/dfs_v2/include/dfs.h

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

+ 10 - 1
components/dfs/dfs_v2/src/dfs.c

@@ -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 */
     {
-        fullpath = (char *)rt_malloc(strlen(directory) + strlen(filename) + 2);
+        int path_len;
 
+        path_len = strlen(directory) + strlen(filename) + 2;
+        if (path_len > DFS_PATH_MAX)
+        {
+            return NULL;
+        }
+
+        fullpath = (char *)rt_malloc(path_len);
         if (fullpath == NULL)
+        {
             return NULL;
+        }
 
         /* join path and file name */
         rt_snprintf(fullpath, strlen(directory) + strlen(filename) + 2,

+ 58 - 90
components/dfs/dfs_v2/src/dfs_file.c

@@ -27,9 +27,24 @@
 #define DBG_LVL    DBG_WARNING
 #include <rtdbg.h>
 
-
 #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
  * 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;
 
-        buf = (char *) rt_malloc (DFS_PATH_MAX);
+        buf = (char *)rt_malloc(DFS_PATH_MAX);
         if (buf)
         {
             do
@@ -211,130 +226,83 @@ 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};
+    char *link_fn;
     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)
     {
         return path;
     }
+    link_fn = path + DFS_PATH_MAX + 1;
 
     if (*mnt && fullpath)
     {
         int i = 0;
         char *fp = fullpath;
 
-        while (*fp != '\0')
+        while ((i = _find_path_node(fp)) > 0)
         {
-            fp++;
-            i++;
-            if (*fp == '/')
+            if (i + index > DFS_PATH_MAX)
             {
-                rt_memcpy(path + index, fp - i, i);
-                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);
-                            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;
+                goto _ERR_RET;
             }
-        }
 
-        if (i)
-        {
-            rt_memcpy(path + index, fp - i, i);
+            rt_memcpy(path + index, fp, i);
             path[index + i] = '\0';
+            fp += i;
 
-            if (mode)
+            dentry = dfs_dentry_lookup(*mnt, path, 0);
+            if (dentry && dentry->vnode->type == FT_SYMLINK)
             {
-                dentry = dfs_dentry_lookup(*mnt, path, 0);
-                if (dentry && dentry->vnode->type == FT_SYMLINK)
-                {
-                    int ret = -1;
+                int ret = -1;
 
-                    if ((*mnt)->fs_ops->readlink)
+                if ((*mnt)->fs_ops->readlink)
+                {
+                    if (dfs_is_mounted((*mnt)) == 0)
                     {
-                        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)
+                {
+                    int len = rt_strlen(link_fn);
 
-                    if (ret > 0)
+                    if (link_fn[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);
+                        path[index] = '/';
                     }
                     else
                     {
-                        rt_kprintf("link error: %s\n", path);
+                        index = 0;
                     }
 
-                    char *_fullpath = dfs_normalize_path(RT_NULL, path);
-                    if (_fullpath)
+                    if (len + index + 1 >= DFS_PATH_MAX)
                     {
-                        strncpy(path, _fullpath, DFS_PATH_MAX);
-                        rt_free(_fullpath);
+                        goto _ERR_RET;
                     }
+
+                    rt_memcpy(path + index, link_fn, len);
+                    index += len;
+                    path[index] = '\0';
+                    *mnt = dfs_mnt_lookup(path);
+                }
+                else
+                {
+                    goto _ERR_RET;
                 }
-                dfs_dentry_unref(dentry);
             }
+            else
+            {
+                index += i;
+            }
+            dfs_dentry_unref(dentry);
         }
     }
     else
     {
+_ERR_RET:
         rt_free(path);
         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);
     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)
         {
             rt_kprintf("Directory %s:\n", path);

+ 10 - 0
components/finsh/msh_file.c

@@ -343,6 +343,11 @@ static void directory_delete_for_msh(const char *pathname, char f, char v)
         if (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);
             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 &&
             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);
             if (dirent->d_type == DT_REG)
             {

+ 1 - 1
components/lwp/lwp_syscall.c

@@ -4874,7 +4874,7 @@ struct libc_dirent {
     off_t d_off;
     unsigned short d_reclen;
     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)