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