Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1713410 > unrolled thread
| Started by | Kees Cook <keescook@google.com> |
|---|---|
| First post | 2017-08-17 01:30 +0200 |
| Last post | 2017-08-17 17:10 +0200 |
| Articles | 5 — 3 participants |
Back to article view | Back to linux.kernel
refactoring timers to avoid init_timer*() Kees Cook <keescook@google.com> - 2017-08-17 01:30 +0200
Re: refactoring timers to avoid init_timer*() Kees Cook <keescook@google.com> - 2017-08-17 16:40 +0200
Re: refactoring timers to avoid init_timer*() Thomas Gleixner <tglx@linutronix.de> - 2017-08-17 16:40 +0200
Re: refactoring timers to avoid init_timer*() Christoph Hellwig <hch@infradead.org> - 2017-08-17 16:50 +0200
Re: refactoring timers to avoid init_timer*() Kees Cook <keescook@google.com> - 2017-08-17 17:10 +0200
| From | Kees Cook <keescook@google.com> |
|---|---|
| Date | 2017-08-17 01:30 +0200 |
| Subject | refactoring timers to avoid init_timer*() |
| Message-ID | <uffV7-52i-1@gated-at.bofh.it> |
Hi, So, my earlier patch[1] to add canaries to the timer struct did not handle many many cases, as I've uncovered. To have a sensible canary, it needs to be written at function-assignment time, but right now things are extremely ad-hoc in the timer API, making it non-trivial to figure out if the code changed the function or if some attacker is exploiting a flaw to overwrite the timer struct function pointer. What I'd like to do is to eliminate all the uses of init_timer*() in favor of setup_timer*() which already includes the function as part of the initialization (which is where a canary could be generated). There are a couple cases where a timer user switches the function out intentionally after setup, but that is the very rare case. Those could use a new helper that would set the function (and canary) after an earlier setup_timer() call (or maybe just re-call setup_timer()?). In the process I noticed that we already have scripts/coccinelle/api/setup_timer.cocci to detect existing cases of: init_timer(t); t->function = func; t->data = data; And replace it with: setup_timer(t, func, data); Another pattern was: t->expires = when; add_timer(t); Which can be replaced with mod_timer(t, when); So, I've created scripts/coccinelle/api/mod_timer.cocci for the latter, and done a few passes with manual review. The current result doesn't fully eliminate init_timer() yet, but it gets much closer. I just wanted to be sure that this whole clean-up would actually be welcome before I try to nail down the last many cases. You can see it here: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/log/?h=kspp/timer/refactor-exploded 135 commits (split by maintainer): 243 files changed, 583 insertions(+), 1055 deletions(-) -Kees [1] http://www.openwall.com/lists/kernel-hardening/2017/08/08/2 -- Kees Cook Pixel Security
[toc] | [next] | [standalone]
| From | Kees Cook <keescook@google.com> |
|---|---|
| Date | 2017-08-17 16:40 +0200 |
| Message-ID | <ufu7M-67i-25@gated-at.bofh.it> |
| In reply to | #1713410 |
On Thu, Aug 17, 2017 at 7:30 AM, Thomas Gleixner <tglx@linutronix.de> wrote: > On Wed, 16 Aug 2017, Kees Cook wrote: >> In the process I noticed that we already have >> scripts/coccinelle/api/setup_timer.cocci to detect existing cases of: >> >> init_timer(t); >> t->function = func; >> t->data = data; >> >> And replace it with: setup_timer(t, func, data); >> >> Another pattern was: >> >> t->expires = when; >> add_timer(t); >> >> Which can be replaced with mod_timer(t, when); >> >> So, I've created scripts/coccinelle/api/mod_timer.cocci for the >> latter, and done a few passes with manual review. The current result >> doesn't fully eliminate init_timer() yet, but it gets much closer. I >> just wanted to be sure that this whole clean-up would actually be >> welcome before I try to nail down the last many cases. > > I think it's worth the trouble, but rather than having a gazillion of > commits with the same changelog, we should do that based on a cocci script > right before the next rc1 in one go and be done with it. > > That will cover most of the init_timer() cases and we can fixup the > remaining few oddballs manually after that. Okay, that sounds good. I'll work on improving the cocci scripts. For example, I noticed that it doesn't notice having assignments _before_ the init_timer() call: timer->function = func; timer->data = data; init_timer(timer); Whee. :) BTW, I may back off on doing ->expires = when; add_timer(timer) --> mod_timer(timer, when) changes since that actually removes a sanity check in add_timer(). My plans currently are collapsing all the open-coded init_timer*()s into setup_*timer() and then adding something like aim_timer(timer, func, data) for post-setup function/data changes. -Kees > > I just noticed that we have the same pattern with hrtimer_init(). I had a > stab on adding hrtimer_setup() and friends which takes a function argument > and converted the bulk with coccinelle. > > 82 files changed, 186 insertions(+), 210 deletions(-) > > We can do that in the same sweep as the init_timer() one and then you can > do the canary magic on hrtimers as well. > > Thanks, > > tglx > > -- Kees Cook Pixel Security
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-17 16:40 +0200 |
| Message-ID | <ufu7M-67i-27@gated-at.bofh.it> |
| In reply to | #1713410 |
On Wed, 16 Aug 2017, Kees Cook wrote:
> In the process I noticed that we already have
> scripts/coccinelle/api/setup_timer.cocci to detect existing cases of:
>
> init_timer(t);
> t->function = func;
> t->data = data;
>
> And replace it with: setup_timer(t, func, data);
>
> Another pattern was:
>
> t->expires = when;
> add_timer(t);
>
> Which can be replaced with mod_timer(t, when);
>
> So, I've created scripts/coccinelle/api/mod_timer.cocci for the
> latter, and done a few passes with manual review. The current result
> doesn't fully eliminate init_timer() yet, but it gets much closer. I
> just wanted to be sure that this whole clean-up would actually be
> welcome before I try to nail down the last many cases.
I think it's worth the trouble, but rather than having a gazillion of
commits with the same changelog, we should do that based on a cocci script
right before the next rc1 in one go and be done with it.
That will cover most of the init_timer() cases and we can fixup the
remaining few oddballs manually after that.
I just noticed that we have the same pattern with hrtimer_init(). I had a
stab on adding hrtimer_setup() and friends which takes a function argument
and converted the bulk with coccinelle.
82 files changed, 186 insertions(+), 210 deletions(-)
We can do that in the same sweep as the init_timer() one and then you can
do the canary magic on hrtimers as well.
Thanks,
tglx
[toc] | [prev] | [next] | [standalone]
| From | Christoph Hellwig <hch@infradead.org> |
|---|---|
| Date | 2017-08-17 16:50 +0200 |
| Message-ID | <ufuhs-6aR-13@gated-at.bofh.it> |
| In reply to | #1713410 |
Instea of bloating the timer even more we should kill off the data field eventually, which should give you the same protection. See my proposal and the related discussion here: http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1397209.html
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@google.com> |
|---|---|
| Date | 2017-08-17 17:10 +0200 |
| Message-ID | <ufuAO-6yO-13@gated-at.bofh.it> |
| In reply to | #1714103 |
On Thu, Aug 17, 2017 at 7:40 AM, Christoph Hellwig <hch@infradead.org> wrote: > Instea of bloating the timer even more we should kill off > the data field eventually, which should give you the same > protection. > > See my proposal and the related discussion here: > > http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1397209.html Ah! Yes, very cool. Most callbacks could be converted to the new timer callback pretty easily. Some, though, pass non-pointer data in the "data" argument. Those can likely be moved to somewhere else, though. I think it should be possible to just perform all the conversions. Regardless, getting rid of init_timer*() and eliminating the open-coded callback assignments should help. I'll keep grinding on that. -Kees -- Kees Cook Pixel Security
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web