From patchwork Mon Jan 7 12:10:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Taehee Yoo X-Patchwork-Id: 1021281 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="YDxZRzzo"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43YDk3394bz9sMr for ; Mon, 7 Jan 2019 23:10:35 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726792AbfAGMKa (ORCPT ); Mon, 7 Jan 2019 07:10:30 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:33570 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726485AbfAGMKa (ORCPT ); Mon, 7 Jan 2019 07:10:30 -0500 Received: by mail-pl1-f195.google.com with SMTP id z23so81461plo.0; Mon, 07 Jan 2019 04:10:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=98DmvLc/H37HjAYgMJiooCx3JhogoHqBnW+idXeEU6E=; b=YDxZRzzoEtY7lzl2tzQfxk7iFUe2xjTO4oq6f0R3b2vvtjRaKTpsKQBMCGb+FQbWjI z3XDvIYTES0iFNiWe0PHvEktloKjOStsdcNxdYEHgTQYc3RvHVKhBBZrm2dJEaOBhSeV xvB8yR3CeQBQCYoecMiCSbXX/xm8vpaKBy7W3ththikXUY37uAJT9SZkGVp2sxTy0aXJ l5ZEmA8Ck6zI+wcCV0Vy1hb1e0WRInE5PNtBcem9YVjrpOg0QHb4FvbQdJf1dlTwac9c 9JcYL3ge8hmwekeYkb5yIkkwAoKbPZq1dOa8MIjIhpU63WQfUmmbkXcxHn3jWGtBBtJZ yBuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=98DmvLc/H37HjAYgMJiooCx3JhogoHqBnW+idXeEU6E=; b=ZBvOag/ZJvUozQeWjv3oScmL9hlRIDbUboAm0IcI24V9aXot5WPKAaaMpMEFI5SR2l KLfZTsdZNYNQfDv9+FPoobQlXRnekB2oD3rY2CU18ZQffkT8iB9bmR4REOKqOo5ot2YO uYZQC1ob7TCFzMgIxaqBW1WRyMjZwvT1lS3t4nxdCg45WogRqVh52NhMD9i/q2Z77ky0 ML0xiJXVKhoVD5yIZq0Z3ENBXOCDuOGBxo4i2kGlFnm4OXgeXjTvSTutz2wVjWp/W38A CE0R7TUe644KEFNdbuhODRirv6GBjZgGqQP9Go/dM0IjsCxaAc3VVDeQFv2Y3uttgCxL pdJA== X-Gm-Message-State: AJcUuke2rBj4ixhXWsVKEIBpyXVKCi6xhYB8ygwnNRII5WhI9q5eizGK GaJB72B8pH9kVIAKroxb9oY= X-Google-Smtp-Source: ALg8bN5uBiF7BGP9/lz3bvGnwGuPFbaINu2kQzJMeaOXPdapSgoxthkV9ZZ0I5G3OKTywu179xgujg== X-Received: by 2002:a17:902:e002:: with SMTP id ca2mr61911680plb.103.1546863028844; Mon, 07 Jan 2019 04:10:28 -0800 (PST) Received: from ap-To-be-filled-by-O-E-M.8.8.8.8 ([14.33.120.60]) by smtp.gmail.com with ESMTPSA id 62sm79666704pgc.61.2019.01.07.04.10.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Jan 2019 04:10:28 -0800 (PST) From: Taehee Yoo To: davem@davemloft.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, daniel@iogearbox.net, ast@kernel.org, mcgrof@kernel.org Cc: ap420073@gmail.com Subject: [PATCH net v3 1/4] umh: add exit routine for UMH process Date: Mon, 7 Jan 2019 21:10:14 +0900 Message-Id: <20190107121014.13499-1-ap420073@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org A UMH process which is created by the fork_usermode_blob() such as bpfilter needs to release members of the umh_info when process is terminated. But the do_exit() does not release members of the umh_info. hence module which uses UMH needs own code to detect whether UMH process is terminated or not. But this implementation needs extra code for checking the status of UMH process. it eventually makes the code more complex. The new PF_UMH flag is added and it is used to identify UMH processes. The exit_umh() does not release members of the umh_info. Hence umh_info->cleanup callback should release both members of the umh_info and the private data. Suggested-by: David S. Miller Signed-off-by: Taehee Yoo --- v3 : - Avoid unnecessary list lookup for non-UMH processes - Add a new PF_UMH flag include/linux/sched.h | 1 + include/linux/umh.h | 4 ++++ kernel/exit.c | 1 + kernel/umh.c | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 89541d248893..965da2d54c06 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1406,6 +1406,7 @@ extern struct pid *cad_pid; #define PF_RANDOMIZE 0x00400000 /* Randomize virtual address space */ #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ #define PF_MEMSTALL 0x01000000 /* Stalled due to lack of memory */ +#define PF_UMH 0x02000000 /* I'm an Usermodehelper process */ #define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */ #define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ diff --git a/include/linux/umh.h b/include/linux/umh.h index 235f51b62c71..c645f0a19103 100644 --- a/include/linux/umh.h +++ b/include/linux/umh.h @@ -47,6 +47,8 @@ struct umh_info { const char *cmdline; struct file *pipe_to_umh; struct file *pipe_from_umh; + struct list_head list; + void (*cleanup)(struct umh_info *info); pid_t pid; }; int fork_usermode_blob(void *data, size_t len, struct umh_info *info); @@ -75,6 +77,8 @@ static inline void usermodehelper_enable(void) __usermodehelper_set_disable_depth(UMH_ENABLED); } +void exit_umh(struct task_struct *tsk); + extern int usermodehelper_read_trylock(void); extern long usermodehelper_read_lock_wait(long timeout); extern void usermodehelper_read_unlock(void); diff --git a/kernel/exit.c b/kernel/exit.c index 8a01b671dc1f..dad70419195c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -866,6 +866,7 @@ void __noreturn do_exit(long code) exit_task_namespaces(tsk); exit_task_work(tsk); exit_thread(tsk); + exit_umh(tsk); /* * Flush inherited counters to the parent - before the parent diff --git a/kernel/umh.c b/kernel/umh.c index 0baa672e023c..d96e8cd14384 100644 --- a/kernel/umh.c +++ b/kernel/umh.c @@ -37,6 +37,8 @@ static kernel_cap_t usermodehelper_bset = CAP_FULL_SET; static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; static DEFINE_SPINLOCK(umh_sysctl_lock); static DECLARE_RWSEM(umhelper_sem); +static LIST_HEAD(umh_list); +static DEFINE_MUTEX(umh_list_lock); static void call_usermodehelper_freeinfo(struct subprocess_info *info) { @@ -100,10 +102,12 @@ static int call_usermodehelper_exec_async(void *data) commit_creds(new); sub_info->pid = task_pid_nr(current); - if (sub_info->file) + if (sub_info->file) { retval = do_execve_file(sub_info->file, sub_info->argv, sub_info->envp); - else + if (!retval) + current->flags |= PF_UMH; + } else retval = do_execve(getname_kernel(sub_info->path), (const char __user *const __user *)sub_info->argv, (const char __user *const __user *)sub_info->envp); @@ -517,6 +521,11 @@ int fork_usermode_blob(void *data, size_t len, struct umh_info *info) goto out; err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); + if (!err) { + mutex_lock(&umh_list_lock); + list_add(&info->list, &umh_list); + mutex_unlock(&umh_list_lock); + } out: fput(file); return err; @@ -679,6 +688,29 @@ static int proc_cap_handler(struct ctl_table *table, int write, return 0; } +void exit_umh(struct task_struct *tsk) +{ + struct umh_info *info; + pid_t pid = tsk->pid; + + if (!(tsk->flags & PF_UMH)) + return; + + mutex_lock(&umh_list_lock); + list_for_each_entry(info, &umh_list, list) { + if (info->pid == pid) { + list_del(&info->list); + mutex_unlock(&umh_list_lock); + goto out; + } + } + mutex_unlock(&umh_list_lock); + return; +out: + if (info->cleanup) + info->cleanup(info); +} + struct ctl_table usermodehelper_table[] = { { .procname = "bset", From patchwork Mon Jan 7 12:10:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Taehee Yoo X-Patchwork-Id: 1021282 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mwSTmCO/"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43YDkh1r73z9sN4 for ; Mon, 7 Jan 2019 23:11:08 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726827AbfAGMLC (ORCPT ); Mon, 7 Jan 2019 07:11:02 -0500 Received: from mail-pg1-f193.google.com ([209.85.215.193]:38999 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726485AbfAGMLC (ORCPT ); Mon, 7 Jan 2019 07:11:02 -0500 Received: by mail-pg1-f193.google.com with SMTP id w6so59946pgl.6; Mon, 07 Jan 2019 04:11:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=QMJufnjC2av/TaQG0Gtve4swcI6YQyf9FiBVtu4QS/Y=; b=mwSTmCO/JP4JX/0NMIjbu8rOAnPUv/IZE9XSS7RogoS44O+cczU2xn0Cxe7O2EjRXK j64rhUKMCt0KP+B6wWQQmX/q71V2ear9jeiD1keSFId6GbxFaAwg3xvoJOQkAn3WLBCJ 9sP8vzX4mgHIZ5WIIzQxOfLQfU42rSbjvBqN2vBdtDwfb74b3IAt720d33sIL+hHGY6S gsF+qvZAgwKXxOo2sHt6p8y1K5pVBEdxYhbuVBC2ZKr4Klee8w+21yuMIXHmaoPw8gc5 YPklVWQl9Jeehd8p+S31bllctTuYhze2KBW3Vf231bfxRASFF/soga9n686S/LgZO6+T KqWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=QMJufnjC2av/TaQG0Gtve4swcI6YQyf9FiBVtu4QS/Y=; b=oWtQ7TCnBgwBkj4RJlQXD5o0f64aV9IKnpRPCcLwc6tgAHDowCqjd3AlQ79fx++4g0 U4Bh00siFkaKsKcTswFgF//UFYdIb0QwK+hPYzTE/+oyiqfb0IDsMUN/lJ572sX4Wgsv Kvncjvj42a6NFXpesj6Tmaa5mxv02Gt5G1oi9vF1YIIGByNq8xQxJjlPYLRjmJUstyBn BM58kAx9h1DFlWUvnmyQlgvwGXE8k2wL2rza6Z+FSNxEHsuoT2VOw9mPUbYcDzjKox+v EuG5WuNnFXVo+CskZKmkAGNB9rZDQ0cuqkg+1tT50dUPBY2cUH5Ini9F9XqYW9KR0lxk pLvg== X-Gm-Message-State: AJcUukfuSjG+bUP5GWK+6rDf5Fd9pPhXT64RTu7h6L5KYlzWsujinhqu Oqf5yvztTYmqm0U+22cKsOw= X-Google-Smtp-Source: ALg8bN5s5LVeY9D0qFLBGTh+1wL5jf2faMlhMIOJGOpo0DvKC3eXSRhRcCWKig01kGjiEj8Ss2Vkpw== X-Received: by 2002:a62:c583:: with SMTP id j125mr63302398pfg.37.1546863061022; Mon, 07 Jan 2019 04:11:01 -0800 (PST) Received: from ap-To-be-filled-by-O-E-M.8.8.8.8 ([14.33.120.60]) by smtp.gmail.com with ESMTPSA id 125sm114569860pfd.124.2019.01.07.04.10.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Jan 2019 04:11:00 -0800 (PST) From: Taehee Yoo To: davem@davemloft.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, daniel@iogearbox.net, ast@kernel.org, mcgrof@kernel.org Cc: ap420073@gmail.com Subject: [PATCH net v3 2/4] net: bpfilter: use cleanup callback to release umh_info Date: Mon, 7 Jan 2019 21:10:52 +0900 Message-Id: <20190107121052.13645-1-ap420073@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Now, UMH process is killed, do_exit() calls the umh_info->cleanup callback to release members of the umh_info. This patch makes bpfilter_umh's cleanup routine to use the umh_info->cleanup callback. Signed-off-by: Taehee Yoo --- include/linux/bpfilter.h | 11 ++++++++--- net/bpfilter/bpfilter_kern.c | 23 ++++++++++------------- net/ipv4/bpfilter/sockopt.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/include/linux/bpfilter.h b/include/linux/bpfilter.h index f02cee0225d4..70ffeed280e9 100644 --- a/include/linux/bpfilter.h +++ b/include/linux/bpfilter.h @@ -3,13 +3,18 @@ #define _LINUX_BPFILTER_H #include +#include struct sock; int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen); int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen); -extern int (*bpfilter_process_sockopt)(struct sock *sk, int optname, - char __user *optval, - unsigned int optlen, bool is_set); +struct bpfilter_umh_ops { + struct umh_info info; + int (*sockopt)(struct sock *sk, int optname, + char __user *optval, + unsigned int optlen, bool is_set); +}; +extern struct bpfilter_umh_ops bpfilter_ops; #endif diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index 7acfc83087d5..a68940b74c01 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c @@ -13,7 +13,6 @@ extern char bpfilter_umh_start; extern char bpfilter_umh_end; -static struct umh_info info; /* since ip_getsockopt() can run in parallel, serialize access to umh */ static DEFINE_MUTEX(bpfilter_lock); @@ -28,16 +27,13 @@ static void shutdown_umh(struct umh_info *info) force_sig(SIGKILL, tsk); put_task_struct(tsk); } - fput(info->pipe_to_umh); - fput(info->pipe_from_umh); - info->pid = 0; } static void __stop_umh(void) { if (IS_ENABLED(CONFIG_INET)) { - bpfilter_process_sockopt = NULL; - shutdown_umh(&info); + bpfilter_ops.sockopt = NULL; + shutdown_umh(&bpfilter_ops.info); } } @@ -64,9 +60,10 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname, req.addr = (long __force __user)optval; req.len = optlen; mutex_lock(&bpfilter_lock); - if (!info.pid) + if (!bpfilter_ops.info.pid) goto out; - n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos); + n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req), + &pos); if (n != sizeof(req)) { pr_err("write fail %zd\n", n); __stop_umh(); @@ -74,7 +71,8 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname, goto out; } pos = 0; - n = kernel_read(info.pipe_from_umh, &reply, sizeof(reply), &pos); + n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply), + &pos); if (n != sizeof(reply)) { pr_err("read fail %zd\n", n); __stop_umh(); @@ -92,13 +90,12 @@ static int __init load_umh(void) int err; /* fork usermode process */ - info.cmdline = "bpfilter_umh"; err = fork_usermode_blob(&bpfilter_umh_start, &bpfilter_umh_end - &bpfilter_umh_start, - &info); + &bpfilter_ops.info); if (err) return err; - pr_info("Loaded bpfilter_umh pid %d\n", info.pid); + pr_info("Loaded bpfilter_umh pid %d\n", bpfilter_ops.info.pid); /* health check that usermode process started correctly */ if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) { @@ -106,7 +103,7 @@ static int __init load_umh(void) return -EFAULT; } if (IS_ENABLED(CONFIG_INET)) - bpfilter_process_sockopt = &__bpfilter_process_sockopt; + bpfilter_ops.sockopt = &__bpfilter_process_sockopt; return 0; } diff --git a/net/ipv4/bpfilter/sockopt.c b/net/ipv4/bpfilter/sockopt.c index 5e04ed25bc0e..c326cfbc0f62 100644 --- a/net/ipv4/bpfilter/sockopt.c +++ b/net/ipv4/bpfilter/sockopt.c @@ -1,28 +1,37 @@ // SPDX-License-Identifier: GPL-2.0 +#include +#include #include #include #include #include #include +#include +#include -int (*bpfilter_process_sockopt)(struct sock *sk, int optname, - char __user *optval, - unsigned int optlen, bool is_set); -EXPORT_SYMBOL_GPL(bpfilter_process_sockopt); +struct bpfilter_umh_ops bpfilter_ops; +EXPORT_SYMBOL_GPL(bpfilter_ops); + +static void bpfilter_umh_cleanup(struct umh_info *info) +{ + fput(info->pipe_to_umh); + fput(info->pipe_from_umh); + info->pid = 0; +} static int bpfilter_mbox_request(struct sock *sk, int optname, char __user *optval, unsigned int optlen, bool is_set) { - if (!bpfilter_process_sockopt) { + if (!bpfilter_ops.sockopt) { int err = request_module("bpfilter"); if (err) return err; - if (!bpfilter_process_sockopt) + if (!bpfilter_ops.sockopt) return -ECHILD; } - return bpfilter_process_sockopt(sk, optname, optval, optlen, is_set); + return bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set); } int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval, @@ -41,3 +50,13 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval, return bpfilter_mbox_request(sk, optname, optval, len, false); } + +static int __init bpfilter_sockopt_init(void) +{ + bpfilter_ops.info.cmdline = "bpfilter_umh"; + bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup; + + return 0; +} + +module_init(bpfilter_sockopt_init); From patchwork Mon Jan 7 12:11:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Taehee Yoo X-Patchwork-Id: 1021283 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QjMn5xK1"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43YDl93MBVz9sN1 for ; Mon, 7 Jan 2019 23:11:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726893AbfAGMLT (ORCPT ); Mon, 7 Jan 2019 07:11:19 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:32925 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726485AbfAGMLT (ORCPT ); Mon, 7 Jan 2019 07:11:19 -0500 Received: by mail-pf1-f193.google.com with SMTP id c123so83375pfb.0; Mon, 07 Jan 2019 04:11:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=MpvPXvIifufe+uDDCsa2UqAYZWkhMO+OlIK179a13b0=; b=QjMn5xK1bcIDMygfoVhyKutstONy9YcGjUh961V07+OfFF69tc5e72LjMDcUdom1qC GvHbP2Jg0dRdkOKtAKL055u3DQDPjcHyqfZwzTPMA4mPLioXH/EETvpor3D5ruYXyco2 6+GMxOKLNjq0EiHpUjj81ylzQWdnXRQ0Jg2FTsw5dN1mLaI+IsZFJa40xKA2f091yrG1 A4o5aDNOQE9dAepcXNIUiUkyGr40b0aR56kd7L55tXqgzLRgtTfLETFDQ3QCc08M+r/t L/ljCJxugh2+9kZhstE1HYUfoZmkFOhHGp2dDC2uza3VFHlcKS6a3MoR80HbzoaLLf+D /qKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=MpvPXvIifufe+uDDCsa2UqAYZWkhMO+OlIK179a13b0=; b=EFSIMOd0bVu7YE1qQFGcG5XuZQxwwN3kp7Ih7/26tzHUDZbCQRcolwPas8oDW/ALAV kWQS6abmcNBaceCU7Mndjow9+GXDImdXDsd4DKoL+UgOJoTLjFnSnaxiiQ69vxT6hh0D e6Nc/qp+Ody1qWXWEm7XC92lfUbu8wZWtsBiLrkMkUlLq//7Q7ijl3R/0Rb5NPJo8TpD B4EB08Pj3MRaN4BnY7oVZivPQB40VknVVI8NYA33DDF2A5QMOO137gqeAbcAC5V80acU ZNcavLmTlJIH82Yd/+DqyEw1MbbFPzgOWYjHZv7KRjMJt1zJ4vFaRDzeyStml1i1iK5H fVsg== X-Gm-Message-State: AJcUukfYS21Ft12itAmI/hpyo7XIHmildT2XkL3UT3iV+GoX/eNLPl3s cL3wUp65GXOO1geE5I/8kSs= X-Google-Smtp-Source: ALg8bN4LtwOXkWW+8/1Gz+FBl/QCdxKel9wqj+R+Hucb+9bTs6ElwD3DynDz26ERhqHWn+UnCD12Iw== X-Received: by 2002:a63:ee4c:: with SMTP id n12mr10403087pgk.21.1546863077993; Mon, 07 Jan 2019 04:11:17 -0800 (PST) Received: from ap-To-be-filled-by-O-E-M.8.8.8.8 ([14.33.120.60]) by smtp.gmail.com with ESMTPSA id m3sm109476941pff.173.2019.01.07.04.11.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Jan 2019 04:11:17 -0800 (PST) From: Taehee Yoo To: davem@davemloft.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, daniel@iogearbox.net, ast@kernel.org, mcgrof@kernel.org Cc: ap420073@gmail.com Subject: [PATCH net v3 3/4] net: bpfilter: restart bpfilter_umh when error occurred Date: Mon, 7 Jan 2019 21:11:10 +0900 Message-Id: <20190107121110.13725-1-ap420073@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 $ iptables -vnL [ 480.045136] bpfilter: write fail -32 $ iptables -vnL All iptables commands will fail. After this patch, Test commands: $ iptables -vnL $ kill -9 $ iptables -vnL $ iptables -vnL Now, all iptables commands will work. Fixes: d2ba09c17a06 ("net: add skeleton of bpfilter kernel module") Signed-off-by: Taehee Yoo --- include/linux/bpfilter.h | 2 ++ net/bpfilter/bpfilter_kern.c | 35 +++++++++++++++++++++++--------- net/bpfilter/bpfilter_umh_blob.S | 2 +- net/ipv4/bpfilter/sockopt.c | 11 +++++++++- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/include/linux/bpfilter.h b/include/linux/bpfilter.h index 70ffeed280e9..8ebcbdd70bdc 100644 --- a/include/linux/bpfilter.h +++ b/include/linux/bpfilter.h @@ -15,6 +15,8 @@ struct bpfilter_umh_ops { int (*sockopt)(struct sock *sk, int optname, char __user *optval, unsigned int optlen, bool is_set); + int (*start)(void); + bool stop; }; extern struct bpfilter_umh_ops bpfilter_ops; #endif diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index a68940b74c01..33d6b159ba88 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c @@ -16,13 +16,14 @@ extern char bpfilter_umh_end; /* since ip_getsockopt() can run in parallel, serialize access to umh */ static DEFINE_MUTEX(bpfilter_lock); -static void shutdown_umh(struct umh_info *info) +static void shutdown_umh(void) { struct task_struct *tsk; - if (!info->pid) + if (bpfilter_ops.stop) return; - tsk = get_pid_task(find_vpid(info->pid), PIDTYPE_PID); + + tsk = get_pid_task(find_vpid(bpfilter_ops.info.pid), PIDTYPE_PID); if (tsk) { force_sig(SIGKILL, tsk); put_task_struct(tsk); @@ -31,10 +32,8 @@ static void shutdown_umh(struct umh_info *info) static void __stop_umh(void) { - if (IS_ENABLED(CONFIG_INET)) { - bpfilter_ops.sockopt = NULL; - shutdown_umh(&bpfilter_ops.info); - } + if (IS_ENABLED(CONFIG_INET)) + shutdown_umh(); } static void stop_umh(void) @@ -85,7 +84,7 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname, return ret; } -static int __init load_umh(void) +static int start_umh(void) { int err; @@ -95,6 +94,7 @@ static int __init load_umh(void) &bpfilter_ops.info); if (err) return err; + bpfilter_ops.stop = false; pr_info("Loaded bpfilter_umh pid %d\n", bpfilter_ops.info.pid); /* health check that usermode process started correctly */ @@ -102,14 +102,29 @@ static int __init load_umh(void) stop_umh(); return -EFAULT; } - if (IS_ENABLED(CONFIG_INET)) - bpfilter_ops.sockopt = &__bpfilter_process_sockopt; return 0; } +static int __init load_umh(void) +{ + int err; + + err = start_umh(); + if (!err && IS_ENABLED(CONFIG_INET)) { + bpfilter_ops.sockopt = &__bpfilter_process_sockopt; + bpfilter_ops.start = &start_umh; + } + + return err; +} + static void __exit fini_umh(void) { + if (IS_ENABLED(CONFIG_INET)) { + bpfilter_ops.start = NULL; + bpfilter_ops.sockopt = 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 c326cfbc0f62..de84ede4e765 100644 --- a/net/ipv4/bpfilter/sockopt.c +++ b/net/ipv4/bpfilter/sockopt.c @@ -14,6 +14,7 @@ EXPORT_SYMBOL_GPL(bpfilter_ops); static void bpfilter_umh_cleanup(struct umh_info *info) { + bpfilter_ops.stop = true; fput(info->pipe_to_umh); fput(info->pipe_from_umh); info->pid = 0; @@ -23,14 +24,21 @@ static int bpfilter_mbox_request(struct sock *sk, int optname, char __user *optval, unsigned int optlen, bool is_set) { + int err; + if (!bpfilter_ops.sockopt) { - int err = request_module("bpfilter"); + err = request_module("bpfilter"); if (err) return err; if (!bpfilter_ops.sockopt) return -ECHILD; } + if (bpfilter_ops.stop) { + err = bpfilter_ops.start(); + if (err) + return err; + } return bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set); } @@ -53,6 +61,7 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval, static int __init bpfilter_sockopt_init(void) { + bpfilter_ops.stop = true; bpfilter_ops.info.cmdline = "bpfilter_umh"; bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup; From patchwork Mon Jan 7 12:11:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Taehee Yoo X-Patchwork-Id: 1021284 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="SU3RxPI0"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43YDlM4bmPz9sNK for ; Mon, 7 Jan 2019 23:11:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727001AbfAGMLh (ORCPT ); Mon, 7 Jan 2019 07:11:37 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:45739 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726485AbfAGMLh (ORCPT ); Mon, 7 Jan 2019 07:11:37 -0500 Received: by mail-pf1-f193.google.com with SMTP id g62so51956pfd.12; Mon, 07 Jan 2019 04:11:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=Aa5tu8ePszw0nciQVUDoZTAH6B34pZH2n0LXGrrctAQ=; b=SU3RxPI0dxYHMzRF3VJJYoPHcHD4uCEMdXNO6V59r7a6DrDweht6LWAlPshHk7zrfN 7qbvzSbMDpt0njnB4MGqbVhwmL0qWbdZZjzFpdhbZ1P0mFOVHkZiJg8zVu2gCFzJIcPR 55xarbPjnkIOFhDNJY8LHJIEuuwBV4NPQzneBUcs+2QDosKaJbOBtWnZD+5t+QKlzOzi 9XP+faxytjdjaNVevnT6qYq3qm6kb6rd5RijfZIKGyu6ChD0QdbyX8CDn8KN55o/MlDv rXxEW05Ne3asZjDo9kCqBxVfsCSi1yfeMxDL25ptMdB64+O2fOAozGgp9j9kLKGDuiTr lwXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=Aa5tu8ePszw0nciQVUDoZTAH6B34pZH2n0LXGrrctAQ=; b=gZ2I2iC4ZLK4u2CLdPz38WSWHQkhq8JDxhjjshlP26bloKUOSXgJ/RA4w9vH70Z0Vj 3byDrG6v1cy6OpZ1Z1kogC5xVUN77djh1a/bNMU7l5SRNRHGROM+oqA1S0YUsVl9yVCY zOiqu8p23ILE/AyYnsyHy8KQlLcwyNUlEPGrzWFVHKfVW48y5XmTX69FN5cBQK7swO8M 2GzZY8vKJ7AJazo9pa0PG2i7v6rZfkhzdcv+eojV8rzMARq4+VG/CWrCQmOGevjt27bw 5Gdw3X4ZM45GMD3PEeeLBpgVSoGYin4FD+LasvfUt+uHSBbM6M3KiphgIO/LwUEiSpvh 6WWg== X-Gm-Message-State: AJcUukfUgmjiNiXkc01etdheqqV0MeE64pMAmZf8QvImSDzAr9EgUkea xl1eeiLasXOjo+sOEmOpYlE= X-Google-Smtp-Source: ALg8bN4yKRukNu2STSFS/7YeDCKzMxMNSgxvWzREQZI9E4tJVDY7IKZ/f+zRDMRN5U80cV38DoswHQ== X-Received: by 2002:a63:5f50:: with SMTP id t77mr10761603pgb.76.1546863095611; Mon, 07 Jan 2019 04:11:35 -0800 (PST) Received: from ap-To-be-filled-by-O-E-M.8.8.8.8 ([14.33.120.60]) by smtp.gmail.com with ESMTPSA id u123sm87665077pfb.1.2019.01.07.04.11.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Jan 2019 04:11:34 -0800 (PST) From: Taehee Yoo To: davem@davemloft.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, daniel@iogearbox.net, ast@kernel.org, mcgrof@kernel.org Cc: ap420073@gmail.com Subject: [PATCH net v3 4/4] net: bpfilter: disallow to remove bpfilter module while being used Date: Mon, 7 Jan 2019 21:11:28 +0900 Message-Id: <20190107121128.13878-1-ap420073@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The bpfilter.ko module can be removed while functions of the bpfilter.ko are executing. so panic can occurred. in order to protect that, locks can be used. a bpfilter_lock protects routines in the __bpfilter_process_sockopt() but it's not enough because __exit routine can be executed concurrently. Now, the bpfilter_umh can not run in parallel. So, the module do not removed while it's being used and it do not double-create UMH process. The members of the umh_info and the bpfilter_umh_ops are protected by the bpfilter_umh_ops.lock. test commands: while : do iptables -I FORWARD -m string --string ap --algo kmp & modprobe -rv bpfilter & done splat looks like: [ 298.623435] BUG: unable to handle kernel paging request at fffffbfff807440b [ 298.628512] #PF error: [normal kernel read fault] [ 298.633018] PGD 124327067 P4D 124327067 PUD 11c1a3067 PMD 119eb2067 PTE 0 [ 298.638859] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN PTI [ 298.638859] CPU: 0 PID: 2997 Comm: iptables Not tainted 4.20.0+ #154 [ 298.638859] RIP: 0010:__mutex_lock+0x6b9/0x16a0 [ 298.638859] Code: c0 00 00 e8 89 82 ff ff 80 bd 8f fc ff ff 00 0f 85 d9 05 00 00 48 8b 85 80 fc ff ff 48 bf 00 00 00 00 00 fc ff df 48 c1 e8 03 <80> 3c 38 00 0f 85 1d 0e 00 00 48 8b 85 c8 fc ff ff 49 39 47 58 c6 [ 298.638859] RSP: 0018:ffff88810e7777a0 EFLAGS: 00010202 [ 298.638859] RAX: 1ffffffff807440b RBX: ffff888111bd4d80 RCX: 0000000000000000 [ 298.638859] RDX: 1ffff110235ff806 RSI: ffff888111bd5538 RDI: dffffc0000000000 [ 298.638859] RBP: ffff88810e777b30 R08: 0000000080000002 R09: 0000000000000000 [ 298.638859] R10: 0000000000000000 R11: 0000000000000000 R12: fffffbfff168a42c [ 298.638859] R13: ffff888111bd4d80 R14: ffff8881040e9a05 R15: ffffffffc03a2000 [ 298.638859] FS: 00007f39e3758700(0000) GS:ffff88811ae00000(0000) knlGS:0000000000000000 [ 298.638859] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 298.638859] CR2: fffffbfff807440b CR3: 000000011243e000 CR4: 00000000001006f0 [ 298.638859] Call Trace: [ 298.638859] ? mutex_lock_io_nested+0x1560/0x1560 [ 298.638859] ? kasan_kmalloc+0xa0/0xd0 [ 298.638859] ? kmem_cache_alloc+0x1c2/0x260 [ 298.638859] ? __alloc_file+0x92/0x3c0 [ 298.638859] ? alloc_empty_file+0x43/0x120 [ 298.638859] ? alloc_file_pseudo+0x220/0x330 [ 298.638859] ? sock_alloc_file+0x39/0x160 [ 298.638859] ? __sys_socket+0x113/0x1d0 [ 298.638859] ? __x64_sys_socket+0x6f/0xb0 [ 298.638859] ? do_syscall_64+0x138/0x560 [ 298.638859] ? entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 298.638859] ? __alloc_file+0x92/0x3c0 [ 298.638859] ? init_object+0x6b/0x80 [ 298.638859] ? cyc2ns_read_end+0x10/0x10 [ 298.638859] ? cyc2ns_read_end+0x10/0x10 [ 298.638859] ? hlock_class+0x140/0x140 [ 298.638859] ? sched_clock_local+0xd4/0x140 [ 298.638859] ? sched_clock_local+0xd4/0x140 [ 298.638859] ? check_flags.part.37+0x440/0x440 [ 298.638859] ? __lock_acquire+0x4f90/0x4f90 [ 298.638859] ? set_rq_offline.part.89+0x140/0x140 [ ... ] Fixes: d2ba09c17a06 ("net: add skeleton of bpfilter kernel module") Signed-off-by: Taehee Yoo --- include/linux/bpfilter.h | 2 ++ net/bpfilter/bpfilter_kern.c | 20 ++++++-------------- net/ipv4/bpfilter/sockopt.c | 21 ++++++++++++++++----- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/include/linux/bpfilter.h b/include/linux/bpfilter.h index 8ebcbdd70bdc..d815622cd31e 100644 --- a/include/linux/bpfilter.h +++ b/include/linux/bpfilter.h @@ -12,6 +12,8 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval, int __user *optlen); struct bpfilter_umh_ops { struct umh_info info; + /* since ip_getsockopt() can run in parallel, serialize access to umh */ + struct mutex lock; int (*sockopt)(struct sock *sk, int optname, char __user *optval, unsigned int optlen, bool is_set); diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index 33d6b159ba88..eedb83863cb0 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c @@ -13,9 +13,6 @@ extern char bpfilter_umh_start; extern char bpfilter_umh_end; -/* since ip_getsockopt() can run in parallel, serialize access to umh */ -static DEFINE_MUTEX(bpfilter_lock); - static void shutdown_umh(void) { struct task_struct *tsk; @@ -36,13 +33,6 @@ static void __stop_umh(void) shutdown_umh(); } -static void stop_umh(void) -{ - mutex_lock(&bpfilter_lock); - __stop_umh(); - mutex_unlock(&bpfilter_lock); -} - static int __bpfilter_process_sockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen, bool is_set) @@ -58,7 +48,6 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname, req.cmd = optname; req.addr = (long __force __user)optval; req.len = optlen; - mutex_lock(&bpfilter_lock); if (!bpfilter_ops.info.pid) goto out; n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req), @@ -80,7 +69,6 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname, } ret = reply.status; out: - mutex_unlock(&bpfilter_lock); return ret; } @@ -99,7 +87,7 @@ static int start_umh(void) /* health check that usermode process started correctly */ if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) { - stop_umh(); + shutdown_umh(); return -EFAULT; } @@ -110,22 +98,26 @@ static int __init load_umh(void) { int err; + mutex_lock(&bpfilter_ops.lock); err = start_umh(); if (!err && IS_ENABLED(CONFIG_INET)) { bpfilter_ops.sockopt = &__bpfilter_process_sockopt; bpfilter_ops.start = &start_umh; } + mutex_unlock(&bpfilter_ops.lock); return err; } static void __exit fini_umh(void) { + mutex_lock(&bpfilter_ops.lock); if (IS_ENABLED(CONFIG_INET)) { + shutdown_umh(); bpfilter_ops.start = NULL; bpfilter_ops.sockopt = NULL; } - stop_umh(); + mutex_unlock(&bpfilter_ops.lock); } module_init(load_umh); module_exit(fini_umh); diff --git a/net/ipv4/bpfilter/sockopt.c b/net/ipv4/bpfilter/sockopt.c index de84ede4e765..2611f7a7f3d1 100644 --- a/net/ipv4/bpfilter/sockopt.c +++ b/net/ipv4/bpfilter/sockopt.c @@ -14,10 +14,12 @@ EXPORT_SYMBOL_GPL(bpfilter_ops); static void bpfilter_umh_cleanup(struct umh_info *info) { + mutex_lock(&bpfilter_ops.lock); bpfilter_ops.stop = true; fput(info->pipe_to_umh); fput(info->pipe_from_umh); info->pid = 0; + mutex_unlock(&bpfilter_ops.lock); } static int bpfilter_mbox_request(struct sock *sk, int optname, @@ -26,20 +28,28 @@ static int bpfilter_mbox_request(struct sock *sk, int optname, { int err; + mutex_lock(&bpfilter_ops.lock); if (!bpfilter_ops.sockopt) { + mutex_unlock(&bpfilter_ops.lock); err = request_module("bpfilter"); + mutex_lock(&bpfilter_ops.lock); if (err) - return err; - if (!bpfilter_ops.sockopt) - return -ECHILD; + goto out; + if (!bpfilter_ops.sockopt) { + err = -ECHILD; + goto out; + } } if (bpfilter_ops.stop) { err = bpfilter_ops.start(); if (err) - return err; + goto out; } - return bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set); + err = bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set); +out: + mutex_unlock(&bpfilter_ops.lock); + return err; } int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval, @@ -61,6 +71,7 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval, static int __init bpfilter_sockopt_init(void) { + mutex_init(&bpfilter_ops.lock); bpfilter_ops.stop = true; bpfilter_ops.info.cmdline = "bpfilter_umh"; bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup;