* [patch 0/3] audit: Fixes and tasklist_lock -> RCU conversion
@ 2009-12-09 14:19 Thomas Gleixner
2009-12-09 14:19 ` [patch 1/3] audit: Call tty_audit_push_task() outside preempt disabled Thomas Gleixner
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Thomas Gleixner @ 2009-12-09 14:19 UTC (permalink / raw)
To: LKML; +Cc: Al Viro, Eric Paris, Ingo Molnar, Peter Zijlstra
Hi,
the following patches result from auditing read_lock(&tasklist_lock)
sites whether they can be converted to RCU.
Thanks,
tglx
^ permalink raw reply [flat|nested] 8+ messages in thread
* [patch 1/3] audit: Call tty_audit_push_task() outside preempt disabled
2009-12-09 14:19 [patch 0/3] audit: Fixes and tasklist_lock -> RCU conversion Thomas Gleixner
@ 2009-12-09 14:19 ` Thomas Gleixner
2009-12-09 14:19 ` [patch 2/3] audit: Do not send uninitialized data for AUDIT_TTY_GET Thomas Gleixner
2009-12-09 14:19 ` [patch 3/3] audit: Use rcu for task lookup protection Thomas Gleixner
2 siblings, 0 replies; 8+ messages in thread
From: Thomas Gleixner @ 2009-12-09 14:19 UTC (permalink / raw)
To: LKML; +Cc: Al Viro, Eric Paris, Ingo Molnar, Peter Zijlstra, Oleg Nesterov
[-- Attachment #1: audit-call-tty_audit_push_task-outside-preempt-disabled-region.patch region --]
[-- Type: text/plain, Size: 4519 bytes --]
While auditing all tasklist_lock read_lock sites I stumbled over the
following call chain:
audit_prepare_user_tty()
read_lock(&tasklist_lock);
tty_audit_push_task();
mutex_lock(&buf->mutex);
--> buf->mutex is locked with preemption disabled.
Solve this by acquiring a reference to the task struct under
rcu_read_lock and call tty_audit_push_task outside of the preempt
disabled region.
Move all code which needs to be protected by sighand lock into
tty_audit_push_task() and use lock/unlock_sighand as we do not hold
tasklist_lock.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Eric Paris <eparis@redhat.com>
Cc: Oleg Nesterov <oleg@redhat.com>
---
drivers/char/tty_audit.c | 38 ++++++++++++++++++++++++++++----------
include/linux/tty.h | 8 ++++----
kernel/audit.c | 25 +++++++++----------------
3 files changed, 41 insertions(+), 30 deletions(-)
Index: linux-2.6-tip/drivers/char/tty_audit.c
===================================================================
--- linux-2.6-tip.orig/drivers/char/tty_audit.c
+++ linux-2.6-tip/drivers/char/tty_audit.c
@@ -188,25 +188,43 @@ void tty_audit_tiocsti(struct tty_struct
}
/**
- * tty_audit_push_task - Flush task's pending audit data
+ * tty_audit_push_task - Flush task's pending audit data
+ * @tsk: task pointer
+ * @loginuid: sender login uid
+ * @sessionid: sender session id
+ *
+ * Called with a ref on @tsk held. Try to lock sighand and get a
+ * reference to the tty audit buffer if available.
+ * Flush the buffer or return an appropriate error code.
*/
-void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
+int tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
{
- struct tty_audit_buf *buf;
+ struct tty_audit_buf *buf = ERR_PTR(-EPERM);
+ unsigned long flags;
- spin_lock_irq(&tsk->sighand->siglock);
- buf = tsk->signal->tty_audit_buf;
- if (buf)
- atomic_inc(&buf->count);
- spin_unlock_irq(&tsk->sighand->siglock);
- if (!buf)
- return;
+ if (!lock_task_sighand(tsk, &flags))
+ return -ESRCH;
+
+ if (tsk->signal->audit_tty) {
+ buf = tsk->signal->tty_audit_buf;
+ if (buf)
+ atomic_inc(&buf->count);
+ }
+ unlock_task_sighand(tsk, &flags);
+
+ /*
+ * Return 0 when signal->audit_tty set
+ * but tsk->signal->tty_audit_buf == NULL.
+ */
+ if (!buf || IS_ERR(buf))
+ return PTR_ERR(buf);
mutex_lock(&buf->mutex);
tty_audit_buf_push(tsk, loginuid, sessionid, buf);
mutex_unlock(&buf->mutex);
tty_audit_buf_put(buf);
+ return 0;
}
/**
Index: linux-2.6-tip/include/linux/tty.h
===================================================================
--- linux-2.6-tip.orig/include/linux/tty.h
+++ linux-2.6-tip/include/linux/tty.h
@@ -494,8 +494,8 @@ extern void tty_audit_exit(void);
extern void tty_audit_fork(struct signal_struct *sig);
extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
extern void tty_audit_push(struct tty_struct *tty);
-extern void tty_audit_push_task(struct task_struct *tsk,
- uid_t loginuid, u32 sessionid);
+extern int tty_audit_push_task(struct task_struct *tsk,
+ uid_t loginuid, u32 sessionid);
#else
static inline void tty_audit_add_data(struct tty_struct *tty,
unsigned char *data, size_t size)
@@ -513,8 +513,8 @@ static inline void tty_audit_fork(struct
static inline void tty_audit_push(struct tty_struct *tty)
{
}
-static inline void tty_audit_push_task(struct task_struct *tsk,
- uid_t loginuid, u32 sessionid)
+static inline int tty_audit_push_task(struct task_struct *tsk,
+ uid_t loginuid, u32 sessionid)
{
}
#endif
Index: linux-2.6-tip/kernel/audit.c
===================================================================
--- linux-2.6-tip.orig/kernel/audit.c
+++ linux-2.6-tip/kernel/audit.c
@@ -467,23 +467,16 @@ static int audit_prepare_user_tty(pid_t
struct task_struct *tsk;
int err;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
tsk = find_task_by_vpid(pid);
- err = -ESRCH;
- if (!tsk)
- goto out;
- err = 0;
-
- spin_lock_irq(&tsk->sighand->siglock);
- if (!tsk->signal->audit_tty)
- err = -EPERM;
- spin_unlock_irq(&tsk->sighand->siglock);
- if (err)
- goto out;
-
- tty_audit_push_task(tsk, loginuid, sessionid);
-out:
- read_unlock(&tasklist_lock);
+ if (!tsk) {
+ rcu_read_unlock();
+ return -ESRCH;
+ }
+ get_task_struct(tsk);
+ rcu_read_unlock();
+ err = tty_audit_push_task(tsk, loginuid, sessionid);
+ put_task_struct(tsk);
return err;
}
^ permalink raw reply [flat|nested] 8+ messages in thread
* [patch 2/3] audit: Do not send uninitialized data for AUDIT_TTY_GET
2009-12-09 14:19 [patch 0/3] audit: Fixes and tasklist_lock -> RCU conversion Thomas Gleixner
2009-12-09 14:19 ` [patch 1/3] audit: Call tty_audit_push_task() outside preempt disabled Thomas Gleixner
@ 2009-12-09 14:19 ` Thomas Gleixner
2009-12-09 14:19 ` [patch 3/3] audit: Use rcu for task lookup protection Thomas Gleixner
2 siblings, 0 replies; 8+ messages in thread
From: Thomas Gleixner @ 2009-12-09 14:19 UTC (permalink / raw)
To: LKML; +Cc: Al Viro, Eric Paris, Ingo Molnar, Peter Zijlstra
[-- Attachment #1: audit-do-not-send-reply-when-esrch.patch --]
[-- Type: text/plain, Size: 894 bytes --]
audit_receive_msg() sends uninitialized data for AUDIT_TTY_GET when
the task was not found.
Send reply only when task was found.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Eric Paris <eparis@redhat.com>
---
kernel/audit.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
Index: linux-2.6-tip/kernel/audit.c
===================================================================
--- linux-2.6-tip.orig/kernel/audit.c
+++ linux-2.6-tip/kernel/audit.c
@@ -884,8 +884,10 @@ static int audit_receive_msg(struct sk_b
spin_unlock_irq(&tsk->sighand->siglock);
}
read_unlock(&tasklist_lock);
- audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0,
- &s, sizeof(s));
+
+ if (!err)
+ audit_send_reply(NETLINK_CB(skb).pid, seq,
+ AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
break;
}
case AUDIT_TTY_SET: {
^ permalink raw reply [flat|nested] 8+ messages in thread
* [patch 3/3] audit: Use rcu for task lookup protection
2009-12-09 14:19 [patch 0/3] audit: Fixes and tasklist_lock -> RCU conversion Thomas Gleixner
2009-12-09 14:19 ` [patch 1/3] audit: Call tty_audit_push_task() outside preempt disabled Thomas Gleixner
2009-12-09 14:19 ` [patch 2/3] audit: Do not send uninitialized data for AUDIT_TTY_GET Thomas Gleixner
@ 2009-12-09 14:19 ` Thomas Gleixner
2 siblings, 0 replies; 8+ messages in thread
From: Thomas Gleixner @ 2009-12-09 14:19 UTC (permalink / raw)
To: LKML; +Cc: Al Viro, Eric Paris, Ingo Molnar, Peter Zijlstra, Oleg Nesterov
[-- Attachment #1: audit-use-rcu-for-lookup.patch --]
[-- Type: text/plain, Size: 2049 bytes --]
Protect the task lookups in audit_receive_msg() with rcu_read_lock()
instead of tasklist_lock and use lock/unlock_sighand to protect
against the exit race.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Eric Paris <eparis@redhat.com>
Cc: Oleg Nesterov <oleg@redhat.com>
---
kernel/audit.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
Index: linux-2.6-tip/kernel/audit.c
===================================================================
--- linux-2.6-tip.orig/kernel/audit.c
+++ linux-2.6-tip/kernel/audit.c
@@ -873,17 +873,16 @@ static int audit_receive_msg(struct sk_b
case AUDIT_TTY_GET: {
struct audit_tty_status s;
struct task_struct *tsk;
+ unsigned long flags;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
tsk = find_task_by_vpid(pid);
- if (!tsk)
- err = -ESRCH;
- else {
- spin_lock_irq(&tsk->sighand->siglock);
+ if (tsk && lock_task_sighand(tsk, &flags)) {
s.enabled = tsk->signal->audit_tty != 0;
- spin_unlock_irq(&tsk->sighand->siglock);
- }
- read_unlock(&tasklist_lock);
+ unlock_task_sighand(tsk, &flags);
+ } else
+ err = -ESRCH;
+ rcu_read_unlock();
if (!err)
audit_send_reply(NETLINK_CB(skb).pid, seq,
@@ -893,22 +892,21 @@ static int audit_receive_msg(struct sk_b
case AUDIT_TTY_SET: {
struct audit_tty_status *s;
struct task_struct *tsk;
+ unsigned long flags;
if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
return -EINVAL;
s = data;
if (s->enabled != 0 && s->enabled != 1)
return -EINVAL;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
tsk = find_task_by_vpid(pid);
- if (!tsk)
- err = -ESRCH;
- else {
- spin_lock_irq(&tsk->sighand->siglock);
+ if (tsk && lock_task_sighand(tsk, &flags)) {
tsk->signal->audit_tty = s->enabled != 0;
- spin_unlock_irq(&tsk->sighand->siglock);
- }
- read_unlock(&tasklist_lock);
+ unlock_task_sighand(tsk, &flags);
+ } else
+ err = -ESRCH;
+ rcu_read_unlock();
break;
}
default:
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 3/3] audit: Use rcu for task lookup protection
2010-09-07 20:25 ` Thomas Gleixner
@ 2010-09-08 12:44 ` Oleg Nesterov
0 siblings, 0 replies; 8+ messages in thread
From: Oleg Nesterov @ 2010-09-08 12:44 UTC (permalink / raw)
To: Thomas Gleixner; +Cc: LKML, Al Viro, Peter Zijlstra, Andrew Morton, Eric Paris
On 09/07, Thomas Gleixner wrote:
>
> On Tue, 7 Sep 2010, Oleg Nesterov wrote:
>
> > But, sorry, can't resists ;) off-topic nit.
> >
> > > @@ -873,17 +873,16 @@ static int audit_receive_msg(struct sk_b
> > > case AUDIT_TTY_GET: {
> > > struct audit_tty_status s;
> > > struct task_struct *tsk;
> > > + unsigned long flags;
> > >
> > > - read_lock(&tasklist_lock);
> > > + rcu_read_lock();
> > > tsk = find_task_by_vpid(pid);
> > > - if (!tsk)
> > > - err = -ESRCH;
> > > - else {
> > > - spin_lock_irq(&tsk->sighand->siglock);
> > > + if (tsk && lock_task_sighand(tsk, &flags)) {
> > > s.enabled = tsk->signal->audit_tty != 0;
> >
> > Yes, this is what original code does, it takes ->siglock every time
> > around read/write of ->audit_tty. And this looks absolutely bogus.
> > Say, tty_audit_fork(). Why does it take ->siglock ?
Yes, I still think ->audit_tty doesn't need the locking.
> > As for ->tty_audit_buf, I am not sure ->siglock is the best choice,
> > perhaps task_lock() would be better.
OOPS, I misread the code. ->tty_audit_buf is per-process (of course!).
Well, unless I missed something again, tty_audit_push() and
tty_audit_tiocsti() can access ->tty_audit_buf lockless.
> > Once again, I think the patch is fine. Just it seems to me this code
> > needs more cleanups.
>
> Yeah, thought about that, but that's not in the scope of what I was
> working on. I leave that to the audit folks. :)
Yes, yes, sure.
Oleg.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 3/3] audit: Use rcu for task lookup protection
2010-09-07 18:25 ` Oleg Nesterov
@ 2010-09-07 20:25 ` Thomas Gleixner
2010-09-08 12:44 ` Oleg Nesterov
0 siblings, 1 reply; 8+ messages in thread
From: Thomas Gleixner @ 2010-09-07 20:25 UTC (permalink / raw)
To: Oleg Nesterov; +Cc: LKML, Al Viro, Peter Zijlstra, Andrew Morton, Eric Paris
On Tue, 7 Sep 2010, Oleg Nesterov wrote:
> On 09/07, Thomas Gleixner wrote:
> >
> > Protect the task lookups in audit_receive_msg() with rcu_read_lock()
> > instead of tasklist_lock and use lock/unlock_sighand to protect
> > against the exit race.
>
> I do not understand audit, but I belive both 1/3 and 3/3 patches are
> fine (I didn't get 2/3).
>
>
>
> But, sorry, can't resists ;) off-topic nit.
>
> > @@ -873,17 +873,16 @@ static int audit_receive_msg(struct sk_b
> > case AUDIT_TTY_GET: {
> > struct audit_tty_status s;
> > struct task_struct *tsk;
> > + unsigned long flags;
> >
> > - read_lock(&tasklist_lock);
> > + rcu_read_lock();
> > tsk = find_task_by_vpid(pid);
> > - if (!tsk)
> > - err = -ESRCH;
> > - else {
> > - spin_lock_irq(&tsk->sighand->siglock);
> > + if (tsk && lock_task_sighand(tsk, &flags)) {
> > s.enabled = tsk->signal->audit_tty != 0;
>
> Yes, this is what original code does, it takes ->siglock every time
> around read/write of ->audit_tty. And this looks absolutely bogus.
> Say, tty_audit_fork(). Why does it take ->siglock ?
>
> As for ->tty_audit_buf, I am not sure ->siglock is the best choice,
> perhaps task_lock() would be better.
>
> Once again, I think the patch is fine. Just it seems to me this code
> needs more cleanups.
Yeah, thought about that, but that's not in the scope of what I was
working on. I leave that to the audit folks. :)
Thanks,
tglx
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 3/3] audit: Use rcu for task lookup protection
2010-09-07 14:00 ` [patch 3/3] audit: Use rcu for task lookup protection Thomas Gleixner
@ 2010-09-07 18:25 ` Oleg Nesterov
2010-09-07 20:25 ` Thomas Gleixner
0 siblings, 1 reply; 8+ messages in thread
From: Oleg Nesterov @ 2010-09-07 18:25 UTC (permalink / raw)
To: Thomas Gleixner; +Cc: LKML, Al Viro, Peter Zijlstra, Andrew Morton, Eric Paris
On 09/07, Thomas Gleixner wrote:
>
> Protect the task lookups in audit_receive_msg() with rcu_read_lock()
> instead of tasklist_lock and use lock/unlock_sighand to protect
> against the exit race.
I do not understand audit, but I belive both 1/3 and 3/3 patches are
fine (I didn't get 2/3).
But, sorry, can't resists ;) off-topic nit.
> @@ -873,17 +873,16 @@ static int audit_receive_msg(struct sk_b
> case AUDIT_TTY_GET: {
> struct audit_tty_status s;
> struct task_struct *tsk;
> + unsigned long flags;
>
> - read_lock(&tasklist_lock);
> + rcu_read_lock();
> tsk = find_task_by_vpid(pid);
> - if (!tsk)
> - err = -ESRCH;
> - else {
> - spin_lock_irq(&tsk->sighand->siglock);
> + if (tsk && lock_task_sighand(tsk, &flags)) {
> s.enabled = tsk->signal->audit_tty != 0;
Yes, this is what original code does, it takes ->siglock every time
around read/write of ->audit_tty. And this looks absolutely bogus.
Say, tty_audit_fork(). Why does it take ->siglock ?
As for ->tty_audit_buf, I am not sure ->siglock is the best choice,
perhaps task_lock() would be better.
Once again, I think the patch is fine. Just it seems to me this code
needs more cleanups.
Oleg.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [patch 3/3] audit: Use rcu for task lookup protection
2010-09-07 13:59 [patch 0/3] audit: Fixes and tasklist_lock -> RCU conversion - Resend Thomas Gleixner
@ 2010-09-07 14:00 ` Thomas Gleixner
2010-09-07 18:25 ` Oleg Nesterov
0 siblings, 1 reply; 8+ messages in thread
From: Thomas Gleixner @ 2010-09-07 14:00 UTC (permalink / raw)
To: LKML; +Cc: Al Viro, Peter Zijlstra, Andrew Morton, Eric Paris, Oleg Nesterov
[-- Attachment #1: audit-use-rcu-for-task-lookup-protection.patch --]
[-- Type: text/plain, Size: 2132 bytes --]
Protect the task lookups in audit_receive_msg() with rcu_read_lock()
instead of tasklist_lock and use lock/unlock_sighand to protect
against the exit race.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Eric Paris <eparis@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Oleg Nesterov <oleg@redhat.com>
---
kernel/audit.c | 30 ++++++++++++++----------------
kernel/audit.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
Index: linux-2.6/kernel/audit.c
===================================================================
--- linux-2.6.orig/kernel/audit.c
+++ linux-2.6/kernel/audit.c
@@ -873,17 +873,16 @@ static int audit_receive_msg(struct sk_b
case AUDIT_TTY_GET: {
struct audit_tty_status s;
struct task_struct *tsk;
+ unsigned long flags;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
tsk = find_task_by_vpid(pid);
- if (!tsk)
- err = -ESRCH;
- else {
- spin_lock_irq(&tsk->sighand->siglock);
+ if (tsk && lock_task_sighand(tsk, &flags)) {
s.enabled = tsk->signal->audit_tty != 0;
- spin_unlock_irq(&tsk->sighand->siglock);
- }
- read_unlock(&tasklist_lock);
+ unlock_task_sighand(tsk, &flags);
+ } else
+ err = -ESRCH;
+ rcu_read_unlock();
if (!err)
audit_send_reply(NETLINK_CB(skb).pid, seq,
@@ -893,22 +892,21 @@ static int audit_receive_msg(struct sk_b
case AUDIT_TTY_SET: {
struct audit_tty_status *s;
struct task_struct *tsk;
+ unsigned long flags;
if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
return -EINVAL;
s = data;
if (s->enabled != 0 && s->enabled != 1)
return -EINVAL;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
tsk = find_task_by_vpid(pid);
- if (!tsk)
- err = -ESRCH;
- else {
- spin_lock_irq(&tsk->sighand->siglock);
+ if (tsk && lock_task_sighand(tsk, &flags)) {
tsk->signal->audit_tty = s->enabled != 0;
- spin_unlock_irq(&tsk->sighand->siglock);
- }
- read_unlock(&tasklist_lock);
+ unlock_task_sighand(tsk, &flags);
+ } else
+ err = -ESRCH;
+ rcu_read_unlock();
break;
}
default:
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-09-08 12:47 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-09 14:19 [patch 0/3] audit: Fixes and tasklist_lock -> RCU conversion Thomas Gleixner
2009-12-09 14:19 ` [patch 1/3] audit: Call tty_audit_push_task() outside preempt disabled Thomas Gleixner
2009-12-09 14:19 ` [patch 2/3] audit: Do not send uninitialized data for AUDIT_TTY_GET Thomas Gleixner
2009-12-09 14:19 ` [patch 3/3] audit: Use rcu for task lookup protection Thomas Gleixner
2010-09-07 13:59 [patch 0/3] audit: Fixes and tasklist_lock -> RCU conversion - Resend Thomas Gleixner
2010-09-07 14:00 ` [patch 3/3] audit: Use rcu for task lookup protection Thomas Gleixner
2010-09-07 18:25 ` Oleg Nesterov
2010-09-07 20:25 ` Thomas Gleixner
2010-09-08 12:44 ` Oleg Nesterov
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.