Skip to content

Commit fb67227

Browse files
committed
fix(syscall): honor per-handle FD_CLOEXEC in fcntl
1 parent 43ed7eb commit fb67227

4 files changed

Lines changed: 38 additions & 5 deletions

File tree

kernel/fs/fstypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ constexpr uint32_t O_EXCL = 0x80;
2626
constexpr uint32_t O_TRUNC = 0x200;
2727
constexpr uint32_t O_APPEND = 0x400;
2828
constexpr uint32_t O_NONBLOCK = 0x800;
29+
constexpr uint32_t O_CLOEXEC = 0x80000;
2930

3031
constexpr uint32_t ACCESS_MODE_MASK = 0x3;
3132

kernel/resource/handle_table.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ struct resource_object;
1010

1111
constexpr uint32_t MAX_TASK_HANDLES = 128;
1212

13+
// Private high bit in handle_entry::flags reserved for FD_CLOEXEC state
14+
constexpr uint32_t RESOURCE_HANDLE_CLOEXEC = 0x80000000;
15+
1316
struct handle_entry {
1417
bool used;
1518
uint16_t generation;

kernel/resource/resource.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ __PRIVILEGED_CODE int32_t open(
113113
return (rc == HANDLE_ERR_NOSPC) ? ERR_TABLEFULL : ERR_IO;
114114
}
115115

116+
if (flags & fs::O_CLOEXEC) {
117+
uint32_t handle_flags = 0;
118+
get_handle_flags(&owner->handles, *out_handle, &handle_flags);
119+
set_handle_flags(&owner->handles, *out_handle,
120+
handle_flags | RESOURCE_HANDLE_CLOEXEC);
121+
}
122+
116123
// Table now owns one reference.
117124
resource_release(obj);
118125
return OK;

kernel/syscall/handlers/sys_fd.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@ DEFINE_SYSCALL3(fcntl, fd, cmd, arg) {
11841184
if (rc != resource::HANDLE_OK) {
11851185
return syscall::EBADF;
11861186
}
1187-
return FD_CLOEXEC;
1187+
return (flags & resource::RESOURCE_HANDLE_CLOEXEC) ? FD_CLOEXEC : 0;
11881188
}
11891189

11901190
if (cmd == F_SETFD) {
@@ -1194,24 +1194,46 @@ DEFINE_SYSCALL3(fcntl, fd, cmd, arg) {
11941194
if (rc != resource::HANDLE_OK) {
11951195
return syscall::EBADF;
11961196
}
1197-
(void)arg;
1197+
1198+
flags &= ~resource::RESOURCE_HANDLE_CLOEXEC;
1199+
if (arg & FD_CLOEXEC) {
1200+
flags |= resource::RESOURCE_HANDLE_CLOEXEC;
1201+
}
1202+
1203+
rc = resource::set_handle_flags(
1204+
&task->handles, static_cast<resource::handle_t>(fd), flags);
1205+
1206+
if (rc != resource::HANDLE_OK) {
1207+
return syscall::EBADF;
1208+
}
11981209
return 0;
11991210
}
12001211

12011212
if (cmd == F_GETFL) {
12021213
uint32_t flags = 0;
12031214
int32_t rc = resource::get_handle_flags(
12041215
&task->handles, static_cast<resource::handle_t>(fd), &flags);
1216+
12051217
if (rc != resource::HANDLE_OK) {
12061218
return syscall::EBADF;
12071219
}
1208-
return static_cast<int64_t>(flags);
1220+
1221+
return static_cast<int64_t>(flags & ~resource::RESOURCE_HANDLE_CLOEXEC);
12091222
}
12101223

12111224
if (cmd == F_SETFL) {
1212-
uint32_t flags = static_cast<uint32_t>(arg) & SETFL_MASK;
1213-
int32_t rc = resource::set_handle_flags(
1225+
uint32_t flags = 0;
1226+
int32_t rc = resource::get_handle_flags(
1227+
&task->handles, static_cast<resource::handle_t>(fd), &flags);
1228+
1229+
if (rc != resource::HANDLE_OK) {
1230+
return syscall::EBADF;
1231+
}
1232+
1233+
flags = (flags & ~SETFL_MASK) | (static_cast<uint32_t>(arg) & SETFL_MASK);
1234+
rc = resource::set_handle_flags(
12141235
&task->handles, static_cast<resource::handle_t>(fd), flags);
1236+
12151237
if (rc != resource::HANDLE_OK) {
12161238
return syscall::EBADF;
12171239
}

0 commit comments

Comments
 (0)