@@ -729,16 +729,27 @@ SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
729729}
730730
731731static long do_pselect (int n , fd_set __user * inp , fd_set __user * outp ,
732- fd_set __user * exp , struct timespec __user * tsp ,
733- const sigset_t __user * sigmask , size_t sigsetsize )
732+ fd_set __user * exp , void __user * tsp ,
733+ const sigset_t __user * sigmask , size_t sigsetsize ,
734+ enum poll_time_type type )
734735{
735736 sigset_t ksigmask , sigsaved ;
736737 struct timespec64 ts , end_time , * to = NULL ;
737738 int ret ;
738739
739740 if (tsp ) {
740- if (get_timespec64 (& ts , tsp ))
741- return - EFAULT ;
741+ switch (type ) {
742+ case PT_TIMESPEC :
743+ if (get_timespec64 (& ts , tsp ))
744+ return - EFAULT ;
745+ break ;
746+ case PT_OLD_TIMESPEC :
747+ if (get_old_timespec32 (& ts , tsp ))
748+ return - EFAULT ;
749+ break ;
750+ default :
751+ BUG ();
752+ }
742753
743754 to = & end_time ;
744755 if (poll_select_set_timeout (to , ts .tv_sec , ts .tv_nsec ))
@@ -750,7 +761,7 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
750761 return ret ;
751762
752763 ret = core_sys_select (n , inp , outp , exp , to );
753- ret = poll_select_copy_remaining (& end_time , tsp , PT_TIMESPEC , ret );
764+ ret = poll_select_copy_remaining (& end_time , tsp , type , ret );
754765
755766 restore_user_sigmask (sigmask , & sigsaved );
756767
@@ -764,7 +775,27 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
764775 * the sigset size.
765776 */
766777SYSCALL_DEFINE6 (pselect6 , int , n , fd_set __user * , inp , fd_set __user * , outp ,
767- fd_set __user * , exp , struct timespec __user * , tsp ,
778+ fd_set __user * , exp , struct __kernel_timespec __user * , tsp ,
779+ void __user * , sig )
780+ {
781+ size_t sigsetsize = 0 ;
782+ sigset_t __user * up = NULL ;
783+
784+ if (sig ) {
785+ if (!access_ok (VERIFY_READ , sig , sizeof (void * )+ sizeof (size_t ))
786+ || __get_user (up , (sigset_t __user * __user * )sig )
787+ || __get_user (sigsetsize ,
788+ (size_t __user * )(sig + sizeof (void * ))))
789+ return - EFAULT ;
790+ }
791+
792+ return do_pselect (n , inp , outp , exp , tsp , up , sigsetsize , PT_TIMESPEC );
793+ }
794+
795+ #if defined(CONFIG_COMPAT_32BIT_TIME ) && !defined(CONFIG_64BIT )
796+
797+ SYSCALL_DEFINE6 (pselect6_time32 , int , n , fd_set __user * , inp , fd_set __user * , outp ,
798+ fd_set __user * , exp , struct old_timespec32 __user * , tsp ,
768799 void __user * , sig )
769800{
770801 size_t sigsetsize = 0 ;
@@ -778,9 +809,11 @@ SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
778809 return - EFAULT ;
779810 }
780811
781- return do_pselect (n , inp , outp , exp , tsp , up , sigsetsize );
812+ return do_pselect (n , inp , outp , exp , tsp , up , sigsetsize , PT_OLD_TIMESPEC );
782813}
783814
815+ #endif
816+
784817#ifdef __ARCH_WANT_SYS_OLD_SELECT
785818struct sel_arg_struct {
786819 unsigned long n ;
@@ -1289,16 +1322,26 @@ COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
12891322
12901323static long do_compat_pselect (int n , compat_ulong_t __user * inp ,
12911324 compat_ulong_t __user * outp , compat_ulong_t __user * exp ,
1292- struct old_timespec32 __user * tsp , compat_sigset_t __user * sigmask ,
1293- compat_size_t sigsetsize )
1325+ void __user * tsp , compat_sigset_t __user * sigmask ,
1326+ compat_size_t sigsetsize , enum poll_time_type type )
12941327{
12951328 sigset_t ksigmask , sigsaved ;
12961329 struct timespec64 ts , end_time , * to = NULL ;
12971330 int ret ;
12981331
12991332 if (tsp ) {
1300- if (get_old_timespec32 (& ts , tsp ))
1301- return - EFAULT ;
1333+ switch (type ) {
1334+ case PT_OLD_TIMESPEC :
1335+ if (get_old_timespec32 (& ts , tsp ))
1336+ return - EFAULT ;
1337+ break ;
1338+ case PT_TIMESPEC :
1339+ if (get_timespec64 (& ts , tsp ))
1340+ return - EFAULT ;
1341+ break ;
1342+ default :
1343+ BUG ();
1344+ }
13021345
13031346 to = & end_time ;
13041347 if (poll_select_set_timeout (to , ts .tv_sec , ts .tv_nsec ))
@@ -1310,13 +1353,35 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
13101353 return ret ;
13111354
13121355 ret = compat_core_sys_select (n , inp , outp , exp , to );
1313- ret = poll_select_copy_remaining (& end_time , tsp , PT_OLD_TIMESPEC , ret );
1356+ ret = poll_select_copy_remaining (& end_time , tsp , type , ret );
13141357
13151358 restore_user_sigmask (sigmask , & sigsaved );
13161359
13171360 return ret ;
13181361}
13191362
1363+ COMPAT_SYSCALL_DEFINE6 (pselect6_time64 , int , n , compat_ulong_t __user * , inp ,
1364+ compat_ulong_t __user * , outp , compat_ulong_t __user * , exp ,
1365+ struct __kernel_timespec __user * , tsp , void __user * , sig )
1366+ {
1367+ compat_size_t sigsetsize = 0 ;
1368+ compat_uptr_t up = 0 ;
1369+
1370+ if (sig ) {
1371+ if (!access_ok (VERIFY_READ , sig ,
1372+ sizeof (compat_uptr_t )+ sizeof (compat_size_t )) ||
1373+ __get_user (up , (compat_uptr_t __user * )sig ) ||
1374+ __get_user (sigsetsize ,
1375+ (compat_size_t __user * )(sig + sizeof (up ))))
1376+ return - EFAULT ;
1377+ }
1378+
1379+ return do_compat_pselect (n , inp , outp , exp , tsp , compat_ptr (up ),
1380+ sigsetsize , PT_TIMESPEC );
1381+ }
1382+
1383+ #if defined(CONFIG_COMPAT_32BIT_TIME )
1384+
13201385COMPAT_SYSCALL_DEFINE6 (pselect6 , int , n , compat_ulong_t __user * , inp ,
13211386 compat_ulong_t __user * , outp , compat_ulong_t __user * , exp ,
13221387 struct old_timespec32 __user * , tsp , void __user * , sig )
@@ -1332,10 +1397,13 @@ COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
13321397 (compat_size_t __user * )(sig + sizeof (up ))))
13331398 return - EFAULT ;
13341399 }
1400+
13351401 return do_compat_pselect (n , inp , outp , exp , tsp , compat_ptr (up ),
1336- sigsetsize );
1402+ sigsetsize , PT_OLD_TIMESPEC );
13371403}
13381404
1405+ #endif
1406+
13391407#if defined(CONFIG_COMPAT_32BIT_TIME )
13401408COMPAT_SYSCALL_DEFINE5 (ppoll , struct pollfd __user * , ufds ,
13411409 unsigned int , nfds , struct old_timespec32 __user * , tsp ,
0 commit comments