Replace the SUID_DUMP_DISABLE/USER/ROOT preprocessor constants with enum task_dumpable. Numeric values are preserved (kernel.suid_dumpable sysctl and prctl(PR_SET_DUMPABLE) ABI), so this is a pure rename with no behavioral change. Subsequent commits relocate dumpability onto a per-task structure where the enum type will allow stronger type-checking on the new API.
Unified · Split
| @@ -538,7 +538,7 @@ static int access_remote_tags(struct task_struct *tsk, unsigned long addr, · 537 unmodified lines | |||
| 538 | return -EPERM; | 538 | return -EPERM; |
| 539 | 539 | ||
| 540 | if (!tsk->ptrace || (current != tsk->parent) || | 540 | if (!tsk->ptrace || (current != tsk->parent) || |
| 541 | ((get_dumpable(mm) != SUID_DUMP_USER) && | 541 | ((get_dumpable(mm) != TASK_DUMPABLE_OWNER) && |
| 542 | !ptracer_capable(tsk, mm->user_ns))) { | 542 | !ptracer_capable(tsk, mm->user_ns))) { |
| 543 | mmput(mm); | 543 | mmput(mm); |
| 544 | return -EPERM; | 544 | return -EPERM; |
| @@ -873,7 +873,7 @@ static inline bool coredump_socket(struct core_name *cn, struct coredump_params · 872 unmodified lines | |||
| 873 | static inline bool coredump_force_suid_safe(const struct coredump_params *cprm) | 873 | static inline bool coredump_force_suid_safe(const struct coredump_params *cprm) |
| 874 | { | 874 | { |
| 875 | /* Require nonrelative corefile path and be extra careful. */ | 875 | /* Require nonrelative corefile path and be extra careful. */ |
| 876 | return __get_dumpable(cprm->mm_flags) == SUID_DUMP_ROOT; | 876 | return __get_dumpable(cprm->mm_flags) == TASK_DUMPABLE_ROOT; |
| 877 | } | 877 | } |
| 878 | 878 | ||
| 879 | static bool coredump_file(struct core_name *cn, struct coredump_params *cprm, | 879 | static bool coredump_file(struct core_name *cn, struct coredump_params *cprm, |
| @@ -1419,7 +1419,7 @@ EXPORT_SYMBOL(dump_align); · 539 unmodified lines | |||
| 1419 | 1419 | ||
| 1420 | void validate_coredump_safety(void) | 1420 | void validate_coredump_safety(void) |
| 1421 | { | 1421 | { |
| 1422 | if (suid_dumpable == SUID_DUMP_ROOT && | 1422 | if (suid_dumpable == TASK_DUMPABLE_ROOT && |
| 1423 | core_pattern[0] != '/' && core_pattern[0] != '|' && core_pattern[0] != '@') { | 1423 | core_pattern[0] != '/' && core_pattern[0] != '|' && core_pattern[0] != '@') { |
| 1424 | 1424 | ||
| 1425 | coredump_report_failure("Unsafe core_pattern used with fs.suid_dumpable=2: " | 1425 | coredump_report_failure("Unsafe core_pattern used with fs.suid_dumpable=2: " |
| @@ -1212,7 +1212,7 @@ int begin_new_exec(struct linux_binprm * bprm) · 1211 unmodified lines | |||
| 1212 | gid_eq(current_egid(), current_gid()))) | 1212 | gid_eq(current_egid(), current_gid()))) |
| 1213 | set_dumpable(current->mm, suid_dumpable); | 1213 | set_dumpable(current->mm, suid_dumpable); |
| 1214 | else | 1214 | else |
| 1215 | set_dumpable(current->mm, SUID_DUMP_USER); | 1215 | set_dumpable(current->mm, TASK_DUMPABLE_OWNER); |
| 1216 | 1216 | ||
| 1217 | perf_event_exec(); | 1217 | perf_event_exec(); |
| 1218 | 1218 | ||
| @@ -1261,7 +1261,7 @@ int begin_new_exec(struct linux_binprm * bprm) · 42 unmodified lines | |||
| 1261 | * wait until new credentials are committed | 1261 | * wait until new credentials are committed |
| 1262 | * by commit_creds() above | 1262 | * by commit_creds() above |
| 1263 | */ | 1263 | */ |
| 1264 | if (get_dumpable(me->mm) != SUID_DUMP_USER) | 1264 | if (get_dumpable(me->mm) != TASK_DUMPABLE_OWNER) |
| 1265 | perf_event_exit_task(me); | 1265 | perf_event_exit_task(me); |
| 1266 | /* | 1266 | /* |
| 1267 | * cred_guard_mutex must be held at least to this point to prevent | 1267 | * cred_guard_mutex must be held at least to this point to prevent |
| @@ -1906,11 +1906,11 @@ void set_binfmt(struct linux_binfmt *new) · 638 unmodified lines | |||
| 1906 | EXPORT_SYMBOL(set_binfmt); | 1906 | EXPORT_SYMBOL(set_binfmt); |
| 1907 | 1907 | ||
| 1908 | /* | 1908 | /* |
| 1909 | * set_dumpable stores three-value SUID_DUMP_* into mm->flags. | 1909 | * set_dumpable stores three-value TASK_DUMPABLE_* into mm->flags. |
| 1910 | */ | 1910 | */ |
| 1911 | void set_dumpable(struct mm_struct *mm, int value) | 1911 | void set_dumpable(struct mm_struct *mm, int value) |
| 1912 | { | 1912 | { |
| 1913 | if (WARN_ON((unsigned)value > SUID_DUMP_ROOT)) | 1913 | if (WARN_ON((unsigned)value > TASK_DUMPABLE_ROOT)) |
| 1914 | return; | 1914 | return; |
| 1915 | 1915 | ||
| 1916 | __mm_flags_set_mask_dumpable(mm, value); | 1916 | __mm_flags_set_mask_dumpable(mm, value); |
| @@ -341,11 +341,11 @@ static inline bool pid_in_current_pidns(const struct pid *pid) · 340 unmodified lines | |||
| 341 | static __u32 pidfs_coredump_mask(unsigned long mm_flags) | 341 | static __u32 pidfs_coredump_mask(unsigned long mm_flags) |
| 342 | { | 342 | { |
| 343 | switch (__get_dumpable(mm_flags)) { | 343 | switch (__get_dumpable(mm_flags)) { |
| 344 | case SUID_DUMP_USER: | 344 | case TASK_DUMPABLE_OWNER: |
| 345 | return PIDFD_COREDUMP_USER; | 345 | return PIDFD_COREDUMP_USER; |
| 346 | case SUID_DUMP_ROOT: | 346 | case TASK_DUMPABLE_ROOT: |
| 347 | return PIDFD_COREDUMP_ROOT; | 347 | return PIDFD_COREDUMP_ROOT; |
| 348 | case SUID_DUMP_DISABLE: | 348 | case TASK_DUMPABLE_OFF: |
| 349 | return PIDFD_COREDUMP_SKIP; | 349 | return PIDFD_COREDUMP_SKIP; |
| 350 | default: | 350 | default: |
| 351 | WARN_ON_ONCE(true); | 351 | WARN_ON_ONCE(true); |
| @@ -1909,7 +1909,7 @@ void task_dump_owner(struct task_struct *task, umode_t mode, · 1908 unmodified lines | |||
| 1909 | mm = task->mm; | 1909 | mm = task->mm; |
| 1910 | /* Make non-dumpable tasks owned by some root */ | 1910 | /* Make non-dumpable tasks owned by some root */ |
| 1911 | if (mm) { | 1911 | if (mm) { |
| 1912 | if (get_dumpable(mm) != SUID_DUMP_USER) { | 1912 | if (get_dumpable(mm) != TASK_DUMPABLE_OWNER) { |
| 1913 | struct user_namespace *user_ns = mm->user_ns; | 1913 | struct user_namespace *user_ns = mm->user_ns; |
| 1914 | 1914 | ||
| 1915 | uid = make_kuid(user_ns, 0); | 1915 | uid = make_kuid(user_ns, 0); |
| @@ -1908,7 +1908,7 @@ enum { · 1907 unmodified lines | |||
| 1908 | 1908 | ||
| 1909 | /* | 1909 | /* |
| 1910 | * The first two bits represent core dump modes for set-user-ID, | 1910 | * The first two bits represent core dump modes for set-user-ID, |
| 1911 | * the modes are SUID_DUMP_* defined in linux/sched/coredump.h | 1911 | * the modes are TASK_DUMPABLE_* defined in linux/sched/coredump.h |
| 1912 | */ | 1912 | */ |
| 1913 | #define MMF_DUMPABLE_BITS 2 | 1913 | #define MMF_DUMPABLE_BITS 2 |
| 1914 | #define MMF_DUMPABLE_MASK (BIT(MMF_DUMPABLE_BITS) - 1) | 1914 | #define MMF_DUMPABLE_MASK (BIT(MMF_DUMPABLE_BITS) - 1) |
| @@ -4,9 +4,16 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <linux/mm_types.h> | 5 | #include <linux/mm_types.h> |
| 6 | 6 | ||
| 7 | #define SUID_DUMP_DISABLE 0 /* No setuid dumping */ | 7 | /* |
| 8 | #define SUID_DUMP_USER 1 /* Dump as user of process */ | 8 | * Task dumpability mode. Gates core dump production and ptrace_attach() |
| 9 | #define SUID_DUMP_ROOT 2 /* Dump as root */ | 9 | * authorization. The numeric values are stable ABI (suid_dumpable |
| 10 | * sysctl, prctl(PR_SET_DUMPABLE)); do not renumber. | ||
| 11 | */ | ||
| 12 | enum task_dumpable { | ||
| 13 | TASK_DUMPABLE_OFF = 0, /* no dump; ptrace needs CAP_SYS_PTRACE */ | ||
| 14 | TASK_DUMPABLE_OWNER = 1, /* default; dump and ptrace by uid match */ | ||
| 15 | TASK_DUMPABLE_ROOT = 2, /* dump as root; ptrace needs CAP_SYS_PTRACE */ | ||
| 16 | }; | ||
| 10 | 17 | ||
| 11 | static inline unsigned long __mm_flags_get_dumpable(const struct mm_struct *mm) | 18 | static inline unsigned long __mm_flags_get_dumpable(const struct mm_struct *mm) |
| 12 | { | 19 | { |
| @@ -26,7 +33,7 @@ extern void set_dumpable(struct mm_struct *mm, int value); · 13 unmodified lines | |||
| 26 | /* | 33 | /* |
| 27 | * This returns the actual value of the suid_dumpable flag. For things | 34 | * This returns the actual value of the suid_dumpable flag. For things |
| 28 | * that are using this for checking for privilege transitions, it must | 35 | * that are using this for checking for privilege transitions, it must |
| 29 | * test against SUID_DUMP_USER rather than treating it as a boolean | 36 | * test against TASK_DUMPABLE_OWNER rather than treating it as a boolean |
| 30 | * value. | 37 | * value. |
| 31 | */ | 38 | */ |
| 32 | static inline int __get_dumpable(unsigned long mm_flags) | 39 | static inline int __get_dumpable(unsigned long mm_flags) |
| @@ -571,7 +571,7 @@ static void exit_mm(void) · 570 unmodified lines | |||
| 571 | */ | 571 | */ |
| 572 | smp_mb__after_spinlock(); | 572 | smp_mb__after_spinlock(); |
| 573 | local_irq_disable(); | 573 | local_irq_disable(); |
| 574 | current->user_dumpable = (get_dumpable(mm) == SUID_DUMP_USER); | 574 | current->user_dumpable = (get_dumpable(mm) == TASK_DUMPABLE_OWNER); |
| 575 | current->mm = NULL; | 575 | current->mm = NULL; |
| 576 | membarrier_update_current_mm(NULL); | 576 | membarrier_update_current_mm(NULL); |
| 577 | enter_lazy_tlb(mm, current); | 577 | enter_lazy_tlb(mm, current); |
| @@ -53,7 +53,7 @@ int ptrace_access_vm(struct task_struct *tsk, unsigned long addr, · 52 unmodified lines | |||
| 53 | 53 | ||
| 54 | if (!tsk->ptrace || | 54 | if (!tsk->ptrace || |
| 55 | (current != tsk->parent) || | 55 | (current != tsk->parent) || |
| 56 | ((get_dumpable(mm) != SUID_DUMP_USER) && | 56 | ((get_dumpable(mm) != TASK_DUMPABLE_OWNER) && |
| 57 | !ptracer_capable(tsk, mm->user_ns))) { | 57 | !ptracer_capable(tsk, mm->user_ns))) { |
| 58 | mmput(mm); | 58 | mmput(mm); |
| 59 | return 0; | 59 | return 0; |
| @@ -276,7 +276,7 @@ static bool task_still_dumpable(struct task_struct *task, unsigned int mode) · 216 unmodified lines | |||
| 276 | { | 276 | { |
| 277 | struct mm_struct *mm = task->mm; | 277 | struct mm_struct *mm = task->mm; |
| 278 | if (mm) { | 278 | if (mm) { |
| 279 | if (get_dumpable(mm) == SUID_DUMP_USER) | 279 | if (get_dumpable(mm) == TASK_DUMPABLE_OWNER) |
| 280 | return true; | 280 | return true; |
| 281 | return ptrace_has_cap(mm->user_ns, mode); | 281 | return ptrace_has_cap(mm->user_ns, mode); |
| 282 | } | 282 | } |
| @@ -2568,7 +2568,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, · 2567 unmodified lines | |||
| 2568 | error = get_dumpable(me->mm); | 2568 | error = get_dumpable(me->mm); |
| 2569 | break; | 2569 | break; |
| 2570 | case PR_SET_DUMPABLE: | 2570 | case PR_SET_DUMPABLE: |
| 2571 | if (arg2 != SUID_DUMP_DISABLE && arg2 != SUID_DUMP_USER) { | 2571 | if (arg2 != TASK_DUMPABLE_OFF && arg2 != TASK_DUMPABLE_OWNER) { |
| 2572 | error = -EINVAL; | 2572 | error = -EINVAL; |
| 2573 | break; | 2573 | break; |
| 2574 | } | 2574 | } |