Kernel/LibC: remove PATH resoltion from kernel

I have no idea why I had made PATH environment variable parsing
to be part of the kernel. Now the shell does the parsing and
environment syscall is no longer needed.
This commit is contained in:
Bananymous 2023-09-23 02:43:02 +03:00
parent 7a7c5e433e
commit 3ba15b41a3
8 changed files with 73 additions and 71 deletions

View File

@ -71,8 +71,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_sleep(int seconds);
BAN::ErrorOr<long> sys_nanosleep(const timespec* rqtp, timespec* rmtp);
BAN::ErrorOr<long> sys_setenvp(char** envp);
BAN::ErrorOr<long> sys_setpwd(const char* path);
BAN::ErrorOr<long> sys_getpwd(char* buffer, size_t size);
@ -147,7 +145,7 @@ namespace Kernel
static void register_process(Process*);
// Load an elf file to virtual address space of the current page table
static BAN::ErrorOr<BAN::UniqPtr<LibELF::ELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd, const BAN::Vector<BAN::StringView>& path_env);
static BAN::ErrorOr<BAN::UniqPtr<LibELF::ELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd);
// Copy an elf file from the current page table to the processes own
void load_elf_to_memory(LibELF::ELF&);

View File

@ -99,7 +99,7 @@ namespace Kernel
BAN::ErrorOr<Process*> Process::create_userspace(const Credentials& credentials, BAN::StringView path)
{
auto elf = TRY(load_elf_for_exec(credentials, path, "/"sv, {}));
auto elf = TRY(load_elf_for_exec(credentials, path, "/"sv));
auto* process = create_process(credentials, 0);
MUST(process->m_working_directory.push_back('/'));
@ -114,7 +114,6 @@ namespace Kernel
elf.clear();
char** argv = nullptr;
char** envp = nullptr;
{
PageTableScope _(process->page_table());
@ -123,18 +122,11 @@ namespace Kernel
memcpy(argv[0], path.data(), path.size());
argv[0][path.size()] = '\0';
argv[1] = nullptr;
BAN::StringView env1 = "PATH=/bin:/usr/bin"sv;
envp = (char**)MUST(process->sys_alloc(sizeof(char**) * 2));
envp[0] = (char*)MUST(process->sys_alloc(env1.size() + 1));
memcpy(envp[0], env1.data(), env1.size());
envp[0][env1.size()] = '\0';
envp[1] = nullptr;
}
process->m_userspace_info.argc = 1;
process->m_userspace_info.argv = argv;
process->m_userspace_info.envp = envp;
process->m_userspace_info.envp = nullptr;
auto* thread = MUST(Thread::create_userspace(process));
process->add_thread(thread);
@ -275,7 +267,7 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<BAN::UniqPtr<LibELF::ELF>> Process::load_elf_for_exec(const Credentials& credentials, BAN::StringView file_path, const BAN::String& cwd, const BAN::Vector<BAN::StringView>& path_env)
BAN::ErrorOr<BAN::UniqPtr<LibELF::ELF>> Process::load_elf_for_exec(const Credentials& credentials, BAN::StringView file_path, const BAN::String& cwd)
{
if (file_path.empty())
return BAN::Error::from_errno(ENOENT);
@ -283,44 +275,13 @@ namespace Kernel
BAN::String absolute_path;
if (file_path.front() == '/')
{
// We have an absolute path
TRY(absolute_path.append(file_path));
}
else if (file_path.front() == '.' || file_path.contains('/'))
else
{
// We have a relative path
TRY(absolute_path.append(cwd));
TRY(absolute_path.push_back('/'));
TRY(absolute_path.append(file_path));
}
else
{
// We have neither relative or absolute path,
// search from PATH environment
for (auto path_part : path_env)
{
if (path_part.empty())
continue;
if (path_part.front() != '/')
{
TRY(absolute_path.append(cwd));
TRY(absolute_path.push_back('/'));
}
TRY(absolute_path.append(path_part));
TRY(absolute_path.push_back('/'));
TRY(absolute_path.append(file_path));
if (!VirtualFileSystem::get().file_from_absolute_path(credentials, absolute_path, O_EXEC).is_error())
break;
absolute_path.clear();
}
if (absolute_path.empty())
return BAN::Error::from_errno(ENOENT);
}
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, absolute_path, O_EXEC));
@ -412,14 +373,9 @@ namespace Kernel
for (int i = 0; argv && argv[i]; i++)
TRY(str_argv.emplace_back(argv[i]));
BAN::Vector<BAN::StringView> path_env;
BAN::Vector<BAN::String> str_envp;
for (int i = 0; envp && envp[i]; i++)
{
TRY(str_envp.emplace_back(envp[i]));
if (strncmp(envp[i], "PATH=", 5) == 0)
path_env = TRY(BAN::StringView(envp[i]).substring(5).split(':'));
}
BAN::String working_directory;
@ -428,7 +384,7 @@ namespace Kernel
TRY(working_directory.append(m_working_directory));
}
auto elf = TRY(load_elf_for_exec(m_credentials, path, working_directory, path_env));
auto elf = TRY(load_elf_for_exec(m_credentials, path, working_directory));
LockGuard lock_guard(m_lock);
@ -547,13 +503,6 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_setenvp(char** envp)
{
LockGuard _(m_lock);
m_userspace_info.envp = envp;
return 0;
}
void Process::load_elf_to_memory(LibELF::ELF& elf)
{
ASSERT(elf.is_native());

View File

@ -97,9 +97,6 @@ namespace Kernel
case SYS_FSTAT:
ret = Process::current().sys_fstat((int)arg1, (struct stat*)arg2);
break;
case SYS_SETENVP:
ret = Process::current().sys_setenvp((char**)arg1);
break;
case SYS_READ_DIR_ENTRIES:
ret = Process::current().sys_read_dir_entries((int)arg1, (API::DirectoryEntryList*)arg2, (size_t)arg3);
break;

View File

@ -21,7 +21,6 @@ __BEGIN_DECLS
#define SYS_SLEEP 17
#define SYS_WAIT 18
#define SYS_FSTAT 19
#define SYS_SETENVP 20
#define SYS_READ_DIR_ENTRIES 21
#define SYS_SET_UID 22
#define SYS_SET_GID 23

View File

@ -124,6 +124,16 @@ int putenv(char* string)
return -1;
}
if (!environ)
{
environ = (char**)malloc(sizeof(char*) * 2);
if (!environ)
return -1;
environ[0] = string;
environ[1] = nullptr;
return 0;
}
int cnt = 0;
for (int i = 0; string[i]; i++)
if (string[i] == '=')
@ -151,10 +161,7 @@ int putenv(char* string)
char** new_envp = (char**)malloc(sizeof(char*) * (env_count + 2));
if (new_envp == nullptr)
{
errno = ENOMEM;
return -1;
}
for (int i = 0; i < env_count; i++)
new_envp[i] = environ[i];
@ -164,8 +171,6 @@ int putenv(char* string)
free(environ);
environ = new_envp;
if (syscall(SYS_SETENVP, environ) == -1)
return -1;
return 0;
}

View File

@ -14,8 +14,23 @@ char** environ;
extern void init_malloc();
extern "C" void _init_libc(char** _environ)
{
environ = _environ;
init_malloc();
if (!_environ)
return;
size_t env_count = 0;
while (_environ[env_count])
env_count++;
environ = (char**)malloc(sizeof(char*) * env_count + 1);
for (size_t i = 0; i < env_count; i++)
{
size_t bytes = strlen(_environ[i]) + 1;
environ[i] = (char*)malloc(bytes);
memcpy(environ[i], _environ[i], bytes);
}
environ[env_count] = nullptr;
}
void _exit(int status)

View File

@ -437,6 +437,40 @@ pid_t execute_command_no_wait(BAN::Vector<BAN::String>& args, int fd_in, int fd_
MUST(cmd_args.push_back((char*)arg.data()));
MUST(cmd_args.push_back(nullptr));
// do PATH resolution
BAN::String executable_file;
if (!args.front().empty() && args.front().front() != '.' && args.front().front() != '/')
{
char* path_env_cstr = getenv("PATH");
if (path_env_cstr)
{
auto path_env_list = MUST(BAN::StringView(path_env_cstr).split(':'));
for (auto path_env : path_env_list)
{
BAN::String test_file = path_env;
MUST(test_file.push_back('/'));
MUST(test_file.append(args.front()));
struct stat st;
if (stat(test_file.data(), &st) == 0)
{
executable_file = BAN::move(test_file);
break;
}
}
if (executable_file.empty())
{
fprintf(stderr, "command not found: %s\n", args.front().data());
return -1;
}
}
}
else
{
executable_file = args.front();
}
pid_t pid = fork();
if (pid == 0)
{
@ -477,11 +511,14 @@ pid_t execute_command_no_wait(BAN::Vector<BAN::String>& args, int fd_in, int fd_
setpgid(0, pgrp);
}
execv(cmd_args.front(), cmd_args.data());
execv(executable_file.data(), cmd_args.data());
perror("execv");
exit(1);
}
if (pid == -1)
ERROR_RETURN("fork", -1);
return pid;
}
@ -489,7 +526,7 @@ int execute_command(BAN::Vector<BAN::String>& args, int fd_in, int fd_out)
{
pid_t pid = execute_command_no_wait(args, fd_in, fd_out, 0);
if (pid == -1)
ERROR_RETURN("fork", 1);
return 1;
int status;
if (waitpid(pid, &status, 0) == -1)

View File

@ -74,6 +74,8 @@ int main()
if (setuid(pwd->pw_uid) == -1)
perror("setuid");
setenv("PATH", "/bin:/usr/bin", 0);
setenv("HOME", pwd->pw_dir, 1);
chdir(pwd->pw_dir);