The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Вариант для распечатки  
Пред. тема | След. тема 
Форум Разговоры, обсуждение новостей
Режим отображения отдельной подветви беседы [ Отслеживать ]

Оглавление

Новый способ совершения локальной DoS-атаки в Linux, opennews (??), 25-Ноя-10, (0) [смотреть все]

Сообщения [Сортировка по времени | RSS]


30. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 25-Ноя-10, 22:35 
вот так выглядит более правильно
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 3c8af63..7ca2e4f 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -6,7 +6,7 @@
#include <linux/mutex.h>
#include <net/sock.h>

-extern void unix_inflight(struct file *fp);
+extern int unix_inflight(struct file *fp);
extern void unix_notinflight(struct file *fp);
extern void unix_gc(void);
extern void wait_for_unix_gc(void);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index cb552e2..673ea9c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -572,11 +572,17 @@ static struct proto unix_proto = {
  */
static struct lock_class_key af_unix_sk_receive_queue_lock_key;

+#define UNIX_INFLIGHT_TRIGGER_GC 128
+extern bool gc_in_progress;
+
static struct sock * unix_create1(struct socket *sock)
{
        struct sock *sk = NULL;
        struct unix_sock *u;

+       if (atomic_read(&unix_tot_inflight) > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
+               unix_gc();
+
        if (atomic_read(&unix_nr_socks) >= 2*get_max_files())
                goto out;

@@ -1268,6 +1274,7 @@ EXPORT_SYMBOL_GPL(unix_destruct_fds);
static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
{
        int i;
+       int rc = 0;
        /*
         * Need to duplicate file references for the sake of garbage
@@ -1278,10 +1285,13 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
        if (!UNIXCB(skb).fp)
                return -ENOMEM;

-       for (i=scm->fp->count-1; i>=0; i--)
-               unix_inflight(scm->fp->fp[i]);
+       for (i=scm->fp->count-1; i>=0; i--) {
+               rc = unix_inflight(scm->fp->fp[i]);
+               if (rc)
+                       break;
+       }
        skb->destructor = unix_destruct_fds;
-       return 0;
+       return rc;
}

/*
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 5f96cea..4042e9a 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -124,21 +124,25 @@ static struct sock *unix_get_socket(struct file *filp)
  *     descriptor if it is for an AF_UNIX socket.
  */

-void unix_inflight(struct file *fp)
+int unix_inflight(struct file *fp)
{
+       int ret = 0;
        struct sock *s = unix_get_socket(fp);
        if(s) {
                struct unix_sock *u = unix_sk(s);
                spin_lock(&unix_gc_lock);
-               if (atomic_inc_return(&u->inflight) == 1) {
+               ret = atomic_inc_return(&u->inflight);
+               if (ret == 1) {

                        BUG_ON(!list_empty(&u->link));
                        list_add_tail(&u->link, &gc_inflight_list);
                } else {
                        BUG_ON(list_empty(&u->link));
                }
                atomic_inc(&unix_tot_inflight);
+               ret = ret > get_max_files();
                spin_unlock(&unix_gc_lock);
        }
+       return ret;
}
EXPORT_SYMBOL_GPL(unix_notinflight);

@@ -270,7 +274,7 @@ static void inc_inflight_move_tail(struct unix_sock *u)
                list_move_tail(&u->link, &gc_candidates);
}

-static bool gc_in_progress = false;
+bool gc_in_progress = false;

void wait_for_unix_gc(void)
{

ну и для параноиков sysctl -w fs.files-max=1000

Ответить | Правка | Наверх | Cообщить модератору

39. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от pavlinux (ok), 26-Ноя-10, 00:29 
sysctl -w fs.file-max=1000

Ответить | Правка | Наверх | Cообщить модератору

59. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 26-Ноя-10, 13:29 
и загубишь все на корню - слишком глобальная эта ручка, а если в фиксе заменить за get_max_file() на NR_FILES просто ограничишь очередь сообщений до 8к. и все будет жить.
Ответить | Правка | Наверх | Cообщить модератору

64. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от pavlinux (ok), 26-Ноя-10, 14:06 
> и загубишь все на корню - слишком глобальная эта ручка, а если
> в фиксе заменить за get_max_file() на NR_FILES просто ограничишь очередь сообщений
> до 8к. и все будет жить.

Не, там синтаксисеская обшибка

вместо
fs.files-max, надо
fs.file-max

Ответить | Правка | Наверх | Cообщить модератору

70. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 26-Ноя-10, 15:30 
ааа. это я полусонным рисовал по памяти.
спасибо.
Ответить | Правка | Наверх | Cообщить модератору

71. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 26-Ноя-10, 15:32 
> ааа. это я полусонным рисовал по памяти.
> спасибо.

просто максимальное количество unix sockets это 2*get_max_files().
так что ddos тулза упрется в нее в конце концов - но системе станет хреново к тому моменту.
А потом exit_task -> put file struct - будет оооочень долгим ибо их дохрена.

Ответить | Правка | Наверх | Cообщить модератору

74. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от pavlinux (ok), 26-Ноя-10, 15:49 
>> ааа. это я полусонным рисовал по памяти.
>> спасибо.
> просто максимальное количество unix sockets это 2*get_max_files().
> так что ddos тулза упрется в нее в конце концов - но
> системе станет хреново к тому моменту.
> А потом exit_task -> put file struct - будет оооочень долгим ибо
> их дохрена.

Ну там дальше идет в ход schedule(), по этому при больших file-max,
дело до SIG_KILL дойдет не скоро. Более того, его же надо чем-то послать -
терминал пустить, bash породить, который сам ещё форкнется и уж потом exec_нет kill

Я вот опытным путём дошёл до значения 84000, нагрузка на CPU стала от 75% до 98%

Ответить | Правка | Наверх | Cообщить модератору

77. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 26-Ноя-10, 16:13 
exit_task прервать нельзя - в этом code path нету мьютексов - только spinlock / rwlock / rcu.
поэтому schedule() вызвать некому.
при всем этом оно еще держит на себе BKL и стопку локов (один из которых помоему task_lock) - поэтому ошибка которая должна приводить с 100% загрузки на одном CPU - не дает работать на других.
в моей тестовой vmware + RHEL5 - загрузка сразу взлетела на 100%, но kill можно было послать, а потом система стала в ступор пытаясь в течении нескольких минут освобожать файловые дискрипторы.
Это и послужило причиной того что оригинальный патч был отвергнут и написана эта затычка, который не спасет если добавить fork() или просто запустить несколько экземпляров - но ослабит атаку.

А дальше подождем правильного фикса.

Ответить | Правка | Наверх | Cообщить модератору

80. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от pavlinux (ok), 26-Ноя-10, 16:25 
> exit_task прервать нельзя - в этом code path нету мьютексов - только
> spinlock / rwlock / rcu.
> поэтому schedule() вызвать некому.

void wait_for_unix_gc(void)
{
        wait_event(unix_gc_wait, gc_in_progress == false);
}

#define wait_event()    
http://lxr.linux.no/#linux+v2.6.36/include/linux/wait.h#L217

schedule_timeout()
http://lxr.linux.no/#linux+v2.6.36/kernel/timer.c#L1430

шыдуля().

Ответить | Правка | Наверх | Cообщить модератору

82. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 26-Ноя-10, 16:41 
>[оверквотинг удален]
>> spinlock / rwlock / rcu.
>> поэтому schedule() вызвать некому.
> void wait_for_unix_gc(void)
> {
>         wait_event(unix_gc_wait, gc_in_progress == false);
> }
> #define wait_event()
> http://lxr.linux.no/#linux+v2.6.36/include/linux/wait.h#L217
> schedule_timeout()
> http://lxr.linux.no/#linux+v2.6.36/kernel/timer.c#L1430

С теперь козырный вопрос - где вы в exit_task увидели вызов wait_for_unix_gc ?
эта функция вызывается при send() если не путаю и при close(), но close на сокет уже вызывался из приложения - только ресурсы это не освободило.

Ответить | Правка | Наверх | Cообщить модератору

87. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от pavlinux (ok), 26-Ноя-10, 18:34 
> но close на сокет уже вызывался из приложения

так там же for (;;)

Ответить | Правка | Наверх | Cообщить модератору

88. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 26-Ноя-10, 18:50 
позволю себе напомнить код "эксплойта"
int main ()
{
  int fd[2], ff[2];
  int target;
  if (socketpair (PF_UNIX, SOCK_SEQPACKET, 0, fd)==-1)
    return 1;
  for (;;)
  {
    if (socketpair (PF_UNIX, SOCK_SEQPACKET, 0, ff)==-1)
    return 2;
    send_fd (ff[0], fd[0]);
    send_fd (ff[0], fd[1]);
    close (fd[1]); <<< это что ?
    close (fd[0]); <<< и вот это ?
    fd[0] = ff[0];
    fd[1] = ff[1];
  }
}

если хорошо посмотрим в код net/unix

static int unix_release_sock(struct sock *sk, int embrion)
{
...

        if (unix_tot_inflight)
                unix_gc();              /* Garbage collect fds */

        return 0;
}


unix_release
{
unix_release_sock().
}
..

static const struct proto_ops unix_stream_ops = {
        .family =       PF_UNIX,
        .owner =        THIS_MODULE,
        .release =      unix_release,
..
}

Ответить | Правка | Наверх | Cообщить модератору

90. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от pavlinux (ok), 26-Ноя-10, 19:56 
Чёй-та я не пойму хода Ваших мыслей.

>   for (;;)
>   {
>     if (socketpair (PF_UNIX, SOCK_SEQPACKET, 0, ff) == -1) return -1;
>     close (fd[1]); <<< это что ?
>     close (fd[0]); <<< и вот это ?
> }

Схема такая

for(;;) {
...
close (1);
|_
  unix_release()
  |_
    unix_release_sock().
    |_
       unix_gc();      

close(0);
|_
  unix_release()
  |_
    unix_release_sock().
    |_
       unix_gc();      
}

Ответить | Правка | К родителю #88 | Наверх | Cообщить модератору

94. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от Аноним (-), 27-Ноя-10, 23:31 
я там тоже не все понял, но факт в том что in flight реквесты накапливаются на одном сокете.
из-за этого unix_gc не может пометить этот сокет как gc_candidate и прибить.
почему так - не разбирался. если есть желание добавь стопку printk и посмотри.
Но это подтверждается патчем - который срабатывает по привышению количества in flight на сокете.
Ответить | Правка | К родителю #90 | Наверх | Cообщить модератору

89. "Новый способ совершения локальной DoS-атаки в Linux"  +/
Сообщение от h4tr3demail (ok), 26-Ноя-10, 18:52 
На своём EeePC 1000 при дефолтных (сиречь моих рабочих настройках) проверил:
fs.file-max = 101749

в /etc/sysctl.conf только:
# Disable packet forwarding
net.ipv4.ip_forward=0
# Disable the magic-sysrq key (console security issues)
kernel.sysrq = 0
# Enable TCP SYN Cookie Protection
net.ipv4.tcp_syncookies = 1
vm.dirty_writeback_centisecs=1500

ядрышко: 2.6.35.8, памяти 1024Мб (часть на видео расходуется), CPU - Atom N270

как результат, система стала заметно дольше откликаться, но и после 10 минут работы бомбы, терминал запустился где-то за 15 секунд, правда для убийства пришлось ввести что-то вроде:
while true do killall -9 tst; done

и долго ждать убийства всего этого безобразия :)

Ответить | Правка | К родителю #74 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру