LINUX.ORG.RU

system_call


0

0

Всем снова сдрасте. У меня новая проблема :) Мне нужно модифицировать (клонировать) обработчик 80 прерывания, она же функция system_call. Но он везде где я находил описан очень и очень хренова. Обычно все описание заключается в том что сказано: в eax передается номер вызываемой функции, он проверяется, далее запускается, если чтото не так то производются сложные действия для коректного возврата. Без каких либо подробностей. Мне нужно сделать практически аналогичный обработчик за некими маленькими отклонениями. А чтобы понять где эти маленькие поправления должны быть нужно понять как там все это работает, до последнего винтика. Прошу вашей помощи в разборе. Начнем по порядку.

Во первых сделаем для простоты такое упущение: ничего лишнего кроме как посмотреть номер вызываемой функции, вызвать ее и вернуть результат, ни надо, пока нужен самый минимум чтобы работал в идеальных условиях. И второе: нужно четко осознать те моменты где прямым образом фигурируют какие либо опоминания об пользовательском пространстве (дескрипторы GDT, DPL = 3, процесс вызвавший прерывание).

	.pushsection .kprobes.text, "ax" # это относиться к обработчику или нет ?
	# system call handler stub
ENTRY(system_call)
	RING0_INT_FRAME			# подготавливается стек ядра? Но как оно работает
	pushl %eax			# save orig_eax
	CFI_ADJUST_CFA_OFFSET 4 # не понял что это ?
	SAVE_ALL # сохраняем в стек все необходимые регистры
	GET_THREAD_INFO(%ebp) # получаем инфу о треде вызвавшем прерывание ? Но кукую и для чего она ?
					# system call tracing in operation / emulation
	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) # проверка чего ?) Того что из данного треда можно делать системные вызовы ?
	jnz syscall_trace_entry # сюда попадем если проверка не прошла, но в этой метке все равно может произойти вызов (см. ниже)
	cmpl $(nr_syscalls), %eax
	jae syscall_badsys # сюда прыгаем если номер системного переданный в eax неправильны, и далее возвращается ENOSYS
syscall_call:
	call *sys_call_table(,%eax,4) # самое суть
	movl %eax,PT_EAX(%esp)		# кладем результат работы обратно в eax
syscall_exit:
	LOCKDEP_SYS_EXIT # нах это ?
	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
					# setting need_resched or sigpending
					# between sampling and the iret
                                        # На сколько я понял это некий аналог "For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti")"
	TRACE_IRQS_OFF # не понял что это
	movl TI_flags(%ebp), %ecx # кладем в ecx то чем можно идентифицировать тред который запустил прерывания, или его отдельное значение
	testl $_TIF_ALLWORK_MASK, %ecx	# current->work
                                        # смотрим работаетли еще тред вызвавший прерывание ?
	jne syscall_exit_work # сюда пошли если процесс уже не работает ?

restore_all: # а сюда для выхода в прерывания при работающем процессе ?
	TRACE_IRQS_IRET # посмотрели что прерывание уже неработает ? Оо
restore_all_notrace: # подготовка в козврату в юзерспейс
	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
	# are returning to the kernel.
	# See comments in process.c:copy_thread() for details.
	movb PT_OLDSS(%esp), %ah
	movb PT_CS(%esp), %al
	andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax # макросы однозначно образую число 20403h, оно кладеться в eax
	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax # тут макросы образую также однозначно число 403h и эта проверка пройдет всегда, зачем она тогда О_о
	CFI_REMEMBER_STATE # ???
	je ldt_ss			# returning to user-space with LDT SS
                                        # какая то махинация со стеком
restore_nocheck:
	RESTORE_REGS 4			# skip orig_eax/error_code
                                        # восстанавливаем значения регистров (см. ниже)
	CFI_ADJUST_CFA_OFFSET -4 # этот макрос на сколько я понял что то вроде метки на стеке откудова брать куда класть значения регистров
irq_return:
	INTERRUPT_RETURN # вот тут то мы вызовем заветную инструкцию iret с помощью которой перейдем в usep space и произведем понижение привелегий (вот только я незаметил момента когда мы клали в стек необходимые ей параметры ?)
/* а все что дальше идет зачем ? */

syscall_trace_entry: # проверка не прошла прыгнули сюда и тут еще один шанс
	movl $-ENOSYS,PT_EAX(%esp)
	movl %esp, %eax
	call syscall_trace_enter # что делает функция ?
	/* What it returned is what we'll actually use.  */
	cmpl $(nr_syscalls), %eax
	jnae syscall_call # и бац все равно можем сделать то что хотели, проделав какуюто преобработку, какую ?
	jmp syscall_exit
END(syscall_trace_entry)

При таком вызове макроса

restore_nocheck:
	RESTORE_REGS 4
как он будет выполнятся ? Сначала выполнится чертвертая метка, потом 1-3 и он закончит свою работу выполнив POP_GS \pop ?
.macro RESTORE_REGS pop=0
	RESTORE_INT_REGS
1:	popl %ds
	CFI_ADJUST_CFA_OFFSET -4
	/*CFI_RESTORE ds;*/
2:	popl %es
	CFI_ADJUST_CFA_OFFSET -4
	/*CFI_RESTORE es;*/
3:	popl %fs
	CFI_ADJUST_CFA_OFFSET -4
	/*CFI_RESTORE fs;*/
	POP_GS \pop
.pushsection .fixup, "ax"
4:	movl $0, (%esp)
	jmp 1b
5:	movl $0, (%esp)
	jmp 2b
6:	movl $0, (%esp)
	jmp 3b
.section __ex_table, "a"
	.align 4
	.long 1b, 4b
	.long 2b, 5b
	.long 3b, 6b
.popsection
	POP_GS_EX
.endm

.macro POP_GS pop=0 # что оно делает ?)
	addl $(4 + \pop), %esp
	CFI_ADJUST_CFA_OFFSET -(4 + \pop)
.endm

фух, несколько часов пост делал. Простите за мноо букф и еще больше вопросов, просто нужно все это понять %) Отвечайте по возможности лучше кусочками, так проще мазайку будет сложить.

PS. И кстати если получится сложить все это в единую картину с хорошим описание то это будет очень хороший мануал, коих нету на белом свете.


Кулхацкер???

Мне не понятно зачем тебе знать как работает внутри обработчик прерывания. Вроде достаточно знать как прерывание вызывается, и как оно возвращает результат. Далее перебиваем обработчик на свой код. Этот код делает свое «грязное дело», а потом вызывает оригинальный syscall (который мы предварительно запомнили).

З.Ы. Сказать по правде я не крут в ядерном программировании, так что поправьте, если я не прав.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

затем что это будет вызывается не из user space и ему до сис. прерывания доступа вообще быть не должно.

Cupper
() автор топика
Ответ на: комментарий от bibi

Пока что смог от туда подчерпнуть только осознаниче того что делает строчка GET_CURRENT (%ebx) :) а именно получает указатель на структура task_struct текущего процессе. Уже не плохо )

Cupper
() автор топика
Ответ на: комментарий от Cupper

>затем что это будет вызывается не из user space и ему до сис. прерывания доступа вообще быть не должно.

O_o Сказанное не понял. Если не трудно, то дайте пожалуйста более развернутый комментарий.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

(Для того чтобы порадовать) Читал, что в Линуксе добавили ещё один способ вызова syscall через sysenter/sysexit, вместо 80 прерывания.

Вот статейка по syscall http://rflinux.blogspot.com/2008/03/linux-syscalls-linux.html. Поищи там про sysenter/sysexit.

pathfinder ★★★★
()
Ответ на: комментарий от Cupper

>затем что это будет вызывается не из user space и ему до сис. прерывания доступа вообще быть не должно.

Моя идея была в том, что делаем так, как это бы сделали в старом «страшном чёрном» DOS-е. Т.е. заменяем 80 прерывание своим. Старое прерывание запоминаем. При срабатывании «нашего» обработчика прерывания делаем «что-то нехорошее», а потом вызываем код старого прерывания просто как функцию по сохраненному указателю.

Правда «защищенный режим» может внести свои коррективы. Если это так, то «просветите» меня.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

sysenter ненужен. Подмена int 80 неуместна. Давайте не будем увлекаться бессмысленными разговорами и просто попробуем понять до винтиков как оно работает :)

Cupper
() автор топика
Ответ на: комментарий от pathfinder

Защищенный режим обязательно внесет коррективы. Если уж действительно нужно делать перехват вызовов, то стоит поизучать LD_PRELOAD.

rmap
()
Ответ на: комментарий от Cupper

>sysenter ненужен. Подмена int 80 неуместна.

Вот теперь я понял. Дело не в подмене/модифицировании/клонировании обработчика 80 прерывания. Просто вам очень хочется понять каждую строчку в этом «замечательном» ассемблерном коде. Занятие благородное, но бессмысленное, т.к. завтра все может кардинально поменяться код после метки syscall_exit: Поберегите лучше нервы. Почитайте лучше общеобразовательные статьи на данную тему и этим ограничтесь.

Давайте не будем увлекаться бессмысленными...

Фраза безусловно радует.

pathfinder ★★★★
()

Сходи сюда
http://sourceware.org/insight/
собери gdb с графическим фронтендом insight
отлаживай сколько влезет в пошаговом режиме
там есть и ассемблер и С и смешаный вид,
хоть в qemu хоть kgdb включи в ядре.

anonymous
()
Ответ на: комментарий от rmap

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

Cupper
() автор топика
Ответ на: комментарий от Cupper

Вот нашел чтото похожее на то что я делаю :) http://icefoto.narod.ru/new_int.htm. Права устаревшее и без подробностей.

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

   testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) # проверка чего ?) Того что из данного треда можно делать системные вызовы ? 
   jnz syscall_trace_entry # сюда попадем если проверка не прошла, но в этой метке все равно может произойти вызов (см. ниже) 

Cupper
() автор топика
Ответ на: комментарий от Cupper

что непонятно-то?

если _TIF_WORK_SYSCALL_ENTRY, то у нас slow path перед
собственно вызовом syscall, напр этот thread под отладчиком
и/или audit/tracepoint.

см syscall_trace_enter(), напр.

idle ★★★★★
()

Ты монстр. В хорошем смысле этого слова.

ttnl ★★★★★
()

ради интереса я бы прогнал это через препроцессор, дабы избавиться от макросов

anonymous
()
Ответ на: комментарий от Cupper

на примере Haiku/BeOS, вот как работает механизм сисколлов: http://www.haiku-os.org/documents/dev/system_calls

В линукс аналогично, тоже трамплин , только ядро и способ вызова сисколлов другой. Еще можешь посмотреть минимализм в духе http://wiki.osdev.org/Category:Bare_bones_tutorials и сравнить с реализацией в линукс/бзд/хайке.

anonymous
()
Ответ на: комментарий от Cupper

gcc -E. .S — исходник, не обработанный препроцессором, .s — обработанный. Это для gas, nasm и yasm свои ключики имеют.

anonymous
()
Ответ на: комментарий от anonymous

ещё механизм работы сисколлов, и через int 80, и через sysenter/sysexit, и гибридный linuxemu/freebsd был хорошо расписан в Linux assembly HOWTO. Основная идея всё та же: проход через трамплин, который перенаправляет вызовы из userspace в пространство ядра.

anonymous
()
Ответ на: комментарий от anonymous

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

Cupper
() автор топика
Ответ на: комментарий от anonymous

> gcc -E. .S — исходник, не обработанный препроцессором, .s — обработанный. Это для gas, nasm и yasm свои ключики имеют.

отделите тегами пожалуйста а то не могу понять где граница между кодом и описанием

Cupper
() автор топика
Ответ на: комментарий от Cupper

IDT

Мы столкнулись с еще одной проблеммой, выбор номера прерывания, изначально выбрали f2, т.к. в книже Боветти Чезати было сказано что номера прерываний f1-fa зарезервированы на будущее, потом в коде нашли что f1-f7 используются для нужд толи TLS толи TSS. А потом просто расспечатали все IDT и оказалось что все забито. Нуежно все номера прерывание уже использованы О-о ? кто нибудь обладает актуальной такой инфой ?

Cupper
() автор топика
Ответ на: комментарий от anonymous

вопрос по отладке: как отлаживать int80 начиная из юзер спейса чтобы узреть все трансформации стека, а то банально получается только саму рабоу system_call а этого недостаточно

Cupper
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.