From: Greg Kroah-Hartman Date: Mon, 1 Mar 2021 16:07:09 +0000 (+0100) Subject: 5.11-stable patches X-Git-Tag: v4.4.259~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a15ddfc3cd600b31862fdde91f8988e1cfc7bffe;p=thirdparty%2Fkernel%2Fstable-queue.git 5.11-stable patches added patches: net-qrtr-fix-memory-leak-in-qrtr_tun_open.patch net_sched-fix-rtnl-deadlock-again-caused-by-request_module.patch --- diff --git a/queue-5.11/net-qrtr-fix-memory-leak-in-qrtr_tun_open.patch b/queue-5.11/net-qrtr-fix-memory-leak-in-qrtr_tun_open.patch new file mode 100644 index 00000000000..5b6018f8356 --- /dev/null +++ b/queue-5.11/net-qrtr-fix-memory-leak-in-qrtr_tun_open.patch @@ -0,0 +1,75 @@ +From fc0494ead6398609c49afa37bc949b61c5c16b91 Mon Sep 17 00:00:00 2001 +From: Takeshi Misawa +Date: Mon, 22 Feb 2021 08:44:27 +0900 +Subject: net: qrtr: Fix memory leak in qrtr_tun_open + +From: Takeshi Misawa + +commit fc0494ead6398609c49afa37bc949b61c5c16b91 upstream. + +If qrtr_endpoint_register() failed, tun is leaked. +Fix this, by freeing tun in error path. + +syzbot report: +BUG: memory leak +unreferenced object 0xffff88811848d680 (size 64): + comm "syz-executor684", pid 10171, jiffies 4294951561 (age 26.070s) + hex dump (first 32 bytes): + 80 dd 0a 84 ff ff ff ff 00 00 00 00 00 00 00 00 ................ + 90 d6 48 18 81 88 ff ff 90 d6 48 18 81 88 ff ff ..H.......H..... + backtrace: + [<0000000018992a50>] kmalloc include/linux/slab.h:552 [inline] + [<0000000018992a50>] kzalloc include/linux/slab.h:682 [inline] + [<0000000018992a50>] qrtr_tun_open+0x22/0x90 net/qrtr/tun.c:35 + [<0000000003a453ef>] misc_open+0x19c/0x1e0 drivers/char/misc.c:141 + [<00000000dec38ac8>] chrdev_open+0x10d/0x340 fs/char_dev.c:414 + [<0000000079094996>] do_dentry_open+0x1e6/0x620 fs/open.c:817 + [<000000004096d290>] do_open fs/namei.c:3252 [inline] + [<000000004096d290>] path_openat+0x74a/0x1b00 fs/namei.c:3369 + [<00000000b8e64241>] do_filp_open+0xa0/0x190 fs/namei.c:3396 + [<00000000a3299422>] do_sys_openat2+0xed/0x230 fs/open.c:1172 + [<000000002c1bdcef>] do_sys_open fs/open.c:1188 [inline] + [<000000002c1bdcef>] __do_sys_openat fs/open.c:1204 [inline] + [<000000002c1bdcef>] __se_sys_openat fs/open.c:1199 [inline] + [<000000002c1bdcef>] __x64_sys_openat+0x7f/0xe0 fs/open.c:1199 + [<00000000f3a5728f>] do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 + [<000000004b38b7ec>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fixes: 28fb4e59a47d ("net: qrtr: Expose tunneling endpoint to user space") +Reported-by: syzbot+5d6e4af21385f5cfc56a@syzkaller.appspotmail.com +Signed-off-by: Takeshi Misawa +Link: https://lore.kernel.org/r/20210221234427.GA2140@DESKTOP +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/qrtr/tun.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/net/qrtr/tun.c ++++ b/net/qrtr/tun.c +@@ -31,6 +31,7 @@ static int qrtr_tun_send(struct qrtr_end + static int qrtr_tun_open(struct inode *inode, struct file *filp) + { + struct qrtr_tun *tun; ++ int ret; + + tun = kzalloc(sizeof(*tun), GFP_KERNEL); + if (!tun) +@@ -43,7 +44,16 @@ static int qrtr_tun_open(struct inode *i + + filp->private_data = tun; + +- return qrtr_endpoint_register(&tun->ep, QRTR_EP_NID_AUTO); ++ ret = qrtr_endpoint_register(&tun->ep, QRTR_EP_NID_AUTO); ++ if (ret) ++ goto out; ++ ++ return 0; ++ ++out: ++ filp->private_data = NULL; ++ kfree(tun); ++ return ret; + } + + static ssize_t qrtr_tun_read_iter(struct kiocb *iocb, struct iov_iter *to) diff --git a/queue-5.11/net_sched-fix-rtnl-deadlock-again-caused-by-request_module.patch b/queue-5.11/net_sched-fix-rtnl-deadlock-again-caused-by-request_module.patch new file mode 100644 index 00000000000..3302b638632 --- /dev/null +++ b/queue-5.11/net_sched-fix-rtnl-deadlock-again-caused-by-request_module.patch @@ -0,0 +1,311 @@ +From d349f997686887906b1183b5be96933c5452362a Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Sat, 16 Jan 2021 16:56:57 -0800 +Subject: net_sched: fix RTNL deadlock again caused by request_module() + +From: Cong Wang + +commit d349f997686887906b1183b5be96933c5452362a upstream. + +tcf_action_init_1() loads tc action modules automatically with +request_module() after parsing the tc action names, and it drops RTNL +lock and re-holds it before and after request_module(). This causes a +lot of troubles, as discovered by syzbot, because we can be in the +middle of batch initializations when we create an array of tc actions. + +One of the problem is deadlock: + +CPU 0 CPU 1 +rtnl_lock(); +for (...) { + tcf_action_init_1(); + -> rtnl_unlock(); + -> request_module(); + rtnl_lock(); + for (...) { + tcf_action_init_1(); + -> tcf_idr_check_alloc(); + // Insert one action into idr, + // but it is not committed until + // tcf_idr_insert_many(), then drop + // the RTNL lock in the _next_ + // iteration + -> rtnl_unlock(); + -> rtnl_lock(); + -> a_o->init(); + -> tcf_idr_check_alloc(); + // Now waiting for the same index + // to be committed + -> request_module(); + -> rtnl_lock() + // Now waiting for RTNL lock + } + rtnl_unlock(); +} +rtnl_unlock(); + +This is not easy to solve, we can move the request_module() before +this loop and pre-load all the modules we need for this netlink +message and then do the rest initializations. So the loop breaks down +to two now: + + for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { + struct tc_action_ops *a_o; + + a_o = tc_action_load_ops(name, tb[i]...); + ops[i - 1] = a_o; + } + + for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { + act = tcf_action_init_1(ops[i - 1]...); + } + +Although this looks serious, it only has been reported by syzbot, so it +seems hard to trigger this by humans. And given the size of this patch, +I'd suggest to make it to net-next and not to backport to stable. + +This patch has been tested by syzbot and tested with tdc.py by me. + +Fixes: 0fedc63fadf0 ("net_sched: commit action insertions together") +Reported-and-tested-by: syzbot+82752bc5331601cf4899@syzkaller.appspotmail.com +Reported-and-tested-by: syzbot+b3b63b6bff456bd95294@syzkaller.appspotmail.com +Reported-by: syzbot+ba67b12b1ca729912834@syzkaller.appspotmail.com +Cc: Jiri Pirko +Signed-off-by: Cong Wang +Tested-by: Jamal Hadi Salim +Acked-by: Jamal Hadi Salim +Link: https://lore.kernel.org/r/20210117005657.14810-1-xiyou.wangcong@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + include/net/act_api.h | 5 +- + net/sched/act_api.c | 104 +++++++++++++++++++++++++++++++------------------- + net/sched/cls_api.c | 11 ++++- + 3 files changed, 79 insertions(+), 41 deletions(-) + +--- a/include/net/act_api.h ++++ b/include/net/act_api.h +@@ -187,10 +187,13 @@ int tcf_action_init(struct net *net, str + struct nlattr *est, char *name, int ovr, int bind, + struct tc_action *actions[], size_t *attr_size, + bool rtnl_held, struct netlink_ext_ack *extack); ++struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, ++ bool rtnl_held, ++ struct netlink_ext_ack *extack); + struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, + struct nlattr *nla, struct nlattr *est, + char *name, int ovr, int bind, +- bool rtnl_held, ++ struct tc_action_ops *ops, bool rtnl_held, + struct netlink_ext_ack *extack); + int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind, + int ref, bool terse); +--- a/net/sched/act_api.c ++++ b/net/sched/act_api.c +@@ -928,19 +928,13 @@ void tcf_idr_insert_many(struct tc_actio + } + } + +-struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, +- struct nlattr *nla, struct nlattr *est, +- char *name, int ovr, int bind, +- bool rtnl_held, +- struct netlink_ext_ack *extack) ++struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, ++ bool rtnl_held, ++ struct netlink_ext_ack *extack) + { +- struct nla_bitfield32 flags = { 0, 0 }; +- u8 hw_stats = TCA_ACT_HW_STATS_ANY; +- struct tc_action *a; ++ struct nlattr *tb[TCA_ACT_MAX + 1]; + struct tc_action_ops *a_o; +- struct tc_cookie *cookie = NULL; + char act_name[IFNAMSIZ]; +- struct nlattr *tb[TCA_ACT_MAX + 1]; + struct nlattr *kind; + int err; + +@@ -948,33 +942,21 @@ struct tc_action *tcf_action_init_1(stru + err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, + tcf_action_policy, extack); + if (err < 0) +- goto err_out; ++ return ERR_PTR(err); + err = -EINVAL; + kind = tb[TCA_ACT_KIND]; + if (!kind) { + NL_SET_ERR_MSG(extack, "TC action kind must be specified"); +- goto err_out; ++ return ERR_PTR(err); + } + if (nla_strscpy(act_name, kind, IFNAMSIZ) < 0) { + NL_SET_ERR_MSG(extack, "TC action name too long"); +- goto err_out; ++ return ERR_PTR(err); + } +- if (tb[TCA_ACT_COOKIE]) { +- cookie = nla_memdup_cookie(tb); +- if (!cookie) { +- NL_SET_ERR_MSG(extack, "No memory to generate TC cookie"); +- err = -ENOMEM; +- goto err_out; +- } +- } +- hw_stats = tcf_action_hw_stats_get(tb[TCA_ACT_HW_STATS]); +- if (tb[TCA_ACT_FLAGS]) +- flags = nla_get_bitfield32(tb[TCA_ACT_FLAGS]); + } else { + if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) { + NL_SET_ERR_MSG(extack, "TC action name too long"); +- err = -EINVAL; +- goto err_out; ++ return ERR_PTR(-EINVAL); + } + } + +@@ -996,24 +978,56 @@ struct tc_action *tcf_action_init_1(stru + * indicate this using -EAGAIN. + */ + if (a_o != NULL) { +- err = -EAGAIN; +- goto err_mod; ++ module_put(a_o->owner); ++ return ERR_PTR(-EAGAIN); + } + #endif + NL_SET_ERR_MSG(extack, "Failed to load TC action module"); +- err = -ENOENT; +- goto err_free; ++ return ERR_PTR(-ENOENT); + } + ++ return a_o; ++} ++ ++struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, ++ struct nlattr *nla, struct nlattr *est, ++ char *name, int ovr, int bind, ++ struct tc_action_ops *a_o, bool rtnl_held, ++ struct netlink_ext_ack *extack) ++{ ++ struct nla_bitfield32 flags = { 0, 0 }; ++ u8 hw_stats = TCA_ACT_HW_STATS_ANY; ++ struct nlattr *tb[TCA_ACT_MAX + 1]; ++ struct tc_cookie *cookie = NULL; ++ struct tc_action *a; ++ int err; ++ + /* backward compatibility for policer */ +- if (name == NULL) ++ if (name == NULL) { ++ err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla, ++ tcf_action_policy, extack); ++ if (err < 0) ++ return ERR_PTR(err); ++ if (tb[TCA_ACT_COOKIE]) { ++ cookie = nla_memdup_cookie(tb); ++ if (!cookie) { ++ NL_SET_ERR_MSG(extack, "No memory to generate TC cookie"); ++ err = -ENOMEM; ++ goto err_out; ++ } ++ } ++ hw_stats = tcf_action_hw_stats_get(tb[TCA_ACT_HW_STATS]); ++ if (tb[TCA_ACT_FLAGS]) ++ flags = nla_get_bitfield32(tb[TCA_ACT_FLAGS]); ++ + err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind, + rtnl_held, tp, flags.value, extack); +- else ++ } else { + err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held, + tp, flags.value, extack); ++ } + if (err < 0) +- goto err_mod; ++ goto err_out; + + if (!name && tb[TCA_ACT_COOKIE]) + tcf_set_action_cookie(&a->act_cookie, cookie); +@@ -1030,14 +1044,11 @@ struct tc_action *tcf_action_init_1(stru + + return a; + +-err_mod: +- module_put(a_o->owner); +-err_free: ++err_out: + if (cookie) { + kfree(cookie->data); + kfree(cookie); + } +-err_out: + return ERR_PTR(err); + } + +@@ -1048,6 +1059,7 @@ int tcf_action_init(struct net *net, str + struct tc_action *actions[], size_t *attr_size, + bool rtnl_held, struct netlink_ext_ack *extack) + { ++ struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {}; + struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; + struct tc_action *act; + size_t sz = 0; +@@ -1060,8 +1072,19 @@ int tcf_action_init(struct net *net, str + return err; + + for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { ++ struct tc_action_ops *a_o; ++ ++ a_o = tc_action_load_ops(name, tb[i], rtnl_held, extack); ++ if (IS_ERR(a_o)) { ++ err = PTR_ERR(a_o); ++ goto err_mod; ++ } ++ ops[i - 1] = a_o; ++ } ++ ++ for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { + act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind, +- rtnl_held, extack); ++ ops[i - 1], rtnl_held, extack); + if (IS_ERR(act)) { + err = PTR_ERR(act); + goto err; +@@ -1081,6 +1104,11 @@ int tcf_action_init(struct net *net, str + + err: + tcf_action_destroy(actions, bind); ++err_mod: ++ for (i = 0; i < TCA_ACT_MAX_PRIO; i++) { ++ if (ops[i]) ++ module_put(ops[i]->owner); ++ } + return err; + } + +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -3043,12 +3043,19 @@ int tcf_exts_validate(struct net *net, s + size_t attr_size = 0; + + if (exts->police && tb[exts->police]) { ++ struct tc_action_ops *a_o; ++ ++ a_o = tc_action_load_ops("police", tb[exts->police], rtnl_held, extack); ++ if (IS_ERR(a_o)) ++ return PTR_ERR(a_o); + act = tcf_action_init_1(net, tp, tb[exts->police], + rate_tlv, "police", ovr, +- TCA_ACT_BIND, rtnl_held, ++ TCA_ACT_BIND, a_o, rtnl_held, + extack); +- if (IS_ERR(act)) ++ if (IS_ERR(act)) { ++ module_put(a_o->owner); + return PTR_ERR(act); ++ } + + act->type = exts->type = TCA_OLD_COMPAT; + exts->actions[0] = act; diff --git a/queue-5.11/series b/queue-5.11/series index 3ce2ce9dc21..827085223ac 100644 --- a/queue-5.11/series +++ b/queue-5.11/series @@ -771,3 +771,5 @@ net-icmp-pass-zeroed-opts-from-icmp-v6-_ndo_send-before-sending.patch wireguard-selftests-test-multiple-parallel-streams.patch wireguard-queueing-get-rid-of-per-peer-ring-buffers.patch net-sched-fix-police-ext-initialization.patch +net-qrtr-fix-memory-leak-in-qrtr_tun_open.patch +net_sched-fix-rtnl-deadlock-again-caused-by-request_module.patch