@@ -996,12 +996,19 @@ SYSCALL_DEFINE1(exit_group, int, error_code)
996996 return 0 ;
997997}
998998
999+ struct waitid_info {
1000+ pid_t pid ;
1001+ uid_t uid ;
1002+ int status ;
1003+ int cause ;
1004+ };
1005+
9991006struct wait_opts {
10001007 enum pid_type wo_type ;
10011008 int wo_flags ;
10021009 struct pid * wo_pid ;
10031010
1004- struct siginfo __user * wo_info ;
1011+ struct waitid_info * wo_info ;
10051012 int wo_stat ;
10061013 struct rusage * wo_rusage ;
10071014
@@ -1053,31 +1060,20 @@ eligible_child(struct wait_opts *wo, bool ptrace, struct task_struct *p)
10531060static int wait_noreap_copyout (struct wait_opts * wo , struct task_struct * p ,
10541061 pid_t pid , uid_t uid , int why , int status )
10551062{
1056- struct siginfo __user * infop ;
1057- int retval = 0 ;
1063+ struct waitid_info * infop ;
10581064
10591065 if (wo -> wo_rusage )
10601066 getrusage (p , RUSAGE_BOTH , wo -> wo_rusage );
10611067
10621068 put_task_struct (p );
10631069 infop = wo -> wo_info ;
10641070 if (infop ) {
1065- if (!retval )
1066- retval = put_user (SIGCHLD , & infop -> si_signo );
1067- if (!retval )
1068- retval = put_user (0 , & infop -> si_errno );
1069- if (!retval )
1070- retval = put_user ((short )why , & infop -> si_code );
1071- if (!retval )
1072- retval = put_user (pid , & infop -> si_pid );
1073- if (!retval )
1074- retval = put_user (uid , & infop -> si_uid );
1075- if (!retval )
1076- retval = put_user (status , & infop -> si_status );
1071+ infop -> cause = why ;
1072+ infop -> pid = pid ;
1073+ infop -> uid = uid ;
1074+ infop -> status = status ;
10771075 }
1078- if (!retval )
1079- retval = pid ;
1080- return retval ;
1076+ return pid ;
10811077}
10821078
10831079/*
@@ -1088,10 +1084,10 @@ static int wait_noreap_copyout(struct wait_opts *wo, struct task_struct *p,
10881084 */
10891085static int wait_task_zombie (struct wait_opts * wo , struct task_struct * p )
10901086{
1091- int state , retval , status ;
1087+ int state , status ;
10921088 pid_t pid = task_pid_vnr (p );
10931089 uid_t uid = from_kuid_munged (current_user_ns (), task_uid (p ));
1094- struct siginfo __user * infop ;
1090+ struct waitid_info * infop ;
10951091
10961092 if (!likely (wo -> wo_flags & WEXITED ))
10971093 return 0 ;
@@ -1186,36 +1182,22 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
11861182
11871183 if (wo -> wo_rusage )
11881184 getrusage (p , RUSAGE_BOTH , wo -> wo_rusage );
1189- retval = 0 ;
11901185 status = (p -> signal -> flags & SIGNAL_GROUP_EXIT )
11911186 ? p -> signal -> group_exit_code : p -> exit_code ;
11921187 wo -> wo_stat = status ;
11931188
11941189 infop = wo -> wo_info ;
1195- if (!retval && infop )
1196- retval = put_user (SIGCHLD , & infop -> si_signo );
1197- if (!retval && infop )
1198- retval = put_user (0 , & infop -> si_errno );
1199- if (!retval && infop ) {
1200- int why ;
1201-
1190+ if (infop ) {
12021191 if ((status & 0x7f ) == 0 ) {
1203- why = CLD_EXITED ;
1204- status >>= 8 ;
1192+ infop -> cause = CLD_EXITED ;
1193+ infop -> status = status >> 8 ;
12051194 } else {
1206- why = (status & 0x80 ) ? CLD_DUMPED : CLD_KILLED ;
1207- status &= 0x7f ;
1195+ infop -> cause = (status & 0x80 ) ? CLD_DUMPED : CLD_KILLED ;
1196+ infop -> status = status & 0x7f ;
12081197 }
1209- retval = put_user ((short )why , & infop -> si_code );
1210- if (!retval )
1211- retval = put_user (status , & infop -> si_status );
1198+ infop -> pid = pid ;
1199+ infop -> uid = uid ;
12121200 }
1213- if (!retval && infop )
1214- retval = put_user (pid , & infop -> si_pid );
1215- if (!retval && infop )
1216- retval = put_user (uid , & infop -> si_uid );
1217- if (!retval )
1218- retval = pid ;
12191201
12201202 if (state == EXIT_TRACE ) {
12211203 write_lock_irq (& tasklist_lock );
@@ -1232,7 +1214,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
12321214 if (state == EXIT_DEAD )
12331215 release_task (p );
12341216
1235- return retval ;
1217+ return pid ;
12361218}
12371219
12381220static int * task_stopped_code (struct task_struct * p , bool ptrace )
@@ -1268,8 +1250,8 @@ static int *task_stopped_code(struct task_struct *p, bool ptrace)
12681250static int wait_task_stopped (struct wait_opts * wo ,
12691251 int ptrace , struct task_struct * p )
12701252{
1271- struct siginfo __user * infop ;
1272- int retval , exit_code , * p_code , why ;
1253+ struct waitid_info * infop ;
1254+ int exit_code , * p_code , why ;
12731255 uid_t uid = 0 ; /* unneeded, required by compiler */
12741256 pid_t pid ;
12751257
@@ -1320,28 +1302,19 @@ static int wait_task_stopped(struct wait_opts *wo,
13201302
13211303 if (wo -> wo_rusage )
13221304 getrusage (p , RUSAGE_BOTH , wo -> wo_rusage );
1323- retval = 0 ;
13241305 wo -> wo_stat = (exit_code << 8 ) | 0x7f ;
13251306
13261307 infop = wo -> wo_info ;
1327- if (!retval && infop )
1328- retval = put_user (SIGCHLD , & infop -> si_signo );
1329- if (!retval && infop )
1330- retval = put_user (0 , & infop -> si_errno );
1331- if (!retval && infop )
1332- retval = put_user ((short )why , & infop -> si_code );
1333- if (!retval && infop )
1334- retval = put_user (exit_code , & infop -> si_status );
1335- if (!retval && infop )
1336- retval = put_user (pid , & infop -> si_pid );
1337- if (!retval && infop )
1338- retval = put_user (uid , & infop -> si_uid );
1339- if (!retval )
1340- retval = pid ;
1308+ if (infop ) {
1309+ infop -> cause = why ;
1310+ infop -> status = exit_code ;
1311+ infop -> pid = pid ;
1312+ infop -> uid = uid ;
1313+ }
13411314 put_task_struct (p );
13421315
1343- BUG_ON (!retval );
1344- return retval ;
1316+ BUG_ON (!pid );
1317+ return pid ;
13451318}
13461319
13471320/*
@@ -1618,7 +1591,7 @@ static long do_wait(struct wait_opts *wo)
16181591 return retval ;
16191592}
16201593
1621- static long kernel_waitid (int which , pid_t upid , struct siginfo __user * infop ,
1594+ static long kernel_waitid (int which , pid_t upid , struct waitid_info * infop ,
16221595 int options , struct rusage * ru )
16231596{
16241597 struct wait_opts wo ;
@@ -1660,27 +1633,8 @@ static long kernel_waitid(int which, pid_t upid, struct siginfo __user *infop,
16601633 wo .wo_rusage = ru ;
16611634 ret = do_wait (& wo );
16621635
1663- if (ret > 0 ) {
1636+ if (ret > 0 )
16641637 ret = 0 ;
1665- } else if (infop ) {
1666- /*
1667- * For a WNOHANG return, clear out all the fields
1668- * we would set so the user can easily tell the
1669- * difference.
1670- */
1671- if (!ret )
1672- ret = put_user (0 , & infop -> si_signo );
1673- if (!ret )
1674- ret = put_user (0 , & infop -> si_errno );
1675- if (!ret )
1676- ret = put_user (0 , & infop -> si_code );
1677- if (!ret )
1678- ret = put_user (0 , & infop -> si_pid );
1679- if (!ret )
1680- ret = put_user (0 , & infop -> si_uid );
1681- if (!ret )
1682- ret = put_user (0 , & infop -> si_status );
1683- }
16841638
16851639 put_pid (pid );
16861640 return ret ;
@@ -1690,12 +1644,24 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
16901644 infop , int , options , struct rusage __user * , ru )
16911645{
16921646 struct rusage r ;
1693- long err = kernel_waitid (which , upid , infop , options , ru ? & r : NULL );
1647+ struct waitid_info info = {.status = 0 };
1648+ long err = kernel_waitid (which , upid , & info , options , ru ? & r : NULL );
16941649
16951650 if (!err ) {
16961651 if (ru && copy_to_user (ru , & r , sizeof (struct rusage )))
16971652 return - EFAULT ;
16981653 }
1654+ if (!infop )
1655+ return err ;
1656+
1657+ if (put_user (err ? 0 : SIGCHLD , & infop -> si_signo ) ||
1658+ put_user (0 , & infop -> si_errno ) ||
1659+ put_user ((short )info .cause , & infop -> si_code ) ||
1660+ put_user (info .pid , & infop -> si_pid ) ||
1661+ put_user (info .uid , & infop -> si_uid ) ||
1662+ put_user (info .status , & infop -> si_status ))
1663+ err = - EFAULT ;
1664+
16991665 return err ;
17001666}
17011667
@@ -1785,33 +1751,27 @@ COMPAT_SYSCALL_DEFINE5(waitid,
17851751 struct compat_siginfo __user * , infop , int , options ,
17861752 struct compat_rusage __user * , uru )
17871753{
1788- siginfo_t info ;
17891754 struct rusage ru ;
1790- long ret ;
1791- mm_segment_t old_fs = get_fs ();
1792-
1793- memset (& info , 0 , sizeof (info ));
1755+ struct waitid_info info = {.status = 0 };
1756+ long err = kernel_waitid (which , pid , & info , options , uru ? & ru : NULL );
17941757
1795- set_fs (KERNEL_DS );
1796- ret = kernel_waitid (which , pid , (siginfo_t __user * )& info , options ,
1797- uru ? & ru : NULL );
1798- set_fs (old_fs );
1799-
1800- if ((ret < 0 ) || (info .si_signo == 0 ))
1801- return ret ;
1802-
1803- if (uru ) {
1804- /* sys_waitid() overwrites everything in ru */
1758+ if (!err && uru ) {
1759+ /* kernel_waitid() overwrites everything in ru */
18051760 if (COMPAT_USE_64BIT_TIME )
1806- ret = copy_to_user (uru , & ru , sizeof (ru ));
1761+ err = copy_to_user (uru , & ru , sizeof (ru ));
18071762 else
1808- ret = put_compat_rusage (& ru , uru );
1809- if (ret )
1763+ err = put_compat_rusage (& ru , uru );
1764+ if (err )
18101765 return - EFAULT ;
18111766 }
18121767
1813- BUG_ON (info .si_code & __SI_MASK );
1814- info .si_code |= __SI_CHLD ;
1815- return copy_siginfo_to_user32 (infop , & info );
1768+ if (put_user (err ? 0 : SIGCHLD , & infop -> si_signo ) ||
1769+ put_user (0 , & infop -> si_errno ) ||
1770+ put_user ((short )info .cause , & infop -> si_code ) ||
1771+ put_user (info .pid , & infop -> si_pid ) ||
1772+ put_user (info .uid , & infop -> si_uid ) ||
1773+ put_user (info .status , & infop -> si_status ))
1774+ err = - EFAULT ;
1775+ return err ;
18161776}
18171777#endif
0 commit comments