ljmp с понижением CPL

Тема в разделе "WASM.UNIX", создана пользователем friackazoid, 22 фев 2010.

  1. friackazoid

    friackazoid New Member

    Публикаций:
    0
    Регистрация:
    4 июн 2009
    Сообщения:
    102
    Доброго всем времени суток!

    Пытаюсь внутри ядра провернуть магию. Сделать ljmp на свой сегмент

    Код (Text):
    1. __asm__ __volatile__ (
    2.                 "\tljmp $"STR(__MY_CS)", $1f\n"
    3.                 "\t1:\n"
    4.                 "\tnop\n"
    5.                 ::: "eax", "memory");
    Но получаю сбой общей защиты (general protection error)

    При попытке сделать lcall

    Код (Text):
    1. __asm__ __volatile__ (
    2.                 "\tlcall *(%0)\n"
    3.                 ::"r"(virt_to_phys(addr)): "eax", "memory");
    получается тоже самое. addr здес адрес функции на которую хочу прыгнуть.
     
  2. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Если я правильно понял что происходит, то нужно задействовать шлюз вызова (call gate). Просто так повысить себе привилегии (понизить CPL) нельзя. Подойдут также int gate, trap gate и task gate.
     
  3. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Гм. Ради интереса, код из первой коробки в интелловском синтаксисе выглядит как?

    Через far jmp изменить CPL не получится (не считая task switch?). Также, если "понижение CPL" трактовать в прямом смысле (== "понижение привилегированности" == _численное_ увеличение CPL), то через far call это также не провернуть – необходимо использовать retf или iret.
     
  4. friackazoid

    friackazoid New Member

    Публикаций:
    0
    Регистрация:
    4 июн 2009
    Сообщения:
    102
    Mika0x65
    Наверно не точно выраилась понижение привилегий это увеличение CPL. Гейты же служат для повышения привилегий и если верить интеловскому ману DPL гейта не может быть больше CPL вызвавщего кода, то есть нельзя гейтом перепрыгнуть с нулевого кольца на 3.

    Sol_Ksacap
    Код (Text):
    1. jmp far __MY_CS:1
    Как-то так.

    Почему? Ведь при запуске процесса ядро как-то отправляет процесс на пользовательский уровень привилегий (Никак не могу найти именно этот код)

    А можно подробнее как именно? Положить адрес функции в стек?
     
  5. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    >>Через far jmp изменить CPL не получится
    >Почему?
    А вот так определено. В тот же уровень привилегий – пожалуйста (например, из 32х-битного сегмента в 64х-битный), а изменить CPL не должно получиться. Через "far call" можно, но только на повышение привилегированности, через гейт. (Опять-таки что-то там ещё есть с TaskGate, но никогда не касались этого наследия, поэтому ничего не можем сказать).

    >ядро как-то отправляет процесс на пользовательский уровень привилегий
    Вероятно, с помощью "iret".

    >использовать retf или iret
    Из r0 в r3:
    Код (Text):
    1. UsingIret:
    2. push NewSsSelector
    3. push NewEsp
    4. push NewEflags
    5. push NewCsSelector
    6. push NewEip
    7. iret
    8.  
    9. UsingRetf:          ; то же самое, но без eflags
    10. push NewSsSelector
    11. push NewEsp
    12. push NewCsSelector
    13. push NewEip
    14. retf
    Осторожно только в случае с х64 – размер операнда для push'ей 64 бита, а для iret и retf по дефолту – 32 бита. К "retf" х64-ассемблер должен автоматом добавить префикс для переопределения размера операнда нужным образом, а "iret", вероятно, лучше задать явно – "iretq".
     
  6. friackazoid

    friackazoid New Member

    Публикаций:
    0
    Регистрация:
    4 июн 2009
    Сообщения:
    102
    Sol_Ksacap
    Спасибо помогло)
     
  7. friackazoid

    friackazoid New Member

    Публикаций:
    0
    Регистрация:
    4 июн 2009
    Сообщения:
    102
    После выполнение своего кода получае вполне логичную проблему что не могу вернутся на 0 кольцо привилегий. Уместно ли в данном случае попытатся воспользоватся хаком и вызывать пользовательское прерывание exit или надо мудрить с tss.
     
  8. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    В принципе, варианты остаются все те же -- call gate, trap gate, int gate, task gate. Можно воспользоваться существующим, можно добавить свой :).
     
  9. friackazoid

    friackazoid New Member

    Публикаций:
    0
    Регистрация:
    4 июн 2009
    Сообщения:
    102
    А варианты востановить после iret никаких нет?

    Если запускаемому процессу флаг NT выставть в обратную сторону стек раскрутить не получится?
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    friackazoid
    В NT просто так с юзера в ядро и обратно не ходят. Существуют шлюзы, через которые это выполняется. Контекст задачи сохраняется(KTRAP_FRAME), только потом можно чтото вызывать. Не знаю как в линус, но думаю контекст также сохраняется. Интересно почему ось не отваливается после ваших хождений между кольцами защиты.
     
  11. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    NT? В смысле, NestedTask? В этом случае все равно будет задействован task gate. Не думаю, что iret сможет как-то помочь. Продвижение "вглубь" колец защиты возможно только с помощью шлюзов, обратно -- с помощью iret/retf.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Mika0x65
    Windows NT.
    В юзермод вы не пройдёте просто выполнив Iret. Тоесть пройдёте, но поток ничего выполнять не сможет. Окружение не то, например стек ядерный, попытка обращения к нему на высоком кпл приведёт к #GP.
     
  13. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Clerk
    Я friackazoid спрашивал насчет NT, забыл обращение написать. Стек таки сменится, т.к. ss:esp режима пользователя будут (если friackazoid положит :) ) в ядерном стеке лежать в момент выполнения iret/retf. А с окружением придется сложнее. Тут либо надо спроецировать libc и компанию, либо пользоваться только голыми системными вызовами.
     
  14. friackazoid

    friackazoid New Member

    Публикаций:
    0
    Регистрация:
    4 июн 2009
    Сообщения:
    102
    Под NT имеля естественно флаг в eflags. Глупо бы было создавать ветку в юникс разделе и говорить про винду =)

    Clerk
    К тому же кто вам сказал что ядро не падает, еще как падает =) В юзермод то как раз прекрасно проходит вот обратно да только через гейт.
    Вы не поверите но в линукс контекст очень странно сохраняется и очень хочется поотрывать руки за такое количество макросов. Вот честное слово я конечно понимаю что апаратное переключение контекстов медленно. Но написание около лишних 200 строк и невероятная магия со стеком и сегментом данных (знали ли вы что ядро работает с юзерским дескриптором сегмента данных) ради не использования 3-4 медленных команд. Это я еще молчу про накладные расходы на распихивание всего этого дела в шедулер и создания полноценного треда а то и процесса.

    Mika0x65
    libc мне и не нужна я внутри ядра тут никакой libc и не пахнет.

    Общая задача выглядит как исполнение нескольких функций (именно функций, без создания треда и процесса) на более низком кольце привилегий и возврат обратно.
     
  15. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    friackazoid
    Ну тогда EFLAGS.NT не поможет. Делаем шлюз и через него возвращаемся.
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    friackazoid
    Там ведь опенсурсная ось. Загляните в сурцы ;)