Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -79,13 +79,14 @@ struct user_fpsimd_state {

struct user_hwdebug_state {
	__u32		dbg_info;
	__u32		pad;
	struct {
		__u64	addr;
		__u32	ctrl;
		__u32	pad;
	}		dbg_regs[16];
};


#endif /* __ASSEMBLY__ */

#endif /* _UAPI__ASM_PTRACE_H */
+30 −6
Original line number Diff line number Diff line
@@ -372,7 +372,7 @@ static int ptrace_hbp_set_addr(unsigned int note_type,

#define PTRACE_HBP_ADDR_SZ	sizeof(u64)
#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,
			const struct user_regset *regset,
@@ -380,7 +380,7 @@ static int hw_break_get(struct task_struct *target,
			void *kbuf, void __user *ubuf)
{
	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;
	u64 addr;

@@ -389,11 +389,20 @@ static int hw_break_get(struct task_struct *target,
	if (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)
		return ret;

	/* (address, ctrl) registers */
	offset = offsetof(struct user_hwdebug_state, dbg_regs);
	limit = regset->n * regset->size;
	while (count && offset < limit) {
		ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
@@ -413,6 +422,13 @@ static int hw_break_get(struct task_struct *target,
		if (ret)
			return ret;
		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++;
	}

@@ -425,12 +441,13 @@ static int hw_break_set(struct task_struct *target,
			const void *kbuf, const void __user *ubuf)
{
	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;
	u64 addr;

	/* Resource info */
	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
	/* Resource info and pad */
	offset = offsetof(struct user_hwdebug_state, dbg_regs);
	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
	if (ret)
		return ret;

@@ -454,6 +471,13 @@ static int hw_break_set(struct task_struct *target,
		if (ret)
			return ret;
		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++;
	}