mirror of
https://github.com/apache/nuttx.git
synced 2025-12-12 05:34:38 +08:00
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
Reference in New Issue
Block a user