Как настроить порт исключения хоста, используя ядро ​​Mach на macOS? - PullRequest
6 голосов
/ 22 апреля 2019

Я хочу использовать Порты исключений Маха для обработки исключений для всех задач (процессов), работающих в macOS.Насколько я понимаю, host_set_exception_ports будет использоваться в этом случае.Однако host_set_exception_ports возвращает KERN_NO_ACCESS ( код ошибки 8 ), даже когда я выполняю свою программу с sudo.Мой экспериментальный код работает для обработки исключений для одной задачи с использованием task_set_exception_ports.

. Я уже рассмотрел код ядра Mach из host_set_exception_ports.Существует единственная строка кода , где KERN_NO_ACCESS возвращается из функции.У меня немного трудное время, чтобы понять, что там происходит.Кажется, код ядра проверяет маску исключения, которую я передаю host_set_exception_ports.Я тестировал с разными масками исключений, но всегда получал один и тот же отрицательный результат.

Мои вопросы: Означает ли это, что существует общее ограничение на использование host_set_exception_ports в приложении из пользовательского пространства?Если нет, то как мне настроить порты исключений хоста для получения общесистемных исключений в моем приложении?

Следующая программа является минимальным примером, демонстрирующим поведение, и в противном случае она мало используется.Используйте gcc example.c для компиляции программы и sudo ./a.out для ее запуска.

#include <mach/mach.h>
#include <stdio.h>
#include <stdlib.h>

void catchMachExceptions() {
    mach_port_t exception_port;
    kern_return_t rc;

    rc = mach_port_allocate(mach_task_self(),
                            MACH_PORT_RIGHT_RECEIVE,
                            &exception_port);
    if (rc != KERN_SUCCESS) {
        fprintf(stderr, "Unable to allocate exception port: %d\n", rc);
        exit(-1);
    }

    rc = mach_port_insert_right(mach_task_self(),
                                exception_port,
                                exception_port,
                                MACH_MSG_TYPE_MAKE_SEND);
    if (rc != KERN_SUCCESS) {
        fprintf(stderr, "Unable to insert right: %d\n", rc);
        exit(-1);
    }

    rc = host_set_exception_ports(mach_host_self(),
                                  EXC_MASK_ALL,
                                  exception_port,
                                  EXCEPTION_STATE_IDENTITY,
                                  MACHINE_THREAD_STATE);
    if (rc != KERN_SUCCESS) {
        fprintf(stderr, "Unable to set exception: %d\n", rc);
        exit(-1);
    }
}

int main(int argc, char **argv) {
    catchMachExceptions();
}

1 Ответ

2 голосов
/ 01 мая 2019

Перебирая источник, host_set_exception_ports вызывает mac_task_check_set_host_exception_ports, как вы заметили.

Разобравшись с этим, вы обнаружите, что mac_task_check_set_host_exception_ports получает учетные данные на основе задачи, затемвызывая MAC_CHECK(proc_check_set_host_exception_port, cred, exception).

Это макрос, определенный в security/mac_internals.h.Смотрите код xnu здесь .При чтении, это обходит список модулей политики, проверяя, будут ли модули политики разрешать или отклонять запрос.

На основе кода все модули политики должны согласиться и не отправлять сообщение об ошибке.Похоже, вам нужны правильные привилегии.Существует некоторая документация по проекту GNU Mach, в которой указано, что права на отправку на привилегированный порт хоста предоставляются первой задаче и могут быть переданы только оттуда.См. GNU Mach определение host_ports и т. Д. .

Подводя итог, вы можете не только не вносить изменения как пользовательский процесс, вам также необходимо специально наследовать привилегии через цепочку от времени загрузки.

...