xref: /netbsd-src/sys/compat/linux/common/linux_sched.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: linux_sched.c,v 1.6 2000/05/28 05:49:05 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/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,
103 	    NULL, NULL, retval, NULL));
104 }
105 
106 int
107 linux_sys_sched_setparam(cp, v, retval)
108 	struct proc *cp;
109 	void *v;
110 	register_t *retval;
111 {
112 	struct linux_sys_sched_setparam_args /* {
113 		syscallarg(linux_pid_t) pid;
114 		syscallarg(const struct linux_sched_param *) sp;
115 	} */ *uap = v;
116 	int error;
117 	struct linux_sched_param lp;
118 	struct proc *p;
119 
120 /*
121  * We only check for valid parameters and return afterwards.
122  */
123 
124 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
125 		return EINVAL;
126 
127 	error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
128 	if (error)
129 		return error;
130 
131 	if (SCARG(uap, pid) != 0) {
132 		struct pcred *pc = cp->p_cred;
133 
134 		if ((p = pfind(SCARG(uap, pid))) == NULL)
135 			return ESRCH;
136 		if (!(cp == p ||
137 		      pc->pc_ucred->cr_uid == 0 ||
138 		      pc->p_ruid == p->p_cred->p_ruid ||
139 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
140 		      pc->p_ruid == p->p_ucred->cr_uid ||
141 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
142 			return EPERM;
143 	}
144 
145 	return 0;
146 }
147 
148 int
149 linux_sys_sched_getparam(cp, v, retval)
150 	struct proc *cp;
151 	void *v;
152 	register_t *retval;
153 {
154 	struct linux_sys_sched_getparam_args /* {
155 		syscallarg(linux_pid_t) pid;
156 		syscallarg(struct linux_sched_param *) sp;
157 	} */ *uap = v;
158 	struct proc *p;
159 	struct linux_sched_param lp;
160 
161 /*
162  * We only check for valid parameters and return a dummy priority afterwards.
163  */
164 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
165 		return EINVAL;
166 
167 	if (SCARG(uap, pid) != 0) {
168 		struct pcred *pc = cp->p_cred;
169 
170 		if ((p = pfind(SCARG(uap, pid))) == NULL)
171 			return ESRCH;
172 		if (!(cp == p ||
173 		      pc->pc_ucred->cr_uid == 0 ||
174 		      pc->p_ruid == p->p_cred->p_ruid ||
175 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
176 		      pc->p_ruid == p->p_ucred->cr_uid ||
177 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
178 			return EPERM;
179 	}
180 
181 	lp.sched_priority = 0;
182 	return copyout(&lp, SCARG(uap, sp), sizeof(lp));
183 }
184 
185 int
186 linux_sys_sched_setscheduler(cp, v, retval)
187 	struct proc *cp;
188 	void *v;
189 	register_t *retval;
190 {
191 	struct linux_sys_sched_setscheduler_args /* {
192 		syscallarg(linux_pid_t) pid;
193 		syscallarg(int) policy;
194 		syscallarg(cont struct linux_sched_scheduler *) sp;
195 	} */ *uap = v;
196 	int error;
197 	struct linux_sched_param lp;
198 	struct proc *p;
199 
200 /*
201  * We only check for valid parameters and return afterwards.
202  */
203 
204 	if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
205 		return EINVAL;
206 
207 	error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
208 	if (error)
209 		return error;
210 
211 	if (SCARG(uap, pid) != 0) {
212 		struct pcred *pc = cp->p_cred;
213 
214 		if ((p = pfind(SCARG(uap, pid))) == NULL)
215 			return ESRCH;
216 		if (!(cp == p ||
217 		      pc->pc_ucred->cr_uid == 0 ||
218 		      pc->p_ruid == p->p_cred->p_ruid ||
219 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
220 		      pc->p_ruid == p->p_ucred->cr_uid ||
221 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
222 			return EPERM;
223 	}
224 
225 /*
226  * We can't emulate anything put the default scheduling policy.
227  */
228 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER || lp.sched_priority != 0)
229 		return EINVAL;
230 
231 	return 0;
232 }
233 
234 int
235 linux_sys_sched_getscheduler(cp, v, retval)
236 	struct proc *cp;
237 	void *v;
238 	register_t *retval;
239 {
240 	struct linux_sys_sched_getscheduler_args /* {
241 		syscallarg(linux_pid_t) pid;
242 	} */ *uap = v;
243 	struct proc *p;
244 
245 	*retval = -1;
246 /*
247  * We only check for valid parameters and return afterwards.
248  */
249 
250 	if (SCARG(uap, pid) != 0) {
251 		struct pcred *pc = cp->p_cred;
252 
253 		if ((p = pfind(SCARG(uap, pid))) == NULL)
254 			return ESRCH;
255 		if (!(cp == p ||
256 		      pc->pc_ucred->cr_uid == 0 ||
257 		      pc->p_ruid == p->p_cred->p_ruid ||
258 		      pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
259 		      pc->p_ruid == p->p_ucred->cr_uid ||
260 		      pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
261 			return EPERM;
262 	}
263 
264 /*
265  * We can't emulate anything put the default scheduling policy.
266  */
267 	*retval = LINUX_SCHED_OTHER;
268 	return 0;
269 }
270 
271 int
272 linux_sys_sched_yield(cp, v, retval)
273 	struct proc *cp;
274 	void *v;
275 	register_t *retval;
276 {
277 	need_resched();
278 	return 0;
279 }
280 
281 int
282 linux_sys_sched_get_priority_max(cp, v, retval)
283 	struct proc *cp;
284 	void *v;
285 	register_t *retval;
286 {
287 	struct linux_sys_sched_get_priority_max_args /* {
288 		syscallarg(int) policy;
289 	} */ *uap = v;
290 
291 /*
292  * We can't emulate anything put the default scheduling policy.
293  */
294 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
295 		*retval = -1;
296 		return EINVAL;
297 	}
298 
299 	*retval = 0;
300 	return 0;
301 }
302 
303 int
304 linux_sys_sched_get_priority_min(cp, v, retval)
305 	struct proc *cp;
306 	void *v;
307 	register_t *retval;
308 {
309 	struct linux_sys_sched_get_priority_min_args /* {
310 		syscallarg(int) policy;
311 	} */ *uap = v;
312 
313 /*
314  * We can't emulate anything put the default scheduling policy.
315  */
316 	if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
317 		*retval = -1;
318 		return EINVAL;
319 	}
320 
321 	*retval = 0;
322 	return 0;
323 }
324