Re: [PATCH] arm: fix page faults in do_alignment

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

 



Hi Jing,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on arm/for-next]
[cannot apply to v5.3-rc6 next-20190830]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Jing-Xiangfeng/arm-fix-page-faults-in-do_alignment/20190831-173417
base:   git://git.armlinux.org.uk/~rmk/linux-arm.git for-next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@xxxxxxxxx>

All warnings (new ones prefixed by >>):

   arch/arm/mm/alignment.c: In function 'do_alignment':
>> arch/arm/mm/alignment.c:792:28: warning: passing argument 1 of '__copy_from_user' makes pointer from integer without a cast [-Wint-conversion]
      fault = __copy_from_user(tinstr,
                               ^~~~~~
   In file included from include/linux/sched/task.h:11:0,
                    from include/linux/sched/signal.h:9,
                    from arch/arm/mm/alignment.c:20:
   include/linux/uaccess.h:67:1: note: expected 'void *' but argument is of type 'u16 {aka short unsigned int}'
    __copy_from_user(void *to, const void __user *from, unsigned long n)
    ^~~~~~~~~~~~~~~~
   arch/arm/mm/alignment.c:801:30: warning: passing argument 1 of '__copy_from_user' makes pointer from integer without a cast [-Wint-conversion]
        fault = __copy_from_user(tinst2,
                                 ^~~~~~
   In file included from include/linux/sched/task.h:11:0,
                    from include/linux/sched/signal.h:9,
                    from arch/arm/mm/alignment.c:20:
   include/linux/uaccess.h:67:1: note: expected 'void *' but argument is of type 'u16 {aka short unsigned int}'
    __copy_from_user(void *to, const void __user *from, unsigned long n)
    ^~~~~~~~~~~~~~~~
   arch/arm/mm/alignment.c:813:28: warning: passing argument 1 of '__copy_from_user' makes pointer from integer without a cast [-Wint-conversion]
      fault = __copy_from_user(instr,
                               ^~~~~
   In file included from include/linux/sched/task.h:11:0,
                    from include/linux/sched/signal.h:9,
                    from arch/arm/mm/alignment.c:20:
   include/linux/uaccess.h:67:1: note: expected 'void *' but argument is of type 'long unsigned int'
    __copy_from_user(void *to, const void __user *from, unsigned long n)
    ^~~~~~~~~~~~~~~~

vim +/__copy_from_user +792 arch/arm/mm/alignment.c

   769	
   770	static int
   771	do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
   772	{
   773		union offset_union uninitialized_var(offset);
   774		unsigned long instr = 0, instrptr;
   775		int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
   776		unsigned int type;
   777		mm_segment_t fs;
   778		unsigned int fault;
   779		u16 tinstr = 0;
   780		int isize = 4;
   781		int thumb2_32b = 0;
   782	
   783		if (interrupts_enabled(regs))
   784			local_irq_enable();
   785	
   786		instrptr = instruction_pointer(regs);
   787	
   788		fs = get_fs();
   789		set_fs(KERNEL_DS);
   790		if (thumb_mode(regs)) {
   791			u16 *ptr = (u16 *)(instrptr & ~1);
 > 792			fault = __copy_from_user(tinstr,
   793					(__force const void __user *)ptr,
   794					sizeof(tinstr));
   795			tinstr = __mem_to_opcode_thumb16(tinstr);
   796			if (!fault) {
   797				if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
   798				    IS_T32(tinstr)) {
   799					/* Thumb-2 32-bit */
   800					u16 tinst2 = 0;
   801					fault = __copy_from_user(tinst2,
   802							(__force const void __user *)(ptr+1),
   803							sizeof(tinst2));
   804					tinst2 = __mem_to_opcode_thumb16(tinst2);
   805					instr = __opcode_thumb32_compose(tinstr, tinst2);
   806					thumb2_32b = 1;
   807				} else {
   808					isize = 2;
   809					instr = thumb2arm(tinstr);
   810				}
   811			}
   812		} else {
   813			fault = __copy_from_user(instr,
   814					(__force const void __user *)instrptr,
   815					sizeof(instr));
   816			instr = __mem_to_opcode_arm(instr);
   817		}
   818	
   819		set_fs(fs);
   820		if (fault) {
   821			type = TYPE_FAULT;
   822			goto bad_or_fault;
   823		}
   824	
   825		if (user_mode(regs))
   826			goto user;
   827	
   828		ai_sys += 1;
   829		ai_sys_last_pc = (void *)instruction_pointer(regs);
   830	
   831	 fixup:
   832	
   833		regs->ARM_pc += isize;
   834	
   835		switch (CODING_BITS(instr)) {
   836		case 0x00000000:	/* 3.13.4 load/store instruction extensions */
   837			if (LDSTHD_I_BIT(instr))
   838				offset.un = (instr & 0xf00) >> 4 | (instr & 15);
   839			else
   840				offset.un = regs->uregs[RM_BITS(instr)];
   841	
   842			if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */
   843			    (instr & 0x001000f0) == 0x001000f0)   /* LDRSH */
   844				handler = do_alignment_ldrhstrh;
   845			else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
   846				 (instr & 0x001000f0) == 0x000000f0)   /* STRD */
   847				handler = do_alignment_ldrdstrd;
   848			else if ((instr & 0x01f00ff0) == 0x01000090) /* SWP */
   849				goto swp;
   850			else
   851				goto bad;
   852			break;
   853	
   854		case 0x04000000:	/* ldr or str immediate */
   855			if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */
   856				goto bad;
   857			offset.un = OFFSET_BITS(instr);
   858			handler = do_alignment_ldrstr;
   859			break;
   860	
   861		case 0x06000000:	/* ldr or str register */
   862			offset.un = regs->uregs[RM_BITS(instr)];
   863	
   864			if (IS_SHIFT(instr)) {
   865				unsigned int shiftval = SHIFT_BITS(instr);
   866	
   867				switch(SHIFT_TYPE(instr)) {
   868				case SHIFT_LSL:
   869					offset.un <<= shiftval;
   870					break;
   871	
   872				case SHIFT_LSR:
   873					offset.un >>= shiftval;
   874					break;
   875	
   876				case SHIFT_ASR:
   877					offset.sn >>= shiftval;
   878					break;
   879	
   880				case SHIFT_RORRRX:
   881					if (shiftval == 0) {
   882						offset.un >>= 1;
   883						if (regs->ARM_cpsr & PSR_C_BIT)
   884							offset.un |= 1 << 31;
   885					} else
   886						offset.un = offset.un >> shiftval |
   887								  offset.un << (32 - shiftval);
   888					break;
   889				}
   890			}
   891			handler = do_alignment_ldrstr;
   892			break;
   893	
   894		case 0x08000000:	/* ldm or stm, or thumb-2 32bit instruction */
   895			if (thumb2_32b) {
   896				offset.un = 0;
   897				handler = do_alignment_t32_to_handler(&instr, regs, &offset);
   898			} else {
   899				offset.un = 0;
   900				handler = do_alignment_ldmstm;
   901			}
   902			break;
   903	
   904		default:
   905			goto bad;
   906		}
   907	
   908		if (!handler)
   909			goto bad;
   910		type = handler(addr, instr, regs);
   911	
   912		if (type == TYPE_ERROR || type == TYPE_FAULT) {
   913			regs->ARM_pc -= isize;
   914			goto bad_or_fault;
   915		}
   916	
   917		if (type == TYPE_LDST)
   918			do_alignment_finish_ldst(addr, instr, regs, offset);
   919	
   920		return 0;
   921	
   922	 bad_or_fault:
   923		if (type == TYPE_ERROR)
   924			goto bad;
   925		/*
   926		 * We got a fault - fix it up, or die.
   927		 */
   928		do_bad_area(addr, fsr, regs);
   929		return 0;
   930	
   931	 swp:
   932		pr_err("Alignment trap: not handling swp instruction\n");
   933	
   934	 bad:
   935		/*
   936		 * Oops, we didn't handle the instruction.
   937		 */
   938		pr_err("Alignment trap: not handling instruction "
   939			"%0*lx at [<%08lx>]\n",
   940			isize << 1,
   941			isize == 2 ? tinstr : instr, instrptr);
   942		ai_skipped += 1;
   943		return 1;
   944	
   945	 user:
   946		ai_user += 1;
   947	
   948		if (ai_usermode & UM_WARN)
   949			printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
   950			       "Address=0x%08lx FSR 0x%03x\n", current->comm,
   951				task_pid_nr(current), instrptr,
   952				isize << 1,
   953				isize == 2 ? tinstr : instr,
   954			        addr, fsr);
   955	
   956		if (ai_usermode & UM_FIXUP)
   957			goto fixup;
   958	
   959		if (ai_usermode & UM_SIGNAL) {
   960			force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
   961		} else {
   962			/*
   963			 * We're about to disable the alignment trap and return to
   964			 * user space.  But if an interrupt occurs before actually
   965			 * reaching user space, then the IRQ vector entry code will
   966			 * notice that we were still in kernel space and therefore
   967			 * the alignment trap won't be re-enabled in that case as it
   968			 * is presumed to be always on from kernel space.
   969			 * Let's prevent that race by disabling interrupts here (they
   970			 * are disabled on the way back to user space anyway in
   971			 * entry-common.S) and disable the alignment trap only if
   972			 * there is no work pending for this thread.
   973			 */
   974			raw_local_irq_disable();
   975			if (!(current_thread_info()->flags & _TIF_WORK_MASK))
   976				set_cr(cr_no_alignment);
   977		}
   978	
   979		return 0;
   980	}
   981	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Attachment: .config.gz
Description: application/gzip


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux