Message ID | 20230622150331.1242706-1-linma@zju.edu.cn (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [v2] net: nfc: Fix use-after-free caused by nfc_llcp_find_local | expand |
Hi Lin, kernel test robot noticed the following build warnings: [auto build test WARNING on net/main] [also build test WARNING on net-next/main linus/master horms-ipvs/master v6.4-rc7 next-20230622] [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#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Lin-Ma/net-nfc-Fix-use-after-free-caused-by-nfc_llcp_find_local/20230622-230631 base: net/main patch link: https://lore.kernel.org/r/20230622150331.1242706-1-linma%40zju.edu.cn patch subject: [PATCH v2] net: nfc: Fix use-after-free caused by nfc_llcp_find_local config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20230623/202306230247.UPcyNhPl-lkp@intel.com/config) compiler: alpha-linux-gcc (GCC) 12.3.0 reproduce: (https://download.01.org/0day-ci/archive/20230623/202306230247.UPcyNhPl-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202306230247.UPcyNhPl-lkp@intel.com/ All warnings (new ones prefixed by >>): >> net/nfc/llcp_core.c:146:24: warning: no previous prototype for 'nfc_llcp_local_get' [-Wmissing-prototypes] 146 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ^~~~~~~~~~~~~~~~~~ >> net/nfc/llcp_core.c:299:24: warning: no previous prototype for 'nfc_llcp_remove_local' [-Wmissing-prototypes] 299 | struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) | ^~~~~~~~~~~~~~~~~~~~~ vim +/nfc_llcp_local_get +146 net/nfc/llcp_core.c d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 145 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 @146 struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 147 { c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 148 kref_get(&local->ref); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 149 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 150 return local; c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 151 } c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 152 c470e319b48bf1 net/nfc/llcp/llcp.c Samuel Ortiz 2013-04-03 153 static void local_cleanup(struct nfc_llcp_local *local) c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 154 { c470e319b48bf1 net/nfc/llcp/llcp.c Samuel Ortiz 2013-04-03 155 nfc_llcp_socket_release(local, false, ENXIO); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 156 del_timer_sync(&local->link_timer); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 157 skb_queue_purge(&local->tx_queue); 474fee3db16c63 net/nfc/llcp/llcp.c Tejun Heo 2012-08-22 158 cancel_work_sync(&local->tx_work); 474fee3db16c63 net/nfc/llcp/llcp.c Tejun Heo 2012-08-22 159 cancel_work_sync(&local->rx_work); 474fee3db16c63 net/nfc/llcp/llcp.c Tejun Heo 2012-08-22 160 cancel_work_sync(&local->timeout_work); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 161 kfree_skb(local->rx_pending); 4bb4db7f3187c6 net/nfc/llcp_core.c Jisoo Jang 2023-01-11 162 local->rx_pending = NULL; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 163 del_timer_sync(&local->sdreq_timer); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 164 cancel_work_sync(&local->sdreq_timeout_work); d9b8d8e19b0730 net/nfc/llcp/llcp.c Thierry Escande 2013-02-15 165 nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 166 } 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 167 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 168 static void local_release(struct kref *ref) 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 169 { 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 170 struct nfc_llcp_local *local; 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 171 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 172 local = container_of(ref, struct nfc_llcp_local, ref); 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 173 c470e319b48bf1 net/nfc/llcp/llcp.c Samuel Ortiz 2013-04-03 174 local_cleanup(local); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 175 kfree(local); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 176 } c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 177 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 178 int nfc_llcp_local_put(struct nfc_llcp_local *local) c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 179 { a69f32af86e389 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 180 if (local == NULL) a69f32af86e389 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 181 return 0; a69f32af86e389 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 182 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 183 return kref_put(&local->ref, local_release); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 184 } c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 185 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 186 static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 187 u8 ssap, u8 dsap) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 188 { 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 189 struct sock *sk; a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 190 struct nfc_llcp_sock *llcp_sock, *tmp_sock; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 191 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 192 pr_debug("ssap dsap %d %d\n", ssap, dsap); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 193 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 194 if (ssap == 0 && dsap == 0) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 195 return NULL; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 196 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 197 read_lock(&local->sockets.lock); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 198 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 199 llcp_sock = NULL; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 200 b67bfe0d42cac5 net/nfc/llcp/llcp.c Sasha Levin 2013-02-27 201 sk_for_each(sk, &local->sockets.head) { a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 202 tmp_sock = nfc_llcp_sock(sk); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 203 a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 204 if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) { a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 205 llcp_sock = tmp_sock; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 206 break; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 207 } a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 208 } 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 209 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 210 read_unlock(&local->sockets.lock); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 211 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 212 if (llcp_sock == NULL) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 213 return NULL; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 214 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 215 sock_hold(&llcp_sock->sk); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 216 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 217 return llcp_sock; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 218 } 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 219 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 220 static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 221 { 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 222 sock_put(&sock->sk); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 223 } 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 224 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 225 static void nfc_llcp_timeout_work(struct work_struct *work) d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 226 { d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 227 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 228 timeout_work); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 229 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 230 nfc_dep_link_down(local->dev); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 231 } d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 232 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 233 static void nfc_llcp_symm_timer(struct timer_list *t) d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 234 { 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 235 struct nfc_llcp_local *local = from_timer(local, t, link_timer); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 236 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 237 pr_err("SYMM timeout\n"); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 238 916082b073ebb7 net/nfc/llcp/llcp.c Linus Torvalds 2012-10-02 239 schedule_work(&local->timeout_work); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 240 } d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 241 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 242 static void nfc_llcp_sdreq_timeout_work(struct work_struct *work) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 243 { 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 244 unsigned long time; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 245 HLIST_HEAD(nl_sdres_list); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 246 struct hlist_node *n; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 247 struct nfc_llcp_sdp_tlv *sdp; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 248 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 249 sdreq_timeout_work); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 250 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 251 mutex_lock(&local->sdreq_lock); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 252 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 253 time = jiffies - msecs_to_jiffies(3 * local->remote_lto); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 254 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 255 hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) { 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 256 if (time_after(sdp->time, time)) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 257 continue; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 258 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 259 sdp->sap = LLCP_SDP_UNBOUND; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 260 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 261 hlist_del(&sdp->node); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 262 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 263 hlist_add_head(&sdp->node, &nl_sdres_list); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 264 } 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 265 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 266 if (!hlist_empty(&local->pending_sdreqs)) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 267 mod_timer(&local->sdreq_timer, 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 268 jiffies + msecs_to_jiffies(3 * local->remote_lto)); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 269 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 270 mutex_unlock(&local->sdreq_lock); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 271 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 272 if (!hlist_empty(&nl_sdres_list)) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 273 nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 274 } 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 275 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 276 static void nfc_llcp_sdreq_timer(struct timer_list *t) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 277 { 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 278 struct nfc_llcp_local *local = from_timer(local, t, sdreq_timer); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 279 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 280 schedule_work(&local->sdreq_timeout_work); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 281 } 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 282 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 283 struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 284 { 29e27dd86b5c4f net/nfc/llcp_core.c Axel Lin 2014-02-26 285 struct nfc_llcp_local *local; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 286 struct nfc_llcp_local *res = NULL; d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 287 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 288 spin_lock(&llcp_devices_lock); 29e27dd86b5c4f net/nfc/llcp_core.c Axel Lin 2014-02-26 289 list_for_each_entry(local, &llcp_devices, list) 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 290 if (local->dev == dev) { 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 291 res = nfc_llcp_local_get(local); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 292 break; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 293 } 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 294 spin_unlock(&llcp_devices_lock); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 295 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 296 return res; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 297 } 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 298 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 @299 struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 300 { 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 301 struct nfc_llcp_local *local, *tmp; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 302 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 303 spin_lock(&llcp_devices_lock); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 304 list_for_each_entry_safe(local, tmp, &llcp_devices, list) 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 305 if (local->dev == dev) { 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 306 list_del(&local->list); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 307 spin_unlock(&llcp_devices_lock); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 308 return local; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 309 } 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 310 spin_unlock(&llcp_devices_lock); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 311 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 312 pr_warn("Shutting down device not found\n"); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 313 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 314 return NULL; d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 315 } d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 316
Hi Lin, kernel test robot noticed the following build warnings: [auto build test WARNING on net/main] [also build test WARNING on net-next/main linus/master horms-ipvs/master v6.4-rc7 next-20230622] [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#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Lin-Ma/net-nfc-Fix-use-after-free-caused-by-nfc_llcp_find_local/20230622-230631 base: net/main patch link: https://lore.kernel.org/r/20230622150331.1242706-1-linma%40zju.edu.cn patch subject: [PATCH v2] net: nfc: Fix use-after-free caused by nfc_llcp_find_local config: s390-randconfig-r036-20230622 (https://download.01.org/0day-ci/archive/20230623/202306230631.Pk3BN4Kg-lkp@intel.com/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a) reproduce: (https://download.01.org/0day-ci/archive/20230623/202306230631.Pk3BN4Kg-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202306230631.Pk3BN4Kg-lkp@intel.com/ All warnings (new ones prefixed by >>): In file included from net/nfc/llcp_core.c:14: In file included from net/nfc/nfc.h:13: In file included from include/net/nfc/nfc.h:16: In file included from include/linux/skbuff.h:28: In file included from include/linux/dma-mapping.h:10: In file included from include/linux/scatterlist.h:9: In file included from arch/s390/include/asm/io.h:75: include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 547 | val = __raw_readb(PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 560 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr)); | ~~~~~~~~~~ ^ include/uapi/linux/byteorder/big_endian.h:37:59: note: expanded from macro '__le16_to_cpu' 37 | #define __le16_to_cpu(x) __swab16((__force __u16)(__le16)(x)) | ^ include/uapi/linux/swab.h:102:54: note: expanded from macro '__swab16' 102 | #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x)) | ^ In file included from net/nfc/llcp_core.c:14: In file included from net/nfc/nfc.h:13: In file included from include/net/nfc/nfc.h:16: In file included from include/linux/skbuff.h:28: In file included from include/linux/dma-mapping.h:10: In file included from include/linux/scatterlist.h:9: In file included from arch/s390/include/asm/io.h:75: include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 573 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr)); | ~~~~~~~~~~ ^ include/uapi/linux/byteorder/big_endian.h:35:59: note: expanded from macro '__le32_to_cpu' 35 | #define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x)) | ^ include/uapi/linux/swab.h:115:54: note: expanded from macro '__swab32' 115 | #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x)) | ^ In file included from net/nfc/llcp_core.c:14: In file included from net/nfc/nfc.h:13: In file included from include/net/nfc/nfc.h:16: In file included from include/linux/skbuff.h:28: In file included from include/linux/dma-mapping.h:10: In file included from include/linux/scatterlist.h:9: In file included from arch/s390/include/asm/io.h:75: include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 584 | __raw_writeb(value, PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 594 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 604 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr); | ~~~~~~~~~~ ^ include/asm-generic/io.h:692:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 692 | readsb(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:700:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 700 | readsw(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:708:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 708 | readsl(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:717:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 717 | writesb(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:726:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 726 | writesw(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ include/asm-generic/io.h:735:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic] 735 | writesl(PCI_IOBASE + addr, buffer, count); | ~~~~~~~~~~ ^ >> net/nfc/llcp_core.c:146:24: warning: no previous prototype for function 'nfc_llcp_local_get' [-Wmissing-prototypes] 146 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ^ net/nfc/llcp_core.c:146:1: note: declare 'static' if the function is not intended to be used outside of this translation unit 146 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ^ | static >> net/nfc/llcp_core.c:299:24: warning: no previous prototype for function 'nfc_llcp_remove_local' [-Wmissing-prototypes] 299 | struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) | ^ net/nfc/llcp_core.c:299:1: note: declare 'static' if the function is not intended to be used outside of this translation unit 299 | struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) | ^ | static 14 warnings generated. vim +/nfc_llcp_local_get +146 net/nfc/llcp_core.c d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 145 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 @146 struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 147 { c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 148 kref_get(&local->ref); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 149 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 150 return local; c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 151 } c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 152 c470e319b48bf1 net/nfc/llcp/llcp.c Samuel Ortiz 2013-04-03 153 static void local_cleanup(struct nfc_llcp_local *local) c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 154 { c470e319b48bf1 net/nfc/llcp/llcp.c Samuel Ortiz 2013-04-03 155 nfc_llcp_socket_release(local, false, ENXIO); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 156 del_timer_sync(&local->link_timer); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 157 skb_queue_purge(&local->tx_queue); 474fee3db16c63 net/nfc/llcp/llcp.c Tejun Heo 2012-08-22 158 cancel_work_sync(&local->tx_work); 474fee3db16c63 net/nfc/llcp/llcp.c Tejun Heo 2012-08-22 159 cancel_work_sync(&local->rx_work); 474fee3db16c63 net/nfc/llcp/llcp.c Tejun Heo 2012-08-22 160 cancel_work_sync(&local->timeout_work); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 161 kfree_skb(local->rx_pending); 4bb4db7f3187c6 net/nfc/llcp_core.c Jisoo Jang 2023-01-11 162 local->rx_pending = NULL; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 163 del_timer_sync(&local->sdreq_timer); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 164 cancel_work_sync(&local->sdreq_timeout_work); d9b8d8e19b0730 net/nfc/llcp/llcp.c Thierry Escande 2013-02-15 165 nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 166 } 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 167 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 168 static void local_release(struct kref *ref) 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 169 { 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 170 struct nfc_llcp_local *local; 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 171 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 172 local = container_of(ref, struct nfc_llcp_local, ref); 3536da06db0baa net/nfc/llcp/llcp.c Samuel Ortiz 2013-02-21 173 c470e319b48bf1 net/nfc/llcp/llcp.c Samuel Ortiz 2013-04-03 174 local_cleanup(local); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 175 kfree(local); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 176 } c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 177 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 178 int nfc_llcp_local_put(struct nfc_llcp_local *local) c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 179 { a69f32af86e389 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 180 if (local == NULL) a69f32af86e389 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 181 return 0; a69f32af86e389 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 182 c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 183 return kref_put(&local->ref, local_release); c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 184 } c7aa12252f5142 net/nfc/llcp/llcp.c Samuel Ortiz 2012-05-04 185 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 186 static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 187 u8 ssap, u8 dsap) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 188 { 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 189 struct sock *sk; a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 190 struct nfc_llcp_sock *llcp_sock, *tmp_sock; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 191 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 192 pr_debug("ssap dsap %d %d\n", ssap, dsap); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 193 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 194 if (ssap == 0 && dsap == 0) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 195 return NULL; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 196 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 197 read_lock(&local->sockets.lock); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 198 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 199 llcp_sock = NULL; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 200 b67bfe0d42cac5 net/nfc/llcp/llcp.c Sasha Levin 2013-02-27 201 sk_for_each(sk, &local->sockets.head) { a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 202 tmp_sock = nfc_llcp_sock(sk); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 203 a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 204 if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) { a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 205 llcp_sock = tmp_sock; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 206 break; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 207 } a8df0f379213f1 net/nfc/llcp/llcp.c Samuel Ortiz 2012-10-16 208 } 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 209 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 210 read_unlock(&local->sockets.lock); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 211 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 212 if (llcp_sock == NULL) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 213 return NULL; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 214 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 215 sock_hold(&llcp_sock->sk); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 216 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 217 return llcp_sock; 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 218 } 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 219 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 220 static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 221 { 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 222 sock_put(&sock->sk); 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 223 } 8f50020ed9b81b net/nfc/llcp/llcp.c Samuel Ortiz 2012-06-25 224 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 225 static void nfc_llcp_timeout_work(struct work_struct *work) d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 226 { d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 227 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 228 timeout_work); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 229 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 230 nfc_dep_link_down(local->dev); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 231 } d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 232 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 233 static void nfc_llcp_symm_timer(struct timer_list *t) d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 234 { 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 235 struct nfc_llcp_local *local = from_timer(local, t, link_timer); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 236 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 237 pr_err("SYMM timeout\n"); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 238 916082b073ebb7 net/nfc/llcp/llcp.c Linus Torvalds 2012-10-02 239 schedule_work(&local->timeout_work); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 240 } d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 241 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 242 static void nfc_llcp_sdreq_timeout_work(struct work_struct *work) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 243 { 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 244 unsigned long time; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 245 HLIST_HEAD(nl_sdres_list); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 246 struct hlist_node *n; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 247 struct nfc_llcp_sdp_tlv *sdp; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 248 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 249 sdreq_timeout_work); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 250 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 251 mutex_lock(&local->sdreq_lock); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 252 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 253 time = jiffies - msecs_to_jiffies(3 * local->remote_lto); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 254 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 255 hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) { 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 256 if (time_after(sdp->time, time)) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 257 continue; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 258 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 259 sdp->sap = LLCP_SDP_UNBOUND; 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 260 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 261 hlist_del(&sdp->node); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 262 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 263 hlist_add_head(&sdp->node, &nl_sdres_list); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 264 } 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 265 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 266 if (!hlist_empty(&local->pending_sdreqs)) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 267 mod_timer(&local->sdreq_timer, 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 268 jiffies + msecs_to_jiffies(3 * local->remote_lto)); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 269 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 270 mutex_unlock(&local->sdreq_lock); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 271 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 272 if (!hlist_empty(&nl_sdres_list)) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 273 nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 274 } 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 275 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 276 static void nfc_llcp_sdreq_timer(struct timer_list *t) 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 277 { 4b519bb493e086 net/nfc/llcp_core.c Allen Pais 2017-10-11 278 struct nfc_llcp_local *local = from_timer(local, t, sdreq_timer); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 279 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 280 schedule_work(&local->sdreq_timeout_work); 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 281 } 40213fa8513c2a net/nfc/llcp/llcp.c Thierry Escande 2013-03-04 282 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 283 struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 284 { 29e27dd86b5c4f net/nfc/llcp_core.c Axel Lin 2014-02-26 285 struct nfc_llcp_local *local; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 286 struct nfc_llcp_local *res = NULL; d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 287 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 288 spin_lock(&llcp_devices_lock); 29e27dd86b5c4f net/nfc/llcp_core.c Axel Lin 2014-02-26 289 list_for_each_entry(local, &llcp_devices, list) 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 290 if (local->dev == dev) { 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 291 res = nfc_llcp_local_get(local); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 292 break; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 293 } 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 294 spin_unlock(&llcp_devices_lock); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 295 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 296 return res; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 297 } 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 298 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 @299 struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 300 { 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 301 struct nfc_llcp_local *local, *tmp; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 302 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 303 spin_lock(&llcp_devices_lock); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 304 list_for_each_entry_safe(local, tmp, &llcp_devices, list) 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 305 if (local->dev == dev) { 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 306 list_del(&local->list); 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 307 spin_unlock(&llcp_devices_lock); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 308 return local; 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 309 } 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 310 spin_unlock(&llcp_devices_lock); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 311 972f46a30da575 net/nfc/llcp_core.c Lin Ma 2023-06-22 312 pr_warn("Shutting down device not found\n"); d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 313 d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 314 return NULL; d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 315 } d646960f7986fe net/nfc/llcp/llcp.c Samuel Ortiz 2011-12-14 316
diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index c1d9be636933..d8345ed57c95 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -201,7 +201,6 @@ void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); -struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); int nfc_llcp_local_put(struct nfc_llcp_local *local); u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, struct nfc_llcp_sock *sock); diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c index 41e3a20c8935..5d2d4bc26ef9 100644 --- a/net/nfc/llcp_commands.c +++ b/net/nfc/llcp_commands.c @@ -359,6 +359,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) struct sk_buff *skb; struct nfc_llcp_local *local; u16 size = 0; + int err; local = nfc_llcp_find_local(dev); if (local == NULL) @@ -368,8 +369,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; skb = alloc_skb(size, GFP_KERNEL); - if (skb == NULL) - return -ENOMEM; + if (skb == NULL) { + err = -ENOMEM; + goto out; + } skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); @@ -379,8 +382,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX); - return nfc_data_exchange(dev, local->target_idx, skb, + err = nfc_data_exchange(dev, local->target_idx, skb, nfc_llcp_recv, local); +out: + nfc_llcp_local_put(local); + return err; } int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index a27e1842b2a0..34eea997318c 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -17,6 +17,8 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; static LIST_HEAD(llcp_devices); +/* Protects llcp_devices list */ +static DEFINE_SPINLOCK(llcp_devices_lock); static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); @@ -169,7 +171,6 @@ static void local_release(struct kref *ref) local = container_of(ref, struct nfc_llcp_local, ref); - list_del(&local->list); local_cleanup(local); kfree(local); } @@ -282,12 +283,33 @@ static void nfc_llcp_sdreq_timer(struct timer_list *t) struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) { struct nfc_llcp_local *local; + struct nfc_llcp_local *res = NULL; + spin_lock(&llcp_devices_lock); list_for_each_entry(local, &llcp_devices, list) - if (local->dev == dev) + if (local->dev == dev) { + res = nfc_llcp_local_get(local); + break; + } + spin_unlock(&llcp_devices_lock); + + return res; +} + +struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev) +{ + struct nfc_llcp_local *local, *tmp; + + spin_lock(&llcp_devices_lock); + list_for_each_entry_safe(local, tmp, &llcp_devices, list) + if (local->dev == dev) { + list_del(&local->list); + spin_unlock(&llcp_devices_lock); return local; + } + spin_unlock(&llcp_devices_lock); - pr_debug("No device found\n"); + pr_warn("Shutting down device not found\n"); return NULL; } @@ -608,12 +630,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) *general_bytes_len = local->gb_len; + nfc_llcp_local_put(local); + return local->gb; } int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len) { struct nfc_llcp_local *local; + int err; if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN) return -EINVAL; @@ -630,12 +655,16 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len) if (memcmp(local->remote_gb, llcp_magic, 3)) { pr_err("MAC does not support LLCP\n"); - return -EINVAL; + err = -EINVAL; + goto out; } - return nfc_llcp_parse_gb_tlv(local, + err = nfc_llcp_parse_gb_tlv(local, &local->remote_gb[3], local->remote_gb_len - 3); +out: + nfc_llcp_local_put(local); + return err; } static u8 nfc_llcp_dsap(const struct sk_buff *pdu) @@ -1517,6 +1546,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) __nfc_llcp_recv(local, skb); + nfc_llcp_local_put(local); + return 0; } @@ -1533,6 +1564,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) /* Close and purge all existing sockets */ nfc_llcp_socket_release(local, true, 0); + + nfc_llcp_local_put(local); } void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, @@ -1558,6 +1591,8 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, mod_timer(&local->link_timer, jiffies + msecs_to_jiffies(local->remote_lto)); } + + nfc_llcp_local_put(local); } int nfc_llcp_register_device(struct nfc_dev *ndev) @@ -1608,7 +1643,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) void nfc_llcp_unregister_device(struct nfc_dev *dev) { - struct nfc_llcp_local *local = nfc_llcp_find_local(dev); + struct nfc_llcp_local *local = nfc_llcp_remove_local(dev); if (local == NULL) { pr_debug("No such device\n"); diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 77642d18a3b4..fa6a9e455b53 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -99,7 +99,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->local = local; llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; llcp_sock->service_name_len = min_t(unsigned int, llcp_addr.service_name_len, @@ -186,7 +186,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr, } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->local = local; llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; nfc_llcp_sock_link(&local->raw_sockets, sk); @@ -696,20 +696,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, if (dev->dep_link_up == false) { ret = -ENOLINK; device_unlock(&dev->dev); - goto put_dev; + goto sock_llcp_put_local; } device_unlock(&dev->dev); if (local->rf_mode == NFC_RF_INITIATOR && addr->target_idx != local->target_idx) { ret = -ENOLINK; - goto put_dev; + goto sock_llcp_put_local; } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->local = local; llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { + llcp_sock->local = NULL; + llcp_sock->dev = NULL; ret = -ENOMEM; goto sock_llcp_put_local; } @@ -758,9 +760,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, nfc_llcp_put_ssap(local, llcp_sock->ssap); sock_llcp_put_local: - nfc_llcp_local_put(llcp_sock->local); - llcp_sock->local = NULL; - llcp_sock->dev = NULL; + nfc_llcp_local_put(local); put_dev: nfc_put_device(dev); diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index b9264e730fd9..e9ac6a6f934e 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -1039,11 +1039,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { rc = -ENOMEM; - goto exit; + goto put_local; } rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq); +put_local: + nfc_llcp_local_put(local); + exit: device_unlock(&dev->dev); @@ -1105,7 +1108,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) { if (dev->dep_link_up) { rc = -EINPROGRESS; - goto exit; + goto put_local; } local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]); @@ -1117,6 +1120,9 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX]) local->miux = cpu_to_be16(miux); +put_local: + nfc_llcp_local_put(local); + exit: device_unlock(&dev->dev); @@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) if (rc != 0) { rc = -EINVAL; - goto exit; + goto put_local; } if (!sdp_attrs[NFC_SDP_ATTR_URI]) @@ -1191,7 +1197,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len); if (sdreq == NULL) { rc = -ENOMEM; - goto exit; + goto put_local; } tlvs_len += sdreq->tlv_len; @@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) if (hlist_empty(&sdreq_list)) { rc = -EINVAL; - goto exit; + goto put_local; } rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len); + +put_local: + nfc_llcp_local_put(local); + exit: device_unlock(&dev->dev); diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index de2ec66d7e83..0b1e6466f4fb 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -52,6 +52,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len); u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); +int nfc_llcp_local_put(struct nfc_llcp_local *local); int __init nfc_llcp_init(void); void nfc_llcp_exit(void); void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);