Merge tag 'y2038-cleanups-5.5' of git://git.kernel.org:/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 1 Dec 2019 22:00:59 +0000 (14:00 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 1 Dec 2019 22:00:59 +0000 (14:00 -0800)
Pull y2038 cleanups from Arnd Bergmann:
 "y2038 syscall implementation cleanups

  This is a series of cleanups for the y2038 work, mostly intended for
  namespace cleaning: the kernel defines the traditional time_t, timeval
  and timespec types that often lead to y2038-unsafe code. Even though
  the unsafe usage is mostly gone from the kernel, having the types and
  associated functions around means that we can still grow new users,
  and that we may be missing conversions to safe types that actually
  matter.

  There are still a number of driver specific patches needed to get the
  last users of these types removed, those have been submitted to the
  respective maintainers"

Link: https://lore.kernel.org/lkml/20191108210236.1296047-1-arnd@arndb.de/
* tag 'y2038-cleanups-5.5' of git://git.kernel.org:/pub/scm/linux/kernel/git/arnd/playground: (26 commits)
  y2038: alarm: fix half-second cut-off
  y2038: ipc: fix x32 ABI breakage
  y2038: fix typo in powerpc vdso "LOPART"
  y2038: allow disabling time32 system calls
  y2038: itimer: change implementation to timespec64
  y2038: move itimer reset into itimer.c
  y2038: use compat_{get,set}_itimer on alpha
  y2038: itimer: compat handling to itimer.c
  y2038: time: avoid timespec usage in settimeofday()
  y2038: timerfd: Use timespec64 internally
  y2038: elfcore: Use __kernel_old_timeval for process times
  y2038: make ns_to_compat_timeval use __kernel_old_timeval
  y2038: socket: use __kernel_old_timespec instead of timespec
  y2038: socket: remove timespec reference in timestamping
  y2038: syscalls: change remaining timeval to __kernel_old_timeval
  y2038: rusage: use __kernel_old_timeval
  y2038: uapi: change __kernel_time_t to __kernel_old_time_t
  y2038: stat: avoid 'time_t' in 'struct stat'
  y2038: ipc: remove __kernel_time_t reference from headers
  y2038: vdso: powerpc: avoid timespec references
  ...

13 files changed:
1  2 
arch/Kconfig
arch/powerpc/include/asm/asm-prototypes.h
arch/powerpc/kernel/time.c
arch/x86/entry/vsyscall/vsyscall_64.c
fs/aio.c
include/linux/compat.h
include/linux/skbuff.h
include/linux/types.h
include/trace/events/timer.h
include/uapi/linux/ppp_defs.h
net/ipv4/tcp.c
net/socket.c
security/selinux/hooks.c

diff --combined arch/Kconfig
@@@ -796,16 -796,9 +796,9 @@@ config OLD_SIGACTIO
  config COMPAT_OLD_SIGACTION
        bool
  
- config 64BIT_TIME
-       def_bool y
-       help
-         This should be selected by all architectures that need to support
-         new system calls with a 64-bit time_t. This is relevant on all 32-bit
-         architectures, and 64-bit architectures as part of compat syscall
-         handling.
  config COMPAT_32BIT_TIME
-       def_bool !64BIT || COMPAT
+       bool "Provide system calls for 32-bit time_t"
+       default !64BIT || COMPAT
        help
          This enables 32 bit time_t support in addition to 64 bit time_t support.
          This is relevant on all 32-bit architectures, and 64-bit architectures
@@@ -892,6 -885,27 +885,6 @@@ config STRICT_MODULE_RW
  config ARCH_HAS_PHYS_TO_DMA
        bool
  
 -config ARCH_HAS_REFCOUNT
 -      bool
 -      help
 -        An architecture selects this when it has implemented refcount_t
 -        using open coded assembly primitives that provide an optimized
 -        refcount_t implementation, possibly at the expense of some full
 -        refcount state checks of CONFIG_REFCOUNT_FULL=y.
 -
 -        The refcount overflow check behavior, however, must be retained.
 -        Catching overflows is the primary security concern for protecting
 -        against bugs in reference counts.
 -
 -config REFCOUNT_FULL
 -      bool "Perform full reference count validation at the expense of speed"
 -      help
 -        Enabling this switches the refcounting infrastructure from a fast
 -        unchecked atomic_t implementation to a fully state checked
 -        implementation, which can be (slightly) slower but provides protections
 -        against various use-after-free conditions that can be used in
 -        security flaw exploits.
 -
  config HAVE_ARCH_COMPILER_H
        bool
        help
@@@ -939,14 -953,6 +932,14 @@@ config REL
  config ARCH_HAS_MEM_ENCRYPT
        bool
  
 +config HAVE_SPARSE_SYSCALL_NR
 +       bool
 +       help
 +          An architecture should select this if its syscall numbering is sparse
 +        to save space. For example, MIPS architecture has a syscall array with
 +        entries at 4000, 5000 and 6000 locations. This option turns on syscall
 +        related optimizations for a given architecture.
 +
  source "kernel/gcov/Kconfig"
  
  source "scripts/gcc-plugins/Kconfig"
@@@ -92,7 -92,8 +92,8 @@@ long sys_swapcontext(struct ucontext __
  long sys_debug_setcontext(struct ucontext __user *ctx,
                          int ndbg, struct sig_dbg_op __user *dbg);
  int
- ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp);
+ ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
+          struct __kernel_old_timeval __user *tvp);
  unsigned long __init early_init(unsigned long dt_ptr);
  void __init machine_init(u64 dt_ptr);
  #endif
@@@ -152,12 -153,9 +153,12 @@@ void _kvmppc_save_tm_pr(struct kvm_vcp
  /* Patch sites */
  extern s32 patch__call_flush_count_cache;
  extern s32 patch__flush_count_cache_return;
 +extern s32 patch__flush_link_stack_return;
 +extern s32 patch__call_kvm_flush_link_stack;
  extern s32 patch__memset_nocache, patch__memcpy_nocache;
  
  extern long flush_count_cache;
 +extern long kvm_flush_link_stack;
  
  #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
  void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv);
@@@ -232,7 -232,7 +232,7 @@@ static u64 scan_dispatch_log(u64 stop_t
   * Accumulate stolen time by scanning the dispatch trace log.
   * Called on entry from user mode.
   */
 -void accumulate_stolen_time(void)
 +void notrace accumulate_stolen_time(void)
  {
        u64 sst, ust;
        unsigned long save_irq_soft_mask = irq_soft_mask_return();
@@@ -338,7 -338,7 +338,7 @@@ static unsigned long vtime_delta(struc
        return stime;
  }
  
 -void vtime_account_system(struct task_struct *tsk)
 +void vtime_account_kernel(struct task_struct *tsk)
  {
        unsigned long stime, stime_scaled, steal_time;
        struct cpu_accounting_data *acct = get_accounting(tsk);
  #endif
        }
  }
 -EXPORT_SYMBOL_GPL(vtime_account_system);
 +EXPORT_SYMBOL_GPL(vtime_account_kernel);
  
  void vtime_account_idle(struct task_struct *tsk)
  {
@@@ -395,7 -395,7 +395,7 @@@ static void vtime_flush_scaled(struct t
  /*
   * Account the whole cputime accumulated in the paca
   * Must be called with interrupts disabled.
 - * Assumes that vtime_account_system/idle() has been called
 + * Assumes that vtime_account_kernel/idle() has been called
   * recently (i.e. since the last entry from usermode) so that
   * get_paca()->user_time_scaled is up to date.
   */
@@@ -885,7 -885,7 +885,7 @@@ static notrace u64 timebase_read(struc
  
  void update_vsyscall(struct timekeeper *tk)
  {
-       struct timespec xt;
+       struct timespec64 xt;
        struct clocksource *clock = tk->tkr_mono.clock;
        u32 mult = tk->tkr_mono.mult;
        u32 shift = tk->tkr_mono.shift;
        vdso_data->tb_to_xs = new_tb_to_xs;
        vdso_data->wtom_clock_sec = tk->wall_to_monotonic.tv_sec;
        vdso_data->wtom_clock_nsec = tk->wall_to_monotonic.tv_nsec;
-       vdso_data->stamp_xtime = xt;
+       vdso_data->stamp_xtime_sec = xt.tv_sec;
+       vdso_data->stamp_xtime_nsec = xt.tv_nsec;
        vdso_data->stamp_sec_fraction = frac_sec;
        smp_wmb();
        ++(vdso_data->tb_update_count);
@@@ -184,7 -184,7 +184,7 @@@ bool emulate_vsyscall(unsigned long err
         */
        switch (vsyscall_nr) {
        case 0:
-               if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) ||
+               if (!write_ok_or_segv(regs->di, sizeof(struct __kernel_old_timeval)) ||
                    !write_ok_or_segv(regs->si, sizeof(struct timezone))) {
                        ret = -EFAULT;
                        goto check_fault;
                break;
  
        case 1:
-               if (!write_ok_or_segv(regs->di, sizeof(time_t))) {
+               if (!write_ok_or_segv(regs->di, sizeof(__kernel_old_time_t))) {
                        ret = -EFAULT;
                        goto check_fault;
                }
         */
        regs->orig_ax = syscall_nr;
        regs->ax = -ENOSYS;
 -      tmp = secure_computing(NULL);
 +      tmp = secure_computing();
        if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) {
                warn_bad_vsyscall(KERN_DEBUG, regs,
                                  "seccomp tried to change syscall nr or ip");
diff --combined fs/aio.c
+++ b/fs/aio.c
@@@ -2056,7 -2056,7 +2056,7 @@@ static long do_io_getevents(aio_context
   *    specifies an infinite timeout. Note that the timeout pointed to by
   *    timeout is relative.  Will fail with -ENOSYS if not implemented.
   */
- #if !defined(CONFIG_64BIT_TIME) || defined(CONFIG_64BIT)
+ #ifdef CONFIG_64BIT
  
  SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
                long, min_nr,
@@@ -2179,7 -2179,7 +2179,7 @@@ SYSCALL_DEFINE5(io_getevents_time32, __
  #ifdef CONFIG_COMPAT
  
  struct __compat_aio_sigset {
 -      compat_sigset_t __user  *sigmask;
 +      compat_uptr_t           sigmask;
        compat_size_t           sigsetsize;
  };
  
@@@ -2193,7 -2193,7 +2193,7 @@@ COMPAT_SYSCALL_DEFINE6(io_pgetevents
                struct old_timespec32 __user *, timeout,
                const struct __compat_aio_sigset __user *, usig)
  {
 -      struct __compat_aio_sigset ksig = { NULL, };
 +      struct __compat_aio_sigset ksig = { 0, };
        struct timespec64 t;
        bool interrupted;
        int ret;
        if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
                return -EFAULT;
  
 -      ret = set_compat_user_sigmask(ksig.sigmask, ksig.sigsetsize);
 +      ret = set_compat_user_sigmask(compat_ptr(ksig.sigmask), ksig.sigsetsize);
        if (ret)
                return ret;
  
@@@ -2228,7 -2228,7 +2228,7 @@@ COMPAT_SYSCALL_DEFINE6(io_pgetevents_ti
                struct __kernel_timespec __user *, timeout,
                const struct __compat_aio_sigset __user *, usig)
  {
 -      struct __compat_aio_sigset ksig = { NULL, };
 +      struct __compat_aio_sigset ksig = { 0, };
        struct timespec64 t;
        bool interrupted;
        int ret;
        if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
                return -EFAULT;
  
 -      ret = set_compat_user_sigmask(ksig.sigmask, ksig.sigsetsize);
 +      ret = set_compat_user_sigmask(compat_ptr(ksig.sigmask), ksig.sigsetsize);
        if (ret)
                return ret;
  
diff --combined include/linux/compat.h
@@@ -116,14 -116,7 +116,7 @@@ typedef __compat_gid32_t  compat_gid_t
  struct compat_sel_arg_struct;
  struct rusage;
  
- struct compat_itimerval {
-       struct old_timeval32    it_interval;
-       struct old_timeval32    it_value;
- };
- struct itimerval;
- int get_compat_itimerval(struct itimerval *, const struct compat_itimerval __user *);
- int put_compat_itimerval(struct compat_itimerval __user *, const struct itimerval *);
+ struct old_itimerval32;
  
  struct compat_tms {
        compat_clock_t          tms_utime;
@@@ -410,6 -403,8 +403,6 @@@ struct compat_kexec_segment
  struct compat_mq_attr;
  struct compat_msgbuf;
  
 -extern void compat_exit_robust_list(struct task_struct *curr);
 -
  #define BITS_PER_COMPAT_LONG    (8*sizeof(compat_long_t))
  
  #define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)
@@@ -666,10 -661,10 +659,10 @@@ compat_sys_get_robust_list(int pid, com
  
  /* kernel/itimer.c */
  asmlinkage long compat_sys_getitimer(int which,
-                                    struct compat_itimerval __user *it);
+                                    struct old_itimerval32 __user *it);
  asmlinkage long compat_sys_setitimer(int which,
-                                    struct compat_itimerval __user *in,
-                                    struct compat_itimerval __user *out);
+                                    struct old_itimerval32 __user *in,
+                                    struct old_itimerval32 __user *out);
  
  /* kernel/kexec.c */
  asmlinkage long compat_sys_kexec_load(compat_ulong_t entry,
@@@ -935,10 -930,10 +928,10 @@@ static inline bool in_compat_syscall(vo
   */
  static inline struct old_timeval32 ns_to_old_timeval32(s64 nsec)
  {
-       struct timeval tv;
+       struct __kernel_old_timeval tv;
        struct old_timeval32 ctv;
  
-       tv = ns_to_timeval(nsec);
+       tv = ns_to_kernel_old_timeval(nsec);
        ctv.tv_sec = tv.tv_sec;
        ctv.tv_usec = tv.tv_usec;
  
diff --combined include/linux/skbuff.h
@@@ -1795,7 -1795,7 +1795,7 @@@ static inline struct sk_buff *skb_peek_
   */
  static inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_)
  {
 -      struct sk_buff *skb = list_->prev;
 +      struct sk_buff *skb = READ_ONCE(list_->prev);
  
        if (skb == (struct sk_buff *)list_)
                skb = NULL;
@@@ -1861,9 -1861,7 +1861,9 @@@ static inline void __skb_insert(struct 
                                struct sk_buff *prev, struct sk_buff *next,
                                struct sk_buff_head *list)
  {
 -      /* see skb_queue_empty_lockless() for the opposite READ_ONCE() */
 +      /* See skb_queue_empty_lockless() and skb_peek_tail()
 +       * for the opposite READ_ONCE()
 +       */
        WRITE_ONCE(newsk->next, next);
        WRITE_ONCE(newsk->prev, prev);
        WRITE_ONCE(next->prev, newsk);
@@@ -2279,12 -2277,12 +2279,12 @@@ static inline void *pskb_pull(struct sk
        return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len);
  }
  
 -static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
 +static inline bool pskb_may_pull(struct sk_buff *skb, unsigned int len)
  {
        if (likely(len <= skb_headlen(skb)))
 -              return 1;
 +              return true;
        if (unlikely(len > skb->len))
 -              return 0;
 +              return false;
        return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL;
  }
  
@@@ -3658,9 -3656,12 +3658,12 @@@ static inline void skb_get_new_timestam
  }
  
  static inline void skb_get_timestampns(const struct sk_buff *skb,
-                                      struct timespec *stamp)
+                                      struct __kernel_old_timespec *stamp)
  {
-       *stamp = ktime_to_timespec(skb->tstamp);
+       struct timespec64 ts = ktime_to_timespec64(skb->tstamp);
+       stamp->tv_sec = ts.tv_sec;
+       stamp->tv_nsec = ts.tv_nsec;
  }
  
  static inline void skb_get_new_timestampns(const struct sk_buff *skb,
@@@ -4171,18 -4172,12 +4174,18 @@@ static inline void skb_ext_reset(struc
                skb->active_extensions = 0;
        }
  }
 +
 +static inline bool skb_has_extensions(struct sk_buff *skb)
 +{
 +      return unlikely(skb->active_extensions);
 +}
  #else
  static inline void skb_ext_put(struct sk_buff *skb) {}
  static inline void skb_ext_reset(struct sk_buff *skb) {}
  static inline void skb_ext_del(struct sk_buff *skb, int unused) {}
  static inline void __skb_ext_copy(struct sk_buff *d, const struct sk_buff *s) {}
  static inline void skb_ext_copy(struct sk_buff *dst, const struct sk_buff *s) {}
 +static inline bool skb_has_extensions(struct sk_buff *skb) { return false; }
  #endif /* CONFIG_SKB_EXTENSIONS */
  
  static inline void nf_reset_ct(struct sk_buff *skb)
diff --combined include/linux/types.h
@@@ -67,7 -67,7 +67,7 @@@ typedef __kernel_ptrdiff_t    ptrdiff_t
  
  #ifndef _TIME_T
  #define _TIME_T
- typedef __kernel_time_t               time_t;
+ typedef __kernel_old_time_t   time_t;
  #endif
  
  #ifndef _CLOCK_T
@@@ -225,10 -225,5 +225,10 @@@ struct callback_head 
  typedef void (*rcu_callback_t)(struct rcu_head *head);
  typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
  
 +typedef void (*swap_func_t)(void *a, void *b, int size);
 +
 +typedef int (*cmp_r_func_t)(const void *a, const void *b, const void *priv);
 +typedef int (*cmp_func_t)(const void *a, const void *b);
 +
  #endif /*  __ASSEMBLY__ */
  #endif /* _LINUX_TYPES_H */
@@@ -303,7 -303,7 +303,7 @@@ DEFINE_EVENT(hrtimer_class, hrtimer_can
   */
  TRACE_EVENT(itimer_state,
  
-       TP_PROTO(int which, const struct itimerval *const value,
+       TP_PROTO(int which, const struct itimerspec64 *const value,
                 unsigned long long expires),
  
        TP_ARGS(which, value, expires),
                __field(        int,                    which           )
                __field(        unsigned long long,     expires         )
                __field(        long,                   value_sec       )
-               __field(        long,                   value_usec      )
+               __field(        long,                   value_nsec      )
                __field(        long,                   interval_sec    )
-               __field(        long,                   interval_usec   )
+               __field(        long,                   interval_nsec   )
        ),
  
        TP_fast_assign(
                __entry->which          = which;
                __entry->expires        = expires;
                __entry->value_sec      = value->it_value.tv_sec;
-               __entry->value_usec     = value->it_value.tv_usec;
+               __entry->value_nsec     = value->it_value.tv_nsec;
                __entry->interval_sec   = value->it_interval.tv_sec;
-               __entry->interval_usec  = value->it_interval.tv_usec;
+               __entry->interval_nsec  = value->it_interval.tv_nsec;
        ),
  
-       TP_printk("which=%d expires=%llu it_value=%ld.%ld it_interval=%ld.%ld",
+       TP_printk("which=%d expires=%llu it_value=%ld.%06ld it_interval=%ld.%06ld",
                  __entry->which, __entry->expires,
-                 __entry->value_sec, __entry->value_usec,
-                 __entry->interval_sec, __entry->interval_usec)
+                 __entry->value_sec, __entry->value_nsec / NSEC_PER_USEC,
+                 __entry->interval_sec, __entry->interval_nsec / NSEC_PER_USEC)
  );
  
  /**
@@@ -367,8 -367,7 +367,8 @@@ TRACE_EVENT(itimer_expire
                tick_dep_name(POSIX_TIMER)              \
                tick_dep_name(PERF_EVENTS)              \
                tick_dep_name(SCHED)                    \
 -              tick_dep_name_end(CLOCK_UNSTABLE)
 +              tick_dep_name(CLOCK_UNSTABLE)           \
 +              tick_dep_name_end(RCU)
  
  #undef tick_dep_name
  #undef tick_dep_mask_name
@@@ -142,24 -142,10 +142,24 @@@ struct ppp_comp_stats 
  /*
   * The following structure records the time in seconds since
   * the last NP packet was sent or received.
 + *
 + * Linux implements both 32-bit and 64-bit time_t versions
 + * for compatibility with user space that defines ppp_idle
 + * based on the libc time_t.
   */
  struct ppp_idle {
-     __kernel_time_t xmit_idle;        /* time since last NP packet sent */
-     __kernel_time_t recv_idle;        /* time since last NP packet received */
+     __kernel_old_time_t xmit_idle;    /* time since last NP packet sent */
+     __kernel_old_time_t recv_idle;    /* time since last NP packet received */
  };
  
 +struct ppp_idle32 {
 +    __s32 xmit_idle;          /* time since last NP packet sent */
 +    __s32 recv_idle;          /* time since last NP packet received */
 +};
 +
 +struct ppp_idle64 {
 +    __s64 xmit_idle;          /* time since last NP packet sent */
 +    __s64 recv_idle;          /* time since last NP packet received */
 +};
 +
  #endif /* _UAPI_PPP_DEFS_H_ */
diff --combined net/ipv4/tcp.c
@@@ -1741,8 -1741,8 +1741,8 @@@ static int tcp_zerocopy_receive(struct 
                                struct tcp_zerocopy_receive *zc)
  {
        unsigned long address = (unsigned long)zc->address;
 +      u32 length = 0, seq, offset, zap_len;
        const skb_frag_t *frags = NULL;
 -      u32 length = 0, seq, offset;
        struct vm_area_struct *vma;
        struct sk_buff *skb = NULL;
        struct tcp_sock *tp;
        seq = tp->copied_seq;
        inq = tcp_inq(sk);
        zc->length = min_t(u32, zc->length, inq);
 -      zc->length &= ~(PAGE_SIZE - 1);
 -      if (zc->length) {
 -              zap_page_range(vma, address, zc->length);
 +      zap_len = zc->length & ~(PAGE_SIZE - 1);
 +      if (zap_len) {
 +              zap_page_range(vma, address, zap_len);
                zc->recv_skip_hint = 0;
        } else {
 -              zc->recv_skip_hint = inq;
 +              zc->recv_skip_hint = zc->length;
        }
        ret = 0;
        while (length + PAGE_SIZE <= zc->length) {
@@@ -1864,29 -1864,33 +1864,33 @@@ static void tcp_recv_timestamp(struct m
                if (sock_flag(sk, SOCK_RCVTSTAMP)) {
                        if (sock_flag(sk, SOCK_RCVTSTAMPNS)) {
                                if (new_tstamp) {
-                                       struct __kernel_timespec kts = {tss->ts[0].tv_sec, tss->ts[0].tv_nsec};
+                                       struct __kernel_timespec kts = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_nsec = tss->ts[0].tv_nsec,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
                                                 sizeof(kts), &kts);
                                } else {
-                                       struct timespec ts_old = timespec64_to_timespec(tss->ts[0]);
+                                       struct __kernel_old_timespec ts_old = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_nsec = tss->ts[0].tv_nsec,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
                                                 sizeof(ts_old), &ts_old);
                                }
                        } else {
                                if (new_tstamp) {
-                                       struct __kernel_sock_timeval stv;
-                                       stv.tv_sec = tss->ts[0].tv_sec;
-                                       stv.tv_usec = tss->ts[0].tv_nsec / 1000;
+                                       struct __kernel_sock_timeval stv = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_usec = tss->ts[0].tv_nsec / 1000,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
                                                 sizeof(stv), &stv);
                                } else {
-                                       struct __kernel_old_timeval tv;
-                                       tv.tv_sec = tss->ts[0].tv_sec;
-                                       tv.tv_usec = tss->ts[0].tv_nsec / 1000;
+                                       struct __kernel_old_timeval tv = {
+                                               .tv_sec = tss->ts[0].tv_sec,
+                                               .tv_usec = tss->ts[0].tv_nsec / 1000,
+                                       };
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
                                                 sizeof(tv), &tv);
                                }
@@@ -1958,7 -1962,8 +1962,7 @@@ int tcp_recvmsg(struct sock *sk, struc
        struct sk_buff *skb, *last;
        u32 urg_hole = 0;
        struct scm_timestamping_internal tss;
 -      bool has_tss = false;
 -      bool has_cmsg;
 +      int cmsg_flags;
  
        if (unlikely(flags & MSG_ERRQUEUE))
                return inet_recv_error(sk, msg, len, addr_len);
        if (sk->sk_state == TCP_LISTEN)
                goto out;
  
 -      has_cmsg = tp->recvmsg_inq;
 +      cmsg_flags = tp->recvmsg_inq ? 1 : 0;
        timeo = sock_rcvtimeo(sk, nonblock);
  
        /* Urgent data needs to be handled specially. */
  
                /* Well, if we have backlog, try to process it now yet. */
  
 -              if (copied >= target && !sk->sk_backlog.tail)
 +              if (copied >= target && !READ_ONCE(sk->sk_backlog.tail))
                        break;
  
                if (copied) {
@@@ -2156,7 -2161,8 +2160,7 @@@ skip_copy
  
                if (TCP_SKB_CB(skb)->has_rxtstamp) {
                        tcp_update_recv_tstamps(skb, &tss);
 -                      has_tss = true;
 -                      has_cmsg = true;
 +                      cmsg_flags |= 2;
                }
                if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
                        goto found_fin_ok;
@@@ -2181,10 -2187,10 +2185,10 @@@ found_fin_ok
  
        release_sock(sk);
  
 -      if (has_cmsg) {
 -              if (has_tss)
 +      if (cmsg_flags) {
 +              if (cmsg_flags & 2)
                        tcp_recv_timestamp(msg, sk, &tss);
 -              if (tp->recvmsg_inq) {
 +              if (cmsg_flags & 1) {
                        inq = tcp_inq_hint(sk);
                        put_cmsg(msg, SOL_TCP, TCP_CM_INQ, sizeof(inq), &inq);
                }
@@@ -2664,7 -2670,6 +2668,7 @@@ int tcp_disconnect(struct sock *sk, in
        /* Clean up fastopen related fields */
        tcp_free_fastopen_req(tp);
        inet->defer_connect = 0;
 +      tp->fastopen_client_fail = 0;
  
        WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
  
@@@ -3223,8 -3228,8 +3227,8 @@@ void tcp_get_info(struct sock *sk, stru
                 * tcpi_unacked -> Number of children ready for accept()
                 * tcpi_sacked  -> max backlog
                 */
 -              info->tcpi_unacked = sk->sk_ack_backlog;
 -              info->tcpi_sacked = sk->sk_max_ack_backlog;
 +              info->tcpi_unacked = READ_ONCE(sk->sk_ack_backlog);
 +              info->tcpi_sacked = READ_ONCE(sk->sk_max_ack_backlog);
                return;
        }
  
        info->tcpi_reord_seen = tp->reord_seen;
        info->tcpi_rcv_ooopack = tp->rcv_ooopack;
        info->tcpi_snd_wnd = tp->snd_wnd;
 +      info->tcpi_fastopen_client_fail = tp->fastopen_client_fail;
        unlock_sock_fast(sk, slow);
  }
  EXPORT_SYMBOL_GPL(tcp_get_info);
diff --combined net/socket.c
  #include <linux/if_tun.h>
  #include <linux/ipv6_route.h>
  #include <linux/route.h>
 +#include <linux/termios.h>
  #include <linux/sockios.h>
  #include <net/busy_poll.h>
  #include <linux/errqueue.h>
@@@ -405,7 -404,6 +405,7 @@@ struct file *sock_alloc_file(struct soc
  
        sock->file = file;
        file->private_data = sock;
 +      stream_open(SOCK_INODE(sock), file);
        return file;
  }
  EXPORT_SYMBOL(sock_alloc_file);
@@@ -795,7 -793,7 +795,7 @@@ void __sock_recv_timestamp(struct msghd
                                put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
                                         sizeof(ts), &ts);
                        } else {
-                               struct timespec ts;
+                               struct __kernel_old_timespec ts;
  
                                skb_get_timestampns(skb, &ts);
                                put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
@@@ -1692,13 -1690,24 +1692,13 @@@ SYSCALL_DEFINE2(listen, int, fd, int, b
        return __sys_listen(fd, backlog);
  }
  
 -/*
 - *    For accept, we attempt to create a new socket, set up the link
 - *    with the client, wake up the client, then return the new
 - *    connected fd. We collect the address of the connector in kernel
 - *    space and move it to user at the very end. This is unclean because
 - *    we open the socket then return an error.
 - *
 - *    1003.1g adds the ability to recvmsg() to query connection pending
 - *    status to recvmsg. We need to add that support in a way thats
 - *    clean when we restructure accept also.
 - */
 -
 -int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
 -                int __user *upeer_addrlen, int flags)
 +int __sys_accept4_file(struct file *file, unsigned file_flags,
 +                     struct sockaddr __user *upeer_sockaddr,
 +                     int __user *upeer_addrlen, int flags)
  {
        struct socket *sock, *newsock;
        struct file *newfile;
 -      int err, len, newfd, fput_needed;
 +      int err, len, newfd;
        struct sockaddr_storage address;
  
        if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
        if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
                flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
  
 -      sock = sockfd_lookup_light(fd, &err, &fput_needed);
 +      sock = sock_from_file(file, &err);
        if (!sock)
                goto out;
  
        err = -ENFILE;
        newsock = sock_alloc();
        if (!newsock)
 -              goto out_put;
 +              goto out;
  
        newsock->type = sock->type;
        newsock->ops = sock->ops;
        if (unlikely(newfd < 0)) {
                err = newfd;
                sock_release(newsock);
 -              goto out_put;
 +              goto out;
        }
        newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
        if (IS_ERR(newfile)) {
                err = PTR_ERR(newfile);
                put_unused_fd(newfd);
 -              goto out_put;
 +              goto out;
        }
  
        err = security_socket_accept(sock, newsock);
        if (err)
                goto out_fd;
  
 -      err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
 +      err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags,
 +                                      false);
        if (err < 0)
                goto out_fd;
  
  
        fd_install(newfd, newfile);
        err = newfd;
 -
 -out_put:
 -      fput_light(sock->file, fput_needed);
  out:
        return err;
  out_fd:
        fput(newfile);
        put_unused_fd(newfd);
 -      goto out_put;
 +      goto out;
 +
 +}
 +
 +/*
 + *    For accept, we attempt to create a new socket, set up the link
 + *    with the client, wake up the client, then return the new
 + *    connected fd. We collect the address of the connector in kernel
 + *    space and move it to user at the very end. This is unclean because
 + *    we open the socket then return an error.
 + *
 + *    1003.1g adds the ability to recvmsg() to query connection pending
 + *    status to recvmsg. We need to add that support in a way thats
 + *    clean when we restructure accept also.
 + */
 +
 +int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
 +                int __user *upeer_addrlen, int flags)
 +{
 +      int ret = -EBADF;
 +      struct fd f;
 +
 +      f = fdget(fd);
 +      if (f.file) {
 +              ret = __sys_accept4_file(f.file, 0, upeer_sockaddr,
 +                                              upeer_addrlen, flags);
 +              if (f.flags)
 +                      fput(f.file);
 +      }
 +
 +      return ret;
  }
  
  SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
@@@ -1826,46 -1807,32 +1826,46 @@@ SYSCALL_DEFINE3(accept, int, fd, struc
   *    include the -EINPROGRESS status for such sockets.
   */
  
 -int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
 +int __sys_connect_file(struct file *file, struct sockaddr __user *uservaddr,
 +                     int addrlen, int file_flags)
  {
        struct socket *sock;
        struct sockaddr_storage address;
 -      int err, fput_needed;
 +      int err;
  
 -      sock = sockfd_lookup_light(fd, &err, &fput_needed);
 +      sock = sock_from_file(file, &err);
        if (!sock)
                goto out;
        err = move_addr_to_kernel(uservaddr, addrlen, &address);
        if (err < 0)
 -              goto out_put;
 +              goto out;
  
        err =
            security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
        if (err)
 -              goto out_put;
 +              goto out;
  
        err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
 -                               sock->file->f_flags);
 -out_put:
 -      fput_light(sock->file, fput_needed);
 +                               sock->file->f_flags | file_flags);
  out:
        return err;
  }
  
 +int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
 +{
 +      int ret = -EBADF;
 +      struct fd f;
 +
 +      f = fdget(fd);
 +      if (f.file) {
 +              ret = __sys_connect_file(f.file, uservaddr, addrlen, 0);
 +              if (f.flags)
 +                      fput(f.file);
 +      }
 +
 +      return ret;
 +}
 +
  SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
                int, addrlen)
  {
@@@ -2265,10 -2232,15 +2265,10 @@@ static int copy_msghdr_from_user(struc
        return err < 0 ? err : 0;
  }
  
 -static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 -                       struct msghdr *msg_sys, unsigned int flags,
 -                       struct used_address *used_address,
 -                       unsigned int allowed_msghdr_flags)
 +static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys,
 +                         unsigned int flags, struct used_address *used_address,
 +                         unsigned int allowed_msghdr_flags)
  {
 -      struct compat_msghdr __user *msg_compat =
 -          (struct compat_msghdr __user *)msg;
 -      struct sockaddr_storage address;
 -      struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
        unsigned char ctl[sizeof(struct cmsghdr) + 20]
                                __aligned(sizeof(__kernel_size_t));
        /* 20 is size of ipv6_pktinfo */
        int ctl_len;
        ssize_t err;
  
 -      msg_sys->msg_name = &address;
 -
 -      if (MSG_CMSG_COMPAT & flags)
 -              err = get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
 -      else
 -              err = copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
 -      if (err < 0)
 -              return err;
 -
        err = -ENOBUFS;
  
        if (msg_sys->msg_controllen > INT_MAX)
 -              goto out_freeiov;
 +              goto out;
        flags |= (msg_sys->msg_flags & allowed_msghdr_flags);
        ctl_len = msg_sys->msg_controllen;
        if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
                    cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
                                                     sizeof(ctl));
                if (err)
 -                      goto out_freeiov;
 +                      goto out;
                ctl_buf = msg_sys->msg_control;
                ctl_len = msg_sys->msg_controllen;
        } else if (ctl_len) {
                if (ctl_len > sizeof(ctl)) {
                        ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
                        if (ctl_buf == NULL)
 -                              goto out_freeiov;
 +                              goto out;
                }
                err = -EFAULT;
                /*
  out_freectl:
        if (ctl_buf != ctl)
                sock_kfree_s(sock->sk, ctl_buf, ctl_len);
 -out_freeiov:
 +out:
 +      return err;
 +}
 +
 +static int sendmsg_copy_msghdr(struct msghdr *msg,
 +                             struct user_msghdr __user *umsg, unsigned flags,
 +                             struct iovec **iov)
 +{
 +      int err;
 +
 +      if (flags & MSG_CMSG_COMPAT) {
 +              struct compat_msghdr __user *msg_compat;
 +
 +              msg_compat = (struct compat_msghdr __user *) umsg;
 +              err = get_compat_msghdr(msg, msg_compat, NULL, iov);
 +      } else {
 +              err = copy_msghdr_from_user(msg, umsg, NULL, iov);
 +      }
 +      if (err < 0)
 +              return err;
 +
 +      return 0;
 +}
 +
 +static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 +                       struct msghdr *msg_sys, unsigned int flags,
 +                       struct used_address *used_address,
 +                       unsigned int allowed_msghdr_flags)
 +{
 +      struct sockaddr_storage address;
 +      struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
 +      ssize_t err;
 +
 +      msg_sys->msg_name = &address;
 +
 +      err = sendmsg_copy_msghdr(msg_sys, msg, flags, &iov);
 +      if (err < 0)
 +              return err;
 +
 +      err = ____sys_sendmsg(sock, msg_sys, flags, used_address,
 +                              allowed_msghdr_flags);
        kfree(iov);
        return err;
  }
  /*
   *    BSD sendmsg interface
   */
 -long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
 +long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *umsg,
                        unsigned int flags)
  {
 -      struct msghdr msg_sys;
 +      struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
 +      struct sockaddr_storage address;
 +      struct msghdr msg = { .msg_name = &address };
 +      ssize_t err;
 +
 +      err = sendmsg_copy_msghdr(&msg, umsg, flags, &iov);
 +      if (err)
 +              return err;
 +      /* disallow ancillary data requests from this path */
 +      if (msg.msg_control || msg.msg_controllen) {
 +              err = -EINVAL;
 +              goto out;
 +      }
  
 -      return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
 +      err = ____sys_sendmsg(sock, &msg, flags, NULL, 0);
 +out:
 +      kfree(iov);
 +      return err;
  }
  
  long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
@@@ -2516,41 -2442,33 +2516,41 @@@ SYSCALL_DEFINE4(sendmmsg, int, fd, stru
        return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
  }
  
 -static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
 -                       struct msghdr *msg_sys, unsigned int flags, int nosec)
 +static int recvmsg_copy_msghdr(struct msghdr *msg,
 +                             struct user_msghdr __user *umsg, unsigned flags,
 +                             struct sockaddr __user **uaddr,
 +                             struct iovec **iov)
  {
 -      struct compat_msghdr __user *msg_compat =
 -          (struct compat_msghdr __user *)msg;
 -      struct iovec iovstack[UIO_FASTIOV];
 -      struct iovec *iov = iovstack;
 -      unsigned long cmsg_ptr;
 -      int len;
        ssize_t err;
  
 -      /* kernel mode address */
 -      struct sockaddr_storage addr;
 +      if (MSG_CMSG_COMPAT & flags) {
 +              struct compat_msghdr __user *msg_compat;
  
 -      /* user mode address pointers */
 -      struct sockaddr __user *uaddr;
 -      int __user *uaddr_len = COMPAT_NAMELEN(msg);
 -
 -      msg_sys->msg_name = &addr;
 -
 -      if (MSG_CMSG_COMPAT & flags)
 -              err = get_compat_msghdr(msg_sys, msg_compat, &uaddr, &iov);
 -      else
 -              err = copy_msghdr_from_user(msg_sys, msg, &uaddr, &iov);
 +              msg_compat = (struct compat_msghdr __user *) umsg;
 +              err = get_compat_msghdr(msg, msg_compat, uaddr, iov);
 +      } else {
 +              err = copy_msghdr_from_user(msg, umsg, uaddr, iov);
 +      }
        if (err < 0)
                return err;
  
 +      return 0;
 +}
 +
 +static int ____sys_recvmsg(struct socket *sock, struct msghdr *msg_sys,
 +                         struct user_msghdr __user *msg,
 +                         struct sockaddr __user *uaddr,
 +                         unsigned int flags, int nosec)
 +{
 +      struct compat_msghdr __user *msg_compat =
 +                                      (struct compat_msghdr __user *) msg;
 +      int __user *uaddr_len = COMPAT_NAMELEN(msg);
 +      struct sockaddr_storage addr;
 +      unsigned long cmsg_ptr;
 +      int len;
 +      ssize_t err;
 +
 +      msg_sys->msg_name = &addr;
        cmsg_ptr = (unsigned long)msg_sys->msg_control;
        msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
  
                flags |= MSG_DONTWAIT;
        err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, flags);
        if (err < 0)
 -              goto out_freeiov;
 +              goto out;
        len = err;
  
        if (uaddr != NULL) {
                                        msg_sys->msg_namelen, uaddr,
                                        uaddr_len);
                if (err < 0)
 -                      goto out_freeiov;
 +                      goto out;
        }
        err = __put_user((msg_sys->msg_flags & ~MSG_CMSG_COMPAT),
                         COMPAT_FLAGS(msg));
        if (err)
 -              goto out_freeiov;
 +              goto out;
        if (MSG_CMSG_COMPAT & flags)
                err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
                                 &msg_compat->msg_controllen);
                err = __put_user((unsigned long)msg_sys->msg_control - cmsg_ptr,
                                 &msg->msg_controllen);
        if (err)
 -              goto out_freeiov;
 +              goto out;
        err = len;
 +out:
 +      return err;
 +}
 +
 +static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
 +                       struct msghdr *msg_sys, unsigned int flags, int nosec)
 +{
 +      struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
 +      /* user mode address pointers */
 +      struct sockaddr __user *uaddr;
 +      ssize_t err;
  
 -out_freeiov:
 +      err = recvmsg_copy_msghdr(msg_sys, msg, flags, &uaddr, &iov);
 +      if (err < 0)
 +              return err;
 +
 +      err = ____sys_recvmsg(sock, msg_sys, msg, uaddr, flags, nosec);
        kfree(iov);
        return err;
  }
   *    BSD recvmsg interface
   */
  
 -long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
 +long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *umsg,
                        unsigned int flags)
  {
 -      struct msghdr msg_sys;
 +      struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
 +      struct sockaddr_storage address;
 +      struct msghdr msg = { .msg_name = &address };
 +      struct sockaddr __user *uaddr;
 +      ssize_t err;
  
 -      return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
 +      err = recvmsg_copy_msghdr(&msg, umsg, flags, &uaddr, &iov);
 +      if (err)
 +              return err;
 +      /* disallow ancillary data requests from this path */
 +      if (msg.msg_control || msg.msg_controllen) {
 +              err = -EINVAL;
 +              goto out;
 +      }
 +
 +      err = ____sys_recvmsg(sock, &msg, umsg, uaddr, flags, 0);
 +out:
 +      kfree(iov);
 +      return err;
  }
  
  long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
@@@ -2946,7 -2833,7 +2946,7 @@@ SYSCALL_DEFINE2(socketcall, int, call, 
                                    a[2], true);
                break;
        case SYS_RECVMMSG:
-               if (IS_ENABLED(CONFIG_64BIT) || !IS_ENABLED(CONFIG_64BIT_TIME))
+               if (IS_ENABLED(CONFIG_64BIT))
                        err = __sys_recvmmsg(a0, (struct mmsghdr __user *)a1,
                                             a[2], a[3],
                                             (struct __kernel_timespec __user *)a[4],
@@@ -3565,8 -3452,6 +3565,8 @@@ static int compat_sock_ioctl_trans(stru
        case SIOCSARP:
        case SIOCGARP:
        case SIOCDARP:
 +      case SIOCOUTQ:
 +      case SIOCOUTQNSD:
        case SIOCATMARK:
                return sock_do_ioctl(net, sock, cmd, arg);
        }
diff --combined security/selinux/hooks.c
@@@ -2549,9 -2549,8 +2549,8 @@@ static void selinux_bprm_committing_cre
  static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
  {
        const struct task_security_struct *tsec = selinux_cred(current_cred());
-       struct itimerval itimer;
        u32 osid, sid;
-       int rc, i;
+       int rc;
  
        osid = tsec->osid;
        sid = tsec->sid;
        rc = avc_has_perm(&selinux_state,
                          osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
        if (rc) {
-               if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
-                       memset(&itimer, 0, sizeof itimer);
-                       for (i = 0; i < 3; i++)
-                               do_setitimer(i, &itimer, NULL);
-               }
+               clear_itimer();
                spin_lock_irq(&current->sighand->siglock);
                if (!fatal_signal_pending(current)) {
                        flush_sigqueue(&current->pending);
@@@ -3144,9 -3140,6 +3140,9 @@@ static int selinux_inode_setxattr(struc
                return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
        }
  
 +      if (!selinux_state.initialized)
 +              return (inode_owner_or_capable(inode) ? 0 : -EPERM);
 +
        sbsec = inode->i_sb->s_security;
        if (!(sbsec->flags & SBLABEL_MNT))
                return -EOPNOTSUPP;
@@@ -3230,15 -3223,6 +3226,15 @@@ static void selinux_inode_post_setxattr
                return;
        }
  
 +      if (!selinux_state.initialized) {
 +              /* If we haven't even been initialized, then we can't validate
 +               * against a policy, so leave the label as invalid. It may
 +               * resolve to a valid label on the next revalidation try if
 +               * we've since initialized.
 +               */
 +              return;
 +      }
 +
        rc = security_context_to_sid_force(&selinux_state, value, size,
                                           &newsid);
        if (rc) {
@@@ -4635,8 -4619,8 +4631,8 @@@ static int selinux_socket_bind(struct s
  
                        inet_get_local_port_range(sock_net(sk), &low, &high);
  
 -                      if (snum < max(inet_prot_sock(sock_net(sk)), low) ||
 -                          snum > high) {
 +                      if (inet_port_requires_bind_service(sock_net(sk), snum) ||
 +                          snum < low || snum > high) {
                                err = sel_netport_sid(sk->sk_protocol,
                                                      snum, &sid);
                                if (err)
@@@ -6807,67 -6791,6 +6803,67 @@@ struct lsm_blob_sizes selinux_blob_size
        .lbs_msg_msg = sizeof(struct msg_security_struct),
  };
  
 +#ifdef CONFIG_PERF_EVENTS
 +static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
 +{
 +      u32 requested, sid = current_sid();
 +
 +      if (type == PERF_SECURITY_OPEN)
 +              requested = PERF_EVENT__OPEN;
 +      else if (type == PERF_SECURITY_CPU)
 +              requested = PERF_EVENT__CPU;
 +      else if (type == PERF_SECURITY_KERNEL)
 +              requested = PERF_EVENT__KERNEL;
 +      else if (type == PERF_SECURITY_TRACEPOINT)
 +              requested = PERF_EVENT__TRACEPOINT;
 +      else
 +              return -EINVAL;
 +
 +      return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT,
 +                          requested, NULL);
 +}
 +
 +static int selinux_perf_event_alloc(struct perf_event *event)
 +{
 +      struct perf_event_security_struct *perfsec;
 +
 +      perfsec = kzalloc(sizeof(*perfsec), GFP_KERNEL);
 +      if (!perfsec)
 +              return -ENOMEM;
 +
 +      perfsec->sid = current_sid();
 +      event->security = perfsec;
 +
 +      return 0;
 +}
 +
 +static void selinux_perf_event_free(struct perf_event *event)
 +{
 +      struct perf_event_security_struct *perfsec = event->security;
 +
 +      event->security = NULL;
 +      kfree(perfsec);
 +}
 +
 +static int selinux_perf_event_read(struct perf_event *event)
 +{
 +      struct perf_event_security_struct *perfsec = event->security;
 +      u32 sid = current_sid();
 +
 +      return avc_has_perm(&selinux_state, sid, perfsec->sid,
 +                          SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
 +}
 +
 +static int selinux_perf_event_write(struct perf_event *event)
 +{
 +      struct perf_event_security_struct *perfsec = event->security;
 +      u32 sid = current_sid();
 +
 +      return avc_has_perm(&selinux_state, sid, perfsec->sid,
 +                          SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
 +}
 +#endif
 +
  static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
        LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
        LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
        LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
  #endif
 +
 +#ifdef CONFIG_PERF_EVENTS
 +      LSM_HOOK_INIT(perf_event_open, selinux_perf_event_open),
 +      LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
 +      LSM_HOOK_INIT(perf_event_free, selinux_perf_event_free),
 +      LSM_HOOK_INIT(perf_event_read, selinux_perf_event_read),
 +      LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write),
 +#endif
  };
  
  static __init int selinux_init(void)