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


         

Листинг 2 ключевой фрагмент функции 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;

       }




Содержание  Назад  Вперед