Beispiel #1
0
    def coerce(self, obj: drgn.Object) -> drgn.Object:
        """
        This function attemts to massage the input object into an object
        of a different type.
        """

        # same type is fine
        if obj.type_ == self.type:
            return obj

        # "void *" can be coerced to any pointer type
        if (obj.type_.kind is drgn.TypeKind.POINTER and
                obj.type_.primitive is drgn.PrimitiveType.C_VOID):
            return drgn.cast(self.type, obj)

        # integers can be coerced to any pointer typo
        if obj.type_.kind is drgn.TypeKind.INT:
            return drgn.cast(self.type, obj)

        # "type" can be coerced to "type *"
        if obj.type_.kind is not drgn.TypeKind.POINTER and obj.address_of_(
        ).type_ == self.type:
            return obj.address_of_()

        raise TypeError("can not coerce {} to {}".format(obj.type_, self.type))
Beispiel #2
0
def print_namespace(ns):
    print("mlx5_flow_namespace %lx" % ns.address_of_())
    prio_addr = ns.node.children.address_of_()
    for prio_node in list_for_each_entry('struct fs_node', prio_addr, 'list'):
        prio = cast("struct fs_prio *", prio_node)
        #         print("level 1 namespace")
        print_prio(prio)
        #         print(prio)

        n2_addr = prio.node.children.address_of_()
        for n2_node in list_for_each_entry('struct fs_node', n2_addr, 'list'):
            n2 = cast("struct mlx5_flow_namespace *", n2_node)
            #             print("level 2 prio")
            #             print(n2)

            p3_addr = n2.node.children.address_of_()
            for p3_node in list_for_each_entry('struct fs_node', p3_addr,
                                               'list'):
                p3 = cast("struct fs_prio *", p3_node)
                #                 print("level 3 prio")
                #                 print(p3)

                table_addr = p3.node.children.address_of_()
                for table_node in list_for_each_entry('struct fs_node',
                                                      table_addr, 'list'):
                    table = cast("struct mlx5_flow_table *", table_node)
                    #                     print("level 4 flow table")
                    print_table(table)
Beispiel #3
0
 def aux(node, index):
     if _is_internal_node(node, RADIX_TREE_INTERNAL_NODE):
         parent = _entry_to_node(node, RADIX_TREE_INTERNAL_NODE)
         for i, slot in enumerate(parent.slots):
             yield from aux(
                 cast(parent.type_, slot).read_(),
                 index + (i << parent.shift.value_()))
     elif node:
         yield index, cast('void *', node)
Beispiel #4
0
def get_cgroup():
    if len(sys.argv) == 1:
        return prog["cgrp_dfl_root"].cgrp
    task = find_task(prog, os.getpid())
    with open_dir(sys.argv[1], os.O_RDONLY) as fd:
        file_ = fget(task, fd)
        kn = cast("struct kernfs_node *",
                  file_.f_path.dentry.d_inode.i_private)
        return cast("struct cgroup *", kn.priv)
Beispiel #5
0
 def aux(node: Object, index: int) -> Iterator[Tuple[int, Object]]:
     if _is_internal_node(node, RADIX_TREE_INTERNAL_NODE):
         parent = _entry_to_node(node, RADIX_TREE_INTERNAL_NODE)
         for i, slot in enumerate(parent.slots):
             yield from aux(
                 cast(parent.type_, slot).read_(),
                 index + (i << parent.shift.value_()),
             )
     elif node:
         yield index, cast("void *", node)
Beispiel #6
0
def print_namespace(ns):
    prio_addr = ns.node.children.address_of_()
    for prio_node in list_for_each_entry('struct fs_node', prio_addr, 'list'):
        #         print(prio_node)
        prio = cast("struct fs_prio *", prio_node)
        #         print(prio)
        print_prio(prio, 0)
Beispiel #7
0
def _vmemmap(prog):
    try:
        # KASAN
        return cast('struct page *', prog['vmemmap_base'])
    except KeyError:
        # x86-64
        return Object(prog, 'struct page *', value=0xffffea0000000000)
Beispiel #8
0
 def _slab_freelist(slab: Object) -> Set[int]:
     # In SLAB, the freelist is an array of free object indices.
     freelist = cast(freelist_type, slab.freelist)
     return {
         freelist[i].value_()
         for i in range(slab.active, slab_cache_num)
     }
Beispiel #9
0
def radix_tree_lookup(root, index):
    """
    .. c:function:: void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)

    Look up the entry at a given index in a radix tree. If it is not found,
    this returns a ``NULL`` object.
    """
    node, RADIX_TREE_INTERNAL_NODE = _radix_tree_root_node(root)
    RADIX_TREE_MAP_MASK = node.slots.type_.length - 1
    while True:
        if not _is_internal_node(node, RADIX_TREE_INTERNAL_NODE):
            break
        parent = _entry_to_node(node, RADIX_TREE_INTERNAL_NODE)
        offset = (index >> parent.shift) & RADIX_TREE_MAP_MASK
        node = cast(parent.type_, parent.slots[offset]).read_()
    return cast('void *', node)
Beispiel #10
0
    def test_sk_tcpstate(self):
        with create_socket() as sock:
            task = find_task(self.prog, os.getpid())
            file = fget(task, sock.fileno())
            sk = cast("struct socket *", file.private_data).sk
            self.assertEqual(sk_tcpstate(sk), self.prog["TCP_CLOSE"])

            sock.bind(("localhost", 0))
            sock.listen()
            self.assertEqual(sk_tcpstate(sk), self.prog["TCP_LISTEN"])

            with socket.create_connection(
                    sock.getsockname()), sock.accept()[0] as sock2:
                file = fget(task, sock2.fileno())
                sk = cast("struct socket *", file.private_data).sk
                self.assertEqual(sk_tcpstate(sk), self.prog["TCP_ESTABLISHED"])
Beispiel #11
0
Datei: mm.py Projekt: cneira/drgn
def page_to_pfn(page):
    """
    .. c:function:: unsigned long page_to_pfn(struct page *page)

    Get the page frame number (PFN) of a page.
    """
    return cast("unsigned long", page - _vmemmap(page.prog_))
Beispiel #12
0
def hash(rhashtable, type, member):
    nodes = []

    tbl = rhashtable.tbl

    #     print('')
    #     print("rhashtable %lx" % rhashtable.address_of_())
    #     print("bucket_table %lx" % tbl)
    #     buckets = tbl.buckets
    #     print("buckets %lx" % buckets.address_of_())

    buckets = tbl.buckets
    size = tbl.size.value_()

    print("")
    for i in range(size):
        rhash_head = buckets[i]
        if type_exist("struct rhash_lock_head"):
            rhash_head = cast("struct rhash_head *", rhash_head)
            if rhash_head.value_() == 0:
                continue
        while True:
            if rhash_head.value_() & 1:
                break
            obj = container_of(rhash_head, type, member)
            nodes.append(obj)
            rhash_head = rhash_head.next

    return nodes
Beispiel #13
0
def _radix_tree_root_node(root):
    try:
        node = root.xa_head
    except AttributeError:
        return root.rnode.read_(), 1
    else:
        return cast("struct xa_node *", node).read_(), 2
Beispiel #14
0
def sk_tcpstate(sk):
    """
    .. c:function:: enum TcpState sk_tcpstate(struct sock *sk)

    Return the TCP protocol state of a socket.
    """
    return cast(sk.prog_["TCP_ESTABLISHED"].type_, sk.__sk_common.skc_state)
Beispiel #15
0
Datei: mm.py Projekt: cneira/drgn
def _vmemmap(prog):
    try:
        # KASAN
        return cast("struct page *", prog["vmemmap_base"])
    except KeyError:
        # x86-64
        return Object(prog, "struct page *", value=0xFFFFEA0000000000)
Beispiel #16
0
def print_files(files, n):
    for i in range(n):
        file = files[i]

        print("%2d" % i, end='\t')
        if file.f_op.value_() == eventpoll_fops:
            print_eventpoll(file)
        elif file.f_op.value_() == socket_file_ops:
            sock = Object(prog, "struct socket", address=file.private_data)
            sk = sock.sk
            if sock.ops.value_() == netlink_ops:
                netlink_sock = cast('struct netlink_sock *', sk)
                print_netlink_sock(netlink_sock)
            elif sock.ops.value_() == inet_dgram_ops:
                print_udp_sock(sk)
            else:
                print('')
        elif file.f_op.value_() == pipefifo_fops:
            print('pipefifo_fops')
        elif file.f_op.value_() == null_fops:
            print('null_fops')
        elif file.f_op.value_() == xfs_file_operations:
            print('xfs_file_operations')
        elif file.f_op.value_() == shmem_file_operations:
            print('shmem_file_operations')
        else:
            print(file.f_op)
Beispiel #17
0
def for_each_pid(prog_or_ns: Union[Program, Object]) -> Iterator[Object]:
    """
    Iterate over all PIDs in a namespace.

    :param prog_or_ns: ``struct pid_namespace *`` to iterate over, or
        :class:`Program` to iterate over initial PID namespace.
    :return: Iterator of ``struct pid *`` objects.
    """
    if isinstance(prog_or_ns, Program):
        prog = prog_or_ns
        ns = prog_or_ns["init_pid_ns"].address_of_()
    else:
        prog = prog_or_ns.prog_
        ns = prog_or_ns
    if hasattr(ns, "idr"):
        for nr, entry in idr_for_each(ns.idr):
            yield cast("struct pid *", entry)
    else:
        pid_hash = prog["pid_hash"]
        for i in range(1 << prog["pidhash_shift"].value_()):
            for upid in hlist_for_each_entry("struct upid",
                                             pid_hash[i].address_of_(),
                                             "pid_chain"):
                if upid.ns == ns:
                    yield container_of(upid, "struct pid",
                                       f"numbers[{int(ns.level)}]")
Beispiel #18
0
def find_pid(prog_or_ns, nr):
    """
    .. c:function:: struct pid *find_pid(struct pid_namespace *ns, int nr)

    Return the ``struct pid *`` for the given PID number in the given
    namespace. If given a :class:`Program` instead, the initial PID namespace
    is used.
    """
    if isinstance(prog_or_ns, Program):
        prog = prog_or_ns
        ns = prog_or_ns['init_pid_ns'].address_of_()
    else:
        prog = prog_or_ns.prog_
        ns = prog_or_ns
    if hasattr(ns, 'idr'):
        return cast('struct pid *', idr_find(ns.idr, nr))
    else:
        # We could implement pid_hashfn() and only search that bucket, but it's
        # different for 32-bit and 64-bit systems, and it has changed at least
        # once, in v4.7. Searching the whole hash table is slower but
        # foolproof.
        pid_hash = prog['pid_hash']
        for i in range(1 << prog['pidhash_shift'].value_()):
            for upid in hlist_for_each_entry('struct upid',
                                             pid_hash[i].address_of_(),
                                             'pid_chain'):
                if upid.nr == nr and upid.ns == ns:
                    return container_of(upid, 'struct pid',
                                        f'numbers[{ns.level.value_()}]')
        return NULL(prog, 'struct pid *')
Beispiel #19
0
def for_each_pid(prog_or_ns):
    """
    .. c:function:: for_each_pid(struct pid_namespace *ns)

    Iterate over all of the PIDs in the given namespace. If given a
    :class:`Program` instead, the initial PID namespace is used.

    :return: Iterator of ``struct pid *`` objects.
    """
    if isinstance(prog_or_ns, Program):
        prog = prog_or_ns
        ns = prog_or_ns['init_pid_ns'].address_of_()
    else:
        prog = prog_or_ns.prog_
        ns = prog_or_ns
    if hasattr(ns, 'idr'):
        for nr, entry in idr_for_each(ns.idr):
            yield cast('struct pid *', entry)
    else:
        pid_hash = prog['pid_hash']
        for i in range(1 << prog['pidhash_shift'].value_()):
            for upid in hlist_for_each_entry('struct upid',
                                             pid_hash[i].address_of_(),
                                             'pid_chain'):
                if upid.ns == ns:
                    yield container_of(upid, 'struct pid',
                                       f'numbers[{int(ns.level)}]')
Beispiel #20
0
    def caller(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
        """
        This method will dispatch to the appropriate instance function
        based on the type of the input we receive.
        """

        out_type = self.prog.type(self.output_type)
        has_input = False
        for i in objs:
            has_input = True

            # try subclass-specified input types first, so that they can
            # override any other behavior
            try:
                for (_, method) in inspect.getmembers(self, inspect.ismethod):
                    if not hasattr(method, "input_typename_handled"):
                        continue

                    # Cache parsed type by setting an attribute on the
                    # function that this method is bound to (same place
                    # the input_typename_handled attribute is set).
                    if not hasattr(method, "input_type_handled"):
                        method.__func__.input_type_handled = self.prog.type(
                            method.input_typename_handled)

                    if i.type_ == method.input_type_handled:
                        yield from method(i)
                        raise StopIteration
            except StopIteration:
                continue

            # try passthrough of output type
            # note, this may also be handled by subclass-specified input types
            if i.type_ == out_type:
                yield i
                continue

            # try walkers
            try:
                # pylint: disable=import-outside-toplevel
                #
                # The reason we do the above is that putting
                # the import at the top-level hits a cyclic
                # import error which pretty-much breaks
                # everything. We should reconsider how we
                # handle all our imports.
                from sdb.commands.walk import Walk
                for obj in Walk(self.prog).call([i]):
                    yield drgn.cast(out_type, obj)
                continue
            except TypeError:
                pass

            # error
            raise TypeError(
                'command "{}" does not handle input of type {}'.format(
                    self.names, i.type_))
        if not has_input:
            yield from self.no_input()
Beispiel #21
0
def sock_cgroup_ptr(skcd):
    """
    .. c:function:: struct cgroup *sock_cgroup_ptr(struct sock_cgroup_data *skcd)

    Get the cgroup for a socket from the given ``struct sock_cgroup_data *``
    (usually from ``struct sock::sk_cgrp_data``).
    """
    return cast("struct cgroup *", skcd.val)
Beispiel #22
0
def sk_tcpstate(sk: Object) -> Object:
    """
    Return the TCP protocol state of a socket.

    :param sk: ``struct sock *``
    :return: TCP state enum value.
    """
    return cast(sk.prog_["TCP_ESTABLISHED"].type_, sk.__sk_common.skc_state)
Beispiel #23
0
 def test_cast_primitive_value(self):
     obj = Object(self.prog, "long", value=2 ** 32 + 1)
     self.assertIdentical(cast("int", obj), Object(self.prog, "int", value=1))
     self.assertIdentical(
         cast("int", obj.read_()), Object(self.prog, "int", value=1)
     )
     self.assertIdentical(
         cast("const int", Object(self.prog, "int", value=1)),
         Object(self.prog, "const int", value=1),
     )
     self.assertRaisesRegex(
         TypeError,
         "cannot cast to 'struct point'",
         cast,
         self.point_type,
         Object(self.prog, "int", value=1),
     )
Beispiel #24
0
def print_namespace(ns):
    prio_addr = ns.node.children.address_of_()
    for prio_node in list_for_each_entry('struct fs_node', prio_addr, 'list'):
        #         print(prio_node)
        prio = cast("struct fs_prio *", prio_node)
        #         print(prio)
        if prio.prio == 1:
            print_prio(prio, 0)
            ns_addr = prio.node.children.address_of_()
            for ns_node in list_for_each_entry('struct fs_node', prio_addr,
                                               'list'):
                ns2 = cast("struct mlx5_flow_namespace *", ns_node)
                prio_addr2 = ns2.node.children.address_of_()
                for prio_node2 in list_for_each_entry('struct fs_node',
                                                      prio_addr2, 'list'):
                    prio2 = cast("struct fs_prio *", prio_node2)
                    print_prio(prio, 1)
Beispiel #25
0
def bpf_prog_for_each(prog: Program) -> Iterator[Object]:
    """
    Iterate over all BPF programs.

    :return: Iterator of ``struct bpf_prog *`` objects.
    """
    for nr, entry in idr_for_each(prog["prog_idr"]):
        yield cast("struct bpf_prog *", entry)
Beispiel #26
0
def page_to_pfn(page: Object) -> Object:
    """
    Get the page frame number (PFN) of a page.

    :param page: ``struct page *``
    :return: ``unsigned long``
    """
    return cast("unsigned long", page - page.prog_["vmemmap"])
Beispiel #27
0
def print_udp_sock(sk):
    inet_sock = cast('struct inet_sock *', sk)
    dest_ip = inet_sock.sk.__sk_common.skc_daddr
    src_ip = inet_sock.sk.__sk_common.skc_rcv_saddr
    dest_port = ntohs(inet_sock.sk.__sk_common.skc_dport)
    src_port = ntohs(inet_sock.inet_sport)
    print("dest_ip: %s, src_ip: %s, dest_port: %d, src_port: %d" % \
                (ipv4(ntohl(dest_ip.value_())), ipv4(ntohl(src_ip.value_())), dest_port, src_port))
Beispiel #28
0
def sock_cgroup_ptr(skcd: Object) -> Object:
    """
    Get the cgroup for a socket from the given ``struct sock_cgroup_data *``
    (usually from ``struct sock::sk_cgrp_data``).

    :param skcd: ``struct sock_cgroup_data *``
    :return: ``struct cgroup *``
    """
    return cast("struct cgroup *", skcd.val)
Beispiel #29
0
def print_namespace(ns):
#     print(ns)
    prio_addr = ns.node.children.address_of_()
    for prio_node in list_for_each_entry('struct fs_node', prio_addr, 'list'):
        prio = cast("struct fs_prio *", prio_node)
        print_prio(prio)

        table_addr = prio.node.children.address_of_()
        for table_node in list_for_each_entry('struct fs_node', table_addr, 'list'):
#             print(table_node.type)
            if table_node.type.value_() == prog['FS_TYPE_NAMESPACE'].value_():
                namespace = container_of(table_node, "struct mlx5_flow_namespace", "node")
#                 print(namespace)
#                 print("FS_TYPE_NAMESPACE")
                print_namespace(namespace)
            else:
                table = cast("struct mlx5_flow_table *", table_node)
                print_table(table)
Beispiel #30
0
    def _helper(self, node: drgn.Object) -> Iterable[drgn.Object]:
        if not node:
            return

        count = node.bth_count
        if node.bth_core:
            # alterate recursive descent on the children and generating core objects
            core = drgn.cast('struct zfs_btree_core *', node)
            for i in range(count):
                yield from self._helper(core.btc_children[i])
                yield self._val(core.btc_elems, i)
            # descend the final, far-right child node
            yield from self._helper(core.btc_children[count])
        else:
            # generate each object in the leaf elements
            leaf = drgn.cast('struct zfs_btree_leaf *', node)
            for i in range(count):
                yield self._val(leaf.btl_elems, i)