Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix gregs usage on 32-bit powerpc #8

Merged
merged 1 commit into from
Oct 28, 2019
Merged

Conversation

q66
Copy link
Contributor

@q66 q66 commented Oct 28, 2019

The old code was wrong as uc_regs is not a registers array, but rather an mcontext_t pointer on glibc, therefore indexing it goes way past the memory bounds. The actual registers array is gregs inside the mcontext_t structure.

On non-glibc libcs (as well as inside the kernel headers that are the reference), the structure is defined differently, with uc_mcontext being an actual value member just like on ppc64, so we can use that. On glibc/ppc32, mcontext_t is an union of uc_regs and regs pointers, with the value of the member being a pointer to where the real uc_mcontext field would be.

Basically, this is how the structure looks like in the kernel as well as on musl etc:

typedef struct {
    gregset_t gregs;
    fpregset_t fpregs;
    vrregset_t vrregs;
} mcontext_t;

typedef struct {
    ... some fields ...
    mcontext_t *uc_regs; /* this is set to &ctx->uc_mcontext */
    ... more fields ....
    int __pad[3];
    mcontext_t uc_mcontext;
} ucontext_t;

on glibc the layout is broken, supposedly for compatibility with extremely ancient kernels (think pre-2.4 series) and looks like this instead:

typedef struct {
    ... some fields ...
    union {
        mcontext_t *uc_regs; /* this is set to &ctx->__pad */
        struct pt_regs *regs;
    } uc_mcontext;
    ... more fields ....
    char __pre_pad[12];
    char __pad[sizeof(mcontext_t)]; /* this would normally be uc_mcontext */
} ucontext_t;

The old code was wrong as `uc_regs` is not a registers array,
but rather an `mcontext_t` pointer on glibc, therefore indexing
it goes way past the memory bounds. The actual registers array
is `gregs` inside the `mcontext_t` structure.

On non-glibc libcs (as well as inside the kernel definitions),
the structure is defined differently, with `uc_mcontext` being
an actual value member just like on ppc64, so we can use that.
On glibc/ppc32, `mcontext_t` is an union of `uc_regs` and `regs`
pointers, with the value of the member being a pointer to where
the real `uc_mcontext` field would be.
@dvzrv
Copy link
Collaborator

dvzrv commented Oct 28, 2019

Thanks for the detailed explanation and the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants