diff options
Diffstat (limited to 'kernel/exit.c')
| -rw-r--r-- | kernel/exit.c | 29 | 
1 files changed, 16 insertions, 13 deletions
| diff --git a/kernel/exit.c b/kernel/exit.c index 3481ababd06a..f6cad39f35df 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1600,18 +1600,19 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,  	struct waitid_info info = {.status = 0};  	long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);  	int signo = 0; +  	if (err > 0) {  		signo = SIGCHLD;  		err = 0; -	} - -	if (!err) {  		if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))  			return -EFAULT;  	}  	if (!infop)  		return err; +	if (!access_ok(VERIFY_WRITE, infop, sizeof(*infop))) +		return -EFAULT; +  	user_access_begin();  	unsafe_put_user(signo, &infop->si_signo, Efault);  	unsafe_put_user(0, &infop->si_errno, Efault); @@ -1723,21 +1724,23 @@ COMPAT_SYSCALL_DEFINE5(waitid,  	if (err > 0) {  		signo = SIGCHLD;  		err = 0; -	} - -	if (!err && uru) { -		/* kernel_waitid() overwrites everything in ru */ -		if (COMPAT_USE_64BIT_TIME) -			err = copy_to_user(uru, &ru, sizeof(ru)); -		else -			err = put_compat_rusage(&ru, uru); -		if (err) -			return -EFAULT; +		if (uru) { +			/* kernel_waitid() overwrites everything in ru */ +			if (COMPAT_USE_64BIT_TIME) +				err = copy_to_user(uru, &ru, sizeof(ru)); +			else +				err = put_compat_rusage(&ru, uru); +			if (err) +				return -EFAULT; +		}  	}  	if (!infop)  		return err; +	if (!access_ok(VERIFY_WRITE, infop, sizeof(*infop))) +		return -EFAULT; +  	user_access_begin();  	unsafe_put_user(signo, &infop->si_signo, Efault);  	unsafe_put_user(0, &infop->si_errno, Efault); |