unfortunately the kernel actually uses ptrace_access_check for more than just ptrace, and the LSM (and hence apparmor) is not given context as to where the check is coming from. The current full list that can trigger an apparmor ptrace check is below. We can discard any that are not using a variant of MODE_READ* the mostly likely candidate is reading proc files, but this is going to take some more sleuthing to trace the source operation. AppArmor will throw an EACCES so if we can setup a trace to catch that, it would be helpful in tacking this down. $ git grep security_ptrace_access_check include/linux/security.h:int security_ptrace_access_check(struct task_struct *child, unsigned int mode); include/linux/security.h:static inline int security_ptrace_access_check(struct task_struct *child, kernel/ptrace.c: return security_ptrace_access_check(task, mode); security/security.c:int security_ptrace_access_check(struct task_struct *child, unsigned int mode) jj@flux:~/linux-kernels/linux-2.6$ emacs kernel/ptrace.c & [4] 9110 jj@flux:~/linux-kernels/linux-2.6$ git grep ptrace_may_access Documentation/process/adding-syscalls.rst:``ptrace_may_access()``) so that only a calling process with the same Documentation/translations/it_IT/process/adding-syscalls.rst:la chiamata ``ptrace_may_access()``) di modo che solo un processo chiamante fs/proc/array.c: permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT); fs/proc/base.c: if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) fs/proc/base.c: if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) { fs/proc/base.c: allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); fs/proc/base.c: return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); fs/proc/base.c: if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) fs/proc/base.c: if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) fs/proc/base.c: if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { fs/proc/namespaces.c: if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { fs/proc/namespaces.c: if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { include/linux/ptrace.h: * ptrace_may_access - check whether the caller is permitted to access include/linux/ptrace.h:extern bool ptrace_may_access(struct task_struct *task, unsigned int mode); include/linux/sched/mm.h: * and ptrace_may_access with the mode parameter passed to it kernel/cred.c: * the credential change; otherwise, a __ptrace_may_access() kernel/cred.c: * Pairs with a read barrier in __ptrace_may_access(). kernel/events/core.c: if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) kernel/fork.c: !ptrace_may_access(task, mode)) { kernel/futex.c: if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) kernel/futex.c: if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) kernel/kcmp.c: if (!ptrace_may_access(task1, PTRACE_MODE_READ_REALCREDS) || kernel/kcmp.c: !ptrace_may_access(task2, PTRACE_MODE_READ_REALCREDS)) { kernel/ptrace.c:static int __ptrace_may_access(struct task_struct *task, unsigned int mode) kernel/ptrace.c:bool ptrace_may_access(struct task_struct *task, unsigned int mode) kernel/ptrace.c: err = __ptrace_may_access(task, mode); kernel/ptrace.c: retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS); kernel/seccomp.c: * equivalent (see ptrace_may_access), it is safe to mm/mempolicy.c: * Use the regular "ptrace_may_access()" checks. mm/mempolicy.c: if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) { mm/migrate.c: * process. Use the regular "ptrace_may_access()" checks. mm/migrate.c: if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) {