From: Taehee Yoo Subject: [PATCH net 1/2] net: bpfilter: restart bpfilter_umh when error occurred Date: Wed, 12 Dec 2018 10:19:26 +0900 Message-ID: <20181212011926.28554-1-ap420073@gmail.com> Cc: daniel@iogearbox.net, ast@kernel.org, ap420073@gmail.com To: davem@davemloft.net, netdev@vger.kernel.org Return-path: Received: from mail-pf1-f195.google.com ([209.85.210.195]:46004 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726246AbeLLBTe (ORCPT ); Tue, 11 Dec 2018 20:19:34 -0500 Received: by mail-pf1-f195.google.com with SMTP id g62so7996962pfd.12 for ; Tue, 11 Dec 2018 17:19:32 -0800 (PST) Sender: netdev-owner@vger.kernel.org List-ID: When bpfilter error occurred bpfilter_umh will be stopped via __stop_umh(). The bpfilter_umh() couldn't start again because there is no restart routine. The section of 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. Test commands: $ iptables -vnL $ kill -9 $ iptables -vnL [ 480.045136] bpfilter: write fail -32 $ iptables -vnL iptables v1.8.1 (legacy): can't initialize iptables table `filter': No child processes Perhaps iptables or your kernel needs to be upgraded. Then, iptables command is always failed. Fixes: d2ba09c17a06 ("net: add skeleton of bpfilter kernel module") Signed-off-by: Taehee Yoo --- include/linux/bpfilter.h | 2 ++ net/bpfilter/bpfilter_kern.c | 12 +++++++++++- net/bpfilter/bpfilter_umh_blob.S | 2 +- net/ipv4/bpfilter/sockopt.c | 6 +++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/linux/bpfilter.h b/include/linux/bpfilter.h index f02cee0225d4..3039361cd65a 100644 --- a/include/linux/bpfilter.h +++ b/include/linux/bpfilter.h @@ -12,4 +12,6 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval, extern int (*bpfilter_process_sockopt)(struct sock *sk, int optname, char __user *optval, unsigned int optlen, bool is_set); +extern int (*bpfilter_start_umh)(void); + #endif diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index 7acfc83087d5..7397f5e8da2f 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c @@ -87,7 +87,7 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname, return ret; } -static int __init load_umh(void) +int start_umh(void) { int err; @@ -111,8 +111,18 @@ static int __init load_umh(void) return 0; } +static int __init load_umh(void) +{ + if (IS_ENABLED(CONFIG_INET)) + bpfilter_start_umh = &start_umh; + + return start_umh(); +} + static void __exit fini_umh(void) { + if (IS_ENABLED(CONFIG_INET)) + bpfilter_start_umh = NULL; stop_umh(); } module_init(load_umh); diff --git a/net/bpfilter/bpfilter_umh_blob.S b/net/bpfilter/bpfilter_umh_blob.S index 40311d10d2f2..7f1c521dcc2f 100644 --- a/net/bpfilter/bpfilter_umh_blob.S +++ b/net/bpfilter/bpfilter_umh_blob.S @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ - .section .init.rodata, "a" + .section .bpfilter_umh, "a" .global bpfilter_umh_start bpfilter_umh_start: .incbin "net/bpfilter/bpfilter_umh" diff --git a/net/ipv4/bpfilter/sockopt.c b/net/ipv4/bpfilter/sockopt.c index 5e04ed25bc0e..f7efcff9634d 100644 --- a/net/ipv4/bpfilter/sockopt.c +++ b/net/ipv4/bpfilter/sockopt.c @@ -10,6 +10,9 @@ int (*bpfilter_process_sockopt)(struct sock *sk, int optname, unsigned int optlen, bool is_set); EXPORT_SYMBOL_GPL(bpfilter_process_sockopt); +int (*bpfilter_start_umh)(void); +EXPORT_SYMBOL_GPL(bpfilter_start_umh); + static int bpfilter_mbox_request(struct sock *sk, int optname, char __user *optval, unsigned int optlen, bool is_set) @@ -20,7 +23,8 @@ static int bpfilter_mbox_request(struct sock *sk, int optname, if (err) return err; if (!bpfilter_process_sockopt) - return -ECHILD; + if (!bpfilter_start_umh || bpfilter_start_umh()) + return -ECHILD; } return bpfilter_process_sockopt(sk, optname, optval, optlen, is_set); } -- 2.17.1