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