epoll: fix epoll close error, report by kasan

-#9  0xf7abf899 in __asan::__asan_report_load2 (addr=4072681776) at ../../../../../src/libsanitizer/asan/asan_rtl.cc:117
-#10 0x5693f718 in inode_release (node=0xf2c03124) at inode/fs_inoderelease.c:69
-#11 0x568ea61b in file_close (filep=0xf55fedd0) at vfs/fs_close.c:79
-#12 0x568e7e56 in nx_close (fd=3) at inode/fs_files.c:528
-#13 0x568e7f0e in close (fd=3) at inode/fs_files.c:562
-#14 0x56e76c39 in epoll_close (epfd=3) at vfs/fs_epoll.c:252
-#15 0x56c33829 in sensor_service_delete (ctrl=0x578b8540 <control>) at src/common.c:439
-#16 0x56a0561e in sensor_middle_service_main (argc=1, argv=0xf55de820) at sensor_main.c:118
-#17 0x56878675 in nxtask_startup (entrypt=0x56a054cc <sensor_middle_service_main>, argc=1, argv=0xf55de820) at sched/task_startup.c:70
-#18 0x5684427a in nxtask_start () at task/task_start.c:133
-#19 0xdeadbeef in ?? ()

reason:
epoll_close -> close -> epoll_do_close (free inode)
                     -> inode_release  (reuse inode, crash)

fix:
use the global inode to match the fd which will return to user.
like the g_sock_inode in fs/socket/socket.c

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2022-03-16 22:48:54 +08:00 committed by Petro Karashchenko
parent 2ffca6d16d
commit 0d365f6fb9

View File

@ -83,6 +83,16 @@ static const struct file_operations g_epoll_ops =
#endif
};
static struct inode g_epoll_inode =
{
.i_crefs = 1,
.i_flags = FSNODEFLAG_TYPE_DRIVER,
.u =
{
.i_ops = &g_epoll_ops,
},
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -109,12 +119,12 @@ static FAR struct epoll_head *epoll_head_from_fd(int fd)
return NULL;
}
return (FAR struct epoll_head *)filep->f_inode->i_private;
return (FAR struct epoll_head *)filep->f_priv;
}
static int epoll_do_open(FAR struct file *filep)
{
FAR struct epoll_head *eph = filep->f_inode->i_private;
FAR struct epoll_head *eph = filep->f_priv;
int ret;
ret = nxsem_wait(&eph->sem);
@ -130,7 +140,7 @@ static int epoll_do_open(FAR struct file *filep)
static int epoll_do_close(FAR struct file *filep)
{
FAR struct epoll_head *eph = filep->f_inode->i_private;
FAR struct epoll_head *eph = filep->f_priv;
int ret;
ret = nxsem_wait(&eph->sem);
@ -187,7 +197,7 @@ static int epoll_do_create(int size, int flags)
/* Alloc the file descriptor */
fd = files_allocate(&eph->in, flags, 0, eph, 0);
fd = files_allocate(&g_epoll_inode, flags, 0, eph, 0);
if (fd < 0)
{
nxsem_destroy(&eph->sem);
@ -196,6 +206,7 @@ static int epoll_do_create(int size, int flags)
return -1;
}
inode_addref(&g_epoll_inode);
nxsem_post(&eph->sem);
return fd;
}