Clear excess parts of contexts when finalizing
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 27 Jul 2016 23:28:28 +0000 (19:28 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 29 Jul 2016 21:43:07 +0000 (17:43 -0400)
When we copy out the context from pcpui, we copy the entire struct
user_context.  However, when we fill the context, the amount we copy in
depends on the type.  Hypothetically, if a user has a smaller TF than
the previous resident, such as a SW TF running where a VM TF recently
existed, then the user could see some of the fields of the previous
resident.

By doing this during finalization, we limit the impact of the memset to
when we could give the context back to the user, i.e. after
finalization.

In the process, I moved the finalize routines from trap64.h to trap.c.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/trap.c
kern/arch/x86/trap64.h

index f818cae..e2aeace 100644 (file)
@@ -1108,10 +1108,59 @@ void handle_vmexit(struct vm_trapframe *tf)
        proc_restartcore();
 }
 
-void x86_finalize_vmtf(struct vm_trapframe *tf)
+/* Partial contexts for HW and SW TFs have the user's gs in MSR_KERNEL_GS_BASE.
+ * The kernel's gs is loaded into gs.  We need to put the kernel's gs into
+ * KERNEL_GS_BASE so the core is ready to run another full context, save the
+ * user's {GS,FS}_BASE into their TF so it can run on another core, and keep GS
+ * loaded with the current GS (the kernel's). */
+static void x86_finalize_hwtf(struct hw_trapframe *tf)
+{
+       tf->tf_gsbase = read_msr(MSR_KERNEL_GS_BASE);
+       write_msr(MSR_KERNEL_GS_BASE, read_gsbase());
+       tf->tf_fsbase = read_fsbase();
+       x86_hwtf_clear_partial(tf);
+}
+
+static void x86_finalize_swtf(struct sw_trapframe *tf)
+{
+       tf->tf_gsbase = read_msr(MSR_KERNEL_GS_BASE);
+       write_msr(MSR_KERNEL_GS_BASE, read_gsbase());
+       tf->tf_fsbase = read_fsbase();
+       x86_swtf_clear_partial(tf);
+}
+
+static void x86_finalize_vmtf(struct vm_trapframe *tf)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
 
        x86_vmtf_clear_partial(tf);
        unload_guest_pcore(pcpui->cur_proc, pcpui->guest_pcoreid);
 }
+
+/* Makes sure that the user context is fully saved into ctx and not split across
+ * the struct and HW, meaning it is not a "partial context".
+ *
+ * Be careful to zero out any part of the ctx struct not in use, to avoid
+ * leaking information from other processes. */
+void arch_finalize_ctx(struct user_context *ctx)
+{
+       if (!arch_ctx_is_partial(ctx))
+               return;
+       switch (ctx->type) {
+       case ROS_HW_CTX:
+               x86_finalize_hwtf(&ctx->tf.hw_tf);
+               memset((uint8_t*)&ctx->tf + sizeof(struct hw_trapframe), 0,
+                          sizeof(ctx->tf) - sizeof(struct hw_trapframe));
+               break;
+       case ROS_SW_CTX:
+               x86_finalize_swtf(&ctx->tf.sw_tf);
+               memset((uint8_t*)&ctx->tf + sizeof(struct sw_trapframe), 0,
+                          sizeof(ctx->tf) - sizeof(struct sw_trapframe));
+               break;
+       case ROS_VM_CTX:
+               x86_finalize_vmtf(&ctx->tf.vm_tf);
+               memset((uint8_t*)&ctx->tf + sizeof(struct vm_trapframe), 0,
+                          sizeof(ctx->tf) - sizeof(struct vm_trapframe));
+               break;
+       }
+}
index 1c9b8ae..6475e2e 100644 (file)
@@ -171,45 +171,3 @@ static inline bool arch_ctx_is_partial(struct user_context *ctx)
        }
        return FALSE;
 }
-
-/* Partial contexts for HW and SW TFs have the user's gs in MSR_KERNEL_GS_BASE.
- * The kernel's gs is loaded into gs.  We need to put the kernel's gs into
- * KERNEL_GS_BASE so the core is ready to run another full context, save the
- * user's {GS,FS}_BASE into their TF so it can run on another core, and keep GS
- * loaded with the current GS (the kernel's). */
-static inline void x86_finalize_hwtf(struct hw_trapframe *tf)
-{
-       tf->tf_gsbase = read_msr(MSR_KERNEL_GS_BASE);
-       write_msr(MSR_KERNEL_GS_BASE, read_gsbase());
-       tf->tf_fsbase = read_fsbase();
-       x86_hwtf_clear_partial(tf);
-}
-
-static inline void x86_finalize_swtf(struct sw_trapframe *tf)
-{
-       tf->tf_gsbase = read_msr(MSR_KERNEL_GS_BASE);
-       write_msr(MSR_KERNEL_GS_BASE, read_gsbase());
-       tf->tf_fsbase = read_fsbase();
-       x86_swtf_clear_partial(tf);
-}
-
-void x86_finalize_vmtf(struct vm_trapframe *tf);
-
-/* Makes sure that the user context is fully saved into ctx and not split across
- * the struct and HW, meaning it is not a "partial context". */
-static inline void arch_finalize_ctx(struct user_context *ctx)
-{
-       if (!arch_ctx_is_partial(ctx))
-               return;
-       switch (ctx->type) {
-       case ROS_HW_CTX:
-               x86_finalize_hwtf(&ctx->tf.hw_tf);
-               break;
-       case ROS_SW_CTX:
-               x86_finalize_swtf(&ctx->tf.sw_tf);
-               break;
-       case ROS_VM_CTX:
-               x86_finalize_vmtf(&ctx->tf.vm_tf);
-               break;
-       }
-}