xref: /netbsd-src/sys/compat/linux/common/linux_sched.c (revision e4d7c2e329d54c97e0c0bd3016bbe74f550c3d5e)
1 /*	$NetBSD: linux_sched.c,v 1.4 1999/12/04 21:58:05 tron 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/types.h>
45 #include <sys/param.h>
46 #include <sys/mount.h>
47 #include <sys/proc.h>
48 #include <sys/systm.h>
49 #include <sys/syscallargs.h>
50 
51 #include <machine/cpu.h>
52 
53 #include <compat/linux/common/linux_types.h>
54 #include <compat/linux/common/linux_signal.h>
55 
56 #include <compat/linux/linux_syscallargs.h>
57 
58 #include <compat/linux/common/linux_sched.h>
59 
60 int
61 linux_sys_clone(p, v, retval)
62 	struct proc *p;
63 	void *v;
64 	register_t *retval;
65 {
66 	struct linux_sys_clone_args /* {
67 		syscallarg(int) flags;
68 		syscallarg(void *) stack;
69 	} */ *uap = v;
70 	int flags, sig;
71 
72 	/*
73 	 * We don't support the Linux CLONE_PID or CLONE_PTRACE flags.
74 	 */
75 	if (SCARG(uap, flags) & (LINUX_CLONE_PID|LINUX_CLONE_PTRACE))
76 		return (EINVAL);
77 
78 	flags = 0;
79 
80 	if (SCARG(uap, flags) & LINUX_CLONE_VM)
81 		flags |= FORK_SHAREVM;
82 	if (SCARG(uap, flags) & LINUX_CLONE_FS)
83 		flags |= FORK_SHARECWD;
84 	if (SCARG(uap, flags) & LINUX_CLONE_FILES)
85 		flags |= FORK_SHAREFILES;
86 	if (SCARG(uap, flags) & LINUX_CLONE_SIGHAND)
87 		flags |= FORK_SHARESIGS;
88 	if (SCARG(uap, flags) & LINUX_CLONE_VFORK)
89 		flags |= FORK_PPWAIT;
90 
91 	sig = SCARG(uap, flags) & LINUX_CLONE_CSIGNAL;
92 	if (sig < 0 || sig >= LINUX__NSIG)
93 		return (EINVAL);
94 	sig = linux_to_native_sig[sig];
95 
96 	/*
97 	 * Note that Linux does not provide a portable way of specifying
98 	 * the stack area; the caller must know if the stack grows up
99 	 * or down.  So, we pass a stack size of 0, so that the code
100 	 * that makes this adjustment is a noop.
101 	 */
102 	return (fork1(p, flags, sig, SCARG(uap, stack), 0, retval, NULL));
103 }
104 
105 int
106 linux_sys_sched_setparam(cp, v, retval)
107 	struct proc *cp;
108 	void *v;
109 	register_t *retval;
110 {
111 	struct linux_sys_sched_setparam_args /* {
112 		syscallarg(linux_pid_t) pid;
113 		syscallarg(const struct linux_sched_param *) sp;
114 	} */ *uap = v;
115 	int error;
116 	struct linux_sched_param lp;
117 	register struct proc *p;
118 
119 /*
120  * We only check for valid parameters and return afterwards.
121  */
122 
123 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
124 		return EINVAL;
125 
126 	error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
127 	if (error)
128 		return error;
129 
130 	if (SCARG(uap, pid) != 0) {
131 		register struct pcred *pc = cp->p_cred;
132 
133 		if ((p = pfind(SCARG(uap, pid))) == NULL)
134 			return ESRCH;
135 		if (!(cp == p ||
136 		      pc->pc_ucred->cr_uid == 0 ||
137 		      pc->p_ruid == p->p_cred->p_ruid ||
138 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
139 		      pc->p_ruid == p->p_ucred->cr_uid ||
140 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
141 			return EPERM;
142 	}
143 
144 	return 0;
145 }
146 
147 int
148 linux_sys_sched_getparam(cp, v, retval)
149 	struct proc *cp;
150 	void *v;
151 	register_t *retval;
152 {
153 	struct linux_sys_sched_getparam_args /* {
154 		syscallarg(linux_pid_t) pid;
155 		syscallarg(struct linux_sched_param *) sp;
156 	} */ *uap = v;
157 	register struct proc *p;
158 	struct linux_sched_param lp;
159 
160 /*
161  * We only check for valid parameters and return a dummy priority afterwards.
162  */
163 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
164 		return EINVAL;
165 
166 	if (SCARG(uap, pid) != 0) {
167 		register struct pcred *pc = cp->p_cred;
168 
169 		if ((p = pfind(SCARG(uap, pid))) == NULL)
170 			return ESRCH;
171 		if (!(cp == p ||
172 		      pc->pc_ucred->cr_uid == 0 ||
173 		      pc->p_ruid == p->p_cred->p_ruid ||
174 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
175 		      pc->p_ruid == p->p_ucred->cr_uid ||
176 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
177 			return EPERM;
178 	}
179 
180 	lp.sched_priority = 0;
181 	return copyout(&lp, SCARG(uap, sp), sizeof(lp));
182 }
183 
184 int
185 linux_sys_sched_setscheduler(cp, v, retval)
186 	struct proc *cp;
187 	void *v;
188 	register_t *retval;
189 {
190 	struct linux_sys_sched_setscheduler_args /* {
191 		syscallarg(linux_pid_t) pid;
192 		syscallarg(int) policy;
193 		syscallarg(cont struct linux_sched_scheduler *) sp;
194 	} */ *uap = v;
195 	int error;
196 	struct linux_sched_param lp;
197 	register struct proc *p;
198 
199 /*
200  * We only check for valid parameters and return afterwards.
201  */
202 
203 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
204 		return EINVAL;
205 
206 	error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
207 	if (error)
208 		return error;
209 
210 	if (SCARG(uap, pid) != 0) {
211 		register struct pcred *pc = cp->p_cred;
212 
213 		if ((p = pfind(SCARG(uap, pid))) == NULL)
214 			return ESRCH;
215 		if (!(cp == p ||
216 		      pc->pc_ucred->cr_uid == 0 ||
217 		      pc->p_ruid == p->p_cred->p_ruid ||
218 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
219 		      pc->p_ruid == p->p_ucred->cr_uid ||
220 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
221 			return EPERM;
222 	}
223 
224 /*
225  * We can't emulate anything put the default scheduling policy.
226  */
227 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER || lp.sched_priority != 0)
228 		return EINVAL;
229 
230 	return 0;
231 }
232 
233 int
234 linux_sys_sched_getscheduler(cp, v, retval)
235 	struct proc *cp;
236 	void *v;
237 	register_t *retval;
238 {
239 	struct linux_sys_sched_getscheduler_args /* {
240 		syscallarg(linux_pid_t) pid;
241 	} */ *uap = v;
242 	register struct proc *p;
243 
244 	*retval = -1;
245 /*
246  * We only check for valid parameters and return afterwards.
247  */
248 
249 	if (SCARG(uap, pid) != 0) {
250 		register struct pcred *pc = cp->p_cred;
251 
252 		if ((p = pfind(SCARG(uap, pid))) == NULL)
253 			return ESRCH;
254 		if (!(cp == p ||
255 		      pc->pc_ucred->cr_uid == 0 ||
256 		      pc->p_ruid == p->p_cred->p_ruid ||
257 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
258 		      pc->p_ruid == p->p_ucred->cr_uid ||
259 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
260 			return EPERM;
261 	}
262 
263 /*
264  * We can't emulate anything put the default scheduling policy.
265  */
266 	*retval = LINUX_SCHED_OTHER;
267 	return 0;
268 }
269 
270 int
271 linux_sys_sched_yield(cp, v, retval)
272 	struct proc *cp;
273 	void *v;
274 	register_t *retval;
275 {
276 	need_resched();
277 	return 0;
278 }
279 
280 int
281 linux_sys_sched_get_priority_max(cp, v, retval)
282 	struct proc *cp;
283 	void *v;
284 	register_t *retval;
285 {
286 	struct linux_sys_sched_get_priority_max_args /* {
287 		syscallarg(int) policy;
288 	} */ *uap = v;
289 
290 /*
291  * We can't emulate anything put the default scheduling policy.
292  */
293 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
294 		*retval = -1;
295 		return EINVAL;
296 	}
297 
298 	*retval = 0;
299 	return 0;
300 }
301 
302 int
303 linux_sys_sched_get_priority_min(cp, v, retval)
304 	struct proc *cp;
305 	void *v;
306 	register_t *retval;
307 {
308 	struct linux_sys_sched_get_priority_min_args /* {
309 		syscallarg(int) policy;
310 	} */ *uap = v;
311 
312 /*
313  * We can't emulate anything put the default scheduling policy.
314  */
315 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
316 		*retval = -1;
317 		return EINVAL;
318 	}
319 
320 	*retval = 0;
321 	return 0;
322 }
323