diff mbox series

next/master bisection: boot on qemu_i386

Message ID 5dcf1f39.1c69fb81.409da.a39c@mx.google.com
State New
Headers show
Series next/master bisection: boot on qemu_i386 | expand

Commit Message

kernelci.org bot Nov. 15, 2019, 9:57 p.m. UTC
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* This automated bisection report was sent to you on the basis  *
* that you may be involved with the breaking commit it has      *
* found.  No manual investigation has been done to verify it,   *
* and the root cause of the problem may be somewhere else.      *
*                                                               *
* If you do send a fix, please include this trailer:            *
*   Reported-by: "kernelci.org bot" <bot@kernelci.org>          *
*                                                               *
* Hope this helps!                                              *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

next/master bisection: boot on qemu_i386

Summary:
  Start:      5a6fcbeabe3e Add linux-next specific files for 20191115
  Details:    https://kernelci.org/boot/id/5dcebd0459b514519dcf54be
  Plain log:  https://storage.kernelci.org//next/master/next-20191115/i386/i386_defconfig/gcc-8/lab-baylibre/boot-qemu_i386.txt
  HTML log:   https://storage.kernelci.org//next/master/next-20191115/i386/i386_defconfig/gcc-8/lab-baylibre/boot-qemu_i386.html
  Result:     bc1aca4ab8e0 x86/process: Unify copy_thread_tls()

Checks:
  revert:     PASS
  verify:     PASS

Parameters:
  Tree:       next
  URL:        git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
  Branch:     master
  Target:     qemu_i386
  CPU arch:   i386
  Lab:        lab-baylibre
  Compiler:   gcc-8
  Config:     i386_defconfig
  Test suite: boot

Breaking commit found:

-------------------------------------------------------------------------------
commit bc1aca4ab8e08c01678e14138bea2fc433cd8068
Author: Thomas Gleixner <tglx@linutronix.de>
Date:   Mon Nov 11 23:03:16 2019 +0100

    x86/process: Unify copy_thread_tls()
    
    While looking at the TSS io bitmap it turned out that any change in that
    area would require identical changes to copy_thread_tls(). The 32 and 64
    bit variants share sufficient code to consolidate them into a common
    function to avoid duplication of upcoming modifications.
    
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

    Acked-by: Andy Lutomirski <luto@kernel.org>


-------------------------------------------------------------------------------


Git bisection log:

-------------------------------------------------------------------------------
git bisect start
# good: [633739b2fedb6617d782ca252797b7a8ad754347] rbd: silence bogus uninitialized warning in rbd_object_map_update_finish()
git bisect good 633739b2fedb6617d782ca252797b7a8ad754347
# bad: [5a6fcbeabe3e20459ed8504690b2515dacc5246f] Add linux-next specific files for 20191115
git bisect bad 5a6fcbeabe3e20459ed8504690b2515dacc5246f
# good: [280c9e8802370ed562bf1360fb6906c91fd3c190] Merge remote-tracking branch 'crypto/master'
git bisect good 280c9e8802370ed562bf1360fb6906c91fd3c190
# good: [c49494c35c91edb2013a696c5ab335789c5d3df4] Merge remote-tracking branch 'devicetree/for-next'
git bisect good c49494c35c91edb2013a696c5ab335789c5d3df4
# bad: [518d37a6ac8907ce017751fd985a53fa8a354e6f] Merge remote-tracking branch 'char-misc/char-misc-next'
git bisect bad 518d37a6ac8907ce017751fd985a53fa8a354e6f
# bad: [3d75c03b3bf024c7f25d57da072e0ffacee52499] Merge remote-tracking branch 'edac/edac-for-next'
git bisect bad 3d75c03b3bf024c7f25d57da072e0ffacee52499
# good: [9dc21c69c61512356dc002266e5b10636f75e3f2] Merge branch 'x86/urgent'
git bisect good 9dc21c69c61512356dc002266e5b10636f75e3f2
# good: [8e970f74efde16ae67b33eead1d2f9b6c59b25a6] Merge branch 'efi/core'
git bisect good 8e970f74efde16ae67b33eead1d2f9b6c59b25a6
# good: [5eb263ef08b5014cfc2539a838f39d2fd3531423] spi: pxa2xx: Add missed security checks
git bisect good 5eb263ef08b5014cfc2539a838f39d2fd3531423
# bad: [3b0a842355f77f12dcf71a61b02b49b3cbc5ed1c] Merge branch 'locking/core'
git bisect bad 3b0a842355f77f12dcf71a61b02b49b3cbc5ed1c
# bad: [3e4d603f40ddaf797067dedfe07c07357c901386] selftests/x86/iopl: Extend test to cover IOPL emulation
git bisect bad 3e4d603f40ddaf797067dedfe07c07357c901386
# bad: [78a53d4aabebbda7328aadf6a2821cf75d8d089d] x86/ioperm: Move iobitmap data into a struct
git bisect bad 78a53d4aabebbda7328aadf6a2821cf75d8d089d
# bad: [f07d5e256894dc74266c7639f44e68dcfc961aa3] x86/iopl: Cleanup include maze
git bisect bad f07d5e256894dc74266c7639f44e68dcfc961aa3
# bad: [bc1aca4ab8e08c01678e14138bea2fc433cd8068] x86/process: Unify copy_thread_tls()
git bisect bad bc1aca4ab8e08c01678e14138bea2fc433cd8068
# good: [a66770766fb3152b38ef324b9ed5e98e6d9b89b2] x86/ptrace: Prevent truncation of bitmap size
git bisect good a66770766fb3152b38ef324b9ed5e98e6d9b89b2
# first bad commit: [bc1aca4ab8e08c01678e14138bea2fc433cd8068] x86/process: Unify copy_thread_tls()
-------------------------------------------------------------------------------

Comments

Thomas Gleixner Nov. 15, 2019, 10:28 p.m. UTC | #1
On Fri, 15 Nov 2019, kernelci.org bot wrote:
> -------------------------------------------------------------------------------

> commit bc1aca4ab8e08c01678e14138bea2fc433cd8068

> Author: Thomas Gleixner <tglx@linutronix.de>

> Date:   Mon Nov 11 23:03:16 2019 +0100

> 

>     x86/process: Unify copy_thread_tls()


Does the patch below fix it for you?

Thanks,

	tglx
---
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -148,6 +148,7 @@ int copy_thread_tls(unsigned long clone_
 	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. */
 	frame->flags = X86_EFLAGS_FIXED;
 #endif
Sebastian Andrzej Siewior Nov. 16, 2019, 12:06 p.m. UTC | #2
On 2019-11-15 23:28:49 [+0100], Thomas Gleixner wrote:
> Does the patch below fix it for you?


I can confirm that -next from yesterday with i386_defconfig doesn't boot
on qemu and boots with this change. (I had to disable selinux because it
did not compile otherwise here).

Tested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>


> Thanks,

> 

> 	tglx


Sebastian
diff mbox series

Patch

diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 332eb3525867..5057a8ed100b 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -361,5 +361,11 @@  extern int do_get_thread_area(struct task_struct *p, int idx,
 extern int do_set_thread_area(struct task_struct *p, int idx,
 			      struct user_desc __user *info, int can_allocate);
 
+#ifdef CONFIG_X86_64
+# define do_set_thread_area_64(p, s, t)	do_arch_prctl_64(p, s, t)
+#else
+# define do_set_thread_area_64(p, s, t)	(0)
+#endif
+
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_X86_PTRACE_H */
diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h
index 18a4b6890fa8..0e059b73437b 100644
--- a/arch/x86/include/asm/switch_to.h
+++ b/arch/x86/include/asm/switch_to.h
@@ -103,7 +103,17 @@  static inline void update_task_stack(struct task_struct *task)
 	if (static_cpu_has(X86_FEATURE_XENPV))
 		load_sp0(task_top_of_stack(task));
 #endif
+}
 
+static inline void kthread_frame_init(struct inactive_task_frame *frame,
+				      unsigned long fun, unsigned long arg)
+{
+	frame->bx = fun;
+#ifdef CONFIG_X86_32
+	frame->di = arg;
+#else
+	frame->r12 = arg;
+#endif
 }
 
 #endif /* _ASM_X86_SWITCH_TO_H */
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 5e94c4354d4e..c09130a39954 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -132,6 +132,100 @@  void exit_thread(struct task_struct *tsk)
 	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);
+}
+
+static inline int copy_io_bitmap(struct task_struct *tsk)
+{
+	if (likely(!test_tsk_thread_flag(current, TIF_IO_BITMAP)))
+		return 0;
+
+	tsk->thread.io_bitmap_ptr = kmemdup(current->thread.io_bitmap_ptr,
+					    IO_BITMAP_BYTES, GFP_KERNEL);
+	if (!tsk->thread.io_bitmap_ptr) {
+		tsk->thread.io_bitmap_max = 0;
+		return -ENOMEM;
+	}
+	set_tsk_thread_flag(tsk, TIF_IO_BITMAP);
+	return 0;
+}
+
+static inline void free_io_bitmap(struct task_struct *tsk)
+{
+	if (tsk->thread.io_bitmap_ptr) {
+		kfree(tsk->thread.io_bitmap_ptr);
+		tsk->thread.io_bitmap_ptr = NULL;
+		tsk->thread.io_bitmap_max = 0;
+	}
+}
+
+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;
+
+	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_ptr = 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
+	/* Clear all status flags including IF and set fixed bit. */
+	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
+
+	ret = copy_io_bitmap(p);
+	if (ret)
+		return ret;
+
+	/* Set a new TLS for the child thread? */
+	if (clone_flags & CLONE_SETTLS) {
+		ret = set_new_tls(p, tls);
+		if (ret)
+			free_io_bitmap(p);
+	}
+	return ret;
+}
+
 void flush_thread(void)
 {
 	struct task_struct *tsk = current;
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index b8ceec4974fe..6c7d90527156 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -112,74 +112,6 @@  void release_thread(struct task_struct *dead_task)
 	release_vm86_irqs(dead_task);
 }
 
-int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
-	unsigned long arg, struct task_struct *p, unsigned long tls)
-{
-	struct pt_regs *childregs = task_pt_regs(p);
-	struct fork_frame *fork_frame = container_of(childregs, struct fork_frame, regs);
-	struct inactive_task_frame *frame = &fork_frame->frame;
-	struct task_struct *tsk;
-	int err;
-
-	/*
-	 * For a new task use the RESET flags value since there is no before.
-	 * All the status flags are zero; DF and all the system flags must also
-	 * be 0, specifically IF must be 0 because we context switch to the new
-	 * task with interrupts disabled.
-	 */
-	frame->flags = X86_EFLAGS_FIXED;
-	frame->bp = 0;
-	frame->ret_addr = (unsigned long) ret_from_fork;
-	p->thread.sp = (unsigned long) fork_frame;
-	p->thread.sp0 = (unsigned long) (childregs+1);
-	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
-
-	if (unlikely(p->flags & PF_KTHREAD)) {
-		/* kernel thread */
-		memset(childregs, 0, sizeof(struct pt_regs));
-		frame->bx = sp;		/* function */
-		frame->di = arg;
-		p->thread.io_bitmap_ptr = NULL;
-		return 0;
-	}
-	frame->bx = 0;
-	*childregs = *current_pt_regs();
-	childregs->ax = 0;
-	if (sp)
-		childregs->sp = sp;
-
-	task_user_gs(p) = get_user_gs(current_pt_regs());
-
-	p->thread.io_bitmap_ptr = NULL;
-	tsk = current;
-	err = -ENOMEM;
-
-	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
-		p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
-						IO_BITMAP_BYTES, GFP_KERNEL);
-		if (!p->thread.io_bitmap_ptr) {
-			p->thread.io_bitmap_max = 0;
-			return -ENOMEM;
-		}
-		set_tsk_thread_flag(p, TIF_IO_BITMAP);
-	}
-
-	err = 0;
-
-	/*
-	 * Set a new TLS for the child thread?
-	 */
-	if (clone_flags & CLONE_SETTLS)
-		err = do_set_thread_area(p, -1,
-			(struct user_desc __user *)tls, 0);
-
-	if (err && p->thread.io_bitmap_ptr) {
-		kfree(p->thread.io_bitmap_ptr);
-		p->thread.io_bitmap_max = 0;
-	}
-	return err;
-}
-
 void
 start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
 {
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index af64519b2695..e93a1b8fd7f9 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -371,81 +371,6 @@  void x86_gsbase_write_task(struct task_struct *task, unsigned long gsbase)
 	task->thread.gsbase = gsbase;
 }
 
-int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
-		unsigned long arg, struct task_struct *p, unsigned long tls)
-{
-	int err;
-	struct pt_regs *childregs;
-	struct fork_frame *fork_frame;
-	struct inactive_task_frame *frame;
-	struct task_struct *me = current;
-
-	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_ptr = NULL;
-
-	savesegment(gs, p->thread.gsindex);
-	p->thread.gsbase = p->thread.gsindex ? 0 : me->thread.gsbase;
-	savesegment(fs, p->thread.fsindex);
-	p->thread.fsbase = p->thread.fsindex ? 0 : me->thread.fsbase;
-	savesegment(es, p->thread.es);
-	savesegment(ds, p->thread.ds);
-	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
-
-	if (unlikely(p->flags & PF_KTHREAD)) {
-		/* kernel thread */
-		memset(childregs, 0, sizeof(struct pt_regs));
-		frame->bx = sp;		/* function */
-		frame->r12 = arg;
-		return 0;
-	}
-	frame->bx = 0;
-	*childregs = *current_pt_regs();
-
-	childregs->ax = 0;
-	if (sp)
-		childregs->sp = sp;
-
-	err = -ENOMEM;
-	if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
-		p->thread.io_bitmap_ptr = kmemdup(me->thread.io_bitmap_ptr,
-						  IO_BITMAP_BYTES, GFP_KERNEL);
-		if (!p->thread.io_bitmap_ptr) {
-			p->thread.io_bitmap_max = 0;
-			return -ENOMEM;
-		}
-		set_tsk_thread_flag(p, TIF_IO_BITMAP);
-	}
-
-	/*
-	 * Set a new TLS for the child thread?
-	 */
-	if (clone_flags & CLONE_SETTLS) {
-#ifdef CONFIG_IA32_EMULATION
-		if (in_ia32_syscall())
-			err = do_set_thread_area(p, -1,
-				(struct user_desc __user *)tls, 0);
-		else
-#endif
-			err = do_arch_prctl_64(p, ARCH_SET_FS, tls);
-		if (err)
-			goto out;
-	}
-	err = 0;
-out:
-	if (err && p->thread.io_bitmap_ptr) {
-		kfree(p->thread.io_bitmap_ptr);
-		p->thread.io_bitmap_max = 0;
-	}
-
-	return err;
-}
-
 static void
 start_thread_common(struct pt_regs *regs, unsigned long new_ip,
 		    unsigned long new_sp,