Доброго всем времени суток! Пытаюсь внутри ядра провернуть магию. Сделать ljmp на свой сегмент Код (Text): __asm__ __volatile__ ( "\tljmp $"STR(__MY_CS)", $1f\n" "\t1:\n" "\tnop\n" ::: "eax", "memory"); Но получаю сбой общей защиты (general protection error) При попытке сделать lcall Код (Text): __asm__ __volatile__ ( "\tlcall *(%0)\n" ::"r"(virt_to_phys(addr)): "eax", "memory"); получается тоже самое. addr здес адрес функции на которую хочу прыгнуть.
Если я правильно понял что происходит, то нужно задействовать шлюз вызова (call gate). Просто так повысить себе привилегии (понизить CPL) нельзя. Подойдут также int gate, trap gate и task gate.
Гм. Ради интереса, код из первой коробки в интелловском синтаксисе выглядит как? Через far jmp изменить CPL не получится (не считая task switch?). Также, если "понижение CPL" трактовать в прямом смысле (== "понижение привилегированности" == _численное_ увеличение CPL), то через far call это также не провернуть – необходимо использовать retf или iret.
Mika0x65 Наверно не точно выраилась понижение привилегий это увеличение CPL. Гейты же служат для повышения привилегий и если верить интеловскому ману DPL гейта не может быть больше CPL вызвавщего кода, то есть нельзя гейтом перепрыгнуть с нулевого кольца на 3. Sol_Ksacap Код (Text): jmp far __MY_CS:1 Как-то так. Почему? Ведь при запуске процесса ядро как-то отправляет процесс на пользовательский уровень привилегий (Никак не могу найти именно этот код) А можно подробнее как именно? Положить адрес функции в стек?
>>Через far jmp изменить CPL не получится >Почему? А вот так определено. В тот же уровень привилегий – пожалуйста (например, из 32х-битного сегмента в 64х-битный), а изменить CPL не должно получиться. Через "far call" можно, но только на повышение привилегированности, через гейт. (Опять-таки что-то там ещё есть с TaskGate, но никогда не касались этого наследия, поэтому ничего не можем сказать). >ядро как-то отправляет процесс на пользовательский уровень привилегий Вероятно, с помощью "iret". >использовать retf или iret Из r0 в r3: Код (Text): UsingIret: push NewSsSelector push NewEsp push NewEflags push NewCsSelector push NewEip iret UsingRetf: ; то же самое, но без eflags push NewSsSelector push NewEsp push NewCsSelector push NewEip retf Осторожно только в случае с х64 – размер операнда для push'ей 64 бита, а для iret и retf по дефолту – 32 бита. К "retf" х64-ассемблер должен автоматом добавить префикс для переопределения размера операнда нужным образом, а "iret", вероятно, лучше задать явно – "iretq".
После выполнение своего кода получае вполне логичную проблему что не могу вернутся на 0 кольцо привилегий. Уместно ли в данном случае попытатся воспользоватся хаком и вызывать пользовательское прерывание exit или надо мудрить с tss.
В принципе, варианты остаются все те же -- call gate, trap gate, int gate, task gate. Можно воспользоваться существующим, можно добавить свой .
А варианты востановить после iret никаких нет? Если запускаемому процессу флаг NT выставть в обратную сторону стек раскрутить не получится?
friackazoid В NT просто так с юзера в ядро и обратно не ходят. Существуют шлюзы, через которые это выполняется. Контекст задачи сохраняется(KTRAP_FRAME), только потом можно чтото вызывать. Не знаю как в линус, но думаю контекст также сохраняется. Интересно почему ось не отваливается после ваших хождений между кольцами защиты.
NT? В смысле, NestedTask? В этом случае все равно будет задействован task gate. Не думаю, что iret сможет как-то помочь. Продвижение "вглубь" колец защиты возможно только с помощью шлюзов, обратно -- с помощью iret/retf.
Mika0x65 Windows NT. В юзермод вы не пройдёте просто выполнив Iret. Тоесть пройдёте, но поток ничего выполнять не сможет. Окружение не то, например стек ядерный, попытка обращения к нему на высоком кпл приведёт к #GP.
Clerk Я friackazoid спрашивал насчет NT, забыл обращение написать. Стек таки сменится, т.к. ss:esp режима пользователя будут (если friackazoid положит ) в ядерном стеке лежать в момент выполнения iret/retf. А с окружением придется сложнее. Тут либо надо спроецировать libc и компанию, либо пользоваться только голыми системными вызовами.
Под NT имеля естественно флаг в eflags. Глупо бы было создавать ветку в юникс разделе и говорить про винду =) Clerk К тому же кто вам сказал что ядро не падает, еще как падает =) В юзермод то как раз прекрасно проходит вот обратно да только через гейт. Вы не поверите но в линукс контекст очень странно сохраняется и очень хочется поотрывать руки за такое количество макросов. Вот честное слово я конечно понимаю что апаратное переключение контекстов медленно. Но написание около лишних 200 строк и невероятная магия со стеком и сегментом данных (знали ли вы что ядро работает с юзерским дескриптором сегмента данных) ради не использования 3-4 медленных команд. Это я еще молчу про накладные расходы на распихивание всего этого дела в шедулер и создания полноценного треда а то и процесса. Mika0x65 libc мне и не нужна я внутри ядра тут никакой libc и не пахнет. Общая задача выглядит как исполнение нескольких функций (именно функций, без создания треда и процесса) на более низком кольце привилегий и возврат обратно.