forked from Bananymous/banan-os
				
			Kernel/LibC: Implement chroot
This commit is contained in:
		
							parent
							
								
									695262624d
								
							
						
					
					
						commit
						ef6ee78fd1
					
				|  | @ -20,6 +20,6 @@ namespace Kernel::ELF | ||||||
| 		BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions; | 		BAN::Vector<BAN::UniqPtr<MemoryRegion>> regions; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode>, const Credentials&, PageTable&); | 	BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials&, PageTable&); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -71,13 +71,13 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		File root_file() | 		File root_file() | ||||||
| 		{ | 		{ | ||||||
| 			return File(root_inode(), "/"_sv); | 			return File { root_inode(), "/"_sv }; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		BAN::ErrorOr<File> file_from_relative_path(const File& parent, const Credentials&, BAN::StringView, int); | 		BAN::ErrorOr<File> file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials&, BAN::StringView, int); | ||||||
| 		BAN::ErrorOr<File> file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags) | 		BAN::ErrorOr<File> file_from_absolute_path(BAN::RefPtr<Inode> root_inode, const Credentials& credentials, BAN::StringView path, int flags) | ||||||
| 		{ | 		{ | ||||||
| 			return file_from_relative_path(root_file(), credentials, path, flags); | 			return file_from_relative_path(root_inode, File { root_inode, "/"_sv }, credentials, path, flags); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <BAN/WeakPtr.h> | #include <BAN/WeakPtr.h> | ||||||
| #include <kernel/FS/Socket.h> | #include <kernel/FS/Socket.h> | ||||||
| #include <kernel/FS/TmpFS/Inode.h> | #include <kernel/FS/TmpFS/Inode.h> | ||||||
|  | #include <kernel/FS/VirtualFileSystem.h> | ||||||
| #include <kernel/Lock/SpinLock.h> | #include <kernel/Lock/SpinLock.h> | ||||||
| 
 | 
 | ||||||
| namespace Kernel | namespace Kernel | ||||||
|  | @ -39,8 +40,8 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan); | 		BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan); | ||||||
| 
 | 
 | ||||||
| 		bool is_bound() const { return !m_bound_path.empty(); } | 		bool is_bound() const { return !m_bound_file.canonical_path.empty(); } | ||||||
| 		bool is_bound_to_unused() const { return m_bound_path == "X"_sv; } | 		bool is_bound_to_unused() const { return !m_bound_file.inode; } | ||||||
| 
 | 
 | ||||||
| 		bool is_streaming() const; | 		bool is_streaming() const; | ||||||
| 
 | 
 | ||||||
|  | @ -62,8 +63,8 @@ namespace Kernel | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		const Socket::Type	m_socket_type; | 		const Socket::Type		m_socket_type; | ||||||
| 		BAN::String			m_bound_path; | 		VirtualFileSystem::File	m_bound_file; | ||||||
| 
 | 
 | ||||||
| 		BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info; | 		BAN::Variant<ConnectionInfo, ConnectionlessInfo> m_info; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,6 +76,7 @@ namespace Kernel | ||||||
| 		BAN::ErrorOr<long> sys_getcwd(char* buffer, size_t size); | 		BAN::ErrorOr<long> sys_getcwd(char* buffer, size_t size); | ||||||
| 		BAN::ErrorOr<long> sys_chdir(const char* path); | 		BAN::ErrorOr<long> sys_chdir(const char* path); | ||||||
| 		BAN::ErrorOr<long> sys_fchdir(int fildes); | 		BAN::ErrorOr<long> sys_fchdir(int fildes); | ||||||
|  | 		BAN::ErrorOr<long> sys_chroot(const char* path); | ||||||
| 
 | 
 | ||||||
| 		BAN::ErrorOr<long> sys_setuid(uid_t); | 		BAN::ErrorOr<long> sys_setuid(uid_t); | ||||||
| 		BAN::ErrorOr<long> sys_setgid(gid_t); | 		BAN::ErrorOr<long> sys_setgid(gid_t); | ||||||
|  | @ -234,6 +235,7 @@ namespace Kernel | ||||||
| 		static void update_alarm_queue(); | 		static void update_alarm_queue(); | ||||||
| 
 | 
 | ||||||
| 		const VirtualFileSystem::File& working_directory() const { return m_working_directory; } | 		const VirtualFileSystem::File& working_directory() const { return m_working_directory; } | ||||||
|  | 		const VirtualFileSystem::File& root_file() const { return m_root_file; } | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp); | 		Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp); | ||||||
|  | @ -313,6 +315,7 @@ namespace Kernel | ||||||
| 		mutable Mutex m_process_lock; | 		mutable Mutex m_process_lock; | ||||||
| 
 | 
 | ||||||
| 		VirtualFileSystem::File m_working_directory; | 		VirtualFileSystem::File m_working_directory; | ||||||
|  | 		VirtualFileSystem::File m_root_file; | ||||||
| 
 | 
 | ||||||
| 		BAN::Vector<Thread*> m_threads; | 		BAN::Vector<Thread*> m_threads; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -104,7 +104,7 @@ namespace Kernel::ELF | ||||||
| 		return BAN::move(program_headers); | 		return BAN::move(program_headers); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> inode, const Credentials& credentials, PageTable& page_table) | 	BAN::ErrorOr<LoadResult> load_from_inode(BAN::RefPtr<Inode> root, BAN::RefPtr<Inode> inode, const Credentials& credentials, PageTable& page_table) | ||||||
| 	{ | 	{ | ||||||
| 		auto file_header = TRY(read_and_validate_file_header(inode)); | 		auto file_header = TRY(read_and_validate_file_header(inode)); | ||||||
| 		auto program_headers = TRY(read_program_headers(inode, file_header)); | 		auto program_headers = TRY(read_program_headers(inode, file_header)); | ||||||
|  | @ -143,7 +143,7 @@ namespace Kernel::ELF | ||||||
| 
 | 
 | ||||||
| 		if (!interpreter.empty()) | 		if (!interpreter.empty()) | ||||||
| 		{ | 		{ | ||||||
| 			auto interpreter_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, interpreter, O_EXEC)).inode; | 			auto interpreter_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(root, credentials, interpreter, O_EXEC)).inode; | ||||||
| 			auto interpreter_file_header = TRY(read_and_validate_file_header(interpreter_inode)); | 			auto interpreter_file_header = TRY(read_and_validate_file_header(interpreter_inode)); | ||||||
| 			auto interpreter_program_headers = TRY(read_program_headers(interpreter_inode, interpreter_file_header)); | 			auto interpreter_program_headers = TRY(read_program_headers(interpreter_inode, interpreter_file_header)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -186,7 +186,8 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::StringView block_device_path, BAN::StringView target) | 	BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::StringView block_device_path, BAN::StringView target) | ||||||
| 	{ | 	{ | ||||||
| 		auto block_device_file = TRY(file_from_absolute_path(credentials, block_device_path, true)); | 		// TODO: allow custom root
 | ||||||
|  | 		auto block_device_file = TRY(file_from_absolute_path(root_inode(), credentials, block_device_path, true)); | ||||||
| 		if (!block_device_file.inode->is_device()) | 		if (!block_device_file.inode->is_device()) | ||||||
| 			return BAN::Error::from_errno(ENOTBLK); | 			return BAN::Error::from_errno(ENOTBLK); | ||||||
| 
 | 
 | ||||||
|  | @ -200,7 +201,8 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::RefPtr<FileSystem> file_system, BAN::StringView path) | 	BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::RefPtr<FileSystem> file_system, BAN::StringView path) | ||||||
| 	{ | 	{ | ||||||
| 		auto file = TRY(file_from_absolute_path(credentials, path, true)); | 		// TODO: allow custom root
 | ||||||
|  | 		auto file = TRY(file_from_absolute_path(root_inode(), credentials, path, true)); | ||||||
| 		if (!file.inode->mode().ifdir()) | 		if (!file.inode->mode().ifdir()) | ||||||
| 			return BAN::Error::from_errno(ENOTDIR); | 			return BAN::Error::from_errno(ENOTDIR); | ||||||
| 
 | 
 | ||||||
|  | @ -227,7 +229,7 @@ namespace Kernel | ||||||
| 		return nullptr; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(const File& parent, const Credentials& credentials, BAN::StringView path, int flags) | 	BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials& credentials, BAN::StringView path, int flags) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_mutex); | 		LockGuard _(m_mutex); | ||||||
| 
 | 
 | ||||||
|  | @ -270,13 +272,16 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 			// resolve file name
 | 			// resolve file name
 | ||||||
| 			{ | 			{ | ||||||
| 				auto parent_inode = inode; | 				if (!(inode == root_inode && path_part == ".."_sv)) | ||||||
| 				if (path_part == ".."_sv) | 				{ | ||||||
| 					if (auto* mount_point = mount_from_root_inode(inode)) | 					auto parent_inode = inode; | ||||||
| 						parent_inode = mount_point->host.inode; | 					if (path_part == ".."_sv) | ||||||
| 				if (!parent_inode->can_access(credentials, O_SEARCH)) | 						if (auto* mount_point = mount_from_root_inode(inode)) | ||||||
| 					return BAN::Error::from_errno(EACCES); | 							parent_inode = mount_point->host.inode; | ||||||
| 				inode = TRY(parent_inode->find_inode(path_part)); | 					if (!parent_inode->can_access(credentials, O_SEARCH)) | ||||||
|  | 						return BAN::Error::from_errno(EACCES); | ||||||
|  | 					inode = TRY(parent_inode->find_inode(path_part)); | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
| 				if (path_part == ".."_sv) | 				if (path_part == ".."_sv) | ||||||
| 				{ | 				{ | ||||||
|  | @ -310,7 +315,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 				if (link_target.front() == '/') | 				if (link_target.front() == '/') | ||||||
| 				{ | 				{ | ||||||
| 					inode = root_inode(); | 					inode = root_inode; | ||||||
| 					canonical_path.clear(); | 					canonical_path.clear(); | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
|  |  | ||||||
|  | @ -13,8 +13,16 @@ | ||||||
| namespace Kernel | namespace Kernel | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| 	static BAN::HashMap<BAN::String, BAN::WeakPtr<UnixDomainSocket>>	s_bound_sockets; | 	struct UnixSocketHash | ||||||
| 	static SpinLock														s_bound_socket_lock; | 	{ | ||||||
|  | 		BAN::hash_t operator()(const BAN::RefPtr<Inode>& socket) | ||||||
|  | 		{ | ||||||
|  | 			return BAN::hash<const Inode*>{}(socket.ptr()); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	static BAN::HashMap<BAN::RefPtr<Inode>, BAN::WeakPtr<UnixDomainSocket>, UnixSocketHash> s_bound_sockets; | ||||||
|  | 	static SpinLock s_bound_socket_lock; | ||||||
| 
 | 
 | ||||||
| 	static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE; | 	static constexpr size_t s_packet_buffer_size = 10 * PAGE_SIZE; | ||||||
| 
 | 
 | ||||||
|  | @ -57,9 +65,7 @@ namespace Kernel | ||||||
| 		if (is_bound() && !is_bound_to_unused()) | 		if (is_bound() && !is_bound_to_unused()) | ||||||
| 		{ | 		{ | ||||||
| 			SpinLockGuard _(s_bound_socket_lock); | 			SpinLockGuard _(s_bound_socket_lock); | ||||||
| 			auto it = s_bound_sockets.find(m_bound_path); | 			s_bound_sockets.remove(m_bound_file.inode); | ||||||
| 			if (it != s_bound_sockets.end()) |  | ||||||
| 				s_bound_sockets.remove(it); |  | ||||||
| 		} | 		} | ||||||
| 		if (m_info.has<ConnectionInfo>()) | 		if (m_info.has<ConnectionInfo>()) | ||||||
| 		{ | 		{ | ||||||
|  | @ -117,17 +123,22 @@ namespace Kernel | ||||||
| 			return_inode = reinterpret_cast<UnixDomainSocket*>(return_inode_tmp.ptr()); | 			return_inode = reinterpret_cast<UnixDomainSocket*>(return_inode_tmp.ptr()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		TRY(return_inode->m_bound_path.push_back('X')); | 		TRY(return_inode->m_bound_file.canonical_path.push_back('X')); | ||||||
| 		return_inode->m_info.get<ConnectionInfo>().connection = TRY(pending->get_weak_ptr()); | 		return_inode->m_info.get<ConnectionInfo>().connection = TRY(pending->get_weak_ptr()); | ||||||
| 		pending->m_info.get<ConnectionInfo>().connection = TRY(return_inode->get_weak_ptr()); | 		pending->m_info.get<ConnectionInfo>().connection = TRY(return_inode->get_weak_ptr()); | ||||||
| 		pending->m_info.get<ConnectionInfo>().connection_done = true; | 		pending->m_info.get<ConnectionInfo>().connection_done = true; | ||||||
| 
 | 
 | ||||||
| 		if (address && address_len && !is_bound_to_unused()) | 		if (address && address_len && !is_bound_to_unused()) | ||||||
| 		{ | 		{ | ||||||
| 			size_t copy_len = BAN::Math::min<size_t>(*address_len, sizeof(sockaddr) + m_bound_path.size() + 1); | 			sockaddr_un sa_un { | ||||||
| 			auto& sockaddr_un = *reinterpret_cast<struct sockaddr_un*>(address); | 				.sun_family = AF_UNIX, | ||||||
| 			sockaddr_un.sun_family = AF_UNIX; | 				.sun_path {}, | ||||||
| 			strncpy(sockaddr_un.sun_path, pending->m_bound_path.data(), copy_len); | 			}; | ||||||
|  | 			strcpy(sa_un.sun_path, pending->m_bound_file.canonical_path.data()); | ||||||
|  | 
 | ||||||
|  | 			const size_t to_copy = BAN::Math::min<size_t>(*address_len, sizeof(sockaddr_un)); | ||||||
|  | 			memcpy(address, &sa_un, to_copy); | ||||||
|  | 			*address_len = to_copy; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return TRY(Process::current().open_inode(VirtualFileSystem::File(return_inode, "<unix socket>"_sv), O_RDWR | flags)); | 		return TRY(Process::current().open_inode(VirtualFileSystem::File(return_inode, "<unix socket>"_sv), O_RDWR | flags)); | ||||||
|  | @ -141,10 +152,11 @@ namespace Kernel | ||||||
| 		if (sockaddr_un.sun_family != AF_UNIX) | 		if (sockaddr_un.sun_family != AF_UNIX) | ||||||
| 			return BAN::Error::from_errno(EAFNOSUPPORT); | 			return BAN::Error::from_errno(EAFNOSUPPORT); | ||||||
| 		if (!is_bound()) | 		if (!is_bound()) | ||||||
| 			TRY(m_bound_path.push_back('X')); | 			TRY(m_bound_file.canonical_path.push_back('X')); | ||||||
| 
 | 
 | ||||||
| 		auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path)); | 		auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path)); | ||||||
| 		auto file = TRY(VirtualFileSystem::get().file_from_absolute_path( | 		auto file = TRY(VirtualFileSystem::get().file_from_absolute_path( | ||||||
|  | 			Process::current().root_file().inode, | ||||||
| 			Process::current().credentials(), | 			Process::current().credentials(), | ||||||
| 			absolute_path, | 			absolute_path, | ||||||
| 			O_RDWR | 			O_RDWR | ||||||
|  | @ -154,7 +166,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		{ | 		{ | ||||||
| 			SpinLockGuard _(s_bound_socket_lock); | 			SpinLockGuard _(s_bound_socket_lock); | ||||||
| 			auto it = s_bound_sockets.find(file.canonical_path); | 			auto it = s_bound_sockets.find(file.inode); | ||||||
| 			if (it == s_bound_sockets.end()) | 			if (it == s_bound_sockets.end()) | ||||||
| 				return BAN::Error::from_errno(ECONNREFUSED); | 				return BAN::Error::from_errno(ECONNREFUSED); | ||||||
| 			target = it->value.lock(); | 			target = it->value.lock(); | ||||||
|  | @ -236,7 +248,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		// FIXME: This feels sketchy
 | 		// FIXME: This feels sketchy
 | ||||||
| 		auto parent_file = bind_path.front() == '/' | 		auto parent_file = bind_path.front() == '/' | ||||||
| 			? VirtualFileSystem::get().root_file() | 			? TRY(Process::current().root_file().clone()) | ||||||
| 			: TRY(Process::current().working_directory().clone()); | 			: TRY(Process::current().working_directory().clone()); | ||||||
| 		if (auto ret = Process::current().create_file_or_dir(AT_FDCWD, bind_path.data(), 0755 | S_IFSOCK); ret.is_error()) | 		if (auto ret = Process::current().create_file_or_dir(AT_FDCWD, bind_path.data(), 0755 | S_IFSOCK); ret.is_error()) | ||||||
| 		{ | 		{ | ||||||
|  | @ -245,6 +257,7 @@ namespace Kernel | ||||||
| 			return ret.release_error(); | 			return ret.release_error(); | ||||||
| 		} | 		} | ||||||
| 		auto file = TRY(VirtualFileSystem::get().file_from_relative_path( | 		auto file = TRY(VirtualFileSystem::get().file_from_relative_path( | ||||||
|  | 			Process::current().root_file().inode, | ||||||
| 			parent_file, | 			parent_file, | ||||||
| 			Process::current().credentials(), | 			Process::current().credentials(), | ||||||
| 			bind_path, | 			bind_path, | ||||||
|  | @ -252,10 +265,10 @@ namespace Kernel | ||||||
| 		)); | 		)); | ||||||
| 
 | 
 | ||||||
| 		SpinLockGuard _(s_bound_socket_lock); | 		SpinLockGuard _(s_bound_socket_lock); | ||||||
| 		if (s_bound_sockets.contains(file.canonical_path)) | 		if (s_bound_sockets.contains(file.inode)) | ||||||
| 			return BAN::Error::from_errno(EADDRINUSE); | 			return BAN::Error::from_errno(EADDRINUSE); | ||||||
| 		TRY(s_bound_sockets.emplace(file.canonical_path, TRY(get_weak_ptr()))); | 		TRY(s_bound_sockets.emplace(file.inode, TRY(get_weak_ptr()))); | ||||||
| 		m_bound_path = BAN::move(file.canonical_path); | 		m_bound_file = BAN::move(file); | ||||||
| 
 | 
 | ||||||
| 		return {}; | 		return {}; | ||||||
| 	} | 	} | ||||||
|  | @ -354,14 +367,21 @@ namespace Kernel | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			BAN::String canonical_path; | 			BAN::RefPtr<Inode> target_inode; | ||||||
| 
 | 
 | ||||||
| 			if (!address) | 			if (!address) | ||||||
| 			{ | 			{ | ||||||
| 				auto& connectionless_info = m_info.get<ConnectionlessInfo>(); | 				auto& connectionless_info = m_info.get<ConnectionlessInfo>(); | ||||||
| 				if (connectionless_info.peer_address.empty()) | 				if (connectionless_info.peer_address.empty()) | ||||||
| 					return BAN::Error::from_errno(EDESTADDRREQ); | 					return BAN::Error::from_errno(EDESTADDRREQ); | ||||||
| 				TRY(canonical_path.append(connectionless_info.peer_address)); | 
 | ||||||
|  | 				auto absolute_path = TRY(Process::current().absolute_path_of(connectionless_info.peer_address)); | ||||||
|  | 				target_inode = TRY(VirtualFileSystem::get().file_from_absolute_path( | ||||||
|  | 					Process::current().root_file().inode, | ||||||
|  | 					Process::current().credentials(), | ||||||
|  | 					absolute_path, | ||||||
|  | 					O_RDWR | ||||||
|  | 				)).inode; | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
|  | @ -372,17 +392,16 @@ namespace Kernel | ||||||
| 					return BAN::Error::from_errno(EAFNOSUPPORT); | 					return BAN::Error::from_errno(EAFNOSUPPORT); | ||||||
| 
 | 
 | ||||||
| 				auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path)); | 				auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path)); | ||||||
| 				auto file = TRY(VirtualFileSystem::get().file_from_absolute_path( | 				target_inode = TRY(VirtualFileSystem::get().file_from_absolute_path( | ||||||
|  | 					Process::current().root_file().inode, | ||||||
| 					Process::current().credentials(), | 					Process::current().credentials(), | ||||||
| 					absolute_path, | 					absolute_path, | ||||||
| 					O_WRONLY | 					O_WRONLY | ||||||
| 				)); | 				)).inode; | ||||||
| 
 |  | ||||||
| 				canonical_path = BAN::move(file.canonical_path); |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			SpinLockGuard _(s_bound_socket_lock); | 			SpinLockGuard _(s_bound_socket_lock); | ||||||
| 			auto it = s_bound_sockets.find(canonical_path); | 			auto it = s_bound_sockets.find(target_inode); | ||||||
| 			if (it == s_bound_sockets.end()) | 			if (it == s_bound_sockets.end()) | ||||||
| 				return BAN::Error::from_errno(EDESTADDRREQ); | 				return BAN::Error::from_errno(EDESTADDRREQ); | ||||||
| 			auto target = it->value.lock(); | 			auto target = it->value.lock(); | ||||||
|  | @ -449,20 +468,11 @@ namespace Kernel | ||||||
| 		if (!connection) | 		if (!connection) | ||||||
| 			return BAN::Error::from_errno(ENOTCONN); | 			return BAN::Error::from_errno(ENOTCONN); | ||||||
| 
 | 
 | ||||||
| 		sockaddr_un sa_un; | 		sockaddr_un sa_un { | ||||||
| 		sa_un.sun_family = AF_UNIX; | 			.sun_family = AF_UNIX, | ||||||
| 		sa_un.sun_path[0] = 0; | 			.sun_path = {}, | ||||||
| 
 | 		}; | ||||||
| 		{ | 		strcpy(sa_un.sun_path, connection->m_bound_file.canonical_path.data()); | ||||||
| 			SpinLockGuard _(s_bound_socket_lock); |  | ||||||
| 			for (auto& [path, socket] : s_bound_sockets) |  | ||||||
| 			{ |  | ||||||
| 				if (socket.lock() != connection) |  | ||||||
| 					continue; |  | ||||||
| 				strcpy(sa_un.sun_path, path.data()); |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len); | 		const size_t to_copy = BAN::Math::min<socklen_t>(sizeof(sockaddr_un), *address_len); | ||||||
| 		memcpy(address, &sa_un, to_copy); | 		memcpy(address, &sa_un, to_copy); | ||||||
|  |  | ||||||
|  | @ -77,7 +77,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<int> OpenFileDescriptorSet::open(BAN::StringView absolute_path, int flags) | 	BAN::ErrorOr<int> OpenFileDescriptorSet::open(BAN::StringView absolute_path, int flags) | ||||||
| 	{ | 	{ | ||||||
| 		return open(TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags)), flags); | 		return open(TRY(VirtualFileSystem::get().file_from_absolute_path(Process::current().root_file().inode, m_credentials, absolute_path, flags)), flags); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	struct SocketInfo | 	struct SocketInfo | ||||||
|  |  | ||||||
|  | @ -103,6 +103,8 @@ namespace Kernel | ||||||
| 		auto* process = create_process(credentials, 0); | 		auto* process = create_process(credentials, 0); | ||||||
| 
 | 
 | ||||||
| 		process->m_working_directory = VirtualFileSystem::get().root_file(); | 		process->m_working_directory = VirtualFileSystem::get().root_file(); | ||||||
|  | 		process->m_root_file         = VirtualFileSystem::get().root_file(); | ||||||
|  | 
 | ||||||
| 		process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace())); | 		process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace())); | ||||||
| 
 | 
 | ||||||
| 		TRY(process->m_cmdline.emplace_back()); | 		TRY(process->m_cmdline.emplace_back()); | ||||||
|  | @ -118,7 +120,7 @@ namespace Kernel | ||||||
| 		auto executable_file = TRY(process->find_file(AT_FDCWD, path.data(), O_EXEC)); | 		auto executable_file = TRY(process->find_file(AT_FDCWD, path.data(), O_EXEC)); | ||||||
| 		auto executable_inode = executable_file.inode; | 		auto executable_inode = executable_file.inode; | ||||||
| 
 | 
 | ||||||
| 		auto executable = TRY(ELF::load_from_inode(executable_inode, process->m_credentials, process->page_table())); | 		auto executable = TRY(ELF::load_from_inode(process->m_root_file.inode, executable_inode, process->m_credentials, process->page_table())); | ||||||
| 		process->m_mapped_regions = BAN::move(executable.regions); | 		process->m_mapped_regions = BAN::move(executable.regions); | ||||||
| 
 | 
 | ||||||
| 		if (executable_inode->mode().mode & +Inode::Mode::ISUID) | 		if (executable_inode->mode().mode & +Inode::Mode::ISUID) | ||||||
|  | @ -456,7 +458,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		auto parent_file = TRY(find_relative_parent(fd, path)); | 		auto parent_file = TRY(find_relative_parent(fd, path)); | ||||||
| 		auto file = path | 		auto file = path | ||||||
| 			? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags)) | 			? TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent_file, m_credentials, path, flags)) | ||||||
| 			: BAN::move(parent_file); | 			: BAN::move(parent_file); | ||||||
| 
 | 
 | ||||||
| 		return file; | 		return file; | ||||||
|  | @ -480,7 +482,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		if (auto index = path_sv.rfind('/'); index.has_value()) | 		if (auto index = path_sv.rfind('/'); index.has_value()) | ||||||
| 		{ | 		{ | ||||||
| 			parent = TRY(VirtualFileSystem::get().file_from_relative_path(relative_parent, m_credentials, path_sv.substring(0, index.value()), flags)); | 			parent = TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, relative_parent, m_credentials, path_sv.substring(0, index.value()), flags)); | ||||||
| 			file_name = path_sv.substring(index.value() + 1); | 			file_name = path_sv.substring(index.value() + 1); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
|  | @ -510,7 +512,7 @@ namespace Kernel | ||||||
| 		ASSERT(m_process_lock.is_locked()); | 		ASSERT(m_process_lock.is_locked()); | ||||||
| 
 | 
 | ||||||
| 		if (path && path[0] == '/') | 		if (path && path[0] == '/') | ||||||
| 			return VirtualFileSystem::get().root_file(); | 			return TRY(m_root_file.clone()); | ||||||
| 
 | 
 | ||||||
| 		if (fd == AT_FDCWD) | 		if (fd == AT_FDCWD) | ||||||
| 			return TRY(m_working_directory.clone()); | 			return TRY(m_working_directory.clone()); | ||||||
|  | @ -582,6 +584,7 @@ namespace Kernel | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		auto working_directory = TRY(m_working_directory.clone()); | 		auto working_directory = TRY(m_working_directory.clone()); | ||||||
|  | 		auto root_file         = TRY(m_root_file.clone()); | ||||||
| 
 | 
 | ||||||
| 		BAN::Vector<BAN::String> cmdline; | 		BAN::Vector<BAN::String> cmdline; | ||||||
| 		TRY(cmdline.resize(m_cmdline.size())); | 		TRY(cmdline.resize(m_cmdline.size())); | ||||||
|  | @ -604,6 +607,7 @@ namespace Kernel | ||||||
| 		Process* forked = create_process(m_credentials, m_pid, m_sid, m_pgrp); | 		Process* forked = create_process(m_credentials, m_pid, m_sid, m_pgrp); | ||||||
| 		forked->m_controlling_terminal = m_controlling_terminal; | 		forked->m_controlling_terminal = m_controlling_terminal; | ||||||
| 		forked->m_working_directory = BAN::move(working_directory); | 		forked->m_working_directory = BAN::move(working_directory); | ||||||
|  | 		forked->m_root_file = BAN::move(root_file); | ||||||
| 		forked->m_cmdline = BAN::move(cmdline); | 		forked->m_cmdline = BAN::move(cmdline); | ||||||
| 		forked->m_environ = BAN::move(environ); | 		forked->m_environ = BAN::move(environ); | ||||||
| 		forked->m_page_table = BAN::move(page_table); | 		forked->m_page_table = BAN::move(page_table); | ||||||
|  | @ -656,7 +660,7 @@ namespace Kernel | ||||||
| 			auto executable_file = TRY(find_file(AT_FDCWD, path, O_EXEC)); | 			auto executable_file = TRY(find_file(AT_FDCWD, path, O_EXEC)); | ||||||
| 			auto executable_inode = executable_file.inode; | 			auto executable_inode = executable_file.inode; | ||||||
| 
 | 
 | ||||||
| 			auto executable = TRY(ELF::load_from_inode(executable_inode, m_credentials, *new_page_table)); | 			auto executable = TRY(ELF::load_from_inode(m_root_file.inode, executable_inode, m_credentials, *new_page_table)); | ||||||
| 			auto new_mapped_regions = BAN::move(executable.regions); | 			auto new_mapped_regions = BAN::move(executable.regions); | ||||||
| 
 | 
 | ||||||
| 			BAN::Vector<LibELF::AuxiliaryVector> auxiliary_vector; | 			BAN::Vector<LibELF::AuxiliaryVector> auxiliary_vector; | ||||||
|  | @ -1044,7 +1048,7 @@ namespace Kernel | ||||||
| 		TRY(validate_string_access(path)); | 		TRY(validate_string_access(path)); | ||||||
| 
 | 
 | ||||||
| 		auto [parent, file_name] = TRY(find_parent_file(fd, path, O_RDONLY)); | 		auto [parent, file_name] = TRY(find_parent_file(fd, path, O_RDONLY)); | ||||||
| 		auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, file_name, flags); | 		auto file_or_error = VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent, m_credentials, file_name, flags); | ||||||
| 
 | 
 | ||||||
| 		VirtualFileSystem::File file; | 		VirtualFileSystem::File file; | ||||||
| 		if (file_or_error.is_error()) | 		if (file_or_error.is_error()) | ||||||
|  | @ -1054,7 +1058,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 			// FIXME: There is a race condition between next two lines
 | 			// FIXME: There is a race condition between next two lines
 | ||||||
| 			TRY(parent.inode->create_file(file_name, (mode & 0777) | Inode::Mode::IFREG, m_credentials.euid(), m_credentials.egid())); | 			TRY(parent.inode->create_file(file_name, (mode & 0777) | Inode::Mode::IFREG, m_credentials.euid(), m_credentials.egid())); | ||||||
| 			file = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, file_name, flags & ~O_RDWR)); | 			file = TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, parent, m_credentials, file_name, flags & ~O_RDWR)); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
|  | @ -1135,7 +1139,7 @@ namespace Kernel | ||||||
| 		credentials.set_egid(credentials.rgid()); | 		credentials.set_egid(credentials.rgid()); | ||||||
| 
 | 
 | ||||||
| 		auto relative_parent = TRY(find_relative_parent(AT_FDCWD, path)); | 		auto relative_parent = TRY(find_relative_parent(AT_FDCWD, path)); | ||||||
| 		TRY(VirtualFileSystem::get().file_from_relative_path(relative_parent, credentials, path, flags)); | 		TRY(VirtualFileSystem::get().file_from_relative_path(m_root_file.inode, relative_parent, credentials, path, flags)); | ||||||
| 
 | 
 | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
|  | @ -1258,6 +1262,7 @@ namespace Kernel | ||||||
| 			flag = O_NOFOLLOW; | 			flag = O_NOFOLLOW; | ||||||
| 
 | 
 | ||||||
| 		LockGuard _(m_process_lock); | 		LockGuard _(m_process_lock); | ||||||
|  | 		TRY(validate_string_access(path)); | ||||||
| 
 | 
 | ||||||
| 		auto inode = TRY(find_file(fd, path, flag)).inode; | 		auto inode = TRY(find_file(fd, path, flag)).inode; | ||||||
| 
 | 
 | ||||||
|  | @ -1280,6 +1285,7 @@ namespace Kernel | ||||||
| 			flag = O_NOFOLLOW; | 			flag = O_NOFOLLOW; | ||||||
| 
 | 
 | ||||||
| 		LockGuard _(m_process_lock); | 		LockGuard _(m_process_lock); | ||||||
|  | 		TRY(validate_string_access(path)); | ||||||
| 
 | 
 | ||||||
| 		auto inode = TRY(find_file(fd, path, flag)).inode; | 		auto inode = TRY(find_file(fd, path, flag)).inode; | ||||||
| 
 | 
 | ||||||
|  | @ -2095,22 +2101,25 @@ namespace Kernel | ||||||
| 	BAN::ErrorOr<long> Process::sys_chdir(const char* path) | 	BAN::ErrorOr<long> Process::sys_chdir(const char* path) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_process_lock); | 		LockGuard _(m_process_lock); | ||||||
| 
 |  | ||||||
| 		TRY(validate_string_access(path)); | 		TRY(validate_string_access(path)); | ||||||
| 
 | 		m_working_directory = TRY(find_file(AT_FDCWD, path, O_SEARCH)); | ||||||
| 		auto file = TRY(find_file(AT_FDCWD, path, O_SEARCH)); |  | ||||||
| 		m_working_directory = BAN::move(file); |  | ||||||
| 
 |  | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<long> Process::sys_fchdir(int fildes) | 	BAN::ErrorOr<long> Process::sys_fchdir(int fildes) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_process_lock); | 		LockGuard _(m_process_lock); | ||||||
|  | 		m_working_directory = TRY(m_open_file_descriptors.file_of(fildes)); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 		auto file = TRY(m_open_file_descriptors.file_of(fildes)); | 	BAN::ErrorOr<long> Process::sys_chroot(const char* path) | ||||||
| 		m_working_directory = BAN::move(file); | 	{ | ||||||
| 
 | 		LockGuard _(m_process_lock); | ||||||
|  | 		TRY(validate_string_access(path)); | ||||||
|  | 		if (!m_credentials.is_superuser()) | ||||||
|  | 			return BAN::Error::from_errno(EACCES); | ||||||
|  | 		m_root_file = TRY(find_file(AT_FDCWD, path, O_SEARCH)); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -121,8 +121,8 @@ namespace Kernel | ||||||
| 	void TTY::keyboard_task(void*) | 	void TTY::keyboard_task(void*) | ||||||
| 	{ | 	{ | ||||||
| 		BAN::RefPtr<Inode> keyboard_inode; | 		BAN::RefPtr<Inode> keyboard_inode; | ||||||
| 		if (auto ret = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/keyboard"_sv, O_RDONLY); !ret.is_error()) | 		if (auto ret = DevFileSystem::get().root_inode()->find_inode("keyboard"_sv); !ret.is_error()) | ||||||
| 			keyboard_inode = ret.value().inode; | 			keyboard_inode = ret.release_value(); | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			dprintln("could not open keyboard device: {}", ret.error()); | 			dprintln("could not open keyboard device: {}", ret.error()); | ||||||
|  |  | ||||||
|  | @ -113,6 +113,7 @@ __BEGIN_DECLS | ||||||
| 	O(SYS_FUTEX,			futex)			\ | 	O(SYS_FUTEX,			futex)			\ | ||||||
| 	O(SYS_GETGROUPS,		getgroups)		\ | 	O(SYS_GETGROUPS,		getgroups)		\ | ||||||
| 	O(SYS_SETGROUPS,		setgroups)		\ | 	O(SYS_SETGROUPS,		setgroups)		\ | ||||||
|  | 	O(SYS_CHROOT,			chroot)			\ | ||||||
| 
 | 
 | ||||||
| enum Syscall | enum Syscall | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -596,6 +596,7 @@ int					unlinkat(int fd, const char* path, int flag); | ||||||
| int					usleep(useconds_t usec); | int					usleep(useconds_t usec); | ||||||
| ssize_t				write(int fildes, const void* buf, size_t nbyte); | ssize_t				write(int fildes, const void* buf, size_t nbyte); | ||||||
| 
 | 
 | ||||||
|  | int					chroot(const char* path); | ||||||
| int					getpagesize(void); | int					getpagesize(void); | ||||||
| char*				getpass(const char* prompt); | char*				getpass(const char* prompt); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -626,6 +626,11 @@ int getopt(int argc, char* const argv[], const char* optstring) | ||||||
| 	return '?'; | 	return '?'; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int chroot(const char* path) | ||||||
|  | { | ||||||
|  | 	return syscall(SYS_CHROOT, path); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int getpagesize(void) | int getpagesize(void) | ||||||
| { | { | ||||||
| 	return PAGE_SIZE; | 	return PAGE_SIZE; | ||||||
|  |  | ||||||
|  | @ -31,7 +31,8 @@ namespace LibFont | ||||||
| 
 | 
 | ||||||
| #if __is_kernel | #if __is_kernel | ||||||
| 		{ | 		{ | ||||||
| 			auto inode = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, O_RDONLY)).inode; | 			// FIXME: This does not account for chroot
 | ||||||
|  | 			auto inode = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path(Kernel::VirtualFileSystem::get().root_inode(), { 0, 0, 0, 0 }, path, O_RDONLY)).inode; | ||||||
| 			TRY(file_data.resize(inode->size())); | 			TRY(file_data.resize(inode->size())); | ||||||
| 			TRY(inode->read(0, BAN::ByteSpan(file_data.span()))); | 			TRY(inode->read(0, BAN::ByteSpan(file_data.span()))); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -128,7 +128,8 @@ namespace LibInput | ||||||
| 
 | 
 | ||||||
| #if __is_kernel | #if __is_kernel | ||||||
| 		{ | 		{ | ||||||
| 			auto file = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, 0)); | 			// FIXME: This does not account for chroot
 | ||||||
|  | 			auto file = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path(Kernel::VirtualFileSystem::get().root_inode(), { 0, 0, 0, 0 }, path, 0)); | ||||||
| 			TRY(file_data.resize(file.inode->size())); | 			TRY(file_data.resize(file.inode->size())); | ||||||
| 			TRY(file.inode->read(0, BAN::ByteSpan { reinterpret_cast<uint8_t*>(file_data.data()), file_data.size() })); | 			TRY(file.inode->read(0, BAN::ByteSpan { reinterpret_cast<uint8_t*>(file_data.data()), file_data.size() })); | ||||||
| 			canonical_path = file.canonical_path; | 			canonical_path = file.canonical_path; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue