Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[sfrench/cifs-2.6.git] / arch / x86 / kernel / process.c
index 5e94c4354d4e44101f14c205fc009a6f7c9dc50a..bd2a11ca5dd6c91681adef03b2cfdf270d3d9657 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/desc.h>
 #include <asm/prctl.h>
 #include <asm/spec-ctrl.h>
+#include <asm/io_bitmap.h>
 #include <asm/proto.h>
 
 #include "process.h"
@@ -72,18 +73,9 @@ __visible DEFINE_PER_CPU_PAGE_ALIGNED(struct tss_struct, cpu_tss_rw) = {
 #ifdef CONFIG_X86_32
                .ss0 = __KERNEL_DS,
                .ss1 = __KERNEL_CS,
-               .io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
 #endif
+               .io_bitmap_base = IO_BITMAP_OFFSET_INVALID,
         },
-#ifdef CONFIG_X86_32
-        /*
-         * Note that the .io_bitmap member must be extra-big. This is because
-         * the CPU will access an additional byte beyond the end of the IO
-         * permission bitmap. The extra byte must be all 1 bits, and must
-         * be within the limit.
-         */
-       .io_bitmap              = { [0 ... IO_BITMAP_LONGS] = ~0 },
-#endif
 };
 EXPORT_PER_CPU_SYMBOL(cpu_tss_rw);
 
@@ -110,28 +102,89 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 void exit_thread(struct task_struct *tsk)
 {
        struct thread_struct *t = &tsk->thread;
-       unsigned long *bp = t->io_bitmap_ptr;
        struct fpu *fpu = &t->fpu;
 
-       if (bp) {
-               struct tss_struct *tss = &per_cpu(cpu_tss_rw, get_cpu());
-
-               t->io_bitmap_ptr = NULL;
-               clear_thread_flag(TIF_IO_BITMAP);
-               /*
-                * Careful, clear this in the TSS too:
-                */
-               memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
-               t->io_bitmap_max = 0;
-               put_cpu();
-               kfree(bp);
-       }
+       if (test_thread_flag(TIF_IO_BITMAP))
+               io_bitmap_exit();
 
        free_vm86(t);
 
        fpu__drop(fpu);
 }
 
+static int set_new_tls(struct task_struct *p, unsigned long tls)
+{
+       struct user_desc __user *utls = (struct user_desc __user *)tls;
+
+       if (in_ia32_syscall())
+               return do_set_thread_area(p, -1, utls, 0);
+       else
+               return do_set_thread_area_64(p, ARCH_SET_FS, tls);
+}
+
+int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
+                   unsigned long arg, struct task_struct *p, unsigned long tls)
+{
+       struct inactive_task_frame *frame;
+       struct fork_frame *fork_frame;
+       struct pt_regs *childregs;
+       int ret = 0;
+
+       childregs = task_pt_regs(p);
+       fork_frame = container_of(childregs, struct fork_frame, regs);
+       frame = &fork_frame->frame;
+
+       frame->bp = 0;
+       frame->ret_addr = (unsigned long) ret_from_fork;
+       p->thread.sp = (unsigned long) fork_frame;
+       p->thread.io_bitmap = NULL;
+       memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
+
+#ifdef CONFIG_X86_64
+       savesegment(gs, p->thread.gsindex);
+       p->thread.gsbase = p->thread.gsindex ? 0 : current->thread.gsbase;
+       savesegment(fs, p->thread.fsindex);
+       p->thread.fsbase = p->thread.fsindex ? 0 : current->thread.fsbase;
+       savesegment(es, p->thread.es);
+       savesegment(ds, p->thread.ds);
+#else
+       p->thread.sp0 = (unsigned long) (childregs + 1);
+       /*
+        * Clear all status flags including IF and set fixed bit. 64bit
+        * does not have this initialization as the frame does not contain
+        * flags. The flags consistency (especially vs. AC) is there
+        * ensured via objtool, which lacks 32bit support.
+        */
+       frame->flags = X86_EFLAGS_FIXED;
+#endif
+
+       /* Kernel thread ? */
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               kthread_frame_init(frame, sp, arg);
+               return 0;
+       }
+
+       frame->bx = 0;
+       *childregs = *current_pt_regs();
+       childregs->ax = 0;
+       if (sp)
+               childregs->sp = sp;
+
+#ifdef CONFIG_X86_32
+       task_user_gs(p) = get_user_gs(current_pt_regs());
+#endif
+
+       /* Set a new TLS for the child thread? */
+       if (clone_flags & CLONE_SETTLS)
+               ret = set_new_tls(p, tls);
+
+       if (!ret && unlikely(test_tsk_thread_flag(current, TIF_IO_BITMAP)))
+               io_bitmap_share(p);
+
+       return ret;
+}
+
 void flush_thread(void)
 {
        struct task_struct *tsk = current;
@@ -269,31 +322,96 @@ void arch_setup_new_exec(void)
        }
 }
 
-static inline void switch_to_bitmap(struct thread_struct *prev,
-                                   struct thread_struct *next,
-                                   unsigned long tifp, unsigned long tifn)
+#ifdef CONFIG_X86_IOPL_IOPERM
+static inline void tss_invalidate_io_bitmap(struct tss_struct *tss)
 {
-       struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
+       /*
+        * Invalidate the I/O bitmap by moving io_bitmap_base outside the
+        * TSS limit so any subsequent I/O access from user space will
+        * trigger a #GP.
+        *
+        * This is correct even when VMEXIT rewrites the TSS limit
+        * to 0x67 as the only requirement is that the base points
+        * outside the limit.
+        */
+       tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET_INVALID;
+}
 
-       if (tifn & _TIF_IO_BITMAP) {
-               /*
-                * Copy the relevant range of the IO bitmap.
-                * Normally this is 128 bytes or less:
-                */
-               memcpy(tss->io_bitmap, next->io_bitmap_ptr,
-                      max(prev->io_bitmap_max, next->io_bitmap_max));
+static inline void switch_to_bitmap(unsigned long tifp)
+{
+       /*
+        * Invalidate I/O bitmap if the previous task used it. This prevents
+        * any possible leakage of an active I/O bitmap.
+        *
+        * If the next task has an I/O bitmap it will handle it on exit to
+        * user mode.
+        */
+       if (tifp & _TIF_IO_BITMAP)
+               tss_invalidate_io_bitmap(this_cpu_ptr(&cpu_tss_rw));
+}
+
+static void tss_copy_io_bitmap(struct tss_struct *tss, struct io_bitmap *iobm)
+{
+       /*
+        * Copy at least the byte range of the incoming tasks bitmap which
+        * covers the permitted I/O ports.
+        *
+        * If the previous task which used an I/O bitmap had more bits
+        * permitted, then the copy needs to cover those as well so they
+        * get turned off.
+        */
+       memcpy(tss->io_bitmap.bitmap, iobm->bitmap,
+              max(tss->io_bitmap.prev_max, iobm->max));
+
+       /*
+        * Store the new max and the sequence number of this bitmap
+        * and a pointer to the bitmap itself.
+        */
+       tss->io_bitmap.prev_max = iobm->max;
+       tss->io_bitmap.prev_sequence = iobm->sequence;
+}
+
+/**
+ * tss_update_io_bitmap - Update I/O bitmap before exiting to usermode
+ */
+void tss_update_io_bitmap(void)
+{
+       struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
+       u16 *base = &tss->x86_tss.io_bitmap_base;
+
+       if (test_thread_flag(TIF_IO_BITMAP)) {
+               struct thread_struct *t = &current->thread;
+
+               if (IS_ENABLED(CONFIG_X86_IOPL_IOPERM) && t->iopl_emul == 3) {
+                       *base = IO_BITMAP_OFFSET_VALID_ALL;
+               } else {
+                       struct io_bitmap *iobm = t->io_bitmap;
+                       /*
+                        * Only copy bitmap data when the sequence number
+                        * differs. The update time is accounted to the
+                        * incoming task.
+                        */
+                       if (tss->io_bitmap.prev_sequence != iobm->sequence)
+                               tss_copy_io_bitmap(tss, iobm);
+
+                       /* Enable the bitmap */
+                       *base = IO_BITMAP_OFFSET_VALID_MAP;
+               }
                /*
-                * Make sure that the TSS limit is correct for the CPU
-                * to notice the IO bitmap.
+                * Make sure that the TSS limit is covering the io bitmap.
+                * It might have been cut down by a VMEXIT to 0x67 which
+                * would cause a subsequent I/O access from user space to
+                * trigger a #GP because tbe bitmap is outside the TSS
+                * limit.
                 */
                refresh_tss_limit();
-       } else if (tifp & _TIF_IO_BITMAP) {
-               /*
-                * Clear any possible leftover bits:
-                */
-               memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
+       } else {
+               tss_invalidate_io_bitmap(tss);
        }
 }
+#else /* CONFIG_X86_IOPL_IOPERM */
+static inline void switch_to_bitmap(unsigned long tifp) { }
+#endif
 
 #ifdef CONFIG_SMP
 
@@ -505,7 +623,8 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
 
        tifn = READ_ONCE(task_thread_info(next_p)->flags);
        tifp = READ_ONCE(task_thread_info(prev_p)->flags);
-       switch_to_bitmap(prev, next, tifp, tifn);
+
+       switch_to_bitmap(tifp);
 
        propagate_user_return_notify(prev_p, next_p);