1 /* $NetBSD: linux_misc_notalpha.c,v 1.109 2014/11/09 17:48:08 maxv Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998, 2008 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 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.109 2014/11/09 17:48:08 maxv Exp $"); 35 36 /* 37 * Note that we must NOT include "opt_compat_linux32.h" here, 38 * the maze of ifdefs below relies on COMPAT_LINUX32 only being 39 * defined when this file is built for linux32. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/mman.h> 46 #include <sys/mount.h> 47 #include <sys/mbuf.h> 48 #include <sys/namei.h> 49 #include <sys/proc.h> 50 #include <sys/prot.h> 51 #include <sys/ptrace.h> 52 #include <sys/resource.h> 53 #include <sys/resourcevar.h> 54 #include <sys/time.h> 55 #include <sys/vfs_syscalls.h> 56 #include <sys/wait.h> 57 #include <sys/kauth.h> 58 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 #include <compat/linux/common/linux_ipc.h> 68 #include <compat/linux/common/linux_sem.h> 69 #include <compat/linux/common/linux_statfs.h> 70 71 #include <compat/linux/linux_syscallargs.h> 72 73 /* 74 * This file contains routines which are used 75 * on every linux architechture except the Alpha. 76 */ 77 78 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */ 79 /* Not used on: alpha */ 80 81 #ifdef DEBUG_LINUX 82 #define DPRINTF(a) uprintf a 83 #else 84 #define DPRINTF(a) 85 #endif 86 87 #ifndef COMPAT_LINUX32 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 * XXX This shouldn't be dicking about with the ptimer stuff directly. 94 */ 95 int 96 linux_sys_alarm(struct lwp *l, const struct linux_sys_alarm_args *uap, register_t *retval) 97 { 98 /* { 99 syscallarg(unsigned int) secs; 100 } */ 101 struct proc *p = l->l_proc; 102 struct timespec now; 103 struct itimerspec *itp, it; 104 struct ptimer *ptp, *spare; 105 extern kmutex_t timer_lock; 106 struct ptimers *pts; 107 108 if ((pts = p->p_timers) == NULL) 109 pts = timers_alloc(p); 110 spare = NULL; 111 112 retry: 113 mutex_spin_enter(&timer_lock); 114 if (pts && pts->pts_timers[ITIMER_REAL]) 115 itp = &pts->pts_timers[ITIMER_REAL]->pt_time; 116 else 117 itp = NULL; 118 /* 119 * Clear any pending timer alarms. 120 */ 121 if (itp) { 122 callout_stop(&pts->pts_timers[ITIMER_REAL]->pt_ch); 123 timespecclear(&itp->it_interval); 124 getnanotime(&now); 125 if (timespecisset(&itp->it_value) && 126 timespeccmp(&itp->it_value, &now, >)) 127 timespecsub(&itp->it_value, &now, &itp->it_value); 128 /* 129 * Return how many seconds were left (rounded up) 130 */ 131 retval[0] = itp->it_value.tv_sec; 132 if (itp->it_value.tv_nsec) 133 retval[0]++; 134 } else { 135 retval[0] = 0; 136 } 137 138 /* 139 * alarm(0) just resets the timer. 140 */ 141 if (SCARG(uap, secs) == 0) { 142 if (itp) 143 timespecclear(&itp->it_value); 144 mutex_spin_exit(&timer_lock); 145 return 0; 146 } 147 148 /* 149 * Check the new alarm time for sanity, and set it. 150 */ 151 timespecclear(&it.it_interval); 152 it.it_value.tv_sec = SCARG(uap, secs); 153 it.it_value.tv_nsec = 0; 154 if (itimespecfix(&it.it_value) || itimespecfix(&it.it_interval)) { 155 mutex_spin_exit(&timer_lock); 156 return (EINVAL); 157 } 158 159 ptp = pts->pts_timers[ITIMER_REAL]; 160 if (ptp == NULL) { 161 if (spare == NULL) { 162 mutex_spin_exit(&timer_lock); 163 spare = pool_get(&ptimer_pool, PR_WAITOK); 164 goto retry; 165 } 166 ptp = spare; 167 spare = NULL; 168 ptp->pt_ev.sigev_notify = SIGEV_SIGNAL; 169 ptp->pt_ev.sigev_signo = SIGALRM; 170 ptp->pt_overruns = 0; 171 ptp->pt_proc = p; 172 ptp->pt_type = CLOCK_REALTIME; 173 ptp->pt_entry = CLOCK_REALTIME; 174 ptp->pt_active = 0; 175 ptp->pt_queued = 0; 176 callout_init(&ptp->pt_ch, CALLOUT_MPSAFE); 177 pts->pts_timers[ITIMER_REAL] = ptp; 178 } 179 180 if (timespecisset(&it.it_value)) { 181 /* 182 * Don't need to check tvhzto() return value, here. 183 * callout_reset() does it for us. 184 */ 185 getnanotime(&now); 186 timespecadd(&it.it_value, &now, &it.it_value); 187 callout_reset(&ptp->pt_ch, tshzto(&it.it_value), 188 realtimerexpire, ptp); 189 } 190 ptp->pt_time = it; 191 mutex_spin_exit(&timer_lock); 192 193 return 0; 194 } 195 #endif /* !COMPAT_LINUX32 */ 196 197 #if !defined(__amd64__) 198 int 199 linux_sys_nice(struct lwp *l, const struct linux_sys_nice_args *uap, register_t *retval) 200 { 201 /* { 202 syscallarg(int) incr; 203 } */ 204 struct proc *p = l->l_proc; 205 struct sys_setpriority_args bsa; 206 int error; 207 208 SCARG(&bsa, which) = PRIO_PROCESS; 209 SCARG(&bsa, who) = 0; 210 SCARG(&bsa, prio) = p->p_nice - NZERO + SCARG(uap, incr); 211 212 error = sys_setpriority(l, &bsa, retval); 213 return (error) ? EPERM : 0; 214 } 215 #endif /* !__amd64__ */ 216 217 #ifndef COMPAT_LINUX32 218 #ifndef __amd64__ 219 /* 220 * The old Linux readdir was only able to read one entry at a time, 221 * even though it had a 'count' argument. In fact, the emulation 222 * of the old call was better than the original, because it did handle 223 * the count arg properly. Don't bother with it anymore now, and use 224 * it to distinguish between old and new. The difference is that the 225 * newer one actually does multiple entries, and the reclen field 226 * really is the reclen, not the namelength. 227 */ 228 int 229 linux_sys_readdir(struct lwp *l, const struct linux_sys_readdir_args *uap, register_t *retval) 230 { 231 /* { 232 syscallarg(int) fd; 233 syscallarg(struct linux_dirent *) dent; 234 syscallarg(unsigned int) count; 235 } */ 236 int error; 237 struct linux_sys_getdents_args da; 238 239 SCARG(&da, fd) = SCARG(uap, fd); 240 SCARG(&da, dent) = SCARG(uap, dent); 241 SCARG(&da, count) = 1; 242 243 error = linux_sys_getdents(l, &da, retval); 244 if (error == 0 && *retval > 1) 245 *retval = 1; 246 247 return error; 248 } 249 #endif /* !amd64 */ 250 251 /* 252 * I wonder why Linux has gettimeofday() _and_ time().. Still, we 253 * need to deal with it. 254 */ 255 int 256 linux_sys_time(struct lwp *l, const struct linux_sys_time_args *uap, register_t *retval) 257 { 258 /* { 259 syscallarg(linux_time_t) *t; 260 } */ 261 struct timeval atv; 262 linux_time_t tt; 263 int error; 264 265 microtime(&atv); 266 267 tt = atv.tv_sec; 268 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) 269 return error; 270 271 retval[0] = tt; 272 return 0; 273 } 274 275 /* 276 * utime(). Do conversion to things that utimes() understands, 277 * and pass it on. 278 */ 279 int 280 linux_sys_utime(struct lwp *l, const struct linux_sys_utime_args *uap, register_t *retval) 281 { 282 /* { 283 syscallarg(const char *) path; 284 syscallarg(struct linux_utimbuf *)times; 285 } */ 286 int error; 287 struct timeval tv[2], *tvp; 288 struct linux_utimbuf lut; 289 290 if (SCARG(uap, times) != NULL) { 291 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) 292 return error; 293 tv[0].tv_usec = tv[1].tv_usec = 0; 294 tv[0].tv_sec = lut.l_actime; 295 tv[1].tv_sec = lut.l_modtime; 296 tvp = tv; 297 } else 298 tvp = NULL; 299 300 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 301 tvp, UIO_SYSSPACE); 302 } 303 304 #ifndef __amd64__ 305 /* 306 * waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage. 307 */ 308 int 309 linux_sys_waitpid(struct lwp *l, const struct linux_sys_waitpid_args *uap, register_t *retval) 310 { 311 /* { 312 syscallarg(int) pid; 313 syscallarg(int *) status; 314 syscallarg(int) options; 315 } */ 316 struct linux_sys_wait4_args linux_w4a; 317 318 SCARG(&linux_w4a, pid) = SCARG(uap, pid); 319 SCARG(&linux_w4a, status) = SCARG(uap, status); 320 SCARG(&linux_w4a, options) = SCARG(uap, options); 321 SCARG(&linux_w4a, rusage) = NULL; 322 323 return linux_sys_wait4(l, &linux_w4a, retval); 324 } 325 #endif /* !amd64 */ 326 327 int 328 linux_sys_setresgid(struct lwp *l, const struct linux_sys_setresgid_args *uap, register_t *retval) 329 { 330 /* { 331 syscallarg(gid_t) rgid; 332 syscallarg(gid_t) egid; 333 syscallarg(gid_t) sgid; 334 } */ 335 336 /* 337 * Note: These checks are a little different than the NetBSD 338 * setregid(2) call performs. This precisely follows the 339 * behavior of the Linux kernel. 340 */ 341 return do_setresgid(l, SCARG(uap,rgid), SCARG(uap, egid), 342 SCARG(uap, sgid), 343 ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S | 344 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 345 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S ); 346 } 347 348 int 349 linux_sys_getresgid(struct lwp *l, const struct linux_sys_getresgid_args *uap, register_t *retval) 350 { 351 /* { 352 syscallarg(gid_t *) rgid; 353 syscallarg(gid_t *) egid; 354 syscallarg(gid_t *) sgid; 355 } */ 356 kauth_cred_t pc = l->l_cred; 357 int error; 358 gid_t gid; 359 360 /* 361 * Linux copies these values out to userspace like so: 362 * 363 * 1. Copy out rgid. 364 * 2. If that succeeds, copy out egid. 365 * 3. If both of those succeed, copy out sgid. 366 */ 367 gid = kauth_cred_getgid(pc); 368 if ((error = copyout(&gid, SCARG(uap, rgid), sizeof(gid_t))) != 0) 369 return (error); 370 371 gid = kauth_cred_getegid(pc); 372 if ((error = copyout(&gid, SCARG(uap, egid), sizeof(gid_t))) != 0) 373 return (error); 374 375 gid = kauth_cred_getsvgid(pc); 376 377 return (copyout(&gid, SCARG(uap, sgid), sizeof(gid_t))); 378 } 379 380 #ifndef __amd64__ 381 /* 382 * I wonder why Linux has settimeofday() _and_ stime().. Still, we 383 * need to deal with it. 384 */ 385 int 386 linux_sys_stime(struct lwp *l, const struct linux_sys_stime_args *uap, register_t *retval) 387 { 388 /* { 389 syscallarg(linux_time_t) *t; 390 } */ 391 struct timespec ats; 392 linux_time_t tt; 393 int error; 394 395 if ((error = copyin(SCARG(uap, t), &tt, sizeof tt)) != 0) 396 return error; 397 398 ats.tv_sec = tt; 399 ats.tv_nsec = 0; 400 401 if ((error = settime(l->l_proc, &ats))) 402 return (error); 403 404 return 0; 405 } 406 407 /* 408 * Implement the fs stat functions. Straightforward. 409 */ 410 int 411 linux_sys_statfs64(struct lwp *l, const struct linux_sys_statfs64_args *uap, register_t *retval) 412 { 413 /* { 414 syscallarg(const char *) path; 415 syscallarg(size_t) sz; 416 syscallarg(struct linux_statfs64 *) sp; 417 } */ 418 struct statvfs *sb; 419 struct linux_statfs64 ltmp; 420 int error; 421 422 if (SCARG(uap, sz) != sizeof ltmp) 423 return (EINVAL); 424 425 sb = STATVFSBUF_GET(); 426 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb); 427 if (error == 0) { 428 bsd_to_linux_statfs64(sb, <mp); 429 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 430 } 431 STATVFSBUF_PUT(sb); 432 return error; 433 } 434 435 int 436 linux_sys_fstatfs64(struct lwp *l, const struct linux_sys_fstatfs64_args *uap, register_t *retval) 437 { 438 /* { 439 syscallarg(int) fd; 440 syscallarg(size_t) sz; 441 syscallarg(struct linux_statfs64 *) sp; 442 } */ 443 struct statvfs *sb; 444 struct linux_statfs64 ltmp; 445 int error; 446 447 if (SCARG(uap, sz) != sizeof ltmp) 448 return (EINVAL); 449 450 sb = STATVFSBUF_GET(); 451 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb); 452 if (error == 0) { 453 bsd_to_linux_statfs64(sb, <mp); 454 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 455 } 456 STATVFSBUF_PUT(sb); 457 return error; 458 } 459 #endif /* !__amd64__ */ 460 #endif /* !COMPAT_LINUX32 */ 461