Захватываем ring 0 в Linux

       

ключевой фрагмент функции elf_core_dump(), подверженной переполнению


Типичное переполнение буфера! Программист объявляет знаковую переменную len (см. /* 1 */) и спустя некоторое время передает ее функции copy_form_user, копирующей данные из пользовательской памяти в область ядра. Проверка на отрицательное значение не выполняется (см. /* 2 */). Что это значит для нас в практическом плане? А вот что! Если current->
mm->
arg_start будет больше, чем current->
mm->
arg_end, в ядро скопируется очччень большой регион пользовательского пространства.

А как этого можно добиться? Анализ показывает, что переменные current->
mm->
arg_start и current->
mm->
arg_end инициализируются в функции create_elf_tables, причем если функция strnlen_user возвратит ошибку, то будет инициализирована лишь переменная current->
mm->
arg_start, а current->
mm->
arg_end сохранит свое значение, унаследованное от предыдущего файла.

static elf_addr_t *

create_elf_tables(char *p, int argc, int envc,

       struct elfhdr * exec,

       unsigned long load_addr,

       unsigned long load_bias,

       unsigned long interp_load_addr, int ibcs)

       {

              current->
mm->
arg_start = (unsigned long) p;

              while (argc-->
0)

              {

                     __put_user((elf_caddr_t)(unsigned long)p,argv++);

                     len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);

                     if (!len || len >
PAGE_SIZE*MAX_ARG_PAGES)

                           return NULL; /* * */

                     p += len;

              }

              __put_user(NULL, argv);

              current->
mm->
arg_end = current->
mm->
env_start = (unsigned long) p;

       }



Содержание раздела