bpftrace prints out incorrect values for kernel atomic_long_t

Created on 12 Sep 2019  路  1Comment  路  Source: iovisor/bpftrace

drgn:

$ sudo drgn
drgn 0.0.1 (using Python 3.6.3)
For help, type help(drgn).
>>> import drgn
>>> from drgn import cast, container_of, execscript, NULL, Object, reinterpret
>>> from drgn.helpers.linux import *
>>> find_task(prog, 1).cred.user.locked_vm.counter
(long)14562

bpftrace:

$ cat atomics.bt
#include <linux/cred.h>
#include <linux/sched.h>
#include <linux/uidgid.h>

profile:hz:99
{
        $task = (struct task_struct *)curtask;
        $pid = $task->pid;
        $cred = (struct cred *)$task->cred;
        $user = (struct user_struct *)$cred->user;
        $uid = $user->uid.val;
        $lock_pages = $user->locked_vm.counter;
        if ($pid == 1) {
                printf("uid=%lu, pid=%d,locked_vm: %lld", $uid, $pid, $lock_pages);
                exit();
        }
}

$ sudo bpftrace atomics.bt
Attaching 1 probe...
uid=0, pid=1,locked_vm: 16124

Doesn't look like there's any interesting bit patterns:

$ python3
>>> bin(16124)
'0b11111011111100'
>>> bin(14562)
'0b11100011100010'
>>> bin(16124-14562)
'0b11000011010'
>>> hex(16124-14562)
'0x61a'
>>> hex(16124|14562)
'0x3efe'
>>> bin(16124|14562)
'0b11111011111110'
bug

Most helpful comment

Spent some more time digging. I looked at the llvm IR and all the offsets seemed reasonable. There's a lot of #ifdef's in struct task_struct so my initial thought was that b/c bpftrace doesn't know the define values it has to guess and maybe offsets were wrong. But fortunately bpftrace has btf support so I tried that too and the results were the same.

Then somehow I had the brilliant idea of slamming up-arrow-enter in drgn while bpftrace was running. When you do that, the values actually line up. I think bpf infrastructure is causing this counter to move. So when bpftrace isn't running, it's one value. But when bpftrace is running, it's another.

Funny how things are interconnected like this.

>All comments

Spent some more time digging. I looked at the llvm IR and all the offsets seemed reasonable. There's a lot of #ifdef's in struct task_struct so my initial thought was that b/c bpftrace doesn't know the define values it has to guess and maybe offsets were wrong. But fortunately bpftrace has btf support so I tried that too and the results were the same.

Then somehow I had the brilliant idea of slamming up-arrow-enter in drgn while bpftrace was running. When you do that, the values actually line up. I think bpf infrastructure is causing this counter to move. So when bpftrace isn't running, it's one value. But when bpftrace is running, it's another.

Funny how things are interconnected like this.

Was this page helpful?
0 / 5 - 0 ratings