nanosleep: plug a kernel memory disclosure

nanosleep() updates rmtp on EINVAL.  In that case, kern_nanosleep()
has not updated rmt, so sys_nanosleep() updates the user-space rmtp
by copying garbage from its stack frame.  This is not only a kernel
memory disclosure, it's also not POSIX-compliant.  Fix it to update
rmtp only on EINTR.

Reviewed by:	jilles (via D10020), dchagin
MFC after:	3 days
Security:	possibly
Sponsored by:	Dell EMC
Differential Revision:	https://reviews.freebsd.org/D10044
This commit is contained in:
Eric van Gyzen 2017-03-18 20:16:23 +00:00
parent 94e854c517
commit 4cf66812ea
3 changed files with 4 additions and 4 deletions

View file

@ -2241,7 +2241,7 @@ freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
!useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
return (EFAULT);
error = kern_nanosleep(td, &rqt, &rmt);
if (error && uap->rmtp) {
if (error == EINTR && uap->rmtp) {
int error2;
CP(rmt, rmt32, tv_sec);

View file

@ -519,7 +519,7 @@ linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
return (error);
}
error = kern_nanosleep(td, &rqts, rmtp);
if (args->rmtp != NULL) {
if (error == EINTR && args->rmtp != NULL) {
error2 = native_to_linux_timespec(&lrmts, rmtp);
if (error2 != 0)
return (error2);
@ -583,7 +583,7 @@ linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args
return (error);
}
error = kern_nanosleep(td, &rqts, rmtp);
if (args->rmtp != NULL) {
if (error == EINTR && args->rmtp != NULL) {
/* XXX. Not for TIMER_ABSTIME */
error2 = native_to_linux_timespec(&lrmts, rmtp);
if (error2 != 0)

View file

@ -548,7 +548,7 @@ sys_nanosleep(struct thread *td, struct nanosleep_args *uap)
!useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
return (EFAULT);
error = kern_nanosleep(td, &rqt, &rmt);
if (error && uap->rmtp) {
if (error == EINTR && uap->rmtp) {
int error2;
error2 = copyout(&rmt, uap->rmtp, sizeof(rmt));