Page MenuHomeFreeBSD

Avoid sign extension of value passed to kva_alloc from uma_zone_reserve_kva
ClosedPublic

Authored by zbb on Aug 9 2015, 5:16 PM.
Tags
None
Referenced Files
Unknown Object (File)
Mar 9 2024, 1:48 PM
Unknown Object (File)
Jan 18 2024, 7:36 AM
Unknown Object (File)
Dec 22 2023, 9:03 PM
Unknown Object (File)
Dec 13 2023, 2:54 PM
Unknown Object (File)
Sep 20 2023, 8:32 AM
Unknown Object (File)
Sep 10 2023, 9:43 AM
Unknown Object (File)
Aug 24 2023, 9:57 AM
Unknown Object (File)
Jul 25 2023, 2:09 AM
Subscribers

Details

Summary

Fixes "panic: vm_radix_reserve_kva: unable to reserve KVA" on 64-bit architecture
caused by sign extension of "pages * UMA_SLAB_SIZE" value passed to kva_alloc()
which takes unsigned long argument.

In the erroneus case that triggered this bug, the number of pages
to allocate in uma_zone_reserve_kva() was 0x8ebe6, that gave the
total number of bytes to allocate equal to 0x8ebe6000 (int).
This was then sign extended in kva_alloc() to 0xffffffff8ebe6000
(unsigned long).

Reviewed by:
Submitted by:
Obtained from: Semihalf
Sponsored by: The FreeBSD Foundation
Differential Revision:

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

zbb retitled this revision from to Avoid sign extension of value passed to kva_alloc from uma_zone_reserve_kva.
zbb updated this object.
zbb edited the test plan for this revision. (Show Details)
zbb added reviewers: alc, kib.
zbb set the repository for this revision to rS FreeBSD src repository - subversion.
zbb added a subscriber: arm64.

vm_pindex_t usually considered more appropriate type for the page counts (it was discussed heatly at least once). IMO you could use u_int for pages, the only drawback is that you would need to cast it to vm_offset_t when multiplying in the kva_alloc() argument calculation.

In D3346#68013, @kib wrote:

vm_pindex_t usually considered more appropriate type for the page counts (it was discussed heatly at least once). IMO you could use u_int for pages, the only drawback is that you would need to cast it to vm_offset_t when multiplying in the kva_alloc() argument calculation.

You mean cast it to vm_size_t (not vm_offset_t)? You are right, this may be a better idea to use u_int and cast it explicitly to vm_size_t . If this is what you think is right, I will update the diff.

Who exactly argues for the use of vm_pindex_t to represent *all* page counts? It's not me. :-) And, from your comment, I don't think that it's you either. Am I wrong? There are cases where vm_pindex_t is needed to represent a page count, but this isn't one of them. In this case, the use of vm_pindex_t would force 32-bit machines that will never have address spaces larger than 2^32 bytes to do 64-bit arithmetic unnecessarily.

In D3346#68014, @zbb wrote:

You mean cast it to vm_size_t (not vm_offset_t)? You are right, this may be a better idea to use u_int and cast it explicitly to vm_size_t . If this is what you think is right, I will update the diff.

This is fine with me.

In D3346#68014, @zbb wrote:
In D3346#68013, @kib wrote:

vm_pindex_t usually considered more appropriate type for the page counts (it was discussed heatly at least once). IMO you could use u_int for pages, the only drawback is that you would need to cast it to vm_offset_t when multiplying in the kva_alloc() argument calculation.

You mean cast it to vm_size_t (not vm_offset_t)? You are right, this may be a better idea to use u_int and cast it explicitly to vm_size_t . If this is what you think is right, I will update the diff.

What's being calculated is a size rather than an address, so I would use vm_size_t rather than vm_offset_t.

In D3346#68018, @alc wrote:
In D3346#68014, @zbb wrote:
In D3346#68013, @kib wrote:

vm_pindex_t usually considered more appropriate type for the page counts (it was discussed heatly at least once). IMO you could use u_int for pages, the only drawback is that you would need to cast it to vm_offset_t when multiplying in the kva_alloc() argument calculation.

You mean cast it to vm_size_t (not vm_offset_t)? You are right, this may be a better idea to use u_int and cast it explicitly to vm_size_t . If this is what you think is right, I will update the diff.

What's being calculated is a size rather than an address, so I would use vm_size_t rather than vm_offset_t.

Yes, I thought so. That is why I assumed this was a typo. I'm updating the diff now.

zbb edited edge metadata.
zbb removed rS FreeBSD src repository - subversion as the repository for this revision.
kib edited edge metadata.

It may be reasonable to change KPI of uma_zone_reserve_kva() to take unsigned count, in the separate change.

This revision is now accepted and ready to land.Aug 10 2015, 2:17 PM
alc edited edge metadata.
This revision was automatically updated to reflect the committed changes.

Thank you all for your review. Just sent the change.