Где твои системные вызовы?

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Ядро OpenBSD становится уже очень старым — ну просто очень — ему около сорока пяти лет. Оно, следовательно, не любит сюрпризов. Поэтому программы должны сообщать ему о том, где находятся их системные вызовы. В сегодняшнем выпуске «Вежливого программиста» мы поговорим о том, как это делать по всем правилам этикета.

Если вы программируете на C — всё это делается автоматически. Поэтому мы будем писать код только на языке, который совершенно нельзя назвать C, и при этом обойдёмся без линковки с libc.

Начало

Начнём с простой программы hello:

void
start()
{
        w("hello\n", 6);
        x();
}

typedef unsigned long size_t;
int
w(void *what, size_t len) {
        __asm(
"       mov x2, x1;"
"       mov x1, x0;"
"       mov w0, #1;"
"       mov x8, #4;"
"       svc #0;"
        );
        return 0;
}
void
x() {
        __asm(
"       mov x8, #1;"
"       svc #0;"
        );
}

В «совершенно не C» мы начинаем выполнение программы с функции start и выводим сообщения с помощью функции w (её исходный код включён в листинг). А после этого, в итоге, выходим из программы, вызывая функцию x, так как, если работа завершится в нижней части функции start — это будет настоящая жесть.

Вудуистика

Нам ещё понадобится немного магии вуду — чтобы сообщить ядру о том, что это — настоящая программа, а не плод бредовых фантазий Зимнего безмолвия.

__asm(" .section \".note.openbsd.ident\", \"a\"\n"
"       .p2align 2\n"
"       .long   8\n"
"       .long   4\n"
"       .long   1\n"
"       .ascii \"OpenBSD\\0\"\n"
"       .long   0\n"
"       .previous\n");

Системные вызовы

А теперь, наконец, самое интересное. Мы сообщаем ядру об используемых нами системных вызовах, делая это с помощью небольшой таблицы, описывающей то, что происходит в программе. Как бы ни строги были правила, применяемые при построении этой таблицы, их соблюдение больших усилий не требует.

struct whats {
        unsigned int offset;
        unsigned int sysno;
} happening[] __attribute__((section(".openbsd.syscalls"))) = {
        { 0x104f4, 4 },
        { 0x10530, 1 },
};

Если вы изучали операционные системы — вы можете вспомнить, что write — это системный вызов #4, а exit — системный вызов #1. Что касается шестнадцатеричных смещений — ну — мы, всё же, пишем на языке, который нельзя безоговорочно назвать «совершенно не C», но разобраться с этим не так уж и сложно. Загляните в мануал.

Честно говоря, я не знаю, что ещё можно сделать, чтобы лучше раскрыть этот простой пример, разве что — скомпилировать код и запустить objdump. Указатели функций не являются константами времени компиляции,  они не дадут нам смещение секции elf без дополнительных беззаконных умственных упражнений. Но это — то, что может достаточно легко раскрыть используемый вами набор инструментов. Сложности добавляет лишь то, что эти инструменты пытаются запихать это всё в «одноразовую» демонстрацию. А libc просто использует немного больше «вудуистики» в asm-секциях, но всё это слишком мутно, чтобы тут воспроизводить.

Компиляция

Всё готово.

$ cc -c where.c
$ ld -e start --eh-frame-hdr -Bstatic -o where where.o
$ ./where
hello

Привет! Перед нами — согласованная работа программы и системных вызовов.


О, а приходите к нам работать?
Источник: https://habr.com/ru/companies/wunderfund/articles/889514/


Интересные статьи

Интересные статьи

Всем привет, случалось такое, что вам надо поставить кучу агентов битрикса на крон, а потом сидеть и разбираться - сколько они отрабатывают, отрабатывают ли вообще, когда падают или зависают? Ну конеч...
В процессе разработки почти любого приложения необходим удобный механизм по работе с данными из БД. В данной статье речь пойдет о таком расширении для СMS Bitrix, как alexpr94/bitrix-models, устанавли...
Число утечек персональных данных в России все время растет: новости об очередных инцидентах выходят так часто, что уже перестают вызывать удивление. Чаще всего жертвами утечек становятся клиенты компа...
Сбой миграции в облако проявляется по-разному  - от превышения бюджета и срыва сроков до осознания что что-то попросту "не работает". Хорошая новость в том, что всех этих проблем можно избежать и...
ВведениеВ данной статье я бы хотел рассмотреть проблему обновления PHP в виртуальной машине BitrixVM, и действия, которые возможно применить если выполнение переезда на машину с обновленным ПО невозмо...