]> Git Repo - J-linux.git/commitdiff
Merge branch 'exit-cleanups-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <[email protected]>
Wed, 1 Sep 2021 21:52:05 +0000 (14:52 -0700)
committerLinus Torvalds <[email protected]>
Wed, 1 Sep 2021 21:52:05 +0000 (14:52 -0700)
Pull exit cleanups from Eric Biederman:
 "In preparation of doing something about PTRACE_EVENT_EXIT I have
  started cleaning up various pieces of code related to do_exit. Most of
  that code I did not manage to get tested and reviewed before the merge
  window opened but a handful of very useful cleanups are ready to be
  merged.

  The first change is simply the removal of the bdflush system call. The
  code has now been disabled long enough that even the oldest userspace
  working userspace setups anyone can find to test are fine with the
  bdflush system call being removed.

  Changing m68k fsp040_die to use force_sigsegv(SIGSEGV) instead of
  calling do_exit directly is interesting only in that it is nearly the
  most difficult of the incorrect uses of do_exit to remove.

  The change to the seccomp code to simply send a signal instead of
  calling do_coredump directly is a very nice little cleanup made
  possible by realizing the existing signal sending helpers were missing
  a little bit of functionality that is easy to provide"

* 'exit-cleanups-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  signal/seccomp: Dump core when there is only one live thread
  signal/seccomp: Refactor seccomp signal and coredump generation
  signal/m68k: Use force_sigsegv(SIGSEGV) in fpsp040_die
  exit/bdflush: Remove the deprecated bdflush system call

1  2 
fs/buffer.c
include/linux/sched/signal.h
kernel/seccomp.c
kernel/signal.c

diff --combined fs/buffer.c
index bd6a9e9fbd64c92f9af2909123f6c38c3b7a1049,32718ee13b081f267b35f4f3ef4e253074821696..ab7573d72dd7a2b8b97c18ef00d31f51b98051e1
@@@ -1912,7 -1912,7 +1912,7 @@@ EXPORT_SYMBOL(page_zero_new_buffers)
  
  static void
  iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
 -              struct iomap *iomap)
 +              const struct iomap *iomap)
  {
        loff_t offset = block << inode->i_blkbits;
  
  }
  
  int __block_write_begin_int(struct page *page, loff_t pos, unsigned len,
 -              get_block_t *get_block, struct iomap *iomap)
 +              get_block_t *get_block, const struct iomap *iomap)
  {
        unsigned from = pos & (PAGE_SIZE - 1);
        unsigned to = from + len;
@@@ -3267,33 -3267,6 +3267,6 @@@ out
  }
  EXPORT_SYMBOL(try_to_free_buffers);
  
- /*
-  * There are no bdflush tunables left.  But distributions are
-  * still running obsolete flush daemons, so we terminate them here.
-  *
-  * Use of bdflush() is deprecated and will be removed in a future kernel.
-  * The `flush-X' kernel threads fully replace bdflush daemons and this call.
-  */
- SYSCALL_DEFINE2(bdflush, int, func, long, data)
- {
-       static int msg_count;
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       if (msg_count < 5) {
-               msg_count++;
-               printk(KERN_INFO
-                       "warning: process `%s' used the obsolete bdflush"
-                       " system call\n", current->comm);
-               printk(KERN_INFO "Fix your initscripts?\n");
-       }
-       if (func == 1)
-               do_exit(0);
-       return 0;
- }
  /*
   * Buffer-head allocation
   */
index 548986c7d233b658d7b9e7b92fb5151f0830fb73,e3c933facd86821fc4ed21684e7457924da7ce8f..e5f4ce622ee61a1be97874abf680bd0342483d69
@@@ -298,6 -298,11 +298,6 @@@ static inline void kernel_signal_stop(v
  
        schedule();
  }
 -#ifdef __ARCH_SI_TRAPNO
 -# define ___ARCH_SI_TRAPNO(_a1) , _a1
 -#else
 -# define ___ARCH_SI_TRAPNO(_a1)
 -#endif
  #ifdef __ia64__
  # define ___ARCH_SI_IA64(_a1, _a2, _a3) , _a1, _a2, _a3
  #else
  #endif
  
  int force_sig_fault_to_task(int sig, int code, void __user *addr
 -      ___ARCH_SI_TRAPNO(int trapno)
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
        , struct task_struct *t);
  int force_sig_fault(int sig, int code, void __user *addr
 -      ___ARCH_SI_TRAPNO(int trapno)
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
  int send_sig_fault(int sig, int code, void __user *addr
 -      ___ARCH_SI_TRAPNO(int trapno)
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
        , struct task_struct *t);
  
@@@ -321,9 -329,7 +321,10 @@@ int force_sig_pkuerr(void __user *addr
  int force_sig_perf(void __user *addr, u32 type, u64 sig_data);
  
  int force_sig_ptrace_errno_trap(int errno, void __user *addr);
 +int force_sig_fault_trapno(int sig, int code, void __user *addr, int trapno);
 +int send_sig_fault_trapno(int sig, int code, void __user *addr, int trapno,
 +                      struct task_struct *t);
+ int force_sig_seccomp(int syscall, int reason, bool force_coredump);
  
  extern int send_sig_info(int, struct kernel_siginfo *, struct task_struct *);
  extern void force_sigsegv(int sig);
@@@ -709,12 -715,6 +710,12 @@@ static inline void unlock_task_sighand(
        spin_unlock_irqrestore(&task->sighand->siglock, *flags);
  }
  
 +#ifdef CONFIG_LOCKDEP
 +extern void lockdep_assert_task_sighand_held(struct task_struct *task);
 +#else
 +static inline void lockdep_assert_task_sighand_held(struct task_struct *task) { }
 +#endif
 +
  static inline unsigned long task_rlimit(const struct task_struct *task,
                unsigned int limit)
  {
diff --combined kernel/seccomp.c
index 6469eca8078ca01eb3e0407d741964a25e88d2d1,afa4db09706801a0f7393ed404a31e39b040c382..4d8f44a177274f58f414c2d225498f648f4f88b1
@@@ -602,7 -602,7 +602,7 @@@ static inline void seccomp_sync_threads
                smp_store_release(&thread->seccomp.filter,
                                  caller->seccomp.filter);
                atomic_set(&thread->seccomp.filter_count,
 -                         atomic_read(&thread->seccomp.filter_count));
 +                         atomic_read(&caller->seccomp.filter_count));
  
                /*
                 * Don't let an unprivileged task work around
@@@ -922,30 -922,6 +922,6 @@@ void get_seccomp_filter(struct task_str
        refcount_inc(&orig->users);
  }
  
- static void seccomp_init_siginfo(kernel_siginfo_t *info, int syscall, int reason)
- {
-       clear_siginfo(info);
-       info->si_signo = SIGSYS;
-       info->si_code = SYS_SECCOMP;
-       info->si_call_addr = (void __user *)KSTK_EIP(current);
-       info->si_errno = reason;
-       info->si_arch = syscall_get_arch(current);
-       info->si_syscall = syscall;
- }
- /**
-  * seccomp_send_sigsys - signals the task to allow in-process syscall emulation
-  * @syscall: syscall number to send to userland
-  * @reason: filter-supplied reason code to send to userland (via si_errno)
-  *
-  * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
-  */
- static void seccomp_send_sigsys(int syscall, int reason)
- {
-       struct kernel_siginfo info;
-       seccomp_init_siginfo(&info, syscall, reason);
-       force_sig_info(&info);
- }
  #endif        /* CONFIG_SECCOMP_FILTER */
  
  /* For use with seccomp_actions_logged */
@@@ -1218,7 -1194,7 +1194,7 @@@ static int __seccomp_filter(int this_sy
                /* Show the handler the original registers. */
                syscall_rollback(current, current_pt_regs());
                /* Let the filter pass back 16 bits of data. */
-               seccomp_send_sigsys(this_syscall, data);
+               force_sig_seccomp(this_syscall, data, false);
                goto skip;
  
        case SECCOMP_RET_TRACE:
                seccomp_log(this_syscall, SIGSYS, action, true);
                /* Dump core only if this is the last remaining thread. */
                if (action != SECCOMP_RET_KILL_THREAD ||
-                   get_nr_threads(current) == 1) {
-                       kernel_siginfo_t info;
+                   (atomic_read(&current->signal->live) == 1)) {
                        /* Show the original registers in the dump. */
                        syscall_rollback(current, current_pt_regs());
-                       /* Trigger a manual coredump since do_exit skips it. */
-                       seccomp_init_siginfo(&info, this_syscall, data);
-                       do_coredump(&info);
-               }
-               if (action == SECCOMP_RET_KILL_THREAD)
+                       /* Trigger a coredump with SIGSYS */
+                       force_sig_seccomp(this_syscall, data, true);
+               } else {
                        do_exit(SIGSYS);
-               else
-                       do_group_exit(SIGSYS);
+               }
+               return -1; /* skip the syscall go directly to signal handling */
        }
  
        unreachable();
diff --combined kernel/signal.c
index 65a54118ac9e36122482501a20206e005df217ba,fbf941b80dd4b2b3f3cdeaf76ce5b2dbb0ae433a..cf7e2505ae313fb1f642959685ee39ab33f9ec0c
@@@ -54,6 -54,7 +54,7 @@@
  #include <asm/unistd.h>
  #include <asm/siginfo.h>
  #include <asm/cacheflush.h>
+ #include <asm/syscall.h>      /* for syscall_get_* */
  
  /*
   * SLAB caches for signal bits.
@@@ -1213,7 -1214,7 +1214,7 @@@ static inline bool has_si_pid_and_uid(s
        case SIL_FAULT_MCEERR:
        case SIL_FAULT_BNDERR:
        case SIL_FAULT_PKUERR:
 -      case SIL_PERF_EVENT:
 +      case SIL_FAULT_PERF_EVENT:
        case SIL_SYS:
                ret = false;
                break;
@@@ -1322,7 -1323,7 +1323,7 @@@ int do_send_sig_info(int sig, struct ke
   * that is why we also clear SIGNAL_UNKILLABLE.
   */
  static int
- force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t)
+ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl)
  {
        unsigned long int flags;
        int ret, blocked, ignored;
        action = &t->sighand->action[sig-1];
        ignored = action->sa.sa_handler == SIG_IGN;
        blocked = sigismember(&t->blocked, sig);
-       if (blocked || ignored) {
+       if (blocked || ignored || sigdfl) {
                action->sa.sa_handler = SIG_DFL;
                if (blocked) {
                        sigdelset(&t->blocked, sig);
  
  int force_sig_info(struct kernel_siginfo *info)
  {
-       return force_sig_info_to_task(info, current);
+       return force_sig_info_to_task(info, current, false);
  }
  
  /*
@@@ -1413,21 -1414,6 +1414,21 @@@ struct sighand_struct *__lock_task_sigh
        return sighand;
  }
  
 +#ifdef CONFIG_LOCKDEP
 +void lockdep_assert_task_sighand_held(struct task_struct *task)
 +{
 +      struct sighand_struct *sighand;
 +
 +      rcu_read_lock();
 +      sighand = rcu_dereference(task->sighand);
 +      if (sighand)
 +              lockdep_assert_held(&sighand->siglock);
 +      else
 +              WARN_ON_ONCE(1);
 +      rcu_read_unlock();
 +}
 +#endif
 +
  /*
   * send signal info to all the members of a group
   */
@@@ -1681,6 -1667,7 +1682,6 @@@ void force_sigsegv(int sig
  }
  
  int force_sig_fault_to_task(int sig, int code, void __user *addr
 -      ___ARCH_SI_TRAPNO(int trapno)
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
        , struct task_struct *t)
  {
        info.si_errno = 0;
        info.si_code  = code;
        info.si_addr  = addr;
 -#ifdef __ARCH_SI_TRAPNO
 -      info.si_trapno = trapno;
 -#endif
  #ifdef __ia64__
        info.si_imm = imm;
        info.si_flags = flags;
        info.si_isr = isr;
  #endif
-       return force_sig_info_to_task(&info, t);
+       return force_sig_info_to_task(&info, t, false);
  }
  
  int force_sig_fault(int sig, int code, void __user *addr
 -      ___ARCH_SI_TRAPNO(int trapno)
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
  {
        return force_sig_fault_to_task(sig, code, addr
 -                                     ___ARCH_SI_TRAPNO(trapno)
                                       ___ARCH_SI_IA64(imm, flags, isr), current);
  }
  
  int send_sig_fault(int sig, int code, void __user *addr
 -      ___ARCH_SI_TRAPNO(int trapno)
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
        , struct task_struct *t)
  {
        info.si_errno = 0;
        info.si_code  = code;
        info.si_addr  = addr;
 -#ifdef __ARCH_SI_TRAPNO
 -      info.si_trapno = trapno;
 -#endif
  #ifdef __ia64__
        info.si_imm = imm;
        info.si_flags = flags;
@@@ -1798,6 -1794,27 +1799,27 @@@ int force_sig_perf(void __user *addr, u
        return force_sig_info(&info);
  }
  
+ /**
+  * force_sig_seccomp - signals the task to allow in-process syscall emulation
+  * @syscall: syscall number to send to userland
+  * @reason: filter-supplied reason code to send to userland (via si_errno)
+  *
+  * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
+  */
+ int force_sig_seccomp(int syscall, int reason, bool force_coredump)
+ {
+       struct kernel_siginfo info;
+       clear_siginfo(&info);
+       info.si_signo = SIGSYS;
+       info.si_code = SYS_SECCOMP;
+       info.si_call_addr = (void __user *)KSTK_EIP(current);
+       info.si_errno = reason;
+       info.si_arch = syscall_get_arch(current);
+       info.si_syscall = syscall;
+       return force_sig_info_to_task(&info, current, force_coredump);
+ }
  /* For the crazy architectures that include trap information in
   * the errno field, instead of an actual errno value.
   */
@@@ -1813,39 -1830,6 +1835,39 @@@ int force_sig_ptrace_errno_trap(int err
        return force_sig_info(&info);
  }
  
 +/* For the rare architectures that include trap information using
 + * si_trapno.
 + */
 +int force_sig_fault_trapno(int sig, int code, void __user *addr, int trapno)
 +{
 +      struct kernel_siginfo info;
 +
 +      clear_siginfo(&info);
 +      info.si_signo = sig;
 +      info.si_errno = 0;
 +      info.si_code  = code;
 +      info.si_addr  = addr;
 +      info.si_trapno = trapno;
 +      return force_sig_info(&info);
 +}
 +
 +/* For the rare architectures that include trap information using
 + * si_trapno.
 + */
 +int send_sig_fault_trapno(int sig, int code, void __user *addr, int trapno,
 +                        struct task_struct *t)
 +{
 +      struct kernel_siginfo info;
 +
 +      clear_siginfo(&info);
 +      info.si_signo = sig;
 +      info.si_errno = 0;
 +      info.si_code  = code;
 +      info.si_addr  = addr;
 +      info.si_trapno = trapno;
 +      return send_sig_info(info.si_signo, &info, t);
 +}
 +
  int kill_pgrp(struct pid *pid, int sig, int priv)
  {
        int ret;
@@@ -2595,7 -2579,7 +2617,7 @@@ static void hide_si_addr_tag_bits(struc
        case SIL_FAULT_MCEERR:
        case SIL_FAULT_BNDERR:
        case SIL_FAULT_PKUERR:
 -      case SIL_PERF_EVENT:
 +      case SIL_FAULT_PERF_EVENT:
                ksig->info.si_addr = arch_untagged_si_addr(
                        ksig->info.si_addr, ksig->sig, ksig->info.si_code);
                break;
@@@ -3280,14 -3264,11 +3302,14 @@@ enum siginfo_layout siginfo_layout(unsi
                                layout = SIL_FAULT_PKUERR;
  #endif
                        else if ((sig == SIGTRAP) && (si_code == TRAP_PERF))
 -                              layout = SIL_PERF_EVENT;
 -#ifdef __ARCH_SI_TRAPNO
 -                      else if (layout == SIL_FAULT)
 +                              layout = SIL_FAULT_PERF_EVENT;
 +                      else if (IS_ENABLED(CONFIG_SPARC) &&
 +                               (sig == SIGILL) && (si_code == ILL_ILLTRP))
 +                              layout = SIL_FAULT_TRAPNO;
 +                      else if (IS_ENABLED(CONFIG_ALPHA) &&
 +                               ((sig == SIGFPE) ||
 +                                ((sig == SIGTRAP) && (si_code == TRAP_UNK))))
                                layout = SIL_FAULT_TRAPNO;
 -#endif
                }
                else if (si_code <= NSIGPOLL)
                        layout = SIL_POLL;
@@@ -3409,7 -3390,7 +3431,7 @@@ void copy_siginfo_to_external32(struct 
                to->si_addr = ptr_to_compat(from->si_addr);
                to->si_pkey = from->si_pkey;
                break;
 -      case SIL_PERF_EVENT:
 +      case SIL_FAULT_PERF_EVENT:
                to->si_addr = ptr_to_compat(from->si_addr);
                to->si_perf_data = from->si_perf_data;
                to->si_perf_type = from->si_perf_type;
@@@ -3486,7 -3467,7 +3508,7 @@@ static int post_copy_siginfo_from_user3
                to->si_addr = compat_ptr(from->si_addr);
                to->si_pkey = from->si_pkey;
                break;
 -      case SIL_PERF_EVENT:
 +      case SIL_FAULT_PERF_EVENT:
                to->si_addr = compat_ptr(from->si_addr);
                to->si_perf_data = from->si_perf_data;
                to->si_perf_type = from->si_perf_type;
This page took 0.121432 seconds and 4 git commands to generate.