segfault при доступе к вложенной структуре

Я использую kinfo_getproc в следующих случаях:

int main() {

    struct kinfo_proc *kp;

    kp = kinfo_getproc(getpid());


    printf("kp: %p\n", kp);
    // kp:  0x801216000

    printf("&kp: %p\n", &kp);
    // &kp: 0x7fffffffeac0

    printf("&thread: %p\n", &kp->ki_tdaddr);
    // &thread: 0x801216398


    printf("&thread->td_dupfd: %p\n", &kp->ki_tdaddr->td_dupfd);
    // &thread->td_dupfd: 0xfffff801564d3650

    // segfault accessing contents of td_dupfd
    //printf("thread->td_dupfd: %d\n", kp->ki_tdaddr->td_dupfd);

    return 1;
}

Когда я пытаюсь получить доступ к структуре внутри структуры kp, программа перестает работать.

Я читал, из других сообщений, проблема, вероятно, в том, что структура не распределяется должным образом? Следующее взято из справочной страницы для kinfo_getproc:

RETURN VALUES
   On success the kinfo_getproc() function returns a pointer to a struct
   kinfo_proc structure as defined by <sys/user.h>.  The pointer was
   obtained by an internal call to malloc(3) and must be freed by the caller
   with a call to free(3).  On failure the kinfo_getproc() function returns
   NULL.

Если возвращаемое значение является указателем на kinfo_struct, который уже был malloced, не должен ли просто работать доступ к вложенной структуре? Как мне правильно получить доступ к вложенной структуре в kp?


person fbynite    schedule 23.02.2018    source источник
comment
Не комментируйте код, в котором есть проблема, о которой вы спрашиваете.   -  person Barmar    schedule 24.02.2018
comment
Какое значение kp->ki_tdaddr? Может, это нулевой указатель?   -  person Barmar    schedule 24.02.2018
comment
Документация, которую вы публикуете, не содержит утверждений о том, действителен ли член ki_tdaddr и было ли то, на что он, возможно, указывает, было malloced. Это относится только к указателю, полученному в результате kinfo_getproc. Вам придется погрузиться глубже, чтобы увидеть, когда / если / как обрабатывается ki_tdaddr член.   -  person WhozCraig    schedule 24.02.2018
comment
Процесс - это не поток, почему вы ожидаете, что этот член будет действительным? Он будет действителен только в том случае, если вы вызываете это из созданного потока.   -  person Geoffrey    schedule 24.02.2018
comment
Segfault не возникает из-за доступа к вложенной структуре, это происходит из-за доступа к области памяти, которая не принадлежит вам или вашей программе.   -  person Michi    schedule 24.02.2018
comment
@WhozCraig, копнул глубже и стало очевидно, спасибо.   -  person fbynite    schedule 04.03.2018


Ответы (1)


Я понял, в чем была моя проблема.

Значение kp->ki_tdaddr - это адрес, который находится в пространстве ядра. Другими словами, kp->ki_tdaddr - это указатель на структуру, которая находится в памяти ядра, которая не доступна напрямую из пользовательского пространства, отсюда и ошибка segfault.

Нужно было использовать значение из kp->ki_tdaddr (адрес пространства ядра) с kvm_read() для передачи битов из пространства ядра в пространство пользователя.

код:

int main() {

    struct thread thread;

    /* a structure with process related info */
    struct kinfo_proc *kp = kinfo_getproc(getpid());

    /* a descriptor to access kernel virtual memory */
    kvm_t *kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);

    /* transfer bytes from ki_tdaddr to thread */
    kvm_read(kd, (unsigned long) kp->ki_tdaddr, &thread, sizeof(thread));

    /* can now access thread information */
    printf("thread id: %jd\n", (intmax_t) thread.td_tid);

    return 1;
}
person fbynite    schedule 04.03.2018