fs: Fix the race condition in file_dup

NULL inode passed to files_allocate doesn't mark file struct in the
allocated state, so other threads which invovle in file allocation
(e.g. open or dup) may allocate the same file struct again.

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Change-Id: I53ff876eae3c7a1e311e7f671686b73a4b4ef891
This commit is contained in:
Xiang Xiao
2021-01-02 22:08:43 +08:00
committed by archer
parent b343caae4d
commit 86fab49c46
6 changed files with 21 additions and 23 deletions

View File

@@ -256,7 +256,8 @@ errout_with_sem:
* *
****************************************************************************/ ****************************************************************************/
int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd) int files_allocate(FAR struct inode *inode, int oflags, off_t pos,
FAR void *priv, int minfd)
{ {
FAR struct filelist *list; FAR struct filelist *list;
int ret; int ret;
@@ -282,7 +283,7 @@ int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int minfd)
list->fl_files[i].f_oflags = oflags; list->fl_files[i].f_oflags = oflags;
list->fl_files[i].f_pos = pos; list->fl_files[i].f_pos = pos;
list->fl_files[i].f_inode = inode; list->fl_files[i].f_inode = inode;
list->fl_files[i].f_priv = NULL; list->fl_files[i].f_priv = priv;
_files_semgive(list); _files_semgive(list);
return i; return i;
} }

View File

@@ -387,7 +387,7 @@ void weak_function files_initialize(void);
****************************************************************************/ ****************************************************************************/
int files_allocate(FAR struct inode *inode, int oflags, off_t pos, int files_allocate(FAR struct inode *inode, int oflags, off_t pos,
int minfd); FAR void *priv, int minfd);
/**************************************************************************** /****************************************************************************
* Name: files_close * Name: files_close

View File

@@ -269,7 +269,7 @@ static mqd_t nxmq_vopen(FAR const char *mq_name, int oflags, va_list ap)
return ret; return ret;
} }
ret = files_allocate(mq.f_inode, mq.f_oflags, mq.f_pos, 0); ret = files_allocate(mq.f_inode, mq.f_oflags, mq.f_pos, mq.f_priv, 0);
if (ret < 0) if (ret < 0)
{ {
file_mq_close(&mq); file_mq_close(&mq);

View File

@@ -51,32 +51,29 @@
int file_dup(FAR struct file *filep, int minfd) int file_dup(FAR struct file *filep, int minfd)
{ {
FAR struct file *filep2; struct file filep2;
int fd2; int fd2;
int ret; int ret;
/* Allocate a new file descriptor for the inode */ /* Let file_dup2() do the real work */
fd2 = files_allocate(NULL, 0, 0, minfd); memset(&filep2, 0, sizeof(filep2));
ret = file_dup2(filep, &filep2);
if (ret < 0)
{
return ret;
}
/* Then allocate a new file descriptor for the inode */
fd2 = files_allocate(filep2.f_inode, filep2.f_oflags,
filep2.f_pos, filep2.f_priv, minfd);
if (fd2 < 0) if (fd2 < 0)
{ {
file_close(&filep2);
return fd2; return fd2;
} }
ret = fs_getfilep(fd2, &filep2);
if (ret < 0)
{
files_release(fd2);
return ret;
}
ret = file_dup2(filep, filep2);
if (ret < 0)
{
files_release(fd2);
return ret;
}
return fd2; return fd2;
} }

View File

@@ -204,7 +204,7 @@ int nx_vopen(FAR const char *path, int oflags, va_list ap)
/* Associate the inode with a file structure */ /* Associate the inode with a file structure */
fd = files_allocate(inode, oflags, 0, 0); fd = files_allocate(inode, oflags, 0, NULL, 0);
if (fd < 0) if (fd < 0)
{ {
ret = fd; ret = fd;

View File

@@ -401,7 +401,7 @@ struct file
int f_oflags; /* Open mode flags */ int f_oflags; /* Open mode flags */
off_t f_pos; /* File position */ off_t f_pos; /* File position */
FAR struct inode *f_inode; /* Driver or file system interface */ FAR struct inode *f_inode; /* Driver or file system interface */
void *f_priv; /* Per file driver private data */ FAR void *f_priv; /* Per file driver private data */
}; };
/* This defines a list of files indexed by the file descriptor */ /* This defines a list of files indexed by the file descriptor */