From 4cf66812ea5fd231c98474cd9759a632043a6a37 Mon Sep 17 00:00:00 2001 From: Eric van Gyzen Date: Sat, 18 Mar 2017 20:16:23 +0000 Subject: [PATCH] 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 --- sys/compat/freebsd32/freebsd32_misc.c | 2 +- sys/compat/linux/linux_time.c | 4 ++-- sys/kern/kern_time.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index c90f796e348..86b1399a98c 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -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); diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c index 96e3eabb23c..5c66b1aaf06 100644 --- a/sys/compat/linux/linux_time.c +++ b/sys/compat/linux/linux_time.c @@ -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) diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 8914ebff0a3..d31c12168fc 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -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));