lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <6faed1e2-13bc-68ba-7726-91924cf21b66@gmail.com>
Date:   Tue, 19 Jan 2021 18:24:49 +0100
From:   Bodo Stroesser <bostroesser@...il.com>
To:     Jason Gunthorpe <jgg@...pe.ca>
Cc:     Douglas Gilbert <dgilbert@...erlog.com>,
        linux-scsi@...r.kernel.org, linux-block@...r.kernel.org,
        target-devel@...r.kernel.org, linux-rdma@...r.kernel.org,
        linux-kernel@...r.kernel.org, martin.petersen@...cle.com,
        jejb@...ux.vnet.ibm.com, ddiss@...e.de, bvanassche@....org
Subject: Re: [PATCH v6 1/4] sgl_alloc_order: remove 4 GiB limit, sgl_free()
 warning

On 19.01.21 00:48, Jason Gunthorpe wrote:
> On Mon, Jan 18, 2021 at 10:22:56PM +0100, Bodo Stroesser wrote:
>> On 18.01.21 21:24, Jason Gunthorpe wrote:
>>> On Mon, Jan 18, 2021 at 03:08:51PM -0500, Douglas Gilbert wrote:
>>>> On 2021-01-18 1:28 p.m., Jason Gunthorpe wrote:
>>>>> On Mon, Jan 18, 2021 at 11:30:03AM -0500, Douglas Gilbert wrote:
>>>>>
>>>>>> After several flawed attempts to detect overflow, take the fastest
>>>>>> route by stating as a pre-condition that the 'order' function argument
>>>>>> cannot exceed 16 (2^16 * 4k = 256 MiB).
>>>>>
>>>>> That doesn't help, the point of the overflow check is similar to
>>>>> overflow checks in kcalloc: to prevent the routine from allocating
>>>>> less memory than the caller might assume.
>>>>>
>>>>> For instance ipr_store_update_fw() uses request_firmware() (which is
>>>>> controlled by userspace) to drive the length argument to
>>>>> sgl_alloc_order(). If userpace gives too large a value this will
>>>>> corrupt kernel memory.
>>>>>
>>>>> So this math:
>>>>>
>>>>>      	nent = round_up(length, PAGE_SIZE << order) >> (PAGE_SHIFT + order);
>>>>
>>>> But that check itself overflows if order is too large (e.g. 65).
>>>
>>> I don't reall care about order. It is always controlled by the kernel
>>> and it is fine to just require it be low enough to not
>>> overflow. length is the data under userspace control so math on it
>>> must be checked for overflow.
>>>
>>>> Also note there is another pre-condition statement in that function's
>>>> definition, namely that length cannot be 0.
>>>
>>> I don't see callers checking for that either, if it is true length 0
>>> can't be allowed it should be blocked in the function
>>>
>>> Jason
>>>
>>
>> A already said, I also think there should be a check for length or
>> rather nent overflow.
>>
>> I like the easy to understand check in your proposed code:
>>
>> 	if (length >> (PAGE_SHIFT + order) >= UINT_MAX)
>> 		return NULL;
>>
>>
>> But I don't understand, why you open-coded the nent calculation:
>>
>> 	nent = length >> (PAGE_SHIFT + order);
>> 	if (length & ((1ULL << (PAGE_SHIFT + order)) - 1))
>> 		nent++;
> 
> It is necessary to properly check for overflow, because the easy to
> understand check doesn't prove that round_up will work, only that >>
> results in something that fits in an int and that +1 won't overflow
> the int.
> 
>> Wouldn't it be better to keep the original line instead:
>>
>> 	nent = round_up(length, PAGE_SIZE << order) >> (PAGE_SHIFT + order);
> 
> This can overflow inside the round_up

I had a second look into math.h, but I don't find any reason why 
round_up could overflow. Can you give a hint please?

Regarding the overflow checks: would it be a good idea to not check
length >> (PAGE_SHIFT + order) in the beginning, but check nalloc
immediately before the kmalloc_array() as the only overrun check:

	if ((unsigned long long)nalloc << (PAGE_SHIFT + order) < length)
		return NULL;

-Bodo

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ