xref: /netbsd-src/sys/compat/linux/common/linux_sched.c (revision 001c68bd94f75ce9270b69227c4199fbf34ee396)
1 /*	$NetBSD: linux_sched.c,v 1.12 2003/01/18 21:21:30 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center; by Matthias Scheler.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Linux compatibility module. Try to deal with scheduler related syscalls.
42  */
43 
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.12 2003/01/18 21:21:30 thorpej Exp $");
46 
47 #include <sys/param.h>
48 #include <sys/mount.h>
49 #include <sys/proc.h>
50 #include <sys/systm.h>
51 #include <sys/sa.h>
52 #include <sys/syscallargs.h>
53 
54 #include <machine/cpu.h>
55 
56 #include <compat/linux/common/linux_types.h>
57 #include <compat/linux/common/linux_signal.h>
58 
59 #include <compat/linux/linux_syscallargs.h>
60 
61 #include <compat/linux/common/linux_sched.h>
62 
63 int
64 linux_sys_clone(l, v, retval)
65 	struct lwp *l;
66 	void *v;
67 	register_t *retval;
68 {
69 	struct linux_sys_clone_args /* {
70 		syscallarg(int) flags;
71 		syscallarg(void *) stack;
72 	} */ *uap = v;
73 	int flags, sig;
74 
75 	/*
76 	 * We don't support the Linux CLONE_PID or CLONE_PTRACE flags.
77 	 */
78 	if (SCARG(uap, flags) & (LINUX_CLONE_PID|LINUX_CLONE_PTRACE))
79 		return (EINVAL);
80 
81 	flags = 0;
82 
83 	if (SCARG(uap, flags) & LINUX_CLONE_VM)
84 		flags |= FORK_SHAREVM;
85 	if (SCARG(uap, flags) & LINUX_CLONE_FS)
86 		flags |= FORK_SHARECWD;
87 	if (SCARG(uap, flags) & LINUX_CLONE_FILES)
88 		flags |= FORK_SHAREFILES;
89 	if (SCARG(uap, flags) & LINUX_CLONE_SIGHAND)
90 		flags |= FORK_SHARESIGS;
91 	if (SCARG(uap, flags) & LINUX_CLONE_VFORK)
92 		flags |= FORK_PPWAIT;
93 
94 	sig = SCARG(uap, flags) & LINUX_CLONE_CSIGNAL;
95 	if (sig < 0 || sig >= LINUX__NSIG)
96 		return (EINVAL);
97 	sig = linux_to_native_signo[sig];
98 
99 	/*
100 	 * Note that Linux does not provide a portable way of specifying
101 	 * the stack area; the caller must know if the stack grows up
102 	 * or down.  So, we pass a stack size of 0, so that the code
103 	 * that makes this adjustment is a noop.
104 	 */
105 	return (fork1(l, flags, sig, SCARG(uap, stack), 0,
106 	    NULL, NULL, retval, NULL));
107 }
108 
109 int
110 linux_sys_sched_setparam(cl, v, retval)
111 	struct lwp *cl;
112 	void *v;
113 	register_t *retval;
114 {
115 	struct linux_sys_sched_setparam_args /* {
116 		syscallarg(linux_pid_t) pid;
117 		syscallarg(const struct linux_sched_param *) sp;
118 	} */ *uap = v;
119 	struct proc *cp = cl->l_proc;
120 	int error;
121 	struct linux_sched_param lp;
122 	struct proc *p;
123 
124 /*
125  * We only check for valid parameters and return afterwards.
126  */
127 
128 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
129 		return EINVAL;
130 
131 	error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
132 	if (error)
133 		return error;
134 
135 	if (SCARG(uap, pid) != 0) {
136 		struct pcred *pc = cp->p_cred;
137 
138 		if ((p = pfind(SCARG(uap, pid))) == NULL)
139 			return ESRCH;
140 		if (!(cp == p ||
141 		      pc->pc_ucred->cr_uid == 0 ||
142 		      pc->p_ruid == p->p_cred->p_ruid ||
143 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
144 		      pc->p_ruid == p->p_ucred->cr_uid ||
145 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
146 			return EPERM;
147 	}
148 
149 	return 0;
150 }
151 
152 int
153 linux_sys_sched_getparam(cl, v, retval)
154 	struct lwp *cl;
155 	void *v;
156 	register_t *retval;
157 {
158 	struct linux_sys_sched_getparam_args /* {
159 		syscallarg(linux_pid_t) pid;
160 		syscallarg(struct linux_sched_param *) sp;
161 	} */ *uap = v;
162 	struct proc *cp = cl->l_proc;
163 	struct proc *p;
164 	struct linux_sched_param lp;
165 
166 /*
167  * We only check for valid parameters and return a dummy priority afterwards.
168  */
169 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
170 		return EINVAL;
171 
172 	if (SCARG(uap, pid) != 0) {
173 		struct pcred *pc = cp->p_cred;
174 
175 		if ((p = pfind(SCARG(uap, pid))) == NULL)
176 			return ESRCH;
177 		if (!(cp == p ||
178 		      pc->pc_ucred->cr_uid == 0 ||
179 		      pc->p_ruid == p->p_cred->p_ruid ||
180 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
181 		      pc->p_ruid == p->p_ucred->cr_uid ||
182 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
183 			return EPERM;
184 	}
185 
186 	lp.sched_priority = 0;
187 	return copyout(&lp, SCARG(uap, sp), sizeof(lp));
188 }
189 
190 int
191 linux_sys_sched_setscheduler(cl, v, retval)
192 	struct lwp *cl;
193 	void *v;
194 	register_t *retval;
195 {
196 	struct linux_sys_sched_setscheduler_args /* {
197 		syscallarg(linux_pid_t) pid;
198 		syscallarg(int) policy;
199 		syscallarg(cont struct linux_sched_scheduler *) sp;
200 	} */ *uap = v;
201 	struct proc *cp = cl->l_proc;
202 	int error;
203 	struct linux_sched_param lp;
204 	struct proc *p;
205 
206 /*
207  * We only check for valid parameters and return afterwards.
208  */
209 
210 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
211 		return EINVAL;
212 
213 	error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
214 	if (error)
215 		return error;
216 
217 	if (SCARG(uap, pid) != 0) {
218 		struct pcred *pc = cp->p_cred;
219 
220 		if ((p = pfind(SCARG(uap, pid))) == NULL)
221 			return ESRCH;
222 		if (!(cp == p ||
223 		      pc->pc_ucred->cr_uid == 0 ||
224 		      pc->p_ruid == p->p_cred->p_ruid ||
225 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
226 		      pc->p_ruid == p->p_ucred->cr_uid ||
227 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
228 			return EPERM;
229 	}
230 
231 /*
232  * We can't emulate anything put the default scheduling policy.
233  */
234 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER || lp.sched_priority != 0)
235 		return EINVAL;
236 
237 	return 0;
238 }
239 
240 int
241 linux_sys_sched_getscheduler(cl, v, retval)
242 	struct lwp *cl;
243 	void *v;
244 	register_t *retval;
245 {
246 	struct linux_sys_sched_getscheduler_args /* {
247 		syscallarg(linux_pid_t) pid;
248 	} */ *uap = v;
249 	struct proc *cp = cl->l_proc;
250 	struct proc *p;
251 
252 	*retval = -1;
253 /*
254  * We only check for valid parameters and return afterwards.
255  */
256 
257 	if (SCARG(uap, pid) != 0) {
258 		struct pcred *pc = cp->p_cred;
259 
260 		if ((p = pfind(SCARG(uap, pid))) == NULL)
261 			return ESRCH;
262 		if (!(cp == p ||
263 		      pc->pc_ucred->cr_uid == 0 ||
264 		      pc->p_ruid == p->p_cred->p_ruid ||
265 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
266 		      pc->p_ruid == p->p_ucred->cr_uid ||
267 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
268 			return EPERM;
269 	}
270 
271 /*
272  * We can't emulate anything put the default scheduling policy.
273  */
274 	*retval = LINUX_SCHED_OTHER;
275 	return 0;
276 }
277 
278 int
279 linux_sys_sched_yield(cl, v, retval)
280 	struct lwp *cl;
281 	void *v;
282 	register_t *retval;
283 {
284 
285 	yield();
286 	return 0;
287 }
288 
289 int
290 linux_sys_sched_get_priority_max(cl, v, retval)
291 	struct lwp *cl;
292 	void *v;
293 	register_t *retval;
294 {
295 	struct linux_sys_sched_get_priority_max_args /* {
296 		syscallarg(int) policy;
297 	} */ *uap = v;
298 
299 /*
300  * We can't emulate anything put the default scheduling policy.
301  */
302 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
303 		*retval = -1;
304 		return EINVAL;
305 	}
306 
307 	*retval = 0;
308 	return 0;
309 }
310 
311 int
312 linux_sys_sched_get_priority_min(cl, v, retval)
313 	struct lwp *cl;
314 	void *v;
315 	register_t *retval;
316 {
317 	struct linux_sys_sched_get_priority_min_args /* {
318 		syscallarg(int) policy;
319 	} */ *uap = v;
320 
321 /*
322  * We can't emulate anything put the default scheduling policy.
323  */
324 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
325 		*retval = -1;
326 		return EINVAL;
327 	}
328 
329 	*retval = 0;
330 	return 0;
331 }
332