Skip to content

Commit 545aa52

Browse files
brenns10osandov
authored andcommitted
mm, slab: Fix test failures on kernels with SLOB
In the Fixes commit, as part of the refactor, the _identify_kernel_address() function started open-coding the get_slab_object_info() function. Unfortunately, this resulted in the function failing when CONFIG_SLOB was enabled, since the AttributeError for accessing "slab.slab_cache" was not caught. Open-coding was done to avoid the duplicate bounds check for in_direct_map. In fact, in_direct_map seems like a useful helper itself, and by factoring it out of _find_containing_slab() and into its callers, we can simplify things a bit. Since _find_containing_slab() can handle SLOB, this fixes the test failure too. Fixes: 48e0c51 ("helper.common.memory: recognize vmap addresses in identify_address()") Signed-off-by: Stephen Brennan <[email protected]>
1 parent 46da1ca commit 545aa52

File tree

3 files changed

+27
-41
lines changed

3 files changed

+27
-41
lines changed

drgn/helpers/common/memory.py

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,12 @@
1414
from typing import Any, Dict, Optional
1515

1616
import drgn
17-
from drgn import (
18-
FaultError,
19-
IntegerLike,
20-
Object,
21-
PlatformFlags,
22-
Program,
23-
SymbolKind,
24-
cast,
25-
)
17+
from drgn import FaultError, IntegerLike, Object, PlatformFlags, Program, SymbolKind
2618
from drgn.helpers.common.format import escape_ascii_string
2719
from drgn.helpers.common.prog import takes_program_or_default
28-
from drgn.helpers.linux.mm import (
29-
PageSlab,
30-
compound_head,
31-
find_vmap_area,
32-
pfn_to_virt,
33-
virt_to_page,
34-
)
20+
from drgn.helpers.linux.mm import find_vmap_area, in_direct_map
3521
from drgn.helpers.linux.pid import for_each_task
36-
from drgn.helpers.linux.slab import _get_slab_cache_helper, _get_slab_type
22+
from drgn.helpers.linux.slab import _find_containing_slab, _get_slab_cache_helper
3723

3824
__all__ = (
3925
"identify_address",
@@ -111,27 +97,17 @@ def _identify_kernel_address(
11197
prog: Program, addr: int, cache: Optional[Dict[Any, Any]] = None
11298
) -> Optional[str]:
11399
try:
114-
direct_map_start = pfn_to_virt(prog["min_low_pfn"]).value_()
115-
direct_map_end = (pfn_to_virt(prog["max_low_pfn"]) + prog["PAGE_SIZE"]).value_()
116-
in_direct_map = direct_map_start <= addr < direct_map_end
100+
direct_map = in_direct_map(prog, addr)
117101
except NotImplementedError:
118102
# Virtual address translation isn't implemented for this
119103
# architecture.
120-
in_direct_map = False
121-
if in_direct_map:
122-
page = virt_to_page(prog, addr)
104+
direct_map = False
123105

124-
try:
125-
head_page = compound_head(page)
126-
is_slab = PageSlab(head_page)
127-
except FaultError:
128-
return None
129-
130-
if is_slab:
131-
slab = cast(_get_slab_type(prog), head_page)
132-
slab_info = _get_slab_cache_helper(slab.slab_cache).object_info(
133-
head_page, slab, addr
134-
)
106+
if direct_map:
107+
result = _find_containing_slab(prog, addr)
108+
if result is not None:
109+
slab_cache, page, slab = result
110+
slab_info = _get_slab_cache_helper(slab_cache).object_info(page, slab, addr)
135111
if slab_info:
136112
cache_name = escape_ascii_string(
137113
slab_info.slab_cache.name.string_(), escape_backslash=True

drgn/helpers/linux/mm.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,3 +1377,15 @@ def totalram_pages(prog: Program) -> int:
13771377
return prog["_totalram_pages"].counter.value_()
13781378
except KeyError:
13791379
return prog["totalram_pages"].value_()
1380+
1381+
1382+
@takes_program_or_default
1383+
def in_direct_map(prog: Program, addr: IntegerLike) -> bool:
1384+
"""
1385+
Return True if an address is within the kernel's direct memory mapping
1386+
:param addr: address to check
1387+
"""
1388+
addr = operator.index(addr)
1389+
start_addr = pfn_to_virt(prog["min_low_pfn"]).value_()
1390+
end_addr = (pfn_to_virt(prog["max_low_pfn"]) + prog["PAGE_SIZE"]).value_()
1391+
return start_addr <= addr < end_addr

drgn/helpers/linux/slab.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
_get_PageSlab_impl,
4040
compound_head,
4141
for_each_page,
42+
in_direct_map,
4243
page_to_virt,
43-
pfn_to_virt,
4444
virt_to_page,
4545
)
4646
from drgn.helpers.linux.percpu import per_cpu_ptr
@@ -464,12 +464,6 @@ def slab_cache_for_each_allocated_object(
464464
def _find_containing_slab(
465465
prog: Program, addr: int
466466
) -> Optional[Tuple[Object, Object, Object]]:
467-
start_addr = pfn_to_virt(prog["min_low_pfn"]).value_()
468-
end_addr = (pfn_to_virt(prog["max_low_pfn"]) + prog["PAGE_SIZE"]).value_()
469-
if addr < start_addr or addr >= end_addr:
470-
# Not a directly mapped address
471-
return None
472-
473467
page = virt_to_page(prog, addr)
474468

475469
try:
@@ -516,6 +510,8 @@ def slab_object_info(prog: Program, addr: IntegerLike) -> "Optional[SlabObjectIn
516510
if not.
517511
"""
518512
addr = operator.index(addr)
513+
if not in_direct_map(prog, addr):
514+
return None
519515
result = _find_containing_slab(prog, addr)
520516
if result is None:
521517
return None
@@ -568,6 +564,8 @@ def find_containing_slab_cache(prog: Program, addr: IntegerLike) -> Object:
568564
:return: ``struct kmem_cache *`` containing *addr*, or ``NULL`` if *addr*
569565
is not from a slab cache.
570566
"""
567+
if not in_direct_map(prog, addr):
568+
return NULL(prog, "struct kmem_cache *")
571569
result = _find_containing_slab(prog, operator.index(addr))
572570
if result is None:
573571
return NULL(prog, "struct kmem_cache *")

0 commit comments

Comments
 (0)