1 /* $NetBSD: linux_misc_notalpha.c,v 1.53 2000/03/23 06:48:17 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe 9 * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center. 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 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/mman.h> 44 #include <sys/mount.h> 45 #include <sys/malloc.h> 46 #include <sys/mbuf.h> 47 #include <sys/namei.h> 48 #include <sys/ptrace.h> 49 #include <sys/resource.h> 50 #include <sys/resourcevar.h> 51 #include <sys/wait.h> 52 53 #include <sys/syscallargs.h> 54 55 #include <vm/vm.h> 56 #include <vm/vm_param.h> 57 58 #include <compat/linux/common/linux_types.h> 59 #include <compat/linux/common/linux_fcntl.h> 60 #include <compat/linux/common/linux_misc.h> 61 #include <compat/linux/common/linux_mmap.h> 62 #include <compat/linux/common/linux_signal.h> 63 #include <compat/linux/common/linux_util.h> 64 65 #include <compat/linux/linux_syscallargs.h> 66 67 /* 68 * This file contains routines which are used 69 * on every linux architechture except the Alpha. 70 */ 71 72 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */ 73 /* Not used on: alpha */ 74 75 /* 76 * Alarm. This is a libc call which uses setitimer(2) in NetBSD. 77 * Fiddle with the timers to make it work. 78 */ 79 int 80 linux_sys_alarm(p, v, retval) 81 struct proc *p; 82 void *v; 83 register_t *retval; 84 { 85 struct linux_sys_alarm_args /* { 86 syscallarg(unsigned int) secs; 87 } */ *uap = v; 88 int s; 89 struct itimerval *itp, it; 90 91 itp = &p->p_realtimer; 92 s = splclock(); 93 /* 94 * Clear any pending timer alarms. 95 */ 96 callout_stop(&p->p_realit_ch); 97 timerclear(&itp->it_interval); 98 if (timerisset(&itp->it_value) && 99 timercmp(&itp->it_value, &time, >)) 100 timersub(&itp->it_value, &time, &itp->it_value); 101 /* 102 * Return how many seconds were left (rounded up) 103 */ 104 retval[0] = itp->it_value.tv_sec; 105 if (itp->it_value.tv_usec) 106 retval[0]++; 107 108 /* 109 * alarm(0) just resets the timer. 110 */ 111 if (SCARG(uap, secs) == 0) { 112 timerclear(&itp->it_value); 113 splx(s); 114 return 0; 115 } 116 117 /* 118 * Check the new alarm time for sanity, and set it. 119 */ 120 timerclear(&it.it_interval); 121 it.it_value.tv_sec = SCARG(uap, secs); 122 it.it_value.tv_usec = 0; 123 if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) { 124 splx(s); 125 return (EINVAL); 126 } 127 128 if (timerisset(&it.it_value)) { 129 timeradd(&it.it_value, &time, &it.it_value); 130 callout_reset(&p->p_realit_ch, hzto(&it.it_value), 131 realitexpire, p); 132 } 133 p->p_realtimer = it; 134 splx(s); 135 136 return 0; 137 } 138 139 int 140 linux_sys_nice(p, v, retval) 141 struct proc *p; 142 void *v; 143 register_t *retval; 144 { 145 struct linux_sys_nice_args /* { 146 syscallarg(int) incr; 147 } */ *uap = v; 148 struct sys_setpriority_args bsa; 149 150 SCARG(&bsa, which) = PRIO_PROCESS; 151 SCARG(&bsa, who) = 0; 152 SCARG(&bsa, prio) = SCARG(uap, incr); 153 return sys_setpriority(p, &bsa, retval); 154 } 155 156 /* 157 * The old Linux readdir was only able to read one entry at a time, 158 * even though it had a 'count' argument. In fact, the emulation 159 * of the old call was better than the original, because it did handle 160 * the count arg properly. Don't bother with it anymore now, and use 161 * it to distinguish between old and new. The difference is that the 162 * newer one actually does multiple entries, and the reclen field 163 * really is the reclen, not the namelength. 164 */ 165 int 166 linux_sys_readdir(p, v, retval) 167 struct proc *p; 168 void *v; 169 register_t *retval; 170 { 171 struct linux_sys_readdir_args /* { 172 syscallarg(int) fd; 173 syscallarg(struct linux_dirent *) dent; 174 syscallarg(unsigned int) count; 175 } */ *uap = v; 176 177 SCARG(uap, count) = 1; 178 return linux_sys_getdents(p, uap, retval); 179 } 180 181 /* 182 * I wonder why Linux has gettimeofday() _and_ time().. Still, we 183 * need to deal with it. 184 */ 185 int 186 linux_sys_time(p, v, retval) 187 struct proc *p; 188 void *v; 189 register_t *retval; 190 { 191 struct linux_sys_time_args /* { 192 linux_time_t *t; 193 } */ *uap = v; 194 struct timeval atv; 195 linux_time_t tt; 196 int error; 197 198 microtime(&atv); 199 200 tt = atv.tv_sec; 201 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) 202 return error; 203 204 retval[0] = tt; 205 return 0; 206 } 207 208 /* 209 * utime(). Do conversion to things that utimes() understands, 210 * and pass it on. 211 */ 212 int 213 linux_sys_utime(p, v, retval) 214 struct proc *p; 215 void *v; 216 register_t *retval; 217 { 218 struct linux_sys_utime_args /* { 219 syscallarg(const char *) path; 220 syscallarg(struct linux_utimbuf *)times; 221 } */ *uap = v; 222 caddr_t sg; 223 int error; 224 struct sys_utimes_args ua; 225 struct timeval tv[2], *tvp; 226 struct linux_utimbuf lut; 227 228 sg = stackgap_init(p->p_emul); 229 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 230 231 SCARG(&ua, path) = SCARG(uap, path); 232 233 if (SCARG(uap, times) != NULL) { 234 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) 235 return error; 236 tv[0].tv_usec = tv[1].tv_usec = 0; 237 tv[0].tv_sec = lut.l_actime; 238 tv[1].tv_sec = lut.l_modtime; 239 tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv)); 240 if ((error = copyout(tv, tvp, sizeof tv))) 241 return error; 242 SCARG(&ua, tptr) = tvp; 243 } 244 else 245 SCARG(&ua, tptr) = NULL; 246 247 return sys_utimes(p, &ua, retval); 248 } 249 250 /* 251 * waitpid(2). Passed on to the NetBSD call, surrounded by code to 252 * reserve some space for a NetBSD-style wait status, and converting 253 * it to what Linux wants. 254 */ 255 int 256 linux_sys_waitpid(p, v, retval) 257 struct proc *p; 258 void *v; 259 register_t *retval; 260 { 261 struct linux_sys_waitpid_args /* { 262 syscallarg(int) pid; 263 syscallarg(int *) status; 264 syscallarg(int) options; 265 } */ *uap = v; 266 struct sys_wait4_args w4a; 267 int error, *status, tstat; 268 caddr_t sg; 269 270 if (SCARG(uap, status) != NULL) { 271 sg = stackgap_init(p->p_emul); 272 status = (int *) stackgap_alloc(&sg, sizeof status); 273 } else 274 status = NULL; 275 276 SCARG(&w4a, pid) = SCARG(uap, pid); 277 SCARG(&w4a, status) = status; 278 SCARG(&w4a, options) = SCARG(uap, options); 279 SCARG(&w4a, rusage) = NULL; 280 281 if ((error = sys_wait4(p, &w4a, retval))) 282 return error; 283 284 sigdelset(&p->p_siglist, SIGCHLD); 285 286 if (status != NULL) { 287 if ((error = copyin(status, &tstat, sizeof tstat))) 288 return error; 289 290 bsd_to_linux_wstat(&tstat); 291 return copyout(&tstat, SCARG(uap, status), sizeof tstat); 292 } 293 294 return 0; 295 } 296 297 int 298 linux_sys_setresgid(p, v, retval) 299 struct proc *p; 300 void *v; 301 register_t *retval; 302 { 303 struct linux_sys_setresgid_args /* { 304 syscallarg(gid_t) rgid; 305 syscallarg(gid_t) egid; 306 syscallarg(gid_t) sgid; 307 } */ *uap = v; 308 struct pcred *pc = p->p_cred; 309 gid_t rgid, egid, sgid; 310 int error; 311 312 rgid = SCARG(uap, rgid); 313 egid = SCARG(uap, egid); 314 sgid = SCARG(uap, sgid); 315 316 /* 317 * Note: These checks are a little different than the NetBSD 318 * setregid(2) call performs. This precisely follows the 319 * behavior of the Linux kernel. 320 */ 321 if (rgid != (gid_t)-1 && 322 rgid != pc->p_rgid && 323 rgid != pc->pc_ucred->cr_gid && 324 rgid != pc->p_svgid && 325 (error = suser(pc->pc_ucred, &p->p_acflag))) 326 return (error); 327 328 if (egid != (gid_t)-1 && 329 egid != pc->p_rgid && 330 egid != pc->pc_ucred->cr_gid && 331 egid != pc->p_svgid && 332 (error = suser(pc->pc_ucred, &p->p_acflag))) 333 return (error); 334 335 if (sgid != (gid_t)-1 && 336 sgid != pc->p_rgid && 337 sgid != pc->pc_ucred->cr_gid && 338 sgid != pc->p_svgid && 339 (error = suser(pc->pc_ucred, &p->p_acflag))) 340 return (error); 341 342 /* 343 * Now assign the real, effective, and saved GIDs. 344 * Note that Linux, unlike NetBSD in setregid(2), does not 345 * set the saved UID in this call unless the user specifies 346 * it. 347 */ 348 if (rgid != (gid_t)-1) 349 pc->p_rgid = rgid; 350 351 if (egid != (gid_t)-1) { 352 pc->pc_ucred = crcopy(pc->pc_ucred); 353 pc->pc_ucred->cr_gid = egid; 354 } 355 356 if (sgid != (gid_t)-1) 357 pc->p_svgid = sgid; 358 359 if (rgid != (gid_t)-1 && egid != (gid_t)-1 && sgid != (gid_t)-1) 360 p->p_flag |= P_SUGID; 361 return (0); 362 } 363 364 int 365 linux_sys_getresgid(p, v, retval) 366 struct proc *p; 367 void *v; 368 register_t *retval; 369 { 370 struct linux_sys_getresgid_args /* { 371 syscallarg(gid_t *) rgid; 372 syscallarg(gid_t *) egid; 373 syscallarg(gid_t *) sgid; 374 } */ *uap = v; 375 struct pcred *pc = p->p_cred; 376 int error; 377 378 /* 379 * Linux copies these values out to userspace like so: 380 * 381 * 1. Copy out rgid. 382 * 2. If that succeeds, copy out egid. 383 * 3. If both of those succeed, copy out sgid. 384 */ 385 if ((error = copyout(&pc->p_rgid, SCARG(uap, rgid), 386 sizeof(gid_t))) != 0) 387 return (error); 388 389 if ((error = copyout(&pc->pc_ucred->cr_uid, SCARG(uap, egid), 390 sizeof(gid_t))) != 0) 391 return (error); 392 393 return (copyout(&pc->p_svgid, SCARG(uap, sgid), sizeof(gid_t))); 394 } 395 396 /* 397 * I wonder why Linux has settimeofday() _and_ stime().. Still, we 398 * need to deal with it. 399 */ 400 int 401 linux_sys_stime(p, v, retval) 402 struct proc *p; 403 void *v; 404 register_t *retval; 405 { 406 struct linux_sys_time_args /* { 407 linux_time_t *t; 408 } */ *uap = v; 409 struct timeval atv; 410 linux_time_t tt; 411 int error; 412 413 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 414 return (error); 415 416 if ((error = copyin(&tt, SCARG(uap, t), sizeof tt)) != 0) 417 return error; 418 419 atv.tv_sec = tt; 420 atv.tv_usec = 0; 421 422 if ((error = settime(&atv))) 423 return (error); 424 425 return 0; 426 } 427