The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
To: Oleg Nesterov <oleg@tv-sign.ru>
Cc: linux-kernel <linux-kernel@vger.kernel.org>,
	Prarit Bhargava <prarit@redhat.com>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>
Subject: Re: [RFC][PATCH] ->signal->tty locking
Date: Tue, 17 Oct 2006 12:17:01 +0200	[thread overview]
Message-ID: <1161080221.3036.38.camel@taijtu> (raw)
In-Reply-To: <20061017081018.GA115@oleg>

On Tue, 2006-10-17 at 12:10 +0400, Oleg Nesterov wrote:
> On 10/16, Peter Zijlstra wrote:
> >
> > Oleg wrote:
> > "Historically ->signal/->sighand (both ptrs and their contents) were globally
> > protected by tasklist_lock. 'current' can use these pointers lockless, they
> > can't be changed under him.
> > 
> > Nowadays ->signal/->sighand are _also_ protected by ->sighand->siglock.
> > Unless you are current, you can't lock ->siglock directly (without holding
> > tasklist_lock), you should use lock_task_sighand()."
> > 
> > Then, to be consistent with the rest of the kernel, ->signal->tty
> > locking should look like so:
> > 
> >   mutex_lock(&tty_mutex)
> >     read_lock(&tasklist_lock)
> >       lock_task_sighand(p, &flags)
> 
> I've also started similar patches, but have no time to finish it.
> 
> I don't think we need tasklist_lock. I think ->sighand->siglock is enough.

Right, sys_unshare() makes tasklist_lock meaningless wrt ->siglock.

> So do_task_stat() doesn't need to take tty_mutex at all.
> 
> However, tty_mutex protects ->tty from release_dev(tty), so it is also
> possible to do:
> 
> 	mutex_lock(&tty_mutex);
> 	tty = task->signal->tty;
> 	barrier();
> 	if (tty) {
> 		// ->tty could be changed/cleared from under us,
> 		// but it can't be released while we are holding
> 		// tty_mutex
> 		do_something(tty);
> 	}
> 	...

Nice, I think we have to convert all those callers like sys_vhangup() to
this form.


> > @@ -1350,20 +1357,26 @@ static void do_tty_hangup(void *data)
> >  	  This should get done automatically when the port closes and
> >  	  tty_release is called */
> >  	
> > +	mutex_lock(&tty_mutex);
> 
> I am not sure it is needed.

Right, this would only be needed when using the tty, not when changing
signal->tty.

> >  	read_lock(&tasklist_lock);
> >  	if (tty->session > 0) {
> >  		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
> > +			lock_task_sighand(p, &flags);
> >  			if (p->signal->tty == tty)
> >  				p->signal->tty = NULL;
> > +			unlock_task_sighand(p, &flags);
> 
> We don't need lock_task_sighand() here, we can use spin_lock_irq(->siglock).
> 
> We are holding tasklist_lock. This means that all tasks found by
> do_each_task_pid() have a valid ->signal/->sighand != NULL.
> tasklist_lock protects against release_task()->__exit_signal() and
> from changing ->sighand by de_thread().

I think sys_unshare() spoils the game here; it changes ->sighand in
midair without holding tasklist_lock. So any ->sighand but current's is
fair game.

Hmm, either sys_unshare() is broken in that it doesn't take the
tasklist_lock or a lot of other code is broken.

let us take send_sig_info() vs. sys_unshare()

      1                                        2

read_lock(&tasklist_lock)
spin_lock_irqsave(&p->sighand->siglock, flags);

                         rcu_assign_pointer(current->sighand, new_sigh)

spin_unlock_irqsave(&p->sighand->siglock, flags);
read_unlock(&tasklist_lock);

what happens when 2's current is 1's p....

> > @@ -2910,20 +2953,23 @@ static int tiocsctty(struct tty_struct *
> >  
> >  			read_lock(&tasklist_lock);
> >  			do_each_task_pid(tty->session, PIDTYPE_SID, p) {
> > +				lock_task_sighand(p, &flags);
> >  				p->signal->tty = NULL;
> > +				unlock_task_sighand(p, &flags);
> >  			} while_each_task_pid(tty->session, PIDTYPE_SID, p);
> >  			read_unlock(&tasklist_lock);
> > -		} else
> > +		} else {
> > +			mutex_unlock(&tty_mutex);
> >  			return -EPERM;
> > +		}
> >  	}
> > -	mutex_lock(&tty_mutex);
> > -	task_lock(current);
> > -	current->signal->tty = tty;
> > -	task_unlock(current);
> > -	mutex_unlock(&tty_mutex);
> > -	current->signal->tty_old_pgrp = 0;
> >  	tty->session = current->signal->session;
> >  	tty->pgrp = process_group(current);
> > +	lock_task_sighand(current, &flags);
> > +	current->signal->tty = tty;
> > +	current->signal->tty_old_pgrp = 0;
> > +	unlock_task_sighand(current, &flags);
> > +	mutex_unlock(&tty_mutex);
> >  	return 0;
> >  }
> 
> There is a very similar code in tty_open(), probably we need another
> helper, proc_set_tty().
> 
> But I am not sure about locking. I think we should check
> ->signal->leader/->signal->tty and set ->tty in proc_set_tty()
> under ->siglock, this way we can remove tty_mutex from sys_setsid().

Right, use tty_mutex when using the tty, use ->sighand when changing
signal->tty.


  reply	other threads:[~2006-10-17 12:18 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-10-16  9:53 [RFC][PATCH] ->signal->tty locking Peter Zijlstra
2006-10-16 13:39 ` Prarit Bhargava
2006-10-17  8:10 ` Oleg Nesterov
2006-10-17 10:17   ` Peter Zijlstra [this message]
2006-10-17 12:33     ` Oleg Nesterov
2006-10-17 13:00       ` Peter Zijlstra
2006-10-17 14:08         ` Alan Cox
2006-10-18 16:55         ` Oleg Nesterov
2006-10-17 13:29       ` Alan Cox
2006-10-18 17:21         ` Oleg Nesterov

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=1161080221.3036.38.camel@taijtu \
    --to=a.p.zijlstra@chello.nl \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleg@tv-sign.ru \
    --cc=prarit@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox