Skip to content

Commit

Permalink
powerpc/ptrace: Remove BUG_ON when full register set not available
Browse files Browse the repository at this point in the history
In some cases during a threaded core dump not all the threads will have
a full register set. This happens when the signal causing the core dump
races with a thread exiting.  The race happens when the exiting thread
has entered the kernel for the last time before the signal arrives, but
doesn't get far enough through the exit code to avoid being included
in the core dump.

So we get a thread included in the core dump which is never going to go
out to userspace again and only has a partial register set recorded

Normally we would catch each thread as it is about to go into userspace
and capture the full register set then.

However, this exiting thread is never going to go out to userspace
again, so we have no way to capture its full register set.  It doesn't
really matter, though, as this is a thread which is effectively
already dead.

So instead of hitting a BUG() in this case (a really bad choice of
action in the first place), we use a poison value for the register
values.

[BenH]: Some cosmetic/stylistic changes and fix build on ppc32

Signed-off-by: Mike Wolf <mjw@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Mike Wolf authored and Benjamin Herrenschmidt committed Mar 21, 2011
1 parent d6a2639 commit a71f5d5
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 3 deletions.
2 changes: 2 additions & 0 deletions arch/powerpc/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,10 @@ extern int ptrace_put_reg(struct task_struct *task, int regno,
#endif /* ! __powerpc64__ */
#define TRAP(regs) ((regs)->trap & ~0xF)
#ifdef __powerpc64__
#define NV_REG_POISON 0xdeadbeefdeadbeefUL
#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1)
#else
#define NV_REG_POISON 0xdeadbeef
#define CHECK_FULL_REGS(regs) \
do { \
if ((regs)->trap & 1) \
Expand Down
15 changes: 12 additions & 3 deletions arch/powerpc/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,16 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
{
int ret;
int i, ret;

if (target->thread.regs == NULL)
return -EIO;

CHECK_FULL_REGS(target->thread.regs);
if (!FULL_REGS(target->thread.regs)) {
/* We have a partial register set. Fill 14-31 with bogus values */
for (i = 14; i < 32; i++)
target->thread.regs->gpr[i] = NV_REG_POISON;
}

ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
target->thread.regs,
Expand Down Expand Up @@ -641,11 +645,16 @@ static int gpr32_get(struct task_struct *target,
compat_ulong_t *k = kbuf;
compat_ulong_t __user *u = ubuf;
compat_ulong_t reg;
int i;

if (target->thread.regs == NULL)
return -EIO;

CHECK_FULL_REGS(target->thread.regs);
if (!FULL_REGS(target->thread.regs)) {
/* We have a partial register set. Fill 14-31 with bogus values */
for (i = 14; i < 32; i++)
target->thread.regs->gpr[i] = NV_REG_POISON;
}

pos /= sizeof(reg);
count /= sizeof(reg);
Expand Down

0 comments on commit a71f5d5

Please sign in to comment.