Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1894

kernel-2.6.18-128.1.10.el5.src.rpm

From: Roland McGrath <roland@redhat.com>
Date: Tue, 4 Dec 2007 16:07:56 -0800
Subject: [ppc64] utrace: fix PTRACE_GETVRREGS data
Message-id: 20071205000756.16EE326F8D9@magilla.localdomain
O-Subject: [RHEL5.2 patch] RHBZ#367221 utrace powerpc altivec
Bugzilla: 367221

This fixes RHBZ#367221, where the final slot of the PTRACE_GETVRREGS data
would be wrong.  This is a regression from upstream 2.6.18.  It is not
technically a regression from RHEL4, but only because the original RHEL4
backport of PTRACE_GETVRREGS was botched so it never worked (RHBZ#367061).

This is still waiting for qa_ack + to get rhel-5.2.0 + flags.
But it has a simple win/lose test case already available in a handy
regression test suite (might already be in RHTS, in fact), so I don't
know why it should be held up.

Thanks,
Roland

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 3f8536e..3d2df91 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -159,15 +159,26 @@ vrregs_get(struct task_struct *target,
 	   unsigned int pos, unsigned int count,
 	   void *kbuf, void __user *ubuf)
 {
+	int ret;
+
 	BUILD_BUG_ON(offsetof(struct thread_struct, vscr)
 		     != offsetof(struct thread_struct, vr[32]));
-	BUILD_BUG_ON(offsetof(struct thread_struct, vscr) + sizeof(vector128)
-		     != offsetof(struct thread_struct, vrsave));
 
 	flush_altivec_to_thread(target);
 
-	return utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				     &target->thread.vr, 0, -1);
+	ret = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				    &target->thread.vr,
+				    0, 33 * sizeof(vector128));
+	if (ret == 0 && count > 0) {
+		/*
+		 * Copy out only the low-order word of vrsave.
+		 */
+		u32 vrsave = target->thread.vrsave;
+		ret = utrace_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
+					    33 * sizeof(vector128), -1);
+	}
+
+	return ret;
 }
 
 static int
@@ -176,10 +187,25 @@ vrregs_set(struct task_struct *target,
 	    unsigned int pos, unsigned int count,
 	    const void *kbuf, const void __user *ubuf)
 {
+	int ret;
+
 	flush_altivec_to_thread(target);
 
-	return utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				    &target->thread.vr, 0, -1);
+	ret = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				   &target->thread.vr,
+				   0, 33 * sizeof(vector128));
+	if (ret == 0 && count > 0) {
+		/*
+		 * Copy in only the low-order word of vrsave.
+		 */
+		u32 vrsave;
+		ret = utrace_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
+					   33 * sizeof(vector128), -1);
+		if (ret == 0)
+			target->thread.vrsave = vrsave;
+	}
+
+	return ret;
 }
 #endif	/* CONFIG_ALTIVEC */