Hi Richard

On 2022/6/21 上午12:23, Richard Henderson wrote:
On 6/20/22 02:33, Song Gao wrote:
+static int restore_sigcontext(CPULoongArchState *env,
+                               struct target_sigcontext *sc)
+{
+    int i;
+    int ret = 0;
+    struct extctx_layout extctx;
+
+    memset(&extctx, 0, sizeof(struct extctx_layout));
+
+    __get_user(extctx.flags, &sc->sc_flags);
+
+    ret = parse_extcontext(sc, &extctx);
+    if (ret < 0) {
+        goto bad;
+    }
+
+    __get_user(env->pc, &sc->sc_pc);
+    for (i = 1; i < 32; ++i) {
+        __get_user(env->gpr[i], &sc->sc_regs[i]);
+    }
+
+    if (extctx.fpu.addr) {
+        copy_fpu_from_sigcontext(env, &extctx);
+        restore_fp_status(env);
+    }
+bad:
+    return ret;
+}

This is missing lock_user/unlock_user somewhere.
You can't use the double-underscore __get/__put_user without having done that.

My understanding is that the struct exctx need lock_user_struct/unlock_user_struct,  then we can use __get/__put the struct extctx.
You can use the non-underscore get_user in parse_extcontext, and separately lock the target_fpu_context.  Failures must goto invalid.


+void setup_rt_frame(int sig, struct target_sigaction *ka,
+                    target_siginfo_t *info,
+                    target_sigset_t *set, CPULoongArchState *env)
+{
+    struct target_rt_sigframe *frame;
+    struct extctx_layout extctx;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame), &extctx);
+    trace_user_setup_rt_frame(env, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }

Similarly, this lock...

+
+    tswap_siginfo(&frame->rs_info, info);
+
+    __put_user(0, &frame->rs_uc.tuc_flags);
+    __put_user(0, &frame->rs_uc.tuc_link);
+    target_save_altstack(&frame->rs_uc.tuc_stack, env);
+
+    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext, &extctx);

... fails to cover the extra memory allocated for extctx.

This is why I suggested statically allocating the extra
pieces of the signal frame *on write*.  You obviously
cannot rely on the signal frame being identical on
signal return -- the guest is allowed to create any valid
context to give to rt_sigreturn.

I don’t know if my understanding is correct,

we can put the exctx or target_fpu_context into target_rt_sigframe, like this:
struct target_rt_sigframe {
    struct target_siginfo rs_info;
    struct target_ucontext rs_uc;
    struct extctx_layout rs_ext;
};
This way  that we just need lo lock/unlock target_rt_sigframe on setup_sigcontext/restore_sigcontext,

Thanks.
Song Gao


Reply via email to