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