While looking at a syzbot report I noticed the NAPI only gets disabled before it's deleted. I think that user can detach the queue before destroying the device and the NAPI will never be stopped.
Unified · Split
| @@ -273,6 +273,12 @@ static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile, · 272 unmodified lines | |||
| 273 | } | 273 | } |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | static void tun_napi_enable(struct tun_file *tfile) | ||
| 277 | { | ||
| 278 | if (tfile->napi_enabled) | ||
| 279 | napi_enable(&tfile->napi); | ||
| 280 | } | ||
| 281 | |||
| 276 | static void tun_napi_disable(struct tun_file *tfile) | 282 | static void tun_napi_disable(struct tun_file *tfile) |
| 277 | { | 283 | { |
| 278 | if (tfile->napi_enabled) | 284 | if (tfile->napi_enabled) |
| @@ -653,8 +659,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean) · 374 unmodified lines | |||
| 653 | if (clean) { | 659 | if (clean) { |
| 654 | RCU_INIT_POINTER(tfile->tun, NULL); | 660 | RCU_INIT_POINTER(tfile->tun, NULL); |
| 655 | sock_put(&tfile->sk); | 661 | sock_put(&tfile->sk); |
| 656 | } else | 662 | } else { |
| 657 | tun_disable_queue(tun, tfile); | 663 | tun_disable_queue(tun, tfile); |
| 664 | tun_napi_disable(tfile); | ||
| 665 | } | ||
| 658 | 666 | ||
| 659 | synchronize_net(); | 667 | synchronize_net(); |
| 660 | tun_flow_delete_by_queue(tun, tun->numqueues + 1); | 668 | tun_flow_delete_by_queue(tun, tun->numqueues + 1); |
| @@ -808,6 +816,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file, · 147 unmodified lines | |||
| 808 | 816 | ||
| 809 | if (tfile->detached) { | 817 | if (tfile->detached) { |
| 810 | tun_enable_queue(tfile); | 818 | tun_enable_queue(tfile); |
| 819 | tun_napi_enable(tfile); | ||
| 811 | } else { | 820 | } else { |
| 812 | sock_hold(&tfile->sk); | 821 | sock_hold(&tfile->sk); |
| 813 | tun_napi_init(tun, tfile, napi, napi_frags); | 822 | tun_napi_init(tun, tfile, napi, napi_frags); |