Hi Jim, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on linux/master] [also build test WARNING on linus/master v5.12-rc2 next-20210310] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Jim-Newsome/ptrace-Allow-other-threads-to-access-tracee/20210311-050039 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 144c79ef33536b4ecb4951e07dbc1f2b7fa99d32 config: x86_64-randconfig-s021-20210309 (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce: # apt-get install sparse # sparse version: v0.6.3-262-g5e674421-dirty # https://github.com/0day-ci/linux/commit/874466f21257b7eb31b17d2bdb19da3f365436d7 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Jim-Newsome/ptrace-Allow-other-threads-to-access-tracee/20210311-050039 git checkout 874466f21257b7eb31b17d2bdb19da3f365436d7 # save the attached .config to linux build tree make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot "sparse warnings: (new ones prefixed by >>)" >> kernel/ptrace.c:53:44: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct task_struct *p2 @@ got struct task_struct [noderef] __rcu *parent @@ kernel/ptrace.c:53:44: sparse: expected struct task_struct *p2 kernel/ptrace.c:53:44: sparse: got struct task_struct [noderef] __rcu *parent kernel/ptrace.c:72:23: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct task_struct [noderef] __rcu *parent @@ got struct task_struct *new_parent @@ kernel/ptrace.c:72:23: sparse: expected struct task_struct [noderef] __rcu *parent kernel/ptrace.c:72:23: sparse: got struct task_struct *new_parent kernel/ptrace.c:73:29: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct cred const [noderef] __rcu *ptracer_cred @@ got struct cred const * @@ kernel/ptrace.c:73:29: sparse: expected struct cred const [noderef] __rcu *ptracer_cred kernel/ptrace.c:73:29: sparse: got struct cred const * kernel/ptrace.c:127:18: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct cred const *old_cred @@ got struct cred const [noderef] __rcu *ptracer_cred @@ kernel/ptrace.c:127:18: sparse: expected struct cred const *old_cred kernel/ptrace.c:127:18: sparse: got struct cred const [noderef] __rcu *ptracer_cred kernel/ptrace.c:131:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:131:25: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:131:25: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:169:27: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:169:27: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:169:27: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:181:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:181:28: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:181:28: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:186:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:186:30: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:186:30: sparse: got struct spinlock [noderef] __rcu * >> kernel/ptrace.c:196:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct *p1 @@ got struct task_struct [noderef] __rcu *parent @@ kernel/ptrace.c:196:9: sparse: expected struct task_struct *p1 kernel/ptrace.c:196:9: sparse: got struct task_struct [noderef] __rcu *parent kernel/ptrace.c:202:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:202:28: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:202:28: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:209:30: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:209:30: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:209:30: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:241:53: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct *p1 @@ got struct task_struct [noderef] __rcu *parent @@ kernel/ptrace.c:241:53: sparse: expected struct task_struct *p1 kernel/ptrace.c:241:53: sparse: got struct task_struct [noderef] __rcu *parent kernel/ptrace.c:415:24: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:415:24: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:415:24: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:438:26: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:438:26: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:438:26: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:474:54: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct *parent @@ got struct task_struct [noderef] __rcu *parent @@ kernel/ptrace.c:474:54: sparse: expected struct task_struct *parent kernel/ptrace.c:474:54: sparse: got struct task_struct [noderef] __rcu *parent kernel/ptrace.c:482:53: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct task_struct *new_parent @@ got struct task_struct [noderef] __rcu *real_parent @@ kernel/ptrace.c:482:53: sparse: expected struct task_struct *new_parent kernel/ptrace.c:482:53: sparse: got struct task_struct [noderef] __rcu *real_parent kernel/ptrace.c:530:41: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct *p1 @@ got struct task_struct [noderef] __rcu *real_parent @@ kernel/ptrace.c:530:41: sparse: expected struct task_struct *p1 kernel/ptrace.c:530:41: sparse: got struct task_struct [noderef] __rcu *real_parent kernel/ptrace.c:532:50: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct sighand_struct *sigh @@ got struct sighand_struct [noderef] __rcu *sighand @@ kernel/ptrace.c:532:50: sparse: expected struct sighand_struct *sigh kernel/ptrace.c:532:50: sparse: got struct sighand_struct [noderef] __rcu *sighand kernel/ptrace.c:734:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:734:37: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:734:37: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:742:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:742:39: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:742:39: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:847:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:847:37: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:847:37: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:851:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:851:39: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:851:39: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:1081:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:1081:37: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:1081:37: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:1083:39: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ kernel/ptrace.c:1083:39: sparse: expected struct spinlock [usertype] *lock kernel/ptrace.c:1083:39: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:480:38: sparse: sparse: dereference of noderef expression kernel/ptrace.c: note: in included file (through include/linux/rcuwait.h, include/linux/percpu-rwsem.h, include/linux/fs.h, ...): include/linux/sched/signal.h:708:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ include/linux/sched/signal.h:708:37: sparse: expected struct spinlock [usertype] *lock include/linux/sched/signal.h:708:37: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:681:9: sparse: sparse: context imbalance in 'ptrace_getsiginfo' - different lock contexts for basic block include/linux/sched/signal.h:708:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ include/linux/sched/signal.h:708:37: sparse: expected struct spinlock [usertype] *lock include/linux/sched/signal.h:708:37: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:697:9: sparse: sparse: context imbalance in 'ptrace_setsiginfo' - different lock contexts for basic block kernel/ptrace.c:853:9: sparse: sparse: context imbalance in 'ptrace_resume' - different lock contexts for basic block include/linux/sched/signal.h:708:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ include/linux/sched/signal.h:708:37: sparse: expected struct spinlock [usertype] *lock include/linux/sched/signal.h:708:37: sparse: got struct spinlock [noderef] __rcu * include/linux/sched/signal.h:708:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct spinlock [usertype] *lock @@ got struct spinlock [noderef] __rcu * @@ include/linux/sched/signal.h:708:37: sparse: expected struct spinlock [usertype] *lock include/linux/sched/signal.h:708:37: sparse: got struct spinlock [noderef] __rcu * kernel/ptrace.c:1229:9: sparse: sparse: context imbalance in 'ptrace_request' - different lock contexts for basic block vim +53 kernel/ptrace.c 36 37 /* 38 * Access another process' address space via ptrace. 39 * Source/target buffer must be kernel space, 40 * Do not walk the page table directly, use get_user_pages 41 */ 42 int ptrace_access_vm(struct task_struct *tsk, unsigned long addr, 43 void *buf, int len, unsigned int gup_flags) 44 { 45 struct mm_struct *mm; 46 int ret; 47 48 mm = get_task_mm(tsk); 49 if (!mm) 50 return 0; 51 52 if (!tsk->ptrace || > 53 !same_thread_group(current, tsk->parent) || 54 ((get_dumpable(mm) != SUID_DUMP_USER) && 55 !ptracer_capable(tsk, mm->user_ns))) { 56 mmput(mm); 57 return 0; 58 } 59 60 ret = __access_remote_vm(mm, addr, buf, len, gup_flags); 61 mmput(mm); 62 63 return ret; 64 } 65 66 67 void __ptrace_link(struct task_struct *child, struct task_struct *new_parent, 68 const struct cred *ptracer_cred) 69 { 70 BUG_ON(!list_empty(&child->ptrace_entry)); 71 list_add(&child->ptrace_entry, &new_parent->ptraced); 72 child->parent = new_parent; 73 child->ptracer_cred = get_cred(ptracer_cred); 74 } 75 76 /* 77 * ptrace a task: make the debugger its new parent and 78 * move it to the ptrace list. 79 * 80 * Must be called with the tasklist lock write-held. 81 */ 82 static void ptrace_link(struct task_struct *child, struct task_struct *new_parent) 83 { 84 __ptrace_link(child, new_parent, current_cred()); 85 } 86 87 /** 88 * __ptrace_unlink - unlink ptracee and restore its execution state 89 * @child: ptracee to be unlinked 90 * 91 * Remove @child from the ptrace list, move it back to the original parent, 92 * and restore the execution state so that it conforms to the group stop 93 * state. 94 * 95 * Unlinking can happen via two paths - explicit PTRACE_DETACH or ptracer 96 * exiting. For PTRACE_DETACH, unless the ptracee has been killed between 97 * ptrace_check_attach() and here, it's guaranteed to be in TASK_TRACED. 98 * If the ptracer is exiting, the ptracee can be in any state. 99 * 100 * After detach, the ptracee should be in a state which conforms to the 101 * group stop. If the group is stopped or in the process of stopping, the 102 * ptracee should be put into TASK_STOPPED; otherwise, it should be woken 103 * up from TASK_TRACED. 104 * 105 * If the ptracee is in TASK_TRACED and needs to be moved to TASK_STOPPED, 106 * it goes through TRACED -> RUNNING -> STOPPED transition which is similar 107 * to but in the opposite direction of what happens while attaching to a 108 * stopped task. However, in this direction, the intermediate RUNNING 109 * state is not hidden even from the current ptracer and if it immediately 110 * re-attaches and performs a WNOHANG wait(2), it may fail. 111 * 112 * CONTEXT: 113 * write_lock_irq(tasklist_lock) 114 */ 115 void __ptrace_unlink(struct task_struct *child) 116 { 117 const struct cred *old_cred; 118 BUG_ON(!child->ptrace); 119 120 clear_task_syscall_work(child, SYSCALL_TRACE); 121 #if defined(CONFIG_GENERIC_ENTRY) || defined(TIF_SYSCALL_EMU) 122 clear_task_syscall_work(child, SYSCALL_EMU); 123 #endif 124 125 child->parent = child->real_parent; 126 list_del_init(&child->ptrace_entry); 127 old_cred = child->ptracer_cred; 128 child->ptracer_cred = NULL; 129 put_cred(old_cred); 130 131 spin_lock(&child->sighand->siglock); 132 child->ptrace = 0; 133 /* 134 * Clear all pending traps and TRAPPING. TRAPPING should be 135 * cleared regardless of JOBCTL_STOP_PENDING. Do it explicitly. 136 */ 137 task_clear_jobctl_pending(child, JOBCTL_TRAP_MASK); 138 task_clear_jobctl_trapping(child); 139 140 /* 141 * Reinstate JOBCTL_STOP_PENDING if group stop is in effect and 142 * @child isn't dead. 143 */ 144 if (!(child->flags & PF_EXITING) && 145 (child->signal->flags & SIGNAL_STOP_STOPPED || 146 child->signal->group_stop_count)) { 147 child->jobctl |= JOBCTL_STOP_PENDING; 148 149 /* 150 * This is only possible if this thread was cloned by the 151 * traced task running in the stopped group, set the signal 152 * for the future reports. 153 * FIXME: we should change ptrace_init_task() to handle this 154 * case. 155 */ 156 if (!(child->jobctl & JOBCTL_STOP_SIGMASK)) 157 child->jobctl |= SIGSTOP; 158 } 159 160 /* 161 * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick 162 * @child in the butt. Note that @resume should be used iff @child 163 * is in TASK_TRACED; otherwise, we might unduly disrupt 164 * TASK_KILLABLE sleeps. 165 */ 166 if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) 167 ptrace_signal_wake_up(child, true); 168 169 spin_unlock(&child->sighand->siglock); 170 } 171 172 /* Ensure that nothing can wake it up, even SIGKILL */ 173 static bool ptrace_freeze_traced(struct task_struct *task) 174 { 175 bool ret = false; 176 177 /* Lockless, nobody but us can set this flag */ 178 if (task->jobctl & JOBCTL_LISTENING) 179 return ret; 180 181 spin_lock_irq(&task->sighand->siglock); 182 if (task_is_traced(task) && !__fatal_signal_pending(task)) { 183 task->state = __TASK_TRACED; 184 ret = true; 185 } 186 spin_unlock_irq(&task->sighand->siglock); 187 188 return ret; 189 } 190 191 static void ptrace_unfreeze_traced(struct task_struct *task) 192 { 193 if (task->state != __TASK_TRACED) 194 return; 195 > 196 WARN_ON(!task->ptrace || !same_thread_group(task->parent, current)); 197 198 /* 199 * PTRACE_LISTEN can allow ptrace_trap_notify to wake us up remotely. 200 * Recheck state under the lock to close this race. 201 */ 202 spin_lock_irq(&task->sighand->siglock); 203 if (task->state == __TASK_TRACED) { 204 if (__fatal_signal_pending(task)) 205 wake_up_state(task, __TASK_TRACED); 206 else 207 task->state = TASK_TRACED; 208 } 209 spin_unlock_irq(&task->sighand->siglock); 210 } 211 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org