Отказано в доступе при извлечении поля из указателя на большую структуру в программе BPF

Я пытаюсь написать программу BPF, которая проверяет идентификатор сеанса любого процесса, вызывающего функцию ядра tty_write. Чтобы получить идентификатор, мне нужно пройти ряд полей от указателя к текущему task_struct, однако извлечение указателя group_leader из указателя на текущую задачу кажется ошибкой, поскольку смещение от текущего указателя задачи слишком велико. Мой программный код BPF выглядит следующим образом:

SEC("kprobe/tty_write")
int kprobe__tty_write(struct pt_regs *ctx)
{
    struct task_struct *task;
    struct task_struct *group_leader;
    struct pid_link pid_link;
    struct upid upid;
    int sessionid;

    // get current sessionid
    task = (struct task_struct *)bpf_get_current_task();
    bpf_probe_read(&group_leader, sizeof(group_leader), (void *)task->group_leader);
    bpf_probe_read(&pid_link, sizeof(pid_link), (void *)(group_leader->pids + PIDTYPE_SID));
    bpf_probe_read(&upid, sizeof(upid), (void *)pid_link.pid->numbers); 
    sessionid = upid.nr;

    // do stuff with sessionid

    return 0;
}

Это не удается со следующей ошибкой. Примечание. Я использую пакет gobpf для загрузки скомпилированной программы:

failed to load BPF module: error while loading "kprobe/tty_write" (permission denied):
0: (bf) r6 = r1
1: (85) call bpf_get_current_task#35
2: (79) r3 = *(u64 *)(r0 +1464)
R0 invalid mem access 'inv'

Как я могу обойти эту проблему и в чем причина? Я думал, что это может быть связано с ограничением размера стека в 512 байт, но я не понимаю, почему это имеет значение в данном случае.

uname -a: Linux ubuntu1710 4.13.0-32-generic #35-Ubuntu SMP Чт, 25 января, 09:13:46 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux


person dippynark    schedule 13.02.2018    source источник


Ответы (1)


Я не думаю, что это проблема слишком большого смещения. Существует проблема с рандомизацией полей, которая затрагивает struct task_struct в Linux 4.13.

Вы можете либо использовать другое ядро, либо поместить следующее перед вашими #includes:

#define randomized_struct_fields_start  struct {
#define randomized_struct_fields_end    };

У вас есть вторая проблема с вашим первым bpf_probe_read. Третий аргумент должен быть указателем на значение, которое вы хотите получить (здесь указатель на указатель):

bpf_probe_read(&group_leader, sizeof(group_leader), &task->group_leader);
person pchaigno    schedule 13.02.2018
comment
Я добавил эти определения прямо в начало своей программы, но получаю ту же ошибку — я попытался запустить ее на 4.11 и тоже получил ту же ошибку. - person dippynark; 13.02.2018
comment
Был второй вопрос, который я пропустил. Я обновил свой ответ. - person pchaigno; 13.02.2018
comment
отличного настроения :) Я все еще получаю 0 sessionid, но я думаю, что это другая проблема, которую я пока не понимаю, хотя ваше объяснение имеет смысл - person dippynark; 13.02.2018