mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
Compare commits
4 Commits
863f85ae4f
...
a4f2c8eb89
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4f2c8eb89 | ||
|
|
1a3510d8d9 | ||
|
|
c21c5b327e | ||
|
|
739be1d7f7 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,7 +2,6 @@ build/
|
||||
build-cmake*/
|
||||
*.iso
|
||||
*.tar
|
||||
limine/
|
||||
|
||||
# CMake generated files
|
||||
CMakeCache.txt
|
||||
|
||||
@@ -125,10 +125,27 @@ if(EXISTS "${CLEONOS_MENUCONFIG_CMAKE}")
|
||||
endif()
|
||||
|
||||
function(cl_set_bool_cache VAR_NAME DEFAULT_VALUE DOC_TEXT)
|
||||
if(NOT DEFINED ${VAR_NAME})
|
||||
set(_raw_value "")
|
||||
set(_has_value OFF)
|
||||
|
||||
if(DEFINED ${VAR_NAME})
|
||||
set(_raw_value "${${VAR_NAME}}")
|
||||
set(_has_value ON)
|
||||
elseif(DEFINED ${VAR_NAME}_IS_ENABLED)
|
||||
set(_raw_value "${${VAR_NAME}_IS_ENABLED}")
|
||||
set(_has_value ON)
|
||||
endif()
|
||||
|
||||
if(NOT _has_value)
|
||||
set(${VAR_NAME} ${DEFAULT_VALUE} CACHE BOOL "${DOC_TEXT}")
|
||||
else()
|
||||
set(${VAR_NAME} ${${VAR_NAME}} CACHE BOOL "${DOC_TEXT}" FORCE)
|
||||
string(TOUPPER "${_raw_value}" _raw_upper)
|
||||
if(_raw_upper STREQUAL "Y" OR _raw_upper STREQUAL "M" OR _raw_upper STREQUAL "ON" OR _raw_upper STREQUAL "TRUE" OR _raw_upper STREQUAL "1")
|
||||
set(_bool_value ON)
|
||||
else()
|
||||
set(_bool_value OFF)
|
||||
endif()
|
||||
set(${VAR_NAME} ${_bool_value} CACHE BOOL "${DOC_TEXT}" FORCE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -164,6 +181,19 @@ cl_set_bool_cache(CLEONOS_CLKS_ENABLE_TTY_READY_LOG ON "Print TTY ready logs")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG ON "Print idle loop debug log")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_PROCFS ON "Enable virtual /proc procfs syscall layer")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG ON "Enable EXEC info logs on serial output")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC ON "Enable UserSafeController dangerous syscall confirmations")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_FS_MKDIR ON "USC intercept policy: FS_MKDIR")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_FS_WRITE ON "USC intercept policy: FS_WRITE")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_FS_APPEND ON "USC intercept policy: FS_APPEND")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_FS_REMOVE ON "USC intercept policy: FS_REMOVE")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATH ON "USC intercept policy: EXEC_PATH")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV ON "USC intercept policy: EXEC_PATHV")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV_IO ON "USC intercept policy: EXEC_PATHV_IO")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATH ON "USC intercept policy: SPAWN_PATH")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATHV ON "USC intercept policy: SPAWN_PATHV")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_PROC_KILL ON "USC intercept policy: PROC_KILL")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_SHUTDOWN ON "USC intercept policy: SHUTDOWN")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_USC_SC_RESTART ON "USC intercept policy: RESTART")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY ON "Enable ALT+F1..F4 TTY switch hotkey")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS ON "Enable Ctrl+A/C/V keyboard shortcuts")
|
||||
cl_set_bool_cache(CLEONOS_CLKS_ENABLE_KBD_FORCE_STOP_HOTKEY ON "Enable Ctrl+Alt+C force-stop hotkey")
|
||||
@@ -197,6 +227,19 @@ cl_bool_to_int(CLEONOS_CLKS_ENABLE_TTY_READY_LOG CLKS_CFG_TTY_READY_LOG_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG CLKS_CFG_IDLE_DEBUG_LOG_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_PROCFS CLKS_CFG_PROCFS_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG CLKS_CFG_EXEC_SERIAL_LOG_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC CLKS_CFG_USC_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_FS_MKDIR CLKS_CFG_USC_SC_FS_MKDIR_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_FS_WRITE CLKS_CFG_USC_SC_FS_WRITE_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_FS_APPEND CLKS_CFG_USC_SC_FS_APPEND_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_FS_REMOVE CLKS_CFG_USC_SC_FS_REMOVE_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATH CLKS_CFG_USC_SC_EXEC_PATH_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV CLKS_CFG_USC_SC_EXEC_PATHV_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV_IO CLKS_CFG_USC_SC_EXEC_PATHV_IO_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATH CLKS_CFG_USC_SC_SPAWN_PATH_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATHV CLKS_CFG_USC_SC_SPAWN_PATHV_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_PROC_KILL CLKS_CFG_USC_SC_PROC_KILL_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_SHUTDOWN CLKS_CFG_USC_SC_SHUTDOWN_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_USC_SC_RESTART CLKS_CFG_USC_SC_RESTART_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY CLKS_CFG_KBD_TTY_SWITCH_HOTKEY_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS CLKS_CFG_KBD_CTRL_SHORTCUTS_INT)
|
||||
cl_bool_to_int(CLEONOS_CLKS_ENABLE_KBD_FORCE_STOP_HOTKEY CLKS_CFG_KBD_FORCE_STOP_HOTKEY_INT)
|
||||
@@ -244,6 +287,19 @@ set(ARCH_CFLAGS
|
||||
"-DCLKS_CFG_IDLE_DEBUG_LOG=${CLKS_CFG_IDLE_DEBUG_LOG_INT}"
|
||||
"-DCLKS_CFG_PROCFS=${CLKS_CFG_PROCFS_INT}"
|
||||
"-DCLKS_CFG_EXEC_SERIAL_LOG=${CLKS_CFG_EXEC_SERIAL_LOG_INT}"
|
||||
"-DCLKS_CFG_USC=${CLKS_CFG_USC_INT}"
|
||||
"-DCLKS_CFG_USC_SC_FS_MKDIR=${CLKS_CFG_USC_SC_FS_MKDIR_INT}"
|
||||
"-DCLKS_CFG_USC_SC_FS_WRITE=${CLKS_CFG_USC_SC_FS_WRITE_INT}"
|
||||
"-DCLKS_CFG_USC_SC_FS_APPEND=${CLKS_CFG_USC_SC_FS_APPEND_INT}"
|
||||
"-DCLKS_CFG_USC_SC_FS_REMOVE=${CLKS_CFG_USC_SC_FS_REMOVE_INT}"
|
||||
"-DCLKS_CFG_USC_SC_EXEC_PATH=${CLKS_CFG_USC_SC_EXEC_PATH_INT}"
|
||||
"-DCLKS_CFG_USC_SC_EXEC_PATHV=${CLKS_CFG_USC_SC_EXEC_PATHV_INT}"
|
||||
"-DCLKS_CFG_USC_SC_EXEC_PATHV_IO=${CLKS_CFG_USC_SC_EXEC_PATHV_IO_INT}"
|
||||
"-DCLKS_CFG_USC_SC_SPAWN_PATH=${CLKS_CFG_USC_SC_SPAWN_PATH_INT}"
|
||||
"-DCLKS_CFG_USC_SC_SPAWN_PATHV=${CLKS_CFG_USC_SC_SPAWN_PATHV_INT}"
|
||||
"-DCLKS_CFG_USC_SC_PROC_KILL=${CLKS_CFG_USC_SC_PROC_KILL_INT}"
|
||||
"-DCLKS_CFG_USC_SC_SHUTDOWN=${CLKS_CFG_USC_SC_SHUTDOWN_INT}"
|
||||
"-DCLKS_CFG_USC_SC_RESTART=${CLKS_CFG_USC_SC_RESTART_INT}"
|
||||
"-DCLKS_CFG_KBD_TTY_SWITCH_HOTKEY=${CLKS_CFG_KBD_TTY_SWITCH_HOTKEY_INT}"
|
||||
"-DCLKS_CFG_KBD_CTRL_SHORTCUTS=${CLKS_CFG_KBD_CTRL_SHORTCUTS_INT}"
|
||||
"-DCLKS_CFG_KBD_FORCE_STOP_HOTKEY=${CLKS_CFG_KBD_FORCE_STOP_HOTKEY_INT}"
|
||||
@@ -303,8 +359,6 @@ endif()
|
||||
|
||||
set(KERNEL_SOURCE_DIRS
|
||||
"${CMAKE_SOURCE_DIR}/clks/kernel"
|
||||
"${CMAKE_SOURCE_DIR}/clks/lib"
|
||||
"${CMAKE_SOURCE_DIR}/clks/drivers"
|
||||
"${CMAKE_SOURCE_DIR}/clks/arch/${CLKS_ARCH}"
|
||||
)
|
||||
|
||||
@@ -329,6 +383,15 @@ list(REMOVE_DUPLICATES ASM_SOURCES)
|
||||
list(SORT C_SOURCES)
|
||||
list(SORT ASM_SOURCES)
|
||||
|
||||
set(CLKS_BOOT_LIMINE_SOURCE "clks/kernel/boot/limine/limine_requests.c")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/${CLKS_BOOT_LIMINE_SOURCE}")
|
||||
list(APPEND C_SOURCES "${CLKS_BOOT_LIMINE_SOURCE}")
|
||||
list(REMOVE_DUPLICATES C_SOURCES)
|
||||
list(SORT C_SOURCES)
|
||||
else()
|
||||
cl_log_error("missing required boot source: ${CLKS_BOOT_LIMINE_SOURCE}")
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE KERNEL_INC_SOURCES_ABS CONFIGURE_DEPENDS
|
||||
"${CMAKE_SOURCE_DIR}/clks/**/*.inc"
|
||||
)
|
||||
|
||||
@@ -34,11 +34,64 @@
|
||||
#define CLKS_SYSCALL_KERNEL_ADDR_BASE 0xFFFF800000000000ULL
|
||||
#define CLKS_SYSCALL_STATS_MAX_ID CLKS_SYSCALL_EXEC_PATHV_IO
|
||||
#define CLKS_SYSCALL_STATS_RING_SIZE 256U
|
||||
#define CLKS_SYSCALL_USC_MAX_ALLOWED_APPS 64U
|
||||
|
||||
#ifndef CLKS_CFG_PROCFS
|
||||
#define CLKS_CFG_PROCFS 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC
|
||||
#define CLKS_CFG_USC 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_FS_MKDIR
|
||||
#define CLKS_CFG_USC_SC_FS_MKDIR 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_FS_WRITE
|
||||
#define CLKS_CFG_USC_SC_FS_WRITE 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_FS_APPEND
|
||||
#define CLKS_CFG_USC_SC_FS_APPEND 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_FS_REMOVE
|
||||
#define CLKS_CFG_USC_SC_FS_REMOVE 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_EXEC_PATH
|
||||
#define CLKS_CFG_USC_SC_EXEC_PATH 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_EXEC_PATHV
|
||||
#define CLKS_CFG_USC_SC_EXEC_PATHV 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_EXEC_PATHV_IO
|
||||
#define CLKS_CFG_USC_SC_EXEC_PATHV_IO 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_SPAWN_PATH
|
||||
#define CLKS_CFG_USC_SC_SPAWN_PATH 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_SPAWN_PATHV
|
||||
#define CLKS_CFG_USC_SC_SPAWN_PATHV 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_PROC_KILL
|
||||
#define CLKS_CFG_USC_SC_PROC_KILL 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_SHUTDOWN
|
||||
#define CLKS_CFG_USC_SC_SHUTDOWN 1
|
||||
#endif
|
||||
|
||||
#ifndef CLKS_CFG_USC_SC_RESTART
|
||||
#define CLKS_CFG_USC_SC_RESTART 1
|
||||
#endif
|
||||
|
||||
struct clks_syscall_frame {
|
||||
u64 rax;
|
||||
u64 rbx;
|
||||
@@ -92,6 +145,10 @@ static u64 clks_syscall_stats_recent_id_count[CLKS_SYSCALL_STATS_MAX_ID + 1ULL];
|
||||
static u16 clks_syscall_stats_recent_ring[CLKS_SYSCALL_STATS_RING_SIZE];
|
||||
static u32 clks_syscall_stats_recent_head = 0U;
|
||||
static u32 clks_syscall_stats_recent_size = 0U;
|
||||
#if CLKS_CFG_USC != 0
|
||||
static clks_bool clks_syscall_usc_allowed_used[CLKS_SYSCALL_USC_MAX_ALLOWED_APPS];
|
||||
static char clks_syscall_usc_allowed_path[CLKS_SYSCALL_USC_MAX_ALLOWED_APPS][CLKS_EXEC_PROC_PATH_MAX];
|
||||
#endif
|
||||
|
||||
#if defined(CLKS_ARCH_X86_64)
|
||||
static inline void clks_syscall_outb(u16 port, u8 value) {
|
||||
@@ -1641,6 +1698,264 @@ static void clks_syscall_serial_write_hex64(u64 value) {
|
||||
}
|
||||
}
|
||||
|
||||
#if CLKS_CFG_USC != 0
|
||||
static void clks_syscall_usc_sleep_until_input(void) {
|
||||
#if defined(CLKS_ARCH_X86_64)
|
||||
u64 flags = 0ULL;
|
||||
|
||||
__asm__ volatile("pushfq; popq %0" : "=r"(flags) : : "memory");
|
||||
|
||||
if ((flags & (1ULL << 9)) != 0ULL) {
|
||||
__asm__ volatile("hlt" : : : "memory");
|
||||
} else {
|
||||
__asm__ volatile("sti; hlt; cli" : : : "memory");
|
||||
}
|
||||
#elif defined(CLKS_ARCH_AARCH64)
|
||||
clks_cpu_pause();
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *clks_syscall_usc_syscall_name(u64 id) {
|
||||
switch (id) {
|
||||
case CLKS_SYSCALL_FS_MKDIR:
|
||||
return "FS_MKDIR";
|
||||
case CLKS_SYSCALL_FS_WRITE:
|
||||
return "FS_WRITE";
|
||||
case CLKS_SYSCALL_FS_APPEND:
|
||||
return "FS_APPEND";
|
||||
case CLKS_SYSCALL_FS_REMOVE:
|
||||
return "FS_REMOVE";
|
||||
case CLKS_SYSCALL_EXEC_PATH:
|
||||
return "EXEC_PATH";
|
||||
case CLKS_SYSCALL_EXEC_PATHV:
|
||||
return "EXEC_PATHV";
|
||||
case CLKS_SYSCALL_EXEC_PATHV_IO:
|
||||
return "EXEC_PATHV_IO";
|
||||
case CLKS_SYSCALL_SPAWN_PATH:
|
||||
return "SPAWN_PATH";
|
||||
case CLKS_SYSCALL_SPAWN_PATHV:
|
||||
return "SPAWN_PATHV";
|
||||
case CLKS_SYSCALL_PROC_KILL:
|
||||
return "PROC_KILL";
|
||||
case CLKS_SYSCALL_SHUTDOWN:
|
||||
return "SHUTDOWN";
|
||||
case CLKS_SYSCALL_RESTART:
|
||||
return "RESTART";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static clks_bool clks_syscall_usc_is_dangerous(u64 id) {
|
||||
switch (id) {
|
||||
case CLKS_SYSCALL_FS_MKDIR:
|
||||
return (CLKS_CFG_USC_SC_FS_MKDIR != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_FS_WRITE:
|
||||
return (CLKS_CFG_USC_SC_FS_WRITE != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_FS_APPEND:
|
||||
return (CLKS_CFG_USC_SC_FS_APPEND != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_FS_REMOVE:
|
||||
return (CLKS_CFG_USC_SC_FS_REMOVE != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_EXEC_PATH:
|
||||
return (CLKS_CFG_USC_SC_EXEC_PATH != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_EXEC_PATHV:
|
||||
return (CLKS_CFG_USC_SC_EXEC_PATHV != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_EXEC_PATHV_IO:
|
||||
return (CLKS_CFG_USC_SC_EXEC_PATHV_IO != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_SPAWN_PATH:
|
||||
return (CLKS_CFG_USC_SC_SPAWN_PATH != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_SPAWN_PATHV:
|
||||
return (CLKS_CFG_USC_SC_SPAWN_PATHV != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_PROC_KILL:
|
||||
return (CLKS_CFG_USC_SC_PROC_KILL != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_SHUTDOWN:
|
||||
return (CLKS_CFG_USC_SC_SHUTDOWN != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
case CLKS_SYSCALL_RESTART:
|
||||
return (CLKS_CFG_USC_SC_RESTART != 0) ? CLKS_TRUE : CLKS_FALSE;
|
||||
default:
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_syscall_usc_copy_path(char *dst, usize dst_size, const char *src) {
|
||||
usize i = 0U;
|
||||
|
||||
if (dst == CLKS_NULL || dst_size == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (src == CLKS_NULL) {
|
||||
dst[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
while (src[i] != '\0' && i + 1U < dst_size) {
|
||||
dst[i] = src[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
dst[i] = '\0';
|
||||
}
|
||||
|
||||
static clks_bool clks_syscall_usc_current_app_path(char *out_path, usize out_size) {
|
||||
u64 pid;
|
||||
struct clks_exec_proc_snapshot snap;
|
||||
|
||||
if (out_path == CLKS_NULL || out_size == 0U) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
out_path[0] = '\0';
|
||||
pid = clks_exec_current_pid();
|
||||
|
||||
if (pid == 0ULL) {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_exec_proc_snapshot(pid, &snap) == CLKS_FALSE || snap.path[0] == '\0') {
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
clks_syscall_usc_copy_path(out_path, out_size, snap.path);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
static i32 clks_syscall_usc_find_allowed_path(const char *path) {
|
||||
u32 i;
|
||||
|
||||
if (path == CLKS_NULL || path[0] == '\0') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0U; i < CLKS_SYSCALL_USC_MAX_ALLOWED_APPS; i++) {
|
||||
if (clks_syscall_usc_allowed_used[i] == CLKS_TRUE &&
|
||||
clks_strcmp(clks_syscall_usc_allowed_path[i], path) == 0) {
|
||||
return (i32)i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void clks_syscall_usc_remember_path(const char *path) {
|
||||
u32 i;
|
||||
|
||||
if (path == CLKS_NULL || path[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clks_syscall_usc_find_allowed_path(path) >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0U; i < CLKS_SYSCALL_USC_MAX_ALLOWED_APPS; i++) {
|
||||
if (clks_syscall_usc_allowed_used[i] == CLKS_FALSE) {
|
||||
clks_syscall_usc_allowed_used[i] = CLKS_TRUE;
|
||||
clks_syscall_usc_copy_path(clks_syscall_usc_allowed_path[i], sizeof(clks_syscall_usc_allowed_path[i]), path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clks_syscall_usc_emit_text_line(const char *label, const char *value) {
|
||||
char message[320];
|
||||
usize pos = 0U;
|
||||
|
||||
message[0] = '\0';
|
||||
pos = clks_syscall_procfs_append_text(message, sizeof(message), pos, label);
|
||||
pos = clks_syscall_procfs_append_text(message, sizeof(message), pos, ": ");
|
||||
pos = clks_syscall_procfs_append_text(message, sizeof(message), pos, value);
|
||||
(void)pos;
|
||||
clks_log(CLKS_LOG_WARN, "USC", message);
|
||||
}
|
||||
|
||||
static void clks_syscall_usc_emit_hex_line(const char *label, u64 value) {
|
||||
clks_log_hex(CLKS_LOG_WARN, "USC", label, value);
|
||||
}
|
||||
|
||||
static clks_bool clks_syscall_usc_prompt_allow(const char *app_path, u64 id, u64 arg0, u64 arg1, u64 arg2) {
|
||||
const char *name = clks_syscall_usc_syscall_name(id);
|
||||
u32 tty_index = clks_exec_current_tty();
|
||||
|
||||
#if !defined(CLKS_CFG_KEYBOARD) || (CLKS_CFG_KEYBOARD == 0)
|
||||
(void)tty_index;
|
||||
clks_syscall_usc_emit_text_line("BLOCK", "keyboard disabled, cannot prompt");
|
||||
return CLKS_FALSE;
|
||||
#else
|
||||
clks_syscall_usc_emit_text_line("DANGEROUS_SYSCALL", "REQUEST DETECTED");
|
||||
clks_syscall_usc_emit_text_line("APP", app_path);
|
||||
clks_syscall_usc_emit_hex_line("SYSCALL_ID", id);
|
||||
clks_syscall_usc_emit_text_line("SYSCALL_NAME", name);
|
||||
clks_syscall_usc_emit_hex_line("ARG0", arg0);
|
||||
clks_syscall_usc_emit_hex_line("ARG1", arg1);
|
||||
clks_syscall_usc_emit_hex_line("ARG2", arg2);
|
||||
clks_log(CLKS_LOG_WARN, "USC", "CONFIRM: Allow this app permanently? [y/N]");
|
||||
clks_tty_write("[WARN][USC] Allow this app permanently? [y/N]: ");
|
||||
clks_serial_write("[WARN][USC] Allow this app permanently? [y/N]: ");
|
||||
|
||||
while (1) {
|
||||
char ch = '\0';
|
||||
|
||||
if (clks_keyboard_pop_char_for_tty(tty_index, &ch) == CLKS_TRUE) {
|
||||
if (ch == 'y' || ch == 'Y') {
|
||||
clks_tty_write("y\n");
|
||||
clks_serial_write("y\n");
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (ch == 'n' || ch == 'N' || ch == '\n' || ch == '\r' || ch == 27) {
|
||||
clks_tty_write("n\n");
|
||||
clks_serial_write("n\n");
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
clks_syscall_usc_sleep_until_input();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static clks_bool clks_syscall_usc_check(u64 id, u64 arg0, u64 arg1, u64 arg2) {
|
||||
#if CLKS_CFG_USC == 0
|
||||
(void)id;
|
||||
(void)arg0;
|
||||
(void)arg1;
|
||||
(void)arg2;
|
||||
return CLKS_TRUE;
|
||||
#else
|
||||
char app_path[CLKS_EXEC_PROC_PATH_MAX];
|
||||
|
||||
if (clks_syscall_usc_is_dangerous(id) == CLKS_FALSE) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (clks_exec_is_running() == CLKS_FALSE || clks_exec_current_path_is_user() == CLKS_FALSE) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (clks_syscall_usc_current_app_path(app_path, sizeof(app_path)) == CLKS_FALSE) {
|
||||
clks_syscall_usc_emit_text_line("BLOCK", "cannot resolve current app path");
|
||||
return CLKS_FALSE;
|
||||
}
|
||||
|
||||
if (clks_syscall_usc_find_allowed_path(app_path) >= 0) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
if (clks_syscall_usc_prompt_allow(app_path, id, arg0, arg1, arg2) == CLKS_TRUE) {
|
||||
clks_syscall_usc_remember_path(app_path);
|
||||
clks_syscall_usc_emit_text_line("ALLOW", app_path);
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
clks_syscall_usc_emit_text_line("DENY", app_path);
|
||||
return CLKS_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void clks_syscall_stats_reset(void) {
|
||||
clks_syscall_stats_total = 0ULL;
|
||||
clks_memset(clks_syscall_stats_id_count, 0, sizeof(clks_syscall_stats_id_count));
|
||||
@@ -1754,6 +2069,10 @@ void clks_syscall_init(void) {
|
||||
clks_syscall_symbols_checked = CLKS_FALSE;
|
||||
clks_syscall_symbols_data = CLKS_NULL;
|
||||
clks_syscall_symbols_size = 0ULL;
|
||||
#if CLKS_CFG_USC != 0
|
||||
clks_memset(clks_syscall_usc_allowed_used, 0, sizeof(clks_syscall_usc_allowed_used));
|
||||
clks_memset(clks_syscall_usc_allowed_path, 0, sizeof(clks_syscall_usc_allowed_path));
|
||||
#endif
|
||||
clks_syscall_stats_reset();
|
||||
clks_log(CLKS_LOG_INFO, "SYSCALL", "INT80 FRAMEWORK ONLINE");
|
||||
}
|
||||
@@ -1773,6 +2092,10 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
||||
clks_syscall_stats_record(id);
|
||||
clks_syscall_trace_user_program(id);
|
||||
|
||||
if (clks_syscall_usc_check(id, frame->rbx, frame->rcx, frame->rdx) == CLKS_FALSE) {
|
||||
return (u64)-1;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case CLKS_SYSCALL_LOG_WRITE:
|
||||
return clks_syscall_log_write(frame->rbx, frame->rcx);
|
||||
@@ -53,6 +53,7 @@ static clks_bool clks_userland_probe_elf(const char *path, const char *tag) {
|
||||
return CLKS_TRUE;
|
||||
}
|
||||
|
||||
#if CLKS_CFG_USER_INIT_SCRIPT_PROBE
|
||||
static void clks_userland_probe_init_script(void) {
|
||||
const void *data;
|
||||
u64 size = 0ULL;
|
||||
@@ -67,6 +68,7 @@ static void clks_userland_probe_init_script(void) {
|
||||
clks_log(CLKS_LOG_INFO, "USER", "INIT SCRIPT READY /SHELL/INIT.CMD");
|
||||
clks_log_hex(CLKS_LOG_INFO, "USER", "INIT_SCRIPT_SIZE", size);
|
||||
}
|
||||
#endif
|
||||
|
||||
static clks_bool clks_userland_request_shell_exec(void) {
|
||||
u64 status = (u64)-1;
|
||||
@@ -4,193 +4,373 @@
|
||||
"key": "CLEONOS_CLKS_ENABLE_AUDIO",
|
||||
"title": "Audio Driver Init",
|
||||
"description": "Initialize kernel audio subsystem during boot.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_MOUSE",
|
||||
"title": "PS/2 Mouse Input",
|
||||
"description": "Initialize kernel PS/2 mouse input subsystem.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_DESKTOP",
|
||||
"title": "TTY2 Desktop",
|
||||
"description": "Enable desktop compositor tick/update path on TTY2.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_MOUSE"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_DRIVER_MANAGER",
|
||||
"title": "Driver Manager",
|
||||
"description": "Initialize kernel ELF driver manager.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_KELF",
|
||||
"title": "KELF Executor",
|
||||
"description": "Enable kernel ELF app dispatcher and kelfd task.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_DRIVER_MANAGER && CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT",
|
||||
"imply": [
|
||||
"CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE",
|
||||
"CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC",
|
||||
"title": "Auto Enter User Shell",
|
||||
"description": "Auto-exec /shell/shell.elf after kernel boot.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USRD_TASK && CLEONOS_CLKS_ENABLE_KEYBOARD",
|
||||
"select": [
|
||||
"CLEONOS_CLKS_ENABLE_USRD_TASK",
|
||||
"CLEONOS_CLKS_ENABLE_KEYBOARD"
|
||||
],
|
||||
"imply": [
|
||||
"CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE",
|
||||
"CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_HEAP_SELFTEST",
|
||||
"title": "Heap Selftest",
|
||||
"description": "Run kmalloc/kfree selftest during kernel boot.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_EXTERNAL_PSF",
|
||||
"title": "Load External PSF Font",
|
||||
"description": "Load /system/tty.psf and apply it to framebuffer TTY.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_KEYBOARD",
|
||||
"title": "PS/2 Keyboard Input",
|
||||
"description": "Initialize PS/2 keyboard input subsystem.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"imply": [
|
||||
"CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY",
|
||||
"CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_ELFRUNNER_PROBE",
|
||||
"title": "ELFRUNNER Probe",
|
||||
"description": "Probe kernel ELF runtime metadata after ELFRUNNER init.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT && CLEONOS_CLKS_ENABLE_KELF"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_KLOGD_TASK",
|
||||
"title": "Scheduler Task: klogd",
|
||||
"description": "Enable periodic klogd maintenance task.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_KWORKER_TASK",
|
||||
"title": "Scheduler Task: kworker",
|
||||
"description": "Enable periodic kernel worker service-heartbeat task.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USRD_TASK",
|
||||
"title": "Scheduler Task: usrd",
|
||||
"description": "Enable user/runtime dispatch task (shell tick, tty tick, exec tick).",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_BOOT_VIDEO_LOG",
|
||||
"title": "Boot Video Geometry Logs",
|
||||
"description": "Print framebuffer width/height/pitch/bpp logs at boot.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_PMM_STATS_LOG",
|
||||
"title": "PMM Stats Logs",
|
||||
"description": "Print PMM managed/free/used/dropped pages at boot.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_HEAP_STATS_LOG",
|
||||
"title": "Heap Stats Logs",
|
||||
"description": "Print heap total/free bytes at boot.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_FS_ROOT_LOG",
|
||||
"title": "FS Root Children Log",
|
||||
"description": "Print root directory children count during FS init.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y",
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_SYSTEM_DIR_CHECK",
|
||||
"title": "FS /SYSTEM Sanity Check",
|
||||
"description": "Require /system directory check during boot.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_ELFRUNNER_INIT",
|
||||
"title": "ELFRUNNER Init",
|
||||
"description": "Initialize ELFRUNNER framework in kernel boot path.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_SYSCALL_TICK_QUERY",
|
||||
"title": "SYSCALL Tick Query",
|
||||
"description": "Query timer ticks via syscall and log result during boot.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_PROCFS"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_TTY_READY_LOG",
|
||||
"title": "TTY Ready Logs",
|
||||
"description": "Print TTY count/active/cursor ready logs.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_IDLE_DEBUG_LOG",
|
||||
"title": "Idle Loop Debug Log",
|
||||
"description": "Print debug log before entering kernel idle loop.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_PROCFS",
|
||||
"title": "Virtual /proc",
|
||||
"description": "Enable virtual procfs paths (/proc, /proc/list, /proc/self, /proc/<pid>) in syscall FS layer.",
|
||||
"type": "bool",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_EXEC_SERIAL_LOG",
|
||||
"title": "EXEC Serial Logs",
|
||||
"description": "Print EXEC run/return/path logs to serial output.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"title": "UserSafeController (USC)",
|
||||
"description": "Prompt before dangerous user syscalls and remember per-app approval for current boot.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_MKDIR",
|
||||
"title": "Intercept FS_MKDIR",
|
||||
"description": "USC prompt for syscall FS_MKDIR.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_WRITE",
|
||||
"title": "Intercept FS_WRITE",
|
||||
"description": "USC prompt for syscall FS_WRITE.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_APPEND",
|
||||
"title": "Intercept FS_APPEND",
|
||||
"description": "USC prompt for syscall FS_APPEND.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_FS_REMOVE",
|
||||
"title": "Intercept FS_REMOVE",
|
||||
"description": "USC prompt for syscall FS_REMOVE.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATH",
|
||||
"title": "Intercept EXEC_PATH",
|
||||
"description": "USC prompt for syscall EXEC_PATH.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV",
|
||||
"title": "Intercept EXEC_PATHV",
|
||||
"description": "USC prompt for syscall EXEC_PATHV.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_EXEC_PATHV_IO",
|
||||
"title": "Intercept EXEC_PATHV_IO",
|
||||
"description": "USC prompt for syscall EXEC_PATHV_IO.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATH",
|
||||
"title": "Intercept SPAWN_PATH",
|
||||
"description": "USC prompt for syscall SPAWN_PATH.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SPAWN_PATHV",
|
||||
"title": "Intercept SPAWN_PATHV",
|
||||
"description": "USC prompt for syscall SPAWN_PATHV.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_PROC_KILL",
|
||||
"title": "Intercept PROC_KILL",
|
||||
"description": "USC prompt for syscall PROC_KILL.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_SHUTDOWN",
|
||||
"title": "Intercept SHUTDOWN",
|
||||
"description": "USC prompt for syscall SHUTDOWN.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USC_SC_RESTART",
|
||||
"title": "Intercept RESTART",
|
||||
"description": "USC prompt for syscall RESTART.",
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USC",
|
||||
"group": "USC Syscall Policy"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY",
|
||||
"title": "Keyboard TTY Switch Hotkey",
|
||||
"description": "Enable ALT+F1..F4 keyboard hotkey for active TTY switching.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_KBD_CTRL_SHORTCUTS",
|
||||
"title": "Keyboard Ctrl Shortcuts",
|
||||
"description": "Enable Ctrl+A/C/V shortcuts for input selection/copy/paste.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD",
|
||||
"imply": [
|
||||
"CLEONOS_CLKS_ENABLE_KBD_TTY_SWITCH_HOTKEY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_KBD_FORCE_STOP_HOTKEY",
|
||||
"title": "Keyboard Force-Stop Hotkey",
|
||||
"description": "Enable Ctrl+Alt+C force-stop for current running user process.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_KEYBOARD && CLEONOS_CLKS_ENABLE_PROCFS"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USER_INIT_SCRIPT_PROBE",
|
||||
"title": "User Init Script Probe",
|
||||
"description": "Probe and log /shell/init.cmd presence during userland init.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_USERLAND_AUTO_EXEC"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_USER_SYSTEM_APP_PROBE",
|
||||
"title": "User System App Probe",
|
||||
"description": "Probe /system/elfrunner.elf and /system/memc.elf during userland init.",
|
||||
"default": true
|
||||
"type": "bool",
|
||||
"default": true,
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_KELF"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_SCHED_TASK_COUNT_LOG",
|
||||
"title": "Scheduler Task Count Log",
|
||||
"description": "Print scheduler task count after scheduler initialization.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y",
|
||||
"depends_on": "CLEONOS_CLKS_ENABLE_KLOGD_TASK || CLEONOS_CLKS_ENABLE_KWORKER_TASK || CLEONOS_CLKS_ENABLE_USRD_TASK"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_INTERRUPT_READY_LOG",
|
||||
"title": "Interrupt Ready Log",
|
||||
"description": "Print IDT/PIC initialized log after interrupt setup.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
},
|
||||
{
|
||||
"key": "CLEONOS_CLKS_ENABLE_SHELL_MODE_LOG",
|
||||
"title": "Shell Mode Log",
|
||||
"description": "Print whether boot default mode is user shell or kernel shell.",
|
||||
"default": true
|
||||
"type": "tristate",
|
||||
"default": "y"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
BIN
scripts/__pycache__/menuconfig.cpython-313.pyc
Normal file
BIN
scripts/__pycache__/menuconfig.cpython-313.pyc
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -37,13 +37,17 @@ python wine/cleonos_wine.py build/x86_64/ramdisk_root/shell/shell.elf --rootfs b
|
||||
## 支持
|
||||
|
||||
- ELF64 (x86_64) PT_LOAD 段装载
|
||||
- CLeonOS `int 0x80` syscall 0..60
|
||||
- CLeonOS `int 0x80` syscall 0..80(含 `FD_*`、`PROC_*`、`STATS_*`、`EXEC_PATHV_IO`)
|
||||
- TTY 输出与键盘输入队列
|
||||
- rootfs 文件/目录访问(`FS_*`)
|
||||
- `/temp` 写入限制(`FS_MKDIR/WRITE/APPEND/REMOVE`)
|
||||
- `EXEC_PATH/EXEC_PATHV` 执行 ELF(带深度限制)
|
||||
- `EXEC_PATHV_IO`(支持 stdio fd 继承/重定向)
|
||||
- `SPAWN_PATH/SPAWN_PATHV/WAITPID/EXIT/SLEEP_TICKS/YIELD`
|
||||
- 进程 `argv/env` 查询(`PROC_ARGC/PROC_ARGV/PROC_ENVC/PROC_ENV`)
|
||||
- 进程枚举与快照(`PROC_COUNT/PROC_PID_AT/PROC_SNAPSHOT/PROC_KILL`)
|
||||
- syscall 统计(`STATS_TOTAL/STATS_ID_COUNT/STATS_RECENT_*`)
|
||||
- 文件描述符(`FD_OPEN/FD_READ/FD_WRITE/FD_CLOSE/FD_DUP`)
|
||||
- 异常退出状态编码与故障元信息(`PROC_LAST_SIGNAL/PROC_FAULT_*`)
|
||||
|
||||
## 参数
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -69,6 +69,48 @@ SYS_PROC_LAST_SIGNAL = 57
|
||||
SYS_PROC_FAULT_VECTOR = 58
|
||||
SYS_PROC_FAULT_ERROR = 59
|
||||
SYS_PROC_FAULT_RIP = 60
|
||||
SYS_PROC_COUNT = 61
|
||||
SYS_PROC_PID_AT = 62
|
||||
SYS_PROC_SNAPSHOT = 63
|
||||
SYS_PROC_KILL = 64
|
||||
SYS_KDBG_SYM = 65
|
||||
SYS_KDBG_BT = 66
|
||||
SYS_KDBG_REGS = 67
|
||||
SYS_STATS_TOTAL = 68
|
||||
SYS_STATS_ID_COUNT = 69
|
||||
SYS_STATS_RECENT_WINDOW = 70
|
||||
SYS_STATS_RECENT_ID = 71
|
||||
SYS_FD_OPEN = 72
|
||||
SYS_FD_READ = 73
|
||||
SYS_FD_WRITE = 74
|
||||
SYS_FD_CLOSE = 75
|
||||
SYS_FD_DUP = 76
|
||||
SYS_DL_OPEN = 77
|
||||
SYS_DL_CLOSE = 78
|
||||
SYS_DL_SYM = 79
|
||||
SYS_EXEC_PATHV_IO = 80
|
||||
|
||||
# proc states (from cleonos/c/include/cleonos_syscall.h)
|
||||
PROC_STATE_UNUSED = 0
|
||||
PROC_STATE_PENDING = 1
|
||||
PROC_STATE_RUNNING = 2
|
||||
PROC_STATE_EXITED = 3
|
||||
PROC_STATE_STOPPED = 4
|
||||
|
||||
# signals (from cleonos/c/include/cleonos_syscall.h)
|
||||
SIGKILL = 9
|
||||
SIGTERM = 15
|
||||
SIGCONT = 18
|
||||
SIGSTOP = 19
|
||||
|
||||
# open flags (from cleonos/c/include/cleonos_syscall.h)
|
||||
O_RDONLY = 0x0000
|
||||
O_WRONLY = 0x0001
|
||||
O_RDWR = 0x0002
|
||||
O_CREAT = 0x0040
|
||||
O_TRUNC = 0x0200
|
||||
O_APPEND = 0x0400
|
||||
FD_INHERIT = U64_MASK
|
||||
|
||||
|
||||
def u64(value: int) -> int:
|
||||
|
||||
@@ -6,40 +6,48 @@ import sys
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import List, Optional, Tuple
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from .constants import (
|
||||
DEFAULT_MAX_EXEC_DEPTH,
|
||||
FD_INHERIT,
|
||||
FS_NAME_MAX,
|
||||
MAX_CSTR,
|
||||
MAX_IO_READ,
|
||||
O_APPEND,
|
||||
O_CREAT,
|
||||
O_RDONLY,
|
||||
O_RDWR,
|
||||
O_TRUNC,
|
||||
O_WRONLY,
|
||||
PAGE_SIZE,
|
||||
PROC_STATE_EXITED,
|
||||
PROC_STATE_PENDING,
|
||||
PROC_STATE_RUNNING,
|
||||
PROC_STATE_STOPPED,
|
||||
SIGCONT,
|
||||
SIGKILL,
|
||||
SIGSTOP,
|
||||
SIGTERM,
|
||||
SYS_AUDIO_AVAILABLE,
|
||||
SYS_AUDIO_PLAY_TONE,
|
||||
SYS_AUDIO_STOP,
|
||||
SYS_CONTEXT_SWITCHES,
|
||||
SYS_CUR_TASK,
|
||||
SYS_DL_CLOSE,
|
||||
SYS_DL_OPEN,
|
||||
SYS_DL_SYM,
|
||||
SYS_EXEC_PATH,
|
||||
SYS_EXEC_PATHV,
|
||||
SYS_EXEC_PATHV_IO,
|
||||
SYS_EXEC_REQUESTS,
|
||||
SYS_EXEC_SUCCESS,
|
||||
SYS_EXIT,
|
||||
SYS_GETPID,
|
||||
SYS_PROC_ARGC,
|
||||
SYS_PROC_ARGV,
|
||||
SYS_PROC_ENVC,
|
||||
SYS_PROC_ENV,
|
||||
SYS_PROC_FAULT_ERROR,
|
||||
SYS_PROC_FAULT_RIP,
|
||||
SYS_PROC_FAULT_VECTOR,
|
||||
SYS_PROC_LAST_SIGNAL,
|
||||
SYS_SLEEP_TICKS,
|
||||
SYS_SPAWN_PATH,
|
||||
SYS_SPAWN_PATHV,
|
||||
SYS_WAITPID,
|
||||
SYS_YIELD,
|
||||
SYS_SHUTDOWN,
|
||||
SYS_RESTART,
|
||||
SYS_FD_CLOSE,
|
||||
SYS_FD_DUP,
|
||||
SYS_FD_OPEN,
|
||||
SYS_FD_READ,
|
||||
SYS_FD_WRITE,
|
||||
SYS_FS_APPEND,
|
||||
SYS_FS_CHILD_COUNT,
|
||||
SYS_FS_GET_CHILD_NAME,
|
||||
@@ -50,6 +58,7 @@ from .constants import (
|
||||
SYS_FS_STAT_SIZE,
|
||||
SYS_FS_STAT_TYPE,
|
||||
SYS_FS_WRITE,
|
||||
SYS_GETPID,
|
||||
SYS_KBD_BUFFERED,
|
||||
SYS_KBD_DROPPED,
|
||||
SYS_KBD_GET_CHAR,
|
||||
@@ -61,8 +70,29 @@ from .constants import (
|
||||
SYS_LOG_JOURNAL_COUNT,
|
||||
SYS_LOG_JOURNAL_READ,
|
||||
SYS_LOG_WRITE,
|
||||
SYS_PROC_ARGC,
|
||||
SYS_PROC_ARGV,
|
||||
SYS_PROC_COUNT,
|
||||
SYS_PROC_ENVC,
|
||||
SYS_PROC_ENV,
|
||||
SYS_PROC_FAULT_ERROR,
|
||||
SYS_PROC_FAULT_RIP,
|
||||
SYS_PROC_FAULT_VECTOR,
|
||||
SYS_PROC_KILL,
|
||||
SYS_PROC_LAST_SIGNAL,
|
||||
SYS_PROC_PID_AT,
|
||||
SYS_PROC_SNAPSHOT,
|
||||
SYS_RESTART,
|
||||
SYS_SERVICE_COUNT,
|
||||
SYS_SERVICE_READY_COUNT,
|
||||
SYS_SHUTDOWN,
|
||||
SYS_SLEEP_TICKS,
|
||||
SYS_SPAWN_PATH,
|
||||
SYS_SPAWN_PATHV,
|
||||
SYS_STATS_ID_COUNT,
|
||||
SYS_STATS_RECENT_ID,
|
||||
SYS_STATS_RECENT_WINDOW,
|
||||
SYS_STATS_TOTAL,
|
||||
SYS_TASK_COUNT,
|
||||
SYS_TIMER_TICKS,
|
||||
SYS_TTY_ACTIVE,
|
||||
@@ -75,6 +105,8 @@ from .constants import (
|
||||
SYS_USER_LAUNCH_OK,
|
||||
SYS_USER_LAUNCH_TRIES,
|
||||
SYS_USER_SHELL_READY,
|
||||
SYS_WAITPID,
|
||||
SYS_YIELD,
|
||||
page_ceil,
|
||||
page_floor,
|
||||
u64,
|
||||
@@ -124,6 +156,15 @@ class ELFImage:
|
||||
segments: List[ELFSegment]
|
||||
|
||||
|
||||
@dataclass
|
||||
class FDEntry:
|
||||
kind: str
|
||||
flags: int
|
||||
offset: int = 0
|
||||
path: str = ""
|
||||
tty_index: int = 0
|
||||
|
||||
|
||||
EXEC_PATH_MAX = 192
|
||||
EXEC_ARG_LINE_MAX = 256
|
||||
EXEC_ENV_LINE_MAX = 512
|
||||
@@ -131,6 +172,8 @@ EXEC_MAX_ARGS = 24
|
||||
EXEC_MAX_ENVS = 24
|
||||
EXEC_ITEM_MAX = 128
|
||||
EXEC_STATUS_SIGNAL_FLAG = 1 << 63
|
||||
PROC_PATH_MAX = 192
|
||||
FD_MAX = 64
|
||||
|
||||
|
||||
class CLeonOSWineNative:
|
||||
@@ -150,6 +193,7 @@ class CLeonOSWineNative:
|
||||
ppid: int = 0,
|
||||
argv_items: Optional[List[str]] = None,
|
||||
env_items: Optional[List[str]] = None,
|
||||
inherited_fds: Optional[Dict[int, FDEntry]] = None,
|
||||
) -> None:
|
||||
self.elf_path = elf_path
|
||||
self.rootfs = rootfs
|
||||
@@ -175,9 +219,97 @@ class CLeonOSWineNative:
|
||||
self._stack_size = 0x0000000000020000
|
||||
self._ret_sentinel = 0x00007FFF10000000
|
||||
self._mapped_ranges: List[Tuple[int, int]] = []
|
||||
self._tty_index = int(self.state.tty_active)
|
||||
self._fds: Dict[int, FDEntry] = {}
|
||||
self._fd_inherited = inherited_fds if inherited_fds is not None else {}
|
||||
|
||||
default_path = self._normalize_guest_path(self.guest_path_hint or f"/{self.elf_path.name}")
|
||||
self.argv_items, self.env_items = self._prepare_exec_items(default_path, self.argv_items, self.env_items)
|
||||
self._init_default_fds()
|
||||
|
||||
@staticmethod
|
||||
def _clone_fd_entry(entry: FDEntry) -> FDEntry:
|
||||
return FDEntry(kind=entry.kind, flags=int(entry.flags), offset=int(entry.offset), path=str(entry.path), tty_index=int(entry.tty_index))
|
||||
|
||||
@staticmethod
|
||||
def _fd_access_mode(flags: int) -> int:
|
||||
return int(flags) & 0x3
|
||||
|
||||
@classmethod
|
||||
def _fd_access_mode_valid(cls, flags: int) -> bool:
|
||||
mode = cls._fd_access_mode(flags)
|
||||
return mode in (O_RDONLY, O_WRONLY, O_RDWR)
|
||||
|
||||
@classmethod
|
||||
def _fd_can_read(cls, flags: int) -> bool:
|
||||
mode = cls._fd_access_mode(flags)
|
||||
return mode in (O_RDONLY, O_RDWR)
|
||||
|
||||
@classmethod
|
||||
def _fd_can_write(cls, flags: int) -> bool:
|
||||
mode = cls._fd_access_mode(flags)
|
||||
return mode in (O_WRONLY, O_RDWR)
|
||||
|
||||
def _init_default_fds(self) -> None:
|
||||
self._fds = {
|
||||
0: FDEntry(kind="tty", flags=O_RDONLY, offset=0, tty_index=self._tty_index),
|
||||
1: FDEntry(kind="tty", flags=O_WRONLY, offset=0, tty_index=self._tty_index),
|
||||
2: FDEntry(kind="tty", flags=O_WRONLY, offset=0, tty_index=self._tty_index),
|
||||
}
|
||||
|
||||
for target in (0, 1, 2):
|
||||
inherited = self._fd_inherited.get(target)
|
||||
if inherited is not None:
|
||||
self._fds[target] = self._clone_fd_entry(inherited)
|
||||
|
||||
for target in (0, 1, 2):
|
||||
entry = self._fds.get(target)
|
||||
if entry is not None and entry.kind == "tty":
|
||||
self._tty_index = int(entry.tty_index)
|
||||
break
|
||||
|
||||
def _fd_lookup(self, fd: int) -> Optional[FDEntry]:
|
||||
if fd < 0 or fd >= FD_MAX:
|
||||
return None
|
||||
return self._fds.get(int(fd))
|
||||
|
||||
def _fd_find_free(self) -> int:
|
||||
for fd in range(FD_MAX):
|
||||
if fd not in self._fds:
|
||||
return fd
|
||||
return -1
|
||||
|
||||
def _stdio_entry_for_child(self, target_fd: int, override_fd: int, require_read: bool, require_write: bool) -> Optional[FDEntry]:
|
||||
if override_fd == FD_INHERIT:
|
||||
src = self._fd_lookup(target_fd)
|
||||
else:
|
||||
src = self._fd_lookup(override_fd)
|
||||
|
||||
if src is None:
|
||||
return None
|
||||
|
||||
if require_read and not self._fd_can_read(src.flags):
|
||||
return None
|
||||
|
||||
if require_write and not self._fd_can_write(src.flags):
|
||||
return None
|
||||
|
||||
return self._clone_fd_entry(src)
|
||||
|
||||
def _build_child_stdio_map(self, stdin_fd: int, stdout_fd: int, stderr_fd: int) -> Optional[Dict[int, FDEntry]]:
|
||||
child_map: Dict[int, FDEntry] = {}
|
||||
|
||||
in_entry = self._stdio_entry_for_child(0, stdin_fd, require_read=True, require_write=False)
|
||||
out_entry = self._stdio_entry_for_child(1, stdout_fd, require_read=False, require_write=True)
|
||||
err_entry = self._stdio_entry_for_child(2, stderr_fd, require_read=False, require_write=True)
|
||||
|
||||
if in_entry is None or out_entry is None or err_entry is None:
|
||||
return None
|
||||
|
||||
child_map[0] = in_entry
|
||||
child_map[1] = out_entry
|
||||
child_map[2] = err_entry
|
||||
return child_map
|
||||
|
||||
def run(self) -> Optional[int]:
|
||||
if self.pid == 0:
|
||||
@@ -187,6 +319,7 @@ class CLeonOSWineNative:
|
||||
self.state.set_current_pid(self.pid)
|
||||
self.state.set_proc_cmdline(self.pid, self.argv_items, self.env_items)
|
||||
self.state.set_proc_fault(self.pid, 0, 0, 0, 0)
|
||||
self.state.set_proc_running(self.pid, self.argv_items[0] if self.argv_items else self.guest_path_hint, self._tty_index)
|
||||
|
||||
uc = Uc(UC_ARCH_X86, UC_MODE_64)
|
||||
self._install_hooks(uc)
|
||||
@@ -252,6 +385,7 @@ class CLeonOSWineNative:
|
||||
arg1 = self._reg_read(uc, UC_X86_REG_RCX)
|
||||
arg2 = self._reg_read(uc, UC_X86_REG_RDX)
|
||||
|
||||
self.state.record_syscall(syscall_id)
|
||||
self.state.context_switches = u64(self.state.context_switches + 1)
|
||||
ret = self._dispatch_syscall(uc, syscall_id, arg0, arg1, arg2)
|
||||
self._reg_write(uc, UC_X86_REG_RAX, u64(ret))
|
||||
@@ -291,6 +425,8 @@ class CLeonOSWineNative:
|
||||
return self._exec_path(uc, arg0)
|
||||
if sid == SYS_EXEC_PATHV:
|
||||
return self._exec_pathv(uc, arg0, arg1, arg2)
|
||||
if sid == SYS_EXEC_PATHV_IO:
|
||||
return self._exec_pathv_io(uc, arg0, arg1, arg2)
|
||||
if sid == SYS_SPAWN_PATH:
|
||||
return self._spawn_path(uc, arg0)
|
||||
if sid == SYS_SPAWN_PATHV:
|
||||
@@ -315,6 +451,14 @@ class CLeonOSWineNative:
|
||||
return self._proc_fault_error()
|
||||
if sid == SYS_PROC_FAULT_RIP:
|
||||
return self._proc_fault_rip()
|
||||
if sid == SYS_PROC_COUNT:
|
||||
return self._proc_count()
|
||||
if sid == SYS_PROC_PID_AT:
|
||||
return self._proc_pid_at(uc, arg0, arg1)
|
||||
if sid == SYS_PROC_SNAPSHOT:
|
||||
return self._proc_snapshot(uc, arg0, arg1, arg2)
|
||||
if sid == SYS_PROC_KILL:
|
||||
return self._proc_kill(uc, arg0, arg1)
|
||||
if sid == SYS_EXIT:
|
||||
return self._request_exit(uc, arg0)
|
||||
if sid == SYS_SLEEP_TICKS:
|
||||
@@ -400,6 +544,30 @@ class CLeonOSWineNative:
|
||||
return self.state.kbd_drop_count
|
||||
if sid == SYS_KBD_HOTKEY_SWITCHES:
|
||||
return self.state.kbd_hotkey_switches
|
||||
if sid == SYS_STATS_TOTAL:
|
||||
return self.state.stats_total()
|
||||
if sid == SYS_STATS_ID_COUNT:
|
||||
return self.state.stats_id_count(arg0)
|
||||
if sid == SYS_STATS_RECENT_WINDOW:
|
||||
return self.state.stats_recent_window()
|
||||
if sid == SYS_STATS_RECENT_ID:
|
||||
return self.state.stats_recent_id_count(arg0)
|
||||
if sid == SYS_FD_OPEN:
|
||||
return self._fd_open(uc, arg0, arg1, arg2)
|
||||
if sid == SYS_FD_READ:
|
||||
return self._fd_read(uc, arg0, arg1, arg2)
|
||||
if sid == SYS_FD_WRITE:
|
||||
return self._fd_write(uc, arg0, arg1, arg2)
|
||||
if sid == SYS_FD_CLOSE:
|
||||
return self._fd_close(arg0)
|
||||
if sid == SYS_FD_DUP:
|
||||
return self._fd_dup(arg0)
|
||||
if sid == SYS_DL_OPEN:
|
||||
return u64_neg1()
|
||||
if sid == SYS_DL_CLOSE:
|
||||
return 0
|
||||
if sid == SYS_DL_SYM:
|
||||
return 0
|
||||
|
||||
return u64_neg1()
|
||||
|
||||
@@ -409,6 +577,15 @@ class CLeonOSWineNative:
|
||||
sys.stdout.write(text)
|
||||
sys.stdout.flush()
|
||||
|
||||
def _host_write_bytes(self, data: bytes) -> None:
|
||||
if not data:
|
||||
return
|
||||
if hasattr(sys.stdout, "buffer"):
|
||||
sys.stdout.buffer.write(data)
|
||||
sys.stdout.flush()
|
||||
return
|
||||
self._host_write(data.decode("utf-8", errors="replace"))
|
||||
|
||||
def _load_segments(self, uc: Uc) -> None:
|
||||
for seg in self.image.segments:
|
||||
start = page_floor(seg.vaddr)
|
||||
@@ -504,6 +681,30 @@ class CLeonOSWineNative:
|
||||
except UcError:
|
||||
return b""
|
||||
|
||||
def _read_guest_bytes_exact(self, uc: Uc, addr: int, size: int) -> Optional[bytes]:
|
||||
if size < 0 or addr == 0:
|
||||
return None
|
||||
if size == 0:
|
||||
return b""
|
||||
|
||||
out = bytearray()
|
||||
cursor = int(addr)
|
||||
left = int(size)
|
||||
|
||||
while left > 0:
|
||||
chunk = min(left, MAX_IO_READ)
|
||||
try:
|
||||
data = uc.mem_read(cursor, chunk)
|
||||
except UcError:
|
||||
return None
|
||||
if len(data) != chunk:
|
||||
return None
|
||||
out.extend(data)
|
||||
cursor += chunk
|
||||
left -= chunk
|
||||
|
||||
return bytes(out)
|
||||
|
||||
def _write_guest_bytes(self, uc: Uc, addr: int, data: bytes) -> bool:
|
||||
if addr == 0:
|
||||
return False
|
||||
@@ -743,16 +944,86 @@ class CLeonOSWineNative:
|
||||
return 1 if self._write_guest_bytes(uc, out_ptr, encoded + b"\x00") else 0
|
||||
|
||||
def _exec_path(self, uc: Uc, path_ptr: int) -> int:
|
||||
return self._spawn_path_common(uc, path_ptr, 0, 0, return_pid=False)
|
||||
return self._spawn_path_common(
|
||||
uc,
|
||||
path_ptr,
|
||||
0,
|
||||
0,
|
||||
return_pid=False,
|
||||
env_line_override=None,
|
||||
stdin_fd=FD_INHERIT,
|
||||
stdout_fd=FD_INHERIT,
|
||||
stderr_fd=FD_INHERIT,
|
||||
)
|
||||
|
||||
def _exec_pathv(self, uc: Uc, path_ptr: int, argv_ptr: int, env_ptr: int) -> int:
|
||||
return self._spawn_path_common(uc, path_ptr, argv_ptr, env_ptr, return_pid=False)
|
||||
return self._spawn_path_common(
|
||||
uc,
|
||||
path_ptr,
|
||||
argv_ptr,
|
||||
env_ptr,
|
||||
return_pid=False,
|
||||
env_line_override=None,
|
||||
stdin_fd=FD_INHERIT,
|
||||
stdout_fd=FD_INHERIT,
|
||||
stderr_fd=FD_INHERIT,
|
||||
)
|
||||
|
||||
def _exec_pathv_io(self, uc: Uc, path_ptr: int, argv_ptr: int, req_ptr: int) -> int:
|
||||
req_data: Optional[bytes]
|
||||
env_ptr: int
|
||||
stdin_fd: int
|
||||
stdout_fd: int
|
||||
stderr_fd: int
|
||||
env_line: str
|
||||
|
||||
if req_ptr == 0:
|
||||
return u64_neg1()
|
||||
|
||||
req_data = self._read_guest_bytes_exact(uc, req_ptr, 32)
|
||||
if req_data is None or len(req_data) != 32:
|
||||
return u64_neg1()
|
||||
|
||||
env_ptr, stdin_fd, stdout_fd, stderr_fd = struct.unpack("<QQQQ", req_data)
|
||||
env_line = self._read_guest_cstring(uc, env_ptr, EXEC_ENV_LINE_MAX) if env_ptr != 0 else ""
|
||||
|
||||
return self._spawn_path_common(
|
||||
uc,
|
||||
path_ptr,
|
||||
argv_ptr,
|
||||
0,
|
||||
return_pid=False,
|
||||
env_line_override=env_line,
|
||||
stdin_fd=stdin_fd,
|
||||
stdout_fd=stdout_fd,
|
||||
stderr_fd=stderr_fd,
|
||||
)
|
||||
|
||||
def _spawn_path(self, uc: Uc, path_ptr: int) -> int:
|
||||
return self._spawn_path_common(uc, path_ptr, 0, 0, return_pid=True)
|
||||
return self._spawn_path_common(
|
||||
uc,
|
||||
path_ptr,
|
||||
0,
|
||||
0,
|
||||
return_pid=True,
|
||||
env_line_override=None,
|
||||
stdin_fd=FD_INHERIT,
|
||||
stdout_fd=FD_INHERIT,
|
||||
stderr_fd=FD_INHERIT,
|
||||
)
|
||||
|
||||
def _spawn_pathv(self, uc: Uc, path_ptr: int, argv_ptr: int, env_ptr: int) -> int:
|
||||
return self._spawn_path_common(uc, path_ptr, argv_ptr, env_ptr, return_pid=True)
|
||||
return self._spawn_path_common(
|
||||
uc,
|
||||
path_ptr,
|
||||
argv_ptr,
|
||||
env_ptr,
|
||||
return_pid=True,
|
||||
env_line_override=None,
|
||||
stdin_fd=FD_INHERIT,
|
||||
stdout_fd=FD_INHERIT,
|
||||
stderr_fd=FD_INHERIT,
|
||||
)
|
||||
|
||||
def _spawn_path_common(
|
||||
self,
|
||||
@@ -762,17 +1033,30 @@ class CLeonOSWineNative:
|
||||
env_ptr: int,
|
||||
*,
|
||||
return_pid: bool,
|
||||
env_line_override: Optional[str],
|
||||
stdin_fd: int,
|
||||
stdout_fd: int,
|
||||
stderr_fd: int,
|
||||
) -> int:
|
||||
path = self._read_guest_cstring(uc, path_ptr, EXEC_PATH_MAX)
|
||||
guest_path = self._normalize_guest_path(path)
|
||||
argv_line = self._read_guest_cstring(uc, argv_ptr, EXEC_ARG_LINE_MAX) if argv_ptr != 0 else ""
|
||||
env_line = self._read_guest_cstring(uc, env_ptr, EXEC_ENV_LINE_MAX) if env_ptr != 0 else ""
|
||||
env_line = (
|
||||
env_line_override
|
||||
if env_line_override is not None
|
||||
else (self._read_guest_cstring(uc, env_ptr, EXEC_ENV_LINE_MAX) if env_ptr != 0 else "")
|
||||
)
|
||||
host_path = self._guest_to_host(guest_path, must_exist=True)
|
||||
child_stdio = self._build_child_stdio_map(int(stdin_fd), int(stdout_fd), int(stderr_fd))
|
||||
|
||||
self.state.exec_requests = u64(self.state.exec_requests + 1)
|
||||
self.state.user_exec_requested = 1
|
||||
self.state.user_launch_tries = u64(self.state.user_launch_tries + 1)
|
||||
|
||||
if child_stdio is None:
|
||||
self.state.user_launch_fail = u64(self.state.user_launch_fail + 1)
|
||||
return u64_neg1()
|
||||
|
||||
if host_path is None or not host_path.is_file():
|
||||
self.state.user_launch_fail = u64(self.state.user_launch_fail + 1)
|
||||
return u64_neg1()
|
||||
@@ -802,6 +1086,7 @@ class CLeonOSWineNative:
|
||||
ppid=parent_pid,
|
||||
argv_items=argv_items,
|
||||
env_items=env_items,
|
||||
inherited_fds=child_stdio,
|
||||
)
|
||||
child_ret = child.run()
|
||||
|
||||
@@ -854,6 +1139,97 @@ class CLeonOSWineNative:
|
||||
def _proc_fault_rip(self) -> int:
|
||||
return self.state.proc_fault_rip_value(self.state.get_current_pid())
|
||||
|
||||
def _proc_count(self) -> int:
|
||||
return self.state.proc_count()
|
||||
|
||||
def _proc_pid_at(self, uc: Uc, index: int, out_ptr: int) -> int:
|
||||
if out_ptr == 0:
|
||||
return 0
|
||||
|
||||
pid = self.state.proc_pid_at(int(index))
|
||||
if pid is None:
|
||||
return 0
|
||||
|
||||
return 1 if self._write_guest_bytes(uc, out_ptr, struct.pack("<Q", u64(pid))) else 0
|
||||
|
||||
def _proc_snapshot(self, uc: Uc, pid: int, out_ptr: int, out_size: int) -> int:
|
||||
if out_ptr == 0 or out_size < (13 * 8 + PROC_PATH_MAX):
|
||||
return 0
|
||||
|
||||
target = int(pid)
|
||||
state_value = self.state.proc_state_value(target)
|
||||
if state_value == 0:
|
||||
return 0
|
||||
|
||||
path = self.state.proc_path_value(target)
|
||||
encoded_path = path.encode("utf-8", errors="replace")
|
||||
if len(encoded_path) >= PROC_PATH_MAX:
|
||||
encoded_path = encoded_path[: PROC_PATH_MAX - 1]
|
||||
path_buf = encoded_path + b"\x00" + (b"\x00" * (PROC_PATH_MAX - len(encoded_path) - 1))
|
||||
|
||||
blob = struct.pack(
|
||||
"<13Q",
|
||||
u64(target),
|
||||
u64(self.state.proc_ppid(target)),
|
||||
u64(state_value),
|
||||
u64(self.state.proc_started_tick_value(target)),
|
||||
u64(self.state.proc_exited_tick_value(target)),
|
||||
u64(self.state.proc_exit_status_value(target)),
|
||||
u64(self.state.proc_runtime_ticks(target)),
|
||||
u64(self.state.proc_mem_bytes_value(target)),
|
||||
u64(self.state.proc_tty_index_value(target)),
|
||||
u64(self.state.proc_signal(target)),
|
||||
u64(self.state.proc_fault_vector_value(target)),
|
||||
u64(self.state.proc_fault_error_value(target)),
|
||||
u64(self.state.proc_fault_rip_value(target)),
|
||||
) + path_buf
|
||||
|
||||
return 1 if self._write_guest_bytes(uc, out_ptr, blob) else 0
|
||||
|
||||
def _proc_kill(self, uc: Uc, pid: int, signal: int) -> int:
|
||||
target = int(pid)
|
||||
if target <= 0:
|
||||
return u64_neg1()
|
||||
|
||||
current_state = self.state.proc_state_value(target)
|
||||
if current_state == 0:
|
||||
return u64_neg1()
|
||||
|
||||
effective_signal = int(signal) & 0xFF
|
||||
if effective_signal == 0:
|
||||
effective_signal = SIGTERM
|
||||
|
||||
self.state.set_proc_fault(target, effective_signal, 0, 0, 0)
|
||||
|
||||
if current_state == PROC_STATE_EXITED:
|
||||
return 1
|
||||
|
||||
if effective_signal == SIGCONT:
|
||||
if current_state == PROC_STATE_STOPPED:
|
||||
self.state.set_proc_pending(target)
|
||||
return 1
|
||||
|
||||
if effective_signal == SIGSTOP and current_state in (PROC_STATE_PENDING, PROC_STATE_STOPPED):
|
||||
self.state.set_proc_stopped(target)
|
||||
return 1
|
||||
|
||||
status = self._encode_signal_status(effective_signal, 0, 0)
|
||||
|
||||
if target == self.state.get_current_pid():
|
||||
self._exit_requested = True
|
||||
self._exit_status = u64(status)
|
||||
if effective_signal == SIGSTOP:
|
||||
self.state.set_proc_stopped(target)
|
||||
uc.emu_stop()
|
||||
return 1
|
||||
|
||||
if effective_signal == SIGSTOP:
|
||||
self.state.set_proc_stopped(target)
|
||||
return 1
|
||||
|
||||
self.state.mark_exited(target, status)
|
||||
return 1
|
||||
|
||||
def _wait_pid(self, uc: Uc, pid: int, out_ptr: int) -> int:
|
||||
wait_ret, status = self.state.wait_pid(int(pid))
|
||||
|
||||
@@ -885,6 +1261,190 @@ class CLeonOSWineNative:
|
||||
time.sleep(0)
|
||||
return self.state.timer_ticks()
|
||||
|
||||
def _fd_open(self, uc: Uc, path_ptr: int, flags: int, mode: int) -> int:
|
||||
_ = mode
|
||||
guest_path = self._normalize_guest_path(self._read_guest_cstring(uc, path_ptr, EXEC_PATH_MAX))
|
||||
open_flags = int(u64(flags))
|
||||
lower_path = guest_path.lower()
|
||||
fd_slot: int
|
||||
entry: FDEntry
|
||||
|
||||
if not guest_path.startswith("/"):
|
||||
return u64_neg1()
|
||||
|
||||
if not self._fd_access_mode_valid(open_flags):
|
||||
return u64_neg1()
|
||||
|
||||
if ((open_flags & O_TRUNC) != 0 or (open_flags & O_APPEND) != 0) and not self._fd_can_write(open_flags):
|
||||
return u64_neg1()
|
||||
|
||||
fd_slot = self._fd_find_free()
|
||||
if fd_slot < 0:
|
||||
return u64_neg1()
|
||||
|
||||
if lower_path == "/dev/tty":
|
||||
entry = FDEntry(kind="tty", flags=open_flags, offset=0, tty_index=self._tty_index)
|
||||
self._fds[fd_slot] = entry
|
||||
return fd_slot
|
||||
|
||||
if lower_path == "/dev/null":
|
||||
entry = FDEntry(kind="dev_null", flags=open_flags, offset=0, tty_index=self._tty_index)
|
||||
self._fds[fd_slot] = entry
|
||||
return fd_slot
|
||||
|
||||
if lower_path == "/dev/zero":
|
||||
entry = FDEntry(kind="dev_zero", flags=open_flags, offset=0, tty_index=self._tty_index)
|
||||
self._fds[fd_slot] = entry
|
||||
return fd_slot
|
||||
|
||||
if lower_path == "/dev/random":
|
||||
entry = FDEntry(kind="dev_random", flags=open_flags, offset=0, tty_index=self._tty_index)
|
||||
self._fds[fd_slot] = entry
|
||||
return fd_slot
|
||||
|
||||
host_path = self._guest_to_host(guest_path, must_exist=False)
|
||||
if host_path is None:
|
||||
return u64_neg1()
|
||||
|
||||
try:
|
||||
if not host_path.exists():
|
||||
if (open_flags & O_CREAT) == 0 or not self._fd_can_write(open_flags):
|
||||
return u64_neg1()
|
||||
host_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
host_path.write_bytes(b"")
|
||||
|
||||
if host_path.is_dir():
|
||||
return u64_neg1()
|
||||
|
||||
if (open_flags & O_TRUNC) != 0:
|
||||
host_path.write_bytes(b"")
|
||||
|
||||
offset = int(host_path.stat().st_size) if (open_flags & O_APPEND) != 0 else 0
|
||||
except Exception:
|
||||
return u64_neg1()
|
||||
|
||||
entry = FDEntry(kind="file", flags=open_flags, offset=offset, path=str(host_path), tty_index=self._tty_index)
|
||||
self._fds[fd_slot] = entry
|
||||
return fd_slot
|
||||
|
||||
def _fd_read(self, uc: Uc, fd: int, out_ptr: int, size: int) -> int:
|
||||
req = int(u64(size))
|
||||
entry = self._fd_lookup(int(fd))
|
||||
data: bytes
|
||||
|
||||
if req == 0:
|
||||
return 0
|
||||
|
||||
if out_ptr == 0:
|
||||
return u64_neg1()
|
||||
|
||||
if entry is None or not self._fd_can_read(entry.flags):
|
||||
return u64_neg1()
|
||||
|
||||
req = min(req, MAX_IO_READ)
|
||||
|
||||
if entry.kind == "tty":
|
||||
out = bytearray()
|
||||
while len(out) < req:
|
||||
key = self.state.pop_key()
|
||||
if key is None:
|
||||
break
|
||||
out.append(key & 0xFF)
|
||||
data = bytes(out)
|
||||
elif entry.kind == "dev_null":
|
||||
return 0
|
||||
elif entry.kind == "dev_zero":
|
||||
data = b"\x00" * req
|
||||
elif entry.kind == "dev_random":
|
||||
data = os.urandom(req)
|
||||
elif entry.kind == "file":
|
||||
try:
|
||||
with open(entry.path, "rb") as fh:
|
||||
fh.seek(entry.offset)
|
||||
data = fh.read(req)
|
||||
except Exception:
|
||||
return u64_neg1()
|
||||
else:
|
||||
return u64_neg1()
|
||||
|
||||
if len(data) == 0:
|
||||
return 0
|
||||
|
||||
if not self._write_guest_bytes(uc, int(out_ptr), data):
|
||||
return u64_neg1()
|
||||
|
||||
entry.offset += len(data)
|
||||
return len(data)
|
||||
|
||||
def _fd_write(self, uc: Uc, fd: int, buf_ptr: int, size: int) -> int:
|
||||
req = int(u64(size))
|
||||
entry = self._fd_lookup(int(fd))
|
||||
data: Optional[bytes]
|
||||
write_pos: int
|
||||
|
||||
if req == 0:
|
||||
return 0
|
||||
|
||||
if buf_ptr == 0:
|
||||
return u64_neg1()
|
||||
|
||||
if entry is None or not self._fd_can_write(entry.flags):
|
||||
return u64_neg1()
|
||||
|
||||
req = min(req, MAX_IO_READ)
|
||||
data = self._read_guest_bytes_exact(uc, int(buf_ptr), req)
|
||||
if data is None:
|
||||
return u64_neg1()
|
||||
|
||||
if entry.kind == "tty":
|
||||
self._host_write_bytes(data)
|
||||
entry.offset += len(data)
|
||||
return len(data)
|
||||
|
||||
if entry.kind in ("dev_null", "dev_zero", "dev_random"):
|
||||
entry.offset += len(data)
|
||||
return len(data)
|
||||
|
||||
if entry.kind != "file":
|
||||
return u64_neg1()
|
||||
|
||||
try:
|
||||
host_path = Path(entry.path)
|
||||
if not host_path.exists():
|
||||
if (entry.flags & O_CREAT) == 0 or not self._fd_can_write(entry.flags):
|
||||
return u64_neg1()
|
||||
host_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
host_path.write_bytes(b"")
|
||||
|
||||
with open(host_path, "r+b") as fh:
|
||||
write_pos = int(entry.offset)
|
||||
fh.seek(write_pos)
|
||||
fh.write(data)
|
||||
except Exception:
|
||||
return u64_neg1()
|
||||
|
||||
entry.offset += len(data)
|
||||
return len(data)
|
||||
|
||||
def _fd_close(self, fd: int) -> int:
|
||||
key = int(fd)
|
||||
if key not in self._fds:
|
||||
return u64_neg1()
|
||||
del self._fds[key]
|
||||
return 0
|
||||
|
||||
def _fd_dup(self, fd: int) -> int:
|
||||
src = self._fd_lookup(int(fd))
|
||||
if src is None:
|
||||
return u64_neg1()
|
||||
|
||||
slot = self._fd_find_free()
|
||||
if slot < 0:
|
||||
return u64_neg1()
|
||||
|
||||
self._fds[slot] = self._clone_fd_entry(src)
|
||||
return slot
|
||||
|
||||
@staticmethod
|
||||
def _truncate_item_text(text: str, max_bytes: int = EXEC_ITEM_MAX) -> str:
|
||||
if max_bytes <= 1:
|
||||
|
||||
@@ -6,7 +6,7 @@ import time
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Deque, Dict, List, Optional, Tuple
|
||||
|
||||
from .constants import u64
|
||||
from .constants import PROC_STATE_EXITED, PROC_STATE_PENDING, PROC_STATE_RUNNING, PROC_STATE_STOPPED, u64
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -37,13 +37,27 @@ class SharedKernelState:
|
||||
kbd_hotkey_switches: int = 0
|
||||
log_journal_cap: int = 256
|
||||
log_journal: Deque[str] = field(default_factory=lambda: collections.deque(maxlen=256))
|
||||
fs_write_max: int = 65536
|
||||
fs_write_max: int = 16 * 1024 * 1024
|
||||
|
||||
# syscall stats
|
||||
stats_lock: threading.Lock = field(default_factory=threading.Lock)
|
||||
stats_total_calls: int = 0
|
||||
stats_id_total: Dict[int, int] = field(default_factory=dict)
|
||||
stats_recent_window_cap: int = 256
|
||||
stats_recent_ring: Deque[int] = field(default_factory=lambda: collections.deque(maxlen=256))
|
||||
|
||||
# process table
|
||||
proc_lock: threading.Lock = field(default_factory=threading.Lock)
|
||||
proc_next_pid: int = 1
|
||||
proc_current_pid: int = 0
|
||||
proc_parents: Dict[int, int] = field(default_factory=dict)
|
||||
proc_status: Dict[int, Optional[int]] = field(default_factory=dict)
|
||||
proc_state: Dict[int, int] = field(default_factory=dict)
|
||||
proc_started_tick: Dict[int, int] = field(default_factory=dict)
|
||||
proc_exited_tick: Dict[int, int] = field(default_factory=dict)
|
||||
proc_mem_bytes: Dict[int, int] = field(default_factory=dict)
|
||||
proc_tty_index: Dict[int, int] = field(default_factory=dict)
|
||||
proc_path: Dict[int, str] = field(default_factory=dict)
|
||||
proc_argv: Dict[int, List[str]] = field(default_factory=dict)
|
||||
proc_env: Dict[int, List[str]] = field(default_factory=dict)
|
||||
proc_last_signal: Dict[int, int] = field(default_factory=dict)
|
||||
@@ -54,6 +68,32 @@ class SharedKernelState:
|
||||
def timer_ticks(self) -> int:
|
||||
return (time.monotonic_ns() - self.start_ns) // 1_000_000
|
||||
|
||||
def record_syscall(self, sid: int) -> None:
|
||||
key = int(u64(sid))
|
||||
|
||||
with self.stats_lock:
|
||||
self.stats_total_calls = int(u64(self.stats_total_calls + 1))
|
||||
self.stats_id_total[key] = int(u64(self.stats_id_total.get(key, 0) + 1))
|
||||
self.stats_recent_ring.append(key)
|
||||
|
||||
def stats_total(self) -> int:
|
||||
with self.stats_lock:
|
||||
return int(self.stats_total_calls)
|
||||
|
||||
def stats_id_count(self, sid: int) -> int:
|
||||
key = int(u64(sid))
|
||||
with self.stats_lock:
|
||||
return int(self.stats_id_total.get(key, 0))
|
||||
|
||||
def stats_recent_window(self) -> int:
|
||||
with self.stats_lock:
|
||||
return len(self.stats_recent_ring)
|
||||
|
||||
def stats_recent_id_count(self, sid: int) -> int:
|
||||
key = int(u64(sid))
|
||||
with self.stats_lock:
|
||||
return sum(1 for item in self.stats_recent_ring if item == key)
|
||||
|
||||
def push_key(self, key: int) -> None:
|
||||
with self.kbd_lock:
|
||||
if len(self.kbd_queue) >= self.kbd_queue_cap:
|
||||
@@ -94,6 +134,8 @@ class SharedKernelState:
|
||||
return list(self.log_journal)[index_from_oldest]
|
||||
|
||||
def alloc_pid(self, ppid: int) -> int:
|
||||
now = self.timer_ticks()
|
||||
|
||||
with self.proc_lock:
|
||||
pid = int(self.proc_next_pid)
|
||||
|
||||
@@ -107,6 +149,12 @@ class SharedKernelState:
|
||||
|
||||
self.proc_parents[pid] = int(ppid)
|
||||
self.proc_status[pid] = None
|
||||
self.proc_state[pid] = PROC_STATE_PENDING
|
||||
self.proc_started_tick[pid] = now
|
||||
self.proc_exited_tick[pid] = 0
|
||||
self.proc_mem_bytes[pid] = 0
|
||||
self.proc_tty_index[pid] = int(self.tty_active)
|
||||
self.proc_path[pid] = ""
|
||||
self.proc_argv[pid] = []
|
||||
self.proc_env[pid] = []
|
||||
self.proc_last_signal[pid] = 0
|
||||
@@ -123,12 +171,51 @@ class SharedKernelState:
|
||||
with self.proc_lock:
|
||||
return int(self.proc_current_pid)
|
||||
|
||||
def set_proc_running(self, pid: int, path: Optional[str], tty_index: int) -> None:
|
||||
if pid <= 0:
|
||||
return
|
||||
|
||||
now = self.timer_ticks()
|
||||
|
||||
with self.proc_lock:
|
||||
if pid not in self.proc_status:
|
||||
return
|
||||
|
||||
self.proc_state[pid] = PROC_STATE_RUNNING
|
||||
if self.proc_started_tick.get(pid, 0) == 0:
|
||||
self.proc_started_tick[pid] = now
|
||||
self.proc_tty_index[pid] = int(tty_index)
|
||||
if path:
|
||||
self.proc_path[pid] = str(path)
|
||||
|
||||
def mark_exited(self, pid: int, status: int) -> None:
|
||||
if pid <= 0:
|
||||
return
|
||||
|
||||
with self.proc_lock:
|
||||
self.proc_status[int(pid)] = int(u64(status))
|
||||
self.proc_state[int(pid)] = PROC_STATE_EXITED
|
||||
self.proc_exited_tick[int(pid)] = self.timer_ticks()
|
||||
|
||||
def set_proc_stopped(self, pid: int) -> None:
|
||||
if pid <= 0:
|
||||
return
|
||||
|
||||
with self.proc_lock:
|
||||
if pid not in self.proc_status:
|
||||
return
|
||||
if self.proc_state.get(pid, PROC_STATE_PENDING) != PROC_STATE_EXITED:
|
||||
self.proc_state[pid] = PROC_STATE_STOPPED
|
||||
|
||||
def set_proc_pending(self, pid: int) -> None:
|
||||
if pid <= 0:
|
||||
return
|
||||
|
||||
with self.proc_lock:
|
||||
if pid not in self.proc_status:
|
||||
return
|
||||
if self.proc_state.get(pid, PROC_STATE_PENDING) != PROC_STATE_EXITED:
|
||||
self.proc_state[pid] = PROC_STATE_PENDING
|
||||
|
||||
def wait_pid(self, pid: int) -> Tuple[int, int]:
|
||||
with self.proc_lock:
|
||||
@@ -151,6 +238,8 @@ class SharedKernelState:
|
||||
return
|
||||
self.proc_argv[pid] = [str(item) for item in argv]
|
||||
self.proc_env[pid] = [str(item) for item in env]
|
||||
if argv:
|
||||
self.proc_path[pid] = str(argv[0])
|
||||
|
||||
def set_proc_fault(self, pid: int, signal: int, vector: int, error_code: int, rip: int) -> None:
|
||||
if pid <= 0:
|
||||
@@ -164,6 +253,68 @@ class SharedKernelState:
|
||||
self.proc_fault_error[pid] = int(u64(error_code))
|
||||
self.proc_fault_rip[pid] = int(u64(rip))
|
||||
|
||||
def proc_count(self) -> int:
|
||||
with self.proc_lock:
|
||||
return len(self.proc_status)
|
||||
|
||||
def proc_pid_at(self, index: int) -> Optional[int]:
|
||||
if index < 0:
|
||||
return None
|
||||
|
||||
with self.proc_lock:
|
||||
ordered = sorted(self.proc_status.keys())
|
||||
if index >= len(ordered):
|
||||
return None
|
||||
return int(ordered[index])
|
||||
|
||||
def proc_state_value(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
return int(self.proc_state.get(int(pid), 0))
|
||||
|
||||
def proc_ppid(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
return int(self.proc_parents.get(int(pid), 0))
|
||||
|
||||
def proc_started_tick_value(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
return int(self.proc_started_tick.get(int(pid), 0))
|
||||
|
||||
def proc_exited_tick_value(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
return int(self.proc_exited_tick.get(int(pid), 0))
|
||||
|
||||
def proc_exit_status_value(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
value = self.proc_status.get(int(pid))
|
||||
return int(value) if value is not None else 0
|
||||
|
||||
def proc_runtime_ticks(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
start = int(self.proc_started_tick.get(int(pid), 0))
|
||||
state = int(self.proc_state.get(int(pid), 0))
|
||||
end = int(self.proc_exited_tick.get(int(pid), 0))
|
||||
|
||||
if start == 0:
|
||||
return 0
|
||||
|
||||
if state == PROC_STATE_EXITED and end >= start:
|
||||
return end - start
|
||||
|
||||
now = self.timer_ticks()
|
||||
return 0 if now < start else now - start
|
||||
|
||||
def proc_mem_bytes_value(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
return int(self.proc_mem_bytes.get(int(pid), 0))
|
||||
|
||||
def proc_tty_index_value(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
return int(self.proc_tty_index.get(int(pid), 0))
|
||||
|
||||
def proc_path_value(self, pid: int) -> str:
|
||||
with self.proc_lock:
|
||||
return str(self.proc_path.get(int(pid), ""))
|
||||
|
||||
def proc_argc(self, pid: int) -> int:
|
||||
with self.proc_lock:
|
||||
return len(self.proc_argv.get(int(pid), []))
|
||||
|
||||
Reference in New Issue
Block a user