Framework for exporting system header to user space (#59)
[lunaix-os.git] / lunaix-os / kernel / process / process.c
1 #include <klibc/string.h>
2 #include <lunaix/clock.h>
3 #include <lunaix/mm/mmap.h>
4 #include <lunaix/mm/vmm.h>
5 #include <lunaix/mm/region.h>
6 #include <lunaix/mm/valloc.h>
7 #include <lunaix/process.h>
8 #include <lunaix/spike.h>
9 #include <lunaix/status.h>
10 #include <lunaix/syscall.h>
11 #include <lunaix/syslog.h>
12 #include <lunaix/exec.h>
13 #include <lunaix/fs.h>
14
15 #include <asm/abi.h>
16 #include <asm/mm_defs.h>
17
18 LOG_MODULE("PROC")
19
20 int
21 spawn_process(struct thread** created, ptr_t entry, bool with_ustack) 
22 {
23     struct proc_info* kproc = alloc_process();
24     struct proc_mm* mm = vmspace(kproc);
25
26     procvm_initvms_mount(mm);
27
28     struct thread* kthread = create_thread(kproc, with_ustack);
29
30     if (!kthread) {
31         procvm_unmount(mm);
32         delete_process(kproc);
33         return -1;
34     }
35
36     commit_process(kproc);
37     start_thread(kthread, entry);
38
39     procvm_unmount(mm);
40
41     if (created) {
42         *created = kthread;
43     }
44
45     return 0;
46 }
47
48 int
49 spawn_process_usr(struct thread** created, char* path, 
50                     const char** argv, const char** envp)
51 {
52     // FIXME remote injection of user stack not yet implemented
53
54     struct proc_info* proc   = alloc_process();
55     struct proc_mm*   mm     = vmspace(proc);
56     
57     assert(!kernel_process(proc));
58
59     procvm_initvms_mount(mm);
60
61     int errno = 0;
62     struct thread* main_thread;
63     if (!(main_thread = create_thread(proc, true))) {
64         errno = ENOMEM;
65         goto fail;
66     }
67
68     struct exec_host container;
69     exec_init_container(&container, main_thread, VMS_MOUNT_1, argv, envp);
70     if ((errno = exec_load_byname(&container, path))) {
71         goto fail;
72     }
73
74     commit_process(proc);
75     start_thread(main_thread, container.exe.entry);
76
77     if (created) {
78         *created = main_thread;
79     }
80
81     procvm_unmount(mm);
82     return 0;
83
84 fail:
85     procvm_unmount(mm);
86     delete_process(proc);
87     return errno;
88 }
89
90
91 ptr_t proc_vmroot() {
92     return __current->mm->vmroot;
93 }
94
95 __DEFINE_LXSYSCALL(pid_t, getpid)
96 {
97     return __current->pid;
98 }
99
100 __DEFINE_LXSYSCALL(pid_t, getppid)
101 {
102     return __current->parent->pid;
103 }
104
105 __DEFINE_LXSYSCALL(pid_t, getpgid)
106 {
107     return __current->pgid;
108 }
109
110 __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid)
111 {
112     struct proc_info* proc = pid ? get_process(pid) : __current;
113
114     if (!proc) {
115         syscall_result(EINVAL);
116         return -1;
117     }
118
119     pgid = pgid ? pgid : proc->pid;
120
121     struct proc_info* gruppenfuhrer = get_process(pgid);
122
123     if (!gruppenfuhrer || proc->pgid == gruppenfuhrer->pid) {
124         syscall_result(EINVAL);
125         return -1;
126     }
127
128     llist_delete(&proc->grp_member);
129     llist_append(&gruppenfuhrer->grp_member, &proc->grp_member);
130
131     proc->pgid = pgid;
132     return 0;
133 }
134
135 static inline bool
136 __can_change_real_id(const struct user_scope* procu, caps_t id_cap) {
137     if (uscope_with_capability(procu, id_cap)) {
138         return true;
139     }
140
141     if (check_current_acl(0, 0) != ACL_NO_MATCH) {
142         return true;
143     }
144
145     return false;
146 }
147
148 __DEFINE_LXSYSCALL1(int, setuid, uid_t, uid)
149 {
150     struct user_scope* procu;
151
152     procu = current_user_scope();
153
154     if (__can_change_real_id(procu, CAP_SETUID)) 
155     {
156         procu->ruid = uid;
157     }
158
159     __current->suid = uid;
160     __current->euid = uid;
161
162     return 0;
163 }
164
165 __DEFINE_LXSYSCALL1(int, setgid, gid_t, gid)
166 {
167     struct user_scope* procu;
168
169     procu = current_user_scope();
170
171     if (__can_change_real_id(procu, CAP_SETGID)) 
172     {
173         procu->rgid = gid;
174     }
175
176     __current->sgid = gid;
177     __current->egid = gid;
178
179     return 0;
180 }
181
182 __DEFINE_LXSYSCALL1(int, seteuid, uid_t, euid)
183 {
184     __current->euid = euid;
185
186     return 0;
187 }
188
189 __DEFINE_LXSYSCALL1(int, setegid, gid_t, egid)
190 {
191     __current->egid = egid;
192
193     return 0;
194 }
195
196 __DEFINE_LXSYSCALL2(int, setgroups, const gid_t*, gids, unsigned int, len)
197 {
198     struct user_scope* procu;
199
200     procu = current_user_scope();
201
202     if (check_current_acl(0, 0) == ACL_NO_MATCH) {
203         return EPERM;
204     }
205
206     if (uscope_with_capability(procu, CAP_SETGID)) {
207         return EPERM;
208     }
209
210     return uscope_setgroups(procu, gids, len);
211 }
212
213
214 __DEFINE_LXSYSCALL(uid_t, getuid)
215 {
216     return current_user_scope()->ruid;
217 }
218
219 __DEFINE_LXSYSCALL(gid_t, getgid)
220 {
221     return current_user_scope()->rgid;
222 }
223
224 __DEFINE_LXSYSCALL(uid_t, geteuid)
225 {
226     return __current->euid;
227 }
228
229 __DEFINE_LXSYSCALL(gid_t, getegid)
230 {
231     return __current->egid;
232 }
233
234 __DEFINE_LXSYSCALL2(int, getgroups, gid_t*, out_buf, unsigned int, len)
235 {
236     struct user_scope* procu;
237     struct ugroup_obj* gobj;
238
239     procu = current_user_scope();
240     gobj  = user_groups(procu);
241
242     assert(gobj);
243     len = MIN(gobj->maxcap, len);
244
245     unsigned i = 0;
246     for (; i < len && gobj->list[i] != grp_list_end; i++)
247     {
248         out_buf[i] = gobj->list[i];
249     }
250     
251     return i + 1;
252 }