fcntl64 syscall causes user program stack corruption

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

After upgrading the Linux kernel to the recent version I've found that the 
Firefox browser from the Debian 8 (jessie),mipsel stopped working: it causes 
Bus Error exception at startup. The problem is reproducible with the QEMU 
virtual machine (qemu-system-mips64el). Thorough investigation revealed that 
the following syscall in /lib/mipsel-linux-gnu/libpthread-2.19.so causes 
Firefox's stack corruption at address 0x7fff5770:

	0x77fabd28:  li      v0,4220
	0x77fabd2c:  syscall

Relevant registers contents are as follows:

		  zero       at       v0       v1       a0       a1       a2       a3
	 R0   00000000 300004e0 0000107c 77c2e6b0 00000006 0000000e 7fff574c 7fff5770 

The stack corruption is caused by the following patch:

	commit 8c6657cb50cb037ff58b3f6a547c6569568f3527
	Author: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
	Date:   Mon Jun 26 23:51:31 2017 -0400
	
	    Switch flock copyin/copyout primitives to copy_{from,to}_user()
	    
	    ... and lose HAVE_ARCH_...; if copy_{to,from}_user() on an
	    architecture sucks badly enough to make it a problem, we have
	    a worse problem.
	    
	    Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx>

Reverting the change in put_compat_flock() introduced by the patch prevents the 
stack corruption:

	diff --git a/fs/fcntl.c b/fs/fcntl.c
	index 0345a46b8856..c55afd836e5d 100644
	--- a/fs/fcntl.c
	+++ b/fs/fcntl.c
	@@ -550,25 +550,27 @@ static int get_compat_flock64(struct flock *kfl, const struct compat_flock64 __u
	 
	 static int put_compat_flock(const struct flock *kfl, struct compat_flock __user *ufl)
	 {
	-       struct compat_flock fl;
	-
	-       memset(&fl, 0, sizeof(struct compat_flock));
	-       copy_flock_fields(&fl, kfl);
	-       if (copy_to_user(ufl, &fl, sizeof(struct compat_flock)))
	+       if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
	+           __put_user(kfl->l_type, &ufl->l_type) ||
	+           __put_user(kfl->l_whence, &ufl->l_whence) ||
	+           __put_user(kfl->l_start, &ufl->l_start) ||
	+           __put_user(kfl->l_len, &ufl->l_len) ||
	+           __put_user(kfl->l_pid, &ufl->l_pid))
	                return -EFAULT;
	        return 0;
	 }

Actually, the change introduced by the patch is ok. However, it looks like 
there is either a mismatch of sizeof(struct compat_flock) between the kernel 
and the user space or a mismatch of types used by the kernel and the user 
space.  Despite the fact that the user space is built for a different kernel 
version (3.16), I believe this syscall should work fine with it, since `struct 
compat_flock` did not change since the 3.16.  So, probably, the problem is 
caused by some discrepancies which were hidden until "Switch flock 
copyin/copyout..." patch.

Please, give your comments.

Regards,
Peter


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux