diff options
author | Neil Schemenauer <nas-github@arctrix.com> | 2021-10-21 21:05:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-21 21:05:46 (GMT) |
commit | 0224b7180b280794b9fba62057b278ffb536c86f (patch) | |
tree | 965341e9bfb8556f710c79a050ab1405f184eb95 | |
parent | 887a55705bb6c05a507c2886c9978a9e0cff0dd7 (diff) | |
download | cpython-0224b7180b280794b9fba62057b278ffb536c86f.zip cpython-0224b7180b280794b9fba62057b278ffb536c86f.tar.gz cpython-0224b7180b280794b9fba62057b278ffb536c86f.tar.bz2 |
bpo-45526: obmalloc radix use 64 addr bits (GH-29062)
Co-authored-by: Ćukasz Langa <lukasz@langa.pl>
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst | 3 | ||||
-rw-r--r-- | Objects/obmalloc.c | 55 |
2 files changed, 38 insertions, 20 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst new file mode 100644 index 0000000..c35e5f5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst @@ -0,0 +1,3 @@ +In obmalloc, set ADDRESS_BITS to not ignore any bits (ignored 16 before). That is +safer in the case that the kernel gives user-space virtual addresses that span +a range greater than 48 bits. diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 2eddb2c..4e17bf4 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1280,21 +1280,30 @@ _Py_GetAllocatedBlocks(void) #if WITH_PYMALLOC_RADIX_TREE /*==========================================================================*/ -/* radix tree for tracking arena usage +/* radix tree for tracking arena usage. If enabled, used to implement + address_in_range(). - bit allocation for keys + memory address bit allocation for keys - 64-bit pointers and 2^20 arena size: - 16 -> ignored (POINTER_BITS - ADDRESS_BITS) - 10 -> MAP_TOP - 10 -> MAP_MID - 8 -> MAP_BOT + 64-bit pointers, IGNORE_BITS=0 and 2^20 arena size: + 15 -> MAP_TOP_BITS + 15 -> MAP_MID_BITS + 14 -> MAP_BOT_BITS + 20 -> ideal aligned arena + ---- + 64 + + 64-bit pointers, IGNORE_BITS=16, and 2^20 arena size: + 16 -> IGNORE_BITS + 10 -> MAP_TOP_BITS + 10 -> MAP_MID_BITS + 8 -> MAP_BOT_BITS 20 -> ideal aligned arena ---- 64 32-bit pointers and 2^18 arena size: - 14 -> MAP_BOT + 14 -> MAP_BOT_BITS 18 -> ideal aligned arena ---- 32 @@ -1306,11 +1315,16 @@ _Py_GetAllocatedBlocks(void) /* number of bits in a pointer */ #define POINTER_BITS 64 -/* Current 64-bit processors are limited to 48-bit physical addresses. For - * now, the top 17 bits of addresses will all be equal to bit 2**47. If that - * changes in the future, this must be adjusted upwards. +/* High bits of memory addresses that will be ignored when indexing into the + * radix tree. Setting this to zero is the safe default. For most 64-bit + * machines, setting this to 16 would be safe. The kernel would not give + * user-space virtual memory addresses that have significant information in + * those high bits. The main advantage to setting IGNORE_BITS > 0 is that less + * virtual memory will be used for the top and middle radix tree arrays. Those + * arrays are allocated in the BSS segment and so will typically consume real + * memory only if actually accessed. */ -#define ADDRESS_BITS 48 +#define IGNORE_BITS 0 /* use the top and mid layers of the radix tree */ #define USE_INTERIOR_NODES @@ -1318,7 +1332,7 @@ _Py_GetAllocatedBlocks(void) #elif SIZEOF_VOID_P == 4 #define POINTER_BITS 32 -#define ADDRESS_BITS 32 +#define IGNORE_BITS 0 #else @@ -1332,6 +1346,9 @@ _Py_GetAllocatedBlocks(void) # error "arena size must be < 2^32" #endif +/* the lower bits of the address that are not ignored */ +#define ADDRESS_BITS (POINTER_BITS - IGNORE_BITS) + #ifdef USE_INTERIOR_NODES /* number of bits used for MAP_TOP and MAP_MID nodes */ #define INTERIOR_BITS ((ADDRESS_BITS - ARENA_BITS + 2) / 3) @@ -1360,11 +1377,9 @@ _Py_GetAllocatedBlocks(void) #define MAP_MID_INDEX(p) ((AS_UINT(p) >> MAP_MID_SHIFT) & MAP_MID_MASK) #define MAP_TOP_INDEX(p) ((AS_UINT(p) >> MAP_TOP_SHIFT) & MAP_TOP_MASK) -#if ADDRESS_BITS > POINTER_BITS -/* Return non-physical address bits of a pointer. Those bits should be same - * for all valid pointers if ADDRESS_BITS set correctly. Linux has support for - * 57-bit address space (Intel 5-level paging) but will not currently give - * those addresses to user space. +#if IGNORE_BITS > 0 +/* Return the ignored part of the pointer address. Those bits should be same + * for all valid pointers if IGNORE_BITS is set correctly. */ #define HIGH_BITS(p) (AS_UINT(p) >> ADDRESS_BITS) #else @@ -1416,7 +1431,7 @@ static arena_map_bot_t * arena_map_get(block *p, int create) { #ifdef USE_INTERIOR_NODES - /* sanity check that ADDRESS_BITS is correct */ + /* sanity check that IGNORE_BITS is correct */ assert(HIGH_BITS(p) == HIGH_BITS(&arena_map_root)); int i1 = MAP_TOP_INDEX(p); if (arena_map_root.ptrs[i1] == NULL) { @@ -1476,7 +1491,7 @@ arena_map_get(block *p, int create) static int arena_map_mark_used(uintptr_t arena_base, int is_used) { - /* sanity check that ADDRESS_BITS is correct */ + /* sanity check that IGNORE_BITS is correct */ assert(HIGH_BITS(arena_base) == HIGH_BITS(&arena_map_root)); arena_map_bot_t *n_hi = arena_map_get((block *)arena_base, is_used); if (n_hi == NULL) { |