aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/compat.c')
-rw-r--r--kernel/compat.c191
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
55static 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
85static 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
55asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, 113asmlinkage 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
257asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, 321asmlinkage 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
278asmlinkage long compat_sys_setrlimit(unsigned int resource, 344asmlinkage 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
686long 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
620long compat_sys_clock_getres(clockid_t which_clock, 709long 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(&current->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(&current->blocked, &current->blocked, &s);
844
845 recalc_sigpending();
846 spin_unlock_irq(&current->sighand->siglock);
847
848 timeout = schedule_timeout_interruptible(timeout);
849
850 spin_lock_irq(&current->sighand->siglock);
851 sig = dequeue_signal(current, &s, &info);
852 current->blocked = current->real_blocked;
853 siginitset(&current->real_blocked, 0);
854 recalc_sigpending();
855 }
856 }
857 spin_unlock_irq(&current->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
951asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) 1007asmlinkage 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}