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