470 471 return (error); 472} 473 474#endif /* __i386__ */ 475 476int 477linux_select(struct thread *td, struct linux_select_args *args) 478{ 479 l_timeval ltv; 480 struct timeval tv0, tv1, utv, *tvp; 481 int error; 482 483#ifdef DEBUG 484 if (ldebug(select)) 485 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, 486 (void *)args->readfds, (void *)args->writefds, 487 (void *)args->exceptfds, (void *)args->timeout); 488#endif 489 490 /* 491 * Store current time for computation of the amount of 492 * time left. 493 */ 494 if (args->timeout) { 495 if ((error = copyin(args->timeout, <v, sizeof(ltv)))) 496 goto select_out; 497 utv.tv_sec = ltv.tv_sec; 498 utv.tv_usec = ltv.tv_usec; 499#ifdef DEBUG 500 if (ldebug(select)) 501 printf(LMSG("incoming timeout (%jd/%ld)"), 502 (intmax_t)utv.tv_sec, utv.tv_usec); 503#endif 504 505 if (itimerfix(&utv)) { 506 /* 507 * The timeval was invalid. Convert it to something 508 * valid that will act as it does under Linux. 509 */ 510 utv.tv_sec += utv.tv_usec / 1000000; 511 utv.tv_usec %= 1000000; 512 if (utv.tv_usec < 0) { 513 utv.tv_sec -= 1; 514 utv.tv_usec += 1000000; 515 } 516 if (utv.tv_sec < 0) 517 timevalclear(&utv); 518 } 519 microtime(&tv0); 520 tvp = &utv; 521 } else 522 tvp = NULL; 523 524 error = kern_select(td, args->nfds, args->readfds, args->writefds, 525 args->exceptfds, tvp, sizeof(l_int) * 8); 526 527#ifdef DEBUG 528 if (ldebug(select)) 529 printf(LMSG("real select returns %d"), error); 530#endif 531 if (error) 532 goto select_out; 533 534 if (args->timeout) { 535 if (td->td_retval[0]) { 536 /* 537 * Compute how much time was left of the timeout, 538 * by subtracting the current time and the time 539 * before we started the call, and subtracting 540 * that result from the user-supplied value. 541 */ 542 microtime(&tv1); 543 timevalsub(&tv1, &tv0); 544 timevalsub(&utv, &tv1); 545 if (utv.tv_sec < 0) 546 timevalclear(&utv); 547 } else 548 timevalclear(&utv); 549#ifdef DEBUG 550 if (ldebug(select)) 551 printf(LMSG("outgoing timeout (%jd/%ld)"), 552 (intmax_t)utv.tv_sec, utv.tv_usec); 553#endif 554 ltv.tv_sec = utv.tv_sec; 555 ltv.tv_usec = utv.tv_usec; 556 if ((error = copyout(<v, args->timeout, sizeof(ltv)))) 557 goto select_out; 558 } 559 560select_out: 561#ifdef DEBUG 562 if (ldebug(select)) 563 printf(LMSG("select_out -> %d"), error); 564#endif 565 return (error); 566} 567 568int 569linux_mremap(struct thread *td, struct linux_mremap_args *args) 570{ 571 struct munmap_args /* { 572 void *addr; 573 size_t len; 574 } */ bsd_args; 575 int error = 0; 576 577#ifdef DEBUG 578 if (ldebug(mremap)) 579 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"), 580 (void *)(uintptr_t)args->addr, 581 (unsigned long)args->old_len, 582 (unsigned long)args->new_len, 583 (unsigned long)args->flags); 584#endif 585 586 if (args->flags & ~(LINUX_MREMAP_FIXED | LINUX_MREMAP_MAYMOVE)) { 587 td->td_retval[0] = 0; 588 return (EINVAL); 589 } 590 591 /* 592 * Check for the page alignment. 593 * Linux defines PAGE_MASK to be FreeBSD ~PAGE_MASK. 594 */ 595 if (args->addr & PAGE_MASK) { 596 td->td_retval[0] = 0; 597 return (EINVAL); 598 } 599 600 args->new_len = round_page(args->new_len); 601 args->old_len = round_page(args->old_len); 602 603 if (args->new_len > args->old_len) { 604 td->td_retval[0] = 0; 605 return (ENOMEM); 606 } 607 608 if (args->new_len < args->old_len) { 609 bsd_args.addr = 610 (caddr_t)((uintptr_t)args->addr + args->new_len); 611 bsd_args.len = args->old_len - args->new_len; 612 error = sys_munmap(td, &bsd_args); 613 } 614 615 td->td_retval[0] = error ? 0 : (uintptr_t)args->addr; 616 return (error); 617} 618 619#define LINUX_MS_ASYNC 0x0001 620#define LINUX_MS_INVALIDATE 0x0002 621#define LINUX_MS_SYNC 0x0004 622 623int 624linux_msync(struct thread *td, struct linux_msync_args *args) 625{ 626 struct msync_args bsd_args; 627 628 bsd_args.addr = (caddr_t)(uintptr_t)args->addr; 629 bsd_args.len = (uintptr_t)args->len; 630 bsd_args.flags = args->fl & ~LINUX_MS_SYNC; 631 632 return (sys_msync(td, &bsd_args)); 633} 634 635int 636linux_time(struct thread *td, struct linux_time_args *args) 637{ 638 struct timeval tv; 639 l_time_t tm; 640 int error; 641 642#ifdef DEBUG 643 if (ldebug(time)) 644 printf(ARGS(time, "*")); 645#endif 646 647 microtime(&tv); 648 tm = tv.tv_sec; 649 if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm)))) 650 return (error); 651 td->td_retval[0] = tm; 652 return (0); 653} 654 655struct l_times_argv { 656 l_clock_t tms_utime; 657 l_clock_t tms_stime; 658 l_clock_t tms_cutime; 659 l_clock_t tms_cstime; 660}; 661 662 663/* 664 * Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value. 665 * Since 2.2.1 Glibc uses value exported from kernel via AT_CLKTCK 666 * auxiliary vector entry. 667 */ 668#define CLK_TCK 100 669 670#define CONVOTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 671#define CONVNTCK(r) (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz)) 672 673#define CONVTCK(r) (linux_kernver(td) >= LINUX_KERNVER_2004000 ? \ 674 CONVNTCK(r) : CONVOTCK(r)) 675 676int 677linux_times(struct thread *td, struct linux_times_args *args) 678{ 679 struct timeval tv, utime, stime, cutime, cstime; 680 struct l_times_argv tms; 681 struct proc *p; 682 int error; 683 684#ifdef DEBUG 685 if (ldebug(times)) 686 printf(ARGS(times, "*")); 687#endif 688 689 if (args->buf != NULL) { 690 p = td->td_proc; 691 PROC_LOCK(p); 692 PROC_SLOCK(p); 693 calcru(p, &utime, &stime); 694 PROC_SUNLOCK(p); 695 calccru(p, &cutime, &cstime); 696 PROC_UNLOCK(p); 697 698 tms.tms_utime = CONVTCK(utime); 699 tms.tms_stime = CONVTCK(stime); 700 701 tms.tms_cutime = CONVTCK(cutime); 702 tms.tms_cstime = CONVTCK(cstime); 703 704 if ((error = copyout(&tms, args->buf, sizeof(tms)))) 705 return (error); 706 } 707 708 microuptime(&tv); 709 td->td_retval[0] = (int)CONVTCK(tv); 710 return (0); 711} 712 713int 714linux_newuname(struct thread *td, struct linux_newuname_args *args) 715{ 716 struct l_new_utsname utsname; 717 char osname[LINUX_MAX_UTSNAME]; 718 char osrelease[LINUX_MAX_UTSNAME]; 719 char *p; 720 721#ifdef DEBUG 722 if (ldebug(newuname)) 723 printf(ARGS(newuname, "*")); 724#endif 725 726 linux_get_osname(td, osname); 727 linux_get_osrelease(td, osrelease); 728 729 bzero(&utsname, sizeof(utsname)); 730 strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME); 731 getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME); 732 getcreddomainname(td->td_ucred, utsname.domainname, LINUX_MAX_UTSNAME); 733 strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME); 734 strlcpy(utsname.version, version, LINUX_MAX_UTSNAME); 735 for (p = utsname.version; *p != '\0'; ++p) 736 if (*p == '\n') { 737 *p = '\0'; 738 break; 739 } 740 strlcpy(utsname.machine, linux_platform, LINUX_MAX_UTSNAME); 741 742 return (copyout(&utsname, args->buf, sizeof(utsname))); 743} 744 745#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 746struct l_utimbuf { 747 l_time_t l_actime; 748 l_time_t l_modtime; 749}; 750 751int 752linux_utime(struct thread *td, struct linux_utime_args *args) 753{ 754 struct timeval tv[2], *tvp; 755 struct l_utimbuf lut; 756 char *fname; 757 int error; 758 759 LCONVPATHEXIST(td, args->fname, &fname); 760 761#ifdef DEBUG 762 if (ldebug(utime)) 763 printf(ARGS(utime, "%s, *"), fname); 764#endif 765 766 if (args->times) { 767 if ((error = copyin(args->times, &lut, sizeof lut))) { 768 LFREEPATH(fname); 769 return (error); 770 } 771 tv[0].tv_sec = lut.l_actime; 772 tv[0].tv_usec = 0; 773 tv[1].tv_sec = lut.l_modtime; 774 tv[1].tv_usec = 0; 775 tvp = tv; 776 } else 777 tvp = NULL; 778 779 error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 780 LFREEPATH(fname); 781 return (error); 782} 783 784int 785linux_utimes(struct thread *td, struct linux_utimes_args *args) 786{ 787 l_timeval ltv[2]; 788 struct timeval tv[2], *tvp = NULL; 789 char *fname; 790 int error; 791 792 LCONVPATHEXIST(td, args->fname, &fname); 793 794#ifdef DEBUG 795 if (ldebug(utimes)) 796 printf(ARGS(utimes, "%s, *"), fname); 797#endif 798 799 if (args->tptr != NULL) { 800 if ((error = copyin(args->tptr, ltv, sizeof ltv))) { 801 LFREEPATH(fname); 802 return (error); 803 } 804 tv[0].tv_sec = ltv[0].tv_sec; 805 tv[0].tv_usec = ltv[0].tv_usec; 806 tv[1].tv_sec = ltv[1].tv_sec; 807 tv[1].tv_usec = ltv[1].tv_usec; 808 tvp = tv; 809 } 810 811 error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 812 LFREEPATH(fname); 813 return (error); 814} 815 816int 817linux_futimesat(struct thread *td, struct linux_futimesat_args *args) 818{ 819 l_timeval ltv[2]; 820 struct timeval tv[2], *tvp = NULL; 821 char *fname; 822 int error, dfd; 823 824 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 825 LCONVPATHEXIST_AT(td, args->filename, &fname, dfd); 826 827#ifdef DEBUG 828 if (ldebug(futimesat)) 829 printf(ARGS(futimesat, "%s, *"), fname); 830#endif 831 832 if (args->utimes != NULL) { 833 if ((error = copyin(args->utimes, ltv, sizeof ltv))) { 834 LFREEPATH(fname); 835 return (error); 836 } 837 tv[0].tv_sec = ltv[0].tv_sec; 838 tv[0].tv_usec = ltv[0].tv_usec; 839 tv[1].tv_sec = ltv[1].tv_sec; 840 tv[1].tv_usec = ltv[1].tv_usec; 841 tvp = tv; 842 } 843 844 error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 845 LFREEPATH(fname); 846 return (error); 847} 848#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 849 850int 851linux_common_wait(struct thread *td, int pid, int *status, 852 int options, struct rusage *ru) 853{ 854 int error, tmpstat; 855 856 error = kern_wait(td, pid, &tmpstat, options, ru); 857 if (error) 858 return (error); 859 860 if (status) { 861 tmpstat &= 0xffff; 862 if (WIFSIGNALED(tmpstat)) 863 tmpstat = (tmpstat & 0xffffff80) | 864 BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 865 else if (WIFSTOPPED(tmpstat)) 866 tmpstat = (tmpstat & 0xffff00ff) | 867 (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 868 error = copyout(&tmpstat, status, sizeof(int)); 869 } 870 871 return (error); 872} 873 874int 875linux_waitpid(struct thread *td, struct linux_waitpid_args *args) 876{ 877 int options; 878 879#ifdef DEBUG 880 if (ldebug(waitpid)) 881 printf(ARGS(waitpid, "%d, %p, %d"), 882 args->pid, (void *)args->status, args->options); 883#endif 884 /* 885 * this is necessary because the test in kern_wait doesn't work 886 * because we mess with the options here 887 */ 888 if (args->options & ~(WUNTRACED | WNOHANG | WCONTINUED | __WCLONE)) 889 return (EINVAL); 890 891 options = (args->options & (WNOHANG | WUNTRACED)); 892 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 893 if (args->options & __WCLONE) 894 options |= WLINUXCLONE; 895 896 return (linux_common_wait(td, args->pid, args->status, options, NULL)); 897} 898 899 900int 901linux_mknod(struct thread *td, struct linux_mknod_args *args) 902{ 903 char *path; 904 int error; 905 906 LCONVPATHCREAT(td, args->path, &path); 907 908#ifdef DEBUG 909 if (ldebug(mknod)) 910 printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev); 911#endif 912 913 switch (args->mode & S_IFMT) { 914 case S_IFIFO: 915 case S_IFSOCK: 916 error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode); 917 break; 918 919 case S_IFCHR: 920 case S_IFBLK: 921 error = kern_mknod(td, path, UIO_SYSSPACE, args->mode, 922 args->dev); 923 break; 924 925 case S_IFDIR: 926 error = EPERM; 927 break; 928 929 case 0: 930 args->mode |= S_IFREG; 931 /* FALLTHROUGH */ 932 case S_IFREG: 933 error = kern_open(td, path, UIO_SYSSPACE, 934 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 935 if (error == 0) 936 kern_close(td, td->td_retval[0]); 937 break; 938 939 default: 940 error = EINVAL; 941 break; 942 } 943 LFREEPATH(path); 944 return (error); 945} 946 947int 948linux_mknodat(struct thread *td, struct linux_mknodat_args *args) 949{ 950 char *path; 951 int error, dfd; 952 953 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 954 LCONVPATHCREAT_AT(td, args->filename, &path, dfd); 955 956#ifdef DEBUG 957 if (ldebug(mknodat)) 958 printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev); 959#endif 960 961 switch (args->mode & S_IFMT) { 962 case S_IFIFO: 963 case S_IFSOCK: 964 error = kern_mkfifoat(td, dfd, path, UIO_SYSSPACE, args->mode); 965 break; 966 967 case S_IFCHR: 968 case S_IFBLK: 969 error = kern_mknodat(td, dfd, path, UIO_SYSSPACE, args->mode, 970 args->dev); 971 break; 972 973 case S_IFDIR: 974 error = EPERM; 975 break; 976 977 case 0: 978 args->mode |= S_IFREG; 979 /* FALLTHROUGH */ 980 case S_IFREG: 981 error = kern_openat(td, dfd, path, UIO_SYSSPACE, 982 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 983 if (error == 0) 984 kern_close(td, td->td_retval[0]); 985 break; 986 987 default: 988 error = EINVAL; 989 break; 990 } 991 LFREEPATH(path); 992 return (error); 993} 994 995/* 996 * UGH! This is just about the dumbest idea I've ever heard!! 997 */ 998int 999linux_personality(struct thread *td, struct linux_personality_args *args) 1000{ 1001#ifdef DEBUG 1002 if (ldebug(personality)) 1003 printf(ARGS(personality, "%lu"), (unsigned long)args->per); 1004#endif 1005 if (args->per != 0) 1006 return (EINVAL); 1007 1008 /* Yes Jim, it's still a Linux... */ 1009 td->td_retval[0] = 0; 1010 return (0); 1011} 1012 1013struct l_itimerval { 1014 l_timeval it_interval; 1015 l_timeval it_value; 1016}; 1017 1018#define B2L_ITIMERVAL(bip, lip) \ 1019 (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \ 1020 (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \ 1021 (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \ 1022 (bip)->it_value.tv_usec = (lip)->it_value.tv_usec; 1023 1024int 1025linux_setitimer(struct thread *td, struct linux_setitimer_args *uap) 1026{ 1027 int error; 1028 struct l_itimerval ls; 1029 struct itimerval aitv, oitv; 1030 1031#ifdef DEBUG 1032 if (ldebug(setitimer)) 1033 printf(ARGS(setitimer, "%p, %p"), 1034 (void *)uap->itv, (void *)uap->oitv); 1035#endif 1036 1037 if (uap->itv == NULL) { 1038 uap->itv = uap->oitv; 1039 return (linux_getitimer(td, (struct linux_getitimer_args *)uap)); 1040 } 1041 1042 error = copyin(uap->itv, &ls, sizeof(ls)); 1043 if (error != 0) 1044 return (error); 1045 B2L_ITIMERVAL(&aitv, &ls); 1046#ifdef DEBUG 1047 if (ldebug(setitimer)) { 1048 printf("setitimer: value: sec: %jd, usec: %ld\n", 1049 (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec); 1050 printf("setitimer: interval: sec: %jd, usec: %ld\n", 1051 (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec); 1052 } 1053#endif 1054 error = kern_setitimer(td, uap->which, &aitv, &oitv); 1055 if (error != 0 || uap->oitv == NULL) 1056 return (error); 1057 B2L_ITIMERVAL(&ls, &oitv); 1058 1059 return (copyout(&ls, uap->oitv, sizeof(ls))); 1060} 1061 1062int 1063linux_getitimer(struct thread *td, struct linux_getitimer_args *uap) 1064{ 1065 int error; 1066 struct l_itimerval ls; 1067 struct itimerval aitv; 1068 1069#ifdef DEBUG 1070 if (ldebug(getitimer)) 1071 printf(ARGS(getitimer, "%p"), (void *)uap->itv); 1072#endif 1073 error = kern_getitimer(td, uap->which, &aitv); 1074 if (error != 0) 1075 return (error); 1076 B2L_ITIMERVAL(&ls, &aitv); 1077 return (copyout(&ls, uap->itv, sizeof(ls))); 1078} 1079 1080int 1081linux_nice(struct thread *td, struct linux_nice_args *args) 1082{ 1083 struct setpriority_args bsd_args; 1084 1085 bsd_args.which = PRIO_PROCESS; 1086 bsd_args.who = 0; /* current process */ 1087 bsd_args.prio = args->inc; 1088 return (sys_setpriority(td, &bsd_args)); 1089} 1090 1091int 1092linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 1093{ 1094 struct ucred *newcred, *oldcred; 1095 l_gid_t *linux_gidset; 1096 gid_t *bsd_gidset; 1097 int ngrp, error; 1098 struct proc *p; 1099 1100 ngrp = args->gidsetsize; 1101 if (ngrp < 0 || ngrp >= ngroups_max + 1) 1102 return (EINVAL); 1103 linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); 1104 error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); 1105 if (error) 1106 goto out; 1107 newcred = crget(); 1108 p = td->td_proc; 1109 PROC_LOCK(p); 1110 oldcred = crcopysafe(p, newcred); 1111 1112 /* 1113 * cr_groups[0] holds egid. Setting the whole set from 1114 * the supplied set will cause egid to be changed too. 1115 * Keep cr_groups[0] unchanged to prevent that. 1116 */ 1117 1118 if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { 1119 PROC_UNLOCK(p); 1120 crfree(newcred); 1121 goto out; 1122 } 1123 1124 if (ngrp > 0) { 1125 newcred->cr_ngroups = ngrp + 1; 1126 1127 bsd_gidset = newcred->cr_groups; 1128 ngrp--; 1129 while (ngrp >= 0) { 1130 bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; 1131 ngrp--; 1132 } 1133 } else 1134 newcred->cr_ngroups = 1; 1135 1136 setsugid(p); 1137 p->p_ucred = newcred; 1138 PROC_UNLOCK(p); 1139 crfree(oldcred); 1140 error = 0; 1141out: 1142 free(linux_gidset, M_TEMP); 1143 return (error); 1144} 1145 1146int 1147linux_getgroups(struct thread *td, struct linux_getgroups_args *args) 1148{ 1149 struct ucred *cred; 1150 l_gid_t *linux_gidset; 1151 gid_t *bsd_gidset; 1152 int bsd_gidsetsz, ngrp, error; 1153 1154 cred = td->td_ucred; 1155 bsd_gidset = cred->cr_groups; 1156 bsd_gidsetsz = cred->cr_ngroups - 1; 1157 1158 /* 1159 * cr_groups[0] holds egid. Returning the whole set 1160 * here will cause a duplicate. Exclude cr_groups[0] 1161 * to prevent that. 1162 */ 1163 1164 if ((ngrp = args->gidsetsize) == 0) { 1165 td->td_retval[0] = bsd_gidsetsz; 1166 return (0); 1167 } 1168 1169 if (ngrp < bsd_gidsetsz) 1170 return (EINVAL); 1171 1172 ngrp = 0; 1173 linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), 1174 M_TEMP, M_WAITOK); 1175 while (ngrp < bsd_gidsetsz) { 1176 linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; 1177 ngrp++; 1178 } 1179 1180 error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); 1181 free(linux_gidset, M_TEMP); 1182 if (error) 1183 return (error); 1184 1185 td->td_retval[0] = ngrp; 1186 return (0); 1187} 1188 1189int 1190linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args) 1191{ 1192 struct rlimit bsd_rlim; 1193 struct l_rlimit rlim; 1194 u_int which; 1195 int error; 1196 1197#ifdef DEBUG 1198 if (ldebug(setrlimit)) 1199 printf(ARGS(setrlimit, "%d, %p"), 1200 args->resource, (void *)args->rlim); 1201#endif 1202 1203 if (args->resource >= LINUX_RLIM_NLIMITS) 1204 return (EINVAL); 1205 1206 which = linux_to_bsd_resource[args->resource]; 1207 if (which == -1) 1208 return (EINVAL); 1209 1210 error = copyin(args->rlim, &rlim, sizeof(rlim)); 1211 if (error) 1212 return (error); 1213 1214 bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur; 1215 bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max; 1216 return (kern_setrlimit(td, which, &bsd_rlim)); 1217} 1218 1219int 1220linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) 1221{ 1222 struct l_rlimit rlim; 1223 struct proc *p = td->td_proc; 1224 struct rlimit bsd_rlim; 1225 u_int which; 1226 1227#ifdef DEBUG 1228 if (ldebug(old_getrlimit)) 1229 printf(ARGS(old_getrlimit, "%d, %p"), 1230 args->resource, (void *)args->rlim); 1231#endif 1232 1233 if (args->resource >= LINUX_RLIM_NLIMITS) 1234 return (EINVAL); 1235 1236 which = linux_to_bsd_resource[args->resource]; 1237 if (which == -1) 1238 return (EINVAL); 1239 1240 PROC_LOCK(p); 1241 lim_rlimit(p, which, &bsd_rlim); 1242 PROC_UNLOCK(p); 1243 1244#ifdef COMPAT_LINUX32 1245 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; 1246 if (rlim.rlim_cur == UINT_MAX) 1247 rlim.rlim_cur = INT_MAX; 1248 rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max; 1249 if (rlim.rlim_max == UINT_MAX) 1250 rlim.rlim_max = INT_MAX; 1251#else 1252 rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur; 1253 if (rlim.rlim_cur == ULONG_MAX) 1254 rlim.rlim_cur = LONG_MAX; 1255 rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max; 1256 if (rlim.rlim_max == ULONG_MAX) 1257 rlim.rlim_max = LONG_MAX; 1258#endif 1259 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1260} 1261 1262int 1263linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) 1264{ 1265 struct l_rlimit rlim; 1266 struct proc *p = td->td_proc; 1267 struct rlimit bsd_rlim; 1268 u_int which; 1269 1270#ifdef DEBUG 1271 if (ldebug(getrlimit)) 1272 printf(ARGS(getrlimit, "%d, %p"), 1273 args->resource, (void *)args->rlim); 1274#endif 1275 1276 if (args->resource >= LINUX_RLIM_NLIMITS) 1277 return (EINVAL); 1278 1279 which = linux_to_bsd_resource[args->resource]; 1280 if (which == -1) 1281 return (EINVAL); 1282 1283 PROC_LOCK(p); 1284 lim_rlimit(p, which, &bsd_rlim); 1285 PROC_UNLOCK(p); 1286 1287 rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; 1288 rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; 1289 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1290} 1291 1292int 1293linux_sched_setscheduler(struct thread *td, 1294 struct linux_sched_setscheduler_args *args) 1295{ 1296 struct sched_setscheduler_args bsd; 1297 1298#ifdef DEBUG 1299 if (ldebug(sched_setscheduler)) 1300 printf(ARGS(sched_setscheduler, "%d, %d, %p"), 1301 args->pid, args->policy, (const void *)args->param); 1302#endif 1303 1304 switch (args->policy) { 1305 case LINUX_SCHED_OTHER: 1306 bsd.policy = SCHED_OTHER; 1307 break; 1308 case LINUX_SCHED_FIFO: 1309 bsd.policy = SCHED_FIFO; 1310 break; 1311 case LINUX_SCHED_RR: 1312 bsd.policy = SCHED_RR; 1313 break; 1314 default: 1315 return (EINVAL); 1316 } 1317 1318 bsd.pid = args->pid; 1319 bsd.param = (struct sched_param *)args->param; 1320 return (sys_sched_setscheduler(td, &bsd)); 1321} 1322 1323int 1324linux_sched_getscheduler(struct thread *td, 1325 struct linux_sched_getscheduler_args *args) 1326{ 1327 struct sched_getscheduler_args bsd; 1328 int error; 1329 1330#ifdef DEBUG 1331 if (ldebug(sched_getscheduler)) 1332 printf(ARGS(sched_getscheduler, "%d"), args->pid); 1333#endif 1334 1335 bsd.pid = args->pid; 1336 error = sys_sched_getscheduler(td, &bsd); 1337 1338 switch (td->td_retval[0]) { 1339 case SCHED_OTHER: 1340 td->td_retval[0] = LINUX_SCHED_OTHER; 1341 break; 1342 case SCHED_FIFO: 1343 td->td_retval[0] = LINUX_SCHED_FIFO; 1344 break; 1345 case SCHED_RR: 1346 td->td_retval[0] = LINUX_SCHED_RR; 1347 break; 1348 } 1349 1350 return (error); 1351} 1352 1353int 1354linux_sched_get_priority_max(struct thread *td, 1355 struct linux_sched_get_priority_max_args *args) 1356{ 1357 struct sched_get_priority_max_args bsd; 1358 1359#ifdef DEBUG 1360 if (ldebug(sched_get_priority_max)) 1361 printf(ARGS(sched_get_priority_max, "%d"), args->policy); 1362#endif 1363 1364 switch (args->policy) { 1365 case LINUX_SCHED_OTHER: 1366 bsd.policy = SCHED_OTHER; 1367 break; 1368 case LINUX_SCHED_FIFO: 1369 bsd.policy = SCHED_FIFO; 1370 break; 1371 case LINUX_SCHED_RR: 1372 bsd.policy = SCHED_RR; 1373 break; 1374 default: 1375 return (EINVAL); 1376 } 1377 return (sys_sched_get_priority_max(td, &bsd)); 1378} 1379 1380int 1381linux_sched_get_priority_min(struct thread *td, 1382 struct linux_sched_get_priority_min_args *args) 1383{ 1384 struct sched_get_priority_min_args bsd; 1385 1386#ifdef DEBUG 1387 if (ldebug(sched_get_priority_min)) 1388 printf(ARGS(sched_get_priority_min, "%d"), args->policy); 1389#endif 1390 1391 switch (args->policy) { 1392 case LINUX_SCHED_OTHER: 1393 bsd.policy = SCHED_OTHER; 1394 break; 1395 case LINUX_SCHED_FIFO: 1396 bsd.policy = SCHED_FIFO; 1397 break; 1398 case LINUX_SCHED_RR: 1399 bsd.policy = SCHED_RR; 1400 break; 1401 default: 1402 return (EINVAL); 1403 } 1404 return (sys_sched_get_priority_min(td, &bsd)); 1405} 1406 1407#define REBOOT_CAD_ON 0x89abcdef 1408#define REBOOT_CAD_OFF 0 1409#define REBOOT_HALT 0xcdef0123 1410#define REBOOT_RESTART 0x01234567 1411#define REBOOT_RESTART2 0xA1B2C3D4 1412#define REBOOT_POWEROFF 0x4321FEDC 1413#define REBOOT_MAGIC1 0xfee1dead 1414#define REBOOT_MAGIC2 0x28121969 1415#define REBOOT_MAGIC2A 0x05121996 1416#define REBOOT_MAGIC2B 0x16041998 1417 1418int 1419linux_reboot(struct thread *td, struct linux_reboot_args *args) 1420{ 1421 struct reboot_args bsd_args; 1422 1423#ifdef DEBUG 1424 if (ldebug(reboot)) 1425 printf(ARGS(reboot, "0x%x"), args->cmd); 1426#endif 1427 1428 if (args->magic1 != REBOOT_MAGIC1) 1429 return (EINVAL); 1430 1431 switch (args->magic2) { 1432 case REBOOT_MAGIC2: 1433 case REBOOT_MAGIC2A: 1434 case REBOOT_MAGIC2B: 1435 break; 1436 default: 1437 return (EINVAL); 1438 } 1439 1440 switch (args->cmd) { 1441 case REBOOT_CAD_ON: 1442 case REBOOT_CAD_OFF: 1443 return (priv_check(td, PRIV_REBOOT)); 1444 case REBOOT_HALT: 1445 bsd_args.opt = RB_HALT; 1446 break; 1447 case REBOOT_RESTART: 1448 case REBOOT_RESTART2: 1449 bsd_args.opt = 0; 1450 break; 1451 case REBOOT_POWEROFF: 1452 bsd_args.opt = RB_POWEROFF; 1453 break; 1454 default: 1455 return (EINVAL); 1456 } 1457 return (sys_reboot(td, &bsd_args)); 1458} 1459 1460 1461/* 1462 * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify 1463 * td->td_retval[1] when COMPAT_43 is defined. This clobbers registers that 1464 * are assumed to be preserved. The following lightweight syscalls fixes 1465 * this. See also linux_getgid16() and linux_getuid16() in linux_uid16.c 1466 * 1467 * linux_getpid() - MP SAFE 1468 * linux_getgid() - MP SAFE 1469 * linux_getuid() - MP SAFE 1470 */ 1471 1472int 1473linux_getpid(struct thread *td, struct linux_getpid_args *args) 1474{ 1475 struct linux_emuldata *em; 1476 1477#ifdef DEBUG 1478 if (ldebug(getpid)) 1479 printf(ARGS(getpid, "")); 1480#endif 1481 1482 if (linux_use26(td)) { 1483 em = em_find(td->td_proc, EMUL_DONTLOCK); 1484 KASSERT(em != NULL, ("getpid: emuldata not found.\n")); 1485 td->td_retval[0] = em->shared->group_pid; 1486 } else { 1487 td->td_retval[0] = td->td_proc->p_pid; 1488 } 1489 1490 return (0); 1491} 1492 1493int 1494linux_gettid(struct thread *td, struct linux_gettid_args *args) 1495{ 1496 1497#ifdef DEBUG 1498 if (ldebug(gettid)) 1499 printf(ARGS(gettid, "")); 1500#endif 1501 1502 td->td_retval[0] = td->td_proc->p_pid; 1503 return (0); 1504} 1505 1506 1507int 1508linux_getppid(struct thread *td, struct linux_getppid_args *args) 1509{ 1510 struct linux_emuldata *em; 1511 struct proc *p, *pp; 1512 1513#ifdef DEBUG 1514 if (ldebug(getppid)) 1515 printf(ARGS(getppid, "")); 1516#endif 1517 1518 if (!linux_use26(td)) { 1519 PROC_LOCK(td->td_proc); 1520 td->td_retval[0] = td->td_proc->p_pptr->p_pid; 1521 PROC_UNLOCK(td->td_proc); 1522 return (0); 1523 } 1524 1525 em = em_find(td->td_proc, EMUL_DONTLOCK); 1526 1527 KASSERT(em != NULL, ("getppid: process emuldata not found.\n")); 1528 1529 /* find the group leader */ 1530 p = pfind(em->shared->group_pid); 1531 1532 if (p == NULL) { 1533#ifdef DEBUG 1534 printf(LMSG("parent process not found.\n")); 1535#endif 1536 return (0); 1537 } 1538 1539 pp = p->p_pptr; /* switch to parent */ 1540 PROC_LOCK(pp); 1541 PROC_UNLOCK(p); 1542 1543 /* if its also linux process */ 1544 if (pp->p_sysent == &elf_linux_sysvec) { 1545 em = em_find(pp, EMUL_DONTLOCK); 1546 KASSERT(em != NULL, ("getppid: parent emuldata not found.\n")); 1547 1548 td->td_retval[0] = em->shared->group_pid; 1549 } else 1550 td->td_retval[0] = pp->p_pid; 1551 1552 PROC_UNLOCK(pp); 1553 1554 return (0); 1555} 1556 1557int 1558linux_getgid(struct thread *td, struct linux_getgid_args *args) 1559{ 1560 1561#ifdef DEBUG 1562 if (ldebug(getgid)) 1563 printf(ARGS(getgid, "")); 1564#endif 1565 1566 td->td_retval[0] = td->td_ucred->cr_rgid; 1567 return (0); 1568} 1569 1570int 1571linux_getuid(struct thread *td, struct linux_getuid_args *args) 1572{ 1573 1574#ifdef DEBUG 1575 if (ldebug(getuid)) 1576 printf(ARGS(getuid, "")); 1577#endif 1578 1579 td->td_retval[0] = td->td_ucred->cr_ruid; 1580 return (0); 1581} 1582 1583 1584int 1585linux_getsid(struct thread *td, struct linux_getsid_args *args) 1586{ 1587 struct getsid_args bsd; 1588 1589#ifdef DEBUG 1590 if (ldebug(getsid)) 1591 printf(ARGS(getsid, "%i"), args->pid); 1592#endif 1593 1594 bsd.pid = args->pid; 1595 return (sys_getsid(td, &bsd)); 1596} 1597 1598int 1599linux_nosys(struct thread *td, struct nosys_args *ignore) 1600{ 1601 1602 return (ENOSYS); 1603} 1604 1605int 1606linux_getpriority(struct thread *td, struct linux_getpriority_args *args) 1607{ 1608 struct getpriority_args bsd_args; 1609 int error; 1610 1611#ifdef DEBUG 1612 if (ldebug(getpriority)) 1613 printf(ARGS(getpriority, "%i, %i"), args->which, args->who); 1614#endif 1615 1616 bsd_args.which = args->which; 1617 bsd_args.who = args->who; 1618 error = sys_getpriority(td, &bsd_args); 1619 td->td_retval[0] = 20 - td->td_retval[0]; 1620 return (error); 1621} 1622 1623int 1624linux_sethostname(struct thread *td, struct linux_sethostname_args *args) 1625{ 1626 int name[2]; 1627 1628#ifdef DEBUG 1629 if (ldebug(sethostname)) 1630 printf(ARGS(sethostname, "*, %i"), args->len); 1631#endif 1632 1633 name[0] = CTL_KERN; 1634 name[1] = KERN_HOSTNAME; 1635 return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname, 1636 args->len, 0, 0)); 1637} 1638 1639int 1640linux_setdomainname(struct thread *td, struct linux_setdomainname_args *args) 1641{ 1642 int name[2]; 1643 1644#ifdef DEBUG 1645 if (ldebug(setdomainname)) 1646 printf(ARGS(setdomainname, "*, %i"), args->len); 1647#endif 1648 1649 name[0] = CTL_KERN; 1650 name[1] = KERN_NISDOMAINNAME; 1651 return (userland_sysctl(td, name, 2, 0, 0, 0, args->name, 1652 args->len, 0, 0)); 1653} 1654 1655int 1656linux_exit_group(struct thread *td, struct linux_exit_group_args *args) 1657{ 1658 struct linux_emuldata *em; 1659 1660#ifdef DEBUG 1661 if (ldebug(exit_group)) 1662 printf(ARGS(exit_group, "%i"), args->error_code); 1663#endif 1664 1665 em = em_find(td->td_proc, EMUL_DONTLOCK); 1666 if (em->shared->refs > 1) { 1667 EMUL_SHARED_WLOCK(&emul_shared_lock); 1668 em->shared->flags |= EMUL_SHARED_HASXSTAT; 1669 em->shared->xstat = W_EXITCODE(args->error_code, 0); 1670 EMUL_SHARED_WUNLOCK(&emul_shared_lock); 1671 if (linux_use26(td)) 1672 linux_kill_threads(td, SIGKILL); 1673 } 1674 1675 /* 1676 * XXX: we should send a signal to the parent if 1677 * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?) 1678 * as it doesnt occur often. 1679 */ 1680 exit1(td, W_EXITCODE(args->error_code, 0)); 1681 1682 return (0); 1683} 1684 1685#define _LINUX_CAPABILITY_VERSION 0x19980330 1686 1687struct l_user_cap_header { 1688 l_int version; 1689 l_int pid; 1690}; 1691 1692struct l_user_cap_data { 1693 l_int effective; 1694 l_int permitted; 1695 l_int inheritable; 1696}; 1697 1698int 1699linux_capget(struct thread *td, struct linux_capget_args *args) 1700{ 1701 struct l_user_cap_header luch; 1702 struct l_user_cap_data lucd; 1703 int error; 1704 1705 if (args->hdrp == NULL) 1706 return (EFAULT); 1707 1708 error = copyin(args->hdrp, &luch, sizeof(luch)); 1709 if (error != 0) 1710 return (error); 1711 1712 if (luch.version != _LINUX_CAPABILITY_VERSION) { 1713 luch.version = _LINUX_CAPABILITY_VERSION; 1714 error = copyout(&luch, args->hdrp, sizeof(luch)); 1715 if (error) 1716 return (error); 1717 return (EINVAL); 1718 } 1719 1720 if (luch.pid) 1721 return (EPERM); 1722 1723 if (args->datap) { 1724 /* 1725 * The current implementation doesn't support setting 1726 * a capability (it's essentially a stub) so indicate 1727 * that no capabilities are currently set or available 1728 * to request. 1729 */ 1730 bzero (&lucd, sizeof(lucd)); 1731 error = copyout(&lucd, args->datap, sizeof(lucd)); 1732 } 1733 1734 return (error); 1735} 1736 1737int 1738linux_capset(struct thread *td, struct linux_capset_args *args) 1739{ 1740 struct l_user_cap_header luch; 1741 struct l_user_cap_data lucd; 1742 int error; 1743 1744 if (args->hdrp == NULL || args->datap == NULL) 1745 return (EFAULT); 1746 1747 error = copyin(args->hdrp, &luch, sizeof(luch)); 1748 if (error != 0) 1749 return (error); 1750 1751 if (luch.version != _LINUX_CAPABILITY_VERSION) { 1752 luch.version = _LINUX_CAPABILITY_VERSION; 1753 error = copyout(&luch, args->hdrp, sizeof(luch)); 1754 if (error) 1755 return (error); 1756 return (EINVAL); 1757 } 1758 1759 if (luch.pid) 1760 return (EPERM); 1761 1762 error = copyin(args->datap, &lucd, sizeof(lucd)); 1763 if (error != 0) 1764 return (error); 1765 1766 /* We currently don't support setting any capabilities. */ 1767 if (lucd.effective || lucd.permitted || lucd.inheritable) { 1768 linux_msg(td, 1769 "capset effective=0x%x, permitted=0x%x, " 1770 "inheritable=0x%x is not implemented", 1771 (int)lucd.effective, (int)lucd.permitted, 1772 (int)lucd.inheritable); 1773 return (EPERM); 1774 } 1775 1776 return (0); 1777} 1778 1779int 1780linux_prctl(struct thread *td, struct linux_prctl_args *args) 1781{ 1782 int error = 0, max_size; 1783 struct proc *p = td->td_proc; 1784 char comm[LINUX_MAX_COMM_LEN]; 1785 struct linux_emuldata *em; 1786 int pdeath_signal; 1787 1788#ifdef DEBUG 1789 if (ldebug(prctl)) 1790 printf(ARGS(prctl, "%d, %d, %d, %d, %d"), args->option, 1791 args->arg2, args->arg3, args->arg4, args->arg5); 1792#endif 1793 1794 switch (args->option) { 1795 case LINUX_PR_SET_PDEATHSIG: 1796 if (!LINUX_SIG_VALID(args->arg2)) 1797 return (EINVAL); 1798 em = em_find(p, EMUL_DOLOCK); 1799 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1800 em->pdeath_signal = args->arg2; 1801 EMUL_UNLOCK(&emul_lock); 1802 break; 1803 case LINUX_PR_GET_PDEATHSIG: 1804 em = em_find(p, EMUL_DOLOCK); 1805 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1806 pdeath_signal = em->pdeath_signal; 1807 EMUL_UNLOCK(&emul_lock); 1808 error = copyout(&pdeath_signal, 1809 (void *)(register_t)args->arg2, 1810 sizeof(pdeath_signal)); 1811 break; 1812 case LINUX_PR_GET_KEEPCAPS: 1813 /* 1814 * Indicate that we always clear the effective and 1815 * permitted capability sets when the user id becomes 1816 * non-zero (actually the capability sets are simply 1817 * always zero in the current implementation). 1818 */ 1819 td->td_retval[0] = 0; 1820 break; 1821 case LINUX_PR_SET_KEEPCAPS: 1822 /* 1823 * Ignore requests to keep the effective and permitted 1824 * capability sets when the user id becomes non-zero. 1825 */ 1826 break; 1827 case LINUX_PR_SET_NAME: 1828 /* 1829 * To be on the safe side we need to make sure to not 1830 * overflow the size a linux program expects. We already 1831 * do this here in the copyin, so that we don't need to 1832 * check on copyout. 1833 */ 1834 max_size = MIN(sizeof(comm), sizeof(p->p_comm)); 1835 error = copyinstr((void *)(register_t)args->arg2, comm, 1836 max_size, NULL); 1837 1838 /* Linux silently truncates the name if it is too long. */ 1839 if (error == ENAMETOOLONG) { 1840 /* 1841 * XXX: copyinstr() isn't documented to populate the 1842 * array completely, so do a copyin() to be on the 1843 * safe side. This should be changed in case 1844 * copyinstr() is changed to guarantee this. 1845 */ 1846 error = copyin((void *)(register_t)args->arg2, comm, 1847 max_size - 1); 1848 comm[max_size - 1] = '\0'; 1849 } 1850 if (error) 1851 return (error); 1852 1853 PROC_LOCK(p); 1854 strlcpy(p->p_comm, comm, sizeof(p->p_comm)); 1855 PROC_UNLOCK(p); 1856 break; 1857 case LINUX_PR_GET_NAME: 1858 PROC_LOCK(p); 1859 strlcpy(comm, p->p_comm, sizeof(comm)); 1860 PROC_UNLOCK(p); 1861 error = copyout(comm, (void *)(register_t)args->arg2, 1862 strlen(comm) + 1); 1863 break; 1864 default: 1865 error = EINVAL; 1866 break; 1867 } 1868 1869 return (error); 1870} 1871 1872/* 1873 * Get affinity of a process. 1874 */ 1875int 1876linux_sched_getaffinity(struct thread *td, 1877 struct linux_sched_getaffinity_args *args) 1878{ 1879 int error; 1880 struct cpuset_getaffinity_args cga; 1881 1882#ifdef DEBUG 1883 if (ldebug(sched_getaffinity)) 1884 printf(ARGS(sched_getaffinity, "%d, %d, *"), args->pid, 1885 args->len); 1886#endif 1887 if (args->len < sizeof(cpuset_t)) 1888 return (EINVAL); 1889 1890 cga.level = CPU_LEVEL_WHICH; 1891 cga.which = CPU_WHICH_PID; 1892 cga.id = args->pid; 1893 cga.cpusetsize = sizeof(cpuset_t); 1894 cga.mask = (cpuset_t *) args->user_mask_ptr; 1895 1896 if ((error = sys_cpuset_getaffinity(td, &cga)) == 0) 1897 td->td_retval[0] = sizeof(cpuset_t); 1898 1899 return (error); 1900} 1901 1902/* 1903 * Set affinity of a process. 1904 */ 1905int 1906linux_sched_setaffinity(struct thread *td, 1907 struct linux_sched_setaffinity_args *args) 1908{ 1909 struct cpuset_setaffinity_args csa; 1910 1911#ifdef DEBUG 1912 if (ldebug(sched_setaffinity)) 1913 printf(ARGS(sched_setaffinity, "%d, %d, *"), args->pid, 1914 args->len); 1915#endif 1916 if (args->len < sizeof(cpuset_t)) 1917 return (EINVAL); 1918 1919 csa.level = CPU_LEVEL_WHICH; 1920 csa.which = CPU_WHICH_PID; 1921 csa.id = args->pid; 1922 csa.cpusetsize = sizeof(cpuset_t); 1923 csa.mask = (cpuset_t *) args->user_mask_ptr; 1924 1925 return (sys_cpuset_setaffinity(td, &csa)); 1926}
| 460 461 return (error); 462} 463 464#endif /* __i386__ */ 465 466int 467linux_select(struct thread *td, struct linux_select_args *args) 468{ 469 l_timeval ltv; 470 struct timeval tv0, tv1, utv, *tvp; 471 int error; 472 473#ifdef DEBUG 474 if (ldebug(select)) 475 printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, 476 (void *)args->readfds, (void *)args->writefds, 477 (void *)args->exceptfds, (void *)args->timeout); 478#endif 479 480 /* 481 * Store current time for computation of the amount of 482 * time left. 483 */ 484 if (args->timeout) { 485 if ((error = copyin(args->timeout, <v, sizeof(ltv)))) 486 goto select_out; 487 utv.tv_sec = ltv.tv_sec; 488 utv.tv_usec = ltv.tv_usec; 489#ifdef DEBUG 490 if (ldebug(select)) 491 printf(LMSG("incoming timeout (%jd/%ld)"), 492 (intmax_t)utv.tv_sec, utv.tv_usec); 493#endif 494 495 if (itimerfix(&utv)) { 496 /* 497 * The timeval was invalid. Convert it to something 498 * valid that will act as it does under Linux. 499 */ 500 utv.tv_sec += utv.tv_usec / 1000000; 501 utv.tv_usec %= 1000000; 502 if (utv.tv_usec < 0) { 503 utv.tv_sec -= 1; 504 utv.tv_usec += 1000000; 505 } 506 if (utv.tv_sec < 0) 507 timevalclear(&utv); 508 } 509 microtime(&tv0); 510 tvp = &utv; 511 } else 512 tvp = NULL; 513 514 error = kern_select(td, args->nfds, args->readfds, args->writefds, 515 args->exceptfds, tvp, sizeof(l_int) * 8); 516 517#ifdef DEBUG 518 if (ldebug(select)) 519 printf(LMSG("real select returns %d"), error); 520#endif 521 if (error) 522 goto select_out; 523 524 if (args->timeout) { 525 if (td->td_retval[0]) { 526 /* 527 * Compute how much time was left of the timeout, 528 * by subtracting the current time and the time 529 * before we started the call, and subtracting 530 * that result from the user-supplied value. 531 */ 532 microtime(&tv1); 533 timevalsub(&tv1, &tv0); 534 timevalsub(&utv, &tv1); 535 if (utv.tv_sec < 0) 536 timevalclear(&utv); 537 } else 538 timevalclear(&utv); 539#ifdef DEBUG 540 if (ldebug(select)) 541 printf(LMSG("outgoing timeout (%jd/%ld)"), 542 (intmax_t)utv.tv_sec, utv.tv_usec); 543#endif 544 ltv.tv_sec = utv.tv_sec; 545 ltv.tv_usec = utv.tv_usec; 546 if ((error = copyout(<v, args->timeout, sizeof(ltv)))) 547 goto select_out; 548 } 549 550select_out: 551#ifdef DEBUG 552 if (ldebug(select)) 553 printf(LMSG("select_out -> %d"), error); 554#endif 555 return (error); 556} 557 558int 559linux_mremap(struct thread *td, struct linux_mremap_args *args) 560{ 561 struct munmap_args /* { 562 void *addr; 563 size_t len; 564 } */ bsd_args; 565 int error = 0; 566 567#ifdef DEBUG 568 if (ldebug(mremap)) 569 printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"), 570 (void *)(uintptr_t)args->addr, 571 (unsigned long)args->old_len, 572 (unsigned long)args->new_len, 573 (unsigned long)args->flags); 574#endif 575 576 if (args->flags & ~(LINUX_MREMAP_FIXED | LINUX_MREMAP_MAYMOVE)) { 577 td->td_retval[0] = 0; 578 return (EINVAL); 579 } 580 581 /* 582 * Check for the page alignment. 583 * Linux defines PAGE_MASK to be FreeBSD ~PAGE_MASK. 584 */ 585 if (args->addr & PAGE_MASK) { 586 td->td_retval[0] = 0; 587 return (EINVAL); 588 } 589 590 args->new_len = round_page(args->new_len); 591 args->old_len = round_page(args->old_len); 592 593 if (args->new_len > args->old_len) { 594 td->td_retval[0] = 0; 595 return (ENOMEM); 596 } 597 598 if (args->new_len < args->old_len) { 599 bsd_args.addr = 600 (caddr_t)((uintptr_t)args->addr + args->new_len); 601 bsd_args.len = args->old_len - args->new_len; 602 error = sys_munmap(td, &bsd_args); 603 } 604 605 td->td_retval[0] = error ? 0 : (uintptr_t)args->addr; 606 return (error); 607} 608 609#define LINUX_MS_ASYNC 0x0001 610#define LINUX_MS_INVALIDATE 0x0002 611#define LINUX_MS_SYNC 0x0004 612 613int 614linux_msync(struct thread *td, struct linux_msync_args *args) 615{ 616 struct msync_args bsd_args; 617 618 bsd_args.addr = (caddr_t)(uintptr_t)args->addr; 619 bsd_args.len = (uintptr_t)args->len; 620 bsd_args.flags = args->fl & ~LINUX_MS_SYNC; 621 622 return (sys_msync(td, &bsd_args)); 623} 624 625int 626linux_time(struct thread *td, struct linux_time_args *args) 627{ 628 struct timeval tv; 629 l_time_t tm; 630 int error; 631 632#ifdef DEBUG 633 if (ldebug(time)) 634 printf(ARGS(time, "*")); 635#endif 636 637 microtime(&tv); 638 tm = tv.tv_sec; 639 if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm)))) 640 return (error); 641 td->td_retval[0] = tm; 642 return (0); 643} 644 645struct l_times_argv { 646 l_clock_t tms_utime; 647 l_clock_t tms_stime; 648 l_clock_t tms_cutime; 649 l_clock_t tms_cstime; 650}; 651 652 653/* 654 * Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value. 655 * Since 2.2.1 Glibc uses value exported from kernel via AT_CLKTCK 656 * auxiliary vector entry. 657 */ 658#define CLK_TCK 100 659 660#define CONVOTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 661#define CONVNTCK(r) (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz)) 662 663#define CONVTCK(r) (linux_kernver(td) >= LINUX_KERNVER_2004000 ? \ 664 CONVNTCK(r) : CONVOTCK(r)) 665 666int 667linux_times(struct thread *td, struct linux_times_args *args) 668{ 669 struct timeval tv, utime, stime, cutime, cstime; 670 struct l_times_argv tms; 671 struct proc *p; 672 int error; 673 674#ifdef DEBUG 675 if (ldebug(times)) 676 printf(ARGS(times, "*")); 677#endif 678 679 if (args->buf != NULL) { 680 p = td->td_proc; 681 PROC_LOCK(p); 682 PROC_SLOCK(p); 683 calcru(p, &utime, &stime); 684 PROC_SUNLOCK(p); 685 calccru(p, &cutime, &cstime); 686 PROC_UNLOCK(p); 687 688 tms.tms_utime = CONVTCK(utime); 689 tms.tms_stime = CONVTCK(stime); 690 691 tms.tms_cutime = CONVTCK(cutime); 692 tms.tms_cstime = CONVTCK(cstime); 693 694 if ((error = copyout(&tms, args->buf, sizeof(tms)))) 695 return (error); 696 } 697 698 microuptime(&tv); 699 td->td_retval[0] = (int)CONVTCK(tv); 700 return (0); 701} 702 703int 704linux_newuname(struct thread *td, struct linux_newuname_args *args) 705{ 706 struct l_new_utsname utsname; 707 char osname[LINUX_MAX_UTSNAME]; 708 char osrelease[LINUX_MAX_UTSNAME]; 709 char *p; 710 711#ifdef DEBUG 712 if (ldebug(newuname)) 713 printf(ARGS(newuname, "*")); 714#endif 715 716 linux_get_osname(td, osname); 717 linux_get_osrelease(td, osrelease); 718 719 bzero(&utsname, sizeof(utsname)); 720 strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME); 721 getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME); 722 getcreddomainname(td->td_ucred, utsname.domainname, LINUX_MAX_UTSNAME); 723 strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME); 724 strlcpy(utsname.version, version, LINUX_MAX_UTSNAME); 725 for (p = utsname.version; *p != '\0'; ++p) 726 if (*p == '\n') { 727 *p = '\0'; 728 break; 729 } 730 strlcpy(utsname.machine, linux_platform, LINUX_MAX_UTSNAME); 731 732 return (copyout(&utsname, args->buf, sizeof(utsname))); 733} 734 735#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 736struct l_utimbuf { 737 l_time_t l_actime; 738 l_time_t l_modtime; 739}; 740 741int 742linux_utime(struct thread *td, struct linux_utime_args *args) 743{ 744 struct timeval tv[2], *tvp; 745 struct l_utimbuf lut; 746 char *fname; 747 int error; 748 749 LCONVPATHEXIST(td, args->fname, &fname); 750 751#ifdef DEBUG 752 if (ldebug(utime)) 753 printf(ARGS(utime, "%s, *"), fname); 754#endif 755 756 if (args->times) { 757 if ((error = copyin(args->times, &lut, sizeof lut))) { 758 LFREEPATH(fname); 759 return (error); 760 } 761 tv[0].tv_sec = lut.l_actime; 762 tv[0].tv_usec = 0; 763 tv[1].tv_sec = lut.l_modtime; 764 tv[1].tv_usec = 0; 765 tvp = tv; 766 } else 767 tvp = NULL; 768 769 error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 770 LFREEPATH(fname); 771 return (error); 772} 773 774int 775linux_utimes(struct thread *td, struct linux_utimes_args *args) 776{ 777 l_timeval ltv[2]; 778 struct timeval tv[2], *tvp = NULL; 779 char *fname; 780 int error; 781 782 LCONVPATHEXIST(td, args->fname, &fname); 783 784#ifdef DEBUG 785 if (ldebug(utimes)) 786 printf(ARGS(utimes, "%s, *"), fname); 787#endif 788 789 if (args->tptr != NULL) { 790 if ((error = copyin(args->tptr, ltv, sizeof ltv))) { 791 LFREEPATH(fname); 792 return (error); 793 } 794 tv[0].tv_sec = ltv[0].tv_sec; 795 tv[0].tv_usec = ltv[0].tv_usec; 796 tv[1].tv_sec = ltv[1].tv_sec; 797 tv[1].tv_usec = ltv[1].tv_usec; 798 tvp = tv; 799 } 800 801 error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 802 LFREEPATH(fname); 803 return (error); 804} 805 806int 807linux_futimesat(struct thread *td, struct linux_futimesat_args *args) 808{ 809 l_timeval ltv[2]; 810 struct timeval tv[2], *tvp = NULL; 811 char *fname; 812 int error, dfd; 813 814 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 815 LCONVPATHEXIST_AT(td, args->filename, &fname, dfd); 816 817#ifdef DEBUG 818 if (ldebug(futimesat)) 819 printf(ARGS(futimesat, "%s, *"), fname); 820#endif 821 822 if (args->utimes != NULL) { 823 if ((error = copyin(args->utimes, ltv, sizeof ltv))) { 824 LFREEPATH(fname); 825 return (error); 826 } 827 tv[0].tv_sec = ltv[0].tv_sec; 828 tv[0].tv_usec = ltv[0].tv_usec; 829 tv[1].tv_sec = ltv[1].tv_sec; 830 tv[1].tv_usec = ltv[1].tv_usec; 831 tvp = tv; 832 } 833 834 error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE); 835 LFREEPATH(fname); 836 return (error); 837} 838#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 839 840int 841linux_common_wait(struct thread *td, int pid, int *status, 842 int options, struct rusage *ru) 843{ 844 int error, tmpstat; 845 846 error = kern_wait(td, pid, &tmpstat, options, ru); 847 if (error) 848 return (error); 849 850 if (status) { 851 tmpstat &= 0xffff; 852 if (WIFSIGNALED(tmpstat)) 853 tmpstat = (tmpstat & 0xffffff80) | 854 BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 855 else if (WIFSTOPPED(tmpstat)) 856 tmpstat = (tmpstat & 0xffff00ff) | 857 (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 858 error = copyout(&tmpstat, status, sizeof(int)); 859 } 860 861 return (error); 862} 863 864int 865linux_waitpid(struct thread *td, struct linux_waitpid_args *args) 866{ 867 int options; 868 869#ifdef DEBUG 870 if (ldebug(waitpid)) 871 printf(ARGS(waitpid, "%d, %p, %d"), 872 args->pid, (void *)args->status, args->options); 873#endif 874 /* 875 * this is necessary because the test in kern_wait doesn't work 876 * because we mess with the options here 877 */ 878 if (args->options & ~(WUNTRACED | WNOHANG | WCONTINUED | __WCLONE)) 879 return (EINVAL); 880 881 options = (args->options & (WNOHANG | WUNTRACED)); 882 /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 883 if (args->options & __WCLONE) 884 options |= WLINUXCLONE; 885 886 return (linux_common_wait(td, args->pid, args->status, options, NULL)); 887} 888 889 890int 891linux_mknod(struct thread *td, struct linux_mknod_args *args) 892{ 893 char *path; 894 int error; 895 896 LCONVPATHCREAT(td, args->path, &path); 897 898#ifdef DEBUG 899 if (ldebug(mknod)) 900 printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev); 901#endif 902 903 switch (args->mode & S_IFMT) { 904 case S_IFIFO: 905 case S_IFSOCK: 906 error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode); 907 break; 908 909 case S_IFCHR: 910 case S_IFBLK: 911 error = kern_mknod(td, path, UIO_SYSSPACE, args->mode, 912 args->dev); 913 break; 914 915 case S_IFDIR: 916 error = EPERM; 917 break; 918 919 case 0: 920 args->mode |= S_IFREG; 921 /* FALLTHROUGH */ 922 case S_IFREG: 923 error = kern_open(td, path, UIO_SYSSPACE, 924 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 925 if (error == 0) 926 kern_close(td, td->td_retval[0]); 927 break; 928 929 default: 930 error = EINVAL; 931 break; 932 } 933 LFREEPATH(path); 934 return (error); 935} 936 937int 938linux_mknodat(struct thread *td, struct linux_mknodat_args *args) 939{ 940 char *path; 941 int error, dfd; 942 943 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 944 LCONVPATHCREAT_AT(td, args->filename, &path, dfd); 945 946#ifdef DEBUG 947 if (ldebug(mknodat)) 948 printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev); 949#endif 950 951 switch (args->mode & S_IFMT) { 952 case S_IFIFO: 953 case S_IFSOCK: 954 error = kern_mkfifoat(td, dfd, path, UIO_SYSSPACE, args->mode); 955 break; 956 957 case S_IFCHR: 958 case S_IFBLK: 959 error = kern_mknodat(td, dfd, path, UIO_SYSSPACE, args->mode, 960 args->dev); 961 break; 962 963 case S_IFDIR: 964 error = EPERM; 965 break; 966 967 case 0: 968 args->mode |= S_IFREG; 969 /* FALLTHROUGH */ 970 case S_IFREG: 971 error = kern_openat(td, dfd, path, UIO_SYSSPACE, 972 O_WRONLY | O_CREAT | O_TRUNC, args->mode); 973 if (error == 0) 974 kern_close(td, td->td_retval[0]); 975 break; 976 977 default: 978 error = EINVAL; 979 break; 980 } 981 LFREEPATH(path); 982 return (error); 983} 984 985/* 986 * UGH! This is just about the dumbest idea I've ever heard!! 987 */ 988int 989linux_personality(struct thread *td, struct linux_personality_args *args) 990{ 991#ifdef DEBUG 992 if (ldebug(personality)) 993 printf(ARGS(personality, "%lu"), (unsigned long)args->per); 994#endif 995 if (args->per != 0) 996 return (EINVAL); 997 998 /* Yes Jim, it's still a Linux... */ 999 td->td_retval[0] = 0; 1000 return (0); 1001} 1002 1003struct l_itimerval { 1004 l_timeval it_interval; 1005 l_timeval it_value; 1006}; 1007 1008#define B2L_ITIMERVAL(bip, lip) \ 1009 (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \ 1010 (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \ 1011 (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \ 1012 (bip)->it_value.tv_usec = (lip)->it_value.tv_usec; 1013 1014int 1015linux_setitimer(struct thread *td, struct linux_setitimer_args *uap) 1016{ 1017 int error; 1018 struct l_itimerval ls; 1019 struct itimerval aitv, oitv; 1020 1021#ifdef DEBUG 1022 if (ldebug(setitimer)) 1023 printf(ARGS(setitimer, "%p, %p"), 1024 (void *)uap->itv, (void *)uap->oitv); 1025#endif 1026 1027 if (uap->itv == NULL) { 1028 uap->itv = uap->oitv; 1029 return (linux_getitimer(td, (struct linux_getitimer_args *)uap)); 1030 } 1031 1032 error = copyin(uap->itv, &ls, sizeof(ls)); 1033 if (error != 0) 1034 return (error); 1035 B2L_ITIMERVAL(&aitv, &ls); 1036#ifdef DEBUG 1037 if (ldebug(setitimer)) { 1038 printf("setitimer: value: sec: %jd, usec: %ld\n", 1039 (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec); 1040 printf("setitimer: interval: sec: %jd, usec: %ld\n", 1041 (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec); 1042 } 1043#endif 1044 error = kern_setitimer(td, uap->which, &aitv, &oitv); 1045 if (error != 0 || uap->oitv == NULL) 1046 return (error); 1047 B2L_ITIMERVAL(&ls, &oitv); 1048 1049 return (copyout(&ls, uap->oitv, sizeof(ls))); 1050} 1051 1052int 1053linux_getitimer(struct thread *td, struct linux_getitimer_args *uap) 1054{ 1055 int error; 1056 struct l_itimerval ls; 1057 struct itimerval aitv; 1058 1059#ifdef DEBUG 1060 if (ldebug(getitimer)) 1061 printf(ARGS(getitimer, "%p"), (void *)uap->itv); 1062#endif 1063 error = kern_getitimer(td, uap->which, &aitv); 1064 if (error != 0) 1065 return (error); 1066 B2L_ITIMERVAL(&ls, &aitv); 1067 return (copyout(&ls, uap->itv, sizeof(ls))); 1068} 1069 1070int 1071linux_nice(struct thread *td, struct linux_nice_args *args) 1072{ 1073 struct setpriority_args bsd_args; 1074 1075 bsd_args.which = PRIO_PROCESS; 1076 bsd_args.who = 0; /* current process */ 1077 bsd_args.prio = args->inc; 1078 return (sys_setpriority(td, &bsd_args)); 1079} 1080 1081int 1082linux_setgroups(struct thread *td, struct linux_setgroups_args *args) 1083{ 1084 struct ucred *newcred, *oldcred; 1085 l_gid_t *linux_gidset; 1086 gid_t *bsd_gidset; 1087 int ngrp, error; 1088 struct proc *p; 1089 1090 ngrp = args->gidsetsize; 1091 if (ngrp < 0 || ngrp >= ngroups_max + 1) 1092 return (EINVAL); 1093 linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); 1094 error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); 1095 if (error) 1096 goto out; 1097 newcred = crget(); 1098 p = td->td_proc; 1099 PROC_LOCK(p); 1100 oldcred = crcopysafe(p, newcred); 1101 1102 /* 1103 * cr_groups[0] holds egid. Setting the whole set from 1104 * the supplied set will cause egid to be changed too. 1105 * Keep cr_groups[0] unchanged to prevent that. 1106 */ 1107 1108 if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { 1109 PROC_UNLOCK(p); 1110 crfree(newcred); 1111 goto out; 1112 } 1113 1114 if (ngrp > 0) { 1115 newcred->cr_ngroups = ngrp + 1; 1116 1117 bsd_gidset = newcred->cr_groups; 1118 ngrp--; 1119 while (ngrp >= 0) { 1120 bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; 1121 ngrp--; 1122 } 1123 } else 1124 newcred->cr_ngroups = 1; 1125 1126 setsugid(p); 1127 p->p_ucred = newcred; 1128 PROC_UNLOCK(p); 1129 crfree(oldcred); 1130 error = 0; 1131out: 1132 free(linux_gidset, M_TEMP); 1133 return (error); 1134} 1135 1136int 1137linux_getgroups(struct thread *td, struct linux_getgroups_args *args) 1138{ 1139 struct ucred *cred; 1140 l_gid_t *linux_gidset; 1141 gid_t *bsd_gidset; 1142 int bsd_gidsetsz, ngrp, error; 1143 1144 cred = td->td_ucred; 1145 bsd_gidset = cred->cr_groups; 1146 bsd_gidsetsz = cred->cr_ngroups - 1; 1147 1148 /* 1149 * cr_groups[0] holds egid. Returning the whole set 1150 * here will cause a duplicate. Exclude cr_groups[0] 1151 * to prevent that. 1152 */ 1153 1154 if ((ngrp = args->gidsetsize) == 0) { 1155 td->td_retval[0] = bsd_gidsetsz; 1156 return (0); 1157 } 1158 1159 if (ngrp < bsd_gidsetsz) 1160 return (EINVAL); 1161 1162 ngrp = 0; 1163 linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), 1164 M_TEMP, M_WAITOK); 1165 while (ngrp < bsd_gidsetsz) { 1166 linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; 1167 ngrp++; 1168 } 1169 1170 error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); 1171 free(linux_gidset, M_TEMP); 1172 if (error) 1173 return (error); 1174 1175 td->td_retval[0] = ngrp; 1176 return (0); 1177} 1178 1179int 1180linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args) 1181{ 1182 struct rlimit bsd_rlim; 1183 struct l_rlimit rlim; 1184 u_int which; 1185 int error; 1186 1187#ifdef DEBUG 1188 if (ldebug(setrlimit)) 1189 printf(ARGS(setrlimit, "%d, %p"), 1190 args->resource, (void *)args->rlim); 1191#endif 1192 1193 if (args->resource >= LINUX_RLIM_NLIMITS) 1194 return (EINVAL); 1195 1196 which = linux_to_bsd_resource[args->resource]; 1197 if (which == -1) 1198 return (EINVAL); 1199 1200 error = copyin(args->rlim, &rlim, sizeof(rlim)); 1201 if (error) 1202 return (error); 1203 1204 bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur; 1205 bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max; 1206 return (kern_setrlimit(td, which, &bsd_rlim)); 1207} 1208 1209int 1210linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) 1211{ 1212 struct l_rlimit rlim; 1213 struct proc *p = td->td_proc; 1214 struct rlimit bsd_rlim; 1215 u_int which; 1216 1217#ifdef DEBUG 1218 if (ldebug(old_getrlimit)) 1219 printf(ARGS(old_getrlimit, "%d, %p"), 1220 args->resource, (void *)args->rlim); 1221#endif 1222 1223 if (args->resource >= LINUX_RLIM_NLIMITS) 1224 return (EINVAL); 1225 1226 which = linux_to_bsd_resource[args->resource]; 1227 if (which == -1) 1228 return (EINVAL); 1229 1230 PROC_LOCK(p); 1231 lim_rlimit(p, which, &bsd_rlim); 1232 PROC_UNLOCK(p); 1233 1234#ifdef COMPAT_LINUX32 1235 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; 1236 if (rlim.rlim_cur == UINT_MAX) 1237 rlim.rlim_cur = INT_MAX; 1238 rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max; 1239 if (rlim.rlim_max == UINT_MAX) 1240 rlim.rlim_max = INT_MAX; 1241#else 1242 rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur; 1243 if (rlim.rlim_cur == ULONG_MAX) 1244 rlim.rlim_cur = LONG_MAX; 1245 rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max; 1246 if (rlim.rlim_max == ULONG_MAX) 1247 rlim.rlim_max = LONG_MAX; 1248#endif 1249 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1250} 1251 1252int 1253linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) 1254{ 1255 struct l_rlimit rlim; 1256 struct proc *p = td->td_proc; 1257 struct rlimit bsd_rlim; 1258 u_int which; 1259 1260#ifdef DEBUG 1261 if (ldebug(getrlimit)) 1262 printf(ARGS(getrlimit, "%d, %p"), 1263 args->resource, (void *)args->rlim); 1264#endif 1265 1266 if (args->resource >= LINUX_RLIM_NLIMITS) 1267 return (EINVAL); 1268 1269 which = linux_to_bsd_resource[args->resource]; 1270 if (which == -1) 1271 return (EINVAL); 1272 1273 PROC_LOCK(p); 1274 lim_rlimit(p, which, &bsd_rlim); 1275 PROC_UNLOCK(p); 1276 1277 rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; 1278 rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; 1279 return (copyout(&rlim, args->rlim, sizeof(rlim))); 1280} 1281 1282int 1283linux_sched_setscheduler(struct thread *td, 1284 struct linux_sched_setscheduler_args *args) 1285{ 1286 struct sched_setscheduler_args bsd; 1287 1288#ifdef DEBUG 1289 if (ldebug(sched_setscheduler)) 1290 printf(ARGS(sched_setscheduler, "%d, %d, %p"), 1291 args->pid, args->policy, (const void *)args->param); 1292#endif 1293 1294 switch (args->policy) { 1295 case LINUX_SCHED_OTHER: 1296 bsd.policy = SCHED_OTHER; 1297 break; 1298 case LINUX_SCHED_FIFO: 1299 bsd.policy = SCHED_FIFO; 1300 break; 1301 case LINUX_SCHED_RR: 1302 bsd.policy = SCHED_RR; 1303 break; 1304 default: 1305 return (EINVAL); 1306 } 1307 1308 bsd.pid = args->pid; 1309 bsd.param = (struct sched_param *)args->param; 1310 return (sys_sched_setscheduler(td, &bsd)); 1311} 1312 1313int 1314linux_sched_getscheduler(struct thread *td, 1315 struct linux_sched_getscheduler_args *args) 1316{ 1317 struct sched_getscheduler_args bsd; 1318 int error; 1319 1320#ifdef DEBUG 1321 if (ldebug(sched_getscheduler)) 1322 printf(ARGS(sched_getscheduler, "%d"), args->pid); 1323#endif 1324 1325 bsd.pid = args->pid; 1326 error = sys_sched_getscheduler(td, &bsd); 1327 1328 switch (td->td_retval[0]) { 1329 case SCHED_OTHER: 1330 td->td_retval[0] = LINUX_SCHED_OTHER; 1331 break; 1332 case SCHED_FIFO: 1333 td->td_retval[0] = LINUX_SCHED_FIFO; 1334 break; 1335 case SCHED_RR: 1336 td->td_retval[0] = LINUX_SCHED_RR; 1337 break; 1338 } 1339 1340 return (error); 1341} 1342 1343int 1344linux_sched_get_priority_max(struct thread *td, 1345 struct linux_sched_get_priority_max_args *args) 1346{ 1347 struct sched_get_priority_max_args bsd; 1348 1349#ifdef DEBUG 1350 if (ldebug(sched_get_priority_max)) 1351 printf(ARGS(sched_get_priority_max, "%d"), args->policy); 1352#endif 1353 1354 switch (args->policy) { 1355 case LINUX_SCHED_OTHER: 1356 bsd.policy = SCHED_OTHER; 1357 break; 1358 case LINUX_SCHED_FIFO: 1359 bsd.policy = SCHED_FIFO; 1360 break; 1361 case LINUX_SCHED_RR: 1362 bsd.policy = SCHED_RR; 1363 break; 1364 default: 1365 return (EINVAL); 1366 } 1367 return (sys_sched_get_priority_max(td, &bsd)); 1368} 1369 1370int 1371linux_sched_get_priority_min(struct thread *td, 1372 struct linux_sched_get_priority_min_args *args) 1373{ 1374 struct sched_get_priority_min_args bsd; 1375 1376#ifdef DEBUG 1377 if (ldebug(sched_get_priority_min)) 1378 printf(ARGS(sched_get_priority_min, "%d"), args->policy); 1379#endif 1380 1381 switch (args->policy) { 1382 case LINUX_SCHED_OTHER: 1383 bsd.policy = SCHED_OTHER; 1384 break; 1385 case LINUX_SCHED_FIFO: 1386 bsd.policy = SCHED_FIFO; 1387 break; 1388 case LINUX_SCHED_RR: 1389 bsd.policy = SCHED_RR; 1390 break; 1391 default: 1392 return (EINVAL); 1393 } 1394 return (sys_sched_get_priority_min(td, &bsd)); 1395} 1396 1397#define REBOOT_CAD_ON 0x89abcdef 1398#define REBOOT_CAD_OFF 0 1399#define REBOOT_HALT 0xcdef0123 1400#define REBOOT_RESTART 0x01234567 1401#define REBOOT_RESTART2 0xA1B2C3D4 1402#define REBOOT_POWEROFF 0x4321FEDC 1403#define REBOOT_MAGIC1 0xfee1dead 1404#define REBOOT_MAGIC2 0x28121969 1405#define REBOOT_MAGIC2A 0x05121996 1406#define REBOOT_MAGIC2B 0x16041998 1407 1408int 1409linux_reboot(struct thread *td, struct linux_reboot_args *args) 1410{ 1411 struct reboot_args bsd_args; 1412 1413#ifdef DEBUG 1414 if (ldebug(reboot)) 1415 printf(ARGS(reboot, "0x%x"), args->cmd); 1416#endif 1417 1418 if (args->magic1 != REBOOT_MAGIC1) 1419 return (EINVAL); 1420 1421 switch (args->magic2) { 1422 case REBOOT_MAGIC2: 1423 case REBOOT_MAGIC2A: 1424 case REBOOT_MAGIC2B: 1425 break; 1426 default: 1427 return (EINVAL); 1428 } 1429 1430 switch (args->cmd) { 1431 case REBOOT_CAD_ON: 1432 case REBOOT_CAD_OFF: 1433 return (priv_check(td, PRIV_REBOOT)); 1434 case REBOOT_HALT: 1435 bsd_args.opt = RB_HALT; 1436 break; 1437 case REBOOT_RESTART: 1438 case REBOOT_RESTART2: 1439 bsd_args.opt = 0; 1440 break; 1441 case REBOOT_POWEROFF: 1442 bsd_args.opt = RB_POWEROFF; 1443 break; 1444 default: 1445 return (EINVAL); 1446 } 1447 return (sys_reboot(td, &bsd_args)); 1448} 1449 1450 1451/* 1452 * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify 1453 * td->td_retval[1] when COMPAT_43 is defined. This clobbers registers that 1454 * are assumed to be preserved. The following lightweight syscalls fixes 1455 * this. See also linux_getgid16() and linux_getuid16() in linux_uid16.c 1456 * 1457 * linux_getpid() - MP SAFE 1458 * linux_getgid() - MP SAFE 1459 * linux_getuid() - MP SAFE 1460 */ 1461 1462int 1463linux_getpid(struct thread *td, struct linux_getpid_args *args) 1464{ 1465 struct linux_emuldata *em; 1466 1467#ifdef DEBUG 1468 if (ldebug(getpid)) 1469 printf(ARGS(getpid, "")); 1470#endif 1471 1472 if (linux_use26(td)) { 1473 em = em_find(td->td_proc, EMUL_DONTLOCK); 1474 KASSERT(em != NULL, ("getpid: emuldata not found.\n")); 1475 td->td_retval[0] = em->shared->group_pid; 1476 } else { 1477 td->td_retval[0] = td->td_proc->p_pid; 1478 } 1479 1480 return (0); 1481} 1482 1483int 1484linux_gettid(struct thread *td, struct linux_gettid_args *args) 1485{ 1486 1487#ifdef DEBUG 1488 if (ldebug(gettid)) 1489 printf(ARGS(gettid, "")); 1490#endif 1491 1492 td->td_retval[0] = td->td_proc->p_pid; 1493 return (0); 1494} 1495 1496 1497int 1498linux_getppid(struct thread *td, struct linux_getppid_args *args) 1499{ 1500 struct linux_emuldata *em; 1501 struct proc *p, *pp; 1502 1503#ifdef DEBUG 1504 if (ldebug(getppid)) 1505 printf(ARGS(getppid, "")); 1506#endif 1507 1508 if (!linux_use26(td)) { 1509 PROC_LOCK(td->td_proc); 1510 td->td_retval[0] = td->td_proc->p_pptr->p_pid; 1511 PROC_UNLOCK(td->td_proc); 1512 return (0); 1513 } 1514 1515 em = em_find(td->td_proc, EMUL_DONTLOCK); 1516 1517 KASSERT(em != NULL, ("getppid: process emuldata not found.\n")); 1518 1519 /* find the group leader */ 1520 p = pfind(em->shared->group_pid); 1521 1522 if (p == NULL) { 1523#ifdef DEBUG 1524 printf(LMSG("parent process not found.\n")); 1525#endif 1526 return (0); 1527 } 1528 1529 pp = p->p_pptr; /* switch to parent */ 1530 PROC_LOCK(pp); 1531 PROC_UNLOCK(p); 1532 1533 /* if its also linux process */ 1534 if (pp->p_sysent == &elf_linux_sysvec) { 1535 em = em_find(pp, EMUL_DONTLOCK); 1536 KASSERT(em != NULL, ("getppid: parent emuldata not found.\n")); 1537 1538 td->td_retval[0] = em->shared->group_pid; 1539 } else 1540 td->td_retval[0] = pp->p_pid; 1541 1542 PROC_UNLOCK(pp); 1543 1544 return (0); 1545} 1546 1547int 1548linux_getgid(struct thread *td, struct linux_getgid_args *args) 1549{ 1550 1551#ifdef DEBUG 1552 if (ldebug(getgid)) 1553 printf(ARGS(getgid, "")); 1554#endif 1555 1556 td->td_retval[0] = td->td_ucred->cr_rgid; 1557 return (0); 1558} 1559 1560int 1561linux_getuid(struct thread *td, struct linux_getuid_args *args) 1562{ 1563 1564#ifdef DEBUG 1565 if (ldebug(getuid)) 1566 printf(ARGS(getuid, "")); 1567#endif 1568 1569 td->td_retval[0] = td->td_ucred->cr_ruid; 1570 return (0); 1571} 1572 1573 1574int 1575linux_getsid(struct thread *td, struct linux_getsid_args *args) 1576{ 1577 struct getsid_args bsd; 1578 1579#ifdef DEBUG 1580 if (ldebug(getsid)) 1581 printf(ARGS(getsid, "%i"), args->pid); 1582#endif 1583 1584 bsd.pid = args->pid; 1585 return (sys_getsid(td, &bsd)); 1586} 1587 1588int 1589linux_nosys(struct thread *td, struct nosys_args *ignore) 1590{ 1591 1592 return (ENOSYS); 1593} 1594 1595int 1596linux_getpriority(struct thread *td, struct linux_getpriority_args *args) 1597{ 1598 struct getpriority_args bsd_args; 1599 int error; 1600 1601#ifdef DEBUG 1602 if (ldebug(getpriority)) 1603 printf(ARGS(getpriority, "%i, %i"), args->which, args->who); 1604#endif 1605 1606 bsd_args.which = args->which; 1607 bsd_args.who = args->who; 1608 error = sys_getpriority(td, &bsd_args); 1609 td->td_retval[0] = 20 - td->td_retval[0]; 1610 return (error); 1611} 1612 1613int 1614linux_sethostname(struct thread *td, struct linux_sethostname_args *args) 1615{ 1616 int name[2]; 1617 1618#ifdef DEBUG 1619 if (ldebug(sethostname)) 1620 printf(ARGS(sethostname, "*, %i"), args->len); 1621#endif 1622 1623 name[0] = CTL_KERN; 1624 name[1] = KERN_HOSTNAME; 1625 return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname, 1626 args->len, 0, 0)); 1627} 1628 1629int 1630linux_setdomainname(struct thread *td, struct linux_setdomainname_args *args) 1631{ 1632 int name[2]; 1633 1634#ifdef DEBUG 1635 if (ldebug(setdomainname)) 1636 printf(ARGS(setdomainname, "*, %i"), args->len); 1637#endif 1638 1639 name[0] = CTL_KERN; 1640 name[1] = KERN_NISDOMAINNAME; 1641 return (userland_sysctl(td, name, 2, 0, 0, 0, args->name, 1642 args->len, 0, 0)); 1643} 1644 1645int 1646linux_exit_group(struct thread *td, struct linux_exit_group_args *args) 1647{ 1648 struct linux_emuldata *em; 1649 1650#ifdef DEBUG 1651 if (ldebug(exit_group)) 1652 printf(ARGS(exit_group, "%i"), args->error_code); 1653#endif 1654 1655 em = em_find(td->td_proc, EMUL_DONTLOCK); 1656 if (em->shared->refs > 1) { 1657 EMUL_SHARED_WLOCK(&emul_shared_lock); 1658 em->shared->flags |= EMUL_SHARED_HASXSTAT; 1659 em->shared->xstat = W_EXITCODE(args->error_code, 0); 1660 EMUL_SHARED_WUNLOCK(&emul_shared_lock); 1661 if (linux_use26(td)) 1662 linux_kill_threads(td, SIGKILL); 1663 } 1664 1665 /* 1666 * XXX: we should send a signal to the parent if 1667 * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?) 1668 * as it doesnt occur often. 1669 */ 1670 exit1(td, W_EXITCODE(args->error_code, 0)); 1671 1672 return (0); 1673} 1674 1675#define _LINUX_CAPABILITY_VERSION 0x19980330 1676 1677struct l_user_cap_header { 1678 l_int version; 1679 l_int pid; 1680}; 1681 1682struct l_user_cap_data { 1683 l_int effective; 1684 l_int permitted; 1685 l_int inheritable; 1686}; 1687 1688int 1689linux_capget(struct thread *td, struct linux_capget_args *args) 1690{ 1691 struct l_user_cap_header luch; 1692 struct l_user_cap_data lucd; 1693 int error; 1694 1695 if (args->hdrp == NULL) 1696 return (EFAULT); 1697 1698 error = copyin(args->hdrp, &luch, sizeof(luch)); 1699 if (error != 0) 1700 return (error); 1701 1702 if (luch.version != _LINUX_CAPABILITY_VERSION) { 1703 luch.version = _LINUX_CAPABILITY_VERSION; 1704 error = copyout(&luch, args->hdrp, sizeof(luch)); 1705 if (error) 1706 return (error); 1707 return (EINVAL); 1708 } 1709 1710 if (luch.pid) 1711 return (EPERM); 1712 1713 if (args->datap) { 1714 /* 1715 * The current implementation doesn't support setting 1716 * a capability (it's essentially a stub) so indicate 1717 * that no capabilities are currently set or available 1718 * to request. 1719 */ 1720 bzero (&lucd, sizeof(lucd)); 1721 error = copyout(&lucd, args->datap, sizeof(lucd)); 1722 } 1723 1724 return (error); 1725} 1726 1727int 1728linux_capset(struct thread *td, struct linux_capset_args *args) 1729{ 1730 struct l_user_cap_header luch; 1731 struct l_user_cap_data lucd; 1732 int error; 1733 1734 if (args->hdrp == NULL || args->datap == NULL) 1735 return (EFAULT); 1736 1737 error = copyin(args->hdrp, &luch, sizeof(luch)); 1738 if (error != 0) 1739 return (error); 1740 1741 if (luch.version != _LINUX_CAPABILITY_VERSION) { 1742 luch.version = _LINUX_CAPABILITY_VERSION; 1743 error = copyout(&luch, args->hdrp, sizeof(luch)); 1744 if (error) 1745 return (error); 1746 return (EINVAL); 1747 } 1748 1749 if (luch.pid) 1750 return (EPERM); 1751 1752 error = copyin(args->datap, &lucd, sizeof(lucd)); 1753 if (error != 0) 1754 return (error); 1755 1756 /* We currently don't support setting any capabilities. */ 1757 if (lucd.effective || lucd.permitted || lucd.inheritable) { 1758 linux_msg(td, 1759 "capset effective=0x%x, permitted=0x%x, " 1760 "inheritable=0x%x is not implemented", 1761 (int)lucd.effective, (int)lucd.permitted, 1762 (int)lucd.inheritable); 1763 return (EPERM); 1764 } 1765 1766 return (0); 1767} 1768 1769int 1770linux_prctl(struct thread *td, struct linux_prctl_args *args) 1771{ 1772 int error = 0, max_size; 1773 struct proc *p = td->td_proc; 1774 char comm[LINUX_MAX_COMM_LEN]; 1775 struct linux_emuldata *em; 1776 int pdeath_signal; 1777 1778#ifdef DEBUG 1779 if (ldebug(prctl)) 1780 printf(ARGS(prctl, "%d, %d, %d, %d, %d"), args->option, 1781 args->arg2, args->arg3, args->arg4, args->arg5); 1782#endif 1783 1784 switch (args->option) { 1785 case LINUX_PR_SET_PDEATHSIG: 1786 if (!LINUX_SIG_VALID(args->arg2)) 1787 return (EINVAL); 1788 em = em_find(p, EMUL_DOLOCK); 1789 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1790 em->pdeath_signal = args->arg2; 1791 EMUL_UNLOCK(&emul_lock); 1792 break; 1793 case LINUX_PR_GET_PDEATHSIG: 1794 em = em_find(p, EMUL_DOLOCK); 1795 KASSERT(em != NULL, ("prctl: emuldata not found.\n")); 1796 pdeath_signal = em->pdeath_signal; 1797 EMUL_UNLOCK(&emul_lock); 1798 error = copyout(&pdeath_signal, 1799 (void *)(register_t)args->arg2, 1800 sizeof(pdeath_signal)); 1801 break; 1802 case LINUX_PR_GET_KEEPCAPS: 1803 /* 1804 * Indicate that we always clear the effective and 1805 * permitted capability sets when the user id becomes 1806 * non-zero (actually the capability sets are simply 1807 * always zero in the current implementation). 1808 */ 1809 td->td_retval[0] = 0; 1810 break; 1811 case LINUX_PR_SET_KEEPCAPS: 1812 /* 1813 * Ignore requests to keep the effective and permitted 1814 * capability sets when the user id becomes non-zero. 1815 */ 1816 break; 1817 case LINUX_PR_SET_NAME: 1818 /* 1819 * To be on the safe side we need to make sure to not 1820 * overflow the size a linux program expects. We already 1821 * do this here in the copyin, so that we don't need to 1822 * check on copyout. 1823 */ 1824 max_size = MIN(sizeof(comm), sizeof(p->p_comm)); 1825 error = copyinstr((void *)(register_t)args->arg2, comm, 1826 max_size, NULL); 1827 1828 /* Linux silently truncates the name if it is too long. */ 1829 if (error == ENAMETOOLONG) { 1830 /* 1831 * XXX: copyinstr() isn't documented to populate the 1832 * array completely, so do a copyin() to be on the 1833 * safe side. This should be changed in case 1834 * copyinstr() is changed to guarantee this. 1835 */ 1836 error = copyin((void *)(register_t)args->arg2, comm, 1837 max_size - 1); 1838 comm[max_size - 1] = '\0'; 1839 } 1840 if (error) 1841 return (error); 1842 1843 PROC_LOCK(p); 1844 strlcpy(p->p_comm, comm, sizeof(p->p_comm)); 1845 PROC_UNLOCK(p); 1846 break; 1847 case LINUX_PR_GET_NAME: 1848 PROC_LOCK(p); 1849 strlcpy(comm, p->p_comm, sizeof(comm)); 1850 PROC_UNLOCK(p); 1851 error = copyout(comm, (void *)(register_t)args->arg2, 1852 strlen(comm) + 1); 1853 break; 1854 default: 1855 error = EINVAL; 1856 break; 1857 } 1858 1859 return (error); 1860} 1861 1862/* 1863 * Get affinity of a process. 1864 */ 1865int 1866linux_sched_getaffinity(struct thread *td, 1867 struct linux_sched_getaffinity_args *args) 1868{ 1869 int error; 1870 struct cpuset_getaffinity_args cga; 1871 1872#ifdef DEBUG 1873 if (ldebug(sched_getaffinity)) 1874 printf(ARGS(sched_getaffinity, "%d, %d, *"), args->pid, 1875 args->len); 1876#endif 1877 if (args->len < sizeof(cpuset_t)) 1878 return (EINVAL); 1879 1880 cga.level = CPU_LEVEL_WHICH; 1881 cga.which = CPU_WHICH_PID; 1882 cga.id = args->pid; 1883 cga.cpusetsize = sizeof(cpuset_t); 1884 cga.mask = (cpuset_t *) args->user_mask_ptr; 1885 1886 if ((error = sys_cpuset_getaffinity(td, &cga)) == 0) 1887 td->td_retval[0] = sizeof(cpuset_t); 1888 1889 return (error); 1890} 1891 1892/* 1893 * Set affinity of a process. 1894 */ 1895int 1896linux_sched_setaffinity(struct thread *td, 1897 struct linux_sched_setaffinity_args *args) 1898{ 1899 struct cpuset_setaffinity_args csa; 1900 1901#ifdef DEBUG 1902 if (ldebug(sched_setaffinity)) 1903 printf(ARGS(sched_setaffinity, "%d, %d, *"), args->pid, 1904 args->len); 1905#endif 1906 if (args->len < sizeof(cpuset_t)) 1907 return (EINVAL); 1908 1909 csa.level = CPU_LEVEL_WHICH; 1910 csa.which = CPU_WHICH_PID; 1911 csa.id = args->pid; 1912 csa.cpusetsize = sizeof(cpuset_t); 1913 csa.mask = (cpuset_t *) args->user_mask_ptr; 1914 1915 return (sys_cpuset_setaffinity(td, &csa)); 1916}
|