--- /dev/null
+#ifndef SYSCALL
+# error "SYSCALL missing pointer type"
+#endif
+
+SYSCALL 0
+SYSCALL __lxsys_fork /* 1 */
+SYSCALL __lxsys_yield
+SYSCALL __lxsys_sbrk
+SYSCALL __lxsys_brk
+SYSCALL __lxsys_getpid /* 5 */
+SYSCALL __lxsys_getppid
+SYSCALL __lxsys_sleep
+SYSCALL __lxsys_exit
+SYSCALL __lxsys_wait
+SYSCALL __lxsys_waitpid /* 10 */
+SYSCALL __lxsys_sigreturn
+SYSCALL __lxsys_sigprocmask
+SYSCALL __lxsys_sys_sigaction
+SYSCALL __lxsys_pause
+SYSCALL __lxsys_kill /* 15 */
+SYSCALL __lxsys_alarm
+SYSCALL __lxsys_sigpending
+SYSCALL __lxsys_sigsuspend
+SYSCALL __lxsys_open
+SYSCALL __lxsys_close /* 20 */
+SYSCALL __lxsys_read
+SYSCALL __lxsys_write
+SYSCALL __lxsys_sys_readdir
+SYSCALL __lxsys_mkdir
+SYSCALL __lxsys_lseek /* 25 */
+SYSCALL __lxsys_geterrno
+SYSCALL __lxsys_readlink
+SYSCALL __lxsys_readlinkat
+SYSCALL __lxsys_rmdir
+SYSCALL __lxsys_unlink /* 30 */
+SYSCALL __lxsys_unlinkat
+SYSCALL __lxsys_link
+SYSCALL __lxsys_fsync
+SYSCALL __lxsys_dup
+SYSCALL __lxsys_dup2 /* 35 */
+SYSCALL __lxsys_realpathat
+SYSCALL __lxsys_symlink
+SYSCALL __lxsys_chdir
+SYSCALL __lxsys_fchdir
+SYSCALL __lxsys_getcwd /* 40 */
+SYSCALL __lxsys_rename
+SYSCALL __lxsys_mount
+SYSCALL __lxsys_unmount
+SYSCALL __lxsys_getxattr
+SYSCALL __lxsys_setxattr /* 45 */
+SYSCALL __lxsys_fgetxattr
+SYSCALL __lxsys_fsetxattr
+SYSCALL __lxsys_ioctl
+SYSCALL __lxsys_getpgid
+SYSCALL __lxsys_setpgid /* 50 */
+SYSCALL __lxsys_syslog
+SYSCALL __lxsys_sys_mmap
+SYSCALL __lxsys_munmap
+SYSCALL __lxsys_execve
+SYSCALL __lxsys_fstat /* 55 */
+SYSCALL __lxsys_pollctl
+SYSCALL __lxsys_th_create
+SYSCALL __lxsys_th_self
+SYSCALL __lxsys_th_exit
+SYSCALL __lxsys_th_join /* 60 */
+SYSCALL __lxsys_th_kill
+SYSCALL __lxsys_th_detach
+SYSCALL __lxsys_th_sigmask
+SYSCALL __lxsys_getuid
+SYSCALL __lxsys_getgid
+SYSCALL __lxsys_geteuid
+SYSCALL __lxsys_getegid
+SYSCALL __lxsys_getgroups
+SYSCALL __lxsys_setuid
+SYSCALL __lxsys_setgid
+SYSCALL __lxsys_seteuid
+SYSCALL __lxsys_setegid
+SYSCALL __lxsys_setgroups
\ No newline at end of file
"gdbstub.c",
"trace.c",
"hart.c",
- "failsafe.S"
+ "failsafe.S",
+ "syscall_lut.S"
])
sources({
#define __ASM__
#include <lunaix/syscall.h>
-#include "syscall_nr.inc"
.section .text
.type syscall_hndlr, @function
jae 2f
shll $2, %eax
- addl $syscall_table, %eax
+ addl $__syscall_table, %eax
cmpl $0, (%eax)
jne 1f
2:
#define __ASM__
#include <lunaix/syscall.h>
-#include "syscall_nr.inc"
#include "asm/variants/interrupt64.S.inc"
.section .text
jae 2f
shlq $3, %rax // %rax * 8
- movabsq $syscall_table, %r8
+ movabsq $__syscall_table, %r8
addq %r8, %rax
cmpq $0, (%rax)
jne 1f
--- /dev/null
+#define __ASM__
+#include <lunaix/syscall.h>
+
+#ifdef CONFIG_ARCH_X86_64
+# define SYSCALL .8byte
+# define SIZE 8
+#else
+# define SIZE 4
+# define SYSCALL .4byte
+#endif
+
+.section .data
+ .global __syscall_table
+ __syscall_table:
+ 1:
+ #include "syscall_nr.inc"
+ 2:
+ .rept __SYSCALL_MAX - (2b - 1b) / SIZE
+ .long 0
+ .endr
\ No newline at end of file
-#ifdef CONFIG_ARCH_X86_64
-# define PTR .8byte
-# define SIZE 8
-#else
-# define PTR .4byte
-# define SIZE 4
-#endif
+#include <asm-generic/syscall_nr.inc>
-.section .data
- syscall_table:
- 1:
- PTR 0
- PTR __lxsys_fork /* 1 */
- PTR __lxsys_yield
- PTR __lxsys_sbrk
- PTR __lxsys_brk
- PTR __lxsys_getpid /* 5 */
- PTR __lxsys_getppid
- PTR __lxsys_sleep
- PTR __lxsys_exit
- PTR __lxsys_wait
- PTR __lxsys_waitpid /* 10 */
- PTR __lxsys_sigreturn
- PTR __lxsys_sigprocmask
- PTR __lxsys_sys_sigaction
- PTR __lxsys_pause
- PTR __lxsys_kill /* 15 */
- PTR __lxsys_alarm
- PTR __lxsys_sigpending
- PTR __lxsys_sigsuspend
- PTR __lxsys_open
- PTR __lxsys_close /* 20 */
- PTR __lxsys_read
- PTR __lxsys_write
- PTR __lxsys_sys_readdir
- PTR __lxsys_mkdir
- PTR __lxsys_lseek /* 25 */
- PTR __lxsys_geterrno
- PTR __lxsys_readlink
- PTR __lxsys_readlinkat
- PTR __lxsys_rmdir
- PTR __lxsys_unlink /* 30 */
- PTR __lxsys_unlinkat
- PTR __lxsys_link
- PTR __lxsys_fsync
- PTR __lxsys_dup
- PTR __lxsys_dup2 /* 35 */
- PTR __lxsys_realpathat
- PTR __lxsys_symlink
- PTR __lxsys_chdir
- PTR __lxsys_fchdir
- PTR __lxsys_getcwd /* 40 */
- PTR __lxsys_rename
- PTR __lxsys_mount
- PTR __lxsys_unmount
- PTR __lxsys_getxattr
- PTR __lxsys_setxattr /* 45 */
- PTR __lxsys_fgetxattr
- PTR __lxsys_fsetxattr
- PTR __lxsys_ioctl
- PTR __lxsys_getpgid
- PTR __lxsys_setpgid /* 50 */
- PTR __lxsys_syslog
- PTR __lxsys_sys_mmap
- PTR __lxsys_munmap
- PTR __lxsys_execve
- PTR __lxsys_fstat /* 55 */
- PTR __lxsys_pollctl
- PTR __lxsys_th_create
- PTR __lxsys_th_self
- PTR __lxsys_th_exit
- PTR __lxsys_th_join /* 60 */
- PTR __lxsys_th_kill
- PTR __lxsys_th_detach
- PTR __lxsys_th_sigmask
- 2:
- .rept __SYSCALL_MAX - (2b - 1b) / SIZE
- .long 0
- .endr
\ No newline at end of file
+// arch specifics syscalls goes here
--- /dev/null
+#ifndef __LUNAIX_LIMITS_H
+#define __LUNAIX_LIMITS_H
+
+#define NGROUPS_MAX 128
+
+#endif /* __LUNAIX_LIMITS_H */
#include <lunaix/types.h>
#include <lunaix/spike.h>
#include <lunaix/hart_state.h>
+#include <lunaix/usrscope.h>
+
#include <stdint.h>
{
/*
Any change to *critical section*, including layout, size
- must be reflected in arch/x86/interrupt.S.inc to avoid
+ must be reflected in arch/<arch>/interrupt.S.inc to avoid
disaster!
*/
struct
pid_t pgid;
time_t created;
+ uid_t euid;
+ uid_t suid;
+ gid_t egid;
+ gid_t sgid;
+
+ struct user_scope uscope;
+
int state;
int exit_code;
};
return stats->last_entry - stats->last_leave;
}
+static inline struct user_scope*
+current_user_scope()
+{
+ return &__current->uscope;
+}
+
+static inline uid_t must_inline
+current_euid()
+{
+ return __current->euid;
+}
+
+static inline gid_t must_inline
+current_egid()
+{
+ return __current->egid;
+}
#endif /* __LUNAIX_PROCESS_H */
#define __LUNAIX_TYPES_H
#include <lunaix/compiler.h>
+#include <lunaix/limits.h>
#include <stdarg.h>
#include <usr/lunaix/types.h>
typedef unsigned long ptr_t;
typedef unsigned long reg_t;
+typedef unsigned int uid_t;
+typedef unsigned int gid_t;
+
#ifndef CONFIG_ARCH_BITS_64
typedef unsigned long long u64_t;
#else
--- /dev/null
+#ifndef __LUNAIX_USERCAPS_H
+#define __LUNAIX_USERCAPS_H
+
+typedef unsigned long caps_t;
+
+/*
+ * Definition of user capabilities (withdrawn draft POSIX.1e)
+ */
+
+#define CAP_SETUID 0
+#define CAP_SETGID 1
+#define CAP_CHOWN 2
+#define CAP_DAC_OVERRIDE 3
+#define CAP_FSETID 4
+#define CAP_KILL 5
+#define CAP_SYS_CHROOT 6
+#define CAP_SYS_TIM 7
+
+#endif /* __LUNAIX_USERCAPS_H */
--- /dev/null
+#ifndef __LUNAIX_USRSCOPE_H
+#define __LUNAIX_USRSCOPE_H
+
+#include <lunaix/types.h>
+#include "usercaps.h"
+
+struct ugroup_obj
+{
+ gid_t* list;
+ unsigned int maxcap;
+ unsigned int refs;
+};
+
+struct user_scope
+{
+ uid_t ruid;
+ gid_t rgid;
+ caps_t capabilities;
+
+ struct ugroup_obj* grps;
+};
+
+/*
+ Process ACL check result.
+ The encoding here is designed to be the mask for file ACL value
+*/
+enum acl_match
+{
+ ACL_MATCH_U = 0b111000000, // (U)ser
+ ACL_MATCH_G = 0b000111000, // (G)roup
+ ACL_NO_MATCH = 0b000000111, // (O)ther
+};
+
+#define user_groups(uscope) ((uscope)->grps)
+
+#define grp_list_end ((gid_t)-1)
+
+int
+uscope_setgroups(struct user_scope* proc_usr,
+ const gid_t* grps, unsigned int len);
+
+void
+uscope_copy(struct user_scope* from, struct user_scope* to);
+
+bool
+uscope_membership(struct user_scope* proc_usr, gid_t gid);
+
+enum acl_match
+check_current_acl(uid_t desired_u, gid_t desired_g);
+
+static inline bool
+uscope_with_capability(const struct user_scope* proc_usr, caps_t cap)
+{
+ return !!(proc_usr->capabilities & (1UL << cap));
+}
+
+#endif /* __LUNAIX_USRSCOPE_H */
#define EAGAIN -30
#define EDEADLK -31
#define EDQUOT -32
+#define EPERM -33
#endif /* __LUNAIX_STATUS_H */
"bcache.c",
"syscall.c",
"changeling.c",
+ "usrscope.c",
"kprint/kp_records.c",
"kprint/kprintf.c",
"time/clock.c",
LOG_MODULE("PROC")
-__DEFINE_LXSYSCALL(pid_t, getpid)
-{
- return __current->pid;
-}
-
-__DEFINE_LXSYSCALL(pid_t, getppid)
-{
- return __current->parent->pid;
-}
-
-__DEFINE_LXSYSCALL(pid_t, getpgid)
-{
- return __current->pgid;
-}
-
-__DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid)
-{
- struct proc_info* proc = pid ? get_process(pid) : __current;
-
- if (!proc) {
- syscall_result(EINVAL);
- return -1;
- }
-
- pgid = pgid ? pgid : proc->pid;
-
- struct proc_info* gruppenfuhrer = get_process(pgid);
-
- if (!gruppenfuhrer || proc->pgid == gruppenfuhrer->pid) {
- syscall_result(EINVAL);
- return -1;
- }
-
- llist_delete(&proc->grp_member);
- llist_append(&gruppenfuhrer->grp_member, &proc->grp_member);
-
- proc->pgid = pgid;
- return 0;
-}
-
int
spawn_process(struct thread** created, ptr_t entry, bool with_ustack)
{
ptr_t proc_vmroot() {
return __current->mm->vmroot;
+}
+
+__DEFINE_LXSYSCALL(pid_t, getpid)
+{
+ return __current->pid;
+}
+
+__DEFINE_LXSYSCALL(pid_t, getppid)
+{
+ return __current->parent->pid;
+}
+
+__DEFINE_LXSYSCALL(pid_t, getpgid)
+{
+ return __current->pgid;
+}
+
+__DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid)
+{
+ struct proc_info* proc = pid ? get_process(pid) : __current;
+
+ if (!proc) {
+ syscall_result(EINVAL);
+ return -1;
+ }
+
+ pgid = pgid ? pgid : proc->pid;
+
+ struct proc_info* gruppenfuhrer = get_process(pgid);
+
+ if (!gruppenfuhrer || proc->pgid == gruppenfuhrer->pid) {
+ syscall_result(EINVAL);
+ return -1;
+ }
+
+ llist_delete(&proc->grp_member);
+ llist_append(&gruppenfuhrer->grp_member, &proc->grp_member);
+
+ proc->pgid = pgid;
+ return 0;
+}
+
+static inline bool
+__can_change_real_id(const struct user_scope* procu, caps_t id_cap) {
+ if (uscope_with_capability(procu, id_cap)) {
+ return true;
+ }
+
+ if (check_current_acl(0, 0) != ACL_NO_MATCH) {
+ return true;
+ }
+
+ return false;
+}
+
+__DEFINE_LXSYSCALL1(int, setuid, uid_t, uid)
+{
+ struct user_scope* procu;
+
+ procu = current_user_scope();
+
+ if (__can_change_real_id(procu, CAP_SETUID))
+ {
+ procu->ruid = uid;
+ }
+
+ __current->suid = uid;
+ __current->euid = uid;
+
+ return 0;
+}
+
+__DEFINE_LXSYSCALL1(int, setgid, gid_t, gid)
+{
+ struct user_scope* procu;
+
+ procu = current_user_scope();
+
+ if (__can_change_real_id(procu, CAP_SETGID))
+ {
+ procu->rgid = gid;
+ }
+
+ __current->sgid = gid;
+ __current->egid = gid;
+
+ return 0;
+}
+
+__DEFINE_LXSYSCALL1(int, seteuid, uid_t, euid)
+{
+ __current->euid = euid;
+
+ return 0;
+}
+
+__DEFINE_LXSYSCALL1(int, setegid, gid_t, egid)
+{
+ __current->egid = egid;
+
+ return 0;
+}
+
+__DEFINE_LXSYSCALL2(int, setgroups, const gid_t*, gids, unsigned int, len)
+{
+ struct user_scope* procu;
+
+ procu = current_user_scope();
+
+ if (check_current_acl(0, 0) == ACL_NO_MATCH) {
+ return EPERM;
+ }
+
+ if (uscope_with_capability(procu, CAP_SETGID)) {
+ return EPERM;
+ }
+
+ return uscope_setgroups(procu, gids, len);
+}
+
+
+__DEFINE_LXSYSCALL(uid_t, getuid)
+{
+ return current_user_scope()->ruid;
+}
+
+__DEFINE_LXSYSCALL(gid_t, getgid)
+{
+ return current_user_scope()->rgid;
+}
+
+__DEFINE_LXSYSCALL(uid_t, geteuid)
+{
+ return __current->euid;
+}
+
+__DEFINE_LXSYSCALL(gid_t, getegid)
+{
+ return __current->egid;
+}
+
+__DEFINE_LXSYSCALL2(int, getgroups, gid_t*, out_buf, unsigned int, len)
+{
+ struct user_scope* procu;
+ struct ugroup_obj* gobj;
+
+ procu = current_user_scope();
+ gobj = user_groups(procu);
+
+ assert(gobj);
+ len = MIN(gobj->maxcap, len);
+
+ unsigned i = 0;
+ for (; i < len && gobj->list[i] != grp_list_end; i++)
+ {
+ out_buf[i] = gobj->list[i];
+ }
+
+ return i + 1;
}
\ No newline at end of file
--- /dev/null
+#include <lunaix/usrscope.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/status.h>
+#include <lunaix/spike.h>
+#include <lunaix/process.h>
+
+#include <klibc/string.h>
+
+#define GLIST_INIT_LEN 8
+
+static struct ugroup_obj*
+__alloc_groups_obj(unsigned int len)
+{
+ unsigned int size;
+ struct ugroup_obj* ugo;
+
+ assert(len >= GLIST_INIT_LEN);
+
+ ugo = valloc(sizeof(*ugo));
+ ugo->refs = 1;
+
+ size = len * sizeof(gid_t);
+ ugo->list = valloc(size);
+ ugo->maxcap = size;
+
+ memset(ugo->list, grp_list_end, size);
+ return ugo;
+}
+
+static inline void
+__ref_groups_obj(struct ugroup_obj* ugo)
+{
+ ugo->refs++;
+}
+
+static void
+__unref_groups_obj(struct ugroup_obj* ugo)
+{
+ ugo->refs--;
+ if (ugo->refs) {
+ return;
+ }
+
+ vfree_safe(ugo->list);
+ vfree(ugo);
+}
+
+static struct ugroup_obj*
+__modify_group_obj(struct user_scope* procu, unsigned int new_len)
+{
+ struct ugroup_obj* ugo;
+
+ ugo = procu->grps;
+ if (!ugo) {
+ return __alloc_groups_obj(GLIST_INIT_LEN);
+ }
+
+ __unref_groups_obj(ugo);
+
+ new_len = MAX(new_len, ugo->maxcap);
+ ugo = __alloc_groups_obj(new_len);
+ procu->grps = ugo;
+
+ return ugo;
+}
+
+int
+uscope_setgroups(struct user_scope* proc_usr,
+ const gid_t* grps, unsigned int len)
+{
+ struct ugroup_obj* ugo;
+
+ if (len > NGROUPS_MAX) {
+ return E2BIG;
+ }
+
+ ugo = __modify_group_obj(proc_usr, len);
+ memcpy(ugo->list, grps, len * sizeof(gid_t));
+
+ return 0;
+}
+
+bool
+uscope_membership(struct user_scope* proc_usr, gid_t gid)
+{
+ struct ugroup_obj* ugo;
+
+ ugo = proc_usr->grps;
+ if (unlikely(!ugo)) {
+ return false;
+ }
+
+ for (unsigned i = 0; i < ugo->maxcap; i++)
+ {
+ if (ugo->list[i] != grp_list_end) {
+ break;
+ }
+
+ if (ugo->list[i] == gid) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+uscope_copy(struct user_scope* to, struct user_scope* from)
+{
+ __ref_groups_obj(from->grps);
+ memcpy(to, from, sizeof(*to));
+}
+
+
+enum acl_match
+check_current_acl(uid_t desired_u, gid_t desired_g)
+{
+ struct user_scope* uscope;
+
+ if (!__current->euid || __current->euid == desired_u)
+ {
+ return ACL_MATCH_U;
+ }
+
+ if (__current->egid == desired_g) {
+ return ACL_MATCH_G;
+ }
+
+ uscope = current_user_scope();
+ if (uscope_membership(uscope, desired_g)) {
+ return ACL_MATCH_G;
+ }
+
+ return ACL_NO_MATCH;
+}
\ No newline at end of file