|
Message-ID: <CAG48ez0boPBDm=Uh5xHXAxTj0BTRGyGp4uCgPgw7PkOCo47Hdg@mail.gmail.com> Date: Thu, 10 Sep 2020 22:55:11 +0200 From: Jann Horn <jannh@...gle.com> To: Kees Cook <keescook@...omium.org>, John Wood <john.wood@....com> Cc: Kernel Hardening <kernel-hardening@...ts.openwall.com>, Matthew Wilcox <willy@...radead.org>, Jonathan Corbet <corbet@....net>, Alexander Viro <viro@...iv.linux.org.uk>, Ingo Molnar <mingo@...hat.com>, Peter Zijlstra <peterz@...radead.org>, Juri Lelli <juri.lelli@...hat.com>, Vincent Guittot <vincent.guittot@...aro.org>, Dietmar Eggemann <dietmar.eggemann@....com>, Steven Rostedt <rostedt@...dmis.org>, Ben Segall <bsegall@...gle.com>, Mel Gorman <mgorman@...e.de>, Luis Chamberlain <mcgrof@...nel.org>, Iurii Zaikin <yzaikin@...gle.com>, James Morris <jmorris@...ei.org>, "Serge E. Hallyn" <serge@...lyn.com>, linux-doc@...r.kernel.org, kernel list <linux-kernel@...r.kernel.org>, linux-fsdevel <linux-fsdevel@...r.kernel.org>, linux-security-module <linux-security-module@...r.kernel.org> Subject: Re: [RFC PATCH 6/6] security/fbfam: Mitigate a fork brute force attack On Thu, Sep 10, 2020 at 10:22 PM Kees Cook <keescook@...omium.org> wrote: > In order to mitigate a fork brute force attack it is necessary to kill > all the offending tasks. This tasks are all the ones that share the > statistical data with the current task (the task that has crashed). > > Since the attack detection is done in the function fbfam_handle_attack() > that is called every time a core dump is triggered, only is needed to > kill the others tasks that share the same statistical data, not the > current one as this is in the path to be killed. > > When the SIGKILL signal is sent to the offending tasks from the function > fbfam_kill_tasks(), this one will be called again during the core dump > due to the shared statistical data shows a quickly crashing rate. So, to > avoid kill again the same tasks due to a recursive call of this > function, it is necessary to disable the attack detection. > > To disable this attack detection, add a condition in the function > fbfam_handle_attack() to not compute the crashing rate when the jiffies > stored in the statistical data are set to zero. [...] > /** > - * fbfam_handle_attack() - Fork brute force attack detection. > + * fbfam_kill_tasks() - Kill the offending tasks > + * > + * When a fork brute force attack is detected it is necessary to kill all the > + * offending tasks. Since this function is called from fbfam_handle_attack(), > + * and so, every time a core dump is triggered, only is needed to kill the > + * others tasks that share the same statistical data, not the current one as > + * this is in the path to be killed. > + * > + * When the SIGKILL signal is sent to the offending tasks, this function will be > + * called again during the core dump due to the shared statistical data shows a > + * quickly crashing rate. So, to avoid kill again the same tasks due to a > + * recursive call of this function, it is necessary to disable the attack > + * detection setting the jiffies to zero. > + * > + * To improve the for_each_process loop it is possible to end it when all the > + * tasks that shared the same statistics are found. This is not a fastpath, there's no need to be clever and optimize things here, please get rid of that optimization. Especially since that fastpath looks racy against concurrent execve(). > + * Return: -EFAULT if the current task doesn't have statistical data. Zero > + * otherwise. > + */ > +static int fbfam_kill_tasks(void) > +{ > + struct fbfam_stats *stats = current->fbfam_stats; > + struct task_struct *p; > + unsigned int to_kill, killed = 0; > + > + if (!stats) > + return -EFAULT; > + > + to_kill = refcount_read(&stats->refc) - 1; > + if (!to_kill) > + return 0; > + > + /* Disable the attack detection */ > + stats->jiffies = 0; > + rcu_read_lock(); > + > + for_each_process(p) { > + if (p == current || p->fbfam_stats != stats) p->fbfam_stats could change concurrently, you should at least use READ_ONCE() here. Also, if this codepath is hit by a non-leader thread, "p == current" will always be false, and you'll end up killing the caller, too. You may want to compare with current->group_leader instead. > + continue; > + > + do_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_PID); > + pr_warn("fbfam: Offending process with PID %d killed\n", > + p->pid); Normally pr_*() messages about tasks mention not just the pid, but also the ->comm name of the task. > + killed += 1; > + if (killed >= to_kill) > + break; > + } > + > + rcu_read_unlock(); > + return 0; > +}
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.