Skip to content

Commit 6ed23cd

Browse files
TaeheeYoondreys
authored andcommitted
net: bpfilter: restart bpfilter_umh when error occurred
The bpfilter_umh will be stopped via __stop_umh() when the bpfilter error occurred. The bpfilter_umh() couldn't start again because there is no restart routine. The section of the bpfilter_umh_{start/end} is no longer .init.rodata because these area should be reused in the restart routine. hence the section name is changed to .bpfilter_umh. The bpfilter_ops->start() is restart callback. it will be called when bpfilter_umh is stopped. The stop bit means bpfilter_umh is stopped. this bit is set by both start and stop routine. Before this patch, Test commands: $ iptables -vnL $ kill -9 <pid of bpfilter_umh> $ iptables -vnL [ 480.045136] bpfilter: write fail -32 $ iptables -vnL All iptables commands will fail. After this patch, Test commands: $ iptables -vnL $ kill -9 <pid of bpfilter_umh> $ iptables -vnL $ iptables -vnL Now, all iptables commands will work. Fixes: d2ba09c ("net: add skeleton of bpfilter kernel module") Signed-off-by: Taehee Yoo <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c9d4ae8 commit 6ed23cd

File tree

4 files changed

+40
-12
lines changed

4 files changed

+40
-12
lines changed

include/linux/bpfilter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ struct bpfilter_umh_ops {
1515
int (*sockopt)(struct sock *sk, int optname,
1616
char __user *optval,
1717
unsigned int optlen, bool is_set);
18+
int (*start)(void);
19+
bool stop;
1820
};
1921
extern struct bpfilter_umh_ops bpfilter_ops;
2022
#endif

net/bpfilter/bpfilter_kern.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ extern char bpfilter_umh_end;
1616
/* since ip_getsockopt() can run in parallel, serialize access to umh */
1717
static DEFINE_MUTEX(bpfilter_lock);
1818

19-
static void shutdown_umh(struct umh_info *info)
19+
static void shutdown_umh(void)
2020
{
2121
struct task_struct *tsk;
2222

23-
if (!info->pid)
23+
if (bpfilter_ops.stop)
2424
return;
25-
tsk = get_pid_task(find_vpid(info->pid), PIDTYPE_PID);
25+
26+
tsk = get_pid_task(find_vpid(bpfilter_ops.info.pid), PIDTYPE_PID);
2627
if (tsk) {
2728
force_sig(SIGKILL, tsk);
2829
put_task_struct(tsk);
@@ -31,10 +32,8 @@ static void shutdown_umh(struct umh_info *info)
3132

3233
static void __stop_umh(void)
3334
{
34-
if (IS_ENABLED(CONFIG_INET)) {
35-
bpfilter_ops.sockopt = NULL;
36-
shutdown_umh(&bpfilter_ops.info);
37-
}
35+
if (IS_ENABLED(CONFIG_INET))
36+
shutdown_umh();
3837
}
3938

4039
static void stop_umh(void)
@@ -85,7 +84,7 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
8584
return ret;
8685
}
8786

88-
static int __init load_umh(void)
87+
static int start_umh(void)
8988
{
9089
int err;
9190

@@ -95,21 +94,39 @@ static int __init load_umh(void)
9594
&bpfilter_ops.info);
9695
if (err)
9796
return err;
97+
bpfilter_ops.stop = false;
9898
pr_info("Loaded bpfilter_umh pid %d\n", bpfilter_ops.info.pid);
9999

100100
/* health check that usermode process started correctly */
101101
if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) {
102102
stop_umh();
103103
return -EFAULT;
104104
}
105-
if (IS_ENABLED(CONFIG_INET))
106-
bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
107105

108106
return 0;
109107
}
110108

109+
static int __init load_umh(void)
110+
{
111+
int err;
112+
113+
if (!bpfilter_ops.stop)
114+
return -EFAULT;
115+
err = start_umh();
116+
if (!err && IS_ENABLED(CONFIG_INET)) {
117+
bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
118+
bpfilter_ops.start = &start_umh;
119+
}
120+
121+
return err;
122+
}
123+
111124
static void __exit fini_umh(void)
112125
{
126+
if (IS_ENABLED(CONFIG_INET)) {
127+
bpfilter_ops.start = NULL;
128+
bpfilter_ops.sockopt = NULL;
129+
}
113130
stop_umh();
114131
}
115132
module_init(load_umh);

net/bpfilter/bpfilter_umh_blob.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
2-
.section .init.rodata, "a"
2+
.section .bpfilter_umh, "a"
33
.global bpfilter_umh_start
44
bpfilter_umh_start:
55
.incbin "net/bpfilter/bpfilter_umh"

net/ipv4/bpfilter/sockopt.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ EXPORT_SYMBOL_GPL(bpfilter_ops);
1414

1515
static void bpfilter_umh_cleanup(struct umh_info *info)
1616
{
17+
bpfilter_ops.stop = true;
1718
fput(info->pipe_to_umh);
1819
fput(info->pipe_from_umh);
1920
info->pid = 0;
@@ -23,14 +24,21 @@ static int bpfilter_mbox_request(struct sock *sk, int optname,
2324
char __user *optval,
2425
unsigned int optlen, bool is_set)
2526
{
27+
int err;
28+
2629
if (!bpfilter_ops.sockopt) {
27-
int err = request_module("bpfilter");
30+
err = request_module("bpfilter");
2831

2932
if (err)
3033
return err;
3134
if (!bpfilter_ops.sockopt)
3235
return -ECHILD;
3336
}
37+
if (bpfilter_ops.stop) {
38+
err = bpfilter_ops.start();
39+
if (err)
40+
return err;
41+
}
3442
return bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set);
3543
}
3644

@@ -53,6 +61,7 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
5361

5462
static int __init bpfilter_sockopt_init(void)
5563
{
64+
bpfilter_ops.stop = true;
5665
bpfilter_ops.info.cmdline = "bpfilter_umh";
5766
bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup;
5867

0 commit comments

Comments
 (0)