ibcs2_misc.c revision 283359
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 283359 2015-05-24 07:32:02Z kib $"); 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 error = getvnode(td->td_proc->p_fd, uap->fd, 356 cap_rights_init(&rights, CAP_READ), &fp); 357 if (error != 0) 358 return (error); 359 if ((fp->f_flag & FREAD) == 0) { 360 fdrop(fp, td); 361 return (EBADF); 362 } 363 vp = fp->f_vnode; 364 if (vp->v_type != VDIR) { /* XXX vnode readdir op should do this */ 365 fdrop(fp, td); 366 return (EINVAL); 367 } 368 369 off = fp->f_offset; 370#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 371 buflen = max(DIRBLKSIZ, uap->nbytes); 372 buflen = min(buflen, MAXBSIZE); 373 buf = malloc(buflen, M_TEMP, M_WAITOK); 374 vn_lock(vp, LK_SHARED | LK_RETRY); 375again: 376 aiov.iov_base = buf; 377 aiov.iov_len = buflen; 378 auio.uio_iov = &aiov; 379 auio.uio_iovcnt = 1; 380 auio.uio_rw = UIO_READ; 381 auio.uio_segflg = UIO_SYSSPACE; 382 auio.uio_td = td; 383 auio.uio_resid = buflen; 384 auio.uio_offset = off; 385 386 if (cookies) { 387 free(cookies, M_TEMP); 388 cookies = NULL; 389 } 390 391#ifdef MAC 392 error = mac_vnode_check_readdir(td->td_ucred, vp); 393 if (error) 394 goto out; 395#endif 396 397 /* 398 * First we read into the malloc'ed buffer, then 399 * we massage it into user space, one record at a time. 400 */ 401 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) 402 goto out; 403 inp = buf; 404 outp = uap->buf; 405 resid = uap->nbytes; 406 if ((len = buflen - auio.uio_resid) <= 0) 407 goto eof; 408 409 cookiep = cookies; 410 411 if (cookies) { 412 /* 413 * When using cookies, the vfs has the option of reading from 414 * a different offset than that supplied (UFS truncates the 415 * offset to a block boundary to make sure that it never reads 416 * partway through a directory entry, even if the directory 417 * has been compacted). 418 */ 419 while (len > 0 && ncookies > 0 && *cookiep <= off) { 420 len -= BSD_DIRENT(inp)->d_reclen; 421 inp += BSD_DIRENT(inp)->d_reclen; 422 cookiep++; 423 ncookies--; 424 } 425 } 426 427 for (; len > 0; len -= reclen) { 428 if (cookiep && ncookies == 0) 429 break; 430 reclen = BSD_DIRENT(inp)->d_reclen; 431 if (reclen & 3) { 432 printf("ibcs2_getdents: reclen=%d\n", reclen); 433 error = EFAULT; 434 goto out; 435 } 436 if (BSD_DIRENT(inp)->d_fileno == 0) { 437 inp += reclen; /* it is a hole; squish it out */ 438 if (cookiep) { 439 off = *cookiep++; 440 ncookies--; 441 } else 442 off += reclen; 443 continue; 444 } 445 if (reclen > len || resid < IBCS2_RECLEN(reclen)) { 446 /* entry too big for buffer, so just stop */ 447 outp++; 448 break; 449 } 450 /* 451 * Massage in place to make an iBCS2-shaped dirent (otherwise 452 * we have to worry about touching user memory outside of 453 * the copyout() call). 454 */ 455 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno; 456 idb.d_off = (ibcs2_off_t)off; 457 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen); 458 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 || 459 (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10, 460 BSD_DIRENT(inp)->d_namlen + 1)) != 0) 461 goto out; 462 /* advance past this real entry */ 463 if (cookiep) { 464 off = *cookiep++; 465 ncookies--; 466 } else 467 off += reclen; 468 inp += reclen; 469 /* advance output past iBCS2-shaped entry */ 470 outp += IBCS2_RECLEN(reclen); 471 resid -= IBCS2_RECLEN(reclen); 472 } 473 /* if we squished out the whole block, try again */ 474 if (outp == uap->buf) 475 goto again; 476 fp->f_offset = off; /* update the vnode offset */ 477eof: 478 td->td_retval[0] = uap->nbytes - resid; 479out: 480 VOP_UNLOCK(vp, 0); 481 fdrop(fp, td); 482 if (cookies) 483 free(cookies, M_TEMP); 484 free(buf, M_TEMP); 485 return (error); 486} 487 488int 489ibcs2_read(td, uap) 490 struct thread *td; 491 struct ibcs2_read_args *uap; 492{ 493 register struct vnode *vp; 494 register caddr_t inp, buf; /* BSD-format */ 495 register int len, reclen; /* BSD-format */ 496 register caddr_t outp; /* iBCS2-format */ 497 register int resid; /* iBCS2-format */ 498 cap_rights_t rights; 499 struct file *fp; 500 struct uio auio; 501 struct iovec aiov; 502 struct ibcs2_direct { 503 ibcs2_ino_t ino; 504 char name[14]; 505 } idb; 506 off_t off; /* true file offset */ 507 int buflen, error, eofflag, size; 508 u_long *cookies = NULL, *cookiep; 509 int ncookies; 510 511 error = getvnode(td->td_proc->p_fd, uap->fd, 512 cap_rights_init(&rights, CAP_READ), &fp); 513 if (error != 0) { 514 if (error == EINVAL) 515 return sys_read(td, (struct read_args *)uap); 516 else 517 return error; 518 } 519 if ((fp->f_flag & FREAD) == 0) { 520 fdrop(fp, td); 521 return (EBADF); 522 } 523 vp = fp->f_vnode; 524 if (vp->v_type != VDIR) { 525 fdrop(fp, td); 526 return sys_read(td, (struct read_args *)uap); 527 } 528 529 off = fp->f_offset; 530 531 DPRINTF(("ibcs2_read: read directory\n")); 532 533 buflen = max(DIRBLKSIZ, uap->nbytes); 534 buflen = min(buflen, MAXBSIZE); 535 buf = malloc(buflen, M_TEMP, M_WAITOK); 536 vn_lock(vp, LK_SHARED | LK_RETRY); 537again: 538 aiov.iov_base = buf; 539 aiov.iov_len = buflen; 540 auio.uio_iov = &aiov; 541 auio.uio_iovcnt = 1; 542 auio.uio_rw = UIO_READ; 543 auio.uio_segflg = UIO_SYSSPACE; 544 auio.uio_td = td; 545 auio.uio_resid = buflen; 546 auio.uio_offset = off; 547 548 if (cookies) { 549 free(cookies, M_TEMP); 550 cookies = NULL; 551 } 552 553#ifdef MAC 554 error = mac_vnode_check_readdir(td->td_ucred, vp); 555 if (error) 556 goto out; 557#endif 558 559 /* 560 * First we read into the malloc'ed buffer, then 561 * we massage it into user space, one record at a time. 562 */ 563 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) { 564 DPRINTF(("VOP_READDIR failed: %d\n", error)); 565 goto out; 566 } 567 inp = buf; 568 outp = uap->buf; 569 resid = uap->nbytes; 570 if ((len = buflen - auio.uio_resid) <= 0) 571 goto eof; 572 573 cookiep = cookies; 574 575 if (cookies) { 576 /* 577 * When using cookies, the vfs has the option of reading from 578 * a different offset than that supplied (UFS truncates the 579 * offset to a block boundary to make sure that it never reads 580 * partway through a directory entry, even if the directory 581 * has been compacted). 582 */ 583 while (len > 0 && ncookies > 0 && *cookiep <= off) { 584 len -= BSD_DIRENT(inp)->d_reclen; 585 inp += BSD_DIRENT(inp)->d_reclen; 586 cookiep++; 587 ncookies--; 588 } 589 } 590 591 for (; len > 0 && resid > 0; len -= reclen) { 592 if (cookiep && ncookies == 0) 593 break; 594 reclen = BSD_DIRENT(inp)->d_reclen; 595 if (reclen & 3) { 596 printf("ibcs2_read: reclen=%d\n", reclen); 597 error = EFAULT; 598 goto out; 599 } 600 if (BSD_DIRENT(inp)->d_fileno == 0) { 601 inp += reclen; /* it is a hole; squish it out */ 602 if (cookiep) { 603 off = *cookiep++; 604 ncookies--; 605 } else 606 off += reclen; 607 continue; 608 } 609 if (reclen > len || resid < sizeof(struct ibcs2_direct)) { 610 /* entry too big for buffer, so just stop */ 611 outp++; 612 break; 613 } 614 /* 615 * Massage in place to make an iBCS2-shaped dirent (otherwise 616 * we have to worry about touching user memory outside of 617 * the copyout() call). 618 * 619 * TODO: if length(filename) > 14, then break filename into 620 * multiple entries and set inode = 0xffff except last 621 */ 622 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe : 623 BSD_DIRENT(inp)->d_fileno; 624 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size); 625 bzero(idb.name + size, 14 - size); 626 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0) 627 goto out; 628 /* advance past this real entry */ 629 if (cookiep) { 630 off = *cookiep++; 631 ncookies--; 632 } else 633 off += reclen; 634 inp += reclen; 635 /* advance output past iBCS2-shaped entry */ 636 outp += sizeof(struct ibcs2_direct); 637 resid -= sizeof(struct ibcs2_direct); 638 } 639 /* if we squished out the whole block, try again */ 640 if (outp == uap->buf) 641 goto again; 642 fp->f_offset = off; /* update the vnode offset */ 643eof: 644 td->td_retval[0] = uap->nbytes - resid; 645out: 646 VOP_UNLOCK(vp, 0); 647 fdrop(fp, td); 648 if (cookies) 649 free(cookies, M_TEMP); 650 free(buf, M_TEMP); 651 return (error); 652} 653 654int 655ibcs2_mknod(td, uap) 656 struct thread *td; 657 struct ibcs2_mknod_args *uap; 658{ 659 char *path; 660 int error; 661 662 CHECKALTCREAT(td, uap->path, &path); 663 if (S_ISFIFO(uap->mode)) 664 error = kern_mkfifo(td, path, UIO_SYSSPACE, uap->mode); 665 else 666 error = kern_mknod(td, path, UIO_SYSSPACE, uap->mode, uap->dev); 667 free(path, M_TEMP); 668 return (error); 669} 670 671int 672ibcs2_getgroups(td, uap) 673 struct thread *td; 674 struct ibcs2_getgroups_args *uap; 675{ 676 ibcs2_gid_t *iset; 677 gid_t *gp; 678 u_int i, ngrp; 679 int error; 680 681 if (uap->gidsetsize < td->td_ucred->cr_ngroups) { 682 if (uap->gidsetsize == 0) 683 ngrp = 0; 684 else 685 return (EINVAL); 686 } else 687 ngrp = td->td_ucred->cr_ngroups; 688 gp = malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK); 689 error = kern_getgroups(td, &ngrp, gp); 690 if (error) 691 goto out; 692 if (uap->gidsetsize > 0) { 693 iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK); 694 for (i = 0; i < ngrp; i++) 695 iset[i] = (ibcs2_gid_t)gp[i]; 696 error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t)); 697 free(iset, M_TEMP); 698 } 699 if (error == 0) 700 td->td_retval[0] = ngrp; 701out: 702 free(gp, M_TEMP); 703 return (error); 704} 705 706int 707ibcs2_setgroups(td, uap) 708 struct thread *td; 709 struct ibcs2_setgroups_args *uap; 710{ 711 ibcs2_gid_t *iset; 712 gid_t *gp; 713 int error, i; 714 715 if (uap->gidsetsize < 0 || uap->gidsetsize > ngroups_max + 1) 716 return (EINVAL); 717 if (uap->gidsetsize && uap->gidset == NULL) 718 return (EINVAL); 719 gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK); 720 if (uap->gidsetsize) { 721 iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK); 722 error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * 723 uap->gidsetsize); 724 if (error) { 725 free(iset, M_TEMP); 726 goto out; 727 } 728 for (i = 0; i < uap->gidsetsize; i++) 729 gp[i] = (gid_t)iset[i]; 730 } 731 732 error = kern_setgroups(td, uap->gidsetsize, gp); 733out: 734 free(gp, M_TEMP); 735 return (error); 736} 737 738int 739ibcs2_setuid(td, uap) 740 struct thread *td; 741 struct ibcs2_setuid_args *uap; 742{ 743 struct setuid_args sa; 744 745 sa.uid = (uid_t)uap->uid; 746 return sys_setuid(td, &sa); 747} 748 749int 750ibcs2_setgid(td, uap) 751 struct thread *td; 752 struct ibcs2_setgid_args *uap; 753{ 754 struct setgid_args sa; 755 756 sa.gid = (gid_t)uap->gid; 757 return sys_setgid(td, &sa); 758} 759 760int 761ibcs2_time(td, uap) 762 struct thread *td; 763 struct ibcs2_time_args *uap; 764{ 765 struct timeval tv; 766 767 microtime(&tv); 768 td->td_retval[0] = tv.tv_sec; 769 if (uap->tp) 770 return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp, 771 sizeof(ibcs2_time_t)); 772 else 773 return 0; 774} 775 776int 777ibcs2_pathconf(td, uap) 778 struct thread *td; 779 struct ibcs2_pathconf_args *uap; 780{ 781 char *path; 782 int error; 783 784 CHECKALTEXIST(td, uap->path, &path); 785 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 786 error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name, FOLLOW); 787 free(path, M_TEMP); 788 return (error); 789} 790 791int 792ibcs2_fpathconf(td, uap) 793 struct thread *td; 794 struct ibcs2_fpathconf_args *uap; 795{ 796 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 797 return sys_fpathconf(td, (struct fpathconf_args *)uap); 798} 799 800int 801ibcs2_sysconf(td, uap) 802 struct thread *td; 803 struct ibcs2_sysconf_args *uap; 804{ 805 int mib[2], value, len, error; 806 struct proc *p; 807 808 p = td->td_proc; 809 switch(uap->name) { 810 case IBCS2_SC_ARG_MAX: 811 mib[1] = KERN_ARGMAX; 812 break; 813 814 case IBCS2_SC_CHILD_MAX: 815 PROC_LOCK(p); 816 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); 817 PROC_UNLOCK(p); 818 return 0; 819 820 case IBCS2_SC_CLK_TCK: 821 td->td_retval[0] = hz; 822 return 0; 823 824 case IBCS2_SC_NGROUPS_MAX: 825 mib[1] = KERN_NGROUPS; 826 break; 827 828 case IBCS2_SC_OPEN_MAX: 829 PROC_LOCK(p); 830 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); 831 PROC_UNLOCK(p); 832 return 0; 833 834 case IBCS2_SC_JOB_CONTROL: 835 mib[1] = KERN_JOB_CONTROL; 836 break; 837 838 case IBCS2_SC_SAVED_IDS: 839 mib[1] = KERN_SAVED_IDS; 840 break; 841 842 case IBCS2_SC_VERSION: 843 mib[1] = KERN_POSIX1; 844 break; 845 846 case IBCS2_SC_PASS_MAX: 847 td->td_retval[0] = 128; /* XXX - should we create PASS_MAX ? */ 848 return 0; 849 850 case IBCS2_SC_XOPEN_VERSION: 851 td->td_retval[0] = 2; /* XXX: What should that be? */ 852 return 0; 853 854 default: 855 return EINVAL; 856 } 857 858 mib[0] = CTL_KERN; 859 len = sizeof(value); 860 error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0); 861 if (error) 862 return error; 863 td->td_retval[0] = value; 864 return 0; 865} 866 867int 868ibcs2_alarm(td, uap) 869 struct thread *td; 870 struct ibcs2_alarm_args *uap; 871{ 872 struct itimerval itv, oitv; 873 int error; 874 875 timevalclear(&itv.it_interval); 876 itv.it_value.tv_sec = uap->sec; 877 itv.it_value.tv_usec = 0; 878 error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv); 879 if (error) 880 return (error); 881 if (oitv.it_value.tv_usec != 0) 882 oitv.it_value.tv_sec++; 883 td->td_retval[0] = oitv.it_value.tv_sec; 884 return (0); 885} 886 887int 888ibcs2_times(td, uap) 889 struct thread *td; 890 struct ibcs2_times_args *uap; 891{ 892 struct rusage ru; 893 struct timeval t; 894 struct tms tms; 895 int error; 896 897#define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz)) 898 899 error = kern_getrusage(td, RUSAGE_SELF, &ru); 900 if (error) 901 return (error); 902 tms.tms_utime = CONVTCK(ru.ru_utime); 903 tms.tms_stime = CONVTCK(ru.ru_stime); 904 905 error = kern_getrusage(td, RUSAGE_CHILDREN, &ru); 906 if (error) 907 return (error); 908 tms.tms_cutime = CONVTCK(ru.ru_utime); 909 tms.tms_cstime = CONVTCK(ru.ru_stime); 910 911 microtime(&t); 912 td->td_retval[0] = CONVTCK(t); 913 914 return (copyout(&tms, uap->tp, sizeof(struct tms))); 915} 916 917int 918ibcs2_stime(td, uap) 919 struct thread *td; 920 struct ibcs2_stime_args *uap; 921{ 922 struct timeval tv; 923 long secs; 924 int error; 925 926 error = copyin(uap->timep, &secs, sizeof(long)); 927 if (error) 928 return (error); 929 tv.tv_sec = secs; 930 tv.tv_usec = 0; 931 error = kern_settimeofday(td, &tv, NULL); 932 if (error) 933 error = EPERM; 934 return (error); 935} 936 937int 938ibcs2_utime(td, uap) 939 struct thread *td; 940 struct ibcs2_utime_args *uap; 941{ 942 struct ibcs2_utimbuf ubuf; 943 struct timeval tbuf[2], *tp; 944 char *path; 945 int error; 946 947 if (uap->buf) { 948 error = copyin(uap->buf, &ubuf, sizeof(ubuf)); 949 if (error) 950 return (error); 951 tbuf[0].tv_sec = ubuf.actime; 952 tbuf[0].tv_usec = 0; 953 tbuf[1].tv_sec = ubuf.modtime; 954 tbuf[1].tv_usec = 0; 955 tp = tbuf; 956 } else 957 tp = NULL; 958 959 CHECKALTEXIST(td, uap->path, &path); 960 error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE); 961 free(path, M_TEMP); 962 return (error); 963} 964 965int 966ibcs2_nice(td, uap) 967 struct thread *td; 968 struct ibcs2_nice_args *uap; 969{ 970 int error; 971 struct setpriority_args sa; 972 973 sa.which = PRIO_PROCESS; 974 sa.who = 0; 975 sa.prio = td->td_proc->p_nice + uap->incr; 976 if ((error = sys_setpriority(td, &sa)) != 0) 977 return EPERM; 978 td->td_retval[0] = td->td_proc->p_nice; 979 return 0; 980} 981 982/* 983 * iBCS2 getpgrp, setpgrp, setsid, and setpgid 984 */ 985 986int 987ibcs2_pgrpsys(td, uap) 988 struct thread *td; 989 struct ibcs2_pgrpsys_args *uap; 990{ 991 struct proc *p = td->td_proc; 992 switch (uap->type) { 993 case 0: /* getpgrp */ 994 PROC_LOCK(p); 995 td->td_retval[0] = p->p_pgrp->pg_id; 996 PROC_UNLOCK(p); 997 return 0; 998 999 case 1: /* setpgrp */ 1000 { 1001 struct setpgid_args sa; 1002 1003 sa.pid = 0; 1004 sa.pgid = 0; 1005 sys_setpgid(td, &sa); 1006 PROC_LOCK(p); 1007 td->td_retval[0] = p->p_pgrp->pg_id; 1008 PROC_UNLOCK(p); 1009 return 0; 1010 } 1011 1012 case 2: /* setpgid */ 1013 { 1014 struct setpgid_args sa; 1015 1016 sa.pid = uap->pid; 1017 sa.pgid = uap->pgid; 1018 return sys_setpgid(td, &sa); 1019 } 1020 1021 case 3: /* setsid */ 1022 return sys_setsid(td, NULL); 1023 1024 default: 1025 return EINVAL; 1026 } 1027} 1028 1029/* 1030 * XXX - need to check for nested calls 1031 */ 1032 1033int 1034ibcs2_plock(td, uap) 1035 struct thread *td; 1036 struct ibcs2_plock_args *uap; 1037{ 1038 int error; 1039#define IBCS2_UNLOCK 0 1040#define IBCS2_PROCLOCK 1 1041#define IBCS2_TEXTLOCK 2 1042#define IBCS2_DATALOCK 4 1043 1044 1045 switch(uap->cmd) { 1046 case IBCS2_UNLOCK: 1047 error = priv_check(td, PRIV_VM_MUNLOCK); 1048 if (error) 1049 return (error); 1050 /* XXX - TODO */ 1051 return (0); 1052 1053 case IBCS2_PROCLOCK: 1054 case IBCS2_TEXTLOCK: 1055 case IBCS2_DATALOCK: 1056 error = priv_check(td, PRIV_VM_MLOCK); 1057 if (error) 1058 return (error); 1059 /* XXX - TODO */ 1060 return 0; 1061 } 1062 return EINVAL; 1063} 1064 1065int 1066ibcs2_uadmin(td, uap) 1067 struct thread *td; 1068 struct ibcs2_uadmin_args *uap; 1069{ 1070#define SCO_A_REBOOT 1 1071#define SCO_A_SHUTDOWN 2 1072#define SCO_A_REMOUNT 4 1073#define SCO_A_CLOCK 8 1074#define SCO_A_SETCONFIG 128 1075#define SCO_A_GETDEV 130 1076 1077#define SCO_AD_HALT 0 1078#define SCO_AD_BOOT 1 1079#define SCO_AD_IBOOT 2 1080#define SCO_AD_PWRDOWN 3 1081#define SCO_AD_PWRNAP 4 1082 1083#define SCO_AD_PANICBOOT 1 1084 1085#define SCO_AD_GETBMAJ 0 1086#define SCO_AD_GETCMAJ 1 1087 1088 switch(uap->cmd) { 1089 case SCO_A_REBOOT: 1090 case SCO_A_SHUTDOWN: 1091 switch(uap->func) { 1092 struct reboot_args r; 1093 case SCO_AD_HALT: 1094 case SCO_AD_PWRDOWN: 1095 case SCO_AD_PWRNAP: 1096 r.opt = RB_HALT; 1097 return (sys_reboot(td, &r)); 1098 case SCO_AD_BOOT: 1099 case SCO_AD_IBOOT: 1100 r.opt = RB_AUTOBOOT; 1101 return (sys_reboot(td, &r)); 1102 } 1103 return EINVAL; 1104 case SCO_A_REMOUNT: 1105 case SCO_A_CLOCK: 1106 case SCO_A_SETCONFIG: 1107 return 0; 1108 case SCO_A_GETDEV: 1109 return EINVAL; /* XXX - TODO */ 1110 } 1111 return EINVAL; 1112} 1113 1114int 1115ibcs2_sysfs(td, uap) 1116 struct thread *td; 1117 struct ibcs2_sysfs_args *uap; 1118{ 1119#define IBCS2_GETFSIND 1 1120#define IBCS2_GETFSTYP 2 1121#define IBCS2_GETNFSTYP 3 1122 1123 switch(uap->cmd) { 1124 case IBCS2_GETFSIND: 1125 case IBCS2_GETFSTYP: 1126 case IBCS2_GETNFSTYP: 1127 break; 1128 } 1129 return EINVAL; /* XXX - TODO */ 1130} 1131 1132int 1133ibcs2_unlink(td, uap) 1134 struct thread *td; 1135 struct ibcs2_unlink_args *uap; 1136{ 1137 char *path; 1138 int error; 1139 1140 CHECKALTEXIST(td, uap->path, &path); 1141 error = kern_unlink(td, path, UIO_SYSSPACE); 1142 free(path, M_TEMP); 1143 return (error); 1144} 1145 1146int 1147ibcs2_chdir(td, uap) 1148 struct thread *td; 1149 struct ibcs2_chdir_args *uap; 1150{ 1151 char *path; 1152 int error; 1153 1154 CHECKALTEXIST(td, uap->path, &path); 1155 error = kern_chdir(td, path, UIO_SYSSPACE); 1156 free(path, M_TEMP); 1157 return (error); 1158} 1159 1160int 1161ibcs2_chmod(td, uap) 1162 struct thread *td; 1163 struct ibcs2_chmod_args *uap; 1164{ 1165 char *path; 1166 int error; 1167 1168 CHECKALTEXIST(td, uap->path, &path); 1169 error = kern_chmod(td, path, UIO_SYSSPACE, uap->mode); 1170 free(path, M_TEMP); 1171 return (error); 1172} 1173 1174int 1175ibcs2_chown(td, uap) 1176 struct thread *td; 1177 struct ibcs2_chown_args *uap; 1178{ 1179 char *path; 1180 int error; 1181 1182 CHECKALTEXIST(td, uap->path, &path); 1183 error = kern_chown(td, path, UIO_SYSSPACE, uap->uid, uap->gid); 1184 free(path, M_TEMP); 1185 return (error); 1186} 1187 1188int 1189ibcs2_rmdir(td, uap) 1190 struct thread *td; 1191 struct ibcs2_rmdir_args *uap; 1192{ 1193 char *path; 1194 int error; 1195 1196 CHECKALTEXIST(td, uap->path, &path); 1197 error = kern_rmdir(td, path, UIO_SYSSPACE); 1198 free(path, M_TEMP); 1199 return (error); 1200} 1201 1202int 1203ibcs2_mkdir(td, uap) 1204 struct thread *td; 1205 struct ibcs2_mkdir_args *uap; 1206{ 1207 char *path; 1208 int error; 1209 1210 CHECKALTEXIST(td, uap->path, &path); 1211 error = kern_mkdir(td, path, UIO_SYSSPACE, uap->mode); 1212 free(path, M_TEMP); 1213 return (error); 1214} 1215 1216int 1217ibcs2_symlink(td, uap) 1218 struct thread *td; 1219 struct ibcs2_symlink_args *uap; 1220{ 1221 char *path, *link; 1222 int error; 1223 1224 CHECKALTEXIST(td, uap->path, &path); 1225 1226 /* 1227 * Have to expand CHECKALTCREAT() so that 'path' can be freed on 1228 * errors. 1229 */ 1230 error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1); 1231 if (link == NULL) { 1232 free(path, M_TEMP); 1233 return (error); 1234 } 1235 error = kern_symlink(td, path, link, UIO_SYSSPACE); 1236 free(path, M_TEMP); 1237 free(link, M_TEMP); 1238 return (error); 1239} 1240 1241int 1242ibcs2_rename(td, uap) 1243 struct thread *td; 1244 struct ibcs2_rename_args *uap; 1245{ 1246 char *from, *to; 1247 int error; 1248 1249 CHECKALTEXIST(td, uap->from, &from); 1250 1251 /* 1252 * Have to expand CHECKALTCREAT() so that 'from' can be freed on 1253 * errors. 1254 */ 1255 error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1); 1256 if (to == NULL) { 1257 free(from, M_TEMP); 1258 return (error); 1259 } 1260 error = kern_rename(td, from, to, UIO_SYSSPACE); 1261 free(from, M_TEMP); 1262 free(to, M_TEMP); 1263 return (error); 1264} 1265 1266int 1267ibcs2_readlink(td, uap) 1268 struct thread *td; 1269 struct ibcs2_readlink_args *uap; 1270{ 1271 char *path; 1272 int error; 1273 1274 CHECKALTEXIST(td, uap->path, &path); 1275 error = kern_readlink(td, path, UIO_SYSSPACE, uap->buf, UIO_USERSPACE, 1276 uap->count); 1277 free(path, M_TEMP); 1278 return (error); 1279} 1280