Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: где делись сетевые syscall?  (Прочитано 1522 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Olej

  • Автор темы
  • Забанен
  • Активист
  • *
  • Сообщений: 884
    • Просмотр профиля
где делись сетевые syscall?
« : 24 Июня 2015, 15:19:30 »
Вся связь всего программного обеспечения, на чём бы вы его не писали, обслуживается Linux (в конечном итоге) только одним путём - через стандартную C-библиотеку libc.so, которая содержит системные вызовы.
Системные вызов попадают в ядре таблицу системных вызовов sys_call_table, которая является просто массивов точек входов (адресов) функций, обслуживающих системные вызовы.
В принципе, можно и подменить адрес в таблице sys_call_table на свой ... это та техника, которая используется ещё со времён MS-DOS, или на сегодня шиоко в OpenBSD.
Это "Букварь" ... это многократно и по разному использовалось при написании модулей ядра. 

Возникла необходимость найти в sys_call_table (и может их потом модифицировать) сетевые системные вызовы accept(2) (__NR_accept 202) и connect(2) (__NR_connect 203) (обратите внимание, что в man они в секции системных вызовов).
И оказалось, что их ... как и всех 17(?) сетевых системных вызовов в таблице sys_call_table просто нет!

Чтоб не рассказывать долго (убил на это кино полный рабочий день) ... все сетевые системные вызовы идут через одн мало кому известный системный вызов socketcall(2)Ж
$ man socketcall
NAME
       socketcall - socket system calls
SYNOPSIS
       int socketcall(int call, unsigned long *args);
...
... и там же они робко бъясняют >:( ... а). что "так получилось", б). это сугубо Linux фича (такого нигде в других UNIX-like нет), в).   что это "никому кроме завзятых хакеров не нужно и не должно беспокоить", г). что даже в некоторых архитектурах Linux эти вызовы идут по-людски, через sys_call_table, но в i686 / X86_64 - именно так, "через задницу"......

Вопросы:
- из каких соображений это такое могло быть сделано?
- почему даже в описаниях относительно ядра это толком не упоминается (я за 5 лет не натолкнулся)?
- как теперь достать конкретный обработчик accept() или connect()?
... ну и т.д.

"Моему возмущению предела нет!" ;D
« Последнее редактирование: 24 Июня 2015, 15:29:50 от Olej »

Оффлайн Olej

  • Автор темы
  • Забанен
  • Активист
  • *
  • Сообщений: 884
    • Просмотр профиля
Re: где делись сетевые syscall?
« Ответ #1 : 25 Июня 2015, 23:50:24 »
Могу рассказать ... и даже показать ;), как произвести перехват любого сетевого системного вызова:
- находим таблицу системных вызовов sys_call_table
- в позиции __NR_socketcall = 102 таблицы лежит адрес обработчика sys_socketcall (sys_call_table[ __NR_socketcall ])
- сохраняем его как old_sys_socketcall
-  а в sys_call_table[ __NR_socketcall ] записываем адрес old_sys_socketcall() :
asmlinkage long new_sys_socketcall( int call, unsigned long __user *args ) {
   long ret;
   if( SYS_CONNECT == call || SYS_ACCEPT == call )
      LOG( "new_sys_socketcall before cod=%d\n", call );
   ret = old_sys_socketcall( call, args );
   if( SYS_CONNECT == call || SYS_ACCEPT == call )
      LOG( "new_sys_socketcall after cod=%d\n", call );
   // sys_accept & sys_connect` are exported
   // можно вызывать: long aret = sys_accept( 1, (struct sockaddr __user*)args, 0 );
   return ret;
}
EXPORT_SYMBOL( new_sys_socketcall );
- при записи в sys_call_table нужно снять read-only через MMU с страницы RAM размещения таблицы ... это делается аппаратно через скрытый системный регистр процессора CR0.

Вот, собственно, и всё - вот они все наши сетевые syscall-ы в кулаке ;-) .

Пользователь решил продолжить мысль [time]26 Июнь 2015, 11:17:41[/time]:
Почти случайно, в дебрях интернета ;), разыскалась вот такая заметка: sys socketcall: Network systems calls on Linux.
Цитировать
Daniel No´e
April 9, 2008
Насколько я помню, автор - это один из активных разработчиков сетевой подсистемы Linux ... это имя часто мелькает в комментариях исходного кода ядра.

Там есть весьма любопытные вещи:

1. Ну, про то, что а одних аппаратных архитектурах сделанно вот так, через socketcall (через задницу), а в других нормально, просто как все системные вызовы - это и в man написано. Но автор здесь утверждает, что в i386 сделано через задницу, а в X86_64 - нормально, через sys_call_table (man пишет обратное). Но и в X86_64 сохранён i386. Зачем и это сделано автор (как один из разработчиков) выказывает только догадки ... что, наверное, из-за совместимости с 32-бит приложениями.

2. Но он подробно описывает технику происходящего:
- все параметры любого сетевого ситемного вызова плотно пакуются друг за другом в один массив (не взирая, что для accepr, например, 1-й это целый дескриптор, 2-й - указатель struct sockaddr*, а 3-й - указатель на целую длину ... по барабану, всех пакуем вместе ... "доктор строгий - сказал в морг, значит в морг");
- потом всё это уродство одним параметром указателя на этот массив заталкивается в параметр (2-й) socketcall и делается системный вызов...
- в ядре хранится массив (для каждой сетевой операции) длины, которую нужно тупо скопировать из userspace ... байт за байтом не взирая указатель это или целое ...
- а отом каждый сетевой вызов сам разберётся, по порядку, какой элемент этого массива является его очередным параметром вызова...
Цитировать
И эти люди запрещают мне ковыряться в носу!
:2funny:

3. Наконец сам автор-разработчик говорит, что это уродливая, мол, схема в свете современных представлений объектно-ориентированного и т.д. ;D. Но так, мол, получилось.

Эта публикация многое проясняет.
И будет просто необходима каждому, кто как-то свяжется с программированием вокруг сетевой подсистемы Linux.


Пользователь решил продолжить мысль [time]27 Июнь 2015, 00:13:13[/time]:
Всё!
Сделано...
Это фактически микро-прототип распределённого файервола, который перехватывает контроль над системными вызовами connect() & accept() Linux, и может запретить как подключения TCP из определённого IP, так и подключения к определённому IP.

Я показываю этот пример не из-за его функциональности (это если кто захочет - возитесь сами), а ту технику, как в Linux можно подменить любой системный вызов, и в том числе и сетевые. Об этом часто спрашивают. Дальнейшее продвижение самого этого проекта уже продолжать показывать не буду.

« Последнее редактирование: 26 Июня 2015, 23:15:01 от Olej »

Оффлайн it0r

  • Забанен
  • Старожил
  • *
  • Сообщений: 2264
    • Просмотр профиля
Re: где делись сетевые syscall?
« Ответ #2 : 27 Июня 2015, 01:26:48 »
и что, все так плохо?  :(
ТУТ - это дерево. А ЗДЕСЬ - это МЕСТО.... Так что ТУТ - это не ЗДЕСЬ.

Оффлайн Olej

  • Автор темы
  • Забанен
  • Активист
  • *
  • Сообщений: 884
    • Просмотр профиля
Re: где делись сетевые syscall?
« Ответ #3 : 27 Июня 2015, 08:27:14 »
и что, все так плохо?  :(
Да нет, напротив - всё так хорошо! :D
(т.е. на начало дня 24.06 всё было действительно так плохо, но к концу дня 26.06 всё стало вот так хорошо ;))

Практически во всех учебниках по Linux говорится "таблица системных вызовов ядра не экспортируется начиная с ядра 2.6?, поэтому их нельзя заменить на свои, что обеспечивает :2funny: повышенную защищённость".
А достаточно много хакерских статеек в интернет описывают как они ищут эту таблицу ... так же через задницу как и она размещена ... анализируя дампы бинарного кода, например. :-[

Прикреплённый выше примерчик показывает как это можно делать цивильно, ... вопреки довольно странным, скажем так, вкусам зажравшейся команды Линуса Торвальдса, с их представлениями о защищённости. И показанная в примере техника сильно расширяет функциональные возможности программиста-разработчика.

Это вообще :coolsmiley:

А если в частности, про сетевые системные вызовы (небольшая часть общего числа сисколов), то сделаны они, конечно, через задницу, что отмечает в своей заметке и один из авторов этой сетевой подсисемы. Но как сделано - так и сделано. (Это как в Windows, где почти 20 лет от Windows 3.11 поддерживали совместимость с 16-битным кодом ... заботясь о пользователях старых програм из MS-DOS :2funny:).
Но эксперимент и некоторая изобретательность ;) показали, что и все сетевые сисколы доступны с тем же успехом динамическому контролю или замене если надо.
 
Дерзайте. ;)
« Последнее редактирование: 27 Июня 2015, 09:19:44 от Olej »

 

Страница сгенерирована за 0.018 секунд. Запросов: 22.