libbsd: add closefrom() and close_range()

Change-Id: I9c88948d6c4d5a32e3aa06cd696e2ce24c2d298f
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9334
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Jérôme Duval
2025-06-09 16:26:13 +00:00
committed by waddlesplash
parent 396ebbc16f
commit 23f923bcaf
8 changed files with 86 additions and 0 deletions
+3
View File
@@ -28,6 +28,9 @@ char *getusershell(void);
int issetugid(void); int issetugid(void);
void setusershell(void); void setusershell(void);
int closefrom(int lowFd);
int close_range(u_int minFd, u_int maxFd, int flags);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+2
View File
@@ -327,6 +327,8 @@
# define SEEK_HOLE 4 # define SEEK_HOLE 4
#endif #endif
#define CLOSE_RANGE_CLOEXEC 0x4
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
+1
View File
@@ -255,6 +255,7 @@ int _user_dup2(int ofd, int nfd, int flags);
status_t _user_lock_node(int fd); status_t _user_lock_node(int fd);
status_t _user_unlock_node(int fd); status_t _user_unlock_node(int fd);
status_t _user_preallocate(int fd, off_t offset, off_t length); status_t _user_preallocate(int fd, off_t offset, off_t length);
status_t _user_close_range(u_int minFd, u_int maxFd, int flags);
/* socket user prototypes (implementation in socket.cpp) */ /* socket user prototypes (implementation in socket.cpp) */
int _user_socket(int family, int type, int protocol); int _user_socket(int family, int type, int protocol);
+1
View File
@@ -355,6 +355,7 @@ extern status_t _kern_unlock_node(int fd);
extern status_t _kern_get_next_fd_info(team_id team, uint32 *_cookie, extern status_t _kern_get_next_fd_info(team_id team, uint32 *_cookie,
struct fd_info *info, size_t infoSize); struct fd_info *info, size_t infoSize);
extern status_t _kern_preallocate(int fd, off_t offset, off_t length); extern status_t _kern_preallocate(int fd, off_t offset, off_t length);
extern status_t _kern_close_range(u_int minFd, u_int maxFd, int flags);
// socket functions // socket functions
extern int _kern_socket(int family, int type, int protocol); extern int _kern_socket(int family, int type, int protocol);
+15
View File
@@ -44,6 +44,13 @@ static const FlagsTypeHandler::FlagInfo kOpenFlagInfos[] = {
}; };
static const FlagsTypeHandler::FlagInfo kCloseRangeFlagInfos[] = {
FLAG_INFO_ENTRY(CLOSE_RANGE_CLOEXEC),
{ 0, NULL }
};
struct fcntl_info { struct fcntl_info {
unsigned int index; unsigned int index;
const char *name; const char *name;
@@ -69,6 +76,7 @@ static const fcntl_info kFcntls[] = {
}; };
static FlagsTypeHandler::FlagsList kOpenFlags; static FlagsTypeHandler::FlagsList kOpenFlags;
static FlagsTypeHandler::FlagsList kCloseRangeFlags;
static EnumTypeHandler::EnumMap kFcntlNames; static EnumTypeHandler::EnumMap kFcntlNames;
static TypeHandlerSelector::SelectMap kFcntlTypeHandlers; static TypeHandlerSelector::SelectMap kFcntlTypeHandlers;
@@ -79,6 +87,10 @@ patch_fcntl()
kOpenFlags.push_back(kOpenFlagInfos[i]); kOpenFlags.push_back(kOpenFlagInfos[i]);
} }
for (int i = 0; kCloseRangeFlagInfos[i].name != NULL; i++) {
kCloseRangeFlags.push_back(kCloseRangeFlagInfos[i]);
}
for (int i = 0; kFcntls[i].name != NULL; i++) { for (int i = 0; kFcntls[i].name != NULL; i++) {
kFcntlNames[kFcntls[i].index] = kFcntls[i].name; kFcntlNames[kFcntls[i].index] = kFcntls[i].name;
if (kFcntls[i].handler != NULL) if (kFcntls[i].handler != NULL)
@@ -90,6 +102,9 @@ patch_fcntl()
Syscall *open = get_syscall("_kern_open"); Syscall *open = get_syscall("_kern_open");
open->GetParameter("openMode")->SetHandler(new FlagsTypeHandler(kOpenFlags)); open->GetParameter("openMode")->SetHandler(new FlagsTypeHandler(kOpenFlags));
Syscall *closeRange = get_syscall("_kern_close_range");
closeRange->GetParameter("flags")->SetHandler(new FlagsTypeHandler(kCloseRangeFlags));
Syscall *fcntl = get_syscall("_kern_fcntl"); Syscall *fcntl = get_syscall("_kern_fcntl");
fcntl->GetParameter("op")->SetHandler(new EnumTypeHandler(kFcntlNames)); fcntl->GetParameter("op")->SetHandler(new EnumTypeHandler(kFcntlNames));
fcntl->GetParameter("argument")->SetHandler( fcntl->GetParameter("argument")->SetHandler(
+1
View File
@@ -13,6 +13,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
SharedLibrary [ MultiArchDefaultGristFiles libbsd.so ] : SharedLibrary [ MultiArchDefaultGristFiles libbsd.so ] :
arc4random.c arc4random.c
arc4random_uniform.c arc4random_uniform.c
closefrom.cpp
daemon.c daemon.c
dl_iterate_phdr.c dl_iterate_phdr.c
err.c err.c
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright 2025, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <unistd.h>
#include <errno_private.h>
#include <syscall_utils.h>
#include <syscalls.h>
extern "C" int
closefrom(int lowFd)
{
RETURN_AND_SET_ERRNO(_kern_close_range(lowFd, ~0, 0));
}
extern "C" int
close_range(u_int minFd, u_int maxFd, int flags)
{
RETURN_AND_SET_ERRNO(_kern_close_range(minFd, maxFd, flags));
}
+37
View File
@@ -857,6 +857,27 @@ common_close(int fd, bool kernel)
} }
static status_t
common_close_range(u_int minFd, u_int maxFd, int flags, bool kernel)
{
if (maxFd < minFd)
return B_BAD_VALUE;
struct io_context* context = get_current_io_context(kernel);
maxFd = min_c(maxFd, context->table_size - 1);
if ((flags & CLOSE_RANGE_CLOEXEC) == 0) {
for (u_int fd = minFd; fd <= maxFd; fd++)
close_fd_index(context, fd);
} else {
WriteLocker locker(context->lock);
for (u_int fd = minFd; fd <= maxFd; fd++) {
if (context->fds[fd] != NULL)
fd_set_close_on_exec(context, fd, true);
}
}
return B_OK;
}
status_t status_t
user_fd_kernel_ioctl(int fd, uint32 op, void* buffer, size_t length) user_fd_kernel_ioctl(int fd, uint32 op, void* buffer, size_t length)
{ {
@@ -1018,6 +1039,15 @@ _user_close(int fd)
} }
status_t
_user_close_range(u_int minFd, u_int maxFd, int flags)
{
if ((flags & ~(CLOSE_RANGE_CLOEXEC)) != 0)
return B_BAD_VALUE;
return common_close_range(minFd, maxFd, flags, false);
}
int int
_user_dup(int fd) _user_dup(int fd)
{ {
@@ -1210,6 +1240,13 @@ _kern_close(int fd)
} }
status_t
_kern_close_range(u_int minFd, u_int maxFd, int flags)
{
return common_close_range(minFd, maxFd, flags, true);
}
int int
_kern_dup(int fd) _kern_dup(int fd)
{ {