Compare commits
6 Commits
208fdd64ac
...
3867a29a10
Author | SHA1 | Date | |
---|---|---|---|
3867a29a10 | |||
46ee0eb937 | |||
059c2bfa3f | |||
0f8a46ab67 | |||
3da1849c99 | |||
f6f9254eb4 |
@ -3,23 +3,18 @@ function(luna_app SOURCE_FILE APP_NAME)
|
||||
target_compile_options(${APP_NAME} PRIVATE -Os ${COMMON_FLAGS} -Wno-write-strings)
|
||||
add_dependencies(${APP_NAME} libc)
|
||||
target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include)
|
||||
target_link_libraries(${APP_NAME} PRIVATE os)
|
||||
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)
|
||||
endfunction()
|
||||
|
||||
luna_app(init.cpp init)
|
||||
luna_app(env.cpp env)
|
||||
|
||||
luna_app(su.cpp su)
|
||||
luna_app(sh.cpp sh)
|
||||
target_link_libraries(sh PRIVATE os)
|
||||
|
||||
luna_app(cat.cpp cat)
|
||||
target_link_libraries(cat PRIVATE os)
|
||||
|
||||
luna_app(date.cpp date)
|
||||
target_link_libraries(date PRIVATE os)
|
||||
|
||||
luna_app(edit.cpp edit)
|
||||
target_link_libraries(edit PRIVATE os)
|
||||
|
||||
luna_app(ls.cpp ls)
|
||||
target_link_libraries(ls PRIVATE os)
|
||||
luna_app(chown.cpp chown)
|
||||
luna_app(chmod.cpp chmod)
|
||||
luna_app(mkdir.cpp mkdir)
|
||||
|
23
apps/chmod.cpp
Normal file
23
apps/chmod.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include <os/ArgumentParser.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
StringView mode_string;
|
||||
StringView path;
|
||||
|
||||
os::ArgumentParser parser;
|
||||
parser.add_positional_argument(mode_string, "mode"_sv, true);
|
||||
parser.add_positional_argument(path, "path"_sv, true);
|
||||
parser.parse(argc, argv);
|
||||
|
||||
mode_t mode = (mode_t)strtoul(mode_string.chars(), NULL, 8);
|
||||
|
||||
if (chmod(path.chars(), mode) < 0)
|
||||
{
|
||||
perror("chmod");
|
||||
return 1;
|
||||
}
|
||||
}
|
23
apps/chown.cpp
Normal file
23
apps/chown.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include <os/ArgumentParser.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
StringView user;
|
||||
StringView path;
|
||||
|
||||
os::ArgumentParser parser;
|
||||
parser.add_positional_argument(user, "user"_sv, true);
|
||||
parser.add_positional_argument(path, "path"_sv, true);
|
||||
parser.parse(argc, argv);
|
||||
|
||||
u32 id = (u32)strtoul(user.chars(), NULL, 0);
|
||||
|
||||
if (chown(path.chars(), id, id) < 0)
|
||||
{
|
||||
perror("chown");
|
||||
return 1;
|
||||
}
|
||||
}
|
23
apps/mkdir.cpp
Normal file
23
apps/mkdir.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include <os/ArgumentParser.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
StringView path;
|
||||
StringView mode_string;
|
||||
|
||||
os::ArgumentParser parser;
|
||||
parser.add_positional_argument(path, "path"_sv, true);
|
||||
parser.add_positional_argument(mode_string, "mode"_sv, "755"_sv);
|
||||
parser.parse(argc, argv);
|
||||
|
||||
mode_t mode = (mode_t)strtoul(mode_string.chars(), NULL, 8);
|
||||
|
||||
if (mkdir(path.chars(), mode) < 0)
|
||||
{
|
||||
perror("mkdir");
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -74,7 +74,7 @@ int main(int argc, char** argv)
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (file == "-") fputs("sh$ ", stdout);
|
||||
if (file == "-") fputs(getuid() == 0 ? "sh# " : "sh$ ", stdout);
|
||||
|
||||
char cmd[4096];
|
||||
char* rc = fgets(cmd, sizeof(cmd), f);
|
||||
|
32
apps/su.cpp
Normal file
32
apps/su.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include <os/ArgumentParser.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
StringView id;
|
||||
|
||||
if (geteuid() != 0)
|
||||
{
|
||||
fprintf(stderr, "su must be run as root!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
os::ArgumentParser parser;
|
||||
parser.add_positional_argument(id, "id"_sv, true);
|
||||
parser.parse(argc, argv);
|
||||
|
||||
int uid = atoi(id.chars());
|
||||
|
||||
if (uid == 0)
|
||||
{
|
||||
fprintf(stderr, "Already root!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
setgid(uid);
|
||||
setuid(uid);
|
||||
|
||||
execl("/bin/sh", "sh", NULL);
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
#include "boot/bootboot.h"
|
||||
#include "fs/VFS.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include "thread/Thread.h"
|
||||
#include <bits/modes.h>
|
||||
#include <luna/Alignment.h>
|
||||
|
||||
@ -19,7 +20,7 @@ void InitRD::initialize()
|
||||
|
||||
static Result<void> vfs_create_dir_if_not_exists(const char* path, mode_t mode)
|
||||
{
|
||||
auto rc = VFS::create_directory(path);
|
||||
auto rc = VFS::create_directory(path, Credentials {});
|
||||
if (rc.has_error())
|
||||
{
|
||||
if (rc.error() == EEXIST) return {};
|
||||
@ -36,7 +37,7 @@ Result<void> InitRD::populate_vfs()
|
||||
{
|
||||
if (entry.type == TarStream::EntryType::RegularFile)
|
||||
{
|
||||
auto file = TRY(VFS::create_file(entry.name));
|
||||
auto file = TRY(VFS::create_file(entry.name, Credentials {}));
|
||||
file->write(entry.data(), 0, entry.size);
|
||||
file->chmod(entry.mode & (mode_t)~S_IFMT);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "fs/VFS.h"
|
||||
#include "Log.h"
|
||||
#include "thread/Thread.h"
|
||||
#include <bits/modes.h>
|
||||
#include <luna/PathParser.h>
|
||||
|
||||
namespace VFS
|
||||
@ -11,7 +13,7 @@ namespace VFS
|
||||
return *root_fs->root_inode();
|
||||
}
|
||||
|
||||
Result<SharedPtr<Inode>> resolve_path(const char* path)
|
||||
Result<SharedPtr<Inode>> resolve_path(const char* path, Credentials auth)
|
||||
{
|
||||
auto parser = TRY(PathParser::create(path));
|
||||
|
||||
@ -20,17 +22,23 @@ namespace VFS
|
||||
// FIXME: Properly handle relative paths.
|
||||
|
||||
const char* section;
|
||||
while (parser.next().try_set_value(section)) { current_inode = TRY(current_inode->find(section)); }
|
||||
while (parser.next().try_set_value(section))
|
||||
{
|
||||
if (!can_execute(current_inode, auth)) return err(EACCES);
|
||||
current_inode = TRY(current_inode->find(section));
|
||||
}
|
||||
|
||||
return current_inode;
|
||||
}
|
||||
|
||||
Result<SharedPtr<Inode>> create_directory(const char* path)
|
||||
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth)
|
||||
{
|
||||
auto parser = TRY(PathParser::create(path));
|
||||
auto parent_path = TRY(parser.dirname());
|
||||
|
||||
auto parent_inode = TRY(resolve_path(parent_path.chars()));
|
||||
auto parent_inode = TRY(resolve_path(parent_path.chars(), auth));
|
||||
|
||||
if (!can_write(parent_inode, auth)) return err(EACCES);
|
||||
|
||||
auto child_name = TRY(parser.basename());
|
||||
|
||||
@ -39,12 +47,14 @@ namespace VFS
|
||||
return parent_inode->create_subdirectory(child_name.chars());
|
||||
}
|
||||
|
||||
Result<SharedPtr<Inode>> create_file(const char* path)
|
||||
Result<SharedPtr<Inode>> create_file(const char* path, Credentials auth)
|
||||
{
|
||||
auto parser = TRY(PathParser::create(path));
|
||||
auto parent_path = TRY(parser.dirname());
|
||||
|
||||
auto parent_inode = TRY(resolve_path(parent_path.chars()));
|
||||
auto parent_inode = TRY(resolve_path(parent_path.chars(), auth));
|
||||
|
||||
if (!can_write(parent_inode, auth)) return err(EACCES);
|
||||
|
||||
auto child_name = TRY(parser.basename());
|
||||
|
||||
@ -52,4 +62,28 @@ namespace VFS
|
||||
|
||||
return parent_inode->create_file(child_name.chars());
|
||||
}
|
||||
|
||||
bool can_execute(SharedPtr<Inode> inode, Credentials auth)
|
||||
{
|
||||
if (inode->uid() == auth.euid) { return inode->mode() & S_IXUSR; }
|
||||
if (inode->gid() == auth.egid) { return inode->mode() & S_IXGRP; }
|
||||
|
||||
return inode->mode() & S_IXOTH;
|
||||
}
|
||||
|
||||
bool can_write(SharedPtr<Inode> inode, Credentials auth)
|
||||
{
|
||||
if (inode->uid() == auth.euid) { return inode->mode() & S_IWUSR; }
|
||||
if (inode->gid() == auth.egid) { return inode->mode() & S_IWGRP; }
|
||||
|
||||
return inode->mode() & S_IWOTH;
|
||||
}
|
||||
|
||||
bool can_read(SharedPtr<Inode> inode, Credentials auth)
|
||||
{
|
||||
if (inode->uid() == auth.euid) { return inode->mode() & S_IRUSR; }
|
||||
if (inode->gid() == auth.egid) { return inode->mode() & S_IRGRP; }
|
||||
|
||||
return inode->mode() & S_IROTH;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <luna/StaticString.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct Credentials;
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
enum class InodeType
|
||||
@ -46,13 +48,25 @@ namespace VFS
|
||||
virtual bool blocking() const = 0;
|
||||
|
||||
// Metadata accessors
|
||||
virtual usize size() = 0;
|
||||
virtual usize size() const = 0;
|
||||
|
||||
virtual mode_t mode() = 0;
|
||||
virtual mode_t mode() const = 0;
|
||||
|
||||
virtual u32 uid() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual u32 gid() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Metadata changers
|
||||
virtual Result<void> chmod(mode_t mode) = 0;
|
||||
|
||||
virtual Result<void> chown(u32 uid, u32 gid) = 0;
|
||||
|
||||
// Generic VFS-related methods
|
||||
virtual FileSystem& fs() const = 0;
|
||||
|
||||
@ -156,10 +170,14 @@ namespace VFS
|
||||
|
||||
extern SharedPtr<FileSystem> root_fs;
|
||||
|
||||
Result<SharedPtr<Inode>> resolve_path(const char* path);
|
||||
Result<SharedPtr<Inode>> resolve_path(const char* path, Credentials auth);
|
||||
|
||||
Result<SharedPtr<Inode>> create_directory(const char* path);
|
||||
Result<SharedPtr<Inode>> create_file(const char* path);
|
||||
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth);
|
||||
Result<SharedPtr<Inode>> create_file(const char* path, Credentials auth);
|
||||
|
||||
bool can_execute(SharedPtr<Inode> inode, Credentials auth);
|
||||
bool can_read(SharedPtr<Inode> inode, Credentials auth);
|
||||
bool can_write(SharedPtr<Inode> inode, Credentials auth);
|
||||
|
||||
Inode& root_inode();
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ namespace TmpFS
|
||||
return {};
|
||||
}
|
||||
|
||||
usize FileInode::size()
|
||||
usize FileInode::size() const
|
||||
{
|
||||
return m_data_buffer.size();
|
||||
}
|
||||
|
@ -66,19 +66,36 @@ namespace TmpFS
|
||||
|
||||
Result<void> truncate(usize size) override;
|
||||
|
||||
usize size() override;
|
||||
usize size() const override;
|
||||
|
||||
mode_t mode() override
|
||||
mode_t mode() const override
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
u32 uid() const override
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
|
||||
u32 gid() const override
|
||||
{
|
||||
return m_gid;
|
||||
}
|
||||
|
||||
Result<void> chmod(mode_t mode) override
|
||||
{
|
||||
m_mode = mode;
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void> chown(u32 uid, u32 gid) override
|
||||
{
|
||||
m_uid = uid;
|
||||
m_gid = gid;
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual ~FileInode() = default;
|
||||
|
||||
private:
|
||||
@ -86,6 +103,8 @@ namespace TmpFS
|
||||
Buffer m_data_buffer;
|
||||
usize m_inode_number;
|
||||
mode_t m_mode;
|
||||
u32 m_uid { 0 };
|
||||
u32 m_gid { 0 };
|
||||
};
|
||||
|
||||
class DeviceInode : public VFS::DeviceInode
|
||||
@ -139,22 +158,39 @@ namespace TmpFS
|
||||
return m_device->blocking();
|
||||
}
|
||||
|
||||
usize size() override
|
||||
usize size() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
mode_t mode() override
|
||||
mode_t mode() const override
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
u32 uid() const override
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
|
||||
u32 gid() const override
|
||||
{
|
||||
return m_gid;
|
||||
}
|
||||
|
||||
Result<void> chmod(mode_t mode) override
|
||||
{
|
||||
m_mode = mode;
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void> chown(u32 uid, u32 gid) override
|
||||
{
|
||||
m_uid = uid;
|
||||
m_gid = gid;
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual ~DeviceInode() = default;
|
||||
|
||||
private:
|
||||
@ -162,6 +198,8 @@ namespace TmpFS
|
||||
SharedPtr<Device> m_device;
|
||||
usize m_inode_number;
|
||||
mode_t m_mode;
|
||||
u32 m_uid { 0 };
|
||||
u32 m_gid { 0 };
|
||||
};
|
||||
|
||||
class DirInode : public VFS::Inode
|
||||
@ -207,22 +245,39 @@ namespace TmpFS
|
||||
return false;
|
||||
}
|
||||
|
||||
usize size() override
|
||||
usize size() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
mode_t mode() override
|
||||
mode_t mode() const override
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
u32 uid() const override
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
|
||||
u32 gid() const override
|
||||
{
|
||||
return m_gid;
|
||||
}
|
||||
|
||||
Result<void> chmod(mode_t mode) override
|
||||
{
|
||||
m_mode = mode;
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void> chown(u32 uid, u32 gid) override
|
||||
{
|
||||
m_uid = uid;
|
||||
m_gid = gid;
|
||||
return {};
|
||||
}
|
||||
|
||||
VFS::FileSystem& fs() const override
|
||||
{
|
||||
return *m_fs;
|
||||
@ -249,6 +304,8 @@ namespace TmpFS
|
||||
VFS::FileSystem* m_fs;
|
||||
usize m_inode_number;
|
||||
mode_t m_mode;
|
||||
u32 m_uid { 0 };
|
||||
u32 m_gid { 0 };
|
||||
|
||||
SharedPtr<VFS::Inode> m_self;
|
||||
|
||||
|
@ -54,7 +54,7 @@ Result<void> init()
|
||||
TRY(DeviceRegistry::init());
|
||||
InitRD::populate_vfs();
|
||||
|
||||
auto init = TRY(VFS::resolve_path("/bin/init"));
|
||||
auto init = TRY(VFS::resolve_path("/bin/init", Credentials {}));
|
||||
TRY(Scheduler::new_userspace_thread(init, "/bin/init"));
|
||||
|
||||
Scheduler::new_kernel_thread(reap_thread, "[reap]").release_value();
|
||||
|
@ -37,17 +37,16 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
|
||||
auto argv = TRY(copy_string_vector_from_userspace(args[1]));
|
||||
auto envp = TRY(copy_string_vector_from_userspace(args[2]));
|
||||
|
||||
auto current = Scheduler::current();
|
||||
|
||||
// FIXME: Make sure argv & envp are not too big.
|
||||
|
||||
auto inode = TRY(VFS::resolve_path(path.chars()));
|
||||
auto inode = TRY(VFS::resolve_path(path.chars(), current->auth));
|
||||
|
||||
// Not executable
|
||||
if ((inode->mode() & S_IXUSR) != S_IXUSR) return err(EACCES);
|
||||
if (!VFS::can_execute(inode, current->auth)) return err(EACCES);
|
||||
|
||||
kinfoln("exec: attempting to replace current image with %s", path.chars());
|
||||
|
||||
auto current = Scheduler::current();
|
||||
|
||||
auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->directory); });
|
||||
|
||||
auto image = TRY(ThreadImage::try_load_from_elf(inode));
|
||||
@ -111,6 +110,7 @@ Result<u64> sys_fork(Registers* regs, SyscallArgs)
|
||||
thread->parent_id = current->id;
|
||||
thread->fp_data.save();
|
||||
thread->name = current->name;
|
||||
thread->auth = current->auth;
|
||||
|
||||
for (int i = 0; i < FD_MAX; i++) { thread->fd_table[i] = current->fd_table[i]; }
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "memory/MemoryManager.h"
|
||||
#include "sys/Syscall.h"
|
||||
#include "thread/Scheduler.h"
|
||||
|
||||
@ -10,3 +11,116 @@ Result<u64> sys_getppid(Registers*, SyscallArgs)
|
||||
{
|
||||
return Scheduler::current()->parent_id;
|
||||
}
|
||||
|
||||
Result<u64> sys_getuid(Registers*, SyscallArgs)
|
||||
{
|
||||
return Scheduler::current()->auth.uid;
|
||||
}
|
||||
|
||||
Result<u64> sys_geteuid(Registers*, SyscallArgs)
|
||||
{
|
||||
return Scheduler::current()->auth.euid;
|
||||
}
|
||||
|
||||
Result<u64> sys_getgid(Registers*, SyscallArgs)
|
||||
{
|
||||
return Scheduler::current()->auth.gid;
|
||||
}
|
||||
|
||||
Result<u64> sys_getegid(Registers*, SyscallArgs)
|
||||
{
|
||||
return Scheduler::current()->auth.egid;
|
||||
}
|
||||
|
||||
Result<u64> sys_setuid(Registers*, SyscallArgs args)
|
||||
{
|
||||
u32 uid = (u32)args[0];
|
||||
|
||||
Credentials& auth = Scheduler::current()->auth;
|
||||
|
||||
if (auth.euid == 0)
|
||||
{
|
||||
auth.uid = auth.euid = auth.suid = uid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uid != auth.uid && uid != auth.suid) return err(EPERM);
|
||||
auth.euid = uid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result<u64> sys_seteuid(Registers*, SyscallArgs args)
|
||||
{
|
||||
u32 uid = (u32)args[0];
|
||||
|
||||
Credentials& auth = Scheduler::current()->auth;
|
||||
|
||||
if (auth.euid != 0 && uid != auth.uid && uid != auth.suid) return err(EPERM);
|
||||
auth.euid = uid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result<u64> sys_setgid(Registers*, SyscallArgs args)
|
||||
{
|
||||
u32 gid = (u32)args[0];
|
||||
|
||||
Credentials& auth = Scheduler::current()->auth;
|
||||
|
||||
if (auth.euid == 0)
|
||||
{
|
||||
auth.gid = auth.egid = auth.sgid = gid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gid != auth.gid && gid != auth.sgid) return err(EPERM);
|
||||
auth.egid = gid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result<u64> sys_setegid(Registers*, SyscallArgs args)
|
||||
{
|
||||
u32 gid = (u32)args[0];
|
||||
|
||||
Credentials& auth = Scheduler::current()->auth;
|
||||
|
||||
if (auth.euid != 0 && gid != auth.gid && gid != auth.sgid) return err(EPERM);
|
||||
auth.egid = gid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result<u64> sys_chmod(Registers*, SyscallArgs args)
|
||||
{
|
||||
auto path = TRY(MemoryManager::strdup_from_user(args[0]));
|
||||
mode_t mode = (mode_t)args[1];
|
||||
|
||||
Credentials& auth = Scheduler::current()->auth;
|
||||
|
||||
auto inode = TRY(VFS::resolve_path(path.chars(), auth));
|
||||
|
||||
if (auth.euid != 0 && auth.euid != inode->uid()) return err(EPERM);
|
||||
|
||||
TRY(inode->chmod(mode));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result<u64> sys_chown(Registers*, SyscallArgs args)
|
||||
{
|
||||
auto path = TRY(MemoryManager::strdup_from_user(args[0]));
|
||||
u32 uid = (u32)args[1];
|
||||
u32 gid = (u32)args[2];
|
||||
|
||||
Credentials& auth = Scheduler::current()->auth;
|
||||
|
||||
auto inode = TRY(VFS::resolve_path(path.chars(), auth));
|
||||
|
||||
if (auth.euid != 0) return err(EPERM);
|
||||
|
||||
TRY(inode->chown(uid == (u32)-1 ? inode->uid() : uid, gid == (u32)-1 ? inode->gid() : gid));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,16 +2,20 @@
|
||||
#include "fs/VFS.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include "sys/Syscall.h"
|
||||
#include "thread/Scheduler.h"
|
||||
|
||||
Result<u64> sys_mkdir(Registers*, SyscallArgs args)
|
||||
{
|
||||
auto path = TRY(MemoryManager::strdup_from_user(args[0]));
|
||||
mode_t mode = (mode_t)args[1];
|
||||
|
||||
Thread* current = Scheduler::current();
|
||||
|
||||
kinfoln("mkdir: attempting to create %s", path.chars());
|
||||
|
||||
auto inode = TRY(VFS::create_directory(path.chars()));
|
||||
auto inode = TRY(VFS::create_directory(path.chars(), current->auth));
|
||||
inode->chmod(mode);
|
||||
inode->chown(current->auth.euid, current->auth.egid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ Result<u64> sys_mknod(Registers*, SyscallArgs args)
|
||||
mode_t mode = (mode_t)args[1];
|
||||
dev_t dev = (dev_t)args[2];
|
||||
|
||||
Thread* current = Scheduler::current();
|
||||
|
||||
u32 maj = luna_dev_major(dev);
|
||||
u32 min = luna_dev_minor(dev);
|
||||
|
||||
@ -22,7 +24,8 @@ Result<u64> sys_mknod(Registers*, SyscallArgs args)
|
||||
auto dirname = TRY(parser.dirname());
|
||||
auto basename = TRY(parser.basename());
|
||||
|
||||
auto parent = TRY(VFS::resolve_path(dirname.chars()));
|
||||
auto parent = TRY(VFS::resolve_path(dirname.chars(), current->auth));
|
||||
if (!VFS::can_write(parent, current->auth)) return err(EACCES);
|
||||
|
||||
auto inode = TRY(parent->fs().create_device_inode(maj, min));
|
||||
TRY(parent->add_entry(inode, basename.chars()));
|
||||
|
@ -25,13 +25,14 @@ Result<u64> sys_open(Registers*, SyscallArgs args)
|
||||
if ((flags & O_RDWR) == 0) { return err(EINVAL); }
|
||||
|
||||
int error;
|
||||
bool ok = VFS::resolve_path(path.chars()).try_set_value_or_error(inode, error);
|
||||
bool ok = VFS::resolve_path(path.chars(), current->auth).try_set_value_or_error(inode, error);
|
||||
if (!ok)
|
||||
{
|
||||
if (error == ENOENT && (flags & O_CREAT))
|
||||
{
|
||||
inode = TRY(VFS::create_file(path.chars()));
|
||||
inode = TRY(VFS::create_file(path.chars(), current->auth));
|
||||
inode->chmod(mode);
|
||||
inode->chown(current->auth.euid, current->auth.egid);
|
||||
}
|
||||
else
|
||||
return err(error);
|
||||
@ -40,8 +41,8 @@ Result<u64> sys_open(Registers*, SyscallArgs args)
|
||||
return err(EEXIST);
|
||||
else
|
||||
{
|
||||
if ((flags & O_RDONLY) && (inode->mode() & S_IRUSR) == 0) return err(EACCES);
|
||||
if ((flags & O_WRONLY) && (inode->mode() & S_IWUSR) == 0) return err(EACCES);
|
||||
if ((flags & O_RDONLY) && !VFS::can_read(inode, current->auth)) return err(EACCES);
|
||||
if ((flags & O_WRONLY) && !VFS::can_write(inode, current->auth)) return err(EACCES);
|
||||
}
|
||||
|
||||
if (inode->type() != VFS::InodeType::Directory && (flags & O_DIRECTORY)) return err(ENOTDIR);
|
||||
|
@ -72,6 +72,8 @@ namespace Scheduler
|
||||
|
||||
thread->is_kernel = true;
|
||||
|
||||
thread->auth = Credentials { .uid = 0, .euid = 0, .suid = 0, .gid = 0, .egid = 0, .sgid = 0 };
|
||||
|
||||
g_threads.append(thread);
|
||||
|
||||
kinfoln("Created kernel thread: id %lu with ip %#lx and sp %#lx", thread->id, thread->ip(), thread->sp());
|
||||
@ -114,6 +116,7 @@ namespace Scheduler
|
||||
thread->is_kernel = false;
|
||||
thread->name = name;
|
||||
thread->parent_id = 0;
|
||||
thread->auth = Credentials { .uid = 0, .euid = 0, .suid = 0, .gid = 0, .egid = 0, .sgid = 0 };
|
||||
|
||||
Vector<String> args;
|
||||
auto name_string = TRY(String::from_cstring(name));
|
||||
|
@ -38,6 +38,16 @@ struct FileDescriptor
|
||||
|
||||
static constexpr int FD_MAX = 64;
|
||||
|
||||
struct Credentials
|
||||
{
|
||||
u32 uid { 0 };
|
||||
u32 euid { 0 };
|
||||
u32 suid { 0 };
|
||||
u32 gid { 0 };
|
||||
u32 egid { 0 };
|
||||
u32 sgid { 0 };
|
||||
};
|
||||
|
||||
struct Thread : public LinkedListNode<Thread>
|
||||
{
|
||||
Registers regs;
|
||||
@ -45,6 +55,8 @@ struct Thread : public LinkedListNode<Thread>
|
||||
u64 id;
|
||||
u64 parent_id;
|
||||
|
||||
Credentials auth;
|
||||
|
||||
u64 ticks = 0;
|
||||
u64 ticks_in_user = 0;
|
||||
u64 ticks_in_kernel = 0;
|
||||
|
@ -16,6 +16,8 @@ typedef __u64_t useconds_t;
|
||||
typedef __i64_t off_t;
|
||||
typedef __u64_t dev_t;
|
||||
typedef __u64_t ino_t;
|
||||
typedef __u32_t uid_t;
|
||||
typedef __u32_t gid_t;
|
||||
|
||||
typedef off_t fpos_t;
|
||||
|
||||
|
@ -28,6 +28,36 @@ extern "C"
|
||||
/* Return the current process' parent process ID. */
|
||||
pid_t getppid(void);
|
||||
|
||||
/* Return the current process' real user ID. */
|
||||
uid_t getuid(void);
|
||||
|
||||
/* Return the current process' effective user ID. */
|
||||
uid_t geteuid(void);
|
||||
|
||||
/* Return the current process' real group ID. */
|
||||
gid_t getgid(void);
|
||||
|
||||
/* Return the current process' effective group ID. */
|
||||
gid_t getegid(void);
|
||||
|
||||
/* Set the current process' user IDs. */
|
||||
int setuid(uid_t uid);
|
||||
|
||||
/* Set the current process' effective user ID. */
|
||||
int seteuid(uid_t uid);
|
||||
|
||||
/* Set the current process' group IDs. */
|
||||
int setgid(gid_t gid);
|
||||
|
||||
/* Set the current process' effective group ID. */
|
||||
int setegid(gid_t gid);
|
||||
|
||||
/* Change the mode bits of a file. */
|
||||
int chmod(const char* path, mode_t mode);
|
||||
|
||||
/* Change the owner and group of a file. */
|
||||
int chown(const char* path, uid_t uid, gid_t gid);
|
||||
|
||||
/* Replace the current process with another one. On success, does not return. */
|
||||
int execv(const char* path, char* const* argv);
|
||||
|
||||
|
@ -31,6 +31,62 @@ extern "C"
|
||||
return (pid_t)syscall(SYS_getppid);
|
||||
}
|
||||
|
||||
uid_t getuid(void)
|
||||
{
|
||||
return (uid_t)syscall(SYS_getuid);
|
||||
}
|
||||
|
||||
uid_t geteuid(void)
|
||||
{
|
||||
return (uid_t)syscall(SYS_geteuid);
|
||||
}
|
||||
|
||||
gid_t getgid(void)
|
||||
{
|
||||
return (gid_t)syscall(SYS_getgid);
|
||||
}
|
||||
|
||||
gid_t getegid(void)
|
||||
{
|
||||
return (gid_t)syscall(SYS_getegid);
|
||||
}
|
||||
|
||||
int setuid(uid_t uid)
|
||||
{
|
||||
long rc = syscall(SYS_setuid, uid);
|
||||
__errno_return(rc, int);
|
||||
}
|
||||
|
||||
int seteuid(uid_t uid)
|
||||
{
|
||||
long rc = syscall(SYS_seteuid, uid);
|
||||
__errno_return(rc, int);
|
||||
}
|
||||
|
||||
int setgid(gid_t gid)
|
||||
{
|
||||
long rc = syscall(SYS_setgid, gid);
|
||||
__errno_return(rc, int);
|
||||
}
|
||||
|
||||
int setegid(gid_t gid)
|
||||
{
|
||||
long rc = syscall(SYS_setegid, gid);
|
||||
__errno_return(rc, int);
|
||||
}
|
||||
|
||||
int chmod(const char* path, mode_t mode)
|
||||
{
|
||||
long rc = syscall(SYS_chmod, path, mode);
|
||||
__errno_return(rc, int);
|
||||
}
|
||||
|
||||
int chown(const char* path, uid_t uid, gid_t gid)
|
||||
{
|
||||
long rc = syscall(SYS_chown, path, uid, gid);
|
||||
__errno_return(rc, int);
|
||||
}
|
||||
|
||||
int execv(const char* path, char* const* argv)
|
||||
{
|
||||
return execve(path, argv, environ);
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
#define enumerate_syscalls(_e) \
|
||||
_e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \
|
||||
_e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents)
|
||||
_e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) \
|
||||
_e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(chmod) _e(chown)
|
||||
|
||||
enum Syscalls
|
||||
{
|
||||
|
@ -65,13 +65,11 @@ template <typename T> class Vector
|
||||
|
||||
~Vector()
|
||||
{
|
||||
if (m_data) {
|
||||
for(const T& item : *this)
|
||||
{
|
||||
item.~T();
|
||||
}
|
||||
if (m_data)
|
||||
{
|
||||
for (const T& item : *this) { item.~T(); }
|
||||
free_impl(m_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Result<void> try_reserve(usize capacity)
|
||||
@ -115,10 +113,10 @@ template <typename T> class Vector
|
||||
|
||||
T item = move(m_data[0]);
|
||||
|
||||
memmove(m_data, m_data + 1, m_size - 1);
|
||||
|
||||
m_size--;
|
||||
|
||||
memmove(m_data, m_data + 1, m_size * sizeof(T));
|
||||
|
||||
return move(item);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user