arm64: ptrace: fix empty registers set in prstatus of aarch32 process core
authorVictor Kamensky <victor.kamensky@linaro.org>
Tue, 3 Jun 2014 18:21:30 +0000 (19:21 +0100)
committerMark Brown <broonie@kernel.org>
Fri, 24 Oct 2014 12:18:21 +0000 (13:18 +0100)
Currently core file of aarch32 process prstatus note has empty
registers set. As result aarch32 core files create by V8 kernel are
not very useful.

It happens because compat_gpr_get and compat_gpr_set functions can
copy registers values to/from either kbuf or ubuf. ELF core file
collection function fill_thread_core_info calls compat_gpr_get
with kbuf set and ubuf set to 0. But current compat_gpr_get and
compat_gpr_set function handle copy to/from only ubuf case.

Fix is to handle kbuf and ubuf as two separate cases in similar
way as other functions like user_regset_copyout, user_regset_copyin do.

Signed-off-by: Victor Kamensky <victor.kamensky@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: stable@vger.kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
(cherry picked from commit 2227901a0230d8fde81ba9c602d649839390f56b)
Signed-off-by: Mark Brown <broonie@kernel.org>
Conflicts:
arch/arm64/kernel/ptrace.c

arch/arm64/kernel/ptrace.c

index 9fa78cd0f092dcd35646d0ef4edc8f3cdf0f75be..71c6a623e226e594a499954653bd91ee307bd50a 100644 (file)
@@ -650,12 +650,16 @@ static int compat_gpr_get(struct task_struct *target,
                        reg = (void *)&task_pt_regs(target)->regs[idx];
                }
 
-               ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t));
-
-               if (ret)
-                       break;
-               else
-                       ubuf += sizeof(compat_ulong_t);
+               if (kbuf) {
+                       memcpy(kbuf, &reg, sizeof(reg));
+                       kbuf += sizeof(reg);
+               } else {
+                       ret = copy_to_user(ubuf, &reg, sizeof(reg));
+                       if (ret)
+                               break;
+
+                       ubuf += sizeof(reg);
+               }
        }
 
        return ret;
@@ -683,7 +687,18 @@ static int compat_gpr_set(struct task_struct *target,
 
        for (i = 0; i < num_regs; ++i) {
                unsigned int idx = start + i;
-               void *reg;
+               compat_ulong_t reg;
+
+               if (kbuf) {
+                       memcpy(&reg, kbuf, sizeof(reg));
+                       kbuf += sizeof(reg);
+               } else {
+                       ret = copy_from_user(&reg, ubuf, sizeof(reg));
+                       if (ret)
+                               return ret;
+
+                       ubuf += sizeof(reg);
+               }
 
                switch (idx) {
                case 15: