1 /* $NetBSD: linux_misc_notalpha.c,v 1.72 2004/10/07 19:30:28 erh 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/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.72 2004/10/07 19:30:28 erh Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/mman.h> 47 #include <sys/mount.h> 48 #include <sys/malloc.h> 49 #include <sys/mbuf.h> 50 #include <sys/namei.h> 51 #include <sys/proc.h> 52 #include <sys/ptrace.h> 53 #include <sys/resource.h> 54 #include <sys/resourcevar.h> 55 #include <sys/time.h> 56 #include <sys/wait.h> 57 58 #include <sys/sa.h> 59 #include <sys/syscallargs.h> 60 61 #include <compat/linux/common/linux_types.h> 62 #include <compat/linux/common/linux_fcntl.h> 63 #include <compat/linux/common/linux_misc.h> 64 #include <compat/linux/common/linux_mmap.h> 65 #include <compat/linux/common/linux_signal.h> 66 #include <compat/linux/common/linux_util.h> 67 68 #include <compat/linux/linux_syscallargs.h> 69 70 /* 71 * This file contains routines which are used 72 * on every linux architechture except the Alpha. 73 */ 74 75 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */ 76 /* Not used on: alpha */ 77 78 #ifdef DEBUG_LINUX 79 #define DPRINTF(a) uprintf a 80 #else 81 #define DPRINTF(a) 82 #endif 83 84 #ifndef __m68k__ 85 static void bsd_to_linux_statfs64(const struct statvfs *, 86 struct linux_statfs64 *); 87 #endif 88 89 /* 90 * Alarm. This is a libc call which uses setitimer(2) in NetBSD. 91 * Fiddle with the timers to make it work. 92 */ 93 int 94 linux_sys_alarm(l, v, retval) 95 struct lwp *l; 96 void *v; 97 register_t *retval; 98 { 99 struct linux_sys_alarm_args /* { 100 syscallarg(unsigned int) secs; 101 } */ *uap = v; 102 struct proc *p = l->l_proc; 103 int s; 104 struct itimerval *itp, it; 105 struct ptimer *ptp; 106 107 if (p->p_timers && p->p_timers->pts_timers[ITIMER_REAL]) 108 itp = &p->p_timers->pts_timers[ITIMER_REAL]->pt_time; 109 else 110 itp = NULL; 111 s = splclock(); 112 /* 113 * Clear any pending timer alarms. 114 */ 115 if (itp) { 116 callout_stop(&p->p_timers->pts_timers[ITIMER_REAL]->pt_ch); 117 timerclear(&itp->it_interval); 118 if (timerisset(&itp->it_value) && 119 timercmp(&itp->it_value, &time, >)) 120 timersub(&itp->it_value, &time, &itp->it_value); 121 /* 122 * Return how many seconds were left (rounded up) 123 */ 124 retval[0] = itp->it_value.tv_sec; 125 if (itp->it_value.tv_usec) 126 retval[0]++; 127 } else { 128 retval[0] = 0; 129 } 130 131 /* 132 * alarm(0) just resets the timer. 133 */ 134 if (SCARG(uap, secs) == 0) { 135 if (itp) 136 timerclear(&itp->it_value); 137 splx(s); 138 return 0; 139 } 140 141 /* 142 * Check the new alarm time for sanity, and set it. 143 */ 144 timerclear(&it.it_interval); 145 it.it_value.tv_sec = SCARG(uap, secs); 146 it.it_value.tv_usec = 0; 147 if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) { 148 splx(s); 149 return (EINVAL); 150 } 151 152 if (p->p_timers == NULL) 153 timers_alloc(p); 154 ptp = p->p_timers->pts_timers[ITIMER_REAL]; 155 if (ptp == NULL) { 156 ptp = pool_get(&ptimer_pool, PR_WAITOK); 157 ptp->pt_ev.sigev_notify = SIGEV_SIGNAL; 158 ptp->pt_ev.sigev_signo = SIGALRM; 159 ptp->pt_overruns = 0; 160 ptp->pt_proc = p; 161 ptp->pt_type = CLOCK_REALTIME; 162 ptp->pt_entry = CLOCK_REALTIME; 163 callout_init(&ptp->pt_ch); 164 p->p_timers->pts_timers[ITIMER_REAL] = ptp; 165 } 166 167 if (timerisset(&it.it_value)) { 168 /* 169 * Don't need to check hzto() return value, here. 170 * callout_reset() does it for us. 171 */ 172 timeradd(&it.it_value, &time, &it.it_value); 173 callout_reset(&ptp->pt_ch, hzto(&it.it_value), 174 realtimerexpire, ptp); 175 } 176 ptp->pt_time = it; 177 splx(s); 178 179 return 0; 180 } 181 182 int 183 linux_sys_nice(l, v, retval) 184 struct lwp *l; 185 void *v; 186 register_t *retval; 187 { 188 struct linux_sys_nice_args /* { 189 syscallarg(int) incr; 190 } */ *uap = v; 191 struct sys_setpriority_args bsa; 192 193 SCARG(&bsa, which) = PRIO_PROCESS; 194 SCARG(&bsa, who) = 0; 195 SCARG(&bsa, prio) = SCARG(uap, incr); 196 return sys_setpriority(l, &bsa, retval); 197 } 198 199 /* 200 * The old Linux readdir was only able to read one entry at a time, 201 * even though it had a 'count' argument. In fact, the emulation 202 * of the old call was better than the original, because it did handle 203 * the count arg properly. Don't bother with it anymore now, and use 204 * it to distinguish between old and new. The difference is that the 205 * newer one actually does multiple entries, and the reclen field 206 * really is the reclen, not the namelength. 207 */ 208 int 209 linux_sys_readdir(l, v, retval) 210 struct lwp *l; 211 void *v; 212 register_t *retval; 213 { 214 struct linux_sys_readdir_args /* { 215 syscallarg(int) fd; 216 syscallarg(struct linux_dirent *) dent; 217 syscallarg(unsigned int) count; 218 } */ *uap = v; 219 220 SCARG(uap, count) = 1; 221 return linux_sys_getdents(l, uap, retval); 222 } 223 224 /* 225 * I wonder why Linux has gettimeofday() _and_ time().. Still, we 226 * need to deal with it. 227 */ 228 int 229 linux_sys_time(l, v, retval) 230 struct lwp *l; 231 void *v; 232 register_t *retval; 233 { 234 struct linux_sys_time_args /* { 235 linux_time_t *t; 236 } */ *uap = v; 237 struct timeval atv; 238 linux_time_t tt; 239 int error; 240 241 microtime(&atv); 242 243 tt = atv.tv_sec; 244 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) 245 return error; 246 247 retval[0] = tt; 248 return 0; 249 } 250 251 /* 252 * utime(). Do conversion to things that utimes() understands, 253 * and pass it on. 254 */ 255 int 256 linux_sys_utime(l, v, retval) 257 struct lwp *l; 258 void *v; 259 register_t *retval; 260 { 261 struct linux_sys_utime_args /* { 262 syscallarg(const char *) path; 263 syscallarg(struct linux_utimbuf *)times; 264 } */ *uap = v; 265 struct proc *p = l->l_proc; 266 caddr_t sg; 267 int error; 268 struct sys_utimes_args ua; 269 struct timeval tv[2], *tvp; 270 struct linux_utimbuf lut; 271 272 sg = stackgap_init(p, 0); 273 tvp = (struct timeval *) stackgap_alloc(p, &sg, sizeof(tv)); 274 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 275 276 SCARG(&ua, path) = SCARG(uap, path); 277 278 if (SCARG(uap, times) != NULL) { 279 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) 280 return error; 281 tv[0].tv_usec = tv[1].tv_usec = 0; 282 tv[0].tv_sec = lut.l_actime; 283 tv[1].tv_sec = lut.l_modtime; 284 if ((error = copyout(tv, tvp, sizeof tv))) 285 return error; 286 SCARG(&ua, tptr) = tvp; 287 } 288 else 289 SCARG(&ua, tptr) = NULL; 290 291 return sys_utimes(l, &ua, retval); 292 } 293 294 /* 295 * waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage. 296 */ 297 int 298 linux_sys_waitpid(l, v, retval) 299 struct lwp *l; 300 void *v; 301 register_t *retval; 302 { 303 struct linux_sys_waitpid_args /* { 304 syscallarg(int) pid; 305 syscallarg(int *) status; 306 syscallarg(int) options; 307 } */ *uap = v; 308 struct linux_sys_wait4_args linux_w4a; 309 310 SCARG(&linux_w4a, pid) = SCARG(uap, pid); 311 SCARG(&linux_w4a, status) = SCARG(uap, status); 312 SCARG(&linux_w4a, options) = SCARG(uap, options); 313 SCARG(&linux_w4a, rusage) = NULL; 314 315 return linux_sys_wait4(l, &linux_w4a, retval); 316 } 317 318 int 319 linux_sys_setresgid(l, v, retval) 320 struct lwp *l; 321 void *v; 322 register_t *retval; 323 { 324 struct linux_sys_setresgid_args /* { 325 syscallarg(gid_t) rgid; 326 syscallarg(gid_t) egid; 327 syscallarg(gid_t) sgid; 328 } */ *uap = v; 329 330 /* 331 * Note: These checks are a little different than the NetBSD 332 * setregid(2) call performs. This precisely follows the 333 * behavior of the Linux kernel. 334 */ 335 return do_setresgid(l, SCARG(uap,rgid), SCARG(uap, egid), 336 SCARG(uap, sgid), 337 ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S | 338 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 339 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S ); 340 } 341 342 int 343 linux_sys_getresgid(l, v, retval) 344 struct lwp *l; 345 void *v; 346 register_t *retval; 347 { 348 struct linux_sys_getresgid_args /* { 349 syscallarg(gid_t *) rgid; 350 syscallarg(gid_t *) egid; 351 syscallarg(gid_t *) sgid; 352 } */ *uap = v; 353 struct proc *p = l->l_proc; 354 struct pcred *pc = p->p_cred; 355 int error; 356 357 /* 358 * Linux copies these values out to userspace like so: 359 * 360 * 1. Copy out rgid. 361 * 2. If that succeeds, copy out egid. 362 * 3. If both of those succeed, copy out sgid. 363 */ 364 if ((error = copyout(&pc->p_rgid, SCARG(uap, rgid), 365 sizeof(gid_t))) != 0) 366 return (error); 367 368 if ((error = copyout(&pc->pc_ucred->cr_gid, SCARG(uap, egid), 369 sizeof(gid_t))) != 0) 370 return (error); 371 372 return (copyout(&pc->p_svgid, SCARG(uap, sgid), sizeof(gid_t))); 373 } 374 375 /* 376 * I wonder why Linux has settimeofday() _and_ stime().. Still, we 377 * need to deal with it. 378 */ 379 int 380 linux_sys_stime(l, v, retval) 381 struct lwp *l; 382 void *v; 383 register_t *retval; 384 { 385 struct linux_sys_time_args /* { 386 linux_time_t *t; 387 } */ *uap = v; 388 struct proc *p = l->l_proc; 389 struct timeval atv; 390 linux_time_t tt; 391 int error; 392 393 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 394 return (error); 395 396 if ((error = copyin(&tt, SCARG(uap, t), sizeof tt)) != 0) 397 return error; 398 399 atv.tv_sec = tt; 400 atv.tv_usec = 0; 401 402 if ((error = settime(&atv))) 403 return (error); 404 405 return 0; 406 } 407 408 #ifndef __m68k__ 409 /* 410 * Convert NetBSD statvfs structure to Linux statfs64 structure. 411 * See comments in bsd_to_linux_statfs() for further background. 412 * We can safely pass correct bsize and frsize here, since Linux glibc 413 * statvfs() doesn't use statfs64(). 414 */ 415 static void 416 bsd_to_linux_statfs64(bsp, lsp) 417 const struct statvfs *bsp; 418 struct linux_statfs64 *lsp; 419 { 420 int i, div; 421 422 for (i = 0; i < linux_fstypes_cnt; i++) { 423 if (strcmp(bsp->f_fstypename, linux_fstypes[i].bsd) == 0) { 424 lsp->l_ftype = linux_fstypes[i].linux; 425 break; 426 } 427 } 428 429 if (i == linux_fstypes_cnt) { 430 DPRINTF(("unhandled fstype in linux emulation: %s\n", 431 bsp->f_fstypename)); 432 lsp->l_ftype = LINUX_DEFAULT_SUPER_MAGIC; 433 } 434 435 div = bsp->f_bsize / bsp->f_frsize; 436 lsp->l_fbsize = bsp->f_bsize; 437 lsp->l_ffrsize = bsp->f_frsize; 438 lsp->l_fblocks = bsp->f_blocks / div; 439 lsp->l_fbfree = bsp->f_bfree / div; 440 lsp->l_fbavail = bsp->f_bavail / div; 441 lsp->l_ffiles = bsp->f_files; 442 lsp->l_fffree = bsp->f_ffree / div; 443 /* Linux sets the fsid to 0..., we don't */ 444 lsp->l_ffsid.val[0] = bsp->f_fsidx.__fsid_val[0]; 445 lsp->l_ffsid.val[1] = bsp->f_fsidx.__fsid_val[1]; 446 lsp->l_fnamelen = bsp->f_namemax; 447 (void)memset(lsp->l_fspare, 0, sizeof(lsp->l_fspare)); 448 } 449 450 /* 451 * Implement the fs stat functions. Straightforward. 452 */ 453 int 454 linux_sys_statfs64(l, v, retval) 455 struct lwp *l; 456 void *v; 457 register_t *retval; 458 { 459 struct linux_sys_statfs64_args /* { 460 syscallarg(const char *) path; 461 syscallarg(size_t) sz; 462 syscallarg(struct linux_statfs64 *) sp; 463 } */ *uap = v; 464 struct proc *p = l->l_proc; 465 struct statvfs btmp, *bsp; 466 struct linux_statfs64 ltmp; 467 struct sys_statvfs1_args bsa; 468 caddr_t sg; 469 int error; 470 471 if (SCARG(uap, sz) != sizeof ltmp) 472 return (EINVAL); 473 474 sg = stackgap_init(p, 0); 475 bsp = (struct statvfs *) stackgap_alloc(p, &sg, sizeof (struct statvfs)); 476 477 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 478 479 SCARG(&bsa, path) = SCARG(uap, path); 480 SCARG(&bsa, buf) = bsp; 481 SCARG(&bsa, flags) = ST_WAIT; 482 483 if ((error = sys_statvfs1(l, &bsa, retval))) 484 return error; 485 486 if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) 487 return error; 488 489 bsd_to_linux_statfs64(&btmp, <mp); 490 491 return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); 492 } 493 494 int 495 linux_sys_fstatfs64(l, v, retval) 496 struct lwp *l; 497 void *v; 498 register_t *retval; 499 { 500 struct linux_sys_fstatfs64_args /* { 501 syscallarg(int) fd; 502 syscallarg(size_t) sz; 503 syscallarg(struct linux_statfs64 *) sp; 504 } */ *uap = v; 505 struct proc *p = l->l_proc; 506 struct statvfs btmp, *bsp; 507 struct linux_statfs64 ltmp; 508 struct sys_fstatvfs1_args bsa; 509 caddr_t sg; 510 int error; 511 512 if (SCARG(uap, sz) != sizeof ltmp) 513 return (EINVAL); 514 515 sg = stackgap_init(p, 0); 516 bsp = (struct statvfs *) stackgap_alloc(p, &sg, sizeof (struct statvfs)); 517 518 SCARG(&bsa, fd) = SCARG(uap, fd); 519 SCARG(&bsa, buf) = bsp; 520 SCARG(&bsa, flags) = ST_WAIT; 521 522 if ((error = sys_fstatvfs1(l, &bsa, retval))) 523 return error; 524 525 if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) 526 return error; 527 528 bsd_to_linux_statfs64(&btmp, <mp); 529 530 return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); 531 } 532 #endif /* !__m68k__ */ 533