PTRACE_PEEKUSERがx86_64からFPUレジスタの読み出しを許可しないのはなぜですか?

PTRACE_PEEKUSERがx86_64からFPUレジスタの読み出しを許可しないのはなぜですか?

PTRACE_PEEKUSERこの領域で単語を読むことが文書化されており、userx86_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
}

関連情報