From patchwork Thu Jul 26 02:31:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Safonov X-Patchwork-Id: 949433 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=quarantine dis=none) header.from=arista.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=arista.com header.i=@arista.com header.b="OtPrFabd"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41bbjT3TSJz9s21 for ; Thu, 26 Jul 2018 12:32:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729369AbeGZDqg (ORCPT ); Wed, 25 Jul 2018 23:46:36 -0400 Received: from mail-ed1-f67.google.com ([209.85.208.67]:34127 "EHLO mail-ed1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728744AbeGZDqf (ORCPT ); Wed, 25 Jul 2018 23:46:35 -0400 Received: by mail-ed1-f67.google.com with SMTP id h1-v6so343169eds.1 for ; Wed, 25 Jul 2018 19:32:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=googlenew; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Q3uCbXfAPqyJnjkMv2GwF4Igrxwx6DSnJmHdsK7W6YI=; b=OtPrFabdEaXGRpoZgDSO3ywHRPcWXjyRJYwyhLW5HDljQnS7IgesMNHWsmZUAi+AFl C9FZARVN7yha3LcBkWQ5qF3CWbAjWn6zVR7/h89x6iTP51NBO3PDy7kgKbgCe6Kae1bD jN+fb4SGeerIdTChyzx62MBuJPA/xzUDBJMY6vs+X70BVScr83ADiwGbycKwSRF4jSai vYsxlDbdS1uOsCu+Ai6D+iepTrLZyNf2E9ZYlqvCs/7laNHf+c53s+KtD4gP/hm54ghV POhypYxXRkFv7b98eL5TnaCHl1VOWcGXNchNsXf8ZRqoxt4fldxCoDlxQeyQk3mVwQ8+ uM9g== 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:in-reply-to :references; bh=Q3uCbXfAPqyJnjkMv2GwF4Igrxwx6DSnJmHdsK7W6YI=; b=bb9/bXTVJuPIcTijnyrHBedpRON4peviE15eaqGaaQ2MRaK1mSlIIfGQBGKTTOHW7e 9HFpPcmYhWJifR6EiYs+2RGPYYrAdvpsm9sO1+R4GnqIotBoF95MzhfKRyV6P8bTkS7f mgKxBFgCLC9XsEVD1owWquoFDCpzVLJ8bUMxsPZ8X4BkSaqkbTWB6Wkn+SqbHD66m7p5 SFDEV7rLKdq6bZQtnWplZ6Y/X64Ob4L0IL/4mk0wKaWpVWahyHzCtK8+4pmEBVA2CEMX 6JA97OM4ymK1nB9NvQYrYhhrHScnu98BhozN+neQWaZqdd7qSRNEz/xJ3F9maDax/tli twUg== X-Gm-Message-State: AOUpUlGi9AgHWbZ5zYUfM7NXjwpvazRnH/N9YA+klBXe8RUr2oRcXkrb wM009U7SSRWZZXhcpmddcQrp4g== X-Google-Smtp-Source: AAOMgpcAInUKbv+eZPgrG/WA/bmS/BLxTtm4rvM3QsIXdjuGBslL1+q59gtkIDtr/AeMvMGChu9fVg== X-Received: by 2002:a50:83e6:: with SMTP id 93-v6mr483167edi.164.1532572321020; Wed, 25 Jul 2018 19:32:01 -0700 (PDT) Received: from dhcp.ire.aristanetworks.com ([217.173.96.166]) by smtp.gmail.com with ESMTPSA id x13-v6sm241024edx.17.2018.07.25.19.31.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 25 Jul 2018 19:32:00 -0700 (PDT) From: Dmitry Safonov To: linux-kernel@vger.kernel.org Cc: Dmitry Safonov , "David S. Miller" , Herbert Xu , Steffen Klassert , Dmitry Safonov <0x7f454c46@gmail.com>, netdev@vger.kernel.org Subject: [PATCH 13/18] xfrm: Add compat support for xfrm_user_acquire messages Date: Thu, 26 Jul 2018 03:31:39 +0100 Message-Id: <20180726023144.31066-14-dima@arista.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180726023144.31066-1-dima@arista.com> References: <20180726023144.31066-1-dima@arista.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Parse acquire messages sent by userspace according to in_compat_syscall(). Applications that used native bind() syscall are in XFRMNLGRP_ACQUIRE, so send there xfrm_usersa_info messages (with 64-bit ABI). Compatible applications are added to kernel-hidden XFRMNLGRP_COMPAT_ACQUIRE group, so send there xfrm_usersa_info messages_packed (with 32-bit ABI) Cc: "David S. Miller" Cc: Herbert Xu Cc: Steffen Klassert Cc: netdev@vger.kernel.org Signed-off-by: Dmitry Safonov --- net/xfrm/xfrm_user.c | 113 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 36 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index df792a3be8f2..89f891a0a9a4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -73,6 +73,17 @@ struct xfrm_user_expire_packed { __u8 __pad[3]; } __packed; +struct xfrm_user_acquire_packed { + struct xfrm_id id; + xfrm_address_t saddr; + struct xfrm_selector sel; + struct xfrm_userpolicy_info_packed policy; + __u32 aalgos; + __u32 ealgos; + __u32 calgos; + __u32 seq; +} __packed; + /* In-kernel, non-uapi compat groups. * As compat/native messages differ, send notifications according * to .bind() caller's ABI. There are *_COMPAT hidden from userspace @@ -2316,8 +2327,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr *rt = attrs[XFRMA_TMPL]; struct xfrm_mark mark; - struct xfrm_user_acquire *ua = nlmsg_data(nlh); - struct xfrm_userpolicy_info_packed *upi = (void *)&ua->policy; + struct xfrm_user_acquire_packed *ua = nlmsg_data(nlh); + struct xfrm_user_acquire *_ua = nlmsg_data(nlh); struct xfrm_state *x = xfrm_state_alloc(net); int err = -ENOMEM; @@ -2326,12 +2337,12 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, xfrm_mark_get(attrs, &mark); - err = verify_newpolicy_info(upi); + err = verify_newpolicy_info(&ua->policy); if (err) goto free_state; /* build an XP */ - xp = xfrm_policy_construct(net, upi, attrs, &err); + xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); if (!xp) goto free_state; @@ -2348,9 +2359,15 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, x->props.mode = t->mode; x->props.reqid = t->reqid; x->props.family = ut->family; - t->aalgos = ua->aalgos; - t->ealgos = ua->ealgos; - t->calgos = ua->calgos; + if (in_compat_syscall()) { + t->aalgos = ua->aalgos; + t->ealgos = ua->ealgos; + t->calgos = ua->calgos; + } else { + t->aalgos = _ua->aalgos; + t->ealgos = _ua->ealgos; + t->calgos = _ua->calgos; + } err = km_query(x, t, xp); } @@ -3017,25 +3034,32 @@ static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c } -static inline unsigned int xfrm_acquire_msgsize(struct xfrm_state *x, - struct xfrm_policy *xp) +static int build_acquire(struct sk_buff **skb, struct xfrm_state *x, + struct xfrm_tmpl *xt, struct xfrm_policy *xp, + bool compat) { - return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) + __u32 seq = xfrm_get_acqseq(); + struct xfrm_user_acquire_packed *ua; + struct nlmsghdr *nlh; + unsigned int ua_size, ack_msgsize; + int err; + + if (compat) + ua_size = NLMSG_ALIGN(sizeof(struct xfrm_user_acquire_packed)); + else + ua_size = NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)); + + ack_msgsize = ua_size + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) + nla_total_size(sizeof(struct xfrm_mark)) + nla_total_size(xfrm_user_sec_ctx_size(x->security)) + userpolicy_type_attrsize(); -} -static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, - struct xfrm_tmpl *xt, struct xfrm_policy *xp) -{ - __u32 seq = xfrm_get_acqseq(); - struct xfrm_user_acquire *ua; - struct nlmsghdr *nlh; - int err; + *skb = nlmsg_new(ack_msgsize, GFP_ATOMIC); + if (*skb == NULL) + return -ENOMEM; - nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0); + nlh = nlmsg_put(*skb, 0, 0, XFRM_MSG_ACQUIRE, ua_size, 0); if (nlh == NULL) return -EMSGSIZE; @@ -3043,25 +3067,36 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, memcpy(&ua->id, &x->id, sizeof(ua->id)); memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr)); memcpy(&ua->sel, &x->sel, sizeof(ua->sel)); - copy_to_user_policy(xp, &ua->policy, XFRM_POLICY_OUT); - ua->aalgos = xt->aalgos; - ua->ealgos = xt->ealgos; - ua->calgos = xt->calgos; - ua->seq = x->km.seq = seq; - err = copy_to_user_tmpl(xp, skb); + if (compat) { + copy_to_user_policy_compat(xp, &ua->policy, XFRM_POLICY_OUT); + ua->aalgos = xt->aalgos; + ua->ealgos = xt->ealgos; + ua->calgos = xt->calgos; + ua->seq = x->km.seq = seq; + } else { + struct xfrm_user_acquire *_ua = nlmsg_data(nlh); + + copy_to_user_policy(xp, &_ua->policy, XFRM_POLICY_OUT); + _ua->aalgos = xt->aalgos; + _ua->ealgos = xt->ealgos; + _ua->calgos = xt->calgos; + _ua->seq = x->km.seq = seq; + } + + err = copy_to_user_tmpl(xp, *skb); if (!err) - err = copy_to_user_state_sec_ctx(x, skb); + err = copy_to_user_state_sec_ctx(x, *skb); if (!err) - err = copy_to_user_policy_type(xp->type, skb); + err = copy_to_user_policy_type(xp->type, *skb); if (!err) - err = xfrm_mark_put(skb, &xp->mark); + err = xfrm_mark_put(*skb, &xp->mark); if (err) { - nlmsg_cancel(skb, nlh); + nlmsg_cancel(*skb, nlh); return err; } - nlmsg_end(skb, nlh); + nlmsg_end(*skb, nlh); return 0; } @@ -3072,14 +3107,20 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, struct sk_buff *skb; int err; - skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC); - if (skb == NULL) - return -ENOMEM; - err = build_acquire(skb, x, xt, xp); - BUG_ON(err < 0); + err = build_acquire(&skb, x, xt, xp, false); + if (err) + return err; + + err = xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_ACQUIRE); + if ((err && err != -ESRCH) || !IS_ENABLED(CONFIG_COMPAT)) + return err; + + err = build_acquire(&skb, x, xt, xp, true); + if (err) + return err; - return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_ACQUIRE); + return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_COMPAT_ACQUIRE); } /* User gives us xfrm_user_policy_info followed by an array of 0