All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: Romain Perier <romain.perier@gmail.com>
Cc: Kernel Hardening <kernel-hardening@lists.openwall.com>,
	Shyam Saini <mayhs11saini@gmail.com>
Subject: Re: refactor tasklets to avoid unsigned long argument
Date: Wed, 3 Jul 2019 15:46:00 -0700	[thread overview]
Message-ID: <201907031513.8E342FF@keescook> (raw)
In-Reply-To: <CABgxDoJ6ra4DoPzEk8w25e0iTSHtNuYanHT-s+30JSzjfWestQ@mail.gmail.com>

On Wed, Jul 03, 2019 at 05:48:42PM +0200, Romain Perier wrote:
> Mhhh, so If I understand it right, the purpose of this task is to
> remove the "unsigned long data"  argument passed to tasklet_init() ,
> that
> is mostly used to pass the pointer of the parent structure that
> contains the tasklet_struct to the handler.

Right. The idea being that when a tasklet is stored in memory, it no
longer contains both the callback function pointer AND the argument to
pass it. This is the same problem that existed for struct timer_list.
You can see more details about this in at the start of the timer_list
refactoring:
https://git.kernel.org/linus/686fef928bba6be13cabe639f154af7d72b63120

> We don't change the API of tasklet, we simply remove the code that use
> this "unsigned long data" wrongly to pass the pointer of the parent
> structure
> (by using container_of() or something equivalent).

Kind of. In the timer_list case, there were some places were actual data
(and not a pointer) was being passed -- those needed some thought to
convert sanely. I'm hoping that the tasklets are a much smaller part of
the kernel and won't pose as much of a problem, but I haven't studied
it.

> For example this is the case in:   drivers/firewire/ohci.c   or
> drivers/s390/block/dasd.c  .

Right:

struct ar_context {
	...
        struct tasklet_struct tasklet;
};

static void ar_context_tasklet(unsigned long data)
{
        struct ar_context *ctx = (struct ar_context *)data;
...

static int ar_context_init(...)
{
	...
        tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx);


this could instead be:

static void ar_context_tasklet(struct tasklet_struct *tasklet)
{
	struct ar_context *ctx = container_of(tasklet, typeof(*ctx), tasklet);
...

static int ar_context_init(...)
{
	...
        tasklet_setup(&ctx->tasklet, ar_context_tasklet);

> Several question come:
> 
> 1. I am not sure but, do we need to modify the prototype of
> tasklet_init() ?  well, this "unsigned long data" might be use for
> something else that pass the pointer of the parent struct. So I would
> say "no"

Yes, the final step in the refactoring would be to modify the tasklet_init()
prototype. I've included some example commits from the timer_list
refactoring, but look at the history of include/linux/timer.h and
kernel/time/timer.c for more details.

I would expect the refactoring to follow similar changes to timer_list:

- add a new init API (perhaps tasklet_setup() to follow timer_setup()?)
  that passes the tasklet pointer to tasklet_init(), and casts the
  callback.
	https://git.kernel.org/linus/686fef928bba6be13cabe639f154af7d72b63120
- convert all users to the new prototype
	https://git.kernel.org/linus/e99e88a9d2b067465adaa9c111ada99a041bef9a
- remove the "data" member and convert the callback infrastructure to
  pass the tasklet pointer
	https://git.kernel.org/linus/c1eba5bcb6430868427e0b9d1cd1205a07302f06
- and then clean up anything (cast macros, etc)
	https://git.kernel.org/linus/354b46b1a0adda1dd5b7f0bc2a5604cca091be5f

Hopefully tasklet doesn't have a lot of open-coded initialization. This
is what made timer_list such a challenge. Stuff like this:
	https://git.kernel.org/linus/b9eaf18722221ef8b2bd6a67240ebe668622152a

> 2. In term of security, this is a problem ? Or this is just an
> improvement to force developpers to do things correctly ?

It's a reduction in attack surface (attacker has less control
over the argument if the function pointer is overwritten) and it
provides a distinct prototype for CFI, to make is separate from other
functions that take a single unsigned long argument (e.g. before the
timer_list refactoring, all timer callbacks had the same prototype as
native_write_cr4(), making them a powerful target to control on x86).

For examples of the timer_list attacks (which would likely match a
tasklet attack if one got targeted), see "retire_blk_timer" in:
https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html

There's also some more detail on the timer_list work in my blog post
for v4.15:
https://outflux.net/blog/archives/2018/02/05/security-things-in-linux-v4-15/

> I will update the WIKI

Awesome!

Thanks for looking at this! I hope it's not at bad as timer_list. :)

-- 
Kees Cook

  reply	other threads:[~2019-07-03 22:46 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-02  7:35 refactor tasklets to avoid unsigned long argument Romain Perier
2019-07-02 15:51 ` Kees Cook
2019-07-03 15:48   ` Romain Perier
2019-07-03 22:46     ` Kees Cook [this message]
2019-07-21 17:55       ` Romain Perier
2019-07-22 17:19         ` Kees Cook
2019-07-23  8:15           ` Romain Perier
2019-08-08 15:47             ` Romain Perier
2019-08-08 21:02               ` Kees Cook
2019-08-12 17:29                 ` Romain Perier
2019-08-29 18:13                   ` Romain Perier
2019-08-29 18:35                     ` Kees Cook
2019-09-29 16:37                     ` Romain Perier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201907031513.8E342FF@keescook \
    --to=keescook@chromium.org \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=mayhs11saini@gmail.com \
    --cc=romain.perier@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.