···4343#include <linux/security.h>4444#include <linux/highmem.h>4545#include <linux/signal.h>4646-#include <linux/poll.h>4746#include <linux/mm.h>4847#include <linux/fs_struct.h>4948#include <linux/slab.h>···922923COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)923924{924925 return do_sys_open(dfd, filename, flags, mode);925925-}926926-927927-#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))928928-929929-static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,930930- int timeval, int ret)931931-{932932- struct timespec ts;933933-934934- if (!p)935935- return ret;936936-937937- if (current->personality & STICKY_TIMEOUTS)938938- goto sticky;939939-940940- /* No update for zero timeout */941941- if (!end_time->tv_sec && !end_time->tv_nsec)942942- return ret;943943-944944- ktime_get_ts(&ts);945945- ts = timespec_sub(*end_time, ts);946946- if (ts.tv_sec < 0)947947- ts.tv_sec = ts.tv_nsec = 0;948948-949949- if (timeval) {950950- struct compat_timeval rtv;951951-952952- rtv.tv_sec = ts.tv_sec;953953- rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;954954-955955- if (!copy_to_user(p, &rtv, sizeof(rtv)))956956- return ret;957957- } else {958958- struct compat_timespec rts;959959-960960- rts.tv_sec = ts.tv_sec;961961- rts.tv_nsec = ts.tv_nsec;962962-963963- if (!copy_to_user(p, &rts, sizeof(rts)))964964- return ret;965965- }966966- /*967967- * If an application puts its timeval in read-only memory, we968968- * don't want the Linux-specific update to the timeval to969969- * cause a fault after the select has completed970970- * successfully. However, because we're not updating the971971- * timeval, we can't restart the system call.972972- */973973-974974-sticky:975975- if (ret == -ERESTARTNOHAND)976976- ret = -EINTR;977977- return ret;978978-}979979-980980-/*981981- * Ooo, nasty. We need here to frob 32-bit unsigned longs to982982- * 64-bit unsigned longs.983983- */984984-static985985-int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,986986- unsigned long *fdset)987987-{988988- nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);989989- if (ufdset) {990990- unsigned long odd;991991-992992- if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))993993- return -EFAULT;994994-995995- odd = nr & 1UL;996996- nr &= ~1UL;997997- while (nr) {998998- unsigned long h, l;999999- if (__get_user(l, ufdset) || __get_user(h, ufdset+1))10001000- return -EFAULT;10011001- ufdset += 2;10021002- *fdset++ = h << 32 | l;10031003- nr -= 2;10041004- }10051005- if (odd && __get_user(*fdset, ufdset))10061006- return -EFAULT;10071007- } else {10081008- /* Tricky, must clear full unsigned long in the10091009- * kernel fdset at the end, this makes sure that10101010- * actually happens.10111011- */10121012- memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));10131013- }10141014- return 0;10151015-}10161016-10171017-static10181018-int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,10191019- unsigned long *fdset)10201020-{10211021- unsigned long odd;10221022- nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);10231023-10241024- if (!ufdset)10251025- return 0;10261026-10271027- odd = nr & 1UL;10281028- nr &= ~1UL;10291029- while (nr) {10301030- unsigned long h, l;10311031- l = *fdset++;10321032- h = l >> 32;10331033- if (__put_user(l, ufdset) || __put_user(h, ufdset+1))10341034- return -EFAULT;10351035- ufdset += 2;10361036- nr -= 2;10371037- }10381038- if (odd && __put_user(*fdset, ufdset))10391039- return -EFAULT;10401040- return 0;10411041-}10421042-10431043-10441044-/*10451045- * This is a virtual copy of sys_select from fs/select.c and probably10461046- * should be compared to it from time to time10471047- */10481048-10491049-/*10501050- * We can actually return ERESTARTSYS instead of EINTR, but I'd10511051- * like to be certain this leads to no problems. So I return10521052- * EINTR just for safety.10531053- *10541054- * Update: ERESTARTSYS breaks at least the xview clock binary, so10551055- * I'm trying ERESTARTNOHAND which restart only when you want to.10561056- */10571057-int compat_core_sys_select(int n, compat_ulong_t __user *inp,10581058- compat_ulong_t __user *outp, compat_ulong_t __user *exp,10591059- struct timespec *end_time)10601060-{10611061- fd_set_bits fds;10621062- void *bits;10631063- int size, max_fds, ret = -EINVAL;10641064- struct fdtable *fdt;10651065- long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];10661066-10671067- if (n < 0)10681068- goto out_nofds;10691069-10701070- /* max_fds can increase, so grab it once to avoid race */10711071- rcu_read_lock();10721072- fdt = files_fdtable(current->files);10731073- max_fds = fdt->max_fds;10741074- rcu_read_unlock();10751075- if (n > max_fds)10761076- n = max_fds;10771077-10781078- /*10791079- * We need 6 bitmaps (in/out/ex for both incoming and outgoing),10801080- * since we used fdset we need to allocate memory in units of10811081- * long-words.10821082- */10831083- size = FDS_BYTES(n);10841084- bits = stack_fds;10851085- if (size > sizeof(stack_fds) / 6) {10861086- bits = kmalloc(6 * size, GFP_KERNEL);10871087- ret = -ENOMEM;10881088- if (!bits)10891089- goto out_nofds;10901090- }10911091- fds.in = (unsigned long *) bits;10921092- fds.out = (unsigned long *) (bits + size);10931093- fds.ex = (unsigned long *) (bits + 2*size);10941094- fds.res_in = (unsigned long *) (bits + 3*size);10951095- fds.res_out = (unsigned long *) (bits + 4*size);10961096- fds.res_ex = (unsigned long *) (bits + 5*size);10971097-10981098- if ((ret = compat_get_fd_set(n, inp, fds.in)) ||10991099- (ret = compat_get_fd_set(n, outp, fds.out)) ||11001100- (ret = compat_get_fd_set(n, exp, fds.ex)))11011101- goto out;11021102- zero_fd_set(n, fds.res_in);11031103- zero_fd_set(n, fds.res_out);11041104- zero_fd_set(n, fds.res_ex);11051105-11061106- ret = do_select(n, &fds, end_time);11071107-11081108- if (ret < 0)11091109- goto out;11101110- if (!ret) {11111111- ret = -ERESTARTNOHAND;11121112- if (signal_pending(current))11131113- goto out;11141114- ret = 0;11151115- }11161116-11171117- if (compat_set_fd_set(n, inp, fds.res_in) ||11181118- compat_set_fd_set(n, outp, fds.res_out) ||11191119- compat_set_fd_set(n, exp, fds.res_ex))11201120- ret = -EFAULT;11211121-out:11221122- if (bits != stack_fds)11231123- kfree(bits);11241124-out_nofds:11251125- return ret;11261126-}11271127-11281128-COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,11291129- compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,11301130- struct compat_timeval __user *, tvp)11311131-{11321132- struct timespec end_time, *to = NULL;11331133- struct compat_timeval tv;11341134- int ret;11351135-11361136- if (tvp) {11371137- if (copy_from_user(&tv, tvp, sizeof(tv)))11381138- return -EFAULT;11391139-11401140- to = &end_time;11411141- if (poll_select_set_timeout(to,11421142- tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),11431143- (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))11441144- return -EINVAL;11451145- }11461146-11471147- ret = compat_core_sys_select(n, inp, outp, exp, to);11481148- ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);11491149-11501150- return ret;11511151-}11521152-11531153-struct compat_sel_arg_struct {11541154- compat_ulong_t n;11551155- compat_uptr_t inp;11561156- compat_uptr_t outp;11571157- compat_uptr_t exp;11581158- compat_uptr_t tvp;11591159-};11601160-11611161-COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)11621162-{11631163- struct compat_sel_arg_struct a;11641164-11651165- if (copy_from_user(&a, arg, sizeof(a)))11661166- return -EFAULT;11671167- return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),11681168- compat_ptr(a.exp), compat_ptr(a.tvp));11691169-}11701170-11711171-static long do_compat_pselect(int n, compat_ulong_t __user *inp,11721172- compat_ulong_t __user *outp, compat_ulong_t __user *exp,11731173- struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,11741174- compat_size_t sigsetsize)11751175-{11761176- compat_sigset_t ss32;11771177- sigset_t ksigmask, sigsaved;11781178- struct compat_timespec ts;11791179- struct timespec end_time, *to = NULL;11801180- int ret;11811181-11821182- if (tsp) {11831183- if (copy_from_user(&ts, tsp, sizeof(ts)))11841184- return -EFAULT;11851185-11861186- to = &end_time;11871187- if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))11881188- return -EINVAL;11891189- }11901190-11911191- if (sigmask) {11921192- if (sigsetsize != sizeof(compat_sigset_t))11931193- return -EINVAL;11941194- if (copy_from_user(&ss32, sigmask, sizeof(ss32)))11951195- return -EFAULT;11961196- sigset_from_compat(&ksigmask, &ss32);11971197-11981198- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));11991199- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);12001200- }12011201-12021202- ret = compat_core_sys_select(n, inp, outp, exp, to);12031203- ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);12041204-12051205- if (ret == -ERESTARTNOHAND) {12061206- /*12071207- * Don't restore the signal mask yet. Let do_signal() deliver12081208- * the signal on the way back to userspace, before the signal12091209- * mask is restored.12101210- */12111211- if (sigmask) {12121212- memcpy(¤t->saved_sigmask, &sigsaved,12131213- sizeof(sigsaved));12141214- set_restore_sigmask();12151215- }12161216- } else if (sigmask)12171217- sigprocmask(SIG_SETMASK, &sigsaved, NULL);12181218-12191219- return ret;12201220-}12211221-12221222-COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,12231223- compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,12241224- struct compat_timespec __user *, tsp, void __user *, sig)12251225-{12261226- compat_size_t sigsetsize = 0;12271227- compat_uptr_t up = 0;12281228-12291229- if (sig) {12301230- if (!access_ok(VERIFY_READ, sig,12311231- sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||12321232- __get_user(up, (compat_uptr_t __user *)sig) ||12331233- __get_user(sigsetsize,12341234- (compat_size_t __user *)(sig+sizeof(up))))12351235- return -EFAULT;12361236- }12371237- return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),12381238- sigsetsize);12391239-}12401240-12411241-COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,12421242- unsigned int, nfds, struct compat_timespec __user *, tsp,12431243- const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)12441244-{12451245- compat_sigset_t ss32;12461246- sigset_t ksigmask, sigsaved;12471247- struct compat_timespec ts;12481248- struct timespec end_time, *to = NULL;12491249- int ret;12501250-12511251- if (tsp) {12521252- if (copy_from_user(&ts, tsp, sizeof(ts)))12531253- return -EFAULT;12541254-12551255- to = &end_time;12561256- if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))12571257- return -EINVAL;12581258- }12591259-12601260- if (sigmask) {12611261- if (sigsetsize != sizeof(compat_sigset_t))12621262- return -EINVAL;12631263- if (copy_from_user(&ss32, sigmask, sizeof(ss32)))12641264- return -EFAULT;12651265- sigset_from_compat(&ksigmask, &ss32);12661266-12671267- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));12681268- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);12691269- }12701270-12711271- ret = do_sys_poll(ufds, nfds, to);12721272-12731273- /* We can restart this syscall, usually */12741274- if (ret == -EINTR) {12751275- /*12761276- * Don't restore the signal mask yet. Let do_signal() deliver12771277- * the signal on the way back to userspace, before the signal12781278- * mask is restored.12791279- */12801280- if (sigmask) {12811281- memcpy(¤t->saved_sigmask, &sigsaved,12821282- sizeof(sigsaved));12831283- set_restore_sigmask();12841284- }12851285- ret = -ERESTARTNOHAND;12861286- } else if (sigmask)12871287- sigprocmask(SIG_SETMASK, &sigsaved, NULL);12881288-12891289- ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);12901290-12911291- return ret;1292926}12939271294928#ifdef CONFIG_FHANDLE
+419-2
fs/select.c
···338338 return ret;339339}340340341341+/*342342+ * Scalable version of the fd_set.343343+ */344344+345345+typedef struct {346346+ unsigned long *in, *out, *ex;347347+ unsigned long *res_in, *res_out, *res_ex;348348+} fd_set_bits;349349+350350+/*351351+ * How many longwords for "nr" bits?352352+ */353353+#define FDS_BITPERLONG (8*sizeof(long))354354+#define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)355355+#define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long))356356+357357+/*358358+ * We do a VERIFY_WRITE here even though we are only reading this time:359359+ * we'll write to it eventually..360360+ *361361+ * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.362362+ */363363+static inline364364+int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)365365+{366366+ nr = FDS_BYTES(nr);367367+ if (ufdset)368368+ return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0;369369+370370+ memset(fdset, 0, nr);371371+ return 0;372372+}373373+374374+static inline unsigned long __must_check375375+set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)376376+{377377+ if (ufdset)378378+ return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));379379+ return 0;380380+}381381+382382+static inline383383+void zero_fd_set(unsigned long nr, unsigned long *fdset)384384+{385385+ memset(fdset, 0, FDS_BYTES(nr));386386+}387387+341388#define FDS_IN(fds, n) (fds->in + n)342389#define FDS_OUT(fds, n) (fds->out + n)343390#define FDS_EX(fds, n) (fds->ex + n)···448401 wait->_key |= POLLOUT_SET;449402}450403451451-int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)404404+static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)452405{453406 ktime_t expire, *to = NULL;454407 struct poll_wqueues table;···928881#define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \929882 sizeof(struct pollfd))930883931931-int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,884884+static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,932885 struct timespec64 *end_time)933886{934887 struct poll_wqueues table;···1100105311011054 return ret;11021055}10561056+10571057+#ifdef CONFIG_COMPAT10581058+#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))10591059+10601060+static10611061+int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p,10621062+ int timeval, int ret)10631063+{10641064+ struct timespec ts;10651065+10661066+ if (!p)10671067+ return ret;10681068+10691069+ if (current->personality & STICKY_TIMEOUTS)10701070+ goto sticky;10711071+10721072+ /* No update for zero timeout */10731073+ if (!end_time->tv_sec && !end_time->tv_nsec)10741074+ return ret;10751075+10761076+ ktime_get_ts(&ts);10771077+ ts = timespec_sub(*end_time, ts);10781078+ if (ts.tv_sec < 0)10791079+ ts.tv_sec = ts.tv_nsec = 0;10801080+10811081+ if (timeval) {10821082+ struct compat_timeval rtv;10831083+10841084+ rtv.tv_sec = ts.tv_sec;10851085+ rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;10861086+10871087+ if (!copy_to_user(p, &rtv, sizeof(rtv)))10881088+ return ret;10891089+ } else {10901090+ struct compat_timespec rts;10911091+10921092+ rts.tv_sec = ts.tv_sec;10931093+ rts.tv_nsec = ts.tv_nsec;10941094+10951095+ if (!copy_to_user(p, &rts, sizeof(rts)))10961096+ return ret;10971097+ }10981098+ /*10991099+ * If an application puts its timeval in read-only memory, we11001100+ * don't want the Linux-specific update to the timeval to11011101+ * cause a fault after the select has completed11021102+ * successfully. However, because we're not updating the11031103+ * timeval, we can't restart the system call.11041104+ */11051105+11061106+sticky:11071107+ if (ret == -ERESTARTNOHAND)11081108+ ret = -EINTR;11091109+ return ret;11101110+}11111111+11121112+/*11131113+ * Ooo, nasty. We need here to frob 32-bit unsigned longs to11141114+ * 64-bit unsigned longs.11151115+ */11161116+static11171117+int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,11181118+ unsigned long *fdset)11191119+{11201120+ nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);11211121+ if (ufdset) {11221122+ unsigned long odd;11231123+11241124+ if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))11251125+ return -EFAULT;11261126+11271127+ odd = nr & 1UL;11281128+ nr &= ~1UL;11291129+ while (nr) {11301130+ unsigned long h, l;11311131+ if (__get_user(l, ufdset) || __get_user(h, ufdset+1))11321132+ return -EFAULT;11331133+ ufdset += 2;11341134+ *fdset++ = h << 32 | l;11351135+ nr -= 2;11361136+ }11371137+ if (odd && __get_user(*fdset, ufdset))11381138+ return -EFAULT;11391139+ } else {11401140+ /* Tricky, must clear full unsigned long in the11411141+ * kernel fdset at the end, this makes sure that11421142+ * actually happens.11431143+ */11441144+ memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));11451145+ }11461146+ return 0;11471147+}11481148+11491149+static11501150+int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,11511151+ unsigned long *fdset)11521152+{11531153+ unsigned long odd;11541154+ nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);11551155+11561156+ if (!ufdset)11571157+ return 0;11581158+11591159+ odd = nr & 1UL;11601160+ nr &= ~1UL;11611161+ while (nr) {11621162+ unsigned long h, l;11631163+ l = *fdset++;11641164+ h = l >> 32;11651165+ if (__put_user(l, ufdset) || __put_user(h, ufdset+1))11661166+ return -EFAULT;11671167+ ufdset += 2;11681168+ nr -= 2;11691169+ }11701170+ if (odd && __put_user(*fdset, ufdset))11711171+ return -EFAULT;11721172+ return 0;11731173+}11741174+11751175+11761176+/*11771177+ * This is a virtual copy of sys_select from fs/select.c and probably11781178+ * should be compared to it from time to time11791179+ */11801180+11811181+/*11821182+ * We can actually return ERESTARTSYS instead of EINTR, but I'd11831183+ * like to be certain this leads to no problems. So I return11841184+ * EINTR just for safety.11851185+ *11861186+ * Update: ERESTARTSYS breaks at least the xview clock binary, so11871187+ * I'm trying ERESTARTNOHAND which restart only when you want to.11881188+ */11891189+static int compat_core_sys_select(int n, compat_ulong_t __user *inp,11901190+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,11911191+ struct timespec *end_time)11921192+{11931193+ fd_set_bits fds;11941194+ void *bits;11951195+ int size, max_fds, ret = -EINVAL;11961196+ struct fdtable *fdt;11971197+ long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];11981198+11991199+ if (n < 0)12001200+ goto out_nofds;12011201+12021202+ /* max_fds can increase, so grab it once to avoid race */12031203+ rcu_read_lock();12041204+ fdt = files_fdtable(current->files);12051205+ max_fds = fdt->max_fds;12061206+ rcu_read_unlock();12071207+ if (n > max_fds)12081208+ n = max_fds;12091209+12101210+ /*12111211+ * We need 6 bitmaps (in/out/ex for both incoming and outgoing),12121212+ * since we used fdset we need to allocate memory in units of12131213+ * long-words.12141214+ */12151215+ size = FDS_BYTES(n);12161216+ bits = stack_fds;12171217+ if (size > sizeof(stack_fds) / 6) {12181218+ bits = kmalloc(6 * size, GFP_KERNEL);12191219+ ret = -ENOMEM;12201220+ if (!bits)12211221+ goto out_nofds;12221222+ }12231223+ fds.in = (unsigned long *) bits;12241224+ fds.out = (unsigned long *) (bits + size);12251225+ fds.ex = (unsigned long *) (bits + 2*size);12261226+ fds.res_in = (unsigned long *) (bits + 3*size);12271227+ fds.res_out = (unsigned long *) (bits + 4*size);12281228+ fds.res_ex = (unsigned long *) (bits + 5*size);12291229+12301230+ if ((ret = compat_get_fd_set(n, inp, fds.in)) ||12311231+ (ret = compat_get_fd_set(n, outp, fds.out)) ||12321232+ (ret = compat_get_fd_set(n, exp, fds.ex)))12331233+ goto out;12341234+ zero_fd_set(n, fds.res_in);12351235+ zero_fd_set(n, fds.res_out);12361236+ zero_fd_set(n, fds.res_ex);12371237+12381238+ ret = do_select(n, &fds, end_time);12391239+12401240+ if (ret < 0)12411241+ goto out;12421242+ if (!ret) {12431243+ ret = -ERESTARTNOHAND;12441244+ if (signal_pending(current))12451245+ goto out;12461246+ ret = 0;12471247+ }12481248+12491249+ if (compat_set_fd_set(n, inp, fds.res_in) ||12501250+ compat_set_fd_set(n, outp, fds.res_out) ||12511251+ compat_set_fd_set(n, exp, fds.res_ex))12521252+ ret = -EFAULT;12531253+out:12541254+ if (bits != stack_fds)12551255+ kfree(bits);12561256+out_nofds:12571257+ return ret;12581258+}12591259+12601260+COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,12611261+ compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,12621262+ struct compat_timeval __user *, tvp)12631263+{12641264+ struct timespec end_time, *to = NULL;12651265+ struct compat_timeval tv;12661266+ int ret;12671267+12681268+ if (tvp) {12691269+ if (copy_from_user(&tv, tvp, sizeof(tv)))12701270+ return -EFAULT;12711271+12721272+ to = &end_time;12731273+ if (poll_select_set_timeout(to,12741274+ tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),12751275+ (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))12761276+ return -EINVAL;12771277+ }12781278+12791279+ ret = compat_core_sys_select(n, inp, outp, exp, to);12801280+ ret = compat_poll_select_copy_remaining(&end_time, tvp, 1, ret);12811281+12821282+ return ret;12831283+}12841284+12851285+struct compat_sel_arg_struct {12861286+ compat_ulong_t n;12871287+ compat_uptr_t inp;12881288+ compat_uptr_t outp;12891289+ compat_uptr_t exp;12901290+ compat_uptr_t tvp;12911291+};12921292+12931293+COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)12941294+{12951295+ struct compat_sel_arg_struct a;12961296+12971297+ if (copy_from_user(&a, arg, sizeof(a)))12981298+ return -EFAULT;12991299+ return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),13001300+ compat_ptr(a.exp), compat_ptr(a.tvp));13011301+}13021302+13031303+static long do_compat_pselect(int n, compat_ulong_t __user *inp,13041304+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,13051305+ struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,13061306+ compat_size_t sigsetsize)13071307+{13081308+ compat_sigset_t ss32;13091309+ sigset_t ksigmask, sigsaved;13101310+ struct compat_timespec ts;13111311+ struct timespec end_time, *to = NULL;13121312+ int ret;13131313+13141314+ if (tsp) {13151315+ if (copy_from_user(&ts, tsp, sizeof(ts)))13161316+ return -EFAULT;13171317+13181318+ to = &end_time;13191319+ if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))13201320+ return -EINVAL;13211321+ }13221322+13231323+ if (sigmask) {13241324+ if (sigsetsize != sizeof(compat_sigset_t))13251325+ return -EINVAL;13261326+ if (copy_from_user(&ss32, sigmask, sizeof(ss32)))13271327+ return -EFAULT;13281328+ sigset_from_compat(&ksigmask, &ss32);13291329+13301330+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));13311331+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);13321332+ }13331333+13341334+ ret = compat_core_sys_select(n, inp, outp, exp, to);13351335+ ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);13361336+13371337+ if (ret == -ERESTARTNOHAND) {13381338+ /*13391339+ * Don't restore the signal mask yet. Let do_signal() deliver13401340+ * the signal on the way back to userspace, before the signal13411341+ * mask is restored.13421342+ */13431343+ if (sigmask) {13441344+ memcpy(¤t->saved_sigmask, &sigsaved,13451345+ sizeof(sigsaved));13461346+ set_restore_sigmask();13471347+ }13481348+ } else if (sigmask)13491349+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);13501350+13511351+ return ret;13521352+}13531353+13541354+COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,13551355+ compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,13561356+ struct compat_timespec __user *, tsp, void __user *, sig)13571357+{13581358+ compat_size_t sigsetsize = 0;13591359+ compat_uptr_t up = 0;13601360+13611361+ if (sig) {13621362+ if (!access_ok(VERIFY_READ, sig,13631363+ sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||13641364+ __get_user(up, (compat_uptr_t __user *)sig) ||13651365+ __get_user(sigsetsize,13661366+ (compat_size_t __user *)(sig+sizeof(up))))13671367+ return -EFAULT;13681368+ }13691369+ return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),13701370+ sigsetsize);13711371+}13721372+13731373+COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,13741374+ unsigned int, nfds, struct compat_timespec __user *, tsp,13751375+ const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)13761376+{13771377+ compat_sigset_t ss32;13781378+ sigset_t ksigmask, sigsaved;13791379+ struct compat_timespec ts;13801380+ struct timespec end_time, *to = NULL;13811381+ int ret;13821382+13831383+ if (tsp) {13841384+ if (copy_from_user(&ts, tsp, sizeof(ts)))13851385+ return -EFAULT;13861386+13871387+ to = &end_time;13881388+ if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))13891389+ return -EINVAL;13901390+ }13911391+13921392+ if (sigmask) {13931393+ if (sigsetsize != sizeof(compat_sigset_t))13941394+ return -EINVAL;13951395+ if (copy_from_user(&ss32, sigmask, sizeof(ss32)))13961396+ return -EFAULT;13971397+ sigset_from_compat(&ksigmask, &ss32);13981398+13991399+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));14001400+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);14011401+ }14021402+14031403+ ret = do_sys_poll(ufds, nfds, to);14041404+14051405+ /* We can restart this syscall, usually */14061406+ if (ret == -EINTR) {14071407+ /*14081408+ * Don't restore the signal mask yet. Let do_signal() deliver14091409+ * the signal on the way back to userspace, before the signal14101410+ * mask is restored.14111411+ */14121412+ if (sigmask) {14131413+ memcpy(¤t->saved_sigmask, &sigsaved,14141414+ sizeof(sigsaved));14151415+ set_restore_sigmask();14161416+ }14171417+ ret = -ERESTARTNOHAND;14181418+ } else if (sigmask)14191419+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);14201420+14211421+ ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);14221422+14231423+ return ret;14241424+}14251425+#endif
-56
include/linux/poll.h
···9898 ktime_t *expires, unsigned long slack);9999extern u64 select_estimate_accuracy(struct timespec64 *tv);100100101101-102102-static inline int poll_schedule(struct poll_wqueues *pwq, int state)103103-{104104- return poll_schedule_timeout(pwq, state, NULL, 0);105105-}106106-107107-/*108108- * Scalable version of the fd_set.109109- */110110-111111-typedef struct {112112- unsigned long *in, *out, *ex;113113- unsigned long *res_in, *res_out, *res_ex;114114-} fd_set_bits;115115-116116-/*117117- * How many longwords for "nr" bits?118118- */119119-#define FDS_BITPERLONG (8*sizeof(long))120120-#define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)121121-#define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long))122122-123123-/*124124- * We do a VERIFY_WRITE here even though we are only reading this time:125125- * we'll write to it eventually..126126- *127127- * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.128128- */129129-static inline130130-int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)131131-{132132- nr = FDS_BYTES(nr);133133- if (ufdset)134134- return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0;135135-136136- memset(fdset, 0, nr);137137- return 0;138138-}139139-140140-static inline unsigned long __must_check141141-set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)142142-{143143- if (ufdset)144144- return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));145145- return 0;146146-}147147-148148-static inline149149-void zero_fd_set(unsigned long nr, unsigned long *fdset)150150-{151151- memset(fdset, 0, FDS_BYTES(nr));152152-}153153-154101#define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1)155102156156-extern int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time);157157-extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,158158- struct timespec64 *end_time);159103extern int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,160104 fd_set __user *exp, struct timespec64 *end_time);161105