Commit 7797d17c authored by Will Deacon's avatar Will Deacon Committed by Catalin Marinas

arm64: ptrace: make structure padding explicit for debug registers

The user_hwdebug_state structure contains implicit padding to conform to
the alignment requirements of the AArch64 ABI (namely that aggregates
must be aligned to their most aligned member).

This patch fixes the ptrace functions operating on struct
user_hwdebug_state so that the padding is handled correctly.
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 16dd46bb
...@@ -79,13 +79,14 @@ struct user_fpsimd_state { ...@@ -79,13 +79,14 @@ struct user_fpsimd_state {
struct user_hwdebug_state { struct user_hwdebug_state {
__u32 dbg_info; __u32 dbg_info;
__u32 pad;
struct { struct {
__u64 addr; __u64 addr;
__u32 ctrl; __u32 ctrl;
__u32 pad;
} dbg_regs[16]; } dbg_regs[16];
}; };
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _UAPI__ASM_PTRACE_H */ #endif /* _UAPI__ASM_PTRACE_H */
...@@ -372,7 +372,7 @@ static int ptrace_hbp_set_addr(unsigned int note_type, ...@@ -372,7 +372,7 @@ static int ptrace_hbp_set_addr(unsigned int note_type,
#define PTRACE_HBP_ADDR_SZ sizeof(u64) #define PTRACE_HBP_ADDR_SZ sizeof(u64)
#define PTRACE_HBP_CTRL_SZ sizeof(u32) #define PTRACE_HBP_CTRL_SZ sizeof(u32)
#define PTRACE_HBP_REG_OFF sizeof(u32) #define PTRACE_HBP_PAD_SZ sizeof(u32)
static int hw_break_get(struct task_struct *target, static int hw_break_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
...@@ -380,7 +380,7 @@ static int hw_break_get(struct task_struct *target, ...@@ -380,7 +380,7 @@ static int hw_break_get(struct task_struct *target,
void *kbuf, void __user *ubuf) void *kbuf, void __user *ubuf)
{ {
unsigned int note_type = regset->core_note_type; unsigned int note_type = regset->core_note_type;
int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; int ret, idx = 0, offset, limit;
u32 info, ctrl; u32 info, ctrl;
u64 addr; u64 addr;
...@@ -389,11 +389,20 @@ static int hw_break_get(struct task_struct *target, ...@@ -389,11 +389,20 @@ static int hw_break_get(struct task_struct *target,
if (ret) if (ret)
return ret; return ret;
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 4); ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0,
sizeof(info));
if (ret)
return ret;
/* Pad */
offset = offsetof(struct user_hwdebug_state, pad);
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset,
offset + PTRACE_HBP_PAD_SZ);
if (ret) if (ret)
return ret; return ret;
/* (address, ctrl) registers */ /* (address, ctrl) registers */
offset = offsetof(struct user_hwdebug_state, dbg_regs);
limit = regset->n * regset->size; limit = regset->n * regset->size;
while (count && offset < limit) { while (count && offset < limit) {
ret = ptrace_hbp_get_addr(note_type, target, idx, &addr); ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
...@@ -413,6 +422,13 @@ static int hw_break_get(struct task_struct *target, ...@@ -413,6 +422,13 @@ static int hw_break_get(struct task_struct *target,
if (ret) if (ret)
return ret; return ret;
offset += PTRACE_HBP_CTRL_SZ; offset += PTRACE_HBP_CTRL_SZ;
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
offset,
offset + PTRACE_HBP_PAD_SZ);
if (ret)
return ret;
offset += PTRACE_HBP_PAD_SZ;
idx++; idx++;
} }
...@@ -425,12 +441,13 @@ static int hw_break_set(struct task_struct *target, ...@@ -425,12 +441,13 @@ static int hw_break_set(struct task_struct *target,
const void *kbuf, const void __user *ubuf) const void *kbuf, const void __user *ubuf)
{ {
unsigned int note_type = regset->core_note_type; unsigned int note_type = regset->core_note_type;
int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; int ret, idx = 0, offset, limit;
u32 ctrl; u32 ctrl;
u64 addr; u64 addr;
/* Resource info */ /* Resource info and pad */
ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4); offset = offsetof(struct user_hwdebug_state, dbg_regs);
ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
if (ret) if (ret)
return ret; return ret;
...@@ -454,6 +471,13 @@ static int hw_break_set(struct task_struct *target, ...@@ -454,6 +471,13 @@ static int hw_break_set(struct task_struct *target,
if (ret) if (ret)
return ret; return ret;
offset += PTRACE_HBP_CTRL_SZ; offset += PTRACE_HBP_CTRL_SZ;
ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
offset,
offset + PTRACE_HBP_PAD_SZ);
if (ret)
return ret;
offset += PTRACE_HBP_PAD_SZ;
idx++; idx++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment