Re: [4.1 backport trouble] Re: BUGreport: fix minor infoleak in get_user_ex()
From: Al Viro
Date: Fri Oct 28 2016 - 15:34:34 EST
On Fri, Oct 28, 2016 at 12:40:33PM -0400, Joe Korty wrote:
> Backporting 548acf19234d to 4.1.35 does indeed fix the
> issue. However, it is not clear to my _why_ it works,
> so it might be better that someone else push the backport
> to stable.
Because the trick used in fixup_exception() prior to that commit depended
upon the handler being very close to faulting instruction.
# define _ASM_EXTABLE_EX(from,to) \
.pushsection "__ex_table","a" ; \
.balign 8 ; \
.long (from) - . ; \
.long (to) - . + 0x7ffffff0 ; \
.popsection
puts a recognizable value (handler + offset a bit under 2G) into
->fixup and in fixup_exception() we had
if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
/* Special hack for uaccess_err */
current_thread_info()->uaccess_err = 1;
new_ip -= 0x7ffffff0;
}
checking that the value in ->fixup is just below 2G from the faulting
instruction. So _ASM_EXTABLE_EX relied upon the handler very close to
the faulting insn, and worked only because all of its uses had
been "set the ->uaccess_err and continue immediately past the faulting
insn". When the kludge in fixup_exception() had been eliminated
(check what it and _ASM_EXTABLE_EX do these days) this restriction has
disappeared, so the mainline commit had no problems. Backport to 4.1
had it run afoul of that restriction, with the results you've observed -
this "handler + constant offset" had _not_ been recognized as that magic and
had been interpreted as handler being about 2G away from its actual location.
That's where the bogus RIP in your oopsen have come from.