POSIX-2024: support for O_CLOFORK, SO_CLOFORK
Change-Id: I4f3a961947eefdeafd5a249499899cc92d67c2d1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/9330 Tested-by: Commit checker robot <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
ba28b6f5f7
commit
904fd2abf0
@@ -21,6 +21,7 @@
|
|||||||
#define F_SETLK 0x0080 /* set locking information */
|
#define F_SETLK 0x0080 /* set locking information */
|
||||||
#define F_SETLKW 0x0100 /* as above, but waits if blocked */
|
#define F_SETLKW 0x0100 /* as above, but waits if blocked */
|
||||||
#define F_DUPFD_CLOEXEC 0x0200 /* duplicate fd with close on exec set */
|
#define F_DUPFD_CLOEXEC 0x0200 /* duplicate fd with close on exec set */
|
||||||
|
#define F_DUPFD_CLOFORK 0x0400 /* duplicate fd with close on fork set */
|
||||||
|
|
||||||
/* advisory locking types */
|
/* advisory locking types */
|
||||||
#define F_RDLCK 0x0040 /* read or shared lock */
|
#define F_RDLCK 0x0040 /* read or shared lock */
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
|
|
||||||
/* file descriptor flags for fcntl() */
|
/* file descriptor flags for fcntl() */
|
||||||
#define FD_CLOEXEC 1 /* close on exec */
|
#define FD_CLOEXEC 1 /* close on exec */
|
||||||
|
#define FD_CLOFORK 2 /* close on fork */
|
||||||
|
|
||||||
/* file access modes for open() */
|
/* file access modes for open() */
|
||||||
#define O_RDONLY 0x0000 /* read only */
|
#define O_RDONLY 0x0000 /* read only */
|
||||||
@@ -57,6 +59,7 @@
|
|||||||
/* possible */
|
/* possible */
|
||||||
#define O_NOCACHE O_DIRECT
|
#define O_NOCACHE O_DIRECT
|
||||||
#define O_DIRECTORY 0x00200000 /* fail if not a directory */
|
#define O_DIRECTORY 0x00200000 /* fail if not a directory */
|
||||||
|
#define O_CLOFORK 0x00400000 /* close on fork */
|
||||||
|
|
||||||
/* flags for the *at() functions */
|
/* flags for the *at() functions */
|
||||||
#define AT_FDCWD (-100) /* CWD FD for the *at() functions */
|
#define AT_FDCWD (-100) /* CWD FD for the *at() functions */
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ typedef uint8_t sa_family_t;
|
|||||||
|
|
||||||
#define SOCK_NONBLOCK 0x00040000
|
#define SOCK_NONBLOCK 0x00040000
|
||||||
#define SOCK_CLOEXEC 0x00080000
|
#define SOCK_CLOEXEC 0x00080000
|
||||||
|
#define SOCK_CLOFORK 0x00100000
|
||||||
|
|
||||||
/* Socket options for SOL_SOCKET level */
|
/* Socket options for SOL_SOCKET level */
|
||||||
#define SOL_SOCKET -1
|
#define SOL_SOCKET -1
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ extern bool fd_is_file(struct file_descriptor* descriptor);
|
|||||||
extern bool fd_close_on_exec(const struct io_context *context, int fd);
|
extern bool fd_close_on_exec(const struct io_context *context, int fd);
|
||||||
extern void fd_set_close_on_exec(struct io_context *context, int fd,
|
extern void fd_set_close_on_exec(struct io_context *context, int fd,
|
||||||
bool closeFD);
|
bool closeFD);
|
||||||
|
extern bool fd_close_on_fork(const struct io_context *context, int fd);
|
||||||
|
extern void fd_set_close_on_fork(struct io_context *context, int fd,
|
||||||
|
bool closeFD);
|
||||||
|
|
||||||
static struct io_context *get_current_io_context(bool kernel);
|
static struct io_context *get_current_io_context(bool kernel);
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ typedef struct io_context {
|
|||||||
struct file_descriptor **fds;
|
struct file_descriptor **fds;
|
||||||
struct select_info **select_infos;
|
struct select_info **select_infos;
|
||||||
uint8 *fds_close_on_exec;
|
uint8 *fds_close_on_exec;
|
||||||
|
uint8 *fds_close_on_fork;
|
||||||
struct list node_monitors;
|
struct list node_monitors;
|
||||||
uint32 num_monitors;
|
uint32 num_monitors;
|
||||||
uint32 max_monitors;
|
uint32 max_monitors;
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ static const FlagsTypeHandler::FlagInfo kOpenFlagInfos[] = {
|
|||||||
|
|
||||||
FLAG_INFO_ENTRY(O_DIRECTORY),
|
FLAG_INFO_ENTRY(O_DIRECTORY),
|
||||||
|
|
||||||
|
FLAG_INFO_ENTRY(O_CLOFORK),
|
||||||
|
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ static const enum_info kShutdownHow[] = {
|
|||||||
static const FlagsTypeHandler::FlagInfo kSocketFlagInfos[] = {
|
static const FlagsTypeHandler::FlagInfo kSocketFlagInfos[] = {
|
||||||
FLAG_INFO_ENTRY(SOCK_NONBLOCK),
|
FLAG_INFO_ENTRY(SOCK_NONBLOCK),
|
||||||
FLAG_INFO_ENTRY(SOCK_CLOEXEC),
|
FLAG_INFO_ENTRY(SOCK_CLOEXEC),
|
||||||
|
FLAG_INFO_ENTRY(SOCK_CLOFORK),
|
||||||
|
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -109,6 +109,23 @@ fd_set_close_on_exec(struct io_context* context, int fd, bool closeFD)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
fd_close_on_fork(const struct io_context* context, int fd)
|
||||||
|
{
|
||||||
|
return CHECK_BIT(context->fds_close_on_fork[fd / 8], fd & 7) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
fd_set_close_on_fork(struct io_context* context, int fd, bool closeFD)
|
||||||
|
{
|
||||||
|
if (closeFD)
|
||||||
|
context->fds_close_on_fork[fd / 8] |= (1 << (fd & 7));
|
||||||
|
else
|
||||||
|
context->fds_close_on_fork[fd / 8] &= ~(1 << (fd & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Searches a free slot in the FD table of the provided I/O context, and
|
/*! Searches a free slot in the FD table of the provided I/O context, and
|
||||||
inserts the specified descriptor into it.
|
inserts the specified descriptor into it.
|
||||||
*/
|
*/
|
||||||
@@ -315,6 +332,7 @@ remove_fd(struct io_context* context, int fd)
|
|||||||
|
|
||||||
context->fds[fd] = NULL;
|
context->fds[fd] = NULL;
|
||||||
fd_set_close_on_exec(context, fd, false);
|
fd_set_close_on_exec(context, fd, false);
|
||||||
|
fd_set_close_on_fork(context, fd, false);
|
||||||
context->num_used_fds--;
|
context->num_used_fds--;
|
||||||
|
|
||||||
selectInfos = context->select_infos[fd];
|
selectInfos = context->select_infos[fd];
|
||||||
@@ -351,6 +369,7 @@ dup_fd(int fd, bool kernel)
|
|||||||
} else {
|
} else {
|
||||||
WriteLocker locker(context->lock);
|
WriteLocker locker(context->lock);
|
||||||
fd_set_close_on_exec(context, status, false);
|
fd_set_close_on_exec(context, status, false);
|
||||||
|
fd_set_close_on_fork(context, status, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -374,7 +393,7 @@ dup2_fd(int oldfd, int newfd, int flags, bool kernel)
|
|||||||
// quick check
|
// quick check
|
||||||
if (oldfd < 0 || newfd < 0)
|
if (oldfd < 0 || newfd < 0)
|
||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
if ((flags & ~O_CLOEXEC) != 0)
|
if ((flags & ~(O_CLOEXEC | O_CLOFORK)) != 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// Get current I/O context and lock it
|
// Get current I/O context and lock it
|
||||||
@@ -411,6 +430,7 @@ dup2_fd(int oldfd, int newfd, int flags, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fd_set_close_on_exec(context, newfd, (flags & O_CLOEXEC) != 0);
|
fd_set_close_on_exec(context, newfd, (flags & O_CLOEXEC) != 0);
|
||||||
|
fd_set_close_on_fork(context, newfd, (flags & O_CLOFORK) != 0);
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
|
|||||||
@@ -371,6 +371,8 @@ create_socket_fd(net_socket* socket, int flags, bool kernel)
|
|||||||
int oflags = 0;
|
int oflags = 0;
|
||||||
if ((flags & SOCK_CLOEXEC) != 0)
|
if ((flags & SOCK_CLOEXEC) != 0)
|
||||||
oflags |= O_CLOEXEC;
|
oflags |= O_CLOEXEC;
|
||||||
|
if ((flags & SOCK_CLOFORK) != 0)
|
||||||
|
oflags |= O_CLOFORK;
|
||||||
if ((flags & SOCK_NONBLOCK) != 0 || nonBlock)
|
if ((flags & SOCK_NONBLOCK) != 0 || nonBlock)
|
||||||
oflags |= O_NONBLOCK;
|
oflags |= O_NONBLOCK;
|
||||||
|
|
||||||
@@ -394,6 +396,7 @@ create_socket_fd(net_socket* socket, int flags, bool kernel)
|
|||||||
|
|
||||||
rw_lock_write_lock(&context->lock);
|
rw_lock_write_lock(&context->lock);
|
||||||
fd_set_close_on_exec(context, fd, (oflags & O_CLOEXEC) != 0);
|
fd_set_close_on_exec(context, fd, (oflags & O_CLOEXEC) != 0);
|
||||||
|
fd_set_close_on_fork(context, fd, (oflags & O_CLOFORK) != 0);
|
||||||
rw_lock_write_unlock(&context->lock);
|
rw_lock_write_unlock(&context->lock);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
@@ -409,8 +412,8 @@ common_socket(int family, int type, int protocol, bool kernel)
|
|||||||
if (!get_stack_interface_module())
|
if (!get_stack_interface_module())
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
int sflags = type & (SOCK_CLOEXEC | SOCK_NONBLOCK);
|
int sflags = type & (SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_CLOFORK);
|
||||||
type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
|
type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_CLOFORK);
|
||||||
|
|
||||||
// create the socket
|
// create the socket
|
||||||
net_socket* socket;
|
net_socket* socket;
|
||||||
@@ -487,7 +490,7 @@ common_accept(int fd, struct sockaddr *address, socklen_t *_addressLength, int f
|
|||||||
GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
|
GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
|
||||||
FileDescriptorPutter _(descriptor);
|
FileDescriptorPutter _(descriptor);
|
||||||
|
|
||||||
if ((flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) != 0)
|
if ((flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_CLOFORK)) != 0)
|
||||||
RETURN_AND_SET_ERRNO(B_BAD_VALUE);
|
RETURN_AND_SET_ERRNO(B_BAD_VALUE);
|
||||||
|
|
||||||
net_socket* acceptedSocket;
|
net_socket* acceptedSocket;
|
||||||
@@ -649,8 +652,8 @@ common_socketpair(int family, int type, int protocol, int fds[2], bool kernel)
|
|||||||
if (!get_stack_interface_module())
|
if (!get_stack_interface_module())
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
int sflags = type & (SOCK_CLOEXEC | SOCK_NONBLOCK);
|
int sflags = type & (SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_CLOFORK);
|
||||||
type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
|
type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_CLOFORK);
|
||||||
|
|
||||||
net_socket* sockets[2];
|
net_socket* sockets[2];
|
||||||
status_t error = sStackInterface->socketpair(family, type, protocol,
|
status_t error = sStackInterface->socketpair(family, type, protocol,
|
||||||
|
|||||||
@@ -2883,6 +2883,7 @@ get_new_fd(struct fd_ops* ops, struct fs_mount* mount, struct vnode* vnode,
|
|||||||
|
|
||||||
rw_lock_write_lock(&context->lock);
|
rw_lock_write_lock(&context->lock);
|
||||||
fd_set_close_on_exec(context, fd, (openMode & O_CLOEXEC) != 0);
|
fd_set_close_on_exec(context, fd, (openMode & O_CLOEXEC) != 0);
|
||||||
|
fd_set_close_on_fork(context, fd, (openMode & O_CLOFORK) != 0);
|
||||||
rw_lock_write_unlock(&context->lock);
|
rw_lock_write_unlock(&context->lock);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
@@ -3659,6 +3660,7 @@ free_io_context(io_context* context)
|
|||||||
remove_node_monitors(context);
|
remove_node_monitors(context);
|
||||||
|
|
||||||
free(context->fds_close_on_exec);
|
free(context->fds_close_on_exec);
|
||||||
|
free(context->fds_close_on_fork);
|
||||||
free(context->select_infos);
|
free(context->select_infos);
|
||||||
free(context->fds);
|
free(context->fds);
|
||||||
free(context);
|
free(context);
|
||||||
@@ -4974,7 +4976,8 @@ vfs_new_io_context(const io_context* parentContext, bool purgeCloseOnExec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool closeOnExec = fd_close_on_exec(parentContext, i);
|
const bool closeOnExec = fd_close_on_exec(parentContext, i);
|
||||||
if (closeOnExec && purgeCloseOnExec)
|
const bool closeOnFork = fd_close_on_fork(parentContext, i);
|
||||||
|
if ((closeOnExec && purgeCloseOnExec) || (closeOnFork && !purgeCloseOnExec))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TFD(InheritFD(context, i, descriptor, parentContext));
|
TFD(InheritFD(context, i, descriptor, parentContext));
|
||||||
@@ -4986,6 +4989,8 @@ vfs_new_io_context(const io_context* parentContext, bool purgeCloseOnExec)
|
|||||||
|
|
||||||
if (closeOnExec)
|
if (closeOnExec)
|
||||||
fd_set_close_on_exec(context, i, true);
|
fd_set_close_on_exec(context, i, true);
|
||||||
|
if (closeOnFork)
|
||||||
|
fd_set_close_on_fork(context, i, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
parentLocker.Unlock();
|
parentLocker.Unlock();
|
||||||
@@ -5048,6 +5053,7 @@ vfs_resize_fd_table(struct io_context* context, uint32 newSize)
|
|||||||
file_descriptor** oldFDs = context->fds;
|
file_descriptor** oldFDs = context->fds;
|
||||||
select_info** oldSelectInfos = context->select_infos;
|
select_info** oldSelectInfos = context->select_infos;
|
||||||
uint8* oldCloseOnExecTable = context->fds_close_on_exec;
|
uint8* oldCloseOnExecTable = context->fds_close_on_exec;
|
||||||
|
uint8* oldCloseOnForkTable = context->fds_close_on_fork;
|
||||||
|
|
||||||
// allocate new tables (separately to reduce the chances of needing a raw allocation)
|
// allocate new tables (separately to reduce the chances of needing a raw allocation)
|
||||||
file_descriptor** newFDs = (file_descriptor**)malloc(
|
file_descriptor** newFDs = (file_descriptor**)malloc(
|
||||||
@@ -5055,16 +5061,20 @@ vfs_resize_fd_table(struct io_context* context, uint32 newSize)
|
|||||||
select_info** newSelectInfos = (select_info**)malloc(
|
select_info** newSelectInfos = (select_info**)malloc(
|
||||||
+ sizeof(select_info**) * newSize);
|
+ sizeof(select_info**) * newSize);
|
||||||
uint8* newCloseOnExecTable = (uint8*)malloc(newCloseOnExitBitmapSize);
|
uint8* newCloseOnExecTable = (uint8*)malloc(newCloseOnExitBitmapSize);
|
||||||
if (newFDs == NULL || newSelectInfos == NULL || newCloseOnExecTable == NULL) {
|
uint8* newCloseOnForkTable = (uint8*)malloc(newCloseOnExitBitmapSize);
|
||||||
|
if (newFDs == NULL || newSelectInfos == NULL || newCloseOnExecTable == NULL
|
||||||
|
|| newCloseOnForkTable == NULL) {
|
||||||
free(newFDs);
|
free(newFDs);
|
||||||
free(newSelectInfos);
|
free(newSelectInfos);
|
||||||
free(newCloseOnExecTable);
|
free(newCloseOnExecTable);
|
||||||
|
free(newCloseOnForkTable);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
context->fds = newFDs;
|
context->fds = newFDs;
|
||||||
context->select_infos = newSelectInfos;
|
context->select_infos = newSelectInfos;
|
||||||
context->fds_close_on_exec = newCloseOnExecTable;
|
context->fds_close_on_exec = newCloseOnExecTable;
|
||||||
|
context->fds_close_on_fork = newCloseOnForkTable;
|
||||||
context->table_size = newSize;
|
context->table_size = newSize;
|
||||||
|
|
||||||
if (oldSize != 0) {
|
if (oldSize != 0) {
|
||||||
@@ -5075,6 +5085,8 @@ vfs_resize_fd_table(struct io_context* context, uint32 newSize)
|
|||||||
memcpy(context->select_infos, oldSelectInfos, sizeof(void*) * toCopy);
|
memcpy(context->select_infos, oldSelectInfos, sizeof(void*) * toCopy);
|
||||||
memcpy(context->fds_close_on_exec, oldCloseOnExecTable,
|
memcpy(context->fds_close_on_exec, oldCloseOnExecTable,
|
||||||
min_c(oldCloseOnExitBitmapSize, newCloseOnExitBitmapSize));
|
min_c(oldCloseOnExitBitmapSize, newCloseOnExitBitmapSize));
|
||||||
|
memcpy(context->fds_close_on_fork, oldCloseOnForkTable,
|
||||||
|
min_c(oldCloseOnExitBitmapSize, newCloseOnExitBitmapSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear additional entries, if the tables grow
|
// clear additional entries, if the tables grow
|
||||||
@@ -5084,11 +5096,14 @@ vfs_resize_fd_table(struct io_context* context, uint32 newSize)
|
|||||||
sizeof(void*) * (newSize - oldSize));
|
sizeof(void*) * (newSize - oldSize));
|
||||||
memset(context->fds_close_on_exec + oldCloseOnExitBitmapSize, 0,
|
memset(context->fds_close_on_exec + oldCloseOnExitBitmapSize, 0,
|
||||||
newCloseOnExitBitmapSize - oldCloseOnExitBitmapSize);
|
newCloseOnExitBitmapSize - oldCloseOnExitBitmapSize);
|
||||||
|
memset(context->fds_close_on_fork + oldCloseOnExitBitmapSize, 0,
|
||||||
|
newCloseOnExitBitmapSize - oldCloseOnExitBitmapSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(oldFDs);
|
free(oldFDs);
|
||||||
free(oldSelectInfos);
|
free(oldSelectInfos);
|
||||||
free(oldCloseOnExecTable);
|
free(oldCloseOnExecTable);
|
||||||
|
free(oldCloseOnForkTable);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -6238,9 +6253,10 @@ common_fcntl(int fd, int op, size_t argument, bool kernel)
|
|||||||
{
|
{
|
||||||
// Set file descriptor flags
|
// Set file descriptor flags
|
||||||
|
|
||||||
// O_CLOEXEC is the only flag available at this time
|
// O_CLOEXEC and O_CLOFORK are the only flags available at this time
|
||||||
rw_lock_write_lock(&context->lock);
|
rw_lock_write_lock(&context->lock);
|
||||||
fd_set_close_on_exec(context, fd, (argument & FD_CLOEXEC) != 0);
|
fd_set_close_on_exec(context, fd, (argument & FD_CLOEXEC) != 0);
|
||||||
|
fd_set_close_on_fork(context, fd, (argument & FD_CLOFORK) != 0);
|
||||||
rw_lock_write_unlock(&context->lock);
|
rw_lock_write_unlock(&context->lock);
|
||||||
|
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
@@ -6252,6 +6268,7 @@ common_fcntl(int fd, int op, size_t argument, bool kernel)
|
|||||||
// Get file descriptor flags
|
// Get file descriptor flags
|
||||||
rw_lock_read_lock(&context->lock);
|
rw_lock_read_lock(&context->lock);
|
||||||
status = fd_close_on_exec(context, fd) ? FD_CLOEXEC : 0;
|
status = fd_close_on_exec(context, fd) ? FD_CLOEXEC : 0;
|
||||||
|
status |= fd_close_on_fork(context, fd) ? FD_CLOFORK : 0;
|
||||||
rw_lock_read_unlock(&context->lock);
|
rw_lock_read_unlock(&context->lock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -6288,11 +6305,15 @@ common_fcntl(int fd, int op, size_t argument, bool kernel)
|
|||||||
|
|
||||||
case F_DUPFD:
|
case F_DUPFD:
|
||||||
case F_DUPFD_CLOEXEC:
|
case F_DUPFD_CLOEXEC:
|
||||||
|
case F_DUPFD_CLOFORK:
|
||||||
{
|
{
|
||||||
status = new_fd_etc(context, descriptor.Get(), (int)argument);
|
status = new_fd_etc(context, descriptor.Get(), (int)argument);
|
||||||
if (status >= 0) {
|
if (status >= 0) {
|
||||||
rw_lock_write_lock(&context->lock);
|
rw_lock_write_lock(&context->lock);
|
||||||
fd_set_close_on_exec(context, status, op == F_DUPFD_CLOEXEC);
|
if (op == F_DUPFD_CLOEXEC)
|
||||||
|
fd_set_close_on_exec(context, status, true);
|
||||||
|
else if (op == F_DUPFD_CLOFORK)
|
||||||
|
fd_set_close_on_fork(context, status, true);
|
||||||
rw_lock_write_unlock(&context->lock);
|
rw_lock_write_unlock(&context->lock);
|
||||||
|
|
||||||
atomic_add(&descriptor->ref_count, 1);
|
atomic_add(&descriptor->ref_count, 1);
|
||||||
@@ -9575,7 +9596,7 @@ status_t
|
|||||||
_user_create_pipe(int* userFDs, int flags)
|
_user_create_pipe(int* userFDs, int flags)
|
||||||
{
|
{
|
||||||
// check acceptable flags
|
// check acceptable flags
|
||||||
if ((flags & ~(O_NONBLOCK | O_CLOEXEC)) != 0)
|
if ((flags & ~(O_NONBLOCK | O_CLOEXEC | O_CLOFORK)) != 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// rootfs should support creating FIFOs, but let's be sure
|
// rootfs should support creating FIFOs, but let's be sure
|
||||||
|
|||||||
@@ -31,5 +31,7 @@ dup3(int oldFD, int newFD, int flags)
|
|||||||
{
|
{
|
||||||
if (oldFD == newFD)
|
if (oldFD == newFD)
|
||||||
RETURN_AND_SET_ERRNO(EINVAL);
|
RETURN_AND_SET_ERRNO(EINVAL);
|
||||||
|
if ((flags & ~(O_CLOEXEC | O_CLOFORK)) != 0)
|
||||||
|
RETURN_AND_SET_ERRNO(EINVAL);
|
||||||
RETURN_AND_SET_ERRNO(_kern_dup2(oldFD, newFD, flags));
|
RETURN_AND_SET_ERRNO(_kern_dup2(oldFD, newFD, flags));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user