From ab36b5a0123abd1f92a9a3722a26353b0a097736 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 12 May 2020 20:51:00 -0400 Subject: [PATCH] Fixes for 4.14 Signed-off-by: Sasha Levin --- ...nge-__do_notify-to-bypass-check_kill.patch | 152 ++++++++++++++++++ queue-4.14/series | 1 + 2 files changed, 153 insertions(+) create mode 100644 queue-4.14/ipc-mqueue.c-change-__do_notify-to-bypass-check_kill.patch diff --git a/queue-4.14/ipc-mqueue.c-change-__do_notify-to-bypass-check_kill.patch b/queue-4.14/ipc-mqueue.c-change-__do_notify-to-bypass-check_kill.patch new file mode 100644 index 00000000000..ab8934a3c73 --- /dev/null +++ b/queue-4.14/ipc-mqueue.c-change-__do_notify-to-bypass-check_kill.patch @@ -0,0 +1,152 @@ +From 094a4a4442788dac53a1c3ae6743841d97a15d5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2020 18:35:39 -0700 +Subject: ipc/mqueue.c: change __do_notify() to bypass check_kill_permission() + +From: Oleg Nesterov + +[ Upstream commit b5f2006144c6ae941726037120fa1001ddede784 ] + +Commit cc731525f26a ("signal: Remove kernel interal si_code magic") +changed the value of SI_FROMUSER(SI_MESGQ), this means that mq_notify() no +longer works if the sender doesn't have rights to send a signal. + +Change __do_notify() to use do_send_sig_info() instead of kill_pid_info() +to avoid check_kill_permission(). + +This needs the additional notify.sigev_signo != 0 check, shouldn't we +change do_mq_notify() to deny sigev_signo == 0 ? + +Test-case: + + #include + #include + #include + #include + #include + + 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()) { + assert(setuid(1) == 0); + mq_send(fd, "",1,0); + return 0; + } + + wait(NULL); + mq_unlink("/mq"); + assert(notified); + return 0; + } + +[manfred@colorfullife.com: 1) Add self_exec_id evaluation so that the implementation matches do_notify_parent 2) use PIDTYPE_TGID everywhere] +Fixes: cc731525f26a ("signal: Remove kernel interal si_code magic") +Reported-by: Yoji +Signed-off-by: Oleg Nesterov +Signed-off-by: Manfred Spraul +Signed-off-by: Andrew Morton +Acked-by: "Eric W. Biederman" +Cc: Davidlohr Bueso +Cc: Markus Elfring +Cc: <1vier1@web.de> +Cc: +Link: http://lkml.kernel.org/r/e2a782e4-eab9-4f5c-c749-c07a8f7a4e66@colorfullife.com +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + ipc/mqueue.c | 34 ++++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +diff --git a/ipc/mqueue.c b/ipc/mqueue.c +index dccd4ecb786ac..6829ea2ca1ea5 100644 +--- a/ipc/mqueue.c ++++ b/ipc/mqueue.c +@@ -76,6 +76,7 @@ struct mqueue_inode_info { + + struct sigevent notify; + struct pid *notify_owner; ++ u32 notify_self_exec_id; + struct user_namespace *notify_user_ns; + struct user_struct *user; /* user who created, for accounting */ + struct sock *notify_sock; +@@ -639,27 +640,43 @@ static void __do_notify(struct mqueue_inode_info *info) + * synchronously. */ + if (info->notify_owner && + info->attr.mq_curmsgs == 1) { +- struct siginfo sig_i; + switch (info->notify.sigev_notify) { + case SIGEV_NONE: + break; +- case SIGEV_SIGNAL: +- /* sends signal */ ++ case SIGEV_SIGNAL: { ++ struct siginfo sig_i; ++ struct task_struct *task; ++ ++ /* do_mq_notify() accepts sigev_signo == 0, why?? */ ++ if (!info->notify.sigev_signo) ++ break; + + sig_i.si_signo = info->notify.sigev_signo; + sig_i.si_errno = 0; + sig_i.si_code = SI_MESGQ; + sig_i.si_value = info->notify.sigev_value; +- /* map current pid/uid into info->owner's namespaces */ + rcu_read_lock(); ++ /* map current pid/uid into info->owner's namespaces */ + sig_i.si_pid = task_tgid_nr_ns(current, + ns_of_pid(info->notify_owner)); +- sig_i.si_uid = from_kuid_munged(info->notify_user_ns, current_uid()); ++ sig_i.si_uid = from_kuid_munged(info->notify_user_ns, ++ current_uid()); ++ /* ++ * We can't use kill_pid_info(), this signal should ++ * bypass check_kill_permission(). It is from kernel ++ * but si_fromuser() can't know this. ++ * We do check the self_exec_id, to avoid sending ++ * signals to programs that don't expect them. ++ */ ++ task = pid_task(info->notify_owner, PIDTYPE_TGID); ++ if (task && task->self_exec_id == ++ info->notify_self_exec_id) { ++ do_send_sig_info(info->notify.sigev_signo, ++ &sig_i, task, PIDTYPE_TGID); ++ } + rcu_read_unlock(); +- +- kill_pid_info(info->notify.sigev_signo, +- &sig_i, info->notify_owner); + break; ++ } + case SIGEV_THREAD: + set_cookie(info->notify_cookie, NOTIFY_WOKENUP); + netlink_sendskb(info->notify_sock, info->notify_cookie); +@@ -1327,6 +1344,7 @@ retry: + info->notify.sigev_signo = notification->sigev_signo; + info->notify.sigev_value = notification->sigev_value; + info->notify.sigev_notify = SIGEV_SIGNAL; ++ info->notify_self_exec_id = current->self_exec_id; + break; + } + +-- +2.20.1 + diff --git a/queue-4.14/series b/queue-4.14/series index fa7dcdf7031..b680616632a 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -46,3 +46,4 @@ f2fs-sanity-check-of-xattr-entry-size.patch f2fs-fix-to-avoid-accessing-xattr-across-the-boundary.patch f2fs-fix-to-avoid-memory-leakage-in-f2fs_listxattr.patch arm64-hugetlb-avoid-potential-null-dereference.patch +ipc-mqueue.c-change-__do_notify-to-bypass-check_kill.patch -- 2.47.3