Re: faults on copy operations

Maxime Villard <[email protected]>
Newsgroups gmane.os.netbsd.ports.x86-64
Message-ID <[email protected]>
Le 29/04/2020 à 04:44, Chuck Silvers a écrit :
> On Sun, Apr 26, 2020 at 09:45:04PM +0200, Maxime Villard wrote:
>> Le 26/04/2020 à 21:26, Chuck Silvers a écrit :
>>> On Sat, Apr 25, 2020 at 09:50:26AM +0200, Maxime Villard wrote:
>>>> Small tactical mitigation I want to (re)introduce.
>>>>
>>>> The copyin and copyout functions (plus their ufetch and ustore variants)
>>>> register a specific handler, which causes page faults in kernel mode to
>>>> be dismissed as user faults. This way, when userland passes an unmapped
>>>> page to copyin for example, the kernel will page-fault but will consider
>>>> it as a non-fatal user fault.
>>>>
>>>> The problem I see, is that when discarding such faults, the kernel doesn't
>>>> check the VA that faulted, and this hides certain faults that should be
>>>> considered as fatal: those occuring on kernel pages, betraying a bug in the
>>>> caller of the copy functions.
>>>>
>>>> Suppose there is a crazy syscall that passes a user-controllable length to
>>>> copyout (something I've encountered already in the past). An attacker can
>>>> do a gigantic copyout and retrieve kernel memory until a page fault occurs
>>>> on an unmapped kernel page; the page fault will actually be dismissed, and
>>>> the syscall will just error out, meaning that the system remains alive and
>>>> the attacker remains alive too. With simple forms of heap re-modelling, and
>>>> by repeating this operation, the attacker could manage to dump strictly all
>>>> of the kernel memory.
>>>>
>>>> I want to apply this change [1], that causes the handler to panic if the
>>>> fault came from a kernel page. This isn't a very excellent mitigation, but
>>>> at least, it will expose bogus memory accesses and make it less easy for
>>>> severe buffer overflows to go unpunished.
>>>>
>>>> The change is based on KASSERTs I initially added in 2016:
>>>> 	https://mail-index.netbsd.org/source-changes/2016/09/16/msg077746.html
>>>> But which I quickly reverted without really understanding what was wrong
>>>> with them. In 2018 I realized that CR2 was getting accessed in non-page
>>>> faults, which was a bug:
>>>> 	https://mail-index.netbsd.org/source-changes/2018/02/25/msg092488.html
>>>> In retrospect I see that my KASSERTs were firing because of this bug. Now
>>>> I want to re-introduce these KASSERTs as panics.
>>>>
>>>> Maxime
>>>>
>>>> [1] https://m00nbsd.net/garbage/x86/copy-trap.diff
>>>
>>>
>>> Improving the detection of buggy copyin/out()s would be great, however
>>> any copyin/out where the both the kernel and user side are pageable
>>> can legitimately fail on either side.  The examples of this that I can
>>> think of right now are ubc_uiomove() and copyinargs().  Please make sure
>>> that we recover from such legitimate fault failures than treat a failure
>>> in such a situation as a bug.
>>
>> I am aware of that.
>>
>> My patch enforces the policy when the fault couldn't be resolved, AND for a
>> reason different than ENOMEM. The cases you mentioned therefore do not get
>> classified as fatal faults.
>>
>> Maxime
> 
> Kernel faults can legitimately fail for more reasons than just ENOMEM,
> for example they can fail with EIO if a page cannot be read back
> from a storage device.  Other error codes might also be legitimate,
> I haven't gone through all of them.

I see. In fact, there is just no way to make this work, because the error
code could be polluted by an underlying driver. Down the drain.

Maxime
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.