Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp3730829ybv; Mon, 10 Feb 2020 05:28:08 -0800 (PST) X-Google-Smtp-Source: APXvYqycD1UR5OtDf4mlfUKNg+57drGF/+hjVPnWE9OVueqm2gUTbEMSE36YGjrJz3TA3y+hRcwH X-Received: by 2002:a9d:6a85:: with SMTP id l5mr1091357otq.231.1581341288354; Mon, 10 Feb 2020 05:28:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1581341288; cv=none; d=google.com; s=arc-20160816; b=ib6oqYxgDrCHkuXrOdRZBlnzDxkC5G+4jW9eXdNf4WHQ2x7R4pzC4KTM6FhANiBjVu gCN75aTg+gA9flHI64XLQm0YJUKN1UTw0L4PGvDp9WYndpzXUH5n8S4hDnN1GTKf2bg/ E07aRKKY/fRVEcMMyMmiA60ndJs2iyF58IjzZ86ZvGRvTj6Bpp7cq0HD0e6eQ06m+3Yu HfQlHXM6FVXeJbwnxBefME5Tzpc0ZSWXoy5PZJSltSVw2pDj2ltL6u2eIQSaHBFMeT+9 9TlrxvFaL8q8n1BwDqP1cR75MdsctZGQElu0w12SOJ6+7KFiP227TFVA1LRwSGfPwG3w /kBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=cDEd2kru9/s3i/0hmQ6lkYx+E60r40OmlmC3Korrqr0=; b=ZvE6XQcIjMzE1ij7YFrE0VJ8204szTxRIla02v+fr3wtWIhFj15w5+8lfDh2kAy3Y1 9JIOoVNbvDwmP9/5FMnAOzbqybQrLvWQSe/kfEtLTrmiJx92K90hF1Q+jlFuY4oE1omu i6pxpn6AxbqUGexKmuYh08av7jRMYI6PCdIIBWMhP2onYjAIiEVe+MONFRpl0/vD+euS 97usL4k1JaYnmB0hQS8X5JP+vknrwr/x2WKUJU8Ko6ArEU6gTLjY+nWtPcjsZniY3EAP FKEkJzqb8SSINzHJuFrxyGImtcoVms0Gk49jIIfxkamWHpG49B7HmlYrMl945Bs040IN S8JQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=rLL7QjaZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l204si190076oig.31.2020.02.10.05.27.56; Mon, 10 Feb 2020 05:28:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=rLL7QjaZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730056AbgBJN0d (ORCPT + 99 others); Mon, 10 Feb 2020 08:26:33 -0500 Received: from mail.kernel.org ([198.145.29.99]:56566 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728171AbgBJMgp (ORCPT ); Mon, 10 Feb 2020 07:36:45 -0500 Received: from localhost (unknown [209.37.97.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2705D2051A; Mon, 10 Feb 2020 12:36:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581338205; bh=Pc8XaB47gADrFMI9/mbODYIk60bOy2wSiw2J88lHDuE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rLL7QjaZgi9fBi++vwz4mu7tsQrBV+E+oFxVBlyJmhHsZOEwz1eOoZ/ketA2bdtJ3 FFV/syYBRj8LNK5Ck8xOSs0vrke+KJs0INFLkypQHkeySrYT2kP0wp7+jFMWCcI7QV dGyRxOgxUiWsur0ITEXHmOXVcM5U9Q8miLSPgxVE= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, syzbot+fc69d7cb21258ab4ae4d@syzkaller.appspotmail.com, Jozsef Kadlecsik , Pablo Neira Ayuso Subject: [PATCH 5.4 024/309] netfilter: ipset: fix suspicious RCU usage in find_set_and_id Date: Mon, 10 Feb 2020 04:29:40 -0800 Message-Id: <20200210122408.310860575@linuxfoundation.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200210122406.106356946@linuxfoundation.org> References: <20200210122406.106356946@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kadlecsik József commit 5038517119d50ed0240059b1d7fc2faa92371c08 upstream. find_set_and_id() is called when the NFNL_SUBSYS_IPSET mutex is held. However, in the error path there can be a follow-up recvmsg() without the mutex held. Use the start() function of struct netlink_dump_control instead of dump() to verify and report if the specified set does not exist. Thanks to Pablo Neira Ayuso for helping me to understand the subleties of the netlink protocol. Reported-by: syzbot+fc69d7cb21258ab4ae4d@syzkaller.appspotmail.com Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/ipset/ip_set_core.c | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -1293,31 +1293,34 @@ ip_set_dump_policy[IPSET_ATTR_CMD_MAX + }; static int -dump_init(struct netlink_callback *cb, struct ip_set_net *inst) +ip_set_dump_start(struct netlink_callback *cb) { struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); int min_len = nlmsg_total_size(sizeof(struct nfgenmsg)); struct nlattr *cda[IPSET_ATTR_CMD_MAX + 1]; struct nlattr *attr = (void *)nlh + min_len; + struct sk_buff *skb = cb->skb; + struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk)); u32 dump_type; - ip_set_id_t index; int ret; ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, attr, nlh->nlmsg_len - min_len, ip_set_dump_policy, NULL); if (ret) - return ret; + goto error; cb->args[IPSET_CB_PROTO] = nla_get_u8(cda[IPSET_ATTR_PROTOCOL]); if (cda[IPSET_ATTR_SETNAME]) { + ip_set_id_t index; struct ip_set *set; set = find_set_and_id(inst, nla_data(cda[IPSET_ATTR_SETNAME]), &index); - if (!set) - return -ENOENT; - + if (!set) { + ret = -ENOENT; + goto error; + } dump_type = DUMP_ONE; cb->args[IPSET_CB_INDEX] = index; } else { @@ -1333,10 +1336,17 @@ dump_init(struct netlink_callback *cb, s cb->args[IPSET_CB_DUMP] = dump_type; return 0; + +error: + /* We have to create and send the error message manually :-( */ + if (nlh->nlmsg_flags & NLM_F_ACK) { + netlink_ack(cb->skb, nlh, ret, NULL); + } + return ret; } static int -ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) +ip_set_dump_do(struct sk_buff *skb, struct netlink_callback *cb) { ip_set_id_t index = IPSET_INVALID_ID, max; struct ip_set *set = NULL; @@ -1347,18 +1357,8 @@ ip_set_dump_start(struct sk_buff *skb, s bool is_destroyed; int ret = 0; - if (!cb->args[IPSET_CB_DUMP]) { - ret = dump_init(cb, inst); - if (ret < 0) { - nlh = nlmsg_hdr(cb->skb); - /* We have to create and send the error message - * manually :-( - */ - if (nlh->nlmsg_flags & NLM_F_ACK) - netlink_ack(cb->skb, nlh, ret, NULL); - return ret; - } - } + if (!cb->args[IPSET_CB_DUMP]) + return -EINVAL; if (cb->args[IPSET_CB_INDEX] >= inst->ip_set_max) goto out; @@ -1494,7 +1494,8 @@ static int ip_set_dump(struct net *net, { struct netlink_dump_control c = { - .dump = ip_set_dump_start, + .start = ip_set_dump_start, + .dump = ip_set_dump_do, .done = ip_set_dump_done, }; return netlink_dump_start(ctnl, skb, nlh, &c);