From patchwork Tue Apr 14 22:45:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Shearman X-Patchwork-Id: 461291 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 1D1B51402EA for ; Wed, 15 Apr 2015 08:47:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932362AbbDNWrO (ORCPT ); Tue, 14 Apr 2015 18:47:14 -0400 Received: from mx0b-000f0801.pphosted.com ([67.231.152.113]:57213 "EHLO mx0b-000f0801.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932286AbbDNWrK (ORCPT ); Tue, 14 Apr 2015 18:47:10 -0400 Received: from pps.filterd (m0048192.ppops.net [127.0.0.1]) by mx0b-000f0801.pphosted.com (8.14.7/8.14.7) with SMTP id t3ELphDK010291; Tue, 14 Apr 2015 15:47:09 -0700 Received: from brmwp-exchub02.corp.brocade.com ([208.47.132.227]) by mx0b-000f0801.pphosted.com with ESMTP id 1trmugbcqc-5 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT); Tue, 14 Apr 2015 15:47:09 -0700 Received: from EMEAWP-CASH01.corp.brocade.com (172.29.18.10) by BRMWP-EXCHUB02.corp.brocade.com (172.16.187.99) with Microsoft SMTP Server (TLS) id 14.3.123.3; Tue, 14 Apr 2015 16:47:07 -0600 Received: from BRA-2XN4P12.brocade.com (10.72.52.3) by imapeu.brocade.com (172.29.18.15) with Microsoft SMTP Server (TLS) id 8.3.298.1; Wed, 15 Apr 2015 00:46:51 +0200 From: Robert Shearman To: , CC: , Robert Shearman Subject: [PATCH net-next v4 3/6] mpls: Per-device enabling of packet input Date: Tue, 14 Apr 2015 23:45:00 +0100 Message-ID: <1429051503-31287-4-git-send-email-rshearma@brocade.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1429051503-31287-1-git-send-email-rshearma@brocade.com> References: <1427739356-28113-1-git-send-email-rshearma@brocade.com> <1429051503-31287-1-git-send-email-rshearma@brocade.com> MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.13.68, 1.0.33, 0.0.0000 definitions=2015-04-14_07:2015-04-14, 2015-04-14, 1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=2 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=7.0.1-1402240000 definitions=main-1504140182 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org An MPLS network is a single trust domain where the edges must be in control of what labels make their way into the core. The simplest way of ensuring this is for the edge device to always impose the labels, and not allow forward labeled traffic from untrusted neighbours. This is achieved by allowing a per-device configuration of whether MPLS traffic input from that interface should be processed or not. To be secure by default, the default state is changed to MPLS being disabled on all interfaces (except the loopback) unless explicitly enabled and no global option is provided to change the default. Whilst this differs from other protocols (e.g. IPv6), network operators are used to explicitly enabling MPLS forwarding on interfaces, and with the number of links to the MPLS core typically fairly low this doesn't present too much of a burden on operators. Cc: "Eric W. Biederman" Signed-off-by: Robert Shearman --- Documentation/networking/mpls-sysctl.txt | 9 ++++ net/mpls/af_mpls.c | 75 +++++++++++++++++++++++++++++++- net/mpls/internal.h | 3 ++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/mpls-sysctl.txt b/Documentation/networking/mpls-sysctl.txt index 639ddf0ece9b..9ed15f86c17c 100644 --- a/Documentation/networking/mpls-sysctl.txt +++ b/Documentation/networking/mpls-sysctl.txt @@ -18,3 +18,12 @@ platform_labels - INTEGER Possible values: 0 - 1048575 Default: 0 + +conf//input - BOOL + Control whether packets can be input on this interface. + + If disabled, packets will be discarded without further + processing. + + 0 - disabled (default) + not 0 - enabled diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 6e7a91ec1ae1..1fd303a87df4 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c @@ -150,7 +150,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, /* Careful this entire function runs inside of an rcu critical section */ mdev = mpls_dev_get(dev); - if (!mdev) + if (!mdev || !mdev->input_enabled) goto drop; if (skb->pkt_type != PACKET_HOST) @@ -438,6 +438,60 @@ errout: return err; } +#define MPLS_PERDEV_SYSCTL_OFFSET(field) \ + (&((struct mpls_dev *)0)->field) + +static const struct ctl_table mpls_dev_table[] = { + { + .procname = "input", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + .data = MPLS_PERDEV_SYSCTL_OFFSET(input_enabled), + }, + { } +}; + +static int mpls_dev_sysctl_register(struct net_device *dev, + struct mpls_dev *mdev) +{ + char path[sizeof("net/mpls/conf/") + IFNAMSIZ]; + struct ctl_table *table; + int i; + + table = kmemdup(&mpls_dev_table, sizeof(mpls_dev_table), GFP_KERNEL); + if (!table) + goto out; + + /* Table data contains only offsets relative to the base of + * the mdev at this point, so make them absolute. + */ + for (i = 0; i < ARRAY_SIZE(mpls_dev_table); i++) + table[i].data = (char *)mdev + (uintptr_t)table[i].data; + + snprintf(path, sizeof(path), "net/mpls/conf/%s", dev->name); + + mdev->sysctl = register_net_sysctl(dev_net(dev), path, table); + if (!mdev->sysctl) + goto free; + + return 0; + +free: + kfree(table); +out: + return -ENOBUFS; +} + +static void mpls_dev_sysctl_unregister(struct mpls_dev *mdev) +{ + struct ctl_table *table; + + table = mdev->sysctl->ctl_table_arg; + unregister_net_sysctl_table(mdev->sysctl); + kfree(table); +} + static struct mpls_dev *mpls_add_dev(struct net_device *dev) { struct mpls_dev *mdev; @@ -449,9 +503,24 @@ static struct mpls_dev *mpls_add_dev(struct net_device *dev) if (!mdev) return ERR_PTR(err); + /* Enable MPLS by default on loopback devices, since this + * doesn't represent a security boundary and is required for the + * lookup of inner labels for LSPs terminating on this router. + */ + if (dev->flags & IFF_LOOPBACK) + mdev->input_enabled = 1; + + err = mpls_dev_sysctl_register(dev, mdev); + if (err) + goto free; + rcu_assign_pointer(dev->mpls_ptr, mdev); return mdev; + +free: + kfree(mdev); + return ERR_PTR(err); } static void mpls_ifdown(struct net_device *dev) @@ -475,6 +544,8 @@ static void mpls_ifdown(struct net_device *dev) if (!mdev) return; + mpls_dev_sysctl_unregister(mdev); + RCU_INIT_POINTER(dev->mpls_ptr, NULL); kfree(mdev); @@ -958,7 +1029,7 @@ static int mpls_platform_labels(struct ctl_table *table, int write, return ret; } -static struct ctl_table mpls_table[] = { +static const struct ctl_table mpls_table[] = { { .procname = "platform_labels", .data = NULL, diff --git a/net/mpls/internal.h b/net/mpls/internal.h index 7de7e7850d1a..d0aad5e9a2c9 100644 --- a/net/mpls/internal.h +++ b/net/mpls/internal.h @@ -24,6 +24,9 @@ struct mpls_entry_decoded { }; struct mpls_dev { + int input_enabled; + + struct ctl_table_header *sysctl; }; struct sk_buff;