Example #1
0
def test_multiple_inputs():
    line = 'count'
    objs = [
        drgn.Object(MOCK_PROGRAM, 'void *', value=0),
        drgn.Object(MOCK_PROGRAM, 'int', value=0xfffff),
        drgn.Object(MOCK_PROGRAM, 'unsigned long *', value=0xdeadbeef),
    ]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0].value_() == 3
Example #2
0
def test_multi_void_ptr_input_value_match_lt():
    line = 'filter obj < 1'
    objs = [
        drgn.Object(MOCK_PROGRAM, 'void *', value=0),
        drgn.Object(MOCK_PROGRAM, 'void *', value=1),
        drgn.Object(MOCK_PROGRAM, 'void *', value=2),
    ]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0].value_() == 0
    assert ret[0].type_ == MOCK_PROGRAM.type('void *')
Example #3
0
def test_multiple_piped():
    line = 'echo'
    objs = [
        drgn.Object(MOCK_PROGRAM, 'void *', value=0),
        drgn.Object(MOCK_PROGRAM, 'int', value=1),
    ]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 2
    assert ret[0].value_() == 0
    assert ret[0].type_ == MOCK_PROGRAM.type('void *')
    assert ret[1].value_() == 1
    assert ret[1].type_ == MOCK_PROGRAM.type('int')
Example #4
0
def test_multi_void_ptr_input_value_match_ne() -> None:
    line = 'filter "obj != 1"'
    objs = [
        drgn.Object(MOCK_PROGRAM, 'void *', value=0),
        drgn.Object(MOCK_PROGRAM, 'void *', value=1),
        drgn.Object(MOCK_PROGRAM, 'void *', value=2),
    ]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 2
    assert ret[0].value_() == 0
    assert sdb.type_equals(ret[0].type_, MOCK_PROGRAM.type('void *'))
    assert ret[1].value_() == 2
    assert sdb.type_equals(ret[1].type_, MOCK_PROGRAM.type('void *'))
Example #5
0
 def _call_one(self, obj: drgn.Object) -> Iterable[drgn.Object]:
     try:
         sum_ = drgn_percpu.percpu_counter_sum(obj)
     except AttributeError as err:
         raise sdb.CommandError(self.name,
                                "input is not a percpu_counter") from err
     yield drgn.Object(sdb.get_prog(), type="s64", value=sum_)
Example #6
0
def test_single_void_ptr_input_value_no_match():
    line = 'filter obj == 1'
    objs = [drgn.Object(MOCK_PROGRAM, 'void *', value=0)]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert not ret
Example #7
0
    def call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
        try:
            for obj in objs:
                lhs = eval(self.lhs_code, {'__builtins__': None}, {'obj': obj})
                rhs = eval(self.rhs_code, {'__builtins__': None}, {'obj': obj})

                if not isinstance(lhs, drgn.Object):
                    raise sdb.CommandInvalidInputError(
                        self.name,
                        "left hand side has unsupported type ({})".format(
                            type(lhs).__name__))

                if isinstance(rhs, str):
                    lhs = lhs.string_().decode("utf-8")
                elif isinstance(rhs, int):
                    rhs = drgn.Object(self.prog, type=lhs.type_, value=rhs)
                elif isinstance(rhs, bool):
                    pass
                elif isinstance(rhs, drgn.Object):
                    pass
                else:
                    raise sdb.CommandInvalidInputError(
                        self.name,
                        "right hand side has unsupported type ({})".format(
                            type(rhs).__name__))

                if eval("lhs {} rhs".format(self.compare),
                        {'__builtins__': None}, {
                            'lhs': lhs,
                            'rhs': rhs
                        }):
                    yield obj
        except (AttributeError, TypeError, ValueError) as err:
            raise sdb.CommandError(self.name, str(err))
Example #8
0
def test_single_input():
    line = 'count'
    objs = [drgn.Object(MOCK_PROGRAM, 'void *', value=0)]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0].value_() == 1
Example #9
0
 def walk(self, obj: drgn.Object) -> Iterable[drgn.Object]:
     offset = int(obj.list_offset)
     first_node = obj.list_head.address_of_()
     node = first_node.next
     while node != first_node:
         yield drgn.Object(self.prog,
                           type="void *",
                           value=int(node) - offset)
         node = node.next
Example #10
0
def test_single_void_ptr_input_value_match():
    line = 'filter obj == 0'
    objs = [drgn.Object(MOCK_PROGRAM, 'void *', value=0)]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0].value_() == 0
    assert ret[0].type_ == MOCK_PROGRAM.type('void *')
Example #11
0
def test_test_piped_int():
    line = 'echo'
    objs = [drgn.Object(MOCK_PROGRAM, 'int', value=1)]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0].value_() == 1
    assert ret[0].type_ == MOCK_PROGRAM.type('int')
Example #12
0
def test_piped_input():
    line = 'echo'
    objs = [drgn.Object(MOCK_PROGRAM, 'void *', value=0)]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0].value_() == 0
    assert ret[0].type_ == MOCK_PROGRAM.type('void *')
Example #13
0
def test_piped_and_args_combo():
    line = 'echo 0 1'
    objs = [
        drgn.Object(MOCK_PROGRAM, 'void *', value=0),
        drgn.Object(MOCK_PROGRAM, 'int', value=1),
    ]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 4
    assert ret[0].value_() == 0
    assert ret[0].type_ == MOCK_PROGRAM.type('void *')
    assert ret[1].value_() == 1
    assert ret[1].type_ == MOCK_PROGRAM.type('int')
    assert ret[2].value_() == 0
    assert ret[2].type_ == MOCK_PROGRAM.type('void *')
    assert ret[3].value_() == 1
    assert ret[3].type_ == MOCK_PROGRAM.type('void *')
Example #14
0
def test_array_member_index():
    line = 'addr global_struct | member ts_array[0]'
    objs = []

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0] == drgn.Object(MOCK_PROGRAM,
                                 MOCK_PROGRAM.type('int'),
                                 value=0x0f0f0f0f)
Example #15
0
def test_char_array_input_string_match():
    line = 'filter obj == "foo"'
    objs = [drgn.Object(MOCK_PROGRAM, 'char [4]', value=b"foo")]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0].value_() == [102, 111, 111, 0]
    assert ret[0].string_() == b'foo'
    assert ret[0].type_ == MOCK_PROGRAM.type('char [4]')
Example #16
0
    def call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
        for obj in objs:
            yield obj

        for addr in self.args.addrs:
            try:
                value_ = int(addr, 0)
            except ValueError:
                raise sdb.CommandInvalidInputError(self.name, addr)
            yield drgn.Object(self.prog, "void *", value=value_)
Example #17
0
def test_one_member():
    line = 'addr global_struct | member ts_int'
    objs = []

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 1
    assert ret[0] == drgn.Object(MOCK_PROGRAM,
                                 MOCK_PROGRAM.type('int'),
                                 value=1)
Example #18
0
def test_multiple_members():
    line = 'addr global_struct | member ts_int ts_voidp'
    objs = []

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 2
    assert ret[0] == drgn.Object(MOCK_PROGRAM,
                                 MOCK_PROGRAM.type('int'),
                                 value=1)
    assert ret[1] == MOCK_PROGRAM['global_int'].address_of_()
Example #19
0
def test_multi_echo_combo():
    line = 'echo 2 3 | echo 4'
    objs = [
        drgn.Object(MOCK_PROGRAM, 'void *', value=0),
        drgn.Object(MOCK_PROGRAM, 'int', value=1),
    ]

    ret = invoke(MOCK_PROGRAM, objs, line)

    assert len(ret) == 5
    assert ret[0].value_() == 0
    assert ret[0].type_ == MOCK_PROGRAM.type('void *')
    assert ret[1].value_() == 1
    assert ret[1].type_ == MOCK_PROGRAM.type('int')
    assert ret[2].value_() == 2
    assert ret[2].type_ == MOCK_PROGRAM.type('void *')
    assert ret[3].value_() == 3
    assert ret[3].type_ == MOCK_PROGRAM.type('void *')
    assert ret[4].value_() == 4
    assert ret[4].type_ == MOCK_PROGRAM.type('void *')
Example #20
0
    def _helper(self, node: drgn.Object, offset: int) -> Iterable[drgn.Object]:
        if node == drgn.NULL(sdb.prog, node.type_):
            return

        lchild = node.avl_child[0]
        yield from self._helper(lchild, offset)

        obj = drgn.Object(sdb.prog, type="void *", value=int(node) - offset)
        yield obj

        rchild = node.avl_child[1]
        yield from self._helper(rchild, offset)
Example #21
0
def cache_get_free_pointer(cache: drgn.Object, p: drgn.Object) -> drgn.Object:
    """
    Get the next pointer in the freelist. Note, that this
    function assumes that CONFIG_SLAB_FREELIST_HARDENED
    is set in the target
    """
    assert sdb.type_canonical_name(cache.type_) == 'struct kmem_cache *'
    assert sdb.type_canonical_name(p.type_) == 'void *'
    hardened_ptr = p + cache.offset.value_()

    #
    # We basically do what `freelist_dereference()` and
    # `freelist_ptr()` do in the kernel source:
    #
    # ptr <- (void *)*(unsigned long *)(hardened_ptr)
    #
    intermediate_ulong = drgn.Object(sdb.get_prog(),
                                     type='unsigned long',
                                     address=hardened_ptr.value_())
    ptr = drgn.Object(sdb.get_prog(),
                      type='void *',
                      value=intermediate_ulong.value_())

    #
    # ptr_addr <- (unsigned long)hardened_ptr
    #
    ptr_addr = drgn.Object(sdb.get_prog(),
                           type='unsigned long',
                           value=hardened_ptr.value_())

    #
    # return (void *)((unsigned long)ptr ^ cache->random ^ ptr_addr)
    #
    ptr_as_ulong = drgn.Object(sdb.get_prog(),
                               type='unsigned long',
                               value=ptr.value_())
    clean_ptr_val = ptr_as_ulong.value_()
    clean_ptr_val ^= cache.random.value_()
    clean_ptr_val ^= ptr_addr.value_()
    return drgn.Object(sdb.get_prog(), type='void *', value=clean_ptr_val)
Example #22
0
def test_multi_void_ptr_input_value_match_ne():
    line = 'filter obj != 1'
    objs = [
        drgn.Object(MOCK_PROGRAM, 'void *', value=0),
        drgn.Object(MOCK_PROGRAM, 'void *', value=1),
        drgn.Object(MOCK_PROGRAM, 'void *', value=2),
    ]

    #
    # This throws an error for all the wrong reasons. The operator this
    # test is attempting to use is "!=", and due to a bug in the lexer
    # used within "invoke", this operator does not reach the "filter"
    # command. Instead, the lexer sees the "!" character and split the
    # string into the following parts:
    #
    #     1. filter obj
    #     2. = 1
    #
    # As a result, the "filter" command fails because it doesn't see a
    # comparison operator as input to it.
    #
    with pytest.raises(sdb.CommandInvalidInputError):
        invoke(MOCK_PROGRAM, objs, line)
Example #23
0
    def mock_object_find(prog: drgn.Program, name: str,
                         flags: drgn.FindObjectFlags,
                         filename: Optional[str]) -> Optional[drgn.Object]:
        assert filename is None
        assert flags == drgn.FindObjectFlags.ANY

        mock_objects = {
            'global_int': (int_type, 0xffffffffc0a8aee0),
            'global_void_ptr': (voidp_type, 0xffff88d26353c108),
            'global_struct': (struct_type, global_struct_addr),
        }

        if name in mock_objects:
            type_, addr = mock_objects[name]
            return drgn.Object(prog, type=type_, address=addr)
        return None
Example #24
0
    def walk(self, blkcg, q_id, parent_path):
        if not self.include_dying and \
           not (blkcg.css.flags.value_() & prog['CSS_ONLINE'].value_()):
            return

        name = BlkgIterator.blkcg_name(blkcg)
        path = parent_path + '/' + name if parent_path else name
        blkg = drgn.Object(prog, 'struct blkcg_gq',
                           address=radix_tree_lookup(blkcg.blkg_tree, q_id))
        if not blkg.address_:
            return

        self.blkgs.append((path if path else '/', blkg))

        for c in list_for_each_entry('struct blkcg',
                                     blkcg.css.children.address_of_(), 'css.sibling'):
            self.walk(c, q_id, path)
Example #25
0
 def _call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
     for obj in objs:
         #
         # We canonicalize the type just in case it is a typedef
         # to a pointer (e.g. typedef char* char_p).
         #
         obj_type = type_canonicalize(obj.type_)
         if obj_type.kind != drgn.TypeKind.POINTER:
             raise CommandError(
                 self.name,
                 f"'{obj.type_.type_name()}' is not a valid pointer type")
         if obj_type.type.type_name() == 'void':
             raise CommandError(self.name,
                                "cannot dereference a void pointer")
         yield drgn.Object(get_prog(),
                           type=obj.type_.type,
                           address=obj.value_())
Example #26
0
def create_object(type_: Union[str, drgn.Type], val: Any) -> drgn.Object:
    global prog
    return drgn.Object(prog, type_, value=val)
Example #27
0
if args.cgroup:
    for r in args.cgroup:
        if re_str is None:
            re_str = r
        else:
            re_str += '|' + r

filter_re = re.compile(re_str) if re_str else None

# Locate the roots
q_id = None
root_iocg = None
ioc = None

for i, ptr in radix_tree_for_each(blkcg_root.blkg_tree.address_of_()):
    blkg = drgn.Object(prog, 'struct blkcg_gq', address=ptr)
    try:
        if devname == blkg.q.kobj.parent.name.string_().decode('utf-8'):
            q_id = blkg.q.id.value_()
            if blkg.pd[plid]:
                root_iocg = container_of(blkg.pd[plid], 'struct ioc_gq', 'pd')
                ioc = root_iocg.ioc
            break
    except:
        pass

if ioc is None:
    err(f'Could not find ioc for {devname}')

if interval == 0:
    sys.exit(0)
Example #28
0
 def call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
     yield drgn.Object(sdb.prog,
                       type='unsigned long long',
                       value=sum(1 for _ in objs))
Example #29
0
def resolve_for_address(prog: drgn.Program, arg: str) -> drgn.Object:
    if is_hex(arg):
        return drgn.Object(prog, "void *", value=int(arg, 16))
    return prog[arg].address_of_()
Example #30
0
def test_char_array_input_object_match() -> None:
    line = 'filter "obj == obj"'
    objs = [drgn.Object(MOCK_PROGRAM, 'char [4]', value=b"foo")]

    with pytest.raises(sdb.CommandError):
        invoke(MOCK_PROGRAM, objs, line)