1/*- 2 * Copyright (c) 1995 Steven Wallace 3 * Copyright (c) 1994, 1995 Scott Bartram 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the University of 27 * California, Berkeley and its contributors. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 45 * 46 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 47 */ 48 49#include <sys/cdefs.h> 50__FBSDID("$FreeBSD: stable/10/sys/i386/ibcs2/ibcs2_misc.c 331671 2018-03-28 13:44:02Z emaste $"); 51 52/* 53 * IBCS2 compatibility module. 54 * 55 * IBCS2 system calls that are implemented differently in BSD are 56 * handled here. 57 */ 58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/capsicum.h> 61#include <sys/dirent.h> 62#include <sys/fcntl.h> 63#include <sys/filedesc.h> 64#include <sys/imgact.h> 65#include <sys/kernel.h> 66#include <sys/lock.h> 67#include <sys/malloc.h> 68#include <sys/file.h> /* Must come after sys/malloc.h */ 69#include <sys/mutex.h> 70#include <sys/namei.h> 71#include <sys/priv.h> 72#include <sys/reboot.h> 73#include <sys/resourcevar.h> 74#include <sys/stat.h> 75#include <sys/sysctl.h> 76#include <sys/syscallsubr.h> 77#include <sys/sysproto.h> 78#include <sys/time.h> 79#include <sys/times.h> 80#include <sys/vnode.h> 81#include <sys/wait.h> 82 83#include <machine/cpu.h> 84 85#include <i386/ibcs2/ibcs2_dirent.h> 86#include <i386/ibcs2/ibcs2_signal.h> 87#include <i386/ibcs2/ibcs2_proto.h> 88#include <i386/ibcs2/ibcs2_unistd.h> 89#include <i386/ibcs2/ibcs2_util.h> 90#include <i386/ibcs2/ibcs2_utime.h> 91#include <i386/ibcs2/ibcs2_xenix.h> 92 93#include <security/mac/mac_framework.h> 94 95int 96ibcs2_ulimit(td, uap) 97 struct thread *td; 98 struct ibcs2_ulimit_args *uap; 99{ 100 struct rlimit rl; 101 struct proc *p; 102 int error; 103#define IBCS2_GETFSIZE 1 104#define IBCS2_SETFSIZE 2 105#define IBCS2_GETPSIZE 3 106#define IBCS2_GETDTABLESIZE 4 107 108 p = td->td_proc; 109 switch (uap->cmd) { 110 case IBCS2_GETFSIZE: 111 PROC_LOCK(p); 112 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 113 PROC_UNLOCK(p); 114 if (td->td_retval[0] == -1) 115 td->td_retval[0] = 0x7fffffff; 116 return 0; 117 case IBCS2_SETFSIZE: 118 PROC_LOCK(p); 119 rl.rlim_max = lim_max(p, RLIMIT_FSIZE); 120 PROC_UNLOCK(p); 121 rl.rlim_cur = uap->newlimit; 122 error = kern_setrlimit(td, RLIMIT_FSIZE, &rl); 123 if (!error) { 124 PROC_LOCK(p); 125 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 126 PROC_UNLOCK(p); 127 } else { 128 DPRINTF(("failed ")); 129 } 130 return error; 131 case IBCS2_GETPSIZE: 132 PROC_LOCK(p); 133 td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */ 134 PROC_UNLOCK(p); 135 return 0; 136 case IBCS2_GETDTABLESIZE: 137 uap->cmd = IBCS2_SC_OPEN_MAX; 138 return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap); 139 default: 140 return ENOSYS; 141 } 142} 143 144#define IBCS2_WSTOPPED 0177 145#define IBCS2_STOPCODE(sig) ((sig) << 8 | IBCS2_WSTOPPED) 146int 147ibcs2_wait(td, uap) 148 struct thread *td; 149 struct ibcs2_wait_args *uap; 150{ 151 int error, options, status; 152 int *statusp; 153 pid_t pid; 154 struct trapframe *tf = td->td_frame; 155 156 if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V)) 157 == (PSL_Z|PSL_PF|PSL_N|PSL_V)) { 158 /* waitpid */ 159 pid = uap->a1; 160 statusp = (int *)uap->a2; 161 options = uap->a3; 162 } else { 163 /* wait */ 164 pid = WAIT_ANY; 165 statusp = (int *)uap->a1; 166 options = 0; 167 } 168 error = kern_wait(td, pid, &status, options, NULL); 169 if (error) 170 return error; 171 if (statusp) { 172 /* 173 * Convert status/signal result. 174 */ 175 if (WIFSTOPPED(status)) { 176 if (WSTOPSIG(status) <= 0 || 177 WSTOPSIG(status) > IBCS2_SIGTBLSZ) 178 return (EINVAL); 179 status = 180 IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]); 181 } else if (WIFSIGNALED(status)) { 182 if (WTERMSIG(status) <= 0 || 183 WTERMSIG(status) > IBCS2_SIGTBLSZ) 184 return (EINVAL); 185 status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))]; 186 } 187 /* else exit status -- identical */ 188 189 /* record result/status */ 190 td->td_retval[1] = status; 191 return copyout(&status, statusp, sizeof(status)); 192 } 193 194 return 0; 195} 196 197int 198ibcs2_execv(td, uap) 199 struct thread *td; 200 struct ibcs2_execv_args *uap; 201{ 202 struct image_args eargs; 203 struct vmspace *oldvmspace; 204 char *path; 205 int error; 206 207 CHECKALTEXIST(td, uap->path, &path); 208 209 error = pre_execve(td, &oldvmspace); 210 if (error != 0) { 211 free(path, M_TEMP); 212 return (error); 213 } 214 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL); 215 free(path, M_TEMP); 216 if (error == 0) 217 error = kern_execve(td, &eargs, NULL); 218 post_execve(td, error, oldvmspace); 219 return (error); 220} 221 222int 223ibcs2_execve(td, uap) 224 struct thread *td; 225 struct ibcs2_execve_args *uap; 226{ 227 struct image_args eargs; 228 struct vmspace *oldvmspace; 229 char *path; 230 int error; 231 232 CHECKALTEXIST(td, uap->path, &path); 233 234 error = pre_execve(td, &oldvmspace); 235 if (error != 0) { 236 free(path, M_TEMP); 237 return (error); 238 } 239 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, 240 uap->envp); 241 free(path, M_TEMP); 242 if (error == 0) 243 error = kern_execve(td, &eargs, NULL); 244 post_execve(td, error, oldvmspace); 245 return (error); 246} 247 248int 249ibcs2_umount(td, uap) 250 struct thread *td; 251 struct ibcs2_umount_args *uap; 252{ 253 struct unmount_args um; 254 255 um.path = uap->name; 256 um.flags = 0; 257 return sys_unmount(td, &um); 258} 259 260int 261ibcs2_mount(td, uap) 262 struct thread *td; 263 struct ibcs2_mount_args *uap; 264{ 265#ifdef notyet 266 int oflags = uap->flags, nflags, error; 267 char fsname[MFSNAMELEN]; 268 269 if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5)) 270 return (EINVAL); 271 if ((oflags & IBCS2_MS_NEWTYPE) == 0) 272 return (EINVAL); 273 nflags = 0; 274 if (oflags & IBCS2_MS_RDONLY) 275 nflags |= MNT_RDONLY; 276 if (oflags & IBCS2_MS_NOSUID) 277 nflags |= MNT_NOSUID; 278 if (oflags & IBCS2_MS_REMOUNT) 279 nflags |= MNT_UPDATE; 280 uap->flags = nflags; 281 282 if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, 283 (u_int *)0)) 284 return (error); 285 286 if (strcmp(fsname, "4.2") == 0) { 287 uap->type = (caddr_t)STACK_ALLOC(); 288 if (error = copyout("ufs", uap->type, sizeof("ufs"))) 289 return (error); 290 } else if (strcmp(fsname, "nfs") == 0) { 291 struct ibcs2_nfs_args sna; 292 struct sockaddr_in sain; 293 struct nfs_args na; 294 struct sockaddr sa; 295 296 if (error = copyin(uap->data, &sna, sizeof sna)) 297 return (error); 298 if (error = copyin(sna.addr, &sain, sizeof sain)) 299 return (error); 300 bcopy(&sain, &sa, sizeof sa); 301 sa.sa_len = sizeof(sain); 302 uap->data = (caddr_t)STACK_ALLOC(); 303 na.addr = (struct sockaddr *)((int)uap->data + sizeof na); 304 na.sotype = SOCK_DGRAM; 305 na.proto = IPPROTO_UDP; 306 na.fh = (nfsv2fh_t *)sna.fh; 307 na.flags = sna.flags; 308 na.wsize = sna.wsize; 309 na.rsize = sna.rsize; 310 na.timeo = sna.timeo; 311 na.retrans = sna.retrans; 312 na.hostname = sna.hostname; 313 314 if (error = copyout(&sa, na.addr, sizeof sa)) 315 return (error); 316 if (error = copyout(&na, uap->data, sizeof na)) 317 return (error); 318 } 319 return (mount(td, uap)); 320#else 321 return EINVAL; 322#endif 323} 324 325/* 326 * Read iBCS2-style directory entries. We suck them into kernel space so 327 * that they can be massaged before being copied out to user code. Like 328 * SunOS, we squish out `empty' entries. 329 * 330 * This is quite ugly, but what do you expect from compatibility code? 331 */ 332 333int 334ibcs2_getdents(td, uap) 335 struct thread *td; 336 register struct ibcs2_getdents_args *uap; 337{ 338 register struct vnode *vp; 339 register caddr_t inp, buf; /* BSD-format */ 340 register int len, reclen; /* BSD-format */ 341 register caddr_t outp; /* iBCS2-format */ 342 register int resid; /* iBCS2-format */ 343 cap_rights_t rights; 344 struct file *fp; 345 struct uio auio; 346 struct iovec aiov; 347 struct ibcs2_dirent idb; 348 off_t off; /* true file offset */ 349 int buflen, error, eofflag; 350 u_long *cookies = NULL, *cookiep; 351 int ncookies; 352#define BSD_DIRENT(cp) ((struct dirent *)(cp)) 353#define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) 354 355 memset(&idb, 0, sizeof(idb)); 356 error = getvnode(td->td_proc->p_fd, uap->fd, 357 cap_rights_init(&rights, CAP_READ), &fp); 358 if (error != 0) 359 return (error); 360 if ((fp->f_flag & FREAD) == 0) { 361 fdrop(fp, td); 362 return (EBADF); 363 } 364 vp = fp->f_vnode; 365 if (vp->v_type != VDIR) { /* XXX vnode readdir op should do this */ 366 fdrop(fp, td); 367 return (EINVAL); 368 } 369 370 off = fp->f_offset; 371#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 372 buflen = max(DIRBLKSIZ, uap->nbytes); 373 buflen = min(buflen, MAXBSIZE); 374 buf = malloc(buflen, M_TEMP, M_WAITOK); 375 vn_lock(vp, LK_SHARED | LK_RETRY); 376again: 377 aiov.iov_base = buf; 378 aiov.iov_len = buflen; 379 auio.uio_iov = &aiov; 380 auio.uio_iovcnt = 1; 381 auio.uio_rw = UIO_READ; 382 auio.uio_segflg = UIO_SYSSPACE; 383 auio.uio_td = td; 384 auio.uio_resid = buflen; 385 auio.uio_offset = off; 386 387 if (cookies) { 388 free(cookies, M_TEMP); 389 cookies = NULL; 390 } 391 392#ifdef MAC 393 error = mac_vnode_check_readdir(td->td_ucred, vp); 394 if (error) 395 goto out; 396#endif 397 398 /* 399 * First we read into the malloc'ed buffer, then 400 * we massage it into user space, one record at a time. 401 */ 402 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) 403 goto out; 404 inp = buf; 405 outp = uap->buf; 406 resid = uap->nbytes; 407 if ((len = buflen - auio.uio_resid) <= 0) 408 goto eof; 409 410 cookiep = cookies; 411 412 if (cookies) { 413 /* 414 * When using cookies, the vfs has the option of reading from 415 * a different offset than that supplied (UFS truncates the 416 * offset to a block boundary to make sure that it never reads 417 * partway through a directory entry, even if the directory 418 * has been compacted). 419 */ 420 while (len > 0 && ncookies > 0 && *cookiep <= off) { 421 len -= BSD_DIRENT(inp)->d_reclen; 422 inp += BSD_DIRENT(inp)->d_reclen; 423 cookiep++; 424 ncookies--; 425 } 426 } 427 428 for (; len > 0; len -= reclen) { 429 if (cookiep && ncookies == 0) 430 break; 431 reclen = BSD_DIRENT(inp)->d_reclen; 432 if (reclen & 3) { 433 printf("ibcs2_getdents: reclen=%d\n", reclen); 434 error = EFAULT; 435 goto out; 436 } 437 if (BSD_DIRENT(inp)->d_fileno == 0) { 438 inp += reclen; /* it is a hole; squish it out */ 439 if (cookiep) { 440 off = *cookiep++; 441 ncookies--; 442 } else 443 off += reclen; 444 continue; 445 } 446 if (reclen > len || resid < IBCS2_RECLEN(reclen)) { 447 /* entry too big for buffer, so just stop */ 448 outp++; 449 break; 450 } 451 /* 452 * Massage in place to make an iBCS2-shaped dirent (otherwise 453 * we have to worry about touching user memory outside of 454 * the copyout() call). 455 */ 456 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno; 457 idb.d_off = (ibcs2_off_t)off; 458 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen); 459 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 || 460 (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10, 461 BSD_DIRENT(inp)->d_namlen + 1)) != 0) 462 goto out; 463 /* advance past this real entry */ 464 if (cookiep) { 465 off = *cookiep++; 466 ncookies--; 467 } else 468 off += reclen; 469 inp += reclen; 470 /* advance output past iBCS2-shaped entry */ 471 outp += IBCS2_RECLEN(reclen); 472 resid -= IBCS2_RECLEN(reclen); 473 } 474 /* if we squished out the whole block, try again */ 475 if (outp == uap->buf) 476 goto again; 477 fp->f_offset = off; /* update the vnode offset */ 478eof: 479 td->td_retval[0] = uap->nbytes - resid; 480out: 481 VOP_UNLOCK(vp, 0); 482 fdrop(fp, td); 483 if (cookies) 484 free(cookies, M_TEMP); 485 free(buf, M_TEMP); 486 return (error); 487} 488 489int 490ibcs2_read(td, uap) 491 struct thread *td; 492 struct ibcs2_read_args *uap; 493{ 494 register struct vnode *vp; 495 register caddr_t inp, buf; /* BSD-format */ 496 register int len, reclen; /* BSD-format */ 497 register caddr_t outp; /* iBCS2-format */ 498 register int resid; /* iBCS2-format */ 499 cap_rights_t rights; 500 struct file *fp; 501 struct uio auio; 502 struct iovec aiov; 503 struct ibcs2_direct { 504 ibcs2_ino_t ino; 505 char name[14]; 506 } idb; 507 off_t off; /* true file offset */ 508 int buflen, error, eofflag, size; 509 u_long *cookies = NULL, *cookiep; 510 int ncookies; 511 512 error = getvnode(td->td_proc->p_fd, uap->fd, 513 cap_rights_init(&rights, CAP_READ), &fp); 514 if (error != 0) { 515 if (error == EINVAL) 516 return sys_read(td, (struct read_args *)uap); 517 else 518 return error; 519 } 520 if ((fp->f_flag & FREAD) == 0) { 521 fdrop(fp, td); 522 return (EBADF); 523 } 524 vp = fp->f_vnode; 525 if (vp->v_type != VDIR) { 526 fdrop(fp, td); 527 return sys_read(td, (struct read_args *)uap); 528 } 529 530 off = fp->f_offset; 531 532 DPRINTF(("ibcs2_read: read directory\n")); 533 534 buflen = max(DIRBLKSIZ, uap->nbytes); 535 buflen = min(buflen, MAXBSIZE); 536 buf = malloc(buflen, M_TEMP, M_WAITOK); 537 vn_lock(vp, LK_SHARED | LK_RETRY); 538again: 539 aiov.iov_base = buf; 540 aiov.iov_len = buflen; 541 auio.uio_iov = &aiov; 542 auio.uio_iovcnt = 1; 543 auio.uio_rw = UIO_READ; 544 auio.uio_segflg = UIO_SYSSPACE; 545 auio.uio_td = td; 546 auio.uio_resid = buflen; 547 auio.uio_offset = off; 548 549 if (cookies) { 550 free(cookies, M_TEMP); 551 cookies = NULL; 552 } 553 554#ifdef MAC 555 error = mac_vnode_check_readdir(td->td_ucred, vp); 556 if (error) 557 goto out; 558#endif 559 560 /* 561 * First we read into the malloc'ed buffer, then 562 * we massage it into user space, one record at a time. 563 */ 564 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) { 565 DPRINTF(("VOP_READDIR failed: %d\n", error)); 566 goto out; 567 } 568 inp = buf; 569 outp = uap->buf; 570 resid = uap->nbytes; 571 if ((len = buflen - auio.uio_resid) <= 0) 572 goto eof; 573 574 cookiep = cookies; 575 576 if (cookies) { 577 /* 578 * When using cookies, the vfs has the option of reading from 579 * a different offset than that supplied (UFS truncates the 580 * offset to a block boundary to make sure that it never reads 581 * partway through a directory entry, even if the directory 582 * has been compacted). 583 */ 584 while (len > 0 && ncookies > 0 && *cookiep <= off) { 585 len -= BSD_DIRENT(inp)->d_reclen; 586 inp += BSD_DIRENT(inp)->d_reclen; 587 cookiep++; 588 ncookies--; 589 } 590 } 591 592 for (; len > 0 && resid > 0; len -= reclen) { 593 if (cookiep && ncookies == 0) 594 break; 595 reclen = BSD_DIRENT(inp)->d_reclen; 596 if (reclen & 3) { 597 printf("ibcs2_read: reclen=%d\n", reclen); 598 error = EFAULT; 599 goto out; 600 } 601 if (BSD_DIRENT(inp)->d_fileno == 0) { 602 inp += reclen; /* it is a hole; squish it out */ 603 if (cookiep) { 604 off = *cookiep++; 605 ncookies--; 606 } else 607 off += reclen; 608 continue; 609 } 610 if (reclen > len || resid < sizeof(struct ibcs2_direct)) { 611 /* entry too big for buffer, so just stop */ 612 outp++; 613 break; 614 } 615 /* 616 * Massage in place to make an iBCS2-shaped dirent (otherwise 617 * we have to worry about touching user memory outside of 618 * the copyout() call). 619 * 620 * TODO: if length(filename) > 14, then break filename into 621 * multiple entries and set inode = 0xffff except last 622 */ 623 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe : 624 BSD_DIRENT(inp)->d_fileno; 625 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size); 626 bzero(idb.name + size, 14 - size); 627 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0) 628 goto out; 629 /* advance past this real entry */ 630 if (cookiep) { 631 off = *cookiep++; 632 ncookies--; 633 } else 634 off += reclen; 635 inp += reclen; 636 /* advance output past iBCS2-shaped entry */ 637 outp += sizeof(struct ibcs2_direct); 638 resid -= sizeof(struct ibcs2_direct); 639 } 640 /* if we squished out the whole block, try again */ 641 if (outp == uap->buf) 642 goto again; 643 fp->f_offset = off; /* update the vnode offset */ 644eof: 645 td->td_retval[0] = uap->nbytes - resid; 646out: 647 VOP_UNLOCK(vp, 0); 648 fdrop(fp, td); 649 if (cookies) 650 free(cookies, M_TEMP); 651 free(buf, M_TEMP); 652 return (error); 653} 654 655int 656ibcs2_mknod(td, uap) 657 struct thread *td; 658 struct ibcs2_mknod_args *uap; 659{ 660 char *path; 661 int error; 662 663 CHECKALTCREAT(td, uap->path, &path); 664 if (S_ISFIFO(uap->mode)) 665 error = kern_mkfifo(td, path, UIO_SYSSPACE, uap->mode); 666 else 667 error = kern_mknod(td, path, UIO_SYSSPACE, uap->mode, uap->dev); 668 free(path, M_TEMP); 669 return (error); 670} 671 672int 673ibcs2_getgroups(td, uap) 674 struct thread *td; 675 struct ibcs2_getgroups_args *uap; 676{ 677 ibcs2_gid_t *iset; 678 gid_t *gp; 679 u_int i, ngrp; 680 int error; 681 682 if (uap->gidsetsize < td->td_ucred->cr_ngroups) { 683 if (uap->gidsetsize == 0) 684 ngrp = 0; 685 else 686 return (EINVAL); 687 } else 688 ngrp = td->td_ucred->cr_ngroups; 689 gp = malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK); 690 error = kern_getgroups(td, &ngrp, gp); 691 if (error) 692 goto out; 693 if (uap->gidsetsize > 0) { 694 iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK); 695 for (i = 0; i < ngrp; i++) 696 iset[i] = (ibcs2_gid_t)gp[i]; 697 error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t)); 698 free(iset, M_TEMP); 699 } 700 if (error == 0) 701 td->td_retval[0] = ngrp; 702out: 703 free(gp, M_TEMP); 704 return (error); 705} 706 707int 708ibcs2_setgroups(td, uap) 709 struct thread *td; 710 struct ibcs2_setgroups_args *uap; 711{ 712 ibcs2_gid_t *iset; 713 gid_t *gp; 714 int error, i; 715 716 if (uap->gidsetsize < 0 || uap->gidsetsize > ngroups_max + 1) 717 return (EINVAL); 718 if (uap->gidsetsize && uap->gidset == NULL) 719 return (EINVAL); 720 gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK); 721 if (uap->gidsetsize) { 722 iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK); 723 error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * 724 uap->gidsetsize); 725 if (error) { 726 free(iset, M_TEMP); 727 goto out; 728 } 729 for (i = 0; i < uap->gidsetsize; i++) 730 gp[i] = (gid_t)iset[i]; 731 } 732 733 error = kern_setgroups(td, uap->gidsetsize, gp); 734out: 735 free(gp, M_TEMP); 736 return (error); 737} 738 739int 740ibcs2_setuid(td, uap) 741 struct thread *td; 742 struct ibcs2_setuid_args *uap; 743{ 744 struct setuid_args sa; 745 746 sa.uid = (uid_t)uap->uid; 747 return sys_setuid(td, &sa); 748} 749 750int 751ibcs2_setgid(td, uap) 752 struct thread *td; 753 struct ibcs2_setgid_args *uap; 754{ 755 struct setgid_args sa; 756 757 sa.gid = (gid_t)uap->gid; 758 return sys_setgid(td, &sa); 759} 760 761int 762ibcs2_time(td, uap) 763 struct thread *td; 764 struct ibcs2_time_args *uap; 765{ 766 struct timeval tv; 767 768 microtime(&tv); 769 td->td_retval[0] = tv.tv_sec; 770 if (uap->tp) 771 return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp, 772 sizeof(ibcs2_time_t)); 773 else 774 return 0; 775} 776 777int 778ibcs2_pathconf(td, uap) 779 struct thread *td; 780 struct ibcs2_pathconf_args *uap; 781{ 782 char *path; 783 int error; 784 785 CHECKALTEXIST(td, uap->path, &path); 786 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 787 error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name, FOLLOW); 788 free(path, M_TEMP); 789 return (error); 790} 791 792int 793ibcs2_fpathconf(td, uap) 794 struct thread *td; 795 struct ibcs2_fpathconf_args *uap; 796{ 797 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 798 return sys_fpathconf(td, (struct fpathconf_args *)uap); 799} 800 801int 802ibcs2_sysconf(td, uap) 803 struct thread *td; 804 struct ibcs2_sysconf_args *uap; 805{ 806 int mib[2], value, len, error; 807 struct proc *p; 808 809 p = td->td_proc; 810 switch(uap->name) { 811 case IBCS2_SC_ARG_MAX: 812 mib[1] = KERN_ARGMAX; 813 break; 814 815 case IBCS2_SC_CHILD_MAX: 816 PROC_LOCK(p); 817 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); 818 PROC_UNLOCK(p); 819 return 0; 820 821 case IBCS2_SC_CLK_TCK: 822 td->td_retval[0] = hz; 823 return 0; 824 825 case IBCS2_SC_NGROUPS_MAX: 826 mib[1] = KERN_NGROUPS; 827 break; 828 829 case IBCS2_SC_OPEN_MAX: 830 PROC_LOCK(p); 831 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); 832 PROC_UNLOCK(p); 833 return 0; 834 835 case IBCS2_SC_JOB_CONTROL: 836 mib[1] = KERN_JOB_CONTROL; 837 break; 838 839 case IBCS2_SC_SAVED_IDS: 840 mib[1] = KERN_SAVED_IDS; 841 break; 842 843 case IBCS2_SC_VERSION: 844 mib[1] = KERN_POSIX1; 845 break; 846 847 case IBCS2_SC_PASS_MAX: 848 td->td_retval[0] = 128; /* XXX - should we create PASS_MAX ? */ 849 return 0; 850 851 case IBCS2_SC_XOPEN_VERSION: 852 td->td_retval[0] = 2; /* XXX: What should that be? */ 853 return 0; 854 855 default: 856 return EINVAL; 857 } 858 859 mib[0] = CTL_KERN; 860 len = sizeof(value); 861 error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0); 862 if (error) 863 return error; 864 td->td_retval[0] = value; 865 return 0; 866} 867 868int 869ibcs2_alarm(td, uap) 870 struct thread *td; 871 struct ibcs2_alarm_args *uap; 872{ 873 struct itimerval itv, oitv; 874 int error; 875 876 timevalclear(&itv.it_interval); 877 itv.it_value.tv_sec = uap->sec; 878 itv.it_value.tv_usec = 0; 879 error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv); 880 if (error) 881 return (error); 882 if (oitv.it_value.tv_usec != 0) 883 oitv.it_value.tv_sec++; 884 td->td_retval[0] = oitv.it_value.tv_sec; 885 return (0); 886} 887 888int 889ibcs2_times(td, uap) 890 struct thread *td; 891 struct ibcs2_times_args *uap; 892{ 893 struct rusage ru; 894 struct timeval t; 895 struct tms tms; 896 int error; 897 898#define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz)) 899 900 error = kern_getrusage(td, RUSAGE_SELF, &ru); 901 if (error) 902 return (error); 903 tms.tms_utime = CONVTCK(ru.ru_utime); 904 tms.tms_stime = CONVTCK(ru.ru_stime); 905 906 error = kern_getrusage(td, RUSAGE_CHILDREN, &ru); 907 if (error) 908 return (error); 909 tms.tms_cutime = CONVTCK(ru.ru_utime); 910 tms.tms_cstime = CONVTCK(ru.ru_stime); 911 912 microtime(&t); 913 td->td_retval[0] = CONVTCK(t); 914 915 return (copyout(&tms, uap->tp, sizeof(struct tms))); 916} 917 918int 919ibcs2_stime(td, uap) 920 struct thread *td; 921 struct ibcs2_stime_args *uap; 922{ 923 struct timeval tv; 924 long secs; 925 int error; 926 927 error = copyin(uap->timep, &secs, sizeof(long)); 928 if (error) 929 return (error); 930 tv.tv_sec = secs; 931 tv.tv_usec = 0; 932 error = kern_settimeofday(td, &tv, NULL); 933 if (error) 934 error = EPERM; 935 return (error); 936} 937 938int 939ibcs2_utime(td, uap) 940 struct thread *td; 941 struct ibcs2_utime_args *uap; 942{ 943 struct ibcs2_utimbuf ubuf; 944 struct timeval tbuf[2], *tp; 945 char *path; 946 int error; 947 948 if (uap->buf) { 949 error = copyin(uap->buf, &ubuf, sizeof(ubuf)); 950 if (error) 951 return (error); 952 tbuf[0].tv_sec = ubuf.actime; 953 tbuf[0].tv_usec = 0; 954 tbuf[1].tv_sec = ubuf.modtime; 955 tbuf[1].tv_usec = 0; 956 tp = tbuf; 957 } else 958 tp = NULL; 959 960 CHECKALTEXIST(td, uap->path, &path); 961 error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE); 962 free(path, M_TEMP); 963 return (error); 964} 965 966int 967ibcs2_nice(td, uap) 968 struct thread *td; 969 struct ibcs2_nice_args *uap; 970{ 971 int error; 972 struct setpriority_args sa; 973 974 sa.which = PRIO_PROCESS; 975 sa.who = 0; 976 sa.prio = td->td_proc->p_nice + uap->incr; 977 if ((error = sys_setpriority(td, &sa)) != 0) 978 return EPERM; 979 td->td_retval[0] = td->td_proc->p_nice; 980 return 0; 981} 982 983/* 984 * iBCS2 getpgrp, setpgrp, setsid, and setpgid 985 */ 986 987int 988ibcs2_pgrpsys(td, uap) 989 struct thread *td; 990 struct ibcs2_pgrpsys_args *uap; 991{ 992 struct proc *p = td->td_proc; 993 switch (uap->type) { 994 case 0: /* getpgrp */ 995 PROC_LOCK(p); 996 td->td_retval[0] = p->p_pgrp->pg_id; 997 PROC_UNLOCK(p); 998 return 0; 999 1000 case 1: /* setpgrp */ 1001 { 1002 struct setpgid_args sa; 1003 1004 sa.pid = 0; 1005 sa.pgid = 0; 1006 sys_setpgid(td, &sa); 1007 PROC_LOCK(p); 1008 td->td_retval[0] = p->p_pgrp->pg_id; 1009 PROC_UNLOCK(p); 1010 return 0; 1011 } 1012 1013 case 2: /* setpgid */ 1014 { 1015 struct setpgid_args sa; 1016 1017 sa.pid = uap->pid; 1018 sa.pgid = uap->pgid; 1019 return sys_setpgid(td, &sa); 1020 } 1021 1022 case 3: /* setsid */ 1023 return sys_setsid(td, NULL); 1024 1025 default: 1026 return EINVAL; 1027 } 1028} 1029 1030/* 1031 * XXX - need to check for nested calls 1032 */ 1033 1034int 1035ibcs2_plock(td, uap) 1036 struct thread *td; 1037 struct ibcs2_plock_args *uap; 1038{ 1039 int error; 1040#define IBCS2_UNLOCK 0 1041#define IBCS2_PROCLOCK 1 1042#define IBCS2_TEXTLOCK 2 1043#define IBCS2_DATALOCK 4 1044 1045 1046 switch(uap->cmd) { 1047 case IBCS2_UNLOCK: 1048 error = priv_check(td, PRIV_VM_MUNLOCK); 1049 if (error) 1050 return (error); 1051 /* XXX - TODO */ 1052 return (0); 1053 1054 case IBCS2_PROCLOCK: 1055 case IBCS2_TEXTLOCK: 1056 case IBCS2_DATALOCK: 1057 error = priv_check(td, PRIV_VM_MLOCK); 1058 if (error) 1059 return (error); 1060 /* XXX - TODO */ 1061 return 0; 1062 } 1063 return EINVAL; 1064} 1065 1066int 1067ibcs2_uadmin(td, uap) 1068 struct thread *td; 1069 struct ibcs2_uadmin_args *uap; 1070{ 1071#define SCO_A_REBOOT 1 1072#define SCO_A_SHUTDOWN 2 1073#define SCO_A_REMOUNT 4 1074#define SCO_A_CLOCK 8 1075#define SCO_A_SETCONFIG 128 1076#define SCO_A_GETDEV 130 1077 1078#define SCO_AD_HALT 0 1079#define SCO_AD_BOOT 1 1080#define SCO_AD_IBOOT 2 1081#define SCO_AD_PWRDOWN 3 1082#define SCO_AD_PWRNAP 4 1083 1084#define SCO_AD_PANICBOOT 1 1085 1086#define SCO_AD_GETBMAJ 0 1087#define SCO_AD_GETCMAJ 1 1088 1089 switch(uap->cmd) { 1090 case SCO_A_REBOOT: 1091 case SCO_A_SHUTDOWN: 1092 switch(uap->func) { 1093 struct reboot_args r; 1094 case SCO_AD_HALT: 1095 case SCO_AD_PWRDOWN: 1096 case SCO_AD_PWRNAP: 1097 r.opt = RB_HALT; 1098 return (sys_reboot(td, &r)); 1099 case SCO_AD_BOOT: 1100 case SCO_AD_IBOOT: 1101 r.opt = RB_AUTOBOOT; 1102 return (sys_reboot(td, &r)); 1103 } 1104 return EINVAL; 1105 case SCO_A_REMOUNT: 1106 case SCO_A_CLOCK: 1107 case SCO_A_SETCONFIG: 1108 return 0; 1109 case SCO_A_GETDEV: 1110 return EINVAL; /* XXX - TODO */ 1111 } 1112 return EINVAL; 1113} 1114 1115int 1116ibcs2_sysfs(td, uap) 1117 struct thread *td; 1118 struct ibcs2_sysfs_args *uap; 1119{ 1120#define IBCS2_GETFSIND 1 1121#define IBCS2_GETFSTYP 2 1122#define IBCS2_GETNFSTYP 3 1123 1124 switch(uap->cmd) { 1125 case IBCS2_GETFSIND: 1126 case IBCS2_GETFSTYP: 1127 case IBCS2_GETNFSTYP: 1128 break; 1129 } 1130 return EINVAL; /* XXX - TODO */ 1131} 1132 1133int 1134ibcs2_unlink(td, uap) 1135 struct thread *td; 1136 struct ibcs2_unlink_args *uap; 1137{ 1138 char *path; 1139 int error; 1140 1141 CHECKALTEXIST(td, uap->path, &path); 1142 error = kern_unlink(td, path, UIO_SYSSPACE); 1143 free(path, M_TEMP); 1144 return (error); 1145} 1146 1147int 1148ibcs2_chdir(td, uap) 1149 struct thread *td; 1150 struct ibcs2_chdir_args *uap; 1151{ 1152 char *path; 1153 int error; 1154 1155 CHECKALTEXIST(td, uap->path, &path); 1156 error = kern_chdir(td, path, UIO_SYSSPACE); 1157 free(path, M_TEMP); 1158 return (error); 1159} 1160 1161int 1162ibcs2_chmod(td, uap) 1163 struct thread *td; 1164 struct ibcs2_chmod_args *uap; 1165{ 1166 char *path; 1167 int error; 1168 1169 CHECKALTEXIST(td, uap->path, &path); 1170 error = kern_chmod(td, path, UIO_SYSSPACE, uap->mode); 1171 free(path, M_TEMP); 1172 return (error); 1173} 1174 1175int 1176ibcs2_chown(td, uap) 1177 struct thread *td; 1178 struct ibcs2_chown_args *uap; 1179{ 1180 char *path; 1181 int error; 1182 1183 CHECKALTEXIST(td, uap->path, &path); 1184 error = kern_chown(td, path, UIO_SYSSPACE, uap->uid, uap->gid); 1185 free(path, M_TEMP); 1186 return (error); 1187} 1188 1189int 1190ibcs2_rmdir(td, uap) 1191 struct thread *td; 1192 struct ibcs2_rmdir_args *uap; 1193{ 1194 char *path; 1195 int error; 1196 1197 CHECKALTEXIST(td, uap->path, &path); 1198 error = kern_rmdir(td, path, UIO_SYSSPACE); 1199 free(path, M_TEMP); 1200 return (error); 1201} 1202 1203int 1204ibcs2_mkdir(td, uap) 1205 struct thread *td; 1206 struct ibcs2_mkdir_args *uap; 1207{ 1208 char *path; 1209 int error; 1210 1211 CHECKALTEXIST(td, uap->path, &path); 1212 error = kern_mkdir(td, path, UIO_SYSSPACE, uap->mode); 1213 free(path, M_TEMP); 1214 return (error); 1215} 1216 1217int 1218ibcs2_symlink(td, uap) 1219 struct thread *td; 1220 struct ibcs2_symlink_args *uap; 1221{ 1222 char *path, *link; 1223 int error; 1224 1225 CHECKALTEXIST(td, uap->path, &path); 1226 1227 /* 1228 * Have to expand CHECKALTCREAT() so that 'path' can be freed on 1229 * errors. 1230 */ 1231 error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1); 1232 if (link == NULL) { 1233 free(path, M_TEMP); 1234 return (error); 1235 } 1236 error = kern_symlink(td, path, link, UIO_SYSSPACE); 1237 free(path, M_TEMP); 1238 free(link, M_TEMP); 1239 return (error); 1240} 1241 1242int 1243ibcs2_rename(td, uap) 1244 struct thread *td; 1245 struct ibcs2_rename_args *uap; 1246{ 1247 char *from, *to; 1248 int error; 1249 1250 CHECKALTEXIST(td, uap->from, &from); 1251 1252 /* 1253 * Have to expand CHECKALTCREAT() so that 'from' can be freed on 1254 * errors. 1255 */ 1256 error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1); 1257 if (to == NULL) { 1258 free(from, M_TEMP); 1259 return (error); 1260 } 1261 error = kern_rename(td, from, to, UIO_SYSSPACE); 1262 free(from, M_TEMP); 1263 free(to, M_TEMP); 1264 return (error); 1265} 1266 1267int 1268ibcs2_readlink(td, uap) 1269 struct thread *td; 1270 struct ibcs2_readlink_args *uap; 1271{ 1272 char *path; 1273 int error; 1274 1275 CHECKALTEXIST(td, uap->path, &path); 1276 error = kern_readlink(td, path, UIO_SYSSPACE, uap->buf, UIO_USERSPACE, 1277 uap->count); 1278 free(path, M_TEMP); 1279 return (error); 1280} 1281