diff options
Diffstat (limited to 'kernel/compat.c')
-rw-r--r-- | kernel/compat.c | 191 |
1 files changed, 103 insertions, 88 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index c9e2ec0b34a8..fc9eb093acd5 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -52,6 +52,64 @@ static int compat_put_timeval(struct compat_timeval __user *o, | |||
52 | put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0; | 52 | put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0; |
53 | } | 53 | } |
54 | 54 | ||
55 | static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp) | ||
56 | { | ||
57 | memset(txc, 0, sizeof(struct timex)); | ||
58 | |||
59 | if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) || | ||
60 | __get_user(txc->modes, &utp->modes) || | ||
61 | __get_user(txc->offset, &utp->offset) || | ||
62 | __get_user(txc->freq, &utp->freq) || | ||
63 | __get_user(txc->maxerror, &utp->maxerror) || | ||
64 | __get_user(txc->esterror, &utp->esterror) || | ||
65 | __get_user(txc->status, &utp->status) || | ||
66 | __get_user(txc->constant, &utp->constant) || | ||
67 | __get_user(txc->precision, &utp->precision) || | ||
68 | __get_user(txc->tolerance, &utp->tolerance) || | ||
69 | __get_user(txc->time.tv_sec, &utp->time.tv_sec) || | ||
70 | __get_user(txc->time.tv_usec, &utp->time.tv_usec) || | ||
71 | __get_user(txc->tick, &utp->tick) || | ||
72 | __get_user(txc->ppsfreq, &utp->ppsfreq) || | ||
73 | __get_user(txc->jitter, &utp->jitter) || | ||
74 | __get_user(txc->shift, &utp->shift) || | ||
75 | __get_user(txc->stabil, &utp->stabil) || | ||
76 | __get_user(txc->jitcnt, &utp->jitcnt) || | ||
77 | __get_user(txc->calcnt, &utp->calcnt) || | ||
78 | __get_user(txc->errcnt, &utp->errcnt) || | ||
79 | __get_user(txc->stbcnt, &utp->stbcnt)) | ||
80 | return -EFAULT; | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc) | ||
86 | { | ||
87 | if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) || | ||
88 | __put_user(txc->modes, &utp->modes) || | ||
89 | __put_user(txc->offset, &utp->offset) || | ||
90 | __put_user(txc->freq, &utp->freq) || | ||
91 | __put_user(txc->maxerror, &utp->maxerror) || | ||
92 | __put_user(txc->esterror, &utp->esterror) || | ||
93 | __put_user(txc->status, &utp->status) || | ||
94 | __put_user(txc->constant, &utp->constant) || | ||
95 | __put_user(txc->precision, &utp->precision) || | ||
96 | __put_user(txc->tolerance, &utp->tolerance) || | ||
97 | __put_user(txc->time.tv_sec, &utp->time.tv_sec) || | ||
98 | __put_user(txc->time.tv_usec, &utp->time.tv_usec) || | ||
99 | __put_user(txc->tick, &utp->tick) || | ||
100 | __put_user(txc->ppsfreq, &utp->ppsfreq) || | ||
101 | __put_user(txc->jitter, &utp->jitter) || | ||
102 | __put_user(txc->shift, &utp->shift) || | ||
103 | __put_user(txc->stabil, &utp->stabil) || | ||
104 | __put_user(txc->jitcnt, &utp->jitcnt) || | ||
105 | __put_user(txc->calcnt, &utp->calcnt) || | ||
106 | __put_user(txc->errcnt, &utp->errcnt) || | ||
107 | __put_user(txc->stbcnt, &utp->stbcnt) || | ||
108 | __put_user(txc->tai, &utp->tai)) | ||
109 | return -EFAULT; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
55 | asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, | 113 | asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, |
56 | struct timezone __user *tz) | 114 | struct timezone __user *tz) |
57 | { | 115 | { |
@@ -235,6 +293,8 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) | |||
235 | return compat_jiffies_to_clock_t(jiffies); | 293 | return compat_jiffies_to_clock_t(jiffies); |
236 | } | 294 | } |
237 | 295 | ||
296 | #ifdef __ARCH_WANT_SYS_SIGPENDING | ||
297 | |||
238 | /* | 298 | /* |
239 | * Assumption: old_sigset_t and compat_old_sigset_t are both | 299 | * Assumption: old_sigset_t and compat_old_sigset_t are both |
240 | * types that can be passed to put_user()/get_user(). | 300 | * types that can be passed to put_user()/get_user(). |
@@ -254,6 +314,10 @@ asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set) | |||
254 | return ret; | 314 | return ret; |
255 | } | 315 | } |
256 | 316 | ||
317 | #endif | ||
318 | |||
319 | #ifdef __ARCH_WANT_SYS_SIGPROCMASK | ||
320 | |||
257 | asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, | 321 | asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, |
258 | compat_old_sigset_t __user *oset) | 322 | compat_old_sigset_t __user *oset) |
259 | { | 323 | { |
@@ -275,6 +339,8 @@ asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, | |||
275 | return ret; | 339 | return ret; |
276 | } | 340 | } |
277 | 341 | ||
342 | #endif | ||
343 | |||
278 | asmlinkage long compat_sys_setrlimit(unsigned int resource, | 344 | asmlinkage long compat_sys_setrlimit(unsigned int resource, |
279 | struct compat_rlimit __user *rlim) | 345 | struct compat_rlimit __user *rlim) |
280 | { | 346 | { |
@@ -617,6 +683,29 @@ long compat_sys_clock_gettime(clockid_t which_clock, | |||
617 | return err; | 683 | return err; |
618 | } | 684 | } |
619 | 685 | ||
686 | long compat_sys_clock_adjtime(clockid_t which_clock, | ||
687 | struct compat_timex __user *utp) | ||
688 | { | ||
689 | struct timex txc; | ||
690 | mm_segment_t oldfs; | ||
691 | int err, ret; | ||
692 | |||
693 | err = compat_get_timex(&txc, utp); | ||
694 | if (err) | ||
695 | return err; | ||
696 | |||
697 | oldfs = get_fs(); | ||
698 | set_fs(KERNEL_DS); | ||
699 | ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc); | ||
700 | set_fs(oldfs); | ||
701 | |||
702 | err = compat_put_timex(utp, &txc); | ||
703 | if (err) | ||
704 | return err; | ||
705 | |||
706 | return ret; | ||
707 | } | ||
708 | |||
620 | long compat_sys_clock_getres(clockid_t which_clock, | 709 | long compat_sys_clock_getres(clockid_t which_clock, |
621 | struct compat_timespec __user *tp) | 710 | struct compat_timespec __user *tp) |
622 | { | 711 | { |
@@ -809,10 +898,9 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
809 | { | 898 | { |
810 | compat_sigset_t s32; | 899 | compat_sigset_t s32; |
811 | sigset_t s; | 900 | sigset_t s; |
812 | int sig; | ||
813 | struct timespec t; | 901 | struct timespec t; |
814 | siginfo_t info; | 902 | siginfo_t info; |
815 | long ret, timeout = 0; | 903 | long ret; |
816 | 904 | ||
817 | if (sigsetsize != sizeof(sigset_t)) | 905 | if (sigsetsize != sizeof(sigset_t)) |
818 | return -EINVAL; | 906 | return -EINVAL; |
@@ -820,51 +908,19 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
820 | if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) | 908 | if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) |
821 | return -EFAULT; | 909 | return -EFAULT; |
822 | sigset_from_compat(&s, &s32); | 910 | sigset_from_compat(&s, &s32); |
823 | sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
824 | signotset(&s); | ||
825 | 911 | ||
826 | if (uts) { | 912 | if (uts) { |
827 | if (get_compat_timespec (&t, uts)) | 913 | if (get_compat_timespec(&t, uts)) |
828 | return -EFAULT; | 914 | return -EFAULT; |
829 | if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0 | ||
830 | || t.tv_sec < 0) | ||
831 | return -EINVAL; | ||
832 | } | 915 | } |
833 | 916 | ||
834 | spin_lock_irq(¤t->sighand->siglock); | 917 | ret = do_sigtimedwait(&s, &info, uts ? &t : NULL); |
835 | sig = dequeue_signal(current, &s, &info); | ||
836 | if (!sig) { | ||
837 | timeout = MAX_SCHEDULE_TIMEOUT; | ||
838 | if (uts) | ||
839 | timeout = timespec_to_jiffies(&t) | ||
840 | +(t.tv_sec || t.tv_nsec); | ||
841 | if (timeout) { | ||
842 | current->real_blocked = current->blocked; | ||
843 | sigandsets(¤t->blocked, ¤t->blocked, &s); | ||
844 | |||
845 | recalc_sigpending(); | ||
846 | spin_unlock_irq(¤t->sighand->siglock); | ||
847 | |||
848 | timeout = schedule_timeout_interruptible(timeout); | ||
849 | |||
850 | spin_lock_irq(¤t->sighand->siglock); | ||
851 | sig = dequeue_signal(current, &s, &info); | ||
852 | current->blocked = current->real_blocked; | ||
853 | siginitset(¤t->real_blocked, 0); | ||
854 | recalc_sigpending(); | ||
855 | } | ||
856 | } | ||
857 | spin_unlock_irq(¤t->sighand->siglock); | ||
858 | 918 | ||
859 | if (sig) { | 919 | if (ret > 0 && uinfo) { |
860 | ret = sig; | 920 | if (copy_siginfo_to_user32(uinfo, &info)) |
861 | if (uinfo) { | 921 | ret = -EFAULT; |
862 | if (copy_siginfo_to_user32(uinfo, &info)) | ||
863 | ret = -EFAULT; | ||
864 | } | ||
865 | }else { | ||
866 | ret = timeout?-EINTR:-EAGAIN; | ||
867 | } | 922 | } |
923 | |||
868 | return ret; | 924 | return ret; |
869 | 925 | ||
870 | } | 926 | } |
@@ -951,58 +1007,17 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat | |||
951 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) | 1007 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) |
952 | { | 1008 | { |
953 | struct timex txc; | 1009 | struct timex txc; |
954 | int ret; | 1010 | int err, ret; |
955 | |||
956 | memset(&txc, 0, sizeof(struct timex)); | ||
957 | 1011 | ||
958 | if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) || | 1012 | err = compat_get_timex(&txc, utp); |
959 | __get_user(txc.modes, &utp->modes) || | 1013 | if (err) |
960 | __get_user(txc.offset, &utp->offset) || | 1014 | return err; |
961 | __get_user(txc.freq, &utp->freq) || | ||
962 | __get_user(txc.maxerror, &utp->maxerror) || | ||
963 | __get_user(txc.esterror, &utp->esterror) || | ||
964 | __get_user(txc.status, &utp->status) || | ||
965 | __get_user(txc.constant, &utp->constant) || | ||
966 | __get_user(txc.precision, &utp->precision) || | ||
967 | __get_user(txc.tolerance, &utp->tolerance) || | ||
968 | __get_user(txc.time.tv_sec, &utp->time.tv_sec) || | ||
969 | __get_user(txc.time.tv_usec, &utp->time.tv_usec) || | ||
970 | __get_user(txc.tick, &utp->tick) || | ||
971 | __get_user(txc.ppsfreq, &utp->ppsfreq) || | ||
972 | __get_user(txc.jitter, &utp->jitter) || | ||
973 | __get_user(txc.shift, &utp->shift) || | ||
974 | __get_user(txc.stabil, &utp->stabil) || | ||
975 | __get_user(txc.jitcnt, &utp->jitcnt) || | ||
976 | __get_user(txc.calcnt, &utp->calcnt) || | ||
977 | __get_user(txc.errcnt, &utp->errcnt) || | ||
978 | __get_user(txc.stbcnt, &utp->stbcnt)) | ||
979 | return -EFAULT; | ||
980 | 1015 | ||
981 | ret = do_adjtimex(&txc); | 1016 | ret = do_adjtimex(&txc); |
982 | 1017 | ||
983 | if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) || | 1018 | err = compat_put_timex(utp, &txc); |
984 | __put_user(txc.modes, &utp->modes) || | 1019 | if (err) |
985 | __put_user(txc.offset, &utp->offset) || | 1020 | return err; |
986 | __put_user(txc.freq, &utp->freq) || | ||
987 | __put_user(txc.maxerror, &utp->maxerror) || | ||
988 | __put_user(txc.esterror, &utp->esterror) || | ||
989 | __put_user(txc.status, &utp->status) || | ||
990 | __put_user(txc.constant, &utp->constant) || | ||
991 | __put_user(txc.precision, &utp->precision) || | ||
992 | __put_user(txc.tolerance, &utp->tolerance) || | ||
993 | __put_user(txc.time.tv_sec, &utp->time.tv_sec) || | ||
994 | __put_user(txc.time.tv_usec, &utp->time.tv_usec) || | ||
995 | __put_user(txc.tick, &utp->tick) || | ||
996 | __put_user(txc.ppsfreq, &utp->ppsfreq) || | ||
997 | __put_user(txc.jitter, &utp->jitter) || | ||
998 | __put_user(txc.shift, &utp->shift) || | ||
999 | __put_user(txc.stabil, &utp->stabil) || | ||
1000 | __put_user(txc.jitcnt, &utp->jitcnt) || | ||
1001 | __put_user(txc.calcnt, &utp->calcnt) || | ||
1002 | __put_user(txc.errcnt, &utp->errcnt) || | ||
1003 | __put_user(txc.stbcnt, &utp->stbcnt) || | ||
1004 | __put_user(txc.tai, &utp->tai)) | ||
1005 | ret = -EFAULT; | ||
1006 | 1021 | ||
1007 | return ret; | 1022 | return ret; |
1008 | } | 1023 | } |