From ea522205097ba4ff03484f9fc46b148d9bfc9ceb Mon Sep 17 00:00:00 2001 From: fangxinyong Date: Tue, 25 Jul 2023 01:16:19 +0800 Subject: [PATCH] fs/shmfs: fix inode leak issue If the shm file is removed and a subsequent close, only release shm object, but inode is leaked. Should decrease refcount to release inode when unmapped, that matched with refcount increase when mapped. Another fix that remove the shm file failed. nsh> rm /var/shm/pts_mmap_1_2_5 nsh: rm: unlink failed: 6 Signed-off-by: fangxinyong --- fs/shm/shmfs.c | 32 +++++++++++++++++++++++--------- fs/vfs/fs_unlink.c | 3 ++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/fs/shm/shmfs.c b/fs/shm/shmfs.c index 7f0d6d73dd0..8e634e0005e 100644 --- a/fs/shm/shmfs.c +++ b/fs/shm/shmfs.c @@ -258,6 +258,18 @@ static int shmfs_map_object(FAR struct shmfs_object_s *object, return ret; } +/**************************************************************************** + * Name: shmfs_add_map + ****************************************************************************/ + +static int shmfs_add_map(FAR struct mm_map_entry_s *entry, + FAR struct inode *inode) +{ + entry->munmap = shmfs_munmap; + entry->priv.p = (FAR void *)inode; + return mm_map_add(get_current_mm(), entry); +} + /**************************************************************************** * Name: shmfs_mmap ****************************************************************************/ @@ -294,16 +306,11 @@ static int shmfs_mmap(FAR struct file *filep, ret = -EINVAL; } - if (ret < 0) + if (ret < 0 || + (ret = shmfs_add_map(entry, filep->f_inode)) < 0) { inode_release(filep->f_inode); } - else - { - entry->munmap = shmfs_munmap; - entry->priv.p = (FAR void *)filep->f_inode; - ret = mm_map_add(get_current_mm(), entry); - } } return ret; @@ -349,6 +356,7 @@ static int shmfs_munmap(FAR struct task_group_s *group, FAR void *start, size_t length) { + FAR struct inode *inode; int ret; /* Partial unmap is not supported yet */ @@ -358,6 +366,8 @@ static int shmfs_munmap(FAR struct task_group_s *group, return -EINVAL; } + inode = (FAR struct inode *)entry->priv.p; + /* Unmap the virtual memory area from the user's address space */ ret = shmfs_unmap_area(group, entry->vaddr, entry->length); @@ -369,13 +379,17 @@ static int shmfs_munmap(FAR struct task_group_s *group, if (ret == OK) { - ret = shmfs_release((FAR struct inode *)entry->priv.p); + ret = shmfs_release(inode); } - /* Remove the mapping. */ + /* Unkeep the inode when unmapped, decrease refcount */ if (ret == OK) { + inode_release(inode); + + /* Remove the mapping. */ + ret = mm_map_remove(get_group_mm(group), entry); } diff --git a/fs/vfs/fs_unlink.c b/fs/vfs/fs_unlink.c index e3b77b78460..515f577ff8f 100644 --- a/fs/vfs/fs_unlink.c +++ b/fs/vfs/fs_unlink.c @@ -123,7 +123,8 @@ int nx_unlink(FAR const char *pathname) * release all resources because it is no longer accessible. */ - if (INODE_IS_DRIVER(inode) && inode->u.i_ops->unlink) + if ((INODE_IS_DRIVER(inode) || INODE_IS_SHM(inode)) && + inode->u.i_ops->unlink) { /* Notify the character driver that it has been unlinked */