All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleg Nesterov <oleg@redhat.com>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Hugh Dickins <hugh@veritas.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Joe Malicki <jmalicki@metacarta.com>,
	Michael Itz <mitz@metacarta.com>,
	Kenneth Baker <bakerk@metacarta.com>,
	Chris Wright <chrisw@sous-sol.org>,
	David Howells <dhowells@redhat.com>,
	Alexey Dobriyan <adobriyan@gmail.com>,
	Greg Kroah-Hartman <gregkh@suse.de>,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: Q: check_unsafe_exec() races (Was: [PATCH 2/4] fix setuid sometimes doesn't)
Date: Mon, 6 Apr 2009 17:51:03 +0200	[thread overview]
Message-ID: <20090406155103.GB21220@redhat.com> (raw)
In-Reply-To: <20090401023849.GW28946@ZenIV.linux.org.uk>

On 04/01, Al Viro wrote:
>
> On Wed, Apr 01, 2009 at 01:28:01AM +0100, Hugh Dickins wrote:
>
> > Otherwise it looks good to me, except I keep worrying about those
> > EAGAINs.
>
> Frankly, -EAGAIN in situation when we have userland race is fine.  And
> we *do* have a userland race here - execve() will kill -9 those threads
> in case of success, so if they'd been doing something useful, they are
> about to be suddenly screwed.

Can't resist! I dislike the "in_exec && -EAGAIN" oddity too.

Yes sure, we can't break the "well written" applications. But imho this
looks strange. And a bit "assymetrical" wrt LSM_UNSAFE_SHARE, I mean
check_unsafe_exec() allows sub-threads to race or CLONE_FS but only if
LSM_UNSAFE_SHARE.

Another reason, we can have the "my test-case found something strange"
bug-reports.

So. Please feel free to nack or just ignore this message, but since I
personally dislike the current behaviour I should at least try to suggest
something else.

	- add "wait_queue_head_t in_exec_wait" to "struct linux_binprm".

	- kill fs->in_exec, add "wait_queue_head_t *in_exec_wait_ptr"
	  instead.

	- introduce the new helper,

		void fs_lock_check_exec(struct fs_struct *fs)
		{
			write_lock(&fs->lock);
			while (unlikely(fs->in_exec_wait_ptr)) {
				DECLARE_WAITQUEUE(wait, current);

				if (fatal_signal_pending(current))
					/*
					 * clone/exec can't succeed, and this
					 * thread won't return to the user-space
					 */
					break;

				__add_wait_queue(fs->in_exec_wait_ptr, &wait);
				__set_current_state(TASK_KILLABLE);
				write_unlock(&fs->lock);

				schedule();

				write_lock(&fs->lock);
				__remove_wait_queue(&wait);
			}
		}

	  Or we can return -EANYTHING when fatal_signal_pending(), this doesn't
	  matter.

	  Note that this helper can block only if we race with our sub-thread
	  in the middle of !LSM_UNSAFE_SHARE exec. Otherwise this is not slower
	  than write_lock(fs->lock) + if (fs->in_exec) we currently have.


	 - change copy_fs() to do

		if (clone_flags & CLONE_FS) {
			fs_lock_check_exec(fs);
			fs->users++;
			write_unlock(&fs->lock);
			return 0;
		}


	- change check_unsafe_exec:

		void check_unsafe_exec(struct linux_binprm *bprm)
		{
			struct task_struct *p = current, *t;
			unsigned n_fs;

			bprm->unsafe = tracehook_unsafe_exec(p);

			n_fs = 1;
			fs_lock_check_exec(&p->fs);
			if (p->fs->in_exec_wait_ptr)
				/* we are going to die */
				goto out;

			rcu_read_lock();
			for (t = next_thread(p); t != p; t = next_thread(t)) {
				if (t->fs == p->fs)
					n_fs++;
			}
			rcu_read_unlock();

			if (p->fs->users > n_fs) {
				bprm->unsafe |= LSM_UNSAFE_SHARE;
			} else {
				bprm->unsafe |= __LSM_EXEC_WAKE;
				init_waitqueue_head(&bprm->in_exec_wait);
				p->fs->in_exec_wait_ptr = &bprm->in_exec_wait;
			}
		out:
			write_unlock(&p->fs->lock);
		}



	 - and, finally, change do_execve()

			/* execve succeeded */
			current->fs->in_exec_wait_ptr = NULL;

			...

		out_unmark:
			if (bprm->unsafe & __LSM_EXEC_WAKE) {
				write_lock(&current->fs->lock);
				current->fs->in_exec_wait_ptr = NULL;
				wake_up_locked(&bprm->in_exec_wait);
				write_unlock(&current->fs->lock);
			}

Comments?

Oleg.


  parent reply	other threads:[~2009-04-06 15:56 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-28 23:16 [PATCH 1/4] compat_do_execve should unshare_files Hugh Dickins
2009-03-28 23:20 ` [PATCH 2/4] fix setuid sometimes doesn't Hugh Dickins
2009-03-29  0:53   ` Q: check_unsafe_exec() races (Was: [PATCH 2/4] fix setuid sometimes doesn't) Oleg Nesterov
2009-03-29  4:10     ` Al Viro
2009-03-29  4:14       ` Al Viro
2009-03-29  4:52       ` Oleg Nesterov
2009-03-29  5:55         ` Al Viro
2009-03-29  6:01           ` Al Viro
2009-03-29 21:36             ` Oleg Nesterov
2009-03-29 22:20               ` Al Viro
2009-03-29 23:56                 ` Oleg Nesterov
2009-03-30  0:03                   ` Oleg Nesterov
2009-03-30  1:08                     ` Al Viro
2009-03-30  1:13                       ` Al Viro
2009-03-30  1:36                         ` Oleg Nesterov
2009-03-30  1:40                           ` Oleg Nesterov
2009-03-30 12:31                             ` Al Viro
2009-03-30 14:32                               ` Hugh Dickins
2009-03-31  6:16                                 ` Al Viro
2009-04-01  0:28                                   ` Hugh Dickins
2009-04-01  2:38                                     ` Al Viro
2009-04-01  3:03                                       ` Al Viro
2009-04-01 11:25                                         ` Hugh Dickins
2009-04-06 15:31                                         ` Oleg Nesterov
2009-04-19 16:30                                           ` Hugh Dickins
2009-04-21 16:10                                             ` Oleg Nesterov
2009-04-21 16:31                                               ` Linus Torvalds
2009-04-21 17:15                                                 ` Oleg Nesterov
2009-04-21 17:35                                                   ` Linus Torvalds
2009-04-21 19:39                                                     ` Hugh Dickins
2009-04-23 23:01                                                       ` [PATCH 1/2] do_execve() must not clear fs->in_exec if it was set by another thread Oleg Nesterov
2009-04-23 23:18                                                         ` Roland McGrath
2009-04-23 23:31                                                         ` Al Viro
2009-04-24 11:57                                                           ` [PATCH 3/2] check_unsafe_exec: rcu_read_unlock Hugh Dickins
2009-04-24 14:34                                                             ` Oleg Nesterov
2009-04-24  4:20                                                         ` [PATCH 1/2] do_execve() must not clear fs->in_exec if it was set by another thread Hugh Dickins
2009-04-23 23:02                                                       ` [PATCH 2/2] check_unsafe_exec: s/lock_task_sighand/rcu_read_lock/ Oleg Nesterov
2009-04-23 23:18                                                         ` Roland McGrath
2009-04-24  4:29                                                         ` Hugh Dickins
2009-04-01 11:18                                       ` Q: check_unsafe_exec() races (Was: [PATCH 2/4] fix setuid sometimes doesn't) Hugh Dickins
2009-04-06 15:51                                       ` Oleg Nesterov [this message]
2009-04-19 16:44                                         ` Hugh Dickins
2009-04-21 16:39                                           ` Oleg Nesterov
2009-03-30 23:45                               ` Serge E. Hallyn
2009-03-31  6:19                                 ` Al Viro
2009-03-28 23:21 ` [PATCH 3/4] fix setuid sometimes wouldn't Hugh Dickins
2009-03-29 11:19   ` Alexey Dobriyan
2009-03-29 21:48     ` Oleg Nesterov
2009-03-29 22:37       ` Al Viro
2009-03-28 23:23 ` [PATCH 4/4] Annotate struct fs_struct's usage count restriction Hugh Dickins

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=20090406155103.GB21220@redhat.com \
    --to=oleg@redhat.com \
    --cc=adobriyan@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=bakerk@metacarta.com \
    --cc=chrisw@sous-sol.org \
    --cc=dhowells@redhat.com \
    --cc=gregkh@suse.de \
    --cc=hugh@veritas.com \
    --cc=jmalicki@metacarta.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mitz@metacarta.com \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@ZenIV.linux.org.uk \
    /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.