kernel: Add binary format for shebang scripts
This commit is contained in:
parent
1c76675e40
commit
3638d3da46
@ -1,4 +1,4 @@
|
|||||||
Name=mount-home
|
Name=mount-home
|
||||||
Description=Mount the user's home directory on a writable filesystem.
|
Description=Mount the user's home directory on a writable filesystem.
|
||||||
Script=/etc/startup/mount-home.sh
|
Command=/etc/startup/mount-home.sh
|
||||||
Wait=true
|
Wait=true
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
mount -t tmpfs tmpfs /home/selene
|
mount -t tmpfs tmpfs /home/selene
|
||||||
chown selene:selene /home/selene
|
chown selene:selene /home/selene
|
||||||
|
@ -62,6 +62,7 @@ set(SOURCES
|
|||||||
src/fs/InitRD.cpp
|
src/fs/InitRD.cpp
|
||||||
src/binfmt/ELF.cpp
|
src/binfmt/ELF.cpp
|
||||||
src/binfmt/BinaryFormat.cpp
|
src/binfmt/BinaryFormat.cpp
|
||||||
|
src/binfmt/Script.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if("${LUNA_ARCH}" MATCHES "x86_64")
|
if("${LUNA_ARCH}" MATCHES "x86_64")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "binfmt/BinaryFormat.h"
|
#include "binfmt/BinaryFormat.h"
|
||||||
#include "binfmt/ELF.h"
|
#include "binfmt/ELF.h"
|
||||||
|
#include "binfmt/Script.h"
|
||||||
|
|
||||||
struct BinaryFormatDescriptor
|
struct BinaryFormatDescriptor
|
||||||
{
|
{
|
||||||
@ -12,6 +13,7 @@ Vector<BinaryFormatDescriptor> g_binary_formats;
|
|||||||
Result<void> BinaryFormat::init()
|
Result<void> BinaryFormat::init()
|
||||||
{
|
{
|
||||||
TRY(register_binary_format(ELFLoader::create, nullptr));
|
TRY(register_binary_format(ELFLoader::create, nullptr));
|
||||||
|
TRY(register_binary_format(ScriptLoader::create, nullptr));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ class BinaryFormatLoader : public Shareable
|
|||||||
|
|
||||||
virtual StringView format() const = 0;
|
virtual StringView format() const = 0;
|
||||||
|
|
||||||
virtual Result<Vector<String>> cmdline(const String& path, Vector<String> args) = 0;
|
virtual Result<Vector<String>> cmdline(Vector<String> args) = 0;
|
||||||
|
|
||||||
virtual ~BinaryFormatLoader() = default;
|
virtual ~BinaryFormatLoader() = default;
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ Result<u64> ELFLoader::load(AddressSpace* space)
|
|||||||
return elf_header.e_entry;
|
return elf_header.e_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Vector<String>> ELFLoader::cmdline(const String&, Vector<String> args)
|
Result<Vector<String>> ELFLoader::cmdline(Vector<String> args)
|
||||||
{
|
{
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ class ELFLoader : public BinaryFormatLoader
|
|||||||
Result<bool> sniff() override;
|
Result<bool> sniff() override;
|
||||||
Result<u64> load(AddressSpace* space) override;
|
Result<u64> load(AddressSpace* space) override;
|
||||||
|
|
||||||
Result<Vector<String>> cmdline(const String& path, Vector<String> args) override;
|
Result<Vector<String>> cmdline(Vector<String> args) override;
|
||||||
|
|
||||||
StringView format() const override
|
StringView format() const override
|
||||||
{
|
{
|
||||||
|
61
kernel/src/binfmt/Script.cpp
Normal file
61
kernel/src/binfmt/Script.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "binfmt/Script.h"
|
||||||
|
#include "binfmt/ELF.h"
|
||||||
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
|
#define SHEBANG "#!"
|
||||||
|
|
||||||
|
Result<bool> ScriptLoader::sniff()
|
||||||
|
{
|
||||||
|
u8 buf[2];
|
||||||
|
usize nread = TRY(m_inode->read(buf, 0, sizeof buf));
|
||||||
|
if (nread < 2) return false;
|
||||||
|
|
||||||
|
return !memcmp(buf, SHEBANG, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<u64> ScriptLoader::load(AddressSpace* space)
|
||||||
|
{
|
||||||
|
u8 buf[256];
|
||||||
|
usize nread = TRY(m_inode->read(buf, 2, 255));
|
||||||
|
if (!nread) return err(ENOEXEC);
|
||||||
|
for (usize i = 0; i < nread; i++)
|
||||||
|
{
|
||||||
|
if (buf[i] == '\n') buf[i] = '\0';
|
||||||
|
else if (buf[i] == '\r' && (i + 1) < nread && buf[i + 1] == '\n')
|
||||||
|
buf[i] = buf[i + 1] = '\0';
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto view = StringView { (const char*)buf };
|
||||||
|
m_interpreter_cmdline = TRY(view.split(" "));
|
||||||
|
if (!m_interpreter_cmdline.size()) return err(ENOEXEC);
|
||||||
|
|
||||||
|
auto& interpreter_path = m_interpreter_cmdline[0];
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
|
auto interpreter =
|
||||||
|
TRY(VFS::resolve_path(interpreter_path.chars(), current->auth, current->current_directory, true));
|
||||||
|
if (!VFS::can_execute(interpreter, current->auth)) return err(EACCES);
|
||||||
|
|
||||||
|
auto loader = TRY(ELFLoader::create(interpreter, nullptr));
|
||||||
|
return loader->load(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Vector<String>> ScriptLoader::cmdline(Vector<String> args)
|
||||||
|
{
|
||||||
|
Vector<String> new_args;
|
||||||
|
for (auto& arg : m_interpreter_cmdline) { TRY(new_args.try_append(move(arg))); }
|
||||||
|
for (auto& arg : args) { TRY(new_args.try_append(move(arg))); }
|
||||||
|
return new_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptLoader::ScriptLoader(SharedPtr<VFS::Inode> inode) : BinaryFormatLoader(inode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<BinaryFormatLoader>> ScriptLoader::create(SharedPtr<VFS::Inode> inode, void*)
|
||||||
|
{
|
||||||
|
return (SharedPtr<BinaryFormatLoader>)TRY(make_shared<ScriptLoader>(inode));
|
||||||
|
}
|
25
kernel/src/binfmt/Script.h
Normal file
25
kernel/src/binfmt/Script.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "binfmt/BinaryFormat.h"
|
||||||
|
#include "fs/VFS.h"
|
||||||
|
#include "memory/AddressSpace.h"
|
||||||
|
|
||||||
|
class ScriptLoader : public BinaryFormatLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Result<bool> sniff() override;
|
||||||
|
Result<u64> load(AddressSpace* space) override;
|
||||||
|
|
||||||
|
Result<Vector<String>> cmdline(Vector<String> args) override;
|
||||||
|
|
||||||
|
StringView format() const override
|
||||||
|
{
|
||||||
|
return "script";
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptLoader(SharedPtr<VFS::Inode> inode);
|
||||||
|
|
||||||
|
static Result<SharedPtr<BinaryFormatLoader>> create(SharedPtr<VFS::Inode> inode, void*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<String> m_interpreter_cmdline;
|
||||||
|
};
|
@ -80,7 +80,7 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
|
|||||||
|
|
||||||
auto image = TRY(ThreadImage::try_load_from_binary(loader));
|
auto image = TRY(ThreadImage::try_load_from_binary(loader));
|
||||||
|
|
||||||
argv = TRY(loader->cmdline(move(path), move(argv)));
|
argv = TRY(loader->cmdline(move(argv)));
|
||||||
|
|
||||||
u64 user_argv = TRY(image->push_string_vector_on_stack(argv));
|
u64 user_argv = TRY(image->push_string_vector_on_stack(argv));
|
||||||
usize user_argc = argv.size();
|
usize user_argc = argv.size();
|
||||||
|
Loading…
Reference in New Issue
Block a user