Skip to content

Commit e80eb1d

Browse files
committed
bpfilter: Take advantage of the facilities of struct pid
Instead of relying on the exit_umh cleanup callback use the fact a struct pid can be tested to see if a process still exists, and that struct pid has a wait queue that notifies when the process dies. v1: https://lkml.kernel.org/r/[email protected] v2: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Reviewed-by: Greg Kroah-Hartman <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Tested-by: Alexei Starovoitov <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 38fd525 commit e80eb1d

File tree

3 files changed

+15
-18
lines changed

3 files changed

+15
-18
lines changed

include/linux/bpfilter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
1010
unsigned int optlen);
1111
int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
1212
int __user *optlen);
13+
void bpfilter_umh_cleanup(struct umd_info *info);
14+
1315
struct bpfilter_umh_ops {
1416
struct umd_info info;
1517
/* since ip_getsockopt() can run in parallel, serialize access to umh */
@@ -18,7 +20,6 @@ struct bpfilter_umh_ops {
1820
char __user *optval,
1921
unsigned int optlen, bool is_set);
2022
int (*start)(void);
21-
bool stop;
2223
};
2324
extern struct bpfilter_umh_ops bpfilter_ops;
2425
#endif

net/bpfilter/bpfilter_kern.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ static void shutdown_umh(void)
1818
struct umd_info *info = &bpfilter_ops.info;
1919
struct pid *tgid = info->tgid;
2020

21-
if (bpfilter_ops.stop)
22-
return;
23-
24-
kill_pid(tgid, SIGKILL, 1);
21+
if (tgid) {
22+
kill_pid(tgid, SIGKILL, 1);
23+
wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
24+
bpfilter_umh_cleanup(info);
25+
}
2526
}
2627

2728
static void __stop_umh(void)
@@ -77,7 +78,6 @@ static int start_umh(void)
7778
err = fork_usermode_driver(&bpfilter_ops.info);
7879
if (err)
7980
return err;
80-
bpfilter_ops.stop = false;
8181
pr_info("Loaded bpfilter_umh pid %d\n", pid_nr(bpfilter_ops.info.tgid));
8282

8383
/* health check that usermode process started correctly */
@@ -100,16 +100,11 @@ static int __init load_umh(void)
100100
return err;
101101

102102
mutex_lock(&bpfilter_ops.lock);
103-
if (!bpfilter_ops.stop) {
104-
err = -EFAULT;
105-
goto out;
106-
}
107103
err = start_umh();
108104
if (!err && IS_ENABLED(CONFIG_INET)) {
109105
bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
110106
bpfilter_ops.start = &start_umh;
111107
}
112-
out:
113108
mutex_unlock(&bpfilter_ops.lock);
114109
if (err)
115110
umd_unload_blob(&bpfilter_ops.info);

net/ipv4/bpfilter/sockopt.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,14 @@
1212
struct bpfilter_umh_ops bpfilter_ops;
1313
EXPORT_SYMBOL_GPL(bpfilter_ops);
1414

15-
static void bpfilter_umh_cleanup(struct umd_info *info)
15+
void bpfilter_umh_cleanup(struct umd_info *info)
1616
{
17-
mutex_lock(&bpfilter_ops.lock);
18-
bpfilter_ops.stop = true;
1917
fput(info->pipe_to_umh);
2018
fput(info->pipe_from_umh);
2119
put_pid(info->tgid);
2220
info->tgid = NULL;
23-
mutex_unlock(&bpfilter_ops.lock);
2421
}
22+
EXPORT_SYMBOL_GPL(bpfilter_umh_cleanup);
2523

2624
static int bpfilter_mbox_request(struct sock *sk, int optname,
2725
char __user *optval,
@@ -39,7 +37,11 @@ static int bpfilter_mbox_request(struct sock *sk, int optname,
3937
goto out;
4038
}
4139
}
42-
if (bpfilter_ops.stop) {
40+
if (bpfilter_ops.info.tgid &&
41+
thread_group_exited(bpfilter_ops.info.tgid))
42+
bpfilter_umh_cleanup(&bpfilter_ops.info);
43+
44+
if (!bpfilter_ops.info.tgid) {
4345
err = bpfilter_ops.start();
4446
if (err)
4547
goto out;
@@ -70,9 +72,8 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
7072
static int __init bpfilter_sockopt_init(void)
7173
{
7274
mutex_init(&bpfilter_ops.lock);
73-
bpfilter_ops.stop = true;
75+
bpfilter_ops.info.tgid = NULL;
7476
bpfilter_ops.info.driver_name = "bpfilter_umh";
75-
bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup;
7677

7778
return 0;
7879
}

0 commit comments

Comments
 (0)