RDot

RDot (https://rdot.org/forum/index.php)
-   Software development (https://rdot.org/forum/forumdisplay.php?f=19)
-   -   Примеры уязвимостей в коде. (https://rdot.org/forum/showthread.php?t=2672)

SynQ 25.03.2013 14:26

Примеры уязвимостей в коде.
 
Встретил занятный код в ядре линукса, возможно будет интересно.

http://lxr.linux.no/#linux+v3.8/fs/select.c#L816

Код:

816 int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
 817                struct timespec *end_time)
 818 {
 819        struct poll_wqueues table;
 820        int err = -EFAULT, fdcount, len, size;
 821        /* Allocate small arguments on the stack to save memory and be
 822          faster - use long to make sure the buffer is aligned properly
 823          on 64 bit archs to avoid unaligned access */
 824        long stack_pps[POLL_STACK_ALLOC/sizeof(long)];
 825        struct poll_list *const head = (struct poll_list *)stack_pps;
 826        struct poll_list *walk = head;
 827        unsigned long todo = nfds;
 828
 829        if (nfds > rlimit(RLIMIT_NOFILE))
 830                return -EINVAL;
 831
 832        len = min_t(unsigned int, nfds, N_STACK_PPS);
 833        for (;;) {
 834                walk->next = NULL;
 835                walk->len = len;
 836                if (!len)
 837                        break;
 838
 839                if (copy_from_user(walk->entries, ufds + nfds-todo,
 840                                        sizeof(struct pollfd) * walk->len))
 841                        goto out_fds;
 842
 843                todo -= walk->len;
 844                if (!todo)
 845                        break;
 846
 847                len = min(todo, POLLFD_PER_PAGE);
 848                size = sizeof(struct poll_list) + sizeof(struct pollfd) * len;
 849                walk = walk->next = kmalloc(size, GFP_KERNEL);
 850                if (!walk) {
 851                        err = -ENOMEM;
 852                        goto out_fds;
 853                }
 854        }
 855
 856        poll_initwait(&table);
 857        fdcount = do_poll(nfds, head, &table, end_time);
 858        poll_freewait(&table);
 859
 860        for (walk = head; walk; walk = walk->next) {
 861                struct pollfd *fds = walk->entries;
 862                int j;
 863
 864                for (j = 0; j < walk->len; j++, ufds++)
 865                        if (__put_user(fds[j].revents, &ufds->revents))
 866                                goto out_fds;
 867        }

Вызвав сисколл poll с параметрами ufds (указатель) и nfds (unsigned int), попадаем в функцию do_sys_poll() с этими же параметрами.

Здесь могла бы быть неплохая, пусть и не из легких, бага, если бы строка 835 располагась всего двумя строчками ниже :)
Тогда при передаче nfds = 0, из цикла сразу бы происходил выход, не вызывая copy_from_user(), которая проверяет "правильность" переданного указателя ufds, и ниже происходил вызов __put_user(), которая такой проверки не делает.

Получили бы запись неопределённых данных (из stack_pps[]) по любому желаемому адресу в ядре.
С неопределённостью можно бороться, например, предварительным массажем стека.

SynQ 09.10.2015 13:22

Стандартный security баг в модуле ядра:
http://habrahabr.ru/company/ua-hosting/blog/268409/


Часовой пояс GMT +3, время: 17:14.

Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd. Перевод: zCarot