Alexei Starovoitov <alexei.starovoitov@xxxxxxxxx> writes: 2> On Mon, Jun 29, 2020 at 02:55:05PM -0500, Eric W. Biederman wrote: >> >> I have tested thes changes by booting with the code compiled in and >> by killing "bpfilter_umh" and running iptables -vnL to restart >> the userspace driver. >> >> I have compiled tested each change with and without CONFIG_BPFILTER >> enabled. > > With > CONFIG_BPFILTER=y > CONFIG_BPFILTER_UMH=m > it doesn't build: > > ERROR: modpost: "kill_pid_info" [net/bpfilter/bpfilter.ko] undefined! > > I've added: > +EXPORT_SYMBOL(kill_pid_info); > to continue testing... I am rather surprised I thought Tetsuo had already compile tested modules. > I suspect patch 13 is somehow responsible: > + if (tgid) { > + kill_pid_info(SIGKILL, SEND_SIG_PRIV, tgid); > + wait_event(tgid->wait_pidfd, !pid_task(tgid, PIDTYPE_TGID)); > + bpfilter_umh_cleanup(info); > + } > > I cannot figure out why it hangs. Some sort of race ? > Since adding short delay between kill and wait makes it work. Having had a chance to sleep kill_pid_info was a thinko, as was !pid_task. It should have been !pid_has_task as that takes the proper rcu locking. I don't know if that is going to be enough to fix the wait_event but those are obvious bugs that need to be fixed. diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index 91474884ddb7..3e1874030daa 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c @@ -19,8 +19,8 @@ static void shutdown_umh(void) struct pid *tgid = info->tgid; if (tgid) { - kill_pid_info(SIGKILL, SEND_SIG_PRIV, tgid); - wait_event(tgid->wait_pidfd, !pid_task(tgid, PIDTYPE_TGID)); + kill_pid(tgid, SIGKILL, 1); + wait_event(tgid->wait_pidfd, !pid_has_task(tgid, PIDTYPE_TGID)); bpfilter_umh_cleanup(info); } } > And then did: > while true; do iptables -L;rmmod bpfilter; done > > Unfortunately sometimes 'rmmod bpfilter' hangs in wait_event(). Hmm. The wake up happens just of tgid->wait_pidfd happens just before release_task is called so there is a race. As it is possible to wake up and then go back to sleep before pid_has_task becomes false. So I think I need a friendly helper that does: bool task_has_exited(struct pid *tgid) { bool exited = false; rcu_read_lock(); tsk = pid_task(tgid, PIDTYPE_TGID); exited = !!tsk; if (tsk) { exited = !!tsk->exit_state; out: rcu_unlock(); return exited; } There should be a sensible way to do that. Eric