1 /* $NetBSD: linux_misc_notalpha.c,v 1.52 1999/08/16 19:06:29 tron 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 untimeout(realitexpire, p); 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 timeout(realitexpire, p, hzto(&it.it_value)); 131 } 132 p->p_realtimer = it; 133 splx(s); 134 135 return 0; 136 } 137 138 int 139 linux_sys_nice(p, v, retval) 140 struct proc *p; 141 void *v; 142 register_t *retval; 143 { 144 struct linux_sys_nice_args /* { 145 syscallarg(int) incr; 146 } */ *uap = v; 147 struct sys_setpriority_args bsa; 148 149 SCARG(&bsa, which) = PRIO_PROCESS; 150 SCARG(&bsa, who) = 0; 151 SCARG(&bsa, prio) = SCARG(uap, incr); 152 return sys_setpriority(p, &bsa, retval); 153 } 154 155 /* 156 * The old Linux readdir was only able to read one entry at a time, 157 * even though it had a 'count' argument. In fact, the emulation 158 * of the old call was better than the original, because it did handle 159 * the count arg properly. Don't bother with it anymore now, and use 160 * it to distinguish between old and new. The difference is that the 161 * newer one actually does multiple entries, and the reclen field 162 * really is the reclen, not the namelength. 163 */ 164 int 165 linux_sys_readdir(p, v, retval) 166 struct proc *p; 167 void *v; 168 register_t *retval; 169 { 170 struct linux_sys_readdir_args /* { 171 syscallarg(int) fd; 172 syscallarg(struct linux_dirent *) dent; 173 syscallarg(unsigned int) count; 174 } */ *uap = v; 175 176 SCARG(uap, count) = 1; 177 return linux_sys_getdents(p, uap, retval); 178 } 179 180 /* 181 * I wonder why Linux has gettimeofday() _and_ time().. Still, we 182 * need to deal with it. 183 */ 184 int 185 linux_sys_time(p, v, retval) 186 struct proc *p; 187 void *v; 188 register_t *retval; 189 { 190 struct linux_sys_time_args /* { 191 linux_time_t *t; 192 } */ *uap = v; 193 struct timeval atv; 194 linux_time_t tt; 195 int error; 196 197 microtime(&atv); 198 199 tt = atv.tv_sec; 200 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) 201 return error; 202 203 retval[0] = tt; 204 return 0; 205 } 206 207 /* 208 * utime(). Do conversion to things that utimes() understands, 209 * and pass it on. 210 */ 211 int 212 linux_sys_utime(p, v, retval) 213 struct proc *p; 214 void *v; 215 register_t *retval; 216 { 217 struct linux_sys_utime_args /* { 218 syscallarg(const char *) path; 219 syscallarg(struct linux_utimbuf *)times; 220 } */ *uap = v; 221 caddr_t sg; 222 int error; 223 struct sys_utimes_args ua; 224 struct timeval tv[2], *tvp; 225 struct linux_utimbuf lut; 226 227 sg = stackgap_init(p->p_emul); 228 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 229 230 SCARG(&ua, path) = SCARG(uap, path); 231 232 if (SCARG(uap, times) != NULL) { 233 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) 234 return error; 235 tv[0].tv_usec = tv[1].tv_usec = 0; 236 tv[0].tv_sec = lut.l_actime; 237 tv[1].tv_sec = lut.l_modtime; 238 tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv)); 239 if ((error = copyout(tv, tvp, sizeof tv))) 240 return error; 241 SCARG(&ua, tptr) = tvp; 242 } 243 else 244 SCARG(&ua, tptr) = NULL; 245 246 return sys_utimes(p, &ua, retval); 247 } 248 249 /* 250 * waitpid(2). Passed on to the NetBSD call, surrounded by code to 251 * reserve some space for a NetBSD-style wait status, and converting 252 * it to what Linux wants. 253 */ 254 int 255 linux_sys_waitpid(p, v, retval) 256 struct proc *p; 257 void *v; 258 register_t *retval; 259 { 260 struct linux_sys_waitpid_args /* { 261 syscallarg(int) pid; 262 syscallarg(int *) status; 263 syscallarg(int) options; 264 } */ *uap = v; 265 struct sys_wait4_args w4a; 266 int error, *status, tstat; 267 caddr_t sg; 268 269 if (SCARG(uap, status) != NULL) { 270 sg = stackgap_init(p->p_emul); 271 status = (int *) stackgap_alloc(&sg, sizeof status); 272 } else 273 status = NULL; 274 275 SCARG(&w4a, pid) = SCARG(uap, pid); 276 SCARG(&w4a, status) = status; 277 SCARG(&w4a, options) = SCARG(uap, options); 278 SCARG(&w4a, rusage) = NULL; 279 280 if ((error = sys_wait4(p, &w4a, retval))) 281 return error; 282 283 sigdelset(&p->p_siglist, SIGCHLD); 284 285 if (status != NULL) { 286 if ((error = copyin(status, &tstat, sizeof tstat))) 287 return error; 288 289 bsd_to_linux_wstat(&tstat); 290 return copyout(&tstat, SCARG(uap, status), sizeof tstat); 291 } 292 293 return 0; 294 } 295 296 int 297 linux_sys_setresgid(p, v, retval) 298 struct proc *p; 299 void *v; 300 register_t *retval; 301 { 302 struct linux_sys_setresgid_args /* { 303 syscallarg(gid_t) rgid; 304 syscallarg(gid_t) egid; 305 syscallarg(gid_t) sgid; 306 } */ *uap = v; 307 struct pcred *pc = p->p_cred; 308 gid_t rgid, egid, sgid; 309 int error; 310 311 rgid = SCARG(uap, rgid); 312 egid = SCARG(uap, egid); 313 sgid = SCARG(uap, sgid); 314 315 /* 316 * Note: These checks are a little different than the NetBSD 317 * setregid(2) call performs. This precisely follows the 318 * behavior of the Linux kernel. 319 */ 320 if (rgid != (gid_t)-1 && 321 rgid != pc->p_rgid && 322 rgid != pc->pc_ucred->cr_gid && 323 rgid != pc->p_svgid && 324 (error = suser(pc->pc_ucred, &p->p_acflag))) 325 return (error); 326 327 if (egid != (gid_t)-1 && 328 egid != pc->p_rgid && 329 egid != pc->pc_ucred->cr_gid && 330 egid != pc->p_svgid && 331 (error = suser(pc->pc_ucred, &p->p_acflag))) 332 return (error); 333 334 if (sgid != (gid_t)-1 && 335 sgid != pc->p_rgid && 336 sgid != pc->pc_ucred->cr_gid && 337 sgid != pc->p_svgid && 338 (error = suser(pc->pc_ucred, &p->p_acflag))) 339 return (error); 340 341 /* 342 * Now assign the real, effective, and saved GIDs. 343 * Note that Linux, unlike NetBSD in setregid(2), does not 344 * set the saved UID in this call unless the user specifies 345 * it. 346 */ 347 if (rgid != (gid_t)-1) 348 pc->p_rgid = rgid; 349 350 if (egid != (gid_t)-1) { 351 pc->pc_ucred = crcopy(pc->pc_ucred); 352 pc->pc_ucred->cr_gid = egid; 353 } 354 355 if (sgid != (gid_t)-1) 356 pc->p_svgid = sgid; 357 358 if (rgid != (gid_t)-1 && egid != (gid_t)-1 && sgid != (gid_t)-1) 359 p->p_flag |= P_SUGID; 360 return (0); 361 } 362 363 int 364 linux_sys_getresgid(p, v, retval) 365 struct proc *p; 366 void *v; 367 register_t *retval; 368 { 369 struct linux_sys_getresgid_args /* { 370 syscallarg(gid_t *) rgid; 371 syscallarg(gid_t *) egid; 372 syscallarg(gid_t *) sgid; 373 } */ *uap = v; 374 struct pcred *pc = p->p_cred; 375 int error; 376 377 /* 378 * Linux copies these values out to userspace like so: 379 * 380 * 1. Copy out rgid. 381 * 2. If that succeeds, copy out egid. 382 * 3. If both of those succeed, copy out sgid. 383 */ 384 if ((error = copyout(&pc->p_rgid, SCARG(uap, rgid), 385 sizeof(gid_t))) != 0) 386 return (error); 387 388 if ((error = copyout(&pc->pc_ucred->cr_uid, SCARG(uap, egid), 389 sizeof(gid_t))) != 0) 390 return (error); 391 392 return (copyout(&pc->p_svgid, SCARG(uap, sgid), sizeof(gid_t))); 393 } 394 395 /* 396 * I wonder why Linux has settimeofday() _and_ stime().. Still, we 397 * need to deal with it. 398 */ 399 int 400 linux_sys_stime(p, v, retval) 401 struct proc *p; 402 void *v; 403 register_t *retval; 404 { 405 struct linux_sys_time_args /* { 406 linux_time_t *t; 407 } */ *uap = v; 408 struct timeval atv; 409 linux_time_t tt; 410 int error; 411 412 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 413 return (error); 414 415 if ((error = copyin(&tt, SCARG(uap, t), sizeof tt)) != 0) 416 return error; 417 418 atv.tv_sec = tt; 419 atv.tv_usec = 0; 420 421 if ((error = settime(&atv))) 422 return (error); 423 424 return 0; 425 } 426