diff options
| -rw-r--r-- | include/linux/ptrace.h | 13 | ||||
| -rw-r--r-- | include/linux/sched.h | 3 | ||||
| -rw-r--r-- | kernel/exit.c | 2 | ||||
| -rw-r--r-- | kernel/ptrace.c | 17 |
4 files changed, 33 insertions, 2 deletions
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index a1147e5dd245..9178d5cc0b01 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
| @@ -189,6 +189,10 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) | |||
| 189 | child->ptrace = current->ptrace; | 189 | child->ptrace = current->ptrace; |
| 190 | __ptrace_link(child, current->parent); | 190 | __ptrace_link(child, current->parent); |
| 191 | } | 191 | } |
| 192 | |||
| 193 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
| 194 | atomic_set(&child->ptrace_bp_refcnt, 1); | ||
| 195 | #endif | ||
| 192 | } | 196 | } |
| 193 | 197 | ||
| 194 | /** | 198 | /** |
| @@ -350,6 +354,13 @@ extern int task_current_syscall(struct task_struct *target, long *callno, | |||
| 350 | unsigned long args[6], unsigned int maxargs, | 354 | unsigned long args[6], unsigned int maxargs, |
| 351 | unsigned long *sp, unsigned long *pc); | 355 | unsigned long *sp, unsigned long *pc); |
| 352 | 356 | ||
| 353 | #endif | 357 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
| 358 | extern int ptrace_get_breakpoints(struct task_struct *tsk); | ||
| 359 | extern void ptrace_put_breakpoints(struct task_struct *tsk); | ||
| 360 | #else | ||
| 361 | static inline void ptrace_put_breakpoints(struct task_struct *tsk) { } | ||
| 362 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
| 363 | |||
| 364 | #endif /* __KERNEL */ | ||
| 354 | 365 | ||
| 355 | #endif | 366 | #endif |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 18d63cea2848..781abd137673 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1537,6 +1537,9 @@ struct task_struct { | |||
| 1537 | unsigned long memsw_nr_pages; /* uncharged mem+swap usage */ | 1537 | unsigned long memsw_nr_pages; /* uncharged mem+swap usage */ |
| 1538 | } memcg_batch; | 1538 | } memcg_batch; |
| 1539 | #endif | 1539 | #endif |
| 1540 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
| 1541 | atomic_t ptrace_bp_refcnt; | ||
| 1542 | #endif | ||
| 1540 | }; | 1543 | }; |
| 1541 | 1544 | ||
| 1542 | /* Future-safe accessor for struct task_struct's cpus_allowed. */ | 1545 | /* Future-safe accessor for struct task_struct's cpus_allowed. */ |
diff --git a/kernel/exit.c b/kernel/exit.c index f5d2f63bae0b..8dd874181542 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -1016,7 +1016,7 @@ NORET_TYPE void do_exit(long code) | |||
| 1016 | /* | 1016 | /* |
| 1017 | * FIXME: do that only when needed, using sched_exit tracepoint | 1017 | * FIXME: do that only when needed, using sched_exit tracepoint |
| 1018 | */ | 1018 | */ |
| 1019 | flush_ptrace_hw_breakpoint(tsk); | 1019 | ptrace_put_breakpoints(tsk); |
| 1020 | 1020 | ||
| 1021 | exit_notify(tsk, group_dead); | 1021 | exit_notify(tsk, group_dead); |
| 1022 | #ifdef CONFIG_NUMA | 1022 | #ifdef CONFIG_NUMA |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 0fc1eed28d27..dc7ab65f3b36 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/syscalls.h> | 22 | #include <linux/syscalls.h> |
| 23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 24 | #include <linux/regset.h> | 24 | #include <linux/regset.h> |
| 25 | #include <linux/hw_breakpoint.h> | ||
| 25 | 26 | ||
| 26 | 27 | ||
| 27 | /* | 28 | /* |
| @@ -879,3 +880,19 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, | |||
| 879 | return ret; | 880 | return ret; |
| 880 | } | 881 | } |
| 881 | #endif /* CONFIG_COMPAT */ | 882 | #endif /* CONFIG_COMPAT */ |
| 883 | |||
| 884 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
| 885 | int ptrace_get_breakpoints(struct task_struct *tsk) | ||
| 886 | { | ||
| 887 | if (atomic_inc_not_zero(&tsk->ptrace_bp_refcnt)) | ||
| 888 | return 0; | ||
| 889 | |||
| 890 | return -1; | ||
| 891 | } | ||
| 892 | |||
| 893 | void ptrace_put_breakpoints(struct task_struct *tsk) | ||
| 894 | { | ||
| 895 | if (atomic_dec_and_test(&tsk->ptrace_bp_refcnt)) | ||
| 896 | flush_ptrace_hw_breakpoint(tsk); | ||
| 897 | } | ||
| 898 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
