SFrame may represent an undefined return address (RA) as SFrame FRE without any offsets as indication for an outermost frame. Reviewed-by: Indu Bhagat Signed-off-by: Jens Remus --- kernel/unwind/sframe.c | 15 ++++++++++++++- kernel/unwind/sframe.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index a38f50a36363..f723c1a32f90 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -230,7 +230,7 @@ static __always_inline int __read_fre(struct sframe_section *sec, UNSAFE_GET_USER_INC(info, cur, 1, Efault); dataword_count = SFRAME_V3_FRE_DATAWORD_COUNT(info); dataword_size = dataword_size_enum_to_size(SFRAME_V3_FRE_DATAWORD_SIZE(info)); - if (!dataword_count || !dataword_size) + if (!dataword_size) return -EINVAL; if (cur + (dataword_count * dataword_size) > sec->fres_end) @@ -240,6 +240,17 @@ static __always_inline int __read_fre(struct sframe_section *sec, if (fde_type != SFRAME_FDE_TYPE_DEFAULT) return -EINVAL; + if (!dataword_count) { + /* + * A FRE without data words indicates RA undefined / + * outermost frame. + */ + cfa_off = 0; + ra_off = 0; + fp_off = 0; + goto done; + } + UNSAFE_GET_USER_INC(cfa_off, cur, dataword_size, Efault); dataword_count--; @@ -260,6 +271,7 @@ static __always_inline int __read_fre(struct sframe_section *sec, if (dataword_count) return -EINVAL; +done: fre->size = addr_size + 1 + (dataword_count * dataword_size); fre->ip_off = ip_off; fre->cfa_off = cfa_off; @@ -326,6 +338,7 @@ static __always_inline int __find_fre(struct sframe_section *sec, frame->ra_off = fre->ra_off; frame->fp_off = fre->fp_off; frame->use_fp = SFRAME_V3_FRE_CFA_BASE_REG_ID(fre->info) == SFRAME_BASE_REG_FP; + frame->outermost = SFRAME_V3_FRE_RA_UNDEFINED_P(fre->info); return 0; } diff --git a/kernel/unwind/sframe.h b/kernel/unwind/sframe.h index fc2908e92c7b..ed111fd0d702 100644 --- a/kernel/unwind/sframe.h +++ b/kernel/unwind/sframe.h @@ -77,5 +77,6 @@ struct sframe_fda_v3 { #define SFRAME_V3_FRE_DATAWORD_COUNT(info) (((info) >> 1) & 0xf) #define SFRAME_V3_FRE_DATAWORD_SIZE(info) (((info) >> 5) & 0x3) #define SFRAME_V3_AARCH64_FRE_MANGLED_RA_P(info) (((info) >> 7) & 0x1) +#define SFRAME_V3_FRE_RA_UNDEFINED_P(info) (SFRAME_V3_FRE_DATAWORD_COUNT(info) == 0) #endif /* _SFRAME_H */ -- 2.51.0