Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1974

kernel-2.6.18-238.el5.src.rpm

From: Vitaly Mayatskikh <vmayatsk@redhat.com>
Date: Thu, 6 Aug 2009 16:58:55 +0200
Subject: [misc] information leak in sigaltstack
Message-id: 87k51h9efk.wl%vmayatsk@redhat.com
O-Subject: [RHEL-5.5 patch] bz515397 kernel: information leak in sigaltstack
Bugzilla: 515396
RH-Acked-by: Jiri Olsa <jolsa@redhat.com>
RH-Acked-by: Oleg Nesterov <oleg@redhat.com>
RH-Acked-by: Dean Nelson <dnelson@redhat.com>
RH-Acked-by: Eugene Teo <eugene@redhat.com>
RH-Acked-by: Jiri Pirko <jpirko@redhat.com>

https://bugzilla.redhat.com/show_bug.cgi?id=515397

Description:
============
do_sigaltstack() uses copy_to_user() to copy stack_t structure
(created on the stack) to user space. Due to structure alignment
there's random bytes in the hole between members of stack_t, they go
to userspace as well.

This patch copies all required fields one-by-one with help of
put_user().

Upstream status:
================
commit 0083fc2c50e6c5127c2802ad323adf8143ab7856

Test status:
============
Tested with reproducer from https://bugzilla.redhat.com/show_bug.cgi?id=515392#c2
Patched kernel prevents leaks of stack garbage to userspace.

diff --git a/kernel/signal.c b/kernel/signal.c
index 493b8d2..da9b46f 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2171,11 +2171,9 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
 	stack_t oss;
 	int error;
 
-	if (uoss) {
-		oss.ss_sp = (void __user *) current->sas_ss_sp;
-		oss.ss_size = current->sas_ss_size;
-		oss.ss_flags = sas_ss_flags(sp);
-	}
+	oss.ss_sp = (void __user *) current->sas_ss_sp;
+	oss.ss_size = current->sas_ss_size;
+	oss.ss_flags = sas_ss_flags(sp);
 
 	if (uss) {
 		void __user *ss_sp;
@@ -2218,13 +2216,16 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
 		current->sas_ss_size = ss_size;
 	}
 
+	error = 0;
 	if (uoss) {
 		error = -EFAULT;
-		if (copy_to_user(uoss, &oss, sizeof(oss)))
+		if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
 			goto out;
+		error = __put_user(oss.ss_sp, &uoss->ss_sp) |
+			__put_user(oss.ss_size, &uoss->ss_size) |
+			__put_user(oss.ss_flags, &uoss->ss_flags);
 	}
 
-	error = 0;
 out:
 	return error;
 }