diff --git a/Makefile.rhelver b/Makefile.rhelver index e404ab0a6c..02a76d11dc 100644 --- a/Makefile.rhelver +++ b/Makefile.rhelver @@ -12,7 +12,7 @@ RHEL_MINOR = 10 # # Use this spot to avoid future merge conflicts. # Do not trim this comment. -RHEL_RELEASE = 553.124.1 +RHEL_RELEASE = 553.125.1 # # ZSTREAM diff --git a/include/linux/sched.h b/include/linux/sched.h index 4574fcc3a6..294408a5fa 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -864,6 +864,8 @@ struct task_struct { #ifdef CONFIG_PSI RH_KABI_FILL_HOLE(unsigned sched_psi_wake_requeue:1) #endif + /* Save user-dumpable when mm goes away */ + RH_KABI_FILL_HOLE(unsigned user_dumpable:1) /* Force alignment to the next boundary: */ unsigned :0; diff --git a/kernel/exit.c b/kernel/exit.c index aa693f2f02..03f93950e9 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -482,6 +482,7 @@ static void exit_mm(void) BUG_ON(mm != current->active_mm); /* more a memory barrier than a real lock */ task_lock(current); + current->user_dumpable = (get_dumpable(mm) == SUID_DUMP_USER); current->mm = NULL; mmap_read_unlock(mm); enter_lazy_tlb(mm, current); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index bcc8888fcb..0603d5f895 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -284,11 +284,24 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) return has_ns_capability(current, ns, CAP_SYS_PTRACE); } +static bool task_still_dumpable(struct task_struct *task, unsigned int mode) +{ + struct mm_struct *mm = task->mm; + if (mm) { + if (get_dumpable(mm) == SUID_DUMP_USER) + return true; + return ptrace_has_cap(mm->user_ns, mode); + } + + if (task->user_dumpable) + return true; + return ptrace_has_cap(&init_user_ns, mode); +} + /* Returns 0 on success, -errno on denial. */ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) { const struct cred *cred = current_cred(), *tcred; - struct mm_struct *mm; kuid_t caller_uid; kgid_t caller_gid; @@ -349,14 +362,8 @@ ok: * Pairs with a write barrier in commit_creds(). */ smp_rmb(); - mm = task->mm; - if (mm) { - if ((get_dumpable(mm) != SUID_DUMP_USER) && - !ptrace_has_cap(mm->user_ns, mode)) - return -EPERM; - } else if (!ptrace_has_cap(&init_user_ns, mode)) { + if (!task_still_dumpable(task, mode)) return -EPERM; - } return security_ptrace_access_check(task, mode); } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1cf7ff4257..8d4db21c38 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4352,7 +4352,8 @@ normal: skb_copy_from_linear_data_offset(head_skb, offset, skb_put(nskb, hsize), hsize); - skb_shinfo(nskb)->tx_flags |= skb_shinfo(head_skb)->tx_flags & + skb_shinfo(nskb)->tx_flags |= (skb_shinfo(head_skb)->tx_flags | + skb_shinfo(frag_skb)->tx_flags) & SKBTX_SHARED_FRAG; if (skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC)) @@ -4369,6 +4370,9 @@ normal: nfrags = skb_shinfo(list_skb)->nr_frags; frag = skb_shinfo(list_skb)->frags; frag_skb = list_skb; + + skb_shinfo(nskb)->tx_flags |= skb_shinfo(frag_skb)->tx_flags & SKBTX_SHARED_FRAG; + if (!skb_headlen(list_skb)) { BUG_ON(!nfrags); } else {