From: Oleg Nesterov <oleg@redhat.com>
To: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Davidlohr Bueso <dave@stgolabs.net>,
Manfred Spraul <manfred@colorfullife.com>,
Markus Elfring <elfring@users.sourceforge.net>,
Yoji <yoji.fujihar.min@gmail.com>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] ipc/mqueue.c: change __do_notify() to bypass check_kill_permission()
Date: Tue, 24 Mar 2020 11:35:28 +0100 [thread overview]
Message-ID: <20200324103528.GA9061@redhat.com> (raw)
In-Reply-To: <87imivc92n.fsf@x220.int.ebiederm.org>
On 03/23, Eric W. Biederman wrote:
>
> Oleg Nesterov <oleg@redhat.com> writes:
>
> > And this is what we had before cc731525f26a, so this patch tries to fix
> > the regression.
>
> I was intending to suggest a new function that took a pid and did not do
> the permission checks.
Can't we do this on top of this patch? I want a trivially backportable fix
for -stable.
And who else can use this helper? And what exactly it should do? Should it
be called with rcu lock held? Should it check sig != 0? Name?
> Looking a little further I think there is a reasonbly strong argument
> that this code should be using send_sigqueue with a preallocated signal,
> just like timers do.
Hmm. How can mqueue use SIGQUEUE_PREALLOC/send_sigqueue ? The timer can
pre-allocate sigqueue because it won't be used again until dequeued by
its single target, otherwise it just increments overrun.
mqueue can't. Just suppose that the user of mq_notify() blocks this signal,
then another task does mq_notify() and then __do_notify() is called again.
> > Oh, can we discuss the possible cleanups separately? On top of this fix,
> > if possible.
>
> I was saying that from my perspective your proposed fix appears to make
> the code more of a mess, and harder to maintain.
I don't really agree, but I won't argue.
> >> Looking at the code I currently see several places where we have this
> >> kind of semantic (sending a requested signal to a process from the
> >> context of another process): do_notify_parent, pdeath_signal, f_setown,
> >> and mq_notify.
> >
> > To me they all differ, I am not sure I understand how exactly you want
> > to unify them...
>
> The common thread is they all are requested by the receiver of the
> signal (so don't need permission checks) and thus need to be canceled by
> appropriate versions of exec.
Yes. Yet I think they all differ, in particular in how they handle the
exec case. So I still do not understand a) how you are going to unify this
logic and b) why should we do this _before_ the fix.
> > I can easily misread this code, never looked into ipc/mqueue.c before.
> > But it seems that it is not possible to send a signal after exec, suid
> > or not,
> >
> > - sys_mq_open() uses O_CLOEXEC
> >
> > - mqueue_flush_file() does
> >
> > if (task_tgid(current) == info->notify_owner)
> > remove_notification(info);
>
> That is weird. It looks like we are attempt to handle file descriptor
> passing. The unix98 description of exec says all mq file descriptors
> shall be closed, but I can't find a word about file descriptor passing
> with af_unix sockets.
Not sure I understand how this connects to fd-passing...
What I tried to say is that mqueue_fd will be closed on exec. This is not
not enough, but mqueue_flush_file==mqueue_file_operations->flush called
by filp_close() will remove the notification to ensure the signal can't
be sent after that.
> > I know absolutely nothing about ipc/mqueue, and when I read this code
> > or manpage I find the semantics of mq_notify is very strange.
>
> Well at least a small comment please that says the code started
> performing the permission check and userspace code regressed.
Ah, OK, agreed, I'll add a comment.
> Perhaps with the description of the userspace code in the commit log.
> Perhaps a test case?
OK, how about
static int notified;
static void sigh(int sig)
{
notified = 1;
}
int main(void)
{
signal(SIGIO, sigh);
int fd = mq_open("/mq", O_RDWR|O_CREAT, 0666, NULL);
assert(fd >= 0);
struct sigevent se = {
.sigev_notify = SIGEV_SIGNAL,
.sigev_signo = SIGIO,
};
assert(mq_notify(fd, &se) == 0);
if (!fork()) {
setuid(1);
mq_send(fd, "",1,0);
return 0;
}
wait(NULL);
mq_unlink("/mq");
assert(notified);
return 0;
}
? Needs root.
Just in case... it passes on my machine running 4.2.8-300.fc23.x86_64, fails
with upstream kernel, the patch seems to work and looks very simple.
Oleg.
next prev parent reply other threads:[~2020-03-24 10:35 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-22 11:09 [PATCH] ipc/mqueue.c: change __do_notify() to bypass check_kill_permission() Oleg Nesterov
2020-03-22 14:17 ` Eric W. Biederman
2020-03-22 14:59 ` Eric W. Biederman
2020-03-22 20:29 ` Oleg Nesterov
2020-03-23 16:47 ` Eric W. Biederman
2020-03-24 2:12 ` Andrew Morton
2020-03-24 2:57 ` Eric W. Biederman
2020-03-24 11:52 ` Oleg Nesterov
2020-03-24 20:08 ` Oleg Nesterov
2020-03-24 10:35 ` Oleg Nesterov [this message]
2020-03-24 20:09 ` [PATCH V2] " Oleg Nesterov
2020-03-26 12:54 ` Eric W. Biederman
2020-03-27 19:56 ` [PATCH -mm] ipc-mqueuec-change-__do_notify-to-bypass-check_kill_permission-fix 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=20200324103528.GA9061@redhat.com \
--to=oleg@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=dave@stgolabs.net \
--cc=ebiederm@xmission.com \
--cc=elfring@users.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
--cc=manfred@colorfullife.com \
--cc=yoji.fujihar.min@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.