PTRACE_PEEKUSER가 x86_64에서 FPU 레지스터 읽기를 허용하지 않는 이유는 무엇입니까?

PTRACE_PEEKUSER가 x86_64에서 FPU 레지스터 읽기를 허용하지 않는 이유는 무엇입니까?

PTRACE_PEEKUSER이 영역에서 단어를 읽는 것으로 문서화되어 user있으며 x86_64의 부분 레이아웃은 다음과 같습니다.

struct user
{
  struct user_regs_struct       regs;
  int                           u_fpvalid;
  struct user_fpregs_struct     i387;
  //...
  int                           u_debugreg [8];
};

내부 또는 내부 오프셋을 사용하여 행복하게 PTRACE_PEEKUSER호출할 수 있지만 내부 오프셋을 전달하면 무조건 반환됩니다.regsu_debugregi387EIO

커널의 코드를 보면 내부적으로 읽은 regs합계가 u_debugreg유일하게 지원되는 오프셋임을 알 수 있습니다.

    case PTRACE_PEEKUSR: {
        unsigned long tmp;

        ret = -EIO;
        if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
            break;

        tmp = 0;  /* Default return condition */
        if (addr < sizeof(struct user_regs_struct))
            tmp = getreg(child, addr);
        else if (addr >= offsetof(struct user, u_debugreg[0]) &&
             addr <= offsetof(struct user, u_debugreg[7])) {
            addr -= offsetof(struct user, u_debugreg[0]);
            tmp = ptrace_get_debugreg(child, addr / sizeof(data));
        }
        ret = put_user(tmp, datap);
        break;
    }

읽기를 지원하지 않는 것으로 알고 있습니다 i387. 나는 를 호출하여 이 레지스터를 읽을 수 있다는 것을 알고 있습니다 PTRACE_GETFPREGS. 내 질문은: PTRACE_PEEKUSER이러한 레지스터를 사용하고 쓸 수 없는 특별한 이유가 있습니까 ?PTRACE_POKEUSER

내 추측으로는 대부분의 필드가 user_fpregs_struct64비트보다 작기 때문에 읽기 및 쓰기가 여러 레지스터를 다룰 수 있기 때문입니다. 그러나 나는 공개 소스를 작성하고 이에 주석을 달 것이므로 내 추측이 맞는지 확인하고 싶습니다.

답변1

추측해 보세요. 수학 보조 프로세서 레지스터를 읽고 싶습니다. i387커널의 멤버가 언제 업데이트되는지 확인하셨나요 ? struct user나는 그렇지 않았고 틀렸을 수도 있지만 내 추측은 흔하지는 않지만 코어 덤프와 같은 경우에는 그렇습니다.

Arch/x86/include/asm/user_64.h에서

struct user {
/* We start with the registers, to mimic the way that "memory" is returned
   from the ptrace(3,...) function.  */
  struct user_regs_struct regs; /* Where the registers are actually stored */
/* ptrace does not yet supply these.  Someday.... */
  int u_fpvalid;        /* True if math co-processor being used. */
                /* for this mess. Not yet used. */
  int pad0;
  struct user_i387_struct i387; /* Math Co-processor registers. */
  :
  unsigned long u_debugreg[8];
  :
};

따라서 수학 보조 프로세서 레지스터를 읽는 것은 FPU에서 읽는 것이 가장 좋습니다. 커널이 어떻게 실행되는지 확인하면 PTRACE_GETFPREGS구성원이 아닌 FPU에서 가져오는 것을 볼 수 있습니다 struct user i387. 보조 프로세서 레지스터를 사용하여 수학을 작성하는 경우에도 마찬가지입니다 PTRACE_SETFPREGS.

~에서arch_ptrace

case PTRACE_GETFPREGS:  /* Get the child FPU state. */
    return copy_regset_to_user(child,
                   task_user_regset_view(current),
                   REGSET_FP,
                   0, sizeof(struct user_i387_struct),
                   datap);

task_user_regset_viewx86_64_regsets읽기에 대한 반환 값입니다 xfpregs_get.

static struct user_regset x86_64_regsets[] __ro_after_init = {

    [REGSET_FP] = {
        .core_note_type = NT_PRFPREG,
        .n = sizeof(struct user_i387_struct) / sizeof(long),
        .size = sizeof(long), .align = sizeof(long),
        .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set
    },

}

const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
    :
#ifdef CONFIG_X86_64
    return &user_x86_64_view;
#endif
}

관련 정보