Compare commits
55 Commits
9c0fab2e88
...
d896101268
Author | SHA1 | Date | |
---|---|---|---|
d896101268 | |||
ea25d823e5 | |||
b278ae2dbc | |||
41bf27e510 | |||
935aecb96f | |||
3025eadc86 | |||
4bc1530425 | |||
40b0f8c6ec | |||
47c358555d | |||
a411bb6594 | |||
2a06a12721 | |||
cf6fd6ea29 | |||
0c2e9551ca | |||
9fd5d0b874 | |||
f8a5f24352 | |||
dbf014b351 | |||
0a630af250 | |||
dbf9a6bad8 | |||
c3af9091b5 | |||
9fa426eadf | |||
7ddac3c36b | |||
9aad63474b | |||
fdc362d19c | |||
6407ec76e0 | |||
8e36d25e8a | |||
a4b6e988b6 | |||
442a188630 | |||
871d8cce52 | |||
6b32af81f7 | |||
dfe1697ae6 | |||
ad0e8bad4a | |||
987ebe3ef1 | |||
dd9f8afd5b | |||
4b277b38f0 | |||
b4ae8bfaa1 | |||
ba3e32917e | |||
cfb60fad25 | |||
9954fc1658 | |||
a98df9e743 | |||
e2a77bb3da | |||
0ae409ae22 | |||
181b4c151b | |||
0c64b6e040 | |||
fb3c31907d | |||
52064e0317 | |||
ec3c1132d2 | |||
5ea73197ad | |||
5a1adcb2a6 | |||
c4f6191e24 | |||
39e4fbd112 | |||
32fd6889b9 | |||
c6a5a81a7a | |||
3f55a70f6e | |||
b1e164f360 | |||
ed8b210639 |
105
apps/init.cpp
105
apps/init.cpp
@ -4,9 +4,12 @@
|
|||||||
#include <luna/Sort.h>
|
#include <luna/Sort.h>
|
||||||
#include <luna/String.h>
|
#include <luna/String.h>
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
|
#include <os/ArgumentParser.h>
|
||||||
#include <os/Directory.h>
|
#include <os/Directory.h>
|
||||||
#include <os/File.h>
|
#include <os/File.h>
|
||||||
#include <os/Process.h>
|
#include <os/Process.h>
|
||||||
|
#include <os/Security.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -17,6 +20,8 @@
|
|||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static bool g_is_system = false;
|
||||||
|
|
||||||
FILE* g_init_log = nullptr;
|
FILE* g_init_log = nullptr;
|
||||||
|
|
||||||
// Request a successful exit from the system (for tests)
|
// Request a successful exit from the system (for tests)
|
||||||
@ -40,6 +45,8 @@ struct Service
|
|||||||
String standard_output;
|
String standard_output;
|
||||||
String standard_error;
|
String standard_error;
|
||||||
String standard_input;
|
String standard_input;
|
||||||
|
Option<uid_t> user {};
|
||||||
|
Option<gid_t> group {};
|
||||||
bool wait { false };
|
bool wait { false };
|
||||||
Option<pid_t> pid {};
|
Option<pid_t> pid {};
|
||||||
};
|
};
|
||||||
@ -65,6 +72,12 @@ static Result<void> service_child(const Service& service, SharedPtr<os::File> ou
|
|||||||
if (error) dup2(error->fd(), STDERR_FILENO);
|
if (error) dup2(error->fd(), STDERR_FILENO);
|
||||||
if (input) dup2(input->fd(), STDIN_FILENO);
|
if (input) dup2(input->fd(), STDIN_FILENO);
|
||||||
|
|
||||||
|
if (service.user.has_value())
|
||||||
|
{
|
||||||
|
setgid(service.group.value());
|
||||||
|
setuid(service.user.value());
|
||||||
|
}
|
||||||
|
|
||||||
if (service.environment.is_empty()) { TRY(os::Process::exec(args[0].view(), args.slice(), false)); }
|
if (service.environment.is_empty()) { TRY(os::Process::exec(args[0].view(), args.slice(), false)); }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -214,6 +227,15 @@ static Result<void> load_service(const os::Path& path)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_is_system && parts[0].view() == "User")
|
||||||
|
{
|
||||||
|
auto* pw = getpwnam(parts[1].chars());
|
||||||
|
if (!pw) continue;
|
||||||
|
service.user = pw->pw_uid;
|
||||||
|
service.group = pw->pw_gid;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (parts[0].view() == "Wait")
|
if (parts[0].view() == "Wait")
|
||||||
{
|
{
|
||||||
if (parts[1].view() == "true" || parts[1].view().to_uint().value_or(0) == 1)
|
if (parts[1].view() == "true" || parts[1].view().to_uint().value_or(0) == 1)
|
||||||
@ -247,9 +269,9 @@ static Result<void> load_service(const os::Path& path)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result<void> load_services()
|
static Result<void> load_services(StringView path)
|
||||||
{
|
{
|
||||||
auto dir = TRY(os::Directory::open("/etc/init"));
|
auto dir = TRY(os::Directory::open(path));
|
||||||
|
|
||||||
auto services = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
|
auto services = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
|
||||||
sort(services.begin(), services.end(), String::compare);
|
sort(services.begin(), services.end(), String::compare);
|
||||||
@ -259,9 +281,9 @@ static Result<void> load_services()
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result<void> start_services()
|
static Result<void> start_services(StringView path)
|
||||||
{
|
{
|
||||||
TRY(load_services());
|
TRY(load_services(path));
|
||||||
for (auto& service : g_services)
|
for (auto& service : g_services)
|
||||||
{
|
{
|
||||||
do_log("[init] starting service %s\n", service.name.chars());
|
do_log("[init] starting service %s\n", service.name.chars());
|
||||||
@ -301,7 +323,7 @@ static void mount_shmfs()
|
|||||||
if (chmod("/dev/shm", 01777) < 0) exit(255);
|
if (chmod("/dev/shm", 01777) < 0) exit(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
Result<int> sysinit()
|
||||||
{
|
{
|
||||||
if (getpid() != 1)
|
if (getpid() != 1)
|
||||||
{
|
{
|
||||||
@ -309,12 +331,16 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_is_system = true;
|
||||||
|
|
||||||
// Before this point, we don't even have an stdin, stdout and stderr. Set it up now so that child processes (and us)
|
// Before this point, we don't even have an stdin, stdout and stderr. Set it up now so that child processes (and us)
|
||||||
// can print stuff.
|
// can print stuff.
|
||||||
stdin = fopen("/dev/console", "r");
|
stdin = fopen("/dev/console", "r");
|
||||||
stdout = fopen("/dev/console", "w");
|
stdout = fopen("/dev/console", "w");
|
||||||
stderr = fopen("/dev/console", "w");
|
stderr = fopen("/dev/console", "w");
|
||||||
|
|
||||||
|
TRY(os::Security::pledge("stdio rpath wpath cpath fattr host mount proc exec signal", nullptr));
|
||||||
|
|
||||||
mount_tmpfs();
|
mount_tmpfs();
|
||||||
mount_shmfs();
|
mount_shmfs();
|
||||||
|
|
||||||
@ -330,7 +356,11 @@ int main()
|
|||||||
if (signal(SIGTERM, sigterm_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGTERM\n");
|
if (signal(SIGTERM, sigterm_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGTERM\n");
|
||||||
if (signal(SIGQUIT, sigquit_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGQUIT\n");
|
if (signal(SIGQUIT, sigquit_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGQUIT\n");
|
||||||
|
|
||||||
start_services();
|
TRY(os::Security::pledge("stdio rpath wpath cpath proc exec", nullptr));
|
||||||
|
|
||||||
|
start_services("/etc/init");
|
||||||
|
|
||||||
|
TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr));
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -365,3 +395,66 @@ int main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<int> user_init()
|
||||||
|
{
|
||||||
|
setpgid(0, 0);
|
||||||
|
|
||||||
|
g_init_log = fopen("/dev/uart0", "w");
|
||||||
|
check(g_init_log);
|
||||||
|
setlinebuf(g_init_log);
|
||||||
|
fcntl(fileno(g_init_log), F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
TRY(os::Security::pledge("stdio rpath wpath cpath proc exec", nullptr));
|
||||||
|
|
||||||
|
start_services("/etc/user");
|
||||||
|
|
||||||
|
TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr));
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
auto rc = os::Process::wait(os::Process::ANY_CHILD, &status);
|
||||||
|
if (rc.has_error()) continue;
|
||||||
|
|
||||||
|
pid_t child = rc.release_value();
|
||||||
|
|
||||||
|
for (auto& service : g_services)
|
||||||
|
{
|
||||||
|
if (service.pid.has_value() && service.pid.value() == child)
|
||||||
|
{
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
{
|
||||||
|
do_log("[init] service %s exited with status %d\n", service.name.chars(), WEXITSTATUS(status));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do_log("[init] service %s was terminated by signal %d\n", service.name.chars(), WTERMSIG(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service.restart)
|
||||||
|
{
|
||||||
|
do_log("[init] restarting service %s\n", service.name.chars());
|
||||||
|
|
||||||
|
start_service(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<int> luna_main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
bool user;
|
||||||
|
|
||||||
|
os::ArgumentParser parser;
|
||||||
|
parser.add_description("The init system for Luna.");
|
||||||
|
parser.add_system_program_info("init"_sv);
|
||||||
|
parser.add_switch_argument(user, 'u', "user"_sv, "initialize a user session instead of the system");
|
||||||
|
parser.parse(argc, argv);
|
||||||
|
|
||||||
|
if (user) return user_init();
|
||||||
|
return sysinit();
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
pledge("stdio rpath wpath cpath proc", nullptr);
|
||||||
|
|
||||||
int fd = shm_open("/shared", O_CREAT | O_RDWR, 0666);
|
int fd = shm_open("/shared", O_CREAT | O_RDWR, 0666);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,7 @@ set(SOURCES
|
|||||||
${HEADERS}
|
${HEADERS}
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/Log.cpp
|
src/Log.cpp
|
||||||
|
src/Pledge.cpp
|
||||||
src/cxxabi.cpp
|
src/cxxabi.cpp
|
||||||
src/video/Framebuffer.cpp
|
src/video/Framebuffer.cpp
|
||||||
src/video/TextConsole.cpp
|
src/video/TextConsole.cpp
|
||||||
@ -44,6 +45,8 @@ set(SOURCES
|
|||||||
src/sys/signal.cpp
|
src/sys/signal.cpp
|
||||||
src/sys/socket.cpp
|
src/sys/socket.cpp
|
||||||
src/sys/poll.cpp
|
src/sys/poll.cpp
|
||||||
|
src/sys/alarm.cpp
|
||||||
|
src/sys/pledge.cpp
|
||||||
src/fs/VFS.cpp
|
src/fs/VFS.cpp
|
||||||
src/fs/Pipe.cpp
|
src/fs/Pipe.cpp
|
||||||
src/fs/Mount.cpp
|
src/fs/Mount.cpp
|
||||||
|
@ -27,8 +27,8 @@ static void log_serial(LogLevel level, const char* format, va_list origin)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
va_copy(ap, origin);
|
va_copy(ap, origin);
|
||||||
|
|
||||||
const SafeScopeLock lock { g_serial_lock };
|
/*const SafeScopeLock lock { g_serial_lock };
|
||||||
if (!lock.did_succeed()) return;
|
if (!lock.did_succeed()) return;*/
|
||||||
|
|
||||||
Serial::printf("\x1b[%sm"
|
Serial::printf("\x1b[%sm"
|
||||||
"%c"
|
"%c"
|
||||||
@ -61,7 +61,7 @@ static void log_text_console(LogLevel level, const char* format, va_list origin)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
va_copy(ap, origin);
|
va_copy(ap, origin);
|
||||||
|
|
||||||
const ScopeLock lock { g_console_lock };
|
/*const ScopeLock lock { g_console_lock };*/
|
||||||
|
|
||||||
const u32 original_foreground = TextConsole::foreground();
|
const u32 original_foreground = TextConsole::foreground();
|
||||||
const u32 original_background = TextConsole::background();
|
const u32 original_background = TextConsole::background();
|
||||||
|
66
kernel/src/Pledge.cpp
Normal file
66
kernel/src/Pledge.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "memory/MemoryManager.h"
|
||||||
|
|
||||||
|
static const char* promise_names[] = {
|
||||||
|
#define __enumerate(promise) #promise,
|
||||||
|
enumerate_promises(__enumerate)
|
||||||
|
#undef __enumerate
|
||||||
|
};
|
||||||
|
|
||||||
|
Result<void> check_pledge(Thread* thread, Promise promise)
|
||||||
|
{
|
||||||
|
// Thread has not called pledge().
|
||||||
|
if (thread->promises < 0) return {};
|
||||||
|
int mask = (1 << (int)promise);
|
||||||
|
if ((thread->promises & mask) != mask)
|
||||||
|
{
|
||||||
|
kerrorln("Pledge violation in thread %d! Has not pledged %s", thread->id, promise_names[(int)promise]);
|
||||||
|
if (thread->promises & (1 << (int)Promise::p_error)) return err(ENOSYS);
|
||||||
|
|
||||||
|
// Kill this thread with an uncatchable SIGABRT. For this, we reset the disposition of SIGABRT to the default
|
||||||
|
// (dump core). We could just kill the thread here and be done, but that discards anything on the current stack,
|
||||||
|
// which means that some destructors might not be called. Instead, leave the job to the next call of
|
||||||
|
// Thread::process_pending_signals().
|
||||||
|
thread->signal_handlers[SIGABRT - 1].sa_handler = SIG_DFL;
|
||||||
|
|
||||||
|
// If there are any other pending signals, they might be processed before SIGABRT. Avoid that by resetting the
|
||||||
|
// thread's pending signals.
|
||||||
|
thread->pending_signals = 0;
|
||||||
|
|
||||||
|
thread->send_signal(SIGABRT);
|
||||||
|
|
||||||
|
// This should never arrive to userspace.
|
||||||
|
return err(ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<int> parse_promises(u64 pledge)
|
||||||
|
{
|
||||||
|
if (!pledge) return -1;
|
||||||
|
|
||||||
|
auto text = TRY(MemoryManager::strdup_from_user(pledge));
|
||||||
|
if (text.is_empty()) return 0;
|
||||||
|
|
||||||
|
auto promises = TRY(text.split(" "));
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
for (const auto& promise : promises)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (int)Promise::num_promises; i++)
|
||||||
|
{
|
||||||
|
if (promise.view() == promise_names[i])
|
||||||
|
{
|
||||||
|
result |= (1 << i);
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err(EINVAL);
|
||||||
|
found:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
19
kernel/src/Pledge.h
Normal file
19
kernel/src/Pledge.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "thread/Thread.h"
|
||||||
|
#include <luna/Result.h>
|
||||||
|
|
||||||
|
#define enumerate_promises(_p) \
|
||||||
|
_p(stdio) _p(rpath) _p(wpath) _p(cpath) _p(fattr) _p(chown) _p(unix) _p(tty) _p(proc) _p(exec) _p(prot_exec) \
|
||||||
|
_p(id) _p(mount) _p(signal) _p(host) _p(error)
|
||||||
|
|
||||||
|
enum class Promise
|
||||||
|
{
|
||||||
|
#define __enumerate(promise) p_##promise,
|
||||||
|
enumerate_promises(__enumerate)
|
||||||
|
#undef __enumerate
|
||||||
|
num_promises,
|
||||||
|
};
|
||||||
|
|
||||||
|
Result<void> check_pledge(Thread* thread, Promise promise);
|
||||||
|
|
||||||
|
Result<int> parse_promises(u64 pledge);
|
@ -431,6 +431,18 @@ namespace ATA
|
|||||||
m_uses_dma = false;
|
m_uses_dma = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_drive_index == 0 && !(status & BMS_MasterInit))
|
||||||
|
{
|
||||||
|
kwarnln("ata: Drive %d does not have DMA support", m_drive_index);
|
||||||
|
m_uses_dma = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_drive_index == 1 && !(status & BMS_SlaveInit))
|
||||||
|
{
|
||||||
|
kwarnln("ata: Drive %d does not have DMA support", m_drive_index);
|
||||||
|
m_uses_dma = false;
|
||||||
|
}
|
||||||
|
|
||||||
auto frame = MemoryManager::alloc_frame();
|
auto frame = MemoryManager::alloc_frame();
|
||||||
if (frame.has_error() || frame.value() > 0xffffffff)
|
if (frame.has_error() || frame.value() > 0xffffffff)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "fs/devices/ConsoleDevice.h"
|
#include "fs/devices/ConsoleDevice.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "fs/devices/DeviceRegistry.h"
|
#include "fs/devices/DeviceRegistry.h"
|
||||||
#include "fs/devices/KeyboardDevice.h"
|
#include "fs/devices/KeyboardDevice.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
@ -199,6 +200,9 @@ void ConsoleDevice::process_key_event(u8 scancode)
|
|||||||
|
|
||||||
Result<u64> ConsoleDevice::ioctl(int request, void* arg)
|
Result<u64> ConsoleDevice::ioctl(int request, void* arg)
|
||||||
{
|
{
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_tty));
|
||||||
|
|
||||||
switch (request)
|
switch (request)
|
||||||
{
|
{
|
||||||
case TCGETS: {
|
case TCGETS: {
|
||||||
|
18
kernel/src/sys/alarm.cpp
Normal file
18
kernel/src/sys/alarm.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
|
#include "sys/Syscall.h"
|
||||||
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
|
Result<u64> sys_alarm(Registers*, SyscallArgs args)
|
||||||
|
{
|
||||||
|
unsigned int seconds = (unsigned int)args[0];
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
|
u64 time_left = current->alarm_ticks_left;
|
||||||
|
|
||||||
|
current->alarm_ticks_left = seconds * 1000;
|
||||||
|
|
||||||
|
return time_left * 1000;
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -9,6 +10,8 @@ Result<u64> sys_chdir(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_rpath));
|
||||||
|
|
||||||
if (PathParser::is_absolute(path.view()))
|
if (PathParser::is_absolute(path.view()))
|
||||||
{
|
{
|
||||||
SharedPtr<VFS::Inode> inode = TRY(VFS::resolve_path(path.chars(), current->auth));
|
SharedPtr<VFS::Inode> inode = TRY(VFS::resolve_path(path.chars(), current->auth));
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "arch/Timer.h"
|
#include "arch/Timer.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
|
#include "thread/Scheduler.h"
|
||||||
#include <bits/clockid.h>
|
#include <bits/clockid.h>
|
||||||
#include <bits/timespec.h>
|
#include <bits/timespec.h>
|
||||||
|
|
||||||
@ -9,6 +11,10 @@ Result<u64> sys_clock_gettime(Registers*, SyscallArgs args)
|
|||||||
clockid_t id = (clockid_t)args[0];
|
clockid_t id = (clockid_t)args[0];
|
||||||
struct timespec* ts = (struct timespec*)args[1];
|
struct timespec* ts = (struct timespec*)args[1];
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case CLOCK_MONOTONIC: {
|
case CLOCK_MONOTONIC: {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "binfmt/BinaryFormat.h"
|
#include "binfmt/BinaryFormat.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
@ -63,6 +64,8 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
|
|||||||
|
|
||||||
auto current = Scheduler::current();
|
auto current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_exec));
|
||||||
|
|
||||||
auto inode = TRY(VFS::resolve_path(path.chars(), current->auth, current->current_directory));
|
auto inode = TRY(VFS::resolve_path(path.chars(), current->auth, current->current_directory));
|
||||||
|
|
||||||
if (!VFS::can_execute(inode, current->auth)) return err(EACCES);
|
if (!VFS::can_execute(inode, current->auth)) return err(EACCES);
|
||||||
@ -71,6 +74,11 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
|
|||||||
kdbgln("exec: attempting to replace current image with %s", path.chars());
|
kdbgln("exec: attempting to replace current image with %s", path.chars());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool is_setuid = VFS::is_setuid(inode);
|
||||||
|
bool is_setgid = VFS::is_setgid(inode);
|
||||||
|
bool is_secure_environment = is_setgid || is_setuid;
|
||||||
|
if (is_secure_environment && current->execpromises >= 0) return err(EACCES);
|
||||||
|
|
||||||
auto loader = TRY(BinaryFormat::create_loader(inode));
|
auto loader = TRY(BinaryFormat::create_loader(inode));
|
||||||
|
|
||||||
#ifdef EXEC_DEBUG
|
#ifdef EXEC_DEBUG
|
||||||
@ -104,8 +112,8 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
|
|||||||
if (descriptor->flags & O_CLOEXEC) { descriptor = {}; }
|
if (descriptor->flags & O_CLOEXEC) { descriptor = {}; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VFS::is_setuid(inode)) current->auth.euid = current->auth.suid = inode->metadata().uid;
|
if (is_setuid) current->auth.euid = current->auth.suid = inode->metadata().uid;
|
||||||
if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->metadata().gid;
|
if (is_setgid) current->auth.egid = current->auth.sgid = inode->metadata().gid;
|
||||||
|
|
||||||
current->name = path.chars();
|
current->name = path.chars();
|
||||||
|
|
||||||
@ -115,6 +123,9 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
|
|||||||
|
|
||||||
current->set_arguments(user_argc, user_argv, user_envc, user_envp);
|
current->set_arguments(user_argc, user_argv, user_envc, user_envp);
|
||||||
|
|
||||||
|
current->promises = current->execpromises;
|
||||||
|
current->execpromises = -1;
|
||||||
|
|
||||||
memcpy(regs, ¤t->regs, sizeof(*regs));
|
memcpy(regs, ¤t->regs, sizeof(*regs));
|
||||||
|
|
||||||
for (int i = 0; i < NSIG; i++)
|
for (int i = 0; i < NSIG; i++)
|
||||||
@ -133,6 +144,8 @@ Result<u64> sys_fork(Registers* regs, SyscallArgs)
|
|||||||
{
|
{
|
||||||
auto current = Scheduler::current();
|
auto current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_proc));
|
||||||
|
|
||||||
auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory()); });
|
auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory()); });
|
||||||
|
|
||||||
memcpy(¤t->regs, regs, sizeof(*regs));
|
memcpy(¤t->regs, regs, sizeof(*regs));
|
||||||
@ -152,6 +165,8 @@ Result<u64> sys_fork(Registers* regs, SyscallArgs)
|
|||||||
thread->current_directory_path = move(current_directory_path);
|
thread->current_directory_path = move(current_directory_path);
|
||||||
thread->umask = current->umask;
|
thread->umask = current->umask;
|
||||||
thread->parent = current;
|
thread->parent = current;
|
||||||
|
thread->promises = current->promises;
|
||||||
|
thread->execpromises = current->execpromises;
|
||||||
|
|
||||||
for (int i = 0; i < FD_MAX; i++) { thread->fd_table[i] = current->fd_table[i]; }
|
for (int i = 0; i < FD_MAX; i++) { thread->fd_table[i] = current->fd_table[i]; }
|
||||||
|
|
||||||
@ -159,11 +174,7 @@ Result<u64> sys_fork(Registers* regs, SyscallArgs)
|
|||||||
|
|
||||||
memcpy(&thread->regs, regs, sizeof(*regs));
|
memcpy(&thread->regs, regs, sizeof(*regs));
|
||||||
|
|
||||||
for (int i = 0; i < NSIG; i++)
|
for (int i = 0; i < NSIG; i++) thread->signal_handlers[i] = current->signal_handlers[i];
|
||||||
{
|
|
||||||
auto sighandler = current->signal_handlers[i].sa_handler;
|
|
||||||
thread->signal_handlers[i] = { .sa_handler = sighandler, .sa_mask = 0, .sa_flags = 0 };
|
|
||||||
}
|
|
||||||
thread->signal_mask = current->signal_mask;
|
thread->signal_mask = current->signal_mask;
|
||||||
|
|
||||||
thread->set_return(0);
|
thread->set_return(0);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "fs/Pipe.h"
|
#include "fs/Pipe.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
@ -24,6 +25,8 @@ Result<u64> sys_read(Registers* regs, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
auto& descriptor = *TRY(current->resolve_fd(fd));
|
auto& descriptor = *TRY(current->resolve_fd(fd));
|
||||||
|
|
||||||
if (!descriptor.is_readable()) return err(EBADF);
|
if (!descriptor.is_readable()) return err(EBADF);
|
||||||
@ -65,6 +68,8 @@ Result<u64> sys_write(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
auto& descriptor = *TRY(current->resolve_fd(fd));
|
auto& descriptor = *TRY(current->resolve_fd(fd));
|
||||||
|
|
||||||
if (!descriptor.is_writable()) return err(EBADF);
|
if (!descriptor.is_writable()) return err(EBADF);
|
||||||
@ -87,6 +92,8 @@ Result<u64> sys_lseek(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
auto& descriptor = *TRY(current->resolve_fd(fd));
|
auto& descriptor = *TRY(current->resolve_fd(fd));
|
||||||
|
|
||||||
if (descriptor.inode()->type() == VFS::InodeType::FIFO) return err(ESPIPE);
|
if (descriptor.inode()->type() == VFS::InodeType::FIFO) return err(ESPIPE);
|
||||||
@ -117,6 +124,8 @@ Result<u64> sys_fcntl(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
auto& descriptor = *TRY(current->resolve_fd(fd));
|
auto& descriptor = *TRY(current->resolve_fd(fd));
|
||||||
|
|
||||||
bool is_cloexec = true;
|
bool is_cloexec = true;
|
||||||
@ -176,6 +185,7 @@ Result<u64> sys_isatty(Registers*, SyscallArgs args)
|
|||||||
int fd = (int)args[0];
|
int fd = (int)args[0];
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
auto& descriptor = *TRY(current->resolve_fd(fd));
|
auto& descriptor = *TRY(current->resolve_fd(fd));
|
||||||
|
|
||||||
return descriptor.inode()->isatty();
|
return descriptor.inode()->isatty();
|
||||||
@ -188,6 +198,8 @@ Result<u64> sys_dup2(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
if (newfd < 0 || newfd >= FD_MAX) return err(EBADF);
|
if (newfd < 0 || newfd >= FD_MAX) return err(EBADF);
|
||||||
|
|
||||||
auto descriptor = *TRY(current->resolve_fd(oldfd));
|
auto descriptor = *TRY(current->resolve_fd(oldfd));
|
||||||
@ -206,6 +218,8 @@ Result<u64> sys_pipe(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
int rfd = TRY(current->allocate_fd(0));
|
int rfd = TRY(current->allocate_fd(0));
|
||||||
int wfd = TRY(current->allocate_fd(rfd + 1));
|
int wfd = TRY(current->allocate_fd(rfd + 1));
|
||||||
|
|
||||||
@ -229,6 +243,8 @@ Result<u64> sys_umask(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
mode_t old_umask = current->umask;
|
mode_t old_umask = current->umask;
|
||||||
|
|
||||||
current->umask = new_umask & 0777;
|
current->umask = new_umask & 0777;
|
||||||
@ -242,6 +258,7 @@ Result<u64> sys_truncate(Registers*, SyscallArgs args)
|
|||||||
size_t length = (size_t)args[1];
|
size_t length = (size_t)args[1];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_wpath));
|
||||||
auto inode = TRY(VFS::resolve_path(path.chars(), current->auth, current->current_directory));
|
auto inode = TRY(VFS::resolve_path(path.chars(), current->auth, current->current_directory));
|
||||||
|
|
||||||
if (!VFS::can_write(inode, current->auth)) return err(EACCES);
|
if (!VFS::can_write(inode, current->auth)) return err(EACCES);
|
||||||
@ -257,6 +274,7 @@ Result<u64> sys_ftruncate(Registers*, SyscallArgs args)
|
|||||||
size_t length = (size_t)args[1];
|
size_t length = (size_t)args[1];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
auto description = TRY(current->resolve_fd(fd))->description;
|
auto description = TRY(current->resolve_fd(fd))->description;
|
||||||
if (!(description->flags & O_WRONLY)) return err(EBADF);
|
if (!(description->flags & O_WRONLY)) return err(EBADF);
|
||||||
|
|
||||||
@ -273,6 +291,7 @@ Result<u64> sys_utimensat(Registers*, SyscallArgs args)
|
|||||||
int flags = (int)args[3];
|
int flags = (int)args[3];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_fattr));
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
struct timespec ktimes[2];
|
struct timespec ktimes[2];
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
@ -11,6 +12,7 @@ Result<u64> sys_getdents(Registers*, SyscallArgs args)
|
|||||||
usize count = (usize)args[2];
|
usize count = (usize)args[2];
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
auto& descriptor = *TRY(current->resolve_fd(fd));
|
auto& descriptor = *TRY(current->resolve_fd(fd));
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -5,41 +6,54 @@
|
|||||||
|
|
||||||
Result<u64> sys_getpid(Registers*, SyscallArgs)
|
Result<u64> sys_getpid(Registers*, SyscallArgs)
|
||||||
{
|
{
|
||||||
return Scheduler::current()->id;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
return current->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_getppid(Registers*, SyscallArgs)
|
Result<u64> sys_getppid(Registers*, SyscallArgs)
|
||||||
{
|
{
|
||||||
auto* parent = Scheduler::current()->parent;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
auto* parent = current->parent;
|
||||||
return parent ? parent->id : 0;
|
return parent ? parent->id : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_getuid(Registers*, SyscallArgs)
|
Result<u64> sys_getuid(Registers*, SyscallArgs)
|
||||||
{
|
{
|
||||||
return Scheduler::current()->auth.uid;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
return current->auth.uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_geteuid(Registers*, SyscallArgs)
|
Result<u64> sys_geteuid(Registers*, SyscallArgs)
|
||||||
{
|
{
|
||||||
return Scheduler::current()->auth.euid;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
return current->auth.euid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_getgid(Registers*, SyscallArgs)
|
Result<u64> sys_getgid(Registers*, SyscallArgs)
|
||||||
{
|
{
|
||||||
return Scheduler::current()->auth.gid;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
return current->auth.gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_getegid(Registers*, SyscallArgs)
|
Result<u64> sys_getegid(Registers*, SyscallArgs)
|
||||||
{
|
{
|
||||||
return Scheduler::current()->auth.egid;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
return current->auth.egid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_setuid(Registers*, SyscallArgs args)
|
Result<u64> sys_setuid(Registers*, SyscallArgs args)
|
||||||
{
|
{
|
||||||
u32 uid = (u32)args[0];
|
u32 uid = (u32)args[0];
|
||||||
|
|
||||||
Credentials& auth = Scheduler::current()->auth;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_id));
|
||||||
|
Credentials& auth = current->auth;
|
||||||
|
|
||||||
if (auth.euid == 0)
|
if (auth.euid == 0)
|
||||||
{
|
{
|
||||||
@ -57,7 +71,9 @@ Result<u64> sys_seteuid(Registers*, SyscallArgs args)
|
|||||||
{
|
{
|
||||||
u32 uid = (u32)args[0];
|
u32 uid = (u32)args[0];
|
||||||
|
|
||||||
Credentials& auth = Scheduler::current()->auth;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_id));
|
||||||
|
Credentials& auth = current->auth;
|
||||||
|
|
||||||
if (auth.euid != 0 && uid != auth.uid && uid != auth.suid) return err(EPERM);
|
if (auth.euid != 0 && uid != auth.uid && uid != auth.suid) return err(EPERM);
|
||||||
auth.euid = uid;
|
auth.euid = uid;
|
||||||
@ -69,7 +85,9 @@ Result<u64> sys_setgid(Registers*, SyscallArgs args)
|
|||||||
{
|
{
|
||||||
u32 gid = (u32)args[0];
|
u32 gid = (u32)args[0];
|
||||||
|
|
||||||
Credentials& auth = Scheduler::current()->auth;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_id));
|
||||||
|
Credentials& auth = current->auth;
|
||||||
|
|
||||||
if (auth.euid == 0)
|
if (auth.euid == 0)
|
||||||
{
|
{
|
||||||
@ -87,7 +105,9 @@ Result<u64> sys_setegid(Registers*, SyscallArgs args)
|
|||||||
{
|
{
|
||||||
u32 gid = (u32)args[0];
|
u32 gid = (u32)args[0];
|
||||||
|
|
||||||
Credentials& auth = Scheduler::current()->auth;
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_id));
|
||||||
|
Credentials& auth = current->auth;
|
||||||
|
|
||||||
if (auth.euid != 0 && gid != auth.gid && gid != auth.sgid) return err(EPERM);
|
if (auth.euid != 0 && gid != auth.gid && gid != auth.sgid) return err(EPERM);
|
||||||
auth.egid = gid;
|
auth.egid = gid;
|
||||||
@ -101,6 +121,7 @@ Result<u64> sys_setpgid(Registers*, SyscallArgs args)
|
|||||||
pid_t pgid = (pid_t)args[1];
|
pid_t pgid = (pid_t)args[1];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_proc));
|
||||||
if (pid == 0) pid = current->id;
|
if (pid == 0) pid = current->id;
|
||||||
if (pgid == 0) pgid = current->id;
|
if (pgid == 0) pgid = current->id;
|
||||||
|
|
||||||
@ -133,6 +154,7 @@ Result<u64> sys_getpgid(Registers*, SyscallArgs args)
|
|||||||
pid_t pid = (pid_t)args[0];
|
pid_t pid = (pid_t)args[0];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
if (pid == 0) pid = current->id;
|
if (pid == 0) pid = current->id;
|
||||||
|
|
||||||
if (pid < 0) return err(EINVAL);
|
if (pid < 0) return err(EINVAL);
|
||||||
@ -150,6 +172,7 @@ Result<u64> sys_fchmodat(Registers*, SyscallArgs args)
|
|||||||
int flags = (int)args[3];
|
int flags = (int)args[3];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_wpath));
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
@ -171,6 +194,7 @@ Result<u64> sys_fchownat(Registers*, SyscallArgs args)
|
|||||||
int flags = (int)args[4];
|
int flags = (int)args[4];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_chown));
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -12,6 +13,7 @@ Result<u64> sys_unlinkat(Registers*, SyscallArgs args)
|
|||||||
int flags = (int)args[2];
|
int flags = (int)args[2];
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_cpath));
|
||||||
|
|
||||||
auto dirname = TRY(PathParser::dirname(path.view()));
|
auto dirname = TRY(PathParser::dirname(path.view()));
|
||||||
auto basename = TRY(PathParser::basename(path.view()));
|
auto basename = TRY(PathParser::basename(path.view()));
|
||||||
@ -44,6 +46,7 @@ Result<u64> sys_symlinkat(Registers*, SyscallArgs args)
|
|||||||
if (target.is_empty()) return err(ENOENT);
|
if (target.is_empty()) return err(ENOENT);
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_cpath));
|
||||||
|
|
||||||
auto parent = TRY(PathParser::dirname(linkpath.view()));
|
auto parent = TRY(PathParser::dirname(linkpath.view()));
|
||||||
|
|
||||||
@ -73,6 +76,7 @@ Result<u64> sys_readlinkat(Registers*, SyscallArgs args)
|
|||||||
usize bufsiz = (usize)args[3];
|
usize bufsiz = (usize)args[3];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_rpath));
|
||||||
|
|
||||||
auto symlink = TRY(current->resolve_atfile(dirfd, path, true, false));
|
auto symlink = TRY(current->resolve_atfile(dirfd, path, true, false));
|
||||||
|
|
||||||
@ -98,6 +102,7 @@ Result<u64> sys_linkat(Registers*, SyscallArgs args)
|
|||||||
int flags = (int)args[4];
|
int flags = (int)args[4];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_cpath));
|
||||||
|
|
||||||
auto parent = TRY(PathParser::dirname(newpath.view()));
|
auto parent = TRY(PathParser::dirname(newpath.view()));
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
@ -10,6 +11,7 @@ Result<u64> sys_mkdir(Registers*, SyscallArgs args)
|
|||||||
mode_t mode = (mode_t)args[1];
|
mode_t mode = (mode_t)args[1];
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_cpath));
|
||||||
|
|
||||||
auto inode =
|
auto inode =
|
||||||
TRY(VFS::create_directory(path.chars(), mode & ~current->umask, current->auth, current->current_directory));
|
TRY(VFS::create_directory(path.chars(), mode & ~current->umask, current->auth, current->current_directory));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "arch/MMU.h"
|
#include "arch/MMU.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/SharedMemory.h"
|
#include "memory/SharedMemory.h"
|
||||||
@ -22,6 +23,8 @@ Result<u64> sys_mmap(Registers*, SyscallArgs args)
|
|||||||
if (params.flags < 0) return err(EINVAL);
|
if (params.flags < 0) return err(EINVAL);
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
if (params.prot & PROT_EXEC) TRY(check_pledge(current, Promise::p_prot_exec));
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
SharedPtr<OpenFileDescription> description;
|
SharedPtr<OpenFileDescription> description;
|
||||||
if ((params.flags & MAP_ANONYMOUS) != MAP_ANONYMOUS)
|
if ((params.flags & MAP_ANONYMOUS) != MAP_ANONYMOUS)
|
||||||
@ -94,6 +97,7 @@ Result<u64> sys_munmap(Registers*, SyscallArgs args)
|
|||||||
if (!is_aligned<ARCH_PAGE_SIZE>(address)) return err(EINVAL);
|
if (!is_aligned<ARCH_PAGE_SIZE>(address)) return err(EINVAL);
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
bool ok = TRY(current->address_space->free_region(address, ceil_div(size, ARCH_PAGE_SIZE)));
|
bool ok = TRY(current->address_space->free_region(address, ceil_div(size, ARCH_PAGE_SIZE)));
|
||||||
|
|
||||||
@ -118,6 +122,7 @@ Result<u64> sys_msync(Registers*, SyscallArgs args)
|
|||||||
if (!is_aligned<ARCH_PAGE_SIZE>(address)) return err(EINVAL);
|
if (!is_aligned<ARCH_PAGE_SIZE>(address)) return err(EINVAL);
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
TRY(current->address_space->sync_regions(address, ceil_div(size, ARCH_PAGE_SIZE)));
|
TRY(current->address_space->sync_regions(address, ceil_div(size, ARCH_PAGE_SIZE)));
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "fs/ext2/FileSystem.h"
|
#include "fs/ext2/FileSystem.h"
|
||||||
#include "fs/tmpfs/FileSystem.h"
|
#include "fs/tmpfs/FileSystem.h"
|
||||||
@ -12,6 +13,7 @@ Result<u64> sys_mount(Registers*, SyscallArgs args)
|
|||||||
auto source = TRY(MemoryManager::strdup_from_user(args[2]));
|
auto source = TRY(MemoryManager::strdup_from_user(args[2]));
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_mount));
|
||||||
if (current->auth.euid != 0) return err(EPERM);
|
if (current->auth.euid != 0) return err(EPERM);
|
||||||
|
|
||||||
auto get_source = [current, &source]() -> Result<SharedPtr<Device>> {
|
auto get_source = [current, &source]() -> Result<SharedPtr<Device>> {
|
||||||
@ -44,6 +46,7 @@ Result<u64> sys_umount(Registers*, SyscallArgs args)
|
|||||||
auto target = TRY(MemoryManager::strdup_from_user(args[0]));
|
auto target = TRY(MemoryManager::strdup_from_user(args[0]));
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_mount));
|
||||||
if (current->auth.euid != 0) return err(EPERM);
|
if (current->auth.euid != 0) return err(EPERM);
|
||||||
|
|
||||||
TRY(VFS::umount(target.chars(), current->auth, current->current_directory));
|
TRY(VFS::umount(target.chars(), current->auth, current->current_directory));
|
||||||
@ -57,6 +60,7 @@ Result<u64> sys_pivot_root(Registers*, SyscallArgs args)
|
|||||||
auto put_old = TRY(MemoryManager::strdup_from_user(args[1]));
|
auto put_old = TRY(MemoryManager::strdup_from_user(args[1]));
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_mount));
|
||||||
if (current->auth.euid != 0) return err(EPERM);
|
if (current->auth.euid != 0) return err(EPERM);
|
||||||
|
|
||||||
TRY(VFS::pivot_root(new_root.chars(), put_old.chars(), current->current_directory));
|
TRY(VFS::pivot_root(new_root.chars(), put_old.chars(), current->current_directory));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
@ -23,6 +24,12 @@ Result<u64> sys_openat(Registers*, SyscallArgs args)
|
|||||||
// Caller did not pass either O_RDONLY, O_WRONLY or O_RDWR
|
// Caller did not pass either O_RDONLY, O_WRONLY or O_RDWR
|
||||||
if ((flags & O_RDWR) == 0) { return err(EINVAL); }
|
if ((flags & O_RDWR) == 0) { return err(EINVAL); }
|
||||||
|
|
||||||
|
if (flags & O_RDONLY) TRY(check_pledge(current, Promise::p_rpath));
|
||||||
|
else if (flags & O_WRONLY)
|
||||||
|
TRY(check_pledge(current, Promise::p_wpath));
|
||||||
|
|
||||||
|
if (flags & O_CREAT) TRY(check_pledge(current, Promise::p_cpath));
|
||||||
|
|
||||||
if (flags & O_TMPFILE)
|
if (flags & O_TMPFILE)
|
||||||
{
|
{
|
||||||
if (!(flags & O_WRONLY)) return err(EINVAL);
|
if (!(flags & O_WRONLY)) return err(EINVAL);
|
||||||
@ -99,6 +106,7 @@ Result<u64> sys_close(Registers*, SyscallArgs args)
|
|||||||
if (fd < 0 || fd >= FD_MAX) return err(EBADF);
|
if (fd < 0 || fd >= FD_MAX) return err(EBADF);
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
Option<FileDescriptor>& descriptor = current->fd_table[fd];
|
Option<FileDescriptor>& descriptor = current->fd_table[fd];
|
||||||
|
|
||||||
|
40
kernel/src/sys/pledge.cpp
Normal file
40
kernel/src/sys/pledge.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
|
#include "sys/Syscall.h"
|
||||||
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
|
Result<u64> sys_pledge(Registers*, SyscallArgs args)
|
||||||
|
{
|
||||||
|
int promises = TRY(parse_promises(args[0]));
|
||||||
|
int execpromises = TRY(parse_promises(args[1]));
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
|
if (promises >= 0)
|
||||||
|
{
|
||||||
|
int actual_promises = promises & ~(1 << (int)Promise::p_error);
|
||||||
|
int old_promises = current->promises & ~(1 << (int)Promise::p_error);
|
||||||
|
|
||||||
|
if (actual_promises & ~old_promises)
|
||||||
|
{
|
||||||
|
if (current->promises & ~(1 << (int)Promise::p_error)) return 0;
|
||||||
|
return err(EPERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (execpromises >= 0)
|
||||||
|
{
|
||||||
|
int actual_execpromises = execpromises & ~(1 << (int)Promise::p_error);
|
||||||
|
int old_execpromises = current->execpromises & ~(1 << (int)Promise::p_error);
|
||||||
|
|
||||||
|
if (actual_execpromises & ~old_execpromises)
|
||||||
|
{
|
||||||
|
if (current->execpromises & ~(1 << (int)Promise::p_error)) return 0;
|
||||||
|
return err(EPERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promises >= 0) current->promises = promises;
|
||||||
|
if (execpromises >= 0) current->execpromises = execpromises;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "fs/VFS.h"
|
#include "fs/VFS.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "net/Socket.h"
|
#include "net/Socket.h"
|
||||||
@ -19,6 +20,7 @@ Result<u64> sys_poll(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Vector<SharedPtr<VFS::Inode>> inodes;
|
Vector<SharedPtr<VFS::Inode>> inodes;
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
for (nfds_t i = 0; i < nfds; i++)
|
for (nfds_t i = 0; i < nfds; i++)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -14,6 +15,9 @@ Result<u64> sys_pstat(Registers*, SyscallArgs args)
|
|||||||
pid_t pid = (pid_t)args[0];
|
pid_t pid = (pid_t)args[0];
|
||||||
struct process* ps = (struct process*)args[1];
|
struct process* ps = (struct process*)args[1];
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_proc));
|
||||||
|
|
||||||
// If pid == -1, return the PID of the last spawned thread.
|
// If pid == -1, return the PID of the last spawned thread.
|
||||||
if (pid == -1) return g_threads.expect_last()->id;
|
if (pid == -1) return g_threads.expect_last()->id;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -18,6 +19,7 @@ Result<u64> sys_sigreturn(Registers* regs, SyscallArgs)
|
|||||||
Result<u64> sys_sigaction(Registers*, SyscallArgs args)
|
Result<u64> sys_sigaction(Registers*, SyscallArgs args)
|
||||||
{
|
{
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_signal));
|
||||||
|
|
||||||
int signo = (int)args[0];
|
int signo = (int)args[0];
|
||||||
const struct sigaction* act = (const struct sigaction*)args[1];
|
const struct sigaction* act = (const struct sigaction*)args[1];
|
||||||
@ -47,6 +49,7 @@ Result<u64> sys_sigaction(Registers*, SyscallArgs args)
|
|||||||
Result<u64> sys_kill(Registers*, SyscallArgs args)
|
Result<u64> sys_kill(Registers*, SyscallArgs args)
|
||||||
{
|
{
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_proc));
|
||||||
|
|
||||||
pid_t pid = (pid_t)args[0];
|
pid_t pid = (pid_t)args[0];
|
||||||
int signo = (int)args[1];
|
int signo = (int)args[1];
|
||||||
@ -68,6 +71,7 @@ Result<u64> sys_kill(Registers*, SyscallArgs args)
|
|||||||
Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
|
Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
|
||||||
{
|
{
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_signal));
|
||||||
|
|
||||||
int how = (int)args[0];
|
int how = (int)args[0];
|
||||||
const sigset_t* set = (const sigset_t*)args[1];
|
const sigset_t* set = (const sigset_t*)args[1];
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "net/Socket.h"
|
#include "net/Socket.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "net/UnixSocket.h"
|
#include "net/UnixSocket.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
@ -14,9 +15,10 @@ Result<u64> sys_socket(Registers*, SyscallArgs args)
|
|||||||
if (type != SOCK_STREAM) return err(EPROTOTYPE);
|
if (type != SOCK_STREAM) return err(EPROTOTYPE);
|
||||||
if (domain != AF_UNIX) return err(EAFNOSUPPORT);
|
if (domain != AF_UNIX) return err(EAFNOSUPPORT);
|
||||||
|
|
||||||
auto socket = TRY(make_shared<UnixSocket>());
|
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_unix));
|
||||||
|
|
||||||
|
auto socket = TRY(make_shared<UnixSocket>());
|
||||||
|
|
||||||
int fd = TRY(current->allocate_fd(0));
|
int fd = TRY(current->allocate_fd(0));
|
||||||
|
|
||||||
@ -36,6 +38,7 @@ Result<u64> sys_bind(Registers*, SyscallArgs args)
|
|||||||
if (!MemoryManager::copy_from_user(addr, &storage, addrlen)) return err(EFAULT);
|
if (!MemoryManager::copy_from_user(addr, &storage, addrlen)) return err(EFAULT);
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_unix));
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_fd(sockfd))->inode();
|
auto inode = TRY(current->resolve_fd(sockfd))->inode();
|
||||||
|
|
||||||
@ -59,6 +62,7 @@ Result<u64> sys_connect(Registers* regs, SyscallArgs args)
|
|||||||
if (!MemoryManager::copy_from_user(addr, &storage, addrlen)) return err(EFAULT);
|
if (!MemoryManager::copy_from_user(addr, &storage, addrlen)) return err(EFAULT);
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_unix));
|
||||||
|
|
||||||
auto description = TRY(current->resolve_fd(sockfd))->description;
|
auto description = TRY(current->resolve_fd(sockfd))->description;
|
||||||
|
|
||||||
@ -77,6 +81,7 @@ Result<u64> sys_listen(Registers*, SyscallArgs args)
|
|||||||
int backlog = (int)args[1];
|
int backlog = (int)args[1];
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_unix));
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_fd(sockfd))->inode();
|
auto inode = TRY(current->resolve_fd(sockfd))->inode();
|
||||||
|
|
||||||
@ -104,6 +109,7 @@ Result<u64> sys_accept(Registers* regs, SyscallArgs args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_unix));
|
||||||
|
|
||||||
auto description = TRY(current->resolve_fd(sockfd))->description;
|
auto description = TRY(current->resolve_fd(sockfd))->description;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -33,6 +34,7 @@ Result<u64> sys_fstatat(Registers*, SyscallArgs args)
|
|||||||
int flags = (int)args[3];
|
int flags = (int)args[3];
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_rpath));
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
@ -67,6 +69,7 @@ Result<u64> sys_faccessat(Registers*, SyscallArgs args)
|
|||||||
Credentials creds;
|
Credentials creds;
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_rpath));
|
||||||
|
|
||||||
if (flags & AT_EACCESS) creds = current->auth;
|
if (flags & AT_EACCESS) creds = current->auth;
|
||||||
else
|
else
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "arch/CPU.h"
|
#include "arch/CPU.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
@ -40,6 +41,7 @@ Result<u64> sys_sethostname(Registers*, SyscallArgs args)
|
|||||||
usize length = (usize)args[1];
|
usize length = (usize)args[1];
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_host));
|
||||||
if (current->auth.euid != 0) return err(EPERM);
|
if (current->auth.euid != 0) return err(EPERM);
|
||||||
|
|
||||||
if (length >= _UTSNAME_LENGTH) return err(EINVAL);
|
if (length >= _UTSNAME_LENGTH) return err(EINVAL);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "Pledge.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -6,12 +7,13 @@ Result<u64> sys_usleep(Registers*, SyscallArgs args)
|
|||||||
{
|
{
|
||||||
useconds_t us = (useconds_t)args[0];
|
useconds_t us = (useconds_t)args[0];
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
// FIXME: Allow usleep() to use a more precise resolution.
|
// FIXME: Allow usleep() to use a more precise resolution.
|
||||||
if (us < 1000) return 0;
|
if (us < 1000) return 0;
|
||||||
|
|
||||||
kernel_sleep(us / 1000);
|
kernel_sleep(us / 1000);
|
||||||
|
|
||||||
auto* current = Scheduler::current();
|
|
||||||
|
|
||||||
return current->sleep_ticks_left;
|
return current->sleep_ticks_left;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Pledge.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
@ -11,6 +12,7 @@ Result<u64> sys_waitpid(Registers* regs, SyscallArgs args)
|
|||||||
int options = (int)args[2];
|
int options = (int)args[2];
|
||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
TRY(check_pledge(current, Promise::p_stdio));
|
||||||
|
|
||||||
Thread* thread;
|
Thread* thread;
|
||||||
|
|
||||||
|
@ -282,6 +282,8 @@ namespace Scheduler
|
|||||||
{
|
{
|
||||||
if (thread->sleep_ticks_left == 0 || --thread->sleep_ticks_left == 0) thread->wake_up();
|
if (thread->sleep_ticks_left == 0 || --thread->sleep_ticks_left == 0) thread->wake_up();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thread->alarm_ticks_left && --thread->alarm_ticks_left == 0) thread->send_signal(SIGALRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_current->ticks_left) switch_task(regs);
|
if (!g_current->ticks_left) switch_task(regs);
|
||||||
|
@ -87,6 +87,10 @@ struct Thread : public LinkedListNode<Thread>
|
|||||||
|
|
||||||
u64 ticks_left;
|
u64 ticks_left;
|
||||||
u64 sleep_ticks_left;
|
u64 sleep_ticks_left;
|
||||||
|
u64 alarm_ticks_left { 0 };
|
||||||
|
|
||||||
|
int promises { -1 };
|
||||||
|
int execpromises { -1 };
|
||||||
|
|
||||||
Stack stack;
|
Stack stack;
|
||||||
Stack kernel_stack;
|
Stack kernel_stack;
|
||||||
|
@ -25,6 +25,7 @@ set(SOURCES
|
|||||||
src/termios.cpp
|
src/termios.cpp
|
||||||
src/utime.cpp
|
src/utime.cpp
|
||||||
src/strtod.cpp
|
src/strtod.cpp
|
||||||
|
src/math.cpp
|
||||||
src/sys/stat.cpp
|
src/sys/stat.cpp
|
||||||
src/sys/mman.cpp
|
src/sys/mman.cpp
|
||||||
src/sys/wait.cpp
|
src/sys/wait.cpp
|
||||||
|
0
libc/include/arpa/inet.h
Normal file
0
libc/include/arpa/inet.h
Normal file
@ -5,6 +5,28 @@
|
|||||||
|
|
||||||
#include <bits/locale-cat.h>
|
#include <bits/locale-cat.h>
|
||||||
|
|
||||||
|
struct lconv
|
||||||
|
{
|
||||||
|
char* decimal_point;
|
||||||
|
char* thousands_sep;
|
||||||
|
char* grouping;
|
||||||
|
char* int_curr_symbol;
|
||||||
|
char* currency_symbol;
|
||||||
|
char* mon_decimal_point;
|
||||||
|
char* mon_thousands_sep;
|
||||||
|
char* mon_grouping;
|
||||||
|
char* positive_sign;
|
||||||
|
char* negative_sign;
|
||||||
|
char int_frac_digits;
|
||||||
|
char frac_digits;
|
||||||
|
char p_cs_precedes;
|
||||||
|
char p_sep_by_space;
|
||||||
|
char n_cs_precedes;
|
||||||
|
char n_sep_by_space;
|
||||||
|
char p_sign_posn;
|
||||||
|
char n_sign_posn;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -13,6 +35,9 @@ extern "C"
|
|||||||
// Query or set the current locale.
|
// Query or set the current locale.
|
||||||
char* setlocale(int category, const char* locale);
|
char* setlocale(int category, const char* locale);
|
||||||
|
|
||||||
|
// Query formatting information for the current locale.
|
||||||
|
struct lconv* localeconv(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
/* math.h: Floating-point arithmetic functions. */
|
||||||
|
|
||||||
|
#ifndef _MATH_H
|
||||||
|
#define _MATH_H
|
||||||
|
|
||||||
|
typedef float float_t;
|
||||||
|
typedef double double_t;
|
||||||
|
|
||||||
|
#define FP_NAN 0
|
||||||
|
#define FP_INFINITE 1
|
||||||
|
#define FP_ZERO 2
|
||||||
|
#define FP_SUBNORMAL 3
|
||||||
|
#define FP_NORMAL 4
|
||||||
|
#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_ZERO, x)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double cos(double val);
|
||||||
|
float cosf(float val);
|
||||||
|
long double cosl(long double val);
|
||||||
|
double sin(double val);
|
||||||
|
float sinf(float val);
|
||||||
|
long double sinl(long double val);
|
||||||
|
double tan(double val);
|
||||||
|
float tanf(float val);
|
||||||
|
long double tanl(long double val);
|
||||||
|
double acos(double val);
|
||||||
|
float acosf(float val);
|
||||||
|
long double acosl(long double val);
|
||||||
|
double asin(double val);
|
||||||
|
float asinf(float val);
|
||||||
|
long double asinl(long double val);
|
||||||
|
double atan(double val);
|
||||||
|
float atanf(float val);
|
||||||
|
long double atanl(long double val);
|
||||||
|
double cosh(double val);
|
||||||
|
float coshf(float val);
|
||||||
|
long double coshl(long double val);
|
||||||
|
double sinh(double val);
|
||||||
|
float sinhf(float val);
|
||||||
|
long double sinhl(long double val);
|
||||||
|
double tanh(double val);
|
||||||
|
float tanhf(float val);
|
||||||
|
long double tanhl(long double val);
|
||||||
|
double log(double val);
|
||||||
|
float logf(float val);
|
||||||
|
long double logl(long double val);
|
||||||
|
double exp(double val);
|
||||||
|
float expf(float val);
|
||||||
|
long double expl(long double val);
|
||||||
|
double sqrt(double val);
|
||||||
|
float sqrtf(float val);
|
||||||
|
long double sqrtl(long double val);
|
||||||
|
double fabs(double val);
|
||||||
|
float fabsf(float val);
|
||||||
|
long double fabsl(long double val);
|
||||||
|
double floor(double val);
|
||||||
|
float floorf(float val);
|
||||||
|
long double floorl(long double val);
|
||||||
|
double ceil(double val);
|
||||||
|
float ceilf(float val);
|
||||||
|
long double ceill(long double val);
|
||||||
|
double log10(double val);
|
||||||
|
float log10f(float val);
|
||||||
|
long double log10l(long double val);
|
||||||
|
double fmod(double val1, double val2);
|
||||||
|
float fmodf(float val1, float val2);
|
||||||
|
long double fmodl(long double val1, long double val2);
|
||||||
|
double pow(double val1, double val2);
|
||||||
|
float powf(float val1, float val2);
|
||||||
|
long double powl(long double val1, long double val2);
|
||||||
|
double atan2(double val1, double val2);
|
||||||
|
float atan2f(float val1, float val2);
|
||||||
|
long double atan2l(long double val1, long double val2);
|
||||||
|
double frexp(double val1, int* val2);
|
||||||
|
float frexpf(float val1, int* val2);
|
||||||
|
long double frexpl(long double val1, int* val2);
|
||||||
|
double ldexp(double val1, int val2);
|
||||||
|
float ldexpf(float val1, int val2);
|
||||||
|
long double ldexpl(long double val1, int val2);
|
||||||
|
double modf(double val1, double* val2);
|
||||||
|
float modff(float val1, float* val2);
|
||||||
|
long double modfl(long double val1, long double* val2);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
0
libc/include/netdb.h
Normal file
0
libc/include/netdb.h
Normal file
0
libc/include/netinet/in.h
Normal file
0
libc/include/netinet/in.h
Normal file
@ -198,6 +198,9 @@ extern "C"
|
|||||||
/* Change a file's buffering mode to line buffered. */
|
/* Change a file's buffering mode to line buffered. */
|
||||||
void setlinebuf(FILE* stream);
|
void setlinebuf(FILE* stream);
|
||||||
|
|
||||||
|
/* Move a file's location across a file system. */
|
||||||
|
int rename(const char* oldpath, const char* newpath);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -128,6 +128,9 @@ extern "C"
|
|||||||
/* Clear all environment variables. */
|
/* Clear all environment variables. */
|
||||||
int clearenv(void);
|
int clearenv(void);
|
||||||
|
|
||||||
|
/* Add a new variable to the environment. */
|
||||||
|
int putenv(char* string);
|
||||||
|
|
||||||
/* Sort an array of arbitrary elements using a comparison function. */
|
/* Sort an array of arbitrary elements using a comparison function. */
|
||||||
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
|
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
|
||||||
|
|
||||||
|
@ -98,6 +98,9 @@ extern "C"
|
|||||||
/* Compare two null-terminated strings according to the current locale. */
|
/* Compare two null-terminated strings according to the current locale. */
|
||||||
int strcoll(const char* a, const char* b);
|
int strcoll(const char* a, const char* b);
|
||||||
|
|
||||||
|
/* Transform a string according to the current locale. */
|
||||||
|
size_t strxfrm(char* dest, const char* src, size_t n);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,10 +14,10 @@ extern "C"
|
|||||||
int socket(int domain, int type, int protocol);
|
int socket(int domain, int type, int protocol);
|
||||||
|
|
||||||
/* Bind a socket to an address. */
|
/* Bind a socket to an address. */
|
||||||
int bind(int sockfd, struct sockaddr* addr, socklen_t addrlen);
|
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
|
||||||
|
|
||||||
/* Connect a socket to a remote address. */
|
/* Connect a socket to a remote address. */
|
||||||
int connect(int sockfd, struct sockaddr* addr, socklen_t addrlen);
|
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
|
||||||
|
|
||||||
/* Start listening on a socket. */
|
/* Start listening on a socket. */
|
||||||
int listen(int sockfd, int backlog);
|
int listen(int sockfd, int backlog);
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
#include <bits/struct_tm.h>
|
#include <bits/struct_tm.h>
|
||||||
#include <bits/timespec.h>
|
#include <bits/timespec.h>
|
||||||
|
|
||||||
|
typedef long int clock_t;
|
||||||
|
|
||||||
|
#define CLOCKS_PER_SEC 1000000
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -42,9 +46,18 @@ extern "C"
|
|||||||
/* Build a string representation of UNIX time. */
|
/* Build a string representation of UNIX time. */
|
||||||
char* ctime_r(const time_t* tp, char buf[26]);
|
char* ctime_r(const time_t* tp, char buf[26]);
|
||||||
|
|
||||||
|
/* Convert broken-down time back into UNIX time. */
|
||||||
|
time_t mktime(struct tm* tm);
|
||||||
|
|
||||||
/* Format a string representation of broken-down time using a format string. */
|
/* Format a string representation of broken-down time using a format string. */
|
||||||
size_t strftime(char* buf, size_t max, const char* format, const struct tm* tm);
|
size_t strftime(char* buf, size_t max, const char* format, const struct tm* tm);
|
||||||
|
|
||||||
|
/* Return the difference in seconds between two times. */
|
||||||
|
double difftime(time_t a, time_t b);
|
||||||
|
|
||||||
|
/* Estimate the CPU time used by a process. */
|
||||||
|
clock_t clock(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -190,6 +190,15 @@ extern "C"
|
|||||||
/* Truncate a file to a specific length. */
|
/* Truncate a file to a specific length. */
|
||||||
int ftruncate(int fd, size_t size);
|
int ftruncate(int fd, size_t size);
|
||||||
|
|
||||||
|
/* Return the system page size. */
|
||||||
|
int getpagesize(void);
|
||||||
|
|
||||||
|
/* Schedule an alarm signal. */
|
||||||
|
unsigned int alarm(unsigned int seconds);
|
||||||
|
|
||||||
|
/* Restrict system operations. */
|
||||||
|
int pledge(const char* promises, const char* execpromises);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/* wchar.h: Wide-character string manipulation functions. */
|
||||||
|
|
||||||
|
#ifndef _WCHAR_H
|
||||||
|
#define _WCHAR_H
|
||||||
|
|
||||||
|
typedef long int wint_t;
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Calculate the size of a null-terminated wide character string. */
|
||||||
|
size_t wcslen(const wchar_t* str);
|
||||||
|
|
||||||
|
/* Compare two null-terminated wide character strings. */
|
||||||
|
int wcscmp(const wchar_t* a, const wchar_t* b);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,11 +1,13 @@
|
|||||||
#include <bits/errno-return.h>
|
#include <bits/errno-return.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <luna/HashTable.h>
|
||||||
#include <luna/ScopeGuard.h>
|
#include <luna/ScopeGuard.h>
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
extern "C" char** environ;
|
extern "C" char** environ;
|
||||||
Vector<char*> g_dynamic_env = {};
|
Vector<char*> g_dynamic_env = {};
|
||||||
|
HashTable<char*> g_dynamic_vars = {};
|
||||||
bool env_is_dynamic { false };
|
bool env_is_dynamic { false };
|
||||||
|
|
||||||
/* If an environment variable matching key is found, stores its value in value and returns its index. Otherwise,
|
/* If an environment variable matching key is found, stores its value in value and returns its index. Otherwise,
|
||||||
@ -41,22 +43,24 @@ static isize _findenv(const char* key, char** value)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_if_needed(char* element)
|
||||||
|
{
|
||||||
|
if (g_dynamic_vars.try_find(element))
|
||||||
|
{
|
||||||
|
g_dynamic_vars.try_remove(element);
|
||||||
|
free(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Move environ to a heap-allocated array. */
|
/* Move environ to a heap-allocated array. */
|
||||||
static Result<void> _try_move_env()
|
static Result<void> _try_move_env()
|
||||||
{
|
{
|
||||||
char** env = environ;
|
char** env = environ;
|
||||||
g_dynamic_env.clear();
|
g_dynamic_env.clear();
|
||||||
auto guard = make_scope_guard([] {
|
|
||||||
for (auto element : g_dynamic_env)
|
|
||||||
{
|
|
||||||
if (element) free(element);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!env)
|
if (!env)
|
||||||
{
|
{
|
||||||
TRY(g_dynamic_env.try_append(nullptr));
|
TRY(g_dynamic_env.try_append(nullptr));
|
||||||
guard.deactivate();
|
|
||||||
env_is_dynamic = true;
|
env_is_dynamic = true;
|
||||||
environ = g_dynamic_env.data();
|
environ = g_dynamic_env.data();
|
||||||
return {};
|
return {};
|
||||||
@ -64,18 +68,12 @@ static Result<void> _try_move_env()
|
|||||||
|
|
||||||
while (*env)
|
while (*env)
|
||||||
{
|
{
|
||||||
char* ptr = strdup(*(env++));
|
char* ptr = *(env++);
|
||||||
if (!ptr) return err(errno);
|
|
||||||
|
|
||||||
auto ptr_guard = make_scope_guard([=] { free(ptr); });
|
|
||||||
TRY(g_dynamic_env.try_append(ptr));
|
TRY(g_dynamic_env.try_append(ptr));
|
||||||
ptr_guard.deactivate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(g_dynamic_env.try_append(nullptr));
|
TRY(g_dynamic_env.try_append(nullptr));
|
||||||
|
|
||||||
guard.deactivate();
|
|
||||||
|
|
||||||
env_is_dynamic = true;
|
env_is_dynamic = true;
|
||||||
environ = g_dynamic_env.data();
|
environ = g_dynamic_env.data();
|
||||||
|
|
||||||
@ -105,7 +103,7 @@ static void _check_dynamic_env()
|
|||||||
{
|
{
|
||||||
for (auto element : g_dynamic_env)
|
for (auto element : g_dynamic_env)
|
||||||
{
|
{
|
||||||
if (element) free(element);
|
if (element) free_if_needed(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +120,7 @@ extern "C"
|
|||||||
{
|
{
|
||||||
for (auto element : g_dynamic_env)
|
for (auto element : g_dynamic_env)
|
||||||
{
|
{
|
||||||
if (element) free(element);
|
if (element) free_if_needed(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dynamic_env.clear();
|
g_dynamic_env.clear();
|
||||||
@ -152,9 +150,11 @@ extern "C"
|
|||||||
if (_move_env() < 0) return -1;
|
if (_move_env() < 0) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dynamic_env.remove_at(index);
|
char* p = g_dynamic_env.remove_at(index);
|
||||||
_update_env();
|
_update_env();
|
||||||
|
|
||||||
|
free_if_needed(p);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,12 +188,14 @@ extern "C"
|
|||||||
|
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
free(environ[index]);
|
free_if_needed(environ[index]);
|
||||||
environ[index] = str;
|
environ[index] = str;
|
||||||
guard.deactivate();
|
guard.deactivate();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRY_OR_SET_ERRNO(g_dynamic_vars.try_set(str), int, -1);
|
||||||
|
|
||||||
// Add a new NULL at the end of the array and replace the previous one with our string.
|
// Add a new NULL at the end of the array and replace the previous one with our string.
|
||||||
index = g_dynamic_env.size() - 1;
|
index = g_dynamic_env.size() - 1;
|
||||||
|
|
||||||
@ -206,6 +208,43 @@ extern "C"
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int putenv(char* string)
|
||||||
|
{
|
||||||
|
char* p = strchr(string, '=');
|
||||||
|
if (!p) return unsetenv(string);
|
||||||
|
size_t key_len = p - string;
|
||||||
|
|
||||||
|
char* key = strndup(string, key_len);
|
||||||
|
auto guard = make_scope_guard([key] { free(key); });
|
||||||
|
|
||||||
|
auto index = _findenv(key, nullptr);
|
||||||
|
|
||||||
|
_check_dynamic_env();
|
||||||
|
|
||||||
|
if (!env_is_dynamic)
|
||||||
|
{
|
||||||
|
if (_move_env() < 0) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
free_if_needed(environ[index]);
|
||||||
|
environ[index] = string;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new NULL at the end of the array and replace the previous one with our string.
|
||||||
|
index = g_dynamic_env.size() - 1;
|
||||||
|
|
||||||
|
TRY_OR_SET_ERRNO(g_dynamic_env.try_append(nullptr), int, -1);
|
||||||
|
guard.deactivate();
|
||||||
|
_update_env();
|
||||||
|
|
||||||
|
environ[index] = string;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char* getenv(const char* key)
|
char* getenv(const char* key)
|
||||||
{
|
{
|
||||||
char* result;
|
char* result;
|
||||||
|
@ -1,6 +1,30 @@
|
|||||||
|
#include <limits.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
static char s_default_locale[] = "C";
|
static char s_default_locale[] = "C";
|
||||||
|
static char s_empty_string[] = "";
|
||||||
|
static char s_decimal_point[] = ".";
|
||||||
|
|
||||||
|
static struct lconv s_lconv = {
|
||||||
|
.decimal_point = s_decimal_point,
|
||||||
|
.thousands_sep = s_empty_string,
|
||||||
|
.grouping = s_empty_string,
|
||||||
|
.int_curr_symbol = s_empty_string,
|
||||||
|
.currency_symbol = s_empty_string,
|
||||||
|
.mon_decimal_point = s_empty_string,
|
||||||
|
.mon_thousands_sep = s_empty_string,
|
||||||
|
.mon_grouping = s_empty_string,
|
||||||
|
.positive_sign = s_empty_string,
|
||||||
|
.negative_sign = s_empty_string,
|
||||||
|
.int_frac_digits = CHAR_MAX,
|
||||||
|
.frac_digits = CHAR_MAX,
|
||||||
|
.p_cs_precedes = CHAR_MAX,
|
||||||
|
.p_sep_by_space = CHAR_MAX,
|
||||||
|
.n_cs_precedes = CHAR_MAX,
|
||||||
|
.n_sep_by_space = CHAR_MAX,
|
||||||
|
.p_sign_posn = CHAR_MAX,
|
||||||
|
.n_sign_posn = CHAR_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -9,4 +33,9 @@ extern "C"
|
|||||||
// FIXME: Set the current locale if <locale> is not NULL.
|
// FIXME: Set the current locale if <locale> is not NULL.
|
||||||
return s_default_locale;
|
return s_default_locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct lconv* localeconv(void)
|
||||||
|
{
|
||||||
|
return &s_lconv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
106
libc/src/math.cpp
Normal file
106
libc/src/math.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// FIXME: Provide our own definitions instead of relying on the compiler's builtins.
|
||||||
|
|
||||||
|
#define WRAP_AROUND_BUILTIN(name) \
|
||||||
|
double name(double val) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name(val); \
|
||||||
|
} \
|
||||||
|
float name##f(float val) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##f(val); \
|
||||||
|
} \
|
||||||
|
long double name##l(long double val) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##l(val); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WRAP_AROUND_BUILTIN2(name) \
|
||||||
|
double name(double val1, double val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name(val1, val2); \
|
||||||
|
} \
|
||||||
|
float name##f(float val1, float val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##f(val1, val2); \
|
||||||
|
} \
|
||||||
|
long double name##l(long double val1, long double val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##l(val1, val2); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WRAP_AROUND_BUILTIN_WITH_PARAMETER_TYPE(name, type) \
|
||||||
|
double name(double val1, type val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name(val1, val2); \
|
||||||
|
} \
|
||||||
|
float name##f(float val1, type val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##f(val1, val2); \
|
||||||
|
} \
|
||||||
|
long double name##l(long double val1, type val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##l(val1, val2); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WRAP_AROUND_BUILTIN_WITH_POINTER(name) \
|
||||||
|
double name(double val1, double* val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name(val1, val2); \
|
||||||
|
} \
|
||||||
|
float name##f(float val1, float* val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##f(val1, val2); \
|
||||||
|
} \
|
||||||
|
long double name##l(long double val1, long double* val2) \
|
||||||
|
{ \
|
||||||
|
return __builtin_##name##l(val1, val2); \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
WRAP_AROUND_BUILTIN(cos);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(sin);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(tan);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(acos);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(asin);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(atan);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(cosh);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(sinh);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(tanh);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(log);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(exp);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(sqrt);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(fabs);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(floor);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(ceil);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN(log10);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN2(fmod);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN2(pow);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN2(atan2);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN_WITH_PARAMETER_TYPE(frexp, int*);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN_WITH_PARAMETER_TYPE(ldexp, int);
|
||||||
|
|
||||||
|
WRAP_AROUND_BUILTIN_WITH_POINTER(modf);
|
||||||
|
}
|
@ -752,4 +752,13 @@ extern "C"
|
|||||||
{
|
{
|
||||||
setvbuf(stream, NULL, _IOLBF, 0);
|
setvbuf(stream, NULL, _IOLBF, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rename(const char* oldpath, const char* newpath)
|
||||||
|
{
|
||||||
|
// FIXME: Implement this atomically in-kernel.
|
||||||
|
unlink(newpath);
|
||||||
|
if (link(oldpath, newpath) < 0) return -1;
|
||||||
|
unlink(oldpath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,12 @@ extern "C"
|
|||||||
return strcmp(a, b);
|
return strcmp(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t strxfrm(char* dest, const char* src, size_t n)
|
||||||
|
{
|
||||||
|
strncpy(dest, src, n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
char* strerror(int errnum)
|
char* strerror(int errnum)
|
||||||
{
|
{
|
||||||
return const_cast<char*>(error_string(errnum));
|
return const_cast<char*>(error_string(errnum));
|
||||||
|
@ -11,13 +11,13 @@ extern "C"
|
|||||||
__errno_return(rc, int);
|
__errno_return(rc, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bind(int sockfd, struct sockaddr* addr, socklen_t addrlen)
|
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_bind, sockfd, addr, addrlen);
|
long rc = syscall(SYS_bind, sockfd, addr, addrlen);
|
||||||
__errno_return(rc, int);
|
__errno_return(rc, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
int connect(int sockfd, struct sockaddr* addr, socklen_t addrlen)
|
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_connect, sockfd, addr, addrlen);
|
long rc = syscall(SYS_connect, sockfd, addr, addrlen);
|
||||||
__errno_return(rc, int);
|
__errno_return(rc, int);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <luna/Format.h>
|
#include <luna/Format.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -31,6 +32,13 @@ static int day_of_week(int year, int mon, int day)
|
|||||||
return (year + year / 4 - year / 100 + year / 400 + t[mon - 1] + day) % 7;
|
return (year + year / 4 - year / 100 + year / 400 + t[mon - 1] + day) % 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
|
||||||
|
static constexpr u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, u64 sec)
|
||||||
|
{
|
||||||
|
return sec + min * 60 + hour * 3600 + yday * 86400 + (year - 70) * 31536000 + ((year - 69) / 4) * 86400 -
|
||||||
|
((year - 1) / 100) * 86400 + ((year + 299) / 400) * 86400;
|
||||||
|
}
|
||||||
|
|
||||||
static void time_to_struct_tm(time_t time, struct tm* result)
|
static void time_to_struct_tm(time_t time, struct tm* result)
|
||||||
{
|
{
|
||||||
result->tm_isdst = 0; // No DST/timezone support for now.
|
result->tm_isdst = 0; // No DST/timezone support for now.
|
||||||
@ -167,4 +175,29 @@ extern "C"
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t mktime(struct tm* tm)
|
||||||
|
{
|
||||||
|
// FIXME: Check if the tm structure is valid.
|
||||||
|
time_t result = broken_down_to_unix(tm->tm_year, make_yday(tm->tm_year, tm->tm_mon + 1) + (tm->tm_mday - 1),
|
||||||
|
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||||
|
|
||||||
|
tm->tm_yday = make_yday(tm->tm_year + 1900, tm->tm_mon + 1) + (tm->tm_mday - 1);
|
||||||
|
tm->tm_wday = day_of_week(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double difftime(time_t a, time_t b)
|
||||||
|
{
|
||||||
|
return (double)(a - b);
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t clock(void)
|
||||||
|
{
|
||||||
|
struct rusage ru;
|
||||||
|
if (getrusage(RUSAGE_SELF, &ru) < 0) return (clock_t)-1;
|
||||||
|
|
||||||
|
return ru.ru_utime.tv_sec * CLOCKS_PER_SEC + ru.ru_utime.tv_usec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
@ -510,4 +511,20 @@ extern "C"
|
|||||||
long rc = syscall(SYS_ftruncate, fd, size);
|
long rc = syscall(SYS_ftruncate, fd, size);
|
||||||
__errno_return(rc, int);
|
__errno_return(rc, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getpagesize(void)
|
||||||
|
{
|
||||||
|
return PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int alarm(unsigned int seconds)
|
||||||
|
{
|
||||||
|
return (unsigned int)syscall(SYS_alarm, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pledge(const char* promises, const char* execpromises)
|
||||||
|
{
|
||||||
|
long rc = syscall(SYS_pledge, promises, execpromises);
|
||||||
|
__errno_return(rc, int);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
||||||
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \
|
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \
|
||||||
_e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) \
|
_e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) \
|
||||||
_e(truncate) _e(ftruncate) _e(utimensat)
|
_e(truncate) _e(ftruncate) _e(utimensat) _e(alarm) _e(pledge)
|
||||||
|
|
||||||
enum Syscalls
|
enum Syscalls
|
||||||
{
|
{
|
||||||
|
@ -1,62 +1,70 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define EPERM 1 // Operation not permitted
|
#define EPERM 1 // Operation not permitted
|
||||||
#define ENOENT 2 // No such file or directory
|
#define ENOENT 2 // No such file or directory
|
||||||
#define ESRCH 3 // No such process
|
#define ESRCH 3 // No such process
|
||||||
#define EINTR 4 // Interrupted system call
|
#define EINTR 4 // Interrupted system call
|
||||||
#define EIO 5 // Input/output error
|
#define EIO 5 // Input/output error
|
||||||
#define ENXIO 6 // No such device or address
|
#define ENXIO 6 // No such device or address
|
||||||
#define E2BIG 7 // Argument list too long
|
#define E2BIG 7 // Argument list too long
|
||||||
#define ENOEXEC 8 // Exec format error
|
#define ENOEXEC 8 // Exec format error
|
||||||
#define EBADF 9 // Bad file descriptor
|
#define EBADF 9 // Bad file descriptor
|
||||||
#define ECHILD 10 // No child processes
|
#define ECHILD 10 // No child processes
|
||||||
#define EAGAIN 11 // Resource temporarily unavailable
|
#define EAGAIN 11 // Resource temporarily unavailable
|
||||||
#define EWOULDBLOCK 11 // Resource temporarily unavailable
|
#define EWOULDBLOCK 11 // Resource temporarily unavailable
|
||||||
#define ENOMEM 12 // Cannot allocate memory
|
#define ENOMEM 12 // Cannot allocate memory
|
||||||
#define EACCES 13 // Permission denied
|
#define EACCES 13 // Permission denied
|
||||||
#define EFAULT 14 // Bad address
|
#define EFAULT 14 // Bad address
|
||||||
#define ENOTBLK 15 // Block device required
|
#define ENOTBLK 15 // Block device required
|
||||||
#define EBUSY 16 // Device or resource busy
|
#define EBUSY 16 // Device or resource busy
|
||||||
#define EEXIST 17 // File exists
|
#define EEXIST 17 // File exists
|
||||||
#define EXDEV 18 // Invalid cross-device link
|
#define EXDEV 18 // Invalid cross-device link
|
||||||
#define ENODEV 19 // No such device
|
#define ENODEV 19 // No such device
|
||||||
#define ENOTDIR 20 // Not a directory
|
#define ENOTDIR 20 // Not a directory
|
||||||
#define EISDIR 21 // Is a directory
|
#define EISDIR 21 // Is a directory
|
||||||
#define EINVAL 22 // Invalid argument
|
#define EINVAL 22 // Invalid argument
|
||||||
#define ENFILE 23 // Too many open files in system
|
#define ENFILE 23 // Too many open files in system
|
||||||
#define EMFILE 24 // Too many open files
|
#define EMFILE 24 // Too many open files
|
||||||
#define ENOTTY 25 // Inappropriate ioctl for device
|
#define ENOTTY 25 // Inappropriate ioctl for device
|
||||||
#define ETXTBSY 26 // Text file busy
|
#define ETXTBSY 26 // Text file busy
|
||||||
#define EFBIG 27 // File too large
|
#define EFBIG 27 // File too large
|
||||||
#define ENOSPC 28 // No space left on device
|
#define ENOSPC 28 // No space left on device
|
||||||
#define ESPIPE 29 // Illegal seek
|
#define ESPIPE 29 // Illegal seek
|
||||||
#define EROFS 30 // Read-only file system
|
#define EROFS 30 // Read-only file system
|
||||||
#define EMLINK 31 // Too many links
|
#define EMLINK 31 // Too many links
|
||||||
#define EPIPE 32 // Broken pipe
|
#define EPIPE 32 // Broken pipe
|
||||||
#define EDOM 33 // Numerical argument out of domain
|
#define EDOM 33 // Numerical argument out of domain
|
||||||
#define ERANGE 34 // Numerical result out of range
|
#define ERANGE 34 // Numerical result out of range
|
||||||
#define EDEADLK 35 // Resource deadlock avoided
|
#define EDEADLK 35 // Resource deadlock avoided
|
||||||
#define ENAMETOOLONG 36 // File name too long
|
#define ENAMETOOLONG 36 // File name too long
|
||||||
#define ENOLCK 37 // No locks available
|
#define ENOLCK 37 // No locks available
|
||||||
#define ENOSYS 38 // Function not implemented
|
#define ENOSYS 38 // Function not implemented
|
||||||
#define ENOTEMPTY 39 // Directory not empty
|
#define ENOTEMPTY 39 // Directory not empty
|
||||||
#define ELOOP 40 // Too many levels of symbolic links
|
#define ELOOP 40 // Too many levels of symbolic links
|
||||||
#define ENOMSG 42 // No message of desired type
|
#define ENOMSG 42 // No message of desired type
|
||||||
#define EOVERFLOW 75 // Value too large for defined data type
|
#define EOVERFLOW 75 // Value too large for defined data type
|
||||||
#define EILSEQ 84 // Invalid or incomplete multibyte or wide character
|
#define EILSEQ 84 // Invalid or incomplete multibyte or wide character
|
||||||
#define ENOTSOCK 88 // Socket operation on non-socket
|
#define ENOTSOCK 88 // Socket operation on non-socket
|
||||||
#define EDESTADDRREQ 89 // Destination address required
|
#define EDESTADDRREQ 89 // Destination address required
|
||||||
#define EPROTOTYPE 91 // Protocol wrong type for socket
|
#define EMSGSIZE 90 // Message too long
|
||||||
#define ENOTSUP 95 // Operation not supported
|
#define EPROTOTYPE 91 // Protocol wrong type for socket
|
||||||
#define EOPNOTSUPP 95 // Operation not supported
|
#define ENOPROTOOPT 92 // Protocol not available
|
||||||
#define EAFNOSUPPORT 97 // Address family not supported by protocol
|
#define EPROTONOSUPPORT 93 // Protocol not supported
|
||||||
#define EADDRINUSE 98 // Address already in use
|
#define ENOTSUP 95 // Operation not supported
|
||||||
#define EADDRNOTAVAIL 99 // Cannot assign requested address
|
#define EOPNOTSUPP 95 // Operation not supported
|
||||||
#define ENETRESET 102 // Network dropped connection on reset
|
#define EAFNOSUPPORT 97 // Address family not supported by protocol
|
||||||
#define ECONNRESET 104 // Connection reset by peer
|
#define EADDRINUSE 98 // Address already in use
|
||||||
#define EISCONN 106 // Transport endpoint is already connected
|
#define EADDRNOTAVAIL 99 // Cannot assign requested address
|
||||||
#define ENOTCONN 107 // Transport endpoint is not connected
|
#define ENETDOWN 100 // Network is down
|
||||||
#define ETIMEDOUT 110 // Connection timed out
|
#define ENETUNREACH 101 // Network is unreachable
|
||||||
#define ECONNREFUSED 111 // Connection refused
|
#define ENETRESET 102 // Network dropped connection on reset
|
||||||
#define EALREADY 114 // Operation already in progress
|
#define ECONNABORTED 103 // Software caused connection abort
|
||||||
#define EINPROGRESS 115 // Operation now in progress
|
#define ECONNRESET 104 // Connection reset by peer
|
||||||
|
#define ENOBUFS 105 // No buffer space available
|
||||||
|
#define EISCONN 106 // Transport endpoint is already connected
|
||||||
|
#define ENOTCONN 107 // Transport endpoint is not connected
|
||||||
|
#define ETIMEDOUT 110 // Connection timed out
|
||||||
|
#define ECONNREFUSED 111 // Connection refused
|
||||||
|
#define EHOSTUNREACH 113 // No route to host
|
||||||
|
#define EALREADY 114 // Operation already in progress
|
||||||
|
#define EINPROGRESS 115 // Operation now in progress
|
||||||
|
@ -17,10 +17,14 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Otherwise, this is defined in libstdc++.
|
||||||
|
#ifdef USE_FREESTANDING
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
const nothrow_t nothrow;
|
const nothrow_t nothrow;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static constexpr int BLOCK_USED = 1 << 0;
|
static constexpr int BLOCK_USED = 1 << 0;
|
||||||
static constexpr int BLOCK_START_MEM = 1 << 1;
|
static constexpr int BLOCK_START_MEM = 1 << 1;
|
||||||
@ -417,6 +421,8 @@ void dump_heap_usage()
|
|||||||
dbgln("-- Heap memory in use: %zu bytes", alloc_used);
|
dbgln("-- Heap memory in use: %zu bytes", alloc_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, this is defined in libstdc++.
|
||||||
|
#ifdef USE_FREESTANDING
|
||||||
void* operator new(usize size, const std::nothrow_t&) noexcept
|
void* operator new(usize size, const std::nothrow_t&) noexcept
|
||||||
{
|
{
|
||||||
return malloc_impl(size).value_or(nullptr);
|
return malloc_impl(size).value_or(nullptr);
|
||||||
@ -446,3 +452,4 @@ void operator delete[](void* p, usize) noexcept
|
|||||||
{
|
{
|
||||||
free_impl(p);
|
free_impl(p);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -63,6 +63,14 @@ const char* error_string(int error)
|
|||||||
case EADDRNOTAVAIL: return "Cannot assign requested address";
|
case EADDRNOTAVAIL: return "Cannot assign requested address";
|
||||||
case ECONNREFUSED: return "Connection refused";
|
case ECONNREFUSED: return "Connection refused";
|
||||||
case EINPROGRESS: return "Operation now in progress";
|
case EINPROGRESS: return "Operation now in progress";
|
||||||
|
case ECONNABORTED: return "Software caused connection abort";
|
||||||
|
case EHOSTUNREACH: return "No route to host";
|
||||||
|
case EMSGSIZE: return "Message too long";
|
||||||
|
case ENETDOWN: return "Network is down";
|
||||||
|
case ENETUNREACH: return "Network is unreachable";
|
||||||
|
case ENOBUFS: return "No buffer space available";
|
||||||
|
case ENOPROTOOPT: return "Protocol not available";
|
||||||
|
case EPROTONOSUPPORT: return "Protocol not supported";
|
||||||
default: return "Unknown error";
|
default: return "Unknown error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,6 +140,14 @@ const char* error_name(int error)
|
|||||||
ERROR(EADDRNOTAVAIL);
|
ERROR(EADDRNOTAVAIL);
|
||||||
ERROR(ECONNREFUSED);
|
ERROR(ECONNREFUSED);
|
||||||
ERROR(EINPROGRESS);
|
ERROR(EINPROGRESS);
|
||||||
|
ERROR(ECONNABORTED);
|
||||||
|
ERROR(EHOSTUNREACH);
|
||||||
|
ERROR(EMSGSIZE);
|
||||||
|
ERROR(ENETDOWN);
|
||||||
|
ERROR(ENETUNREACH);
|
||||||
|
ERROR(ENOBUFS);
|
||||||
|
ERROR(ENOPROTOOPT);
|
||||||
|
ERROR(EPROTONOSUPPORT);
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ set(SOURCES
|
|||||||
src/Path.cpp
|
src/Path.cpp
|
||||||
src/Mode.cpp
|
src/Mode.cpp
|
||||||
src/Prompt.cpp
|
src/Prompt.cpp
|
||||||
|
src/Security.cpp
|
||||||
src/LocalServer.cpp
|
src/LocalServer.cpp
|
||||||
src/LocalClient.cpp
|
src/LocalClient.cpp
|
||||||
)
|
)
|
||||||
|
48
libos/include/os/Security.h
Normal file
48
libos/include/os/Security.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @file Security.h
|
||||||
|
* @author apio (cloudapio.eu)
|
||||||
|
* @brief Functions to restrict process operations.
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023, the Luna authors.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <luna/Result.h>
|
||||||
|
|
||||||
|
namespace os
|
||||||
|
{
|
||||||
|
namespace Security
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Restrict system operations.
|
||||||
|
*
|
||||||
|
* The pledge() call, borrowed from OpenBSD, is a simple function to sandbox a process effectively.
|
||||||
|
*
|
||||||
|
* Syscalls are divided into a number of categories ("promises"), the following are the ones implemented on
|
||||||
|
* Luna: stdio rpath wpath cpath fattr chown unix tty proc exec prot_exec id mount signal host error
|
||||||
|
*
|
||||||
|
* The way pledge() works is: the process "tells" the kernel which subset of functions it will use, and if it
|
||||||
|
* suddenly uses something it has not promised (probably because the process was hacked, using ROP or something
|
||||||
|
* else) the kernel kills the process immediately with an uncatchable SIGABRT. Alternatively, if the process has
|
||||||
|
* pledged the "error" promise, the call will fail with ENOSYS.
|
||||||
|
*
|
||||||
|
* Pledges are not inherited across exec, although one may specify another set of promises to apply on the next
|
||||||
|
* execve() call. Thus, pledge() is not a way to restrict untrusted programs (unless the "exec" pledge is
|
||||||
|
* removed), but more of a way to protect trusted local programs from vulnerabilities.
|
||||||
|
*
|
||||||
|
* One may call pledge() several times, but only to remove promises, not to add them.
|
||||||
|
*
|
||||||
|
* A typical call to pledge would look like this:
|
||||||
|
*
|
||||||
|
* TRY(os::Security::pledge("stdio rpath wpath unix proc", nullptr));
|
||||||
|
*
|
||||||
|
* @param promises The promises to apply immediately, separated by spaces. If empty, the process may only call
|
||||||
|
* _exit(2). If NULL, the promises are not changed.
|
||||||
|
* @param execpromises The promises to apply on the next call to execve(2), separated by spaces. If empty, the
|
||||||
|
* process may only call _exit(2). If NULL, the execpromises are not changed.
|
||||||
|
* @return Result<void> Whether the operation succeded.
|
||||||
|
*/
|
||||||
|
Result<void> pledge(const char* promises, const char* execpromises);
|
||||||
|
}
|
||||||
|
}
|
22
libos/src/Security.cpp
Normal file
22
libos/src/Security.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* @file Security.cpp
|
||||||
|
* @author apio (cloudapio.eu)
|
||||||
|
* @brief Functions to restrict process operations.
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023, the Luna authors.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <os/Security.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace os::Security
|
||||||
|
{
|
||||||
|
Result<void> pledge(const char* promises, const char* execpromises)
|
||||||
|
{
|
||||||
|
int rc = ::pledge(promises, execpromises);
|
||||||
|
if (rc < 0) return err(errno);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
@ -13,8 +13,11 @@ Name | Version | Description | URL
|
|||||||
---|---|--- | ---
|
---|---|--- | ---
|
||||||
bc | 6.6.0 | An implementation of the POSIX bc calculator | https://github.com/gavinhoward/bc
|
bc | 6.6.0 | An implementation of the POSIX bc calculator | https://github.com/gavinhoward/bc
|
||||||
binutils | 2.39 | The GNU suite of binary utilities | https://www.gnu.org/software/binutils
|
binutils | 2.39 | The GNU suite of binary utilities | https://www.gnu.org/software/binutils
|
||||||
|
gmp | 6.3.0 | The GNU Multiple Precision Arithmetic Library | https://gmplib.org
|
||||||
minitar | 1.7.5 | Tiny and easy-to-use C library to read/write tar archives | https://git.cloudapio.eu/apio/minitar
|
minitar | 1.7.5 | Tiny and easy-to-use C library to read/write tar archives | https://git.cloudapio.eu/apio/minitar
|
||||||
nasm | 2.16.01 | An assembler for the x86 CPU architecture | https://nasm.us
|
mpc | 1.3.1 | The GNU Multiple Precision Complex Library | https://www.multiprecision.org
|
||||||
|
mpfr | 4.2.0 | The GNU Multiple Precision Floating-Point Reliable Library | https://mpfr.org
|
||||||
|
nasm | 2.16.01 | An assembler for the x86 CPU architecture | https://nasm.us
|
||||||
|
|
||||||
## Installing ports
|
## Installing ports
|
||||||
|
|
||||||
@ -48,10 +51,13 @@ The `name` variable should be set to the name of the ported program.
|
|||||||
|
|
||||||
The `version` variable should be set to the currently ported version of the program.
|
The `version` variable should be set to the currently ported version of the program.
|
||||||
|
|
||||||
|
If the program has dependencies on any other library/program, the `dependencies` field should be set to a list of those. Note that these dependencies must also be ported to Luna! Thus, when porting programs, you'll have to start with porting their dependencies (unless those have already been ported).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```
|
```
|
||||||
name="example"
|
name="example"
|
||||||
version="1.0.0"
|
version="1.0.0"
|
||||||
|
dependencies=(foo bar)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Download options
|
#### Download options
|
||||||
|
@ -10,6 +10,7 @@ sha256sum="d12ea6f239f1ffe3533ea11ad6e224ffcb89eb5d01bbea589e9158780fa11f10"
|
|||||||
|
|
||||||
# Build instructions
|
# Build instructions
|
||||||
default_build_make=true
|
default_build_make=true
|
||||||
|
default_install_make=true
|
||||||
|
|
||||||
do_patch()
|
do_patch()
|
||||||
{
|
{
|
||||||
@ -18,13 +19,5 @@ do_patch()
|
|||||||
|
|
||||||
do_configure()
|
do_configure()
|
||||||
{
|
{
|
||||||
$srcdir/configure --host=$LUNA_ARCH-luna --disable-nls --disable-werror --enable-warn-rwx-segments=no --prefix=/usr --enable-gold=no --enable-ld=yes --enable-gprofng=no
|
$srcdir/configure --host=$LUNA_ARCH-luna --with-build-sysroot=$LUNA_BASE --disable-nls --disable-werror --enable-warn-rwx-segments=no --prefix=/usr --enable-gold=no --enable-ld=yes --enable-gprofng=no
|
||||||
}
|
|
||||||
|
|
||||||
do_install()
|
|
||||||
{
|
|
||||||
make install
|
|
||||||
|
|
||||||
cd $installdir/usr/bin
|
|
||||||
$LUNA_ARCH-luna-strip size objdump ar strings ranlib objcopy addr2line readelf elfedit nm strip c++filt as gprof ld.bfd ld
|
|
||||||
}
|
}
|
||||||
|
18
ports/gmp/PACKAGE
Normal file
18
ports/gmp/PACKAGE
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Basic information
|
||||||
|
name="gmp"
|
||||||
|
version="6.3.0"
|
||||||
|
|
||||||
|
# Download options
|
||||||
|
format="tar"
|
||||||
|
url="https://gmplib.org/download/gmp/gmp-$version.tar.xz"
|
||||||
|
output="gmp-$version.tar.xz"
|
||||||
|
sha256sum="a3c2b80201b89e68616f4ad30bc66aee4927c3ce50e33929ca819d5c43538898"
|
||||||
|
|
||||||
|
# Build instructions
|
||||||
|
default_build_make=true
|
||||||
|
default_install_make=true
|
||||||
|
|
||||||
|
do_configure()
|
||||||
|
{
|
||||||
|
$srcdir/configure --enable-shared=no --with-gnu-ld --host=$LUNA_ARCH-luna --prefix=/usr
|
||||||
|
}
|
19
ports/mpc/PACKAGE
Normal file
19
ports/mpc/PACKAGE
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Basic information
|
||||||
|
name="mpc"
|
||||||
|
version="1.3.1"
|
||||||
|
dependencies=(gmp mpfr)
|
||||||
|
|
||||||
|
# Download options
|
||||||
|
format="tar"
|
||||||
|
url="https://ftp.gnu.org/gnu/mpc/mpc-$version.tar.gz"
|
||||||
|
output="mpc-$version.tar.gz"
|
||||||
|
sha256sum="ab642492f5cf882b74aa0cb730cd410a81edcdbec895183ce930e706c1c759b8"
|
||||||
|
|
||||||
|
# Build instructions
|
||||||
|
default_build_make=true
|
||||||
|
default_install_make=true
|
||||||
|
|
||||||
|
do_configure()
|
||||||
|
{
|
||||||
|
$srcdir/configure --enable-shared=no --with-gnu-ld --host=$LUNA_ARCH-luna --prefix=/usr
|
||||||
|
}
|
19
ports/mpfr/PACKAGE
Normal file
19
ports/mpfr/PACKAGE
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Basic information
|
||||||
|
name="mpfr"
|
||||||
|
version="4.2.0"
|
||||||
|
dependencies=(gmp)
|
||||||
|
|
||||||
|
# Download options
|
||||||
|
format="tar"
|
||||||
|
url="https://www.mpfr.org/mpfr-current/mpfr-$version.tar.gz"
|
||||||
|
output="mpfr-$version.tar.gz"
|
||||||
|
sha256sum="f1cc1c6bb14d18f0c61cc416e083f5e697b6e0e3cf9630b9b33e8e483fc960f0"
|
||||||
|
|
||||||
|
# Build instructions
|
||||||
|
default_build_make=true
|
||||||
|
default_install_make=true
|
||||||
|
|
||||||
|
do_configure()
|
||||||
|
{
|
||||||
|
$srcdir/configure --enable-shared=no --with-gnu-ld --host=$LUNA_ARCH-luna --prefix=/usr
|
||||||
|
}
|
@ -72,6 +72,35 @@ TestResult test_setenv_before_and_after_manual_environ_modification()
|
|||||||
test_success;
|
test_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestResult test_putenv()
|
||||||
|
{
|
||||||
|
clearenv();
|
||||||
|
|
||||||
|
char lit[] = "NAME=VALUE";
|
||||||
|
|
||||||
|
validate(putenv(lit) == 0);
|
||||||
|
|
||||||
|
char* value = getenv("NAME");
|
||||||
|
validate(value && !strcmp(value, "VALUE"));
|
||||||
|
|
||||||
|
lit[0] = 'F';
|
||||||
|
|
||||||
|
value = getenv("NAME");
|
||||||
|
validate(!value);
|
||||||
|
|
||||||
|
value = getenv("FAME");
|
||||||
|
validate(value && !strcmp(value, "VALUE"));
|
||||||
|
|
||||||
|
validate(unsetenv("FAME") == 0);
|
||||||
|
|
||||||
|
value = getenv("FAME");
|
||||||
|
validate(!value);
|
||||||
|
|
||||||
|
validate(!strcmp(lit, "FAME=VALUE"));
|
||||||
|
|
||||||
|
test_success;
|
||||||
|
}
|
||||||
|
|
||||||
Result<void> test_main()
|
Result<void> test_main()
|
||||||
{
|
{
|
||||||
test_prelude;
|
test_prelude;
|
||||||
@ -80,6 +109,7 @@ Result<void> test_main()
|
|||||||
run_test(test_setenv_dont_overwrite);
|
run_test(test_setenv_dont_overwrite);
|
||||||
run_test(test_unsetenv);
|
run_test(test_unsetenv);
|
||||||
run_test(test_setenv_before_and_after_manual_environ_modification);
|
run_test(test_setenv_before_and_after_manual_environ_modification);
|
||||||
|
run_test(test_putenv);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ export LUNA_BASE=${LUNA_BASE:-$LUNA_ROOT/base}
|
|||||||
[ -f "$LUNA_ROOT/env-local.sh" ] && source $LUNA_ROOT/env-local.sh
|
[ -f "$LUNA_ROOT/env-local.sh" ] && source $LUNA_ROOT/env-local.sh
|
||||||
|
|
||||||
export LUNA_ARCH=${LUNA_ARCH:-x86_64}
|
export LUNA_ARCH=${LUNA_ARCH:-x86_64}
|
||||||
export PATH=$LUNA_ROOT/toolchain/$LUNA_ARCH-luna/bin:$LUNA_ROOT/toolchain/dist:$PATH
|
export PATH=$LUNA_ROOT/toolchain/$LUNA_ARCH-luna/bin:$LUNA_ROOT/toolchain/dist:$LUNA_ROOT/tools/exec/:$PATH
|
||||||
|
|
||||||
if [ "$USE_MAKE" = "1" ]
|
if [ "$USE_MAKE" = "1" ]
|
||||||
then
|
then
|
||||||
|
10
tools/exec/luna-pkg-config
Normal file
10
tools/exec/luna-pkg-config
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Fill these in appropriately:
|
||||||
|
export PKG_CONFIG_SYSROOT_DIR=$LUNA_BASE
|
||||||
|
export PKG_CONFIG_LIBDIR=$LUNA_BASE/usr/lib/pkgconfig
|
||||||
|
# TODO: If it works this should probably just be set to the empty string.
|
||||||
|
export PKG_CONFIG_PATH=$PKG_CONFIG_LIBDIR
|
||||||
|
# Use --static here if your OS only has static linking.
|
||||||
|
# TODO: Perhaps it's a bug in the libraries if their pkg-config files doesn't
|
||||||
|
# record that only static libraries were built.
|
||||||
|
exec pkg-config --static "$@"
|
110
tools/gcc.patch
110
tools/gcc.patch
@ -1,6 +1,6 @@
|
|||||||
diff --color -rN -u gcc-12.2.0/config.sub build/gcc-12.2.0/config.sub
|
diff --color -rN -u vanilla/gcc-12.2.0/config.sub gcc-12.2.0/config.sub
|
||||||
--- a/gcc-12.2.0/config.sub 2022-08-19 10:09:52.128656687 +0200
|
--- a/gcc-12.2.0/config.sub 2022-08-19 10:09:52.128656687 +0200
|
||||||
+++ b/gcc-12.2.0/config.sub 2022-10-02 11:27:45.660055384 +0200
|
+++ b/gcc-12.2.0/config.sub 2023-08-08 20:42:05.032843544 +0200
|
||||||
@@ -1723,7 +1723,7 @@
|
@@ -1723,7 +1723,7 @@
|
||||||
| hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
|
| hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
|
||||||
| sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
|
| sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
|
||||||
@ -10,9 +10,9 @@ diff --color -rN -u gcc-12.2.0/config.sub build/gcc-12.2.0/config.sub
|
|||||||
| mpw* | magic* | mmixware* | mon960* | lnews* \
|
| mpw* | magic* | mmixware* | mon960* | lnews* \
|
||||||
| amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
|
| amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
|
||||||
| aos* | aros* | cloudabi* | sortix* | twizzler* \
|
| aos* | aros* | cloudabi* | sortix* | twizzler* \
|
||||||
diff --color -rN -u gcc-12.2.0/fixincludes/mkfixinc.sh build/gcc-12.2.0/fixincludes/mkfixinc.sh
|
diff --color -rN -u vanilla/gcc-12.2.0/fixincludes/mkfixinc.sh gcc-12.2.0/fixincludes/mkfixinc.sh
|
||||||
--- a/gcc-12.2.0/fixincludes/mkfixinc.sh 2022-08-19 10:09:52.160657095 +0200
|
--- a/gcc-12.2.0/fixincludes/mkfixinc.sh 2022-08-19 10:09:52.160657095 +0200
|
||||||
+++ b/gcc-12.2.0/fixincludes/mkfixinc.sh 2022-10-02 11:27:45.662055397 +0200
|
+++ b/gcc-12.2.0/fixincludes/mkfixinc.sh 2023-08-08 20:42:05.034843561 +0200
|
||||||
@@ -12,6 +12,8 @@
|
@@ -12,6 +12,8 @@
|
||||||
# Check for special fix rules for particular targets
|
# Check for special fix rules for particular targets
|
||||||
case $machine in
|
case $machine in
|
||||||
@ -22,18 +22,18 @@ diff --color -rN -u gcc-12.2.0/fixincludes/mkfixinc.sh build/gcc-12.2.0/fixinclu
|
|||||||
i?86-*-mingw32* | \
|
i?86-*-mingw32* | \
|
||||||
x86_64-*-mingw32* | \
|
x86_64-*-mingw32* | \
|
||||||
powerpc-*-eabisim* | \
|
powerpc-*-eabisim* | \
|
||||||
diff --color -rN -u gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel build/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel
|
diff --color -rN -u vanilla/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel
|
||||||
--- a/dev/null 1970-01-01 01:00:00.000000000 +0100
|
--- a/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel 1970-01-01 01:00:00.000000000 +0100
|
||||||
+++ b/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel 2022-10-02 11:45:30.955856133 +0200
|
+++ b/gcc-12.2.0/gcc/config/i386/x86_64-luna-kernel 2023-08-08 20:42:05.038843594 +0200
|
||||||
@@ -0,0 +1,4 @@
|
@@ -0,0 +1,4 @@
|
||||||
+#Add libgcc multilib variant without red-zone requirement, for use in the kernel
|
+#Add libgcc multilib variant without red-zone requirement, for use in the kernel
|
||||||
+
|
+
|
||||||
+MULTILIB_OPTIONS += mno-red-zone
|
+MULTILIB_OPTIONS += mno-red-zone
|
||||||
+MULTILIB_DIRNAMES += no-red-zone
|
+MULTILIB_DIRNAMES += no-red-zone
|
||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
diff --color -rN -u gcc-12.2.0/gcc/config/luna.h build/gcc-12.2.0/gcc/config/luna.h
|
diff --color -rN -u vanilla/gcc-12.2.0/gcc/config/luna.h gcc-12.2.0/gcc/config/luna.h
|
||||||
--- a/dev/null 1970-01-01 01:00:00.000000000 +0100
|
--- a/gcc-12.2.0/gcc/config/luna.h 1970-01-01 01:00:00.000000000 +0100
|
||||||
+++ b/gcc-12.2.0/gcc/config/luna.h 2022-10-02 11:27:45.663055404 +0200
|
+++ b/gcc-12.2.0/gcc/config/luna.h 2023-08-08 20:42:05.040843610 +0200
|
||||||
@@ -0,0 +1,36 @@
|
@@ -0,0 +1,36 @@
|
||||||
+#undef TARGET_LUNA
|
+#undef TARGET_LUNA
|
||||||
+#define TARGET_LUNA 1
|
+#define TARGET_LUNA 1
|
||||||
@ -71,11 +71,9 @@ diff --color -rN -u gcc-12.2.0/gcc/config/luna.h build/gcc-12.2.0/gcc/config/lun
|
|||||||
+ } while (0);
|
+ } while (0);
|
||||||
+
|
+
|
||||||
+#undef LINK_SPEC
|
+#undef LINK_SPEC
|
||||||
+#define LINK_SPEC "-z max-page-size=4096"
|
diff --color -rN -u vanilla/gcc-12.2.0/gcc/config.gcc gcc-12.2.0/gcc/config.gcc
|
||||||
\ No newline at end of file
|
|
||||||
diff --color -rN -u gcc-12.2.0/gcc/config.gcc build/gcc-12.2.0/gcc/config.gcc
|
|
||||||
--- a/gcc-12.2.0/gcc/config.gcc 2022-08-19 10:09:52.552662114 +0200
|
--- a/gcc-12.2.0/gcc/config.gcc 2022-08-19 10:09:52.552662114 +0200
|
||||||
+++ b/gcc-12.2.0/gcc/config.gcc 2022-10-02 11:45:18.311797546 +0200
|
+++ b/gcc-12.2.0/gcc/config.gcc 2023-08-08 20:42:05.044843643 +0200
|
||||||
@@ -895,6 +895,12 @@
|
@@ -895,6 +895,12 @@
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -103,9 +101,9 @@ diff --color -rN -u gcc-12.2.0/gcc/config.gcc build/gcc-12.2.0/gcc/config.gcc
|
|||||||
x86_64-*-rtems*)
|
x86_64-*-rtems*)
|
||||||
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h"
|
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h"
|
||||||
;;
|
;;
|
||||||
diff --color -rN -u gcc-12.2.0/libgcc/config.host build/gcc-12.2.0/libgcc/config.host
|
diff --color -rN -u vanilla/gcc-12.2.0/libgcc/config.host gcc-12.2.0/libgcc/config.host
|
||||||
--- a/gcc-12.2.0/libgcc/config.host 2022-08-19 10:09:54.664689148 +0200
|
--- a/gcc-12.2.0/libgcc/config.host 2022-08-19 10:09:54.664689148 +0200
|
||||||
+++ b/gcc-12.2.0/libgcc/config.host 2022-10-02 11:27:45.671055461 +0200
|
+++ b/gcc-12.2.0/libgcc/config.host 2023-08-08 20:42:05.046843660 +0200
|
||||||
@@ -783,6 +783,14 @@
|
@@ -783,6 +783,14 @@
|
||||||
;;
|
;;
|
||||||
i[34567]86-*-lynxos*)
|
i[34567]86-*-lynxos*)
|
||||||
@ -121,9 +119,9 @@ diff --color -rN -u gcc-12.2.0/libgcc/config.host build/gcc-12.2.0/libgcc/config
|
|||||||
i[34567]86-*-nto-qnx*)
|
i[34567]86-*-nto-qnx*)
|
||||||
tmake_file="$tmake_file i386/t-nto t-libgcc-pic"
|
tmake_file="$tmake_file i386/t-nto t-libgcc-pic"
|
||||||
extra_parts=crtbegin.o
|
extra_parts=crtbegin.o
|
||||||
diff --color -rN -u gcc-12.2.0/libgcc/libgcov.h build/gcc-12.2.0/libgcc/libgcov.h
|
diff --color -rN -u vanilla/gcc-12.2.0/libgcc/libgcov.h gcc-12.2.0/libgcc/libgcov.h
|
||||||
--- a/gcc-12.2.0/libgcc/libgcov.h 2022-08-19 10:09:54.728689966 +0200
|
--- a/gcc-12.2.0/libgcc/libgcov.h 2022-08-19 10:09:54.728689966 +0200
|
||||||
+++ b/gcc-12.2.0/libgcc/libgcov.h 2022-10-02 11:41:48.571807335 +0200
|
+++ b/gcc-12.2.0/libgcc/libgcov.h 2023-08-08 20:42:05.048843677 +0200
|
||||||
@@ -194,6 +194,7 @@
|
@@ -194,6 +194,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -132,3 +130,79 @@ diff --color -rN -u gcc-12.2.0/libgcc/libgcov.h build/gcc-12.2.0/libgcc/libgcov.
|
|||||||
|
|
||||||
/* Structures embedded in coveraged program. The structures generated
|
/* Structures embedded in coveraged program. The structures generated
|
||||||
by write_profile must match these. */
|
by write_profile must match these. */
|
||||||
|
diff --color -rN -u vanilla/gcc-12.2.0/libstdc++-v3/acinclude.m4 gcc-12.2.0/libstdc++-v3/acinclude.m4
|
||||||
|
--- a/gcc-12.2.0/libstdc++-v3/acinclude.m4 2022-08-19 10:09:55.380698313 +0200
|
||||||
|
+++ b/gcc-12.2.0/libstdc++-v3/acinclude.m4 2023-08-08 21:08:00.777765701 +0200
|
||||||
|
@@ -1356,6 +1356,10 @@
|
||||||
|
ac_has_nanosleep=yes
|
||||||
|
ac_has_sched_yield=yes
|
||||||
|
;;
|
||||||
|
+ luna*)
|
||||||
|
+ ac_has_clock_monotonic=yes
|
||||||
|
+ ac_has_clock_realtime=yes
|
||||||
|
+ ;;
|
||||||
|
# VxWorks has nanosleep as soon as the kernel is configured with
|
||||||
|
# INCLUDE_POSIX_TIMERS, which is normally/most-often the case.
|
||||||
|
vxworks*)
|
||||||
|
@@ -2421,7 +2425,7 @@
|
||||||
|
dragonfly* | freebsd*)
|
||||||
|
enable_clocale_flag=dragonfly
|
||||||
|
;;
|
||||||
|
- openbsd*)
|
||||||
|
+ openbsd* | luna*)
|
||||||
|
enable_clocale_flag=newlib
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
diff --color -rN -u vanilla/gcc-12.2.0/libstdc++-v3/configure gcc-12.2.0/libstdc++-v3/configure
|
||||||
|
--- a/gcc-12.2.0/libstdc++-v3/configure 2022-08-19 10:09:55.416698774 +0200
|
||||||
|
+++ b/gcc-12.2.0/libstdc++-v3/configure 2023-08-09 11:34:54.810282202 +0200
|
||||||
|
@@ -16481,6 +16481,9 @@
|
||||||
|
openbsd*)
|
||||||
|
enable_clocale_flag=newlib
|
||||||
|
;;
|
||||||
|
+ luna*)
|
||||||
|
+ enable_clocale_flag=generic
|
||||||
|
+ ;;
|
||||||
|
*)
|
||||||
|
if test x"$with_newlib" = x"yes"; then
|
||||||
|
enable_clocale_flag=newlib
|
||||||
|
@@ -20493,6 +20496,10 @@
|
||||||
|
ac_has_nanosleep=yes
|
||||||
|
ac_has_sched_yield=yes
|
||||||
|
;;
|
||||||
|
+ luna*)
|
||||||
|
+ ac_has_clock_monotonic=yes
|
||||||
|
+ ac_has_clock_realtime=yes
|
||||||
|
+ ;;
|
||||||
|
# VxWorks has nanosleep as soon as the kernel is configured with
|
||||||
|
# INCLUDE_POSIX_TIMERS, which is normally/most-often the case.
|
||||||
|
vxworks*)
|
||||||
|
diff --color -rN -u vanilla/gcc-12.2.0/libstdc++-v3/configure.host gcc-12.2.0/libstdc++-v3/configure.host
|
||||||
|
--- a/gcc-12.2.0/libstdc++-v3/configure.host 2022-08-19 10:09:55.420698825 +0200
|
||||||
|
+++ b/gcc-12.2.0/libstdc++-v3/configure.host 2023-08-09 11:35:05.734185945 +0200
|
||||||
|
@@ -306,6 +306,9 @@
|
||||||
|
vxworks*)
|
||||||
|
os_include_dir="os/vxworks"
|
||||||
|
;;
|
||||||
|
+ luna*)
|
||||||
|
+ os_include_dir="os/generic"
|
||||||
|
+ ;;
|
||||||
|
*)
|
||||||
|
os_include_dir="os/generic"
|
||||||
|
;;
|
||||||
|
diff --color -rN -u vanilla/gcc-12.2.0/libstdc++-v3/crossconfig.m4 gcc-12.2.0/libstdc++-v3/crossconfig.m4
|
||||||
|
--- a/gcc-12.2.0/libstdc++-v3/crossconfig.m4 2022-08-19 10:09:55.420698825 +0200
|
||||||
|
+++ b/gcc-12.2.0/libstdc++-v3/crossconfig.m4 2023-08-08 21:16:12.897071194 +0200
|
||||||
|
@@ -277,6 +277,12 @@
|
||||||
|
GLIBCXX_CHECK_MATH_SUPPORT
|
||||||
|
GLIBCXX_CHECK_STDLIB_SUPPORT
|
||||||
|
;;
|
||||||
|
+ *-luna*)
|
||||||
|
+ GLIBCXX_CHECK_COMPILER_FEATURES
|
||||||
|
+ GLIBCXX_CHECK_LINKER_FEATURES
|
||||||
|
+ GLIBCXX_CHECK_MATH_SUPPORT
|
||||||
|
+ GLIBCXX_CHECK_STDLIB_SUPPORT
|
||||||
|
+ ;;
|
||||||
|
*-vxworks*)
|
||||||
|
AC_DEFINE(HAVE_ACOSF)
|
||||||
|
AC_DEFINE(HAVE_ASINF)
|
||||||
|
@ -15,16 +15,23 @@ fi
|
|||||||
|
|
||||||
source ports/$PORT_NAME/PACKAGE
|
source ports/$PORT_NAME/PACKAGE
|
||||||
|
|
||||||
|
IS_NEW_VERSION=0
|
||||||
|
|
||||||
if ! [ -f ports/out/$name-$version.tar.gz ]; then
|
if ! [ -f ports/out/$name-$version.tar.gz ]; then
|
||||||
tools/make-package.sh $PORT_NAME
|
tools/make-package.sh $PORT_NAME
|
||||||
|
IS_NEW_VERSION=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PORT_FILES=$LUNA_BASE/usr/share/pkgdb/$PORT_NAME.files
|
PORT_FILES=$LUNA_BASE/usr/share/pkgdb/$name.files
|
||||||
|
|
||||||
if [ -f $PORT_FILES ]
|
if [ -f $PORT_FILES ]
|
||||||
then
|
then
|
||||||
echo "Package $PORT_NAME is already installed! Updating."
|
if [ "$IS_NEW_VERSION" -eq "0" ]; then
|
||||||
tools/uninstall-package.sh $PORT_NAME
|
echo "Package $PORT_NAME version $version is already installed!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Package $PORT_NAME is already installed! Updating to version $version."
|
||||||
|
tools/uninstall-package.sh $name
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p $LUNA_BASE/usr/share/pkgdb/
|
mkdir -p $LUNA_BASE/usr/share/pkgdb/
|
||||||
|
@ -28,6 +28,13 @@ source ports/$PORT_NAME/PACKAGE
|
|||||||
[ -z ${format+x} ] && show_error "error: The port's PACKAGE file does not have a 'format' key."
|
[ -z ${format+x} ] && show_error "error: The port's PACKAGE file does not have a 'format' key."
|
||||||
[ -z ${url+x} ] && show_error "error: The port's PACKAGE file does not have a 'url' key."
|
[ -z ${url+x} ] && show_error "error: The port's PACKAGE file does not have a 'url' key."
|
||||||
|
|
||||||
|
if ! [ -z ${dependencies+x} ]; then
|
||||||
|
echo "Installing dependencies of $name: (${dependencies[@]})"
|
||||||
|
for dep in ${dependencies[@]}; do
|
||||||
|
tools/install-package.sh $dep
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
export portdir=$LUNA_ROOT/ports/$name/
|
export portdir=$LUNA_ROOT/ports/$name/
|
||||||
export srcdir=${srcdir:-$WORKDIR/$name-$version}
|
export srcdir=${srcdir:-$WORKDIR/$name-$version}
|
||||||
export builddir=$WORKDIR/build-$name
|
export builddir=$WORKDIR/build-$name
|
||||||
@ -41,15 +48,22 @@ case $format in
|
|||||||
tar)
|
tar)
|
||||||
[ -z ${output+x} ] && show_error "error: The 'tar' download format needs an 'output' key."
|
[ -z ${output+x} ] && show_error "error: The 'tar' download format needs an 'output' key."
|
||||||
[ -z ${sha256sum+x} ] && show_error "error: The 'tar' download format needs a 'sha256sum' key."
|
[ -z ${sha256sum+x} ] && show_error "error: The 'tar' download format needs a 'sha256sum' key."
|
||||||
echo "Downloading tarball for $name..."
|
if ! [ -f $output ]; then
|
||||||
wget $url --quiet
|
echo "Downloading tarball for $name..."
|
||||||
|
wget $url --quiet
|
||||||
|
else
|
||||||
|
echo "Using cached tarball for $name."
|
||||||
|
fi
|
||||||
echo "$sha256sum $output" | sha256sum -c
|
echo "$sha256sum $output" | sha256sum -c
|
||||||
tar xf $output
|
tar xf $output
|
||||||
rm $output
|
|
||||||
;;
|
;;
|
||||||
git)
|
git)
|
||||||
echo "Cloning repository for $name..."
|
if ! [ -d $srcdir]; then
|
||||||
git clone $url $srcdir
|
echo "Cloning repository for $name..."
|
||||||
|
git clone $url $srcdir
|
||||||
|
else
|
||||||
|
echo "Using local repository for $name."
|
||||||
|
fi
|
||||||
if ! [ -z ${tag+x} ]; then
|
if ! [ -z ${tag+x} ]; then
|
||||||
cd $srcdir
|
cd $srcdir
|
||||||
git checkout $tag
|
git checkout $tag
|
||||||
@ -61,10 +75,14 @@ case $format in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if ! [ "$set_cc_variables" = "no" ]; then
|
||||||
export CC=x86_64-luna-gcc
|
export CC=x86_64-luna-gcc
|
||||||
export CXX=x86_64-luna-g++
|
export CXX=x86_64-luna-g++
|
||||||
|
export PKG_CONFIG=luna-pkg-config
|
||||||
export CC_FOR_BUILD=gcc
|
export CC_FOR_BUILD=gcc
|
||||||
export CXX_FOR_BUILD=g++
|
export CXX_FOR_BUILD=g++
|
||||||
|
export PKG_CONFIG_FOR_BUILD=pkg-config
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p $builddir
|
mkdir -p $builddir
|
||||||
cd $builddir
|
cd $builddir
|
||||||
@ -109,6 +127,11 @@ else
|
|||||||
do_install
|
do_install
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
rm -f $installdir/usr/lib/*.la # remove all libtool .la files, as they use host stuff which we don't want at all
|
||||||
|
set +e
|
||||||
|
$LUNA_ARCH-luna-strip $installdir/usr/bin/* # strip all binaries
|
||||||
|
set -e
|
||||||
|
|
||||||
cd $installdir
|
cd $installdir
|
||||||
|
|
||||||
tar czf $LUNA_ROOT/ports/out/$name-$version.tar.gz *
|
tar czf $LUNA_ROOT/ports/out/$name-$version.tar.gz *
|
||||||
|
@ -47,7 +47,7 @@ unset CXX
|
|||||||
unset LD
|
unset LD
|
||||||
unset AR
|
unset AR
|
||||||
|
|
||||||
../gcc-$LUNA_GCC_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --enable-languages=c,c++ --without-headers
|
../gcc-$LUNA_GCC_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --enable-languages=c,c++
|
||||||
|
|
||||||
echo Building GCC...
|
echo Building GCC...
|
||||||
|
|
||||||
@ -58,3 +58,10 @@ echo Installing GCC...
|
|||||||
|
|
||||||
make install-gcc
|
make install-gcc
|
||||||
make install-target-libgcc
|
make install-target-libgcc
|
||||||
|
|
||||||
|
mkdir -p $LUNA_BUILD_DIR
|
||||||
|
cmake -S $LUNA_ROOT -B $LUNA_BUILD_DIR -G "$LUNA_CMAKE_GENERATOR_NAME"
|
||||||
|
cmake --build $LUNA_BUILD_DIR --target libc
|
||||||
|
|
||||||
|
make all-target-libstdc++-v3 CXXFLAGS_FOR_TARGET="-fno-exceptions" -j$(nproc)
|
||||||
|
make DESTDIR=$LUNA_BASE/usr install-target-libstdc++-v3
|
||||||
|
@ -14,5 +14,7 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
|
||||||
rm -v $(cat $LUNA_BASE/usr/share/pkgdb/$PORT_NAME.files)
|
rm -v $(cat $LUNA_BASE/usr/share/pkgdb/$PORT_NAME.files)
|
||||||
rm -v $LUNA_BASE/usr/share/pkgdb/$PORT_NAME.files
|
rm -v $LUNA_BASE/usr/share/pkgdb/$PORT_NAME.files
|
||||||
|
Loading…
Reference in New Issue
Block a user