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