meta-starlingx: remove the upstream layer
[pti/rtp.git] / meta-starlingx / meta-stx-integ / recipes-kernel / linux / linux / Notification-of-Death-of-arbitrary-processes.patch
diff --git a/meta-starlingx/meta-stx-integ/recipes-kernel/linux/linux/Notification-of-Death-of-arbitrary-processes.patch b/meta-starlingx/meta-stx-integ/recipes-kernel/linux/linux/Notification-of-Death-of-arbitrary-processes.patch
deleted file mode 100644 (file)
index e1e4ecf..0000000
+++ /dev/null
@@ -1,546 +0,0 @@
-From 4cfbf1a112e17b071fcdae207e4f785c096a198c Mon Sep 17 00:00:00 2001
-From: Saul Wold <sgw@linux.intel.com>
-Date: Thu, 2 Jul 2020 09:46:12 -0700
-Subject: [PATCH] Notification of Death of arbitrary processes
-
-Note: this commit was copied from Titanium Cloud Rel2
-
-This exposes a new feature which may be called to request
-notification when an arbitrary process changes state. The
-caller specifies a pid, signal number, and event mask, and
-when that pid dies, or is stopped, or anything else that
-would normally cause a SIGCHLD, the kernel will send the
-specified signal to the caller if the event is in the event
-mask originally passed down. The siginfo_t struct will
-contain the same information as would be included with SIGCHLD.
-
-This is exposed to userspace via the prctl() call with the
-PR_DO_NOTIFY_TASK_STATE option.
-
-Signed-off-by: Jim Somerville <Jim.Somerville@windriver.com>
-Signed-off-by: Zhang Zhiguo <zhangzhg@neusoft.com>
-Signed-off-by: Shuicheng Lin <shuicheng.lin@intel.com>
-Signed-off-by: Saul Wold <sgw@linux.intel.com>
----
- include/linux/init_task.h  |   9 ++
- include/linux/sched.h      |   6 +
- include/uapi/linux/prctl.h |  18 +++
- init/Kconfig               |  15 +++
- init/init_task.c           |   1 +
- kernel/Makefile            |   1 +
- kernel/death_notify.c      | 228 +++++++++++++++++++++++++++++++++++++
- kernel/death_notify.h      |  46 ++++++++
- kernel/exit.c              |   6 +
- kernel/fork.c              |   4 +
- kernel/signal.c            |  11 ++
- kernel/sys.c               |   8 ++
- 12 files changed, 353 insertions(+)
- create mode 100644 kernel/death_notify.c
- create mode 100644 kernel/death_notify.h
-
-diff --git a/include/linux/init_task.h b/include/linux/init_task.h
-index a7083a45a26c..1ad2341b3036 100644
---- a/include/linux/init_task.h
-+++ b/include/linux/init_task.h
-@@ -24,6 +24,15 @@
- extern struct files_struct init_files;
- extern struct fs_struct init_fs;
- extern struct nsproxy init_nsproxy;
-+
-+#ifdef CONFIG_SIGEXIT
-+#define INIT_SIGEXIT(tsk) \
-+      .notify         = LIST_HEAD_INIT(tsk.notify),                   \
-+      .monitor        = LIST_HEAD_INIT(tsk.monitor),
-+#else
-+#define INIT_SIGEXIT(tsk)
-+#endif
-+
- extern struct group_info init_groups;
- extern struct cred init_cred;
-diff --git a/include/linux/sched.h b/include/linux/sched.h
-index 9b35aff09f70..d6f5a2711b7d 100644
---- a/include/linux/sched.h
-+++ b/include/linux/sched.h
-@@ -1015,6 +1015,12 @@ struct task_struct {
-       short                           il_prev;
-       short                           pref_node_fork;
- #endif
-+#ifdef CONFIG_SIGEXIT
-+      /* list of processes to notify on death */
-+      struct                          list_head notify;
-+      /* list of outstanding monitor requests */
-+      struct                          list_head monitor;
-+#endif
- #ifdef CONFIG_NUMA_BALANCING
-       int                             numa_scan_seq;
-       unsigned int                    numa_scan_period;
-diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
-index b4875a93363a..d50c435a04ea 100644
---- a/include/uapi/linux/prctl.h
-+++ b/include/uapi/linux/prctl.h
-@@ -63,6 +63,24 @@
- # define PR_ENDIAN_LITTLE     1       /* True little endian mode */
- # define PR_ENDIAN_PPC_LITTLE 2       /* "PowerPC" pseudo little endian */
-+#ifdef CONFIG_SIGEXIT
-+#define PR_DO_NOTIFY_TASK_STATE 17    /* Set/get notification for task
-+                                         state changes */
-+
-+/* This is the data structure for requestion process death
-+ * (and other state change) information.  Sig of -1 means
-+ * query, sig of 0 means deregistration, positive sig means
-+ * that you want to set it.  sig and events are value-result
-+ * and will be updated with the previous values on every
-+ * successful call.
-+ */
-+struct task_state_notify_info {
-+      pid_t pid;
-+      int sig;
-+      unsigned int events;
-+};
-+#endif
-+
- /* Get/set process seccomp mode */
- #define PR_GET_SECCOMP        21
- #define PR_SET_SECCOMP        22
-diff --git a/init/Kconfig b/init/Kconfig
-index bdf4f284509b..8102ef3d2adb 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1648,6 +1648,21 @@ config VM_EVENT_COUNTERS
-         on EXPERT systems.  /proc/vmstat will only show page counts
-         if VM event counters are disabled.
-+config SIGEXIT
-+      bool "Notification of death of arbitrary processes"
-+      default n
-+      help
-+        When enabled this exposes a new feature which may be called to request
-+        notification when an arbitrary process changes state.  The caller specifies
-+        a pid, signal number, and event mask, and when that pid dies, or is
-+        stopped, or anything else that would normally cause a SIGCHLD, the
-+        kernel will send the specified signal to the caller if the event is in
-+        the event mask originally passed down. The siginfo_t struct will
-+        contain the same information as would be included with SIGCHLD.
-+
-+        This is exposed to userspace via the prctl()
-+        call with the PR_DO_NOTIFY_TASK_STATE option
-+
- config SLUB_DEBUG
-       default y
-       bool "Enable SLUB debugging support" if EXPERT
-diff --git a/init/init_task.c b/init/init_task.c
-index 5aebe3be4d7c..d0891101ac7d 100644
---- a/init/init_task.c
-+++ b/init/init_task.c
-@@ -116,6 +116,7 @@ struct task_struct init_task
-       .alloc_lock     = __SPIN_LOCK_UNLOCKED(init_task.alloc_lock),
-       .journal_info   = NULL,
-       INIT_CPU_TIMERS(init_task)
-+      INIT_SIGEXIT(init_task)
-       .pi_lock        = __RAW_SPIN_LOCK_UNLOCKED(init_task.pi_lock),
-       .timer_slack_ns = 50000, /* 50 usec default slack */
-       .thread_pid     = &init_struct_pid,
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 1ea0ba13a445..f839f425ca09 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -99,6 +99,7 @@ obj-$(CONFIG_TRACEPOINTS) += trace/
- obj-$(CONFIG_IRQ_WORK) += irq_work.o
- obj-$(CONFIG_CPU_PM) += cpu_pm.o
- obj-$(CONFIG_BPF) += bpf/
-+obj-$(CONFIG_SIGEXIT) += death_notify.o
- obj-$(CONFIG_PERF_EVENTS) += events/
-diff --git a/kernel/death_notify.c b/kernel/death_notify.c
-new file mode 100644
-index 000000000000..5819d35a2564
---- /dev/null
-+++ b/kernel/death_notify.c
-@@ -0,0 +1,228 @@
-+/*
-+ * kernel/death_notify.c, Process death notification support
-+ *
-+ * Copyright (c) 2006-2014 Wind River Systems, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-+ * See the GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ */
-+
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/sched/task.h>
-+#include <linux/slab.h>
-+#include <linux/prctl.h>
-+#include <linux/uaccess.h>
-+#include "death_notify.h"
-+
-+static void unlink_status_notifier(struct signotifier *n)
-+{
-+      list_del(&n->monitor_list);
-+      list_del(&n->notify_list);
-+      kfree(n);
-+}
-+
-+static void handle_already_monitoring(struct signotifier *node,
-+       struct task_state_notify_info *args,
-+       struct task_state_notify_info *oldargs)
-+{
-+      /* Store the old values */
-+      oldargs->sig = node->sig;
-+      oldargs->events = node->events;
-+
-+      /* We know that args->sig is 0 or a valid signal. */
-+      if (args->sig > 0) {
-+              /* Update the new values */
-+              node->sig = args->sig;
-+              node->events = args->events;
-+      } else if (!args->sig) {
-+              /* args->sig of 0 means to deregister */
-+              unlink_status_notifier(node);
-+      }
-+}
-+
-+static void setup_new_node(struct task_struct *p,
-+      struct signotifier *node,
-+      struct task_state_notify_info *args)
-+{
-+      node->notify_tsk = current;
-+      node->sig = args->sig;
-+      node->events = args->events;
-+
-+      /* Add this node to the list of notification requests
-+       * for the specified process.
-+       */
-+      list_add_tail(&node->notify_list, &p->notify);
-+
-+      /* Also add this node to the list of monitor requests
-+       * for the current process.
-+       */
-+      list_add_tail(&node->monitor_list, &current->monitor);
-+}
-+
-+/* Returns 0 if arguments are valid, 1 if they are not. */
-+static int invalid_args(struct task_state_notify_info *args)
-+{
-+      int ret = 1;
-+
-+      if (args->pid <= 0)
-+              goto out;
-+
-+      /* Sig of -1 implies query, sig of 0 implies deregistration.
-+       * Otherwise sig must be positive and within range.
-+       */
-+      if ((args->sig < -1) || (args->sig > _NSIG))
-+              goto out;
-+
-+      /* If positive sig, must have valid events. */
-+      if (args->sig > 0) {
-+              if (!args->events || (args->events >= (1 << (NSIGCHLD+1))))
-+                      goto out;
-+      }
-+
-+      ret = 0;
-+out:
-+      return ret;
-+}
-+
-+/* Notify those registered for process state updates via do_notify_task_state().
-+ * If "del" is nonzero, the process is dying and we want to free
-+ * the nodes in the list as we go.
-+ *
-+ * Note: we only notify processes for events in which they have registered
-+ * interest.
-+ *
-+ * Must be called holding a lock on tasklist_lock.
-+ */
-+void do_notify_others(struct task_struct *tsk, struct kernel_siginfo *info)
-+{
-+      struct signotifier *node;
-+      unsigned int events;
-+
-+      /* This method of generating the event bit must be
-+       * matched in the userspace library.
-+       */
-+      events = 1 << (info->si_code & 0xFF);
-+
-+      list_for_each_entry(node, &tsk->notify, notify_list) {
-+              if (events & node->events) {
-+                      info->si_signo = node->sig;
-+                      group_send_sig_info(node->sig, info, node->notify_tsk, PIDTYPE_TGID);
-+              }
-+      }
-+}
-+
-+void release_notify_others(struct task_struct *p)
-+{
-+      struct signotifier *n, *t;
-+
-+      /* Need to clean up any outstanding requests where we
-+       * wanted to be notified when others died.
-+       */
-+      list_for_each_entry_safe(n, t, &p->monitor, monitor_list) {
-+              unlink_status_notifier(n);
-+      }
-+
-+      /* Also need to clean up any outstanding requests where others
-+       * wanted to be notified when we died.
-+       */
-+      list_for_each_entry_safe(n, t, &p->notify, notify_list) {
-+              unlink_status_notifier(n);
-+      }
-+}
-+
-+/* If the config is defined, then processes can call this routine
-+ * to request notification when the specified task's state changes.
-+ * On the death (or other state change) of the specified process,
-+ * we will send them the specified signal if the event is listed
-+ * in their event bitfield.
-+ *
-+ * A sig of 0 means that we want to deregister.
-+ *
-+ * The sig/events fields are value/result.  On success we update them
-+ * to reflect what they were before the call.
-+ *
-+ * Returns error code on error, on success we return 0.
-+ */
-+int do_notify_task_state(unsigned long arg)
-+{
-+      int err;
-+      struct task_struct *p;
-+      struct signotifier *node, *tmp;
-+      struct task_state_notify_info args, oldargs;
-+
-+      if (copy_from_user(&args, (struct task_state_notify_info __user *)arg,
-+                      sizeof(args)))
-+              return -EFAULT;
-+      oldargs.pid = args.pid;
-+
-+      /* Validate the arguments passed in. */
-+      err = -EINVAL;
-+      if (invalid_args(&args))
-+              goto out;
-+
-+      /* We must hold a write lock on tasklist_lock to add the notification
-+       * later on, and we need some lock on tasklist_lock for
-+       * find_task_by_pid(), so may as well take the write lock now.
-+       * Must use write_lock_irq().
-+       */
-+      write_lock_irq(&tasklist_lock);
-+
-+      err = -ESRCH;
-+      p = find_task_by_vpid(args.pid);
-+      if (!p)
-+              goto unlock_out;
-+
-+      /* Now we know pid exists, unlikely to fail. */
-+      err = 0;
-+
-+      /* Check if we're already monitoring the specified pid. If so, update
-+       * the monitoring parameters and return the old ones.
-+       */
-+      list_for_each_entry(tmp, &p->notify, notify_list) {
-+              if (tmp->notify_tsk == current) {
-+                      handle_already_monitoring(tmp, &args, &oldargs);
-+                      goto unlock_out;
-+              }
-+      }
-+
-+      /* If we get here, we're not currently monitoring the process. */
-+      oldargs.sig = 0;
-+      oldargs.events = 0;
-+
-+      /* If we wanted to set up a new monitor, do it now. If we didn't
-+       * manage to allocate memory for the new node, then we return
-+       * an appropriate error.
-+       */
-+      if (args.sig > 0) {
-+              node = kmalloc(sizeof(*node), GFP_ATOMIC);
-+              if (node)
-+                      setup_new_node(p, node, &args);
-+              else
-+                      err = -ENOMEM;
-+      }
-+
-+unlock_out:
-+      write_unlock_irq(&tasklist_lock);
-+
-+      /* Copy the old values back to caller. */
-+      if (copy_to_user((struct task_state_notify_info __user *)arg,
-+                      &oldargs, sizeof(oldargs)))
-+              err = -EFAULT;
-+
-+out:
-+      return err;
-+}
-+
-diff --git a/kernel/death_notify.h b/kernel/death_notify.h
-new file mode 100644
-index 000000000000..14a0995b79af
---- /dev/null
-+++ b/kernel/death_notify.h
-@@ -0,0 +1,46 @@
-+/*
-+ * kernel/death_notify.h, Process death notification support
-+ *
-+ * Copyright (c) 2006-2014 Wind River Systems, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-+ * See the GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ */
-+#ifndef _KERNEL_DEATH_NOTIFY_H
-+#define _KERNEL_DEATH_NOTIFY_H
-+
-+#ifdef CONFIG_SIGEXIT
-+
-+struct signotifier {
-+      struct task_struct *notify_tsk;
-+      struct list_head notify_list;
-+      struct list_head monitor_list;
-+      int sig;
-+      unsigned int events;
-+};
-+
-+extern int do_notify_task_state(unsigned long arg);
-+extern void do_notify_others(struct task_struct *tsk,
-+                                      struct kernel_siginfo *info);
-+extern void release_notify_others(struct task_struct *p);
-+
-+#else /* !CONFIG_SIGEXIT */
-+
-+static inline void do_notify_others(struct task_struct *tsk,
-+                                      struct kernel_siginfo *info) {}
-+static inline void release_notify_others(struct task_struct *p) {}
-+
-+#endif /* CONFIG_SIGEXIT */
-+#endif
-+
-diff --git a/kernel/exit.c b/kernel/exit.c
-index 2166c2d92ddc..f35f3a5870a8 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -67,6 +67,9 @@
- #include <asm/unistd.h>
- #include <asm/pgtable.h>
- #include <asm/mmu_context.h>
-+#ifdef CONFIG_SIGEXIT
-+#include "death_notify.h"
-+#endif
- static void __unhash_process(struct task_struct *p, bool group_dead)
- {
-@@ -196,6 +199,9 @@ void release_task(struct task_struct *p)
-       proc_flush_task(p);
-       write_lock_irq(&tasklist_lock);
-+#ifdef CONFIG_SIGEXIT
-+      release_notify_others(p);
-+#endif
-       ptrace_release_task(p);
-       __exit_signal(p);
-diff --git a/kernel/fork.c b/kernel/fork.c
-index 17389e9935c4..4d79f261c365 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -1907,6 +1907,10 @@ static __latent_entropy struct task_struct *copy_process(
-       p->sequential_io        = 0;
-       p->sequential_io_avg    = 0;
- #endif
-+#ifdef CONFIG_SIGEXIT
-+      INIT_LIST_HEAD(&p->notify);
-+      INIT_LIST_HEAD(&p->monitor);
-+#endif
-       /* Perform scheduler related setup. Assign this task to a CPU. */
-       retval = sched_fork(clone_flags, p);
-diff --git a/kernel/signal.c b/kernel/signal.c
-index 57b7771e20d7..41126fa53102 100644
---- a/kernel/signal.c
-+++ b/kernel/signal.c
-@@ -51,6 +51,9 @@
- #include <asm/siginfo.h>
- #include <asm/cacheflush.h>
- #include "audit.h"    /* audit_signal_info() */
-+#ifdef CONFIG_SIGEXIT
-+#include "death_notify.h"
-+#endif
- /*
-  * SLAB caches for signal bits.
-@@ -1893,6 +1896,10 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
-       __wake_up_parent(tsk, tsk->parent);
-       spin_unlock_irqrestore(&psig->siglock, flags);
-+#ifdef CONFIG_SIGEXIT
-+      do_notify_others(tsk, &info);
-+#endif
-+
-       return autoreap;
- }
-@@ -1965,6 +1972,10 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
-        */
-       __wake_up_parent(tsk, parent);
-       spin_unlock_irqrestore(&sighand->siglock, flags);
-+
-+#ifdef CONFIG_SIGEXIT
-+      do_notify_others(tsk, &info);
-+#endif
- }
- static inline bool may_ptrace_stop(void)
-diff --git a/kernel/sys.c b/kernel/sys.c
-index f7eb62eceb24..9fadbbe9565f 100644
---- a/kernel/sys.c
-+++ b/kernel/sys.c
-@@ -72,6 +72,9 @@
- #include <asm/unistd.h>
- #include "uid16.h"
-+#ifdef CONFIG_SIGEXIT
-+#include "death_notify.h"
-+#endif
- #ifndef SET_UNALIGN_CTL
- # define SET_UNALIGN_CTL(a, b)        (-EINVAL)
-@@ -2405,6 +2408,11 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
-               else
-                       error = PR_MCE_KILL_DEFAULT;
-               break;
-+#ifdef CONFIG_SIGEXIT
-+      case PR_DO_NOTIFY_TASK_STATE:
-+              error = do_notify_task_state(arg2);
-+              break;
-+#endif
-       case PR_SET_MM:
-               error = prctl_set_mm(arg2, arg3, arg4, arg5);
-               break;
--- 
-2.17.1
-