From 2bf00d9b3f5a694bdc6d8b2c76be7a278f02f40b Mon Sep 17 00:00:00 2001 From: PucklaJ Date: Wed, 24 Apr 2024 15:15:38 +0200 Subject: [PATCH 1/7] [sys/linux]: Add flags parameter to execveat and fix execve on arm64 --- core/sys/linux/constants.odin | 2 ++ core/sys/linux/sys.odin | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index 51f7db68f..389ff1417 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -5,6 +5,8 @@ package linux that relative paths are relative to current directory. */ AT_FDCWD :: Fd(-100) +AT_EMPTY_PATH :: 0x1000 +AT_SYMLINK_NOFOLLOW :: 0x100 /* Special value to put into timespec for utimensat() to set timestamp to the current time. diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 63fb3b776..22fe2ab50 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -769,8 +769,7 @@ execve :: proc "contextless" (name: cstring, argv: [^]cstring, envp: [^]cstring) ret := syscall(SYS_execve, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) return Errno(-ret) } else { - ret := syscall(SYS_execveat, AT_FDCWD, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) - return Errno(-ret) + return execveat(AT_FDCWD, name, argv, envp, 0) } } @@ -2803,8 +2802,8 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er Execute program relative to a directory file descriptor. Available since Linux 3.19. */ -execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) { - ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) +execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: i32) -> (Errno) { + ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, flags) return Errno(-ret) } From a2ad66cd9d5e93ce8789d1a1e088b254922cd88f Mon Sep 17 00:00:00 2001 From: PucklaJ Date: Wed, 24 Apr 2024 15:32:43 +0200 Subject: [PATCH 2/7] [sys/linux]: Add clone syscall and use it in fork for arm64 --- core/sys/linux/sys.odin | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 22fe2ab50..1653a65dd 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -729,7 +729,22 @@ getsockopt :: proc { getsockopt_base, } -// TODO(flysand): clone (probably not in this PR, maybe not ever) +/* + Creates a new ("child") process, in a manner similar to fork. + Available since Linux 1.0? (<2.4) + + Note(flysand): this syscall is not documented, but the bottom 8 bits of flags + are for exit signal +*/ +clone :: proc "contextless" (flags: u64, stack: rawptr, parent_tid, child_tid: ^i32, tls: u64) -> (i64, Errno) { + when ODIN_ARCH == .amd64 { + ret := syscall(SYS_clone, flags, stack, parent_tid, child_tid, tls) + return errno_unwrap(ret, i64) + } else { + ret := syscall(SYS_clone, flags, stack, parent_tid, tls, child_tid) + return errno_unwrap(ret, i64) + } +} /* Creates a copy of the running process. @@ -737,10 +752,9 @@ getsockopt :: proc { */ fork :: proc "contextless" () -> (Pid, Errno) { when ODIN_ARCH == .arm64 { - // Note(flysand): this syscall is not documented, but the bottom 8 bits of flags - // are for exit signal - ret := syscall(SYS_clone, Signal.SIGCHLD) - return errno_unwrap(ret, Pid) + ret, err := clone(u64(Signal.SIGCHLD), nil, nil, nil, 0) + if err != .NONE do return Pid(ret), err + return Pid(ret), .NONE } else { ret := syscall(SYS_fork) return errno_unwrap(ret, Pid) From b0fe6212bb1f55c367991c23c22cb1fa35da34e4 Mon Sep 17 00:00:00 2001 From: PucklaJ Date: Sat, 27 Apr 2024 13:21:04 +0200 Subject: [PATCH 3/7] [sys/linux]: Fix return statement --- core/sys/linux/sys.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 1653a65dd..5b2948c8f 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -754,7 +754,7 @@ fork :: proc "contextless" () -> (Pid, Errno) { when ODIN_ARCH == .arm64 { ret, err := clone(u64(Signal.SIGCHLD), nil, nil, nil, 0) if err != .NONE do return Pid(ret), err - return Pid(ret), .NONE + return Pid(ret), err } else { ret := syscall(SYS_fork) return errno_unwrap(ret, Pid) From 7f301790d0e1828082f8f314475a332084026dd5 Mon Sep 17 00:00:00 2001 From: PucklaJ Date: Sun, 28 Apr 2024 11:48:18 +0200 Subject: [PATCH 4/7] [sys/linux] Change flags parameter of execveat to bit_set --- core/sys/linux/bits.odin | 8 ++++++++ core/sys/linux/constants.odin | 2 -- core/sys/linux/sys.odin | 6 +++--- core/sys/linux/types.odin | 5 +++++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index ad519e1cd..88c4f40c9 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -1756,3 +1756,11 @@ EPoll_Ctl_Opcode :: enum i32 { DEL = 2, MOD = 3, } + +/* + Bits for execveat(2) flags. +*/ +Execveat_Flags_Bits :: enum { + AT_SYMLINK_NOFOLLOW = 8, + AT_EMPTY_PATH = 12, +} diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index 389ff1417..51f7db68f 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -5,8 +5,6 @@ package linux that relative paths are relative to current directory. */ AT_FDCWD :: Fd(-100) -AT_EMPTY_PATH :: 0x1000 -AT_SYMLINK_NOFOLLOW :: 0x100 /* Special value to put into timespec for utimensat() to set timestamp to the current time. diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 5b2948c8f..a9ec3c24e 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -783,7 +783,7 @@ execve :: proc "contextless" (name: cstring, argv: [^]cstring, envp: [^]cstring) ret := syscall(SYS_execve, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) return Errno(-ret) } else { - return execveat(AT_FDCWD, name, argv, envp, 0) + return execveat(AT_FDCWD, name, argv, envp, nil) } } @@ -2816,8 +2816,8 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er Execute program relative to a directory file descriptor. Available since Linux 3.19. */ -execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: i32) -> (Errno) { - ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, flags) +execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: Execveat_Flags) -> (Errno) { + ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, transmute(i32) flags) return Errno(-ret) } diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin index 677bac7e0..e7ecfc609 100644 --- a/core/sys/linux/types.odin +++ b/core/sys/linux/types.odin @@ -1238,3 +1238,8 @@ EPoll_Event :: struct #packed { events: EPoll_Event_Kind, data: EPoll_Data, } + +/* + Flags for execveat(2) syscall. +*/ +Execveat_Flags :: bit_set[Execveat_Flags_Bits; i32] From d1a205e2cfb44df31801201fc8818e02527b45dc Mon Sep 17 00:00:00 2001 From: PucklaJ Date: Sun, 28 Apr 2024 11:56:19 +0200 Subject: [PATCH 5/7] [sys/linux]: Remove clone syscall and call it directly in fork on arm64 --- core/sys/linux/sys.odin | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index a9ec3c24e..57827d45c 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -729,32 +729,14 @@ getsockopt :: proc { getsockopt_base, } -/* - Creates a new ("child") process, in a manner similar to fork. - Available since Linux 1.0? (<2.4) - - Note(flysand): this syscall is not documented, but the bottom 8 bits of flags - are for exit signal -*/ -clone :: proc "contextless" (flags: u64, stack: rawptr, parent_tid, child_tid: ^i32, tls: u64) -> (i64, Errno) { - when ODIN_ARCH == .amd64 { - ret := syscall(SYS_clone, flags, stack, parent_tid, child_tid, tls) - return errno_unwrap(ret, i64) - } else { - ret := syscall(SYS_clone, flags, stack, parent_tid, tls, child_tid) - return errno_unwrap(ret, i64) - } -} - /* Creates a copy of the running process. Available since Linux 1.0. */ fork :: proc "contextless" () -> (Pid, Errno) { when ODIN_ARCH == .arm64 { - ret, err := clone(u64(Signal.SIGCHLD), nil, nil, nil, 0) - if err != .NONE do return Pid(ret), err - return Pid(ret), err + ret := syscall(SYS_clone, u64(Signal.SIGCHLD), cast(rawptr) nil, cast(rawptr) nil, cast(rawptr) nil, u64(0)) + return errno_unwrap(ret, Pid) } else { ret := syscall(SYS_fork) return errno_unwrap(ret, Pid) From 37b026cb9bdd29aa657a54b76d2595bef40ff8c8 Mon Sep 17 00:00:00 2001 From: PucklaJ Date: Sun, 28 Apr 2024 12:00:40 +0200 Subject: [PATCH 6/7] [sys/linux] Directly call syscall in execve on arm64 --- core/sys/linux/sys.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 57827d45c..887feb49d 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -765,7 +765,8 @@ execve :: proc "contextless" (name: cstring, argv: [^]cstring, envp: [^]cstring) ret := syscall(SYS_execve, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp) return Errno(-ret) } else { - return execveat(AT_FDCWD, name, argv, envp, nil) + ret := syscall(SYS_execveat, AT_FDCWD, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, i32(0)) + return Errno(-ret) } } From 1873f7215dd42e4ee628fcd0947579bf42557dbe Mon Sep 17 00:00:00 2001 From: PucklaJ Date: Mon, 22 Jul 2024 11:03:25 +0200 Subject: [PATCH 7/7] [sys/linux]: Change execveat flags type to Execveat_Flags --- core/sys/linux/sys.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 03c34223c..f7cacc544 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -2814,7 +2814,7 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er Execute program relative to a directory file descriptor. Available since Linux 3.19. */ -execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: FD_Flags = {}) -> (Errno) { +execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: Execveat_Flags = {}) -> (Errno) { ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, transmute(i32) flags) return Errno(-ret) }