@@ -41,14 +41,22 @@ 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 > {
4647 auto description = TRY (fds.open_file_description (action->old_fd ));
4748 if (action->old_fd != action->new_fd ) {
4849 if (action->new_fd < 0 || static_cast <size_t >(action->new_fd ) >= fds.max_open ())
4950 return EINVAL;
50- if (!fds.m_fds_metadatas [action->new_fd ].is_allocated ())
51+
52+ if (fds.m_fds_metadatas [action->new_fd ].is_allocated ()) {
53+ if (auto * old_description = fds[action->new_fd ].description ())
54+ (void )old_description->close ();
55+ fds[action->new_fd ].clear ();
56+ } else {
5157 fds.m_fds_metadatas [action->new_fd ].allocate ();
58+ }
59+
5260 fds[action->new_fd ].set (move (description));
5361 }
5462 return {};
@@ -58,6 +66,7 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
5866 case SpawnFileActionType::Close: {
5967 if (header->record_length < sizeof (SpawnFileActionClose))
6068 return EINVAL;
69+
6170 auto const * action = reinterpret_cast <SpawnFileActionClose const *>(header);
6271 TRY (m_fds.with_exclusive ([&](auto & fds) -> ErrorOr<void > {
6372 auto description = TRY (fds.open_file_description (action->fd ));
@@ -70,9 +79,11 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
7079 case SpawnFileActionType::Open: {
7180 if (header->record_length < sizeof (SpawnFileActionOpen))
7281 return EINVAL;
82+
7383 auto const * action = reinterpret_cast <SpawnFileActionOpen const *>(header);
7484 if (header->record_length < sizeof (SpawnFileActionOpen) + action->path_length )
7585 return EINVAL;
86+
7687 auto path = TRY (KString::try_create (StringView { action->path , action->path_length }));
7788 CustodyBase base (AT_FDCWD, path->view ());
7889 auto description = TRY (VirtualFileSystem::open (
@@ -85,20 +96,30 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
8596 TRY (m_fds.with_exclusive ([&](auto & fds) -> ErrorOr<void > {
8697 if (action->fd < 0 || static_cast <size_t >(action->fd ) >= fds.max_open ())
8798 return EINVAL;
88- if (!fds.m_fds_metadatas [action->fd ].is_allocated ())
99+
100+ if (fds.m_fds_metadatas [action->fd ].is_allocated ()) {
101+ if (auto * old_description = fds[action->fd ].description ())
102+ (void )old_description->close ();
103+ fds[action->fd ].clear ();
104+ } else {
89105 fds.m_fds_metadatas [action->fd ].allocate ();
106+ }
107+
90108 u32 fd_flags = (action->flags & O_CLOEXEC) ? FD_CLOEXEC : 0 ;
91109 fds[action->fd ].set (move (description), fd_flags);
92110 return {};
93111 }));
94112 break ;
95113 }
114+
96115 case SpawnFileActionType::Chdir: {
97116 if (header->record_length < sizeof (SpawnFileActionChdir))
98117 return EINVAL;
118+
99119 auto const * action = reinterpret_cast <SpawnFileActionChdir const *>(header);
100120 if (header->record_length < sizeof (SpawnFileActionChdir) + action->path_length )
101121 return EINVAL;
122+
102123 auto path = TRY (KString::try_create (StringView { action->path , action->path_length }));
103124 auto new_directory = TRY (VirtualFileSystem::open_directory (
104125 vfs_root_context (), credentials (), path->view (), current_directory ()));
@@ -110,12 +131,16 @@ ErrorOr<void> Process::execute_file_actions(ReadonlyBytes file_actions_data)
110131 case SpawnFileActionType::Fchdir: {
111132 if (header->record_length < sizeof (SpawnFileActionFchdir))
112133 return EINVAL;
134+
113135 auto const * action = reinterpret_cast <SpawnFileActionFchdir const *>(header);
114136 auto description = TRY (open_file_description (action->fd ));
115137 if (!description->is_directory ())
116138 return ENOTDIR;
139+
140+ // Check for search (+x) permission on the directory.
117141 if (!description->metadata ().may_execute (credentials ()))
118142 return EACCES;
143+
119144 m_current_directory.with ([&](auto & current_directory) {
120145 current_directory = description->custody ();
121146 });
@@ -183,9 +208,9 @@ ErrorOr<FlatPtr> Process::sys$posix_spawn(Userspace<Syscall::SC_posix_spawn_para
183208 Vector<NonnullOwnPtr<KString>> environment;
184209 TRY (copy_user_strings (params.environment , environment));
185210
186- auto const & creds = this ->credentials ();
211+ auto const & credentials = this ->credentials ();
187212 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 ()));
213+ auto [child, child_first_thread] = TRY (Process::create_spawned (credentials ->uid (), credentials ->gid (), pid (), vfs_root_context (), hostname_context (), current_directory (), tty ()));
189214
190215 ArmedScopeGuard thread_finalizer_guard = [&child_first_thread]() {
191216 SpinlockLocker lock (g_scheduler_lock);
0 commit comments