@@ -41,14 +41,23 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
4141 case SpawnFileActionType::Dup2: {
4242 if (header->record_length < sizeof (SpawnFileActionDup2))
4343 return EINVAL;
44+
4445 auto const * action = reinterpret_cast <SpawnFileActionDup2 const *>(header);
4546 TRY (m_fds.with_exclusive ([&](auto & fds) -> ErrorOr<void > {
47+ if (action->new_fd < 0 || static_cast <size_t >(action->new_fd ) >= fds.max_open ())
48+ return EINVAL;
49+
4650 auto description = TRY (fds.open_file_description (action->old_fd ));
4751 if (action->old_fd != action->new_fd ) {
48- if (action->new_fd < 0 || static_cast <size_t >(action->new_fd ) >= fds.max_open ())
49- return EINVAL;
50- if (!fds.m_fds_metadatas [action->new_fd ].is_allocated ())
52+
53+ if (fds.m_fds_metadatas [action->new_fd ].is_allocated ()) {
54+ if (auto * old_description = fds[action->new_fd ].description ())
55+ (void )old_description->close ();
56+ fds[action->new_fd ].clear ();
57+ } else {
5158 fds.m_fds_metadatas [action->new_fd ].allocate ();
59+ }
60+
5261 fds[action->new_fd ].set (move (description));
5362 }
5463 return {};
@@ -58,6 +67,7 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
5867 case SpawnFileActionType::Close: {
5968 if (header->record_length < sizeof (SpawnFileActionClose))
6069 return EINVAL;
70+
6171 auto const * action = reinterpret_cast <SpawnFileActionClose const *>(header);
6272 TRY (m_fds.with_exclusive ([&](auto & fds) -> ErrorOr<void > {
6373 auto description = TRY (fds.open_file_description (action->fd ));
@@ -70,9 +80,11 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
7080 case SpawnFileActionType::Open: {
7181 if (header->record_length < sizeof (SpawnFileActionOpen))
7282 return EINVAL;
83+
7384 auto const * action = reinterpret_cast <SpawnFileActionOpen const *>(header);
7485 if (header->record_length < sizeof (SpawnFileActionOpen) + action->path_length )
7586 return EINVAL;
87+
7688 auto path = TRY (KString::try_create (StringView { action->path , action->path_length }));
7789 CustodyBase base (AT_FDCWD, path->view ());
7890 auto description = TRY (VirtualFileSystem::open (
@@ -85,20 +97,30 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
8597 TRY (m_fds.with_exclusive ([&](auto & fds) -> ErrorOr<void > {
8698 if (action->fd < 0 || static_cast <size_t >(action->fd ) >= fds.max_open ())
8799 return EINVAL;
88- if (!fds.m_fds_metadatas [action->fd ].is_allocated ())
100+
101+ if (fds.m_fds_metadatas [action->fd ].is_allocated ()) {
102+ if (auto * old_description = fds[action->fd ].description ())
103+ (void )old_description->close ();
104+ fds[action->fd ].clear ();
105+ } else {
89106 fds.m_fds_metadatas [action->fd ].allocate ();
107+ }
108+
90109 u32 fd_flags = (action->flags & O_CLOEXEC) ? FD_CLOEXEC : 0 ;
91110 fds[action->fd ].set (move (description), fd_flags);
92111 return {};
93112 }));
94113 break ;
95114 }
115+
96116 case SpawnFileActionType::Chdir: {
97117 if (header->record_length < sizeof (SpawnFileActionChdir))
98118 return EINVAL;
119+
99120 auto const * action = reinterpret_cast <SpawnFileActionChdir const *>(header);
100121 if (header->record_length < sizeof (SpawnFileActionChdir) + action->path_length )
101122 return EINVAL;
123+
102124 auto path = TRY (KString::try_create (StringView { action->path , action->path_length }));
103125 auto new_directory = TRY (VirtualFileSystem::open_directory (
104126 vfs_root_context (), credentials (), path->view (), current_directory ()));
@@ -110,12 +132,16 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
110132 case SpawnFileActionType::Fchdir: {
111133 if (header->record_length < sizeof (SpawnFileActionFchdir))
112134 return EINVAL;
135+
113136 auto const * action = reinterpret_cast <SpawnFileActionFchdir const *>(header);
114137 auto description = TRY (open_file_description (action->fd ));
115138 if (!description->is_directory ())
116139 return ENOTDIR;
140+
141+ // Check for search (+x) permission on the directory.
117142 if (!description->metadata ().may_execute (credentials ()))
118143 return EACCES;
144+
119145 m_current_directory.with ([&](auto & current_directory) {
120146 current_directory = description->custody ();
121147 });
@@ -183,9 +209,9 @@ ErrorOr<FlatPtr> Process::sys$posix_spawn(Userspace<Syscall::SC_posix_spawn_para
183209 Vector<NonnullOwnPtr<KString>> environment;
184210 TRY (copy_user_strings (params.environment , environment));
185211
186- auto const & creds = this ->credentials ();
212+ auto const & credentials = this ->credentials ();
187213 VERIFY (!m_is_kernel_process);
188- auto [child, child_first_thread] = TRY (Process::create_spawned (creds ->uid (), creds ->gid (), pid (), vfs_root_context (), hostname_context (), current_directory (), tty ()));
214+ auto [child, child_first_thread] = TRY (Process::create_spawned (credentials ->uid (), credentials ->gid (), pid (), vfs_root_context (), hostname_context (), current_directory (), tty ()));
189215
190216 ArmedScopeGuard thread_finalizer_guard = [&child_first_thread]() {
191217 SpinlockLocker lock (g_scheduler_lock);
0 commit comments