Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] once: switch to new jump label API
From: Eric Biggers @ 2017-10-09 20:27 UTC (permalink / raw)
  To: Hannes Frederic Sowa
  Cc: David S. Miller, netdev, linux-kernel, Jason Baron,
	Peter Zijlstra, Eric Biggers
In-Reply-To: <20170916040751.GA14238@zzz.localdomain>

On Fri, Sep 15, 2017 at 09:07:51PM -0700, Eric Biggers wrote:
> On Tue, Aug 22, 2017 at 02:44:41PM -0400, Hannes Frederic Sowa wrote:
> > Eric Biggers <ebiggers3@gmail.com> writes:
> > 
> > > From: Eric Biggers <ebiggers@google.com>
> > >
> > > Switch the DO_ONCE() macro from the deprecated jump label API to the new
> > > one.  The new one is more readable, and for DO_ONCE() it also makes the
> > > generated code more icache-friendly: now the one-time initialization
> > > code is placed out-of-line at the jump target, rather than at the inline
> > > fallthrough case.
> > >
> > > Signed-off-by: Eric Biggers <ebiggers@google.com>
> > 
> > Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org.
> > 
> > Thanks!
> 
> Great!  Who though is the maintainer for this code?  It seems it was originally
> taken by David Miller through the networking tree.  David, are you taking
> further patches to the "once" functions, or should I be trying to get this into
> -mm, or somewhere else?
> 
> Eric

Ping.

^ permalink raw reply

* [net-next 0/3] ip_gre: a bunch of fixes for mtu
From: William Tu @ 2017-10-09 20:47 UTC (permalink / raw)
  To: netdev

The first two patches are to fix some issues for mtu and needed_headroom length
calculation from the gre and erspan tunnel header.  The last path tries to avoid
arithmetic operation for every packet when checking for erspan truncate.

William Tu (3):
  ip_gre: fix mtu and headroom size
  ip_gre: fix erspan tunnel mtu calculation
  ip_gre: cache the device mtu hard_header_len calc

 include/net/erspan.h     |  1 +
 include/net/ip_tunnels.h |  1 +
 net/ipv4/ip_gre.c        | 23 +++++++++++------------
 net/ipv4/ip_tunnel.c     |  3 +++
 4 files changed, 16 insertions(+), 12 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [net-next 1/3] ip_gre: fix mtu and headroom size
From: William Tu @ 2017-10-09 20:47 UTC (permalink / raw)
  To: netdev; +Cc: Tom Herbert
In-Reply-To: <1507582067-36718-1-git-send-email-u9012063@gmail.com>

The ip_gre_calc_hlen() already counts gre's base header len (4-byte)
plus optional header's len, so tunnel->hlen has the entire gre
headeri + options len. Thus, remove the -4 and +4 when calculating
the needed_headroom and mtu.

Fixes: 4565e9919cda ("gre: Setup and TX path for gre/UDP foo-over-udp encapsulation")
Signed-off-by: William Tu <u9012063@gmail.com>
Cc: Tom Herbert <tom@quantonium.net>
---
 net/ipv4/ip_gre.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index c105a315b1a3..286065c35959 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -947,8 +947,8 @@ static void __gre_tunnel_init(struct net_device *dev)
 
 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
-	dev->needed_headroom	= LL_MAX_HEADER + t_hlen + 4;
-	dev->mtu		= ETH_DATA_LEN - t_hlen - 4;
+	dev->needed_headroom	= LL_MAX_HEADER + t_hlen;
+	dev->mtu		= ETH_DATA_LEN - t_hlen;
 
 	dev->features		|= GRE_FEATURES;
 	dev->hw_features	|= GRE_FEATURES;
-- 
2.7.4

^ permalink raw reply related

* [net-next 2/3] ip_gre: fix erspan tunnel mtu calculation
From: William Tu @ 2017-10-09 20:47 UTC (permalink / raw)
  To: netdev; +Cc: Xin Long
In-Reply-To: <1507582067-36718-1-git-send-email-u9012063@gmail.com>

Remove the unnecessary -4 and +4 bytes at mtu and headroom calculation.
In addition, erspan uses fixed 8-byte gre header, so add ERSPAN_GREHDR_LEN
macro for better readability.

Now tunnel->hlen = grehdr(8) + erspanhdr(8) = 16 byte.
The mtu should be ETH_DATA_LEN - 16 - iph(20) = 1464.
After the ip_tunnel_bind_dev(), the mtu is adjusted to
1464 - 14 (dev->hard_header_len) = 1450.
The maximum skb->len the erspan tunnel can carry without
being truncated is 1450 + 14 = 1464 byte.

Signed-off-by: William Tu <u9012063@gmail.com>
Cc: Xin Long <lucien.xin@gmail.com>
---
 include/net/erspan.h |  1 +
 net/ipv4/ip_gre.c    | 11 +++++------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/net/erspan.h b/include/net/erspan.h
index ca94fc86865e..e28294e248d0 100644
--- a/include/net/erspan.h
+++ b/include/net/erspan.h
@@ -28,6 +28,7 @@
  */
 
 #define ERSPAN_VERSION	0x1
+#define ERSPAN_GREHDR_LEN 8	/* ERSPAN has fixed 8-byte GRE header */
 
 #define VER_MASK	0xf000
 #define VLAN_MASK	0x0fff
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 286065c35959..6e6e4c4811cc 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -569,8 +569,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 
 	key = &tun_info->key;
 
-	/* ERSPAN has fixed 8 byte GRE header */
-	tunnel_hlen = 8 + sizeof(struct erspanhdr);
+	tunnel_hlen = ERSPAN_GREHDR_LEN + sizeof(struct erspanhdr);
 
 	rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
 	if (!rt)
@@ -591,7 +590,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 	erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
 			    ntohl(md->index), truncate);
 
-	gre_build_header(skb, 8, TUNNEL_SEQ,
+	gre_build_header(skb, ERSPAN_GREHDR_LEN, TUNNEL_SEQ,
 			 htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
 
 	df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
@@ -1242,14 +1241,14 @@ static int erspan_tunnel_init(struct net_device *dev)
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	int t_hlen;
 
-	tunnel->tun_hlen = 8;
+	tunnel->tun_hlen = ERSPAN_GREHDR_LEN;
 	tunnel->parms.iph.protocol = IPPROTO_GRE;
 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
 		       sizeof(struct erspanhdr);
 	t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
-	dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
-	dev->mtu = ETH_DATA_LEN - t_hlen - 4;
+	dev->needed_headroom = LL_MAX_HEADER + t_hlen;
+	dev->mtu = ETH_DATA_LEN - t_hlen;
 	dev->features		|= GRE_FEATURES;
 	dev->hw_features	|= GRE_FEATURES;
 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
-- 
2.7.4

^ permalink raw reply related

* [net-next 3/3] ip_gre: cache the device mtu hard_header_len calc
From: William Tu @ 2017-10-09 20:47 UTC (permalink / raw)
  To: netdev; +Cc: David Laight
In-Reply-To: <1507582067-36718-1-git-send-email-u9012063@gmail.com>

The patch introduces ip_tunnel->ether_mtu fields to cache the value of
dev->mtu + dev->hard_header_len.  This avoids the arithmetic operation
on every packet.

Signed-off-by: William Tu <u9012063@gmail.com>
Cc: David Laight <David.Laight@aculab.com>
---
 include/net/ip_tunnels.h | 1 +
 net/ipv4/ip_gre.c        | 8 ++++----
 net/ipv4/ip_tunnel.c     | 3 +++
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index b41a1e057fce..19565be26e13 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -117,6 +117,7 @@ struct ip_tunnel {
 
 	/* This field used only by ERSPAN */
 	u32		index;		/* ERSPAN type II index */
+	unsigned int	ether_mtu;	/* The mtu including the ether hdr */
 
 	struct dst_cache dst_cache;
 
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 6e6e4c4811cc..994b8ddea0b1 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -578,8 +578,8 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
 	if (gre_handle_offloads(skb, false))
 		goto err_free_rt;
 
-	if (skb->len > dev->mtu + dev->hard_header_len) {
-		pskb_trim(skb, dev->mtu + dev->hard_header_len);
+	if (skb->len > tunnel->ether_mtu) {
+		pskb_trim(skb, tunnel->ether_mtu);
 		truncate = true;
 	}
 
@@ -730,8 +730,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 	if (skb_cow_head(skb, dev->needed_headroom))
 		goto free_skb;
 
-	if (skb->len > dev->mtu + dev->hard_header_len) {
-		pskb_trim(skb, dev->mtu + dev->hard_header_len);
+	if (skb->len > tunnel->ether_mtu) {
+		pskb_trim(skb, tunnel->ether_mtu);
 		truncate = true;
 	}
 
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index fe6fee728ce4..859af5b86802 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -348,6 +348,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
 
 	dev->needed_headroom = t_hlen + hlen;
 	mtu -= (dev->hard_header_len + t_hlen);
+	tunnel->ether_mtu = mtu + dev->hard_header_len;
 
 	if (mtu < 68)
 		mtu = 68;
@@ -952,6 +953,7 @@ int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
 	}
 
 	dev->mtu = new_mtu;
+	tunnel->ether_mtu = new_mtu + dev->hard_header_len;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);
@@ -1183,6 +1185,7 @@ int ip_tunnel_init(struct net_device *dev)
 
 	tunnel->dev = dev;
 	tunnel->net = dev_net(dev);
+	tunnel->ether_mtu = dev->mtu + dev->hard_header_len;
 	strcpy(tunnel->parms.name, dev->name);
 	iph->version		= 4;
 	iph->ihl		= 5;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/3] net-ATM: Adjustments for several function implementations
From: SF Markus Elfring @ 2017-10-09 20:48 UTC (permalink / raw)
  To: netdev, Alexey Dobriyan, Andrew Morton, Augusto Mecking Caringi,
	Bhumika Goyal, David S. Miller, David Windsor, Elena Reshetova,
	Hans Liljestrand, Jarod Wilson, Johannes Berg, Kees Cook,
	Mitchell Blank Jr, Roopa Prabhu
  Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Mon, 9 Oct 2017 22:30:33 +0200

Some update suggestions were taken into account
from static source code analysis.

Markus Elfring (3):
  Delete an error message for a failed memory allocation in five functions
  Improve a size determination in 12 functions
  Adjust 121 checks for null pointers

 net/atm/addr.c        |   2 +-
 net/atm/br2684.c      |  19 ++++----
 net/atm/clip.c        |   6 +--
 net/atm/lec.c         |  49 ++++++++++----------
 net/atm/mpc.c         | 126 ++++++++++++++++++++++++--------------------------
 net/atm/mpoa_caches.c |  75 +++++++++++++++---------------
 net/atm/pppoatm.c     |  11 ++---
 net/atm/proc.c        |   2 +-
 net/atm/signaling.c   |   2 +-
 9 files changed, 141 insertions(+), 151 deletions(-)

-- 
2.14.2

^ permalink raw reply

* [PATCH 1/3] net/atm: Delete an error message for a failed memory allocation in five functions
From: SF Markus Elfring @ 2017-10-09 20:49 UTC (permalink / raw)
  To: netdev, Alexey Dobriyan, Andrew Morton, Augusto Mecking Caringi,
	Bhumika Goyal, David S. Miller, David Windsor, Elena Reshetova,
	Hans Liljestrand, Jarod Wilson, Johannes Berg, Kees Cook,
	Mitchell Blank Jr, Roopa Prabhu
  Cc: LKML, kernel-janitors
In-Reply-To: <10a92558-1105-b947-86a2-6ac763cca36d@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Mon, 9 Oct 2017 21:34:35 +0200

Omit extra messages for a memory allocation failure in these functions.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 net/atm/lec.c         | 5 ++---
 net/atm/mpc.c         | 8 ++------
 net/atm/mpoa_caches.c | 8 ++------
 3 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/net/atm/lec.c b/net/atm/lec.c
index a3d93a1bb133..f5be0b931978 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1553,10 +1553,9 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv,
 	struct lec_arp_table *to_return;
 
 	to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
-	if (!to_return) {
-		pr_info("LEC: Arp entry kmalloc failed\n");
+	if (!to_return)
 		return NULL;
-	}
+
 	ether_addr_copy(to_return->mac_addr, mac_addr);
 	INIT_HLIST_NODE(&to_return->next);
 	setup_timer(&to_return->timer, lec_arp_expire_arp,
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 5677147209e8..dd57d05b5dcc 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -184,10 +184,8 @@ struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos)
 	}
 
 	entry = kmalloc(sizeof(struct atm_mpoa_qos), GFP_KERNEL);
-	if (entry == NULL) {
-		pr_info("mpoa: out of memory\n");
+	if (!entry)
 		return entry;
-	}
 
 	entry->ipaddr = dst_ip;
 	entry->qos = *qos;
@@ -473,10 +471,8 @@ static const uint8_t *copy_macs(struct mpoa_client *mpc,
 			kfree(mpc->mps_macs);
 		mpc->number_of_mps_macs = 0;
 		mpc->mps_macs = kmalloc(num_macs * ETH_ALEN, GFP_KERNEL);
-		if (mpc->mps_macs == NULL) {
-			pr_info("(%s) out of mem\n", mpc->dev->name);
+		if (!mpc->mps_macs)
 			return NULL;
-		}
 	}
 	ether_addr_copy(mpc->mps_macs, router_mac);
 	tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 4ccaa16b1eb1..7495b42d59eb 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -98,10 +98,8 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
 {
 	in_cache_entry *entry = kzalloc(sizeof(in_cache_entry), GFP_KERNEL);
 
-	if (entry == NULL) {
-		pr_info("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
+	if (!entry)
 		return NULL;
-	}
 
 	dprintk("adding an ingress entry, ip = %pI4\n", &dst_ip);
 
@@ -460,10 +458,8 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
 {
 	eg_cache_entry *entry = kzalloc(sizeof(eg_cache_entry), GFP_KERNEL);
 
-	if (entry == NULL) {
-		pr_info("out of memory\n");
+	if (!entry)
 		return NULL;
-	}
 
 	dprintk("adding an egress entry, ip = %pI4, this should be our IP\n",
 		&msg->content.eg_info.eg_dst_ip);
-- 
2.14.2

^ permalink raw reply related

* [PATCH 2/3] net/atm: Improve a size determination in 12 functions
From: SF Markus Elfring @ 2017-10-09 20:50 UTC (permalink / raw)
  To: netdev, Alexey Dobriyan, Andrew Morton, Augusto Mecking Caringi,
	Bhumika Goyal, David S. Miller, David Windsor, Elena Reshetova,
	Hans Liljestrand, Jarod Wilson, Johannes Berg, Kees Cook,
	Mitchell Blank Jr, Roopa Prabhu
  Cc: LKML, kernel-janitors
In-Reply-To: <10a92558-1105-b947-86a2-6ac763cca36d@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Mon, 9 Oct 2017 22:00:19 +0200

Replace the specification of data structures by pointer dereferences
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 net/atm/addr.c        | 2 +-
 net/atm/br2684.c      | 2 +-
 net/atm/clip.c        | 4 ++--
 net/atm/lec.c         | 6 +++---
 net/atm/mpc.c         | 4 ++--
 net/atm/mpoa_caches.c | 4 ++--
 net/atm/signaling.c   | 2 +-
 7 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/net/atm/addr.c b/net/atm/addr.c
index dcda35c66f15..048e6d192818 100644
--- a/net/atm/addr.c
+++ b/net/atm/addr.c
@@ -86,7 +86,7 @@ int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
 			return -EEXIST;
 		}
 	}
-	this = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);
+	this = kmalloc(sizeof(*this), GFP_ATOMIC);
 	if (!this) {
 		spin_unlock_irqrestore(&dev->lock, flags);
 		return -ENOMEM;
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 4e111196f902..f5b601c01f38 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -538,7 +538,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
 
 	if (copy_from_user(&be, arg, sizeof be))
 		return -EFAULT;
-	brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
+	brvcc = kzalloc(sizeof(*brvcc), GFP_KERNEL);
 	if (!brvcc)
 		return -ENOMEM;
 	/*
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 65f706e4344c..041d519b8771 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -60,7 +60,7 @@ static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip)
 	skb = alloc_skb(sizeof(struct atmarp_ctrl), GFP_ATOMIC);
 	if (!skb)
 		return -ENOMEM;
-	ctrl = skb_put(skb, sizeof(struct atmarp_ctrl));
+	ctrl = skb_put(skb, sizeof(*ctrl));
 	ctrl->type = type;
 	ctrl->itf_num = itf;
 	ctrl->ip = ip;
@@ -418,7 +418,7 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout)
 
 	if (!vcc->push)
 		return -EBADFD;
-	clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
+	clip_vcc = kmalloc(sizeof(*clip_vcc), GFP_KERNEL);
 	if (!clip_vcc)
 		return -ENOMEM;
 	pr_debug("%p vcc %p\n", clip_vcc, vcc);
diff --git a/net/atm/lec.c b/net/atm/lec.c
index f5be0b931978..74a794602412 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -690,7 +690,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
 	if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
 	    !dev_lec[ioc_data.dev_num])
 		return -EINVAL;
-	vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL);
+	vpriv = kmalloc(sizeof(*vpriv), GFP_KERNEL);
 	if (!vpriv)
 		return -ENOMEM;
 	vpriv->xoff = 0;
@@ -1552,7 +1552,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv,
 {
 	struct lec_arp_table *to_return;
 
-	to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
+	to_return = kzalloc(sizeof(*to_return), GFP_ATOMIC);
 	if (!to_return)
 		return NULL;
 
@@ -2155,7 +2155,7 @@ static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
 	struct lec_vcc_priv *vpriv;
 	int err = 0;
 
-	vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL);
+	vpriv = kmalloc(sizeof(*vpriv), GFP_KERNEL);
 	if (!vpriv)
 		return -ENOMEM;
 	vpriv->xoff = 0;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index dd57d05b5dcc..d6729d797107 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -183,7 +183,7 @@ struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos)
 		return entry;
 	}
 
-	entry = kmalloc(sizeof(struct atm_mpoa_qos), GFP_KERNEL);
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return entry;
 
@@ -279,7 +279,7 @@ static struct mpoa_client *alloc_mpc(void)
 {
 	struct mpoa_client *mpc;
 
-	mpc = kzalloc(sizeof(struct mpoa_client), GFP_KERNEL);
+	mpc = kzalloc(sizeof(*mpc), GFP_KERNEL);
 	if (mpc == NULL)
 		return NULL;
 	rwlock_init(&mpc->ingress_lock);
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 7495b42d59eb..23f36e5a20ee 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -96,7 +96,7 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
 static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
 					  struct mpoa_client *client)
 {
-	in_cache_entry *entry = kzalloc(sizeof(in_cache_entry), GFP_KERNEL);
+	in_cache_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 
 	if (!entry)
 		return NULL;
@@ -456,7 +456,7 @@ static void eg_cache_remove_entry(eg_cache_entry *entry,
 static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
 					  struct mpoa_client *client)
 {
-	eg_cache_entry *entry = kzalloc(sizeof(eg_cache_entry), GFP_KERNEL);
+	eg_cache_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 
 	if (!entry)
 		return NULL;
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
index 0a20f6e953ac..225234f5cb5f 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -150,7 +150,7 @@ void sigd_enq2(struct atm_vcc *vcc, enum atmsvc_msg_type type,
 	pr_debug("%d (0x%p)\n", (int)type, vcc);
 	while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL)))
 		schedule();
-	msg = skb_put_zero(skb, sizeof(struct atmsvc_msg));
+	msg = skb_put_zero(skb, sizeof(*msg));
 	msg->type = type;
 	*(struct atm_vcc **) &msg->vcc = vcc;
 	*(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
-- 
2.14.2

^ permalink raw reply related

* [PATCH 3/3] net/atm: Adjust 121 checks for null pointers
From: SF Markus Elfring @ 2017-10-09 20:52 UTC (permalink / raw)
  To: netdev, Alexey Dobriyan, Andrew Morton, Augusto Mecking Caringi,
	Bhumika Goyal, David S. Miller, David Windsor, Elena Reshetova,
	Hans Liljestrand, Jarod Wilson, Johannes Berg, Kees Cook,
	Mitchell Blank Jr, Roopa Prabhu
  Cc: LKML, kernel-janitors
In-Reply-To: <10a92558-1105-b947-86a2-6ac763cca36d@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Mon, 9 Oct 2017 22:22:45 +0200
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The script “checkpatch.pl” pointed information out like the following.

Comparison to NULL could be written …

Thus fix the affected source code places.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 net/atm/br2684.c      |  17 ++++----
 net/atm/clip.c        |   2 +-
 net/atm/lec.c         |  38 ++++++++---------
 net/atm/mpc.c         | 114 +++++++++++++++++++++++++-------------------------
 net/atm/mpoa_caches.c |  63 ++++++++++++++--------------
 net/atm/pppoatm.c     |  11 +++--
 net/atm/proc.c        |   2 +-
 7 files changed, 123 insertions(+), 124 deletions(-)

diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index f5b601c01f38..d3f8ec90556a 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -212,7 +212,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
 		struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
 		brvcc->copies_needed++;
 		dev_kfree_skb(skb);
-		if (skb2 == NULL) {
+		if (!skb2) {
 			brvcc->copies_failed++;
 			return 0;
 		}
@@ -299,7 +299,7 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
 	pr_debug("skb_dst(skb)=%p\n", skb_dst(skb));
 	read_lock(&devs_lock);
 	brvcc = pick_outgoing_vcc(skb, brdev);
-	if (brvcc == NULL) {
+	if (!brvcc) {
 		pr_debug("no vcc attached to dev %s\n", dev->name);
 		dev->stats.tx_errors++;
 		dev->stats.tx_carrier_errors++;
@@ -372,13 +372,13 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg)
 		struct br2684_dev *brdev;
 		read_lock(&devs_lock);
 		brdev = BRPRIV(br2684_find_dev(&fs.ifspec));
-		if (brdev == NULL || list_empty(&brdev->brvccs) ||
+		if (!brdev || list_empty(&brdev->brvccs) ||
 		    brdev->brvccs.next != brdev->brvccs.prev)	/* >1 VCC */
 			brvcc = NULL;
 		else
 			brvcc = list_entry_brvcc(brdev->brvccs.next);
 		read_unlock(&devs_lock);
-		if (brvcc == NULL)
+		if (!brvcc)
 			return -ESRCH;
 	} else
 		brvcc = BR2684_VCC(atmvcc);
@@ -427,8 +427,7 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
 	struct br2684_dev *brdev = BRPRIV(net_dev);
 
 	pr_debug("\n");
-
-	if (unlikely(skb == NULL)) {
+	if (unlikely(!skb)) {
 		/* skb==NULL means VCC is being destroyed */
 		br2684_close_vcc(brvcc);
 		if (list_empty(&brdev->brvccs)) {
@@ -550,13 +549,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
 	atomic_set(&brvcc->qspace, 2);
 	write_lock_irq(&devs_lock);
 	net_dev = br2684_find_dev(&be.ifspec);
-	if (net_dev == NULL) {
+	if (!net_dev) {
 		pr_err("tried to attach to non-existent device\n");
 		err = -ENXIO;
 		goto error;
 	}
 	brdev = BRPRIV(net_dev);
-	if (atmvcc->push == NULL) {
+	if (!atmvcc->push) {
 		err = -EBADFD;
 		goto error;
 	}
@@ -839,7 +838,7 @@ static int __init br2684_init(void)
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *p;
 	p = proc_create("br2684", 0, atm_proc_root, &br2684_proc_ops);
-	if (p == NULL)
+	if (!p)
 		return -ENOMEM;
 #endif
 	register_atm_ioctl(&br2684_ioctl_ops);
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 041d519b8771..b45bfcb6cc1b 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -809,7 +809,7 @@ static void *clip_seq_vcc_walk(struct clip_seq_state *state,
 	struct clip_vcc *vcc = state->vcc;
 
 	vcc = clip_seq_next_vcc(e, vcc);
-	if (vcc && pos != NULL) {
+	if (vcc && pos) {
 		while (*pos) {
 			vcc = clip_seq_next_vcc(e, vcc);
 			if (!vcc)
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 74a794602412..4f94c6ed893c 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -139,7 +139,7 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
 		struct atmlec_msg *mesg;
 
 		skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
-		if (skb2 == NULL)
+		if (!skb2)
 			return;
 		skb2->len = sizeof(struct atmlec_msg);
 		mesg = (struct atmlec_msg *)skb2->data;
@@ -264,7 +264,7 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb,
 					       min_frame_size - skb->truesize,
 					       GFP_ATOMIC);
 			dev_kfree_skb(skb);
-			if (skb2 == NULL) {
+			if (!skb2) {
 				dev->stats.tx_dropped++;
 				return NETDEV_TX_OK;
 			}
@@ -431,7 +431,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 		pr_debug("%s: bridge zeppelin asks about %pM\n",
 			 dev->name, mesg->content.proxy.mac_addr);
 
-		if (br_fdb_test_addr_hook == NULL)
+		if (!br_fdb_test_addr_hook)
 			break;
 
 		if (br_fdb_test_addr_hook(dev, mesg->content.proxy.mac_addr)) {
@@ -442,7 +442,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
 			pr_debug("%s: entry found, responding to zeppelin\n",
 				 dev->name);
 			skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
-			if (skb2 == NULL)
+			if (!skb2)
 				break;
 			skb2->len = sizeof(struct atmlec_msg);
 			skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg));
@@ -520,7 +520,7 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
 	mesg = (struct atmlec_msg *)skb->data;
 	memset(mesg, 0, sizeof(struct atmlec_msg));
 	mesg->type = type;
-	if (data != NULL)
+	if (data)
 		mesg->sizeoftlvs = data->len;
 	if (mac_addr)
 		ether_addr_copy(mesg->content.normal.mac_addr, mac_addr);
@@ -534,7 +534,7 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk);
 
-	if (data != NULL) {
+	if (data) {
 		pr_debug("about to send %d bytes of data\n", data->len);
 		atm_force_charge(priv->lecd, data->truesize);
 		skb_queue_tail(&sk->sk_receive_queue, data);
@@ -663,7 +663,7 @@ static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 	struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
 	struct net_device *dev = skb->dev;
 
-	if (vpriv == NULL) {
+	if (!vpriv) {
 		pr_info("vpriv = NULL!?!?!?\n");
 		return;
 	}
@@ -1066,7 +1066,7 @@ static void __exit lane_module_cleanup(void)
 	deregister_atm_ioctl(&lane_ioctl_ops);
 
 	for (i = 0; i < MAX_LEC_ITF; i++) {
-		if (dev_lec[i] != NULL) {
+		if (dev_lec[i]) {
 			unregister_netdev(dev_lec[i]);
 			free_netdev(dev_lec[i]);
 			dev_lec[i] = NULL;
@@ -1097,11 +1097,11 @@ static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
 		spin_lock_irqsave(&priv->lec_arp_lock, flags);
 		table = lec_arp_find(priv, dst_mac);
 		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
-		if (table == NULL)
+		if (!table)
 			return -1;
 
 		*tlvs = kmemdup(table->tlvs, table->sizeoftlvs, GFP_ATOMIC);
-		if (*tlvs == NULL)
+		if (!*tlvs)
 			return -1;
 
 		*sizeoftlvs = table->sizeoftlvs;
@@ -1109,12 +1109,12 @@ static int lane2_resolve(struct net_device *dev, const u8 *dst_mac, int force,
 		return 0;
 	}
 
-	if (sizeoftlvs == NULL)
+	if (!sizeoftlvs)
 		retval = send_to_lecd(priv, l_arp_xmt, dst_mac, NULL, NULL);
 
 	else {
 		skb = alloc_skb(*sizeoftlvs, GFP_ATOMIC);
-		if (skb == NULL)
+		if (!skb)
 			return -1;
 		skb->len = *sizeoftlvs;
 		skb_copy_to_linear_data(skb, *tlvs, *sizeoftlvs);
@@ -1143,12 +1143,12 @@ static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst,
 	kfree(priv->tlvs);	/* NULL if there was no previous association */
 
 	priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
-	if (priv->tlvs == NULL)
+	if (!priv->tlvs)
 		return 0;
 	priv->sizeoftlvs = sizeoftlvs;
 
 	skb = alloc_skb(sizeoftlvs, GFP_ATOMIC);
-	if (skb == NULL)
+	if (!skb)
 		return 0;
 	skb->len = sizeoftlvs;
 	skb_copy_to_linear_data(skb, tlvs, sizeoftlvs);
@@ -1181,13 +1181,13 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr,
 				 */
 	struct lec_arp_table *entry = lec_arp_find(priv, mac_addr);
 
-	if (entry == NULL)
+	if (!entry)
 		return;		/* should not happen */
 
 	kfree(entry->tlvs);
 
 	entry->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL);
-	if (entry->tlvs == NULL)
+	if (!entry->tlvs)
 		return;
 	entry->sizeoftlvs = sizeoftlvs;
 #endif
@@ -1854,7 +1854,7 @@ lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr,
 
 	spin_lock_irqsave(&priv->lec_arp_lock, flags);
 	entry = lec_arp_find(priv, mac_addr);
-	if (entry == NULL && targetless_le_arp)
+	if (!entry && targetless_le_arp)
 		goto out;	/*
 				 * LANE2: ignore targetless LE_ARPs for which
 				 * we have no entry in the cache. 7.1.30
@@ -1965,7 +1965,7 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data,
 		entry->old_recv_push = old_push;
 #endif
 		entry = make_entry(priv, bus_mac);
-		if (entry == NULL)
+		if (!entry)
 			goto out;
 		del_timer(&entry->timer);
 		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
@@ -1990,7 +1990,7 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data,
 			 ioc_data->atm_addr[16], ioc_data->atm_addr[17],
 			 ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
 		entry = make_entry(priv, bus_mac);
-		if (entry == NULL)
+		if (!entry)
 			goto out;
 		memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
 		eth_zero_addr(entry->mac_addr);
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index d6729d797107..ece715f8c9f7 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -129,7 +129,7 @@ static struct mpoa_client *find_mpc_by_itfnum(int itf)
 	struct mpoa_client *mpc;
 
 	mpc = mpcs;  /* our global linked list */
-	while (mpc != NULL) {
+	while (mpc) {
 		if (mpc->dev_num == itf)
 			return mpc;
 		mpc = mpc->next;
@@ -143,7 +143,7 @@ static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
 	struct mpoa_client *mpc;
 
 	mpc = mpcs;  /* our global linked list */
-	while (mpc != NULL) {
+	while (mpc) {
 		if (mpc->mpoad_vcc == vcc)
 			return mpc;
 		mpc = mpc->next;
@@ -157,7 +157,7 @@ static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
 	struct mpoa_client *mpc;
 
 	mpc = mpcs;  /* our global linked list */
-	while (mpc != NULL) {
+	while (mpc) {
 		if (mpc->dev == dev)
 			return mpc;
 		mpc = mpc->next;
@@ -178,7 +178,7 @@ struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos)
 	struct atm_mpoa_qos *entry;
 
 	entry = atm_mpoa_search_qos(dst_ip);
-	if (entry != NULL) {
+	if (entry) {
 		entry->qos = *qos;
 		return entry;
 	}
@@ -217,7 +217,7 @@ int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
 {
 	struct atm_mpoa_qos *curr;
 
-	if (entry == NULL)
+	if (!entry)
 		return 0;
 	if (entry == qos_head) {
 		qos_head = qos_head->next;
@@ -226,7 +226,7 @@ int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
 	}
 
 	curr = qos_head;
-	while (curr != NULL) {
+	while (curr) {
 		if (curr->next == entry) {
 			curr->next = entry->next;
 			kfree(entry);
@@ -247,7 +247,7 @@ void atm_mpoa_disp_qos(struct seq_file *m)
 	seq_printf(m, "QoS entries for shortcuts:\n");
 	seq_printf(m, "IP address\n  TX:max_pcr pcr     min_pcr max_cdv max_sdu\n  RX:max_pcr pcr     min_pcr max_cdv max_sdu\n");
 
-	while (qos != NULL) {
+	while (qos) {
 		seq_printf(m, "%pI4\n     %-7d %-7d %-7d %-7d %-7d\n     %-7d %-7d %-7d %-7d %-7d\n",
 			   &qos->ipaddr,
 			   qos->qos.txtp.max_pcr,
@@ -280,7 +280,7 @@ static struct mpoa_client *alloc_mpc(void)
 	struct mpoa_client *mpc;
 
 	mpc = kzalloc(sizeof(*mpc), GFP_KERNEL);
-	if (mpc == NULL)
+	if (!mpc)
 		return NULL;
 	rwlock_init(&mpc->ingress_lock);
 	rwlock_init(&mpc->egress_lock);
@@ -381,7 +381,7 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr,
 	dprintk("(%s) received TLV(s), ", dev->name);
 	dprintk("total length of all TLVs %d\n", sizeoftlvs);
 	mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
-	if (mpc == NULL) {
+	if (!mpc) {
 		pr_info("(%s) no mpc\n", dev->name);
 		return;
 	}
@@ -445,7 +445,7 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr,
 
 		tlvs = copy_macs(mpc, mac_addr, tlvs,
 				 number_of_mps_macs, mpoa_device_type);
-		if (tlvs == NULL)
+		if (!tlvs)
 			return;
 	}
 	if (end_of_tlvs - tlvs != 0)
@@ -507,9 +507,9 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
 		 mpc->dev->name, ipaddr);
 
 	entry = mpc->in_ops->get(ipaddr, mpc);
-	if (entry == NULL) {
+	if (!entry) {
 		entry = mpc->in_ops->add_entry(ipaddr, mpc);
-		if (entry != NULL)
+		if (entry)
 			mpc->in_ops->put(entry);
 		return 1;
 	}
@@ -571,7 +571,7 @@ static netdev_tx_t mpc_send_packet(struct sk_buff *skb,
 	int i = 0;
 
 	mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
-	if (mpc == NULL) {
+	if (!mpc) {
 		pr_info("(%s) no MPC found\n", dev->name);
 		goto non_ip;
 	}
@@ -617,16 +617,16 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
 		return -EINVAL;
 
 	mpc = find_mpc_by_itfnum(ioc_data.dev_num);
-	if (mpc == NULL)
+	if (!mpc)
 		return -EINVAL;
 
 	if (ioc_data.type == MPC_SOCKET_INGRESS) {
 		in_entry = mpc->in_ops->get(ipaddr, mpc);
-		if (in_entry == NULL ||
+		if (!in_entry ||
 		    in_entry->entry_state < INGRESS_RESOLVED) {
 			pr_info("(%s) did not find RESOLVED entry from ingress cache\n",
 				mpc->dev->name);
-			if (in_entry != NULL)
+			if (in_entry)
 				mpc->in_ops->put(in_entry);
 			return -EINVAL;
 		}
@@ -654,7 +654,7 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
 	eg_cache_entry *eg_entry;
 
 	mpc = find_mpc_by_lec(dev);
-	if (mpc == NULL) {
+	if (!mpc) {
 		pr_info("(%s) close for unknown MPC\n", dev->name);
 		return;
 	}
@@ -674,7 +674,7 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
 		mpc->eg_ops->put(eg_entry);
 	}
 
-	if (in_entry == NULL && eg_entry == NULL)
+	if (!in_entry && !eg_entry)
 		dprintk("(%s) unused vcc closed\n", dev->name);
 }
 
@@ -688,7 +688,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
 	char *tmp;
 
 	ddprintk("(%s)\n", dev->name);
-	if (skb == NULL) {
+	if (!skb) {
 		dprintk("(%s) null skb, closing VCC\n", dev->name);
 		mpc_vcc_close(vcc, dev);
 		return;
@@ -710,7 +710,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
 	atm_return(vcc, skb->truesize);
 
 	mpc = find_mpc_by_lec(dev);
-	if (mpc == NULL) {
+	if (!mpc) {
 		pr_info("(%s) unknown MPC\n", dev->name);
 		return;
 	}
@@ -735,7 +735,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
 	tag = *(__be32 *)tmp;
 
 	eg = mpc->eg_ops->get_by_tag(tag, mpc);
-	if (eg == NULL) {
+	if (!eg) {
 		pr_info("mpoa: (%s) Didn't find egress cache entry, tag = %u\n",
 			dev->name, tag);
 		purge_egress_shortcut(vcc, NULL);
@@ -747,7 +747,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
 	 * See if ingress MPC is using shortcut we opened as a return channel.
 	 * This means we have a bi-directional vcc opened by us.
 	 */
-	if (eg->shortcut == NULL) {
+	if (!eg->shortcut) {
 		eg->shortcut = vcc;
 		pr_info("(%s) egress SVC in use\n", dev->name);
 	}
@@ -757,7 +757,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
 	new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length);
 					/* LLC/SNAP is shorter than MAC header :( */
 	dev_kfree_skb_any(skb);
-	if (new_skb == NULL) {
+	if (!new_skb) {
 		mpc->eg_ops->put(eg);
 		return;
 	}
@@ -794,7 +794,7 @@ static int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg)
 	struct lec_priv *priv;
 	int err;
 
-	if (mpcs == NULL) {
+	if (!mpcs) {
 		init_timer(&mpc_timer);
 		mpc_timer_refresh();
 
@@ -807,10 +807,10 @@ static int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg)
 	}
 
 	mpc = find_mpc_by_itfnum(arg);
-	if (mpc == NULL) {
+	if (!mpc) {
 		dprintk("allocating new mpc for itf %d\n", arg);
 		mpc = alloc_mpc();
-		if (mpc == NULL)
+		if (!mpc)
 			return -ENOMEM;
 		mpc->dev_num = arg;
 		mpc->dev = find_lec_by_itfnum(arg);
@@ -869,7 +869,7 @@ static void mpoad_close(struct atm_vcc *vcc)
 	struct sk_buff *skb;
 
 	mpc = find_mpc_by_vcc(vcc);
-	if (mpc == NULL) {
+	if (!mpc) {
 		pr_info("did not find MPC\n");
 		return;
 	}
@@ -909,7 +909,7 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
 	struct k_message *mesg = (struct k_message *)skb->data;
 	WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
 
-	if (mpc == NULL) {
+	if (!mpc) {
 		pr_info("no mpc found\n");
 		return 0;
 	}
@@ -974,13 +974,13 @@ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
 	struct sk_buff *skb;
 	struct sock *sk;
 
-	if (mpc == NULL || !mpc->mpoad_vcc) {
+	if (!mpc || !mpc->mpoad_vcc) {
 		pr_info("mesg %d to a non-existent mpoad\n", mesg->type);
 		return -ENXIO;
 	}
 
 	skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
-	if (skb == NULL)
+	if (!skb)
 		return -ENOMEM;
 	skb_put(skb, sizeof(struct k_message));
 	skb_copy_to_linear_data(skb, mesg, sizeof(*mesg));
@@ -1013,10 +1013,10 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
 			break;
 		priv->lane2_ops->associate_indicator = lane2_assoc_ind;
 		mpc = find_mpc_by_itfnum(priv->itfnum);
-		if (mpc == NULL) {
+		if (!mpc) {
 			dprintk("allocating new mpc for %s\n", dev->name);
 			mpc = alloc_mpc();
-			if (mpc == NULL) {
+			if (!mpc) {
 				pr_info("no new mpc");
 				break;
 			}
@@ -1029,7 +1029,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
 	case NETDEV_UNREGISTER:
 		/* the lec device was deallocated */
 		mpc = find_mpc_by_lec(dev);
-		if (mpc == NULL)
+		if (!mpc)
 			break;
 		dprintk("device (%s) was deallocated\n", dev->name);
 		stop_mpc(mpc);
@@ -1039,9 +1039,9 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
 	case NETDEV_UP:
 		/* the dev was ifconfig'ed up */
 		mpc = find_mpc_by_lec(dev);
-		if (mpc == NULL)
+		if (!mpc)
 			break;
-		if (mpc->mpoad_vcc != NULL)
+		if (mpc->mpoad_vcc)
 			start_mpc(mpc, dev);
 		break;
 	case NETDEV_DOWN:
@@ -1050,9 +1050,9 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
 		 * upper layer stops
 		 */
 		mpc = find_mpc_by_lec(dev);
-		if (mpc == NULL)
+		if (!mpc)
 			break;
-		if (mpc->mpoad_vcc != NULL)
+		if (mpc->mpoad_vcc)
 			stop_mpc(mpc);
 		break;
 	case NETDEV_REBOOT:
@@ -1080,7 +1080,7 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 	in_cache_entry *entry;
 
 	entry = mpc->in_ops->get(dst_ip, mpc);
-	if (entry == NULL) {
+	if (!entry) {
 		entry = mpc->in_ops->add_entry(dst_ip, mpc);
 		entry->entry_state = INGRESS_RESOLVING;
 		msg->type = SND_MPOA_RES_RQST;
@@ -1134,7 +1134,7 @@ static void check_qos_and_open_shortcut(struct k_message *msg,
 			return;
 		}
 	}
-	if (eg_entry != NULL)
+	if (eg_entry)
 		client->eg_ops->put(eg_entry);
 
 	/* No luck in the egress cache we must open an ingress SVC */
@@ -1158,7 +1158,7 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 		mpc->dev->name, &dst_ip);
 	ddprintk("(%s) entry = %p",
 		 mpc->dev->name, entry);
-	if (entry == NULL) {
+	if (!entry) {
 		pr_info("(%s) ARGH, received res. reply for an entry that doesn't exist.\n",
 			mpc->dev->name);
 		return;
@@ -1178,13 +1178,13 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 	ddprintk_cont("entry->shortcut = %p\n", entry->shortcut);
 
 	if (entry->entry_state == INGRESS_RESOLVING &&
-	    entry->shortcut != NULL) {
+	    entry->shortcut) {
 		entry->entry_state = INGRESS_RESOLVED;
 		mpc->in_ops->put(entry);
 		return; /* Shortcut already open... */
 	}
 
-	if (entry->shortcut != NULL) {
+	if (entry->shortcut) {
 		pr_info("(%s) entry->shortcut != NULL, impossible!\n",
 			mpc->dev->name);
 		mpc->in_ops->put(entry);
@@ -1205,7 +1205,7 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 	__be32 mask = msg->ip_mask;
 	in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
 
-	if (entry == NULL) {
+	if (!entry) {
 		pr_info("(%s) purge for a non-existing entry, ip = %pI4\n",
 			mpc->dev->name, &dst_ip);
 		return;
@@ -1219,7 +1219,7 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 		write_unlock_bh(&mpc->ingress_lock);
 		mpc->in_ops->put(entry);
 		entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
-	} while (entry != NULL);
+	} while (entry);
 }
 
 static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
@@ -1227,7 +1227,7 @@ static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 	__be32 cache_id = msg->content.eg_info.cache_id;
 	eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
 
-	if (entry == NULL) {
+	if (!entry) {
 		dprintk("(%s) purge for a non-existing entry\n",
 			mpc->dev->name);
 		return;
@@ -1247,13 +1247,13 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
 	struct sk_buff *skb;
 
 	dprintk("entering\n");
-	if (vcc == NULL) {
+	if (!vcc) {
 		pr_info("vcc == NULL\n");
 		return;
 	}
 
 	skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
-	if (skb == NULL) {
+	if (!skb) {
 		pr_info("out of memory\n");
 		return;
 	}
@@ -1262,7 +1262,7 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
 	memset(skb->data, 0, sizeof(struct k_message));
 	purge_msg = (struct k_message *)skb->data;
 	purge_msg->type = DATA_PLANE_PURGE;
-	if (entry != NULL)
+	if (entry)
 		purge_msg->content.eg_info = entry->ctrl_info;
 
 	atm_force_charge(vcc, skb->truesize);
@@ -1291,7 +1291,7 @@ static void mps_death(struct k_message *msg, struct mpoa_client *mpc)
 	/* FIXME: This knows too much of the cache structure */
 	read_lock_irq(&mpc->egress_lock);
 	entry = mpc->eg_cache;
-	while (entry != NULL) {
+	while (entry) {
 		purge_egress_shortcut(entry->shortcut, entry);
 		entry = entry->next;
 	}
@@ -1310,7 +1310,7 @@ static void MPOA_cache_impos_rcvd(struct k_message *msg,
 	holding_time = msg->content.eg_info.holding_time;
 	dprintk("(%s) entry = %p, holding_time = %u\n",
 		mpc->dev->name, entry, holding_time);
-	if (entry == NULL && holding_time) {
+	if (!entry && holding_time) {
 		entry = mpc->eg_ops->add_entry(msg, mpc);
 		mpc->eg_ops->put(entry);
 		return;
@@ -1372,7 +1372,7 @@ static void set_mps_mac_addr_rcvd(struct k_message *msg,
 		kfree(client->mps_macs);
 	client->number_of_mps_macs = 0;
 	client->mps_macs = kmemdup(msg->MPS_ctrl, ETH_ALEN, GFP_KERNEL);
-	if (client->mps_macs == NULL) {
+	if (!client->mps_macs) {
 		pr_info("out of memory\n");
 		return;
 	}
@@ -1392,7 +1392,7 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
 	/* FIXME: This knows too much of the cache structure */
 	read_lock_irq(&mpc->egress_lock);
 	entry = mpc->eg_cache;
-	while (entry != NULL) {
+	while (entry) {
 		msg->content.eg_info = entry->ctrl_info;
 		dprintk("cache_id %u\n", entry->ctrl_info.cache_id);
 		msg_to_mpoad(msg, mpc);
@@ -1418,7 +1418,7 @@ static void mpc_cache_check(unsigned long checking_time)
 	static unsigned long previous_resolving_check_time;
 	static unsigned long previous_refresh_time;
 
-	while (mpc != NULL) {
+	while (mpc) {
 		mpc->in_ops->clear_count(mpc);
 		mpc->eg_ops->clear_expired(mpc);
 		if (checking_time - previous_resolving_check_time >
@@ -1494,12 +1494,12 @@ static void __exit atm_mpoa_cleanup(void)
 
 	mpc = mpcs;
 	mpcs = NULL;
-	while (mpc != NULL) {
+	while (mpc) {
 		tmp = mpc->next;
-		if (mpc->dev != NULL) {
+		if (mpc->dev) {
 			stop_mpc(mpc);
 			priv = netdev_priv(mpc->dev);
-			if (priv->lane2_ops != NULL)
+			if (priv->lane2_ops)
 				priv->lane2_ops->associate_indicator = NULL;
 		}
 		ddprintk("about to clear caches\n");
@@ -1516,7 +1516,7 @@ static void __exit atm_mpoa_cleanup(void)
 
 	qos = qos_head;
 	qos_head = NULL;
-	while (qos != NULL) {
+	while (qos) {
 		nextqos = qos->next;
 		dprintk("freeing qos entry %p\n", qos);
 		kfree(qos);
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 23f36e5a20ee..c147fe916446 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -38,7 +38,7 @@ static in_cache_entry *in_cache_get(__be32 dst_ip,
 
 	read_lock_bh(&client->ingress_lock);
 	entry = client->in_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->ctrl_info.in_dst_ip == dst_ip) {
 			refcount_inc(&entry->use);
 			read_unlock_bh(&client->ingress_lock);
@@ -59,7 +59,7 @@ static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip,
 
 	read_lock_bh(&client->ingress_lock);
 	entry = client->in_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if ((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask)) {
 			refcount_inc(&entry->use);
 			read_unlock_bh(&client->ingress_lock);
@@ -80,7 +80,7 @@ static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
 
 	read_lock_bh(&client->ingress_lock);
 	entry = client->in_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->shortcut == vcc) {
 			refcount_inc(&entry->use);
 			read_unlock_bh(&client->ingress_lock);
@@ -108,7 +108,7 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
 	write_lock_bh(&client->ingress_lock);
 	entry->next = client->in_cache;
 	entry->prev = NULL;
-	if (client->in_cache != NULL)
+	if (client->in_cache)
 		client->in_cache->prev = entry;
 	client->in_cache = entry;
 
@@ -133,7 +133,7 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
 	struct k_message msg;
 
 	entry->count++;
-	if (entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL)
+	if (entry->entry_state == INGRESS_RESOLVED && entry->shortcut)
 		return OPEN;
 
 	if (entry->entry_state == INGRESS_REFRESHING) {
@@ -142,18 +142,18 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
 			msg.content.in_info = entry->ctrl_info;
 			memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
 			qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
-			if (qos != NULL)
+			if (qos)
 				msg.qos = qos->qos;
 			msg_to_mpoad(&msg, mpc);
 			do_gettimeofday(&(entry->reply_wait));
 			entry->entry_state = INGRESS_RESOLVING;
 		}
-		if (entry->shortcut != NULL)
+		if (entry->shortcut)
 			return OPEN;
 		return CLOSED;
 	}
 
-	if (entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
+	if (entry->entry_state == INGRESS_RESOLVING && entry->shortcut)
 		return OPEN;
 
 	if (entry->count > mpc->parameters.mpc_p1 &&
@@ -165,7 +165,7 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
 		memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
 		msg.content.in_info = entry->ctrl_info;
 		qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
-		if (qos != NULL)
+		if (qos)
 			msg.qos = qos->qos;
 		msg_to_mpoad(&msg, mpc);
 		do_gettimeofday(&(entry->reply_wait));
@@ -195,23 +195,24 @@ static void in_cache_remove_entry(in_cache_entry *entry,
 	dprintk("removing an ingress entry, ip = %pI4\n",
 		&entry->ctrl_info.in_dst_ip);
 
-	if (entry->prev != NULL)
+	if (entry->prev)
 		entry->prev->next = entry->next;
 	else
 		client->in_cache = entry->next;
-	if (entry->next != NULL)
+	if (entry->next)
 		entry->next->prev = entry->prev;
 	client->in_ops->put(entry);
-	if (client->in_cache == NULL && client->eg_cache == NULL) {
+	if (!client->in_cache && !client->eg_cache) {
 		msg.type = STOP_KEEP_ALIVE_SM;
 		msg_to_mpoad(&msg, client);
 	}
 
 	/* Check if the egress side still uses this VCC */
-	if (vcc != NULL) {
+	if (vcc) {
 		eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc,
 								      client);
-		if (eg_entry != NULL) {
+
+		if (eg_entry) {
 			client->eg_ops->put(eg_entry);
 			return;
 		}
@@ -230,7 +231,7 @@ static void clear_count_and_expired(struct mpoa_client *client)
 
 	write_lock_bh(&client->ingress_lock);
 	entry = client->in_cache;
-	while (entry != NULL) {
+	while (entry) {
 		entry->count = 0;
 		next_entry = entry->next;
 		if ((now.tv_sec - entry->tv.tv_sec)
@@ -257,7 +258,7 @@ static void check_resolving_entries(struct mpoa_client *client)
 
 	read_lock_bh(&client->ingress_lock);
 	entry = client->in_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->entry_state == INGRESS_RESOLVING) {
 			if ((now.tv_sec - entry->hold_down.tv_sec) <
 			    client->parameters.mpc_p6) {
@@ -283,7 +284,7 @@ static void check_resolving_entries(struct mpoa_client *client)
 				memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
 				msg.content.in_info = entry->ctrl_info;
 				qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
-				if (qos != NULL)
+				if (qos)
 					msg.qos = qos->qos;
 				msg_to_mpoad(&msg, client);
 				do_gettimeofday(&(entry->reply_wait));
@@ -304,7 +305,7 @@ static void refresh_entries(struct mpoa_client *client)
 	do_gettimeofday(&now);
 
 	read_lock_bh(&client->ingress_lock);
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->entry_state == INGRESS_RESOLVED) {
 			if (!(entry->refresh_time))
 				entry->refresh_time = (2 * (entry->ctrl_info.holding_time))/3;
@@ -323,7 +324,7 @@ static void refresh_entries(struct mpoa_client *client)
 static void in_destroy_cache(struct mpoa_client *mpc)
 {
 	write_lock_irq(&mpc->ingress_lock);
-	while (mpc->in_cache != NULL)
+	while (mpc->in_cache)
 		mpc->in_ops->remove_entry(mpc->in_cache, mpc);
 	write_unlock_irq(&mpc->ingress_lock);
 }
@@ -335,7 +336,7 @@ static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id,
 
 	read_lock_irq(&mpc->egress_lock);
 	entry = mpc->eg_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->ctrl_info.cache_id == cache_id) {
 			refcount_inc(&entry->use);
 			read_unlock_irq(&mpc->egress_lock);
@@ -356,7 +357,7 @@ static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc)
 
 	read_lock_irqsave(&mpc->egress_lock, flags);
 	entry = mpc->eg_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->ctrl_info.tag == tag) {
 			refcount_inc(&entry->use);
 			read_unlock_irqrestore(&mpc->egress_lock, flags);
@@ -378,7 +379,7 @@ static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc,
 
 	read_lock_irqsave(&mpc->egress_lock, flags);
 	entry = mpc->eg_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->shortcut == vcc) {
 			refcount_inc(&entry->use);
 			read_unlock_irqrestore(&mpc->egress_lock, flags);
@@ -398,7 +399,7 @@ static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr,
 
 	read_lock_irq(&mpc->egress_lock);
 	entry = mpc->eg_cache;
-	while (entry != NULL) {
+	while (entry) {
 		if (entry->latest_ip_addr == ipaddr) {
 			refcount_inc(&entry->use);
 			read_unlock_irq(&mpc->egress_lock);
@@ -430,22 +431,22 @@ static void eg_cache_remove_entry(eg_cache_entry *entry,
 
 	vcc = entry->shortcut;
 	dprintk("removing an egress entry.\n");
-	if (entry->prev != NULL)
+	if (entry->prev)
 		entry->prev->next = entry->next;
 	else
 		client->eg_cache = entry->next;
-	if (entry->next != NULL)
+	if (entry->next)
 		entry->next->prev = entry->prev;
 	client->eg_ops->put(entry);
-	if (client->in_cache == NULL && client->eg_cache == NULL) {
+	if (!client->in_cache && !client->eg_cache) {
 		msg.type = STOP_KEEP_ALIVE_SM;
 		msg_to_mpoad(&msg, client);
 	}
 
 	/* Check if the ingress side still uses this VCC */
-	if (vcc != NULL) {
+	if (vcc) {
 		in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
-		if (in_entry != NULL) {
+		if (in_entry) {
 			client->in_ops->put(in_entry);
 			return;
 		}
@@ -469,7 +470,7 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
 	write_lock_irq(&client->egress_lock);
 	entry->next = client->eg_cache;
 	entry->prev = NULL;
-	if (client->eg_cache != NULL)
+	if (client->eg_cache)
 		client->eg_cache->prev = entry;
 	client->eg_cache = entry;
 
@@ -505,7 +506,7 @@ static void clear_expired(struct mpoa_client *client)
 
 	write_lock_irq(&client->egress_lock);
 	entry = client->eg_cache;
-	while (entry != NULL) {
+	while (entry) {
 		next_entry = entry->next;
 		if ((now.tv_sec - entry->tv.tv_sec)
 		   > entry->ctrl_info.holding_time) {
@@ -524,7 +525,7 @@ static void clear_expired(struct mpoa_client *client)
 static void eg_destroy_cache(struct mpoa_client *mpc)
 {
 	write_lock_irq(&mpc->egress_lock);
-	while (mpc->eg_cache != NULL)
+	while (mpc->eg_cache)
 		mpc->eg_ops->remove_entry(mpc->eg_cache, mpc);
 	write_unlock_irq(&mpc->egress_lock);
 }
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 21d9d341a619..890eb377e2dd 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -183,7 +183,7 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
 {
 	struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
 	pr_debug("\n");
-	if (skb == NULL) {			/* VCC was closed */
+	if (!skb) {			/* VCC was closed */
 		struct module *module;
 
 		pr_debug("removing ATMPPP VCC %p\n", pvcc);
@@ -202,7 +202,7 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
 		skb_pull(skb, LLC_LEN);
 		break;
 	case e_autodetect:
-		if (pvcc->chan.ppp == NULL) {	/* Not bound yet! */
+		if (!pvcc->chan.ppp) {	/* Not bound yet! */
 			kfree_skb(skb);
 			return;
 		}
@@ -324,14 +324,13 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
 		if (skb_headroom(skb) < LLC_LEN) {
 			struct sk_buff *n;
 			n = skb_realloc_headroom(skb, LLC_LEN);
-			if (n != NULL &&
-			    !pppoatm_may_send(pvcc, n->truesize)) {
+			if (n && !pppoatm_may_send(pvcc, n->truesize)) {
 				kfree_skb(n);
 				goto nospace;
 			}
 			consume_skb(skb);
 			skb = n;
-			if (skb == NULL) {
+			if (!skb) {
 				bh_unlock_sock(sk_atm(vcc));
 				return DROP_PACKET;
 			}
@@ -406,7 +405,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
 	    be.encaps != PPPOATM_ENCAPS_VC && be.encaps != PPPOATM_ENCAPS_LLC)
 		return -EINVAL;
 	pvcc = kzalloc(sizeof(*pvcc), GFP_KERNEL);
-	if (pvcc == NULL)
+	if (!pvcc)
 		return -ENOMEM;
 	pvcc->atmvcc = atmvcc;
 
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 4caca2a90ec4..aa230079cf8a 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -118,7 +118,7 @@ static int __vcc_seq_open(struct inode *inode, struct file *file,
 	struct vcc_state *state;
 
 	state = __seq_open_private(file, ops, sizeof(*state));
-	if (state == NULL)
+	if (!state)
 		return -ENOMEM;
 
 	state->family = family;
-- 
2.14.2

^ permalink raw reply related

* Re: [net-next V5 PATCH 1/5] bpf: introduce new bpf cpu map type BPF_MAP_TYPE_CPUMAP
From: Daniel Borkmann @ 2017-10-09 20:56 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: netdev, jakub.kicinski, Michael S. Tsirkin, pavel.odintsov,
	Jason Wang, mchan, John Fastabend, peter.waskiewicz.jr,
	Daniel Borkmann, Alexei Starovoitov, Andy Gospodarek
In-Reply-To: <20171009195924.662f1586@redhat.com>

On 10/09/2017 07:59 PM, Jesper Dangaard Brouer wrote:
[...]
>>> +static void *cpu_map_lookup_elem(struct bpf_map *map, void *key)
>>> +{
>>> +	struct bpf_cpu_map_entry *rcpu =
>>> +		__cpu_map_lookup_elem(map, *(u32 *)key);
>>> +
>>> +	return rcpu ? &rcpu->qsize : NULL;
>>
>> I still think from my prior email/comment that we should use per-cpu
>> scratch buffer here. Would be nice to keep the guarantee that noone
>> can modify it, it's just a tiny change.
>
> Well, it's no-longer really needed, right(?), as this patchset update,
> change that bpf-side cannot invoke this.  The userspace-side reading
> this will get a copy.

Ah sorry, you're right, the related change happens in later patch, I
missed that; would be good to avoid a split in future or other option
is to forbid usage initially in check_map_func_compatibility() by
bailing out in BPF_MAP_TYPE_CPUMAP case unconditionally, and then
enabling it for BPF_FUNC_redirect_map in next step, such that should
someone accidentally only backport this patch, we don't allow for
unintended misuse.

Thanks,
Daniel

^ permalink raw reply

* Re: [PATCH v6 05/11] dt-bindings: net: dwmac-sun8i: update documentation about integrated PHY
From: Maxime Ripard @ 2017-10-09 21:08 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: Andrew Lunn, robh+dt-DgEjT+Ai2ygdnm+yROfE0A, wens-jdAy2FN1RRM,
	f.fainelli-Re5JQEeQqe8AvxtiuMwx3w, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, peppe.cavallaro-qxv4g6HH51o,
	alexandre.torgue-qxv4g6HH51o, frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
	netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20171008183340.GA21531@Red>

[-- Attachment #1: Type: text/plain, Size: 2409 bytes --]

On Sun, Oct 08, 2017 at 06:33:40PM +0000, Corentin Labbe wrote:
> On Thu, Sep 28, 2017 at 09:37:08AM +0200, Corentin Labbe wrote:
> > On Wed, Sep 27, 2017 at 04:02:10PM +0200, Andrew Lunn wrote:
> > > Hi Corentin
> > > 
> > > > +Required properties for the mdio-mux node:
> > > > +  - compatible = "mdio-mux"
> > > 
> > > This is too generic. Please add a more specific compatible for this
> > > particular mux. You can keep "mdio-mux", since that is what the MDIO
> > > subsystem will look for.
> > > 
> > 
> > I will add allwinner,sun8i-h3-mdio-mux
> > 
> > > > +Required properties of the integrated phy node:
> > > >  - clocks: a phandle to the reference clock for the EPHY
> > > >  - resets: a phandle to the reset control for the EPHY
> > > > +- phy-is-integrated
> > > 
> > > So the last thing you said is that the mux is not the problem
> > > here. Something else is locking up. Did you discover what?
> > > 
> > > I really would like phy-is-integrated to go away.
> > > 
> > 
> > I have found the problem: by enabling ephy clk/reset the timeout does not occur anymore.
> > So we could remove phy-is-integrated by:
> > Moving internal phy clk/reset handling in mdio_mux_syscon_switch_fn()
> > But this means:
> > - getting internalphy node always by manually get internal_mdio/internal_phy (and not by the given phyhandle)
> > - doing some unnecessary tasks (enable/scan/disable) when external_phy is needed
> > 
> > Regards
> 
> Hello all
> 
> Below is the current patch, as you can read, it does not use anymore the phy-is-integrated property.
> So now, the mdio-mux must always enable the internal mdio when switch_fn ask for it and so reset MAC and so need to enable ephy clk/reset.
> But for this I need a reference to thoses clock and reset. (this is done in get_ephy_nodes)
> The current version set those clock in mdio-mux node, and as you can see it is already ugly (lots of get next node),
> if the clk/rst nodes were as it should be, in phy nodes, it will be more bad.
> 
> So, since the MAC have a dependency on thoses clk/rst nodes for
> doing reset(), I seek a proper way to get references on it.
>
> OR do you agree that putting ephy clk/rst in emac is acceptable ?

Why not just parsing the DT child nodes looking for resets and clocks
properties? The usual PHY don't have that.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH] once: switch to new jump label API
From: Daniel Borkmann @ 2017-10-09 21:14 UTC (permalink / raw)
  To: Eric Biggers, Hannes Frederic Sowa
  Cc: David S. Miller, netdev, linux-kernel, Jason Baron,
	Peter Zijlstra, Eric Biggers
In-Reply-To: <20171009202708.GB67463@gmail.com>

On 10/09/2017 10:27 PM, Eric Biggers wrote:
> On Fri, Sep 15, 2017 at 09:07:51PM -0700, Eric Biggers wrote:
>> On Tue, Aug 22, 2017 at 02:44:41PM -0400, Hannes Frederic Sowa wrote:
>>> Eric Biggers <ebiggers3@gmail.com> writes:
>>>> From: Eric Biggers <ebiggers@google.com>
>>>>
>>>> Switch the DO_ONCE() macro from the deprecated jump label API to the new
>>>> one.  The new one is more readable, and for DO_ONCE() it also makes the
>>>> generated code more icache-friendly: now the one-time initialization
>>>> code is placed out-of-line at the jump target, rather than at the inline
>>>> fallthrough case.
>>>>
>>>> Signed-off-by: Eric Biggers <ebiggers@google.com>
>>>
>>> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org.
>>>
>>> Thanks!
>>
>> Great!  Who though is the maintainer for this code?  It seems it was originally
>> taken by David Miller through the networking tree.  David, are you taking
>> further patches to the "once" functions, or should I be trying to get this into
>> -mm, or somewhere else?
>>
>> Eric
>
> Ping.

Given original code was accepted against net-next tree as major users of
the api are networking related anyway, it should be fine here as well to
route through this tree. Maybe resend the patch with a [PATCH net-next]
in the subject line (as usually done) to make the targeted tree more clear.

^ permalink raw reply

* Re: [PATCH] once: switch to new jump label API
From: David Miller @ 2017-10-09 21:17 UTC (permalink / raw)
  To: daniel; +Cc: ebiggers3, hannes, netdev, linux-kernel, jbaron, peterz, ebiggers
In-Reply-To: <59DBE6C2.40104@iogearbox.net>

From: Daniel Borkmann <daniel@iogearbox.net>
Date: Mon, 09 Oct 2017 23:14:42 +0200

> Given original code was accepted against net-next tree as major
> users of the api are networking related anyway, it should be fine
> here as well to route through this tree. Maybe resend the patch with
> a [PATCH net-next] in the subject line (as usually done) to make the
> targeted tree more clear.

Indeed, please do, sorry for not replying.

^ permalink raw reply

* Re: [PATCH net] net: enable interface alias removal via rtnl
From: David Ahern @ 2017-10-09 21:17 UTC (permalink / raw)
  To: nicolas.dichtel, Oliver Hartkopp, davem
  Cc: netdev, Oliver Hartkopp, Stephen Hemminger
In-Reply-To: <3e705d90-9b9a-aa02-e1d9-e3a944953014@6wind.com>

On 10/9/17 9:25 AM, Nicolas Dichtel wrote:
> Le 09/10/2017 à 16:02, David Ahern a écrit :
>> On 10/9/17 2:23 AM, Nicolas Dichtel wrote:
>>> Le 06/10/2017 à 22:10, Oliver Hartkopp a écrit :
>>>>
>>>>
>>>> On 10/06/2017 08:18 PM, David Ahern wrote:
>>>>> On 10/5/17 4:19 AM, Nicolas Dichtel wrote:
>>>>>> IFLA_IFALIAS is defined as NLA_STRING. It means that the minimal length of
>>>>>> the attribute is 1 ("\0"). However, to remove an alias, the attribute
>>>>>> length must be 0 (see dev_set_alias()).
>>>>>
>>>>> why not add a check in dev_set_alias that if len is 1 and the 1
>>>>> character is '\0' it means remove the alias?
>>> Because it requires an iproute2 patch. iproute2 doesn't send the '\0'. With the
>>> command 'ip link set dummy0 alias ""', the attribute length is 0.
>>
>> iproute2 needs the feature for 0-len strings or perhaps a 'noalias' option.
> iproute2 needs nothing ...
> 
>>
>> You can reset the alias using the sysfs file. Given that there is a
>> workaround for existing kernels and userspace, upstream can get fixed
>> without changing the UAPI.
>>
> I don't get the point with the UAPI. What will be broken?

never mind; I see the error of my ways.

> I don't see why allowing an attribute with no data is a problem.
> 

I remember the problem now. I made a patch back in March 2016 that
adjusted the policy validation to allow 0-length string. I never sent it
and forgot about it until today. You changing ifla_policy to NLA_BINARY
is achieving the same thing.

I think a comment above the policy line is warranted that clarifies
IFLA_IFALIAS is a string but to allow a 0-length string to remove the
alias NLA_BINARY is used for policy validation.

Comparing the validation done for NLA_STRING vs NLA_BINARY it does
change the behavior for 256-character strings.

^ permalink raw reply

* [PATCH net-next] once: switch to new jump label API
From: Eric Biggers @ 2017-10-09 21:30 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, linux-kernel, Hannes Frederic Sowa, Jason Baron,
	Peter Zijlstra, Eric Biggers

From: Eric Biggers <ebiggers@google.com>

Switch the DO_ONCE() macro from the deprecated jump label API to the new
one.  The new one is more readable, and for DO_ONCE() it also makes the
generated code more icache-friendly: now the one-time initialization
code is placed out-of-line at the jump target, rather than at the inline
fallthrough case.

Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 include/linux/once.h | 6 +++---
 lib/once.c           | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/once.h b/include/linux/once.h
index 9c98aaa87cbc..724724918e8b 100644
--- a/include/linux/once.h
+++ b/include/linux/once.h
@@ -5,7 +5,7 @@
 #include <linux/jump_label.h>
 
 bool __do_once_start(bool *done, unsigned long *flags);
-void __do_once_done(bool *done, struct static_key *once_key,
+void __do_once_done(bool *done, struct static_key_true *once_key,
 		    unsigned long *flags);
 
 /* Call a function exactly once. The idea of DO_ONCE() is to perform
@@ -38,8 +38,8 @@ void __do_once_done(bool *done, struct static_key *once_key,
 	({								     \
 		bool ___ret = false;					     \
 		static bool ___done = false;				     \
-		static struct static_key ___once_key = STATIC_KEY_INIT_TRUE; \
-		if (static_key_true(&___once_key)) {			     \
+		static DEFINE_STATIC_KEY_TRUE(___once_key);		     \
+		if (static_branch_unlikely(&___once_key)) {		     \
 			unsigned long ___flags;				     \
 			___ret = __do_once_start(&___done, &___flags);	     \
 			if (unlikely(___ret)) {				     \
diff --git a/lib/once.c b/lib/once.c
index 05c8604627eb..831c5a6b0bb2 100644
--- a/lib/once.c
+++ b/lib/once.c
@@ -5,7 +5,7 @@
 
 struct once_work {
 	struct work_struct work;
-	struct static_key *key;
+	struct static_key_true *key;
 };
 
 static void once_deferred(struct work_struct *w)
@@ -14,11 +14,11 @@ static void once_deferred(struct work_struct *w)
 
 	work = container_of(w, struct once_work, work);
 	BUG_ON(!static_key_enabled(work->key));
-	static_key_slow_dec(work->key);
+	static_branch_disable(work->key);
 	kfree(work);
 }
 
-static void once_disable_jump(struct static_key *key)
+static void once_disable_jump(struct static_key_true *key)
 {
 	struct once_work *w;
 
@@ -51,7 +51,7 @@ bool __do_once_start(bool *done, unsigned long *flags)
 }
 EXPORT_SYMBOL(__do_once_start);
 
-void __do_once_done(bool *done, struct static_key *once_key,
+void __do_once_done(bool *done, struct static_key_true *once_key,
 		    unsigned long *flags)
 	__releases(once_lock)
 {
-- 
2.14.2.920.gcf0c67979c-goog

^ permalink raw reply related

* RE: [PATCH RFC v1 0/3] Support for tap user-space access with veth interfaces
From: Grandhi, Sainath @ 2017-10-09 21:51 UTC (permalink / raw)
  To: netdev@vger.kernel.org; +Cc: davem@davemloft.net
In-Reply-To: <1504744467-79590-1-git-send-email-sainath.grandhi@intel.com>

Hello,
	Just a reminder for feedback. Please let me know your comments.

> -----Original Message-----
> From: Grandhi, Sainath
> Sent: Wednesday, September 06, 2017 5:34 PM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; Grandhi, Sainath <sainath.grandhi@intel.com>
> Subject: [PATCH RFC v1 0/3] Support for tap user-space access with veth
> interfaces
> 
> From: Sainath Grandhi <sainath.grandhi@intel.com>
> 
> This patchset adds a tap device driver for veth virtual network interface.
> With this implementation, tap character interface can be added only to the peer
> veth interface. Adding tap interface to veth is for usecases that forwards
> packets between host and VMs. This eliminates the need for an additional
> software bridge. This can be extended to create both the peer interfaces as tap
> interfaces. These patches are a step in that direction.
> 
> Sainath Grandhi (3):
>   net: Adding API to parse IFLA_LINKINFO attribute
>   net: Abstracting out common routines from veth for use by vethtap
>   vethtap: veth based tap driver
> 
>  drivers/net/Kconfig                 |   1 +
>  drivers/net/Makefile                |   2 +
>  drivers/net/{veth.c => veth_main.c} |  80 ++++++++++---
>  drivers/net/vethtap.c               | 216 ++++++++++++++++++++++++++++++++++++
>  include/linux/if_veth.h             |  13 +++
>  include/net/rtnetlink.h             |   3 +
>  net/core/rtnetlink.c                |   8 ++
>  7 files changed, 308 insertions(+), 15 deletions(-)  rename drivers/net/{veth.c =>
> veth_main.c} (89%)  create mode 100644 drivers/net/vethtap.c  create mode
> 100644 include/linux/if_veth.h
> 
> --
> 2.7.4

^ permalink raw reply

* Re: [PATCH net-next RFC 4/9] net: dsa: mv88e6xxx: add support for event capture
From: Levi Pearson @ 2017-10-09 22:08 UTC (permalink / raw)
  To: Richard Cochran
  Cc: Brandon Streiff, Linux Kernel Network Developers, linux-kernel,
	David S. Miller, Florian Fainelli, Andrew Lunn, Vivien Didelot,
	Erik Hons
In-Reply-To: <20171008150634.hb7nxwbbmi5xff7m@localhost>

On Sun, Oct 8, 2017 at 9:06 AM, Richard Cochran
<richardcochran@gmail.com> wrote:

>> +static int mv88e6xxx_ptp_enable_perout(struct mv88e6xxx_chip *chip,
>> +                                    struct ptp_clock_request *rq, int on)
>> +{
>> +     struct timespec ts;
>> +     u64 ns;
>> +     int pin;
>> +     int err;
>> +
>> +     pin = ptp_find_pin(chip->ptp_clock, PTP_PF_PEROUT, rq->extts.index);
>> +
>> +     if (pin < 0)
>> +             return -EBUSY;
>> +
>> +     ts.tv_sec = rq->perout.period.sec;
>> +     ts.tv_nsec = rq->perout.period.nsec;
>> +     ns = timespec_to_ns(&ts);
>> +
>> +     if (ns > U32_MAX)
>> +             return -ERANGE;
>> +
>> +     mutex_lock(&chip->reg_lock);
>> +
>> +     err = mv88e6xxx_config_periodic_trig(chip, (u32)ns, 0);
>
> Here you ignore the phase of the signal given in the trq->perout.start
> field.  That is not what the user expects.  For periodic outputs where
> the phase cannot be set, we really would need a new ioctl.
>
> However, in this case, you should just drop this functionality.  I
> understand that this works with your adjustable external oscillator,
> but we cannot support that in mainline (at least, not yet).

I've been working with this patchset and just came across this
limitation as well. The periodic timer output is the basis of the Qbv
t0 timer in devices that support Qbv, and setting this up with the
correct start time is pretty important in that context. The hardware
does support setting a start time, but it must be specified according
to the cycle count of the free-running timer rather than a nanosecond
value. I think this can be worked out from the values stored in the
timecounter struct and I'm writing some code for it now, but if you've
already written something I'd be happy to integrate that instead.

Another issue related to this is that while the free-running counter
in the hardware can't be easily adjusted, the periodic event generator
*can* be finely adjusted (via picosecond and sub-picosecond
accumulators) to correct for drift between the local clock and the PTP
grandmaster time. So to be semantically correct, this needs to be both
started at the right time *and* it needs to have the periodic
corrections made so that the fine correction parameters in the
hardware keep it adjusted to be synchronous with PTP grandmaster time.

So, taking this functionality out in the first pass seems like a good
move for Brandon to take, but I'm working on a complete implementation
for it. I think I've got a handle on how to do it, but if you have any
suggestions, I'm open to them.


Levi

^ permalink raw reply

* [PATCH net-next v2 0/5] bpf: security: New file mode and LSM hooks for eBPF object permission control
From: Chenbo Feng @ 2017-10-09 22:20 UTC (permalink / raw)
  To: linux-security-module, netdev, SELinux
  Cc: Jeffrey Vander Stoep, Alexei Starovoitov, lorenzo,
	Daniel Borkmann, Stephen Smalley, Chenbo Feng

From: Chenbo Feng <fengc@google.com>

Much like files and sockets, eBPF objects are accessed, controlled, and
shared via a file descriptor (FD). Unlike files and sockets, the
existing mechanism for eBPF object access control is very limited.
Currently there are two options for granting accessing to eBPF
operations: grant access to all processes, or only CAP_SYS_ADMIN
processes. The CAP_SYS_ADMIN-only mode is not ideal because most users
do not have this capability and granting a user CAP_SYS_ADMIN grants too
many other security-sensitive permissions. It also unnecessarily allows
all CAP_SYS_ADMIN processes access to eBPF functionality. Allowing all
processes to access to eBPF objects is also undesirable since it has
potential to allow unprivileged processes to consume kernel memory, and
opens up attack surface to the kernel.

Adding LSM hooks maintains the status quo for systems which do not use
an LSM, preserving compatibility with userspace, while allowing security
modules to choose how best to handle permissions on eBPF objects. Here
is a possible use case for the lsm hooks with selinux module:

The network-control daemon (netd) creates and loads an eBPF object for
network packet filtering and analysis. It passes the object FD to an
unprivileged network monitor app (netmonitor), which is not allowed to
create, modify or load eBPF objects, but is allowed to read the traffic
stats from the map.

Selinux could use these hooks to grant the following permissions:
allow netd self:bpf_map { create read write};
allow netmonitor netd:fd use;
allow netmonitor netd:bpf_map read;

In this patch series, A file mode is added to bpf map to store the
accessing mode. With this file mode flags, the map can be obtained read
only, write only or read and write. With the help of this file mode,
several security hooks can be added to the eBPF syscall implementations
to do permissions checks. These LSM hooks are mainly focused on checking
the process privileges before it obtains the fd for a specific bpf
object. No matter from a file location or from a eBPF id. Besides that,
a general check hook is also implemented at the start of bpf syscalls so
that each security module can have their own implementation on the reset
of bpf object related functionalities.

In order to store the ownership and security information about eBPF
maps, a security field pointer is added to the struct bpf_map. And the
last two patch set are implementation of selinux check on these hooks
introduced, plus an additional check when eBPF object is passed between
processes using unix socket as well as binder IPC.

Change since V1:

 - Whitelist the new bpf flags in the map allocate check.
 - Added bpf selftest for the new flags.
 - Added two new security hooks for copying the security information from
   the bpf object security struct to file security struct
 - Simplified the checking action when bpf fd is passed between processes.

Chenbo Feng (5):
  bpf: Add file mode configuration into bpf maps
  bpf: Add tests for eBPF file mode
  security: bpf: Add LSM hooks for bpf object related syscall
  selinux: bpf: Add selinux check for eBPF syscall operations
  selinux: bpf: Add addtional check for bpf object file receive

 include/linux/bpf.h                     |  15 ++-
 include/linux/lsm_hooks.h               |  71 +++++++++++++
 include/linux/security.h                |  54 ++++++++++
 include/uapi/linux/bpf.h                |   6 ++
 kernel/bpf/arraymap.c                   |   7 +-
 kernel/bpf/devmap.c                     |   5 +-
 kernel/bpf/hashtab.c                    |   5 +-
 kernel/bpf/inode.c                      |  15 ++-
 kernel/bpf/lpm_trie.c                   |   3 +-
 kernel/bpf/sockmap.c                    |   5 +-
 kernel/bpf/stackmap.c                   |   5 +-
 kernel/bpf/syscall.c                    | 112 ++++++++++++++++++---
 security/security.c                     |  40 ++++++++
 security/selinux/hooks.c                | 172 ++++++++++++++++++++++++++++++++
 security/selinux/include/classmap.h     |   2 +
 security/selinux/include/objsec.h       |   4 +
 tools/testing/selftests/bpf/test_maps.c |  48 +++++++++
 17 files changed, 542 insertions(+), 27 deletions(-)

-- 
2.14.2.920.gcf0c67979c-goog


^ permalink raw reply

* [PATCH net-next v2 2/5] bpf: Add tests for eBPF file mode
From: Chenbo Feng @ 2017-10-09 22:20 UTC (permalink / raw)
  To: linux-security-module, netdev, SELinux
  Cc: Jeffrey Vander Stoep, Alexei Starovoitov, lorenzo,
	Daniel Borkmann, Stephen Smalley, Chenbo Feng
In-Reply-To: <20171009222028.13096-1-chenbofeng.kernel@gmail.com>

From: Chenbo Feng <fengc@google.com>

Two related tests are added into bpf selftest to test read only map and
write only map. The tests verified the read only and write only flags
are working on hash maps.

Signed-off-by: Chenbo Feng <fengc@google.com>
---
 tools/testing/selftests/bpf/test_maps.c | 48 +++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
index fe3a443a1102..896f23cfe918 100644
--- a/tools/testing/selftests/bpf/test_maps.c
+++ b/tools/testing/selftests/bpf/test_maps.c
@@ -1033,6 +1033,51 @@ static void test_map_parallel(void)
 	assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
 }
 
+static void test_map_rdonly(void)
+{
+	int i, fd, key = 0, value = 0;
+
+	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+			    MAP_SIZE, map_flags | BPF_F_RDONLY);
+	if (fd < 0) {
+		printf("Failed to create map for read only test '%s'!\n",
+		       strerror(errno));
+		exit(1);
+	}
+
+	key = 1;
+	value = 1234;
+	/* Insert key=1 element. */
+	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
+	       errno == EPERM);
+
+	/* Check that key=2 is not found. */
+	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
+	assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
+}
+
+static void test_map_wronly(void)
+{
+	int i, fd, key = 0, value = 0;
+
+	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
+			    MAP_SIZE, map_flags | BPF_F_WRONLY);
+	if (fd < 0) {
+		printf("Failed to create map for read only test '%s'!\n",
+		       strerror(errno));
+		exit(1);
+	}
+
+	key = 1;
+	value = 1234;
+	/* Insert key=1 element. */
+	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0)
+
+	/* Check that key=2 is not found. */
+	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
+	assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
+}
+
 static void run_all_tests(void)
 {
 	test_hashmap(0, NULL);
@@ -1050,6 +1095,9 @@ static void run_all_tests(void)
 	test_map_large();
 	test_map_parallel();
 	test_map_stress();
+
+	test_map_rdonly();
+	test_map_wronly();
 }
 
 int main(void)
-- 
2.14.2.920.gcf0c67979c-goog


^ permalink raw reply related

* [PATCH net-next v2 1/5] bpf: Add file mode configuration into bpf maps
From: Chenbo Feng @ 2017-10-09 22:20 UTC (permalink / raw)
  To: linux-security-module, netdev, SELinux
  Cc: Jeffrey Vander Stoep, Alexei Starovoitov, lorenzo,
	Daniel Borkmann, Stephen Smalley, Chenbo Feng
In-Reply-To: <20171009222028.13096-1-chenbofeng.kernel@gmail.com>

From: Chenbo Feng <fengc@google.com>

Introduce the map read/write flags to the eBPF syscalls that returns the
map fd. The flags is used to set up the file mode when construct a new
file descriptor for bpf maps. To not break the backward capability, the
f_flags is set to O_RDWR if the flag passed by syscall is 0. Otherwise
it should be O_RDONLY or O_WRONLY. When the userspace want to modify or
read the map content, it will check the file mode to see if it is
allowed to make the change.

Signed-off-by: Chenbo Feng <fengc@google.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 include/linux/bpf.h      |  6 ++--
 include/uapi/linux/bpf.h |  6 ++++
 kernel/bpf/arraymap.c    |  7 +++--
 kernel/bpf/devmap.c      |  5 ++-
 kernel/bpf/hashtab.c     |  5 +--
 kernel/bpf/inode.c       | 15 ++++++---
 kernel/bpf/lpm_trie.c    |  3 +-
 kernel/bpf/sockmap.c     |  5 ++-
 kernel/bpf/stackmap.c    |  5 ++-
 kernel/bpf/syscall.c     | 80 +++++++++++++++++++++++++++++++++++++++++++-----
 10 files changed, 114 insertions(+), 23 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index bc7da2ddfcaf..0e9ca2555d7f 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -308,11 +308,11 @@ void bpf_map_area_free(void *base);
 
 extern int sysctl_unprivileged_bpf_disabled;
 
-int bpf_map_new_fd(struct bpf_map *map);
+int bpf_map_new_fd(struct bpf_map *map, int flags);
 int bpf_prog_new_fd(struct bpf_prog *prog);
 
 int bpf_obj_pin_user(u32 ufd, const char __user *pathname);
-int bpf_obj_get_user(const char __user *pathname);
+int bpf_obj_get_user(const char __user *pathname, int flags);
 
 int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value);
 int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value);
@@ -331,6 +331,8 @@ int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file,
 				void *key, void *value, u64 map_flags);
 int bpf_fd_htab_map_lookup_elem(struct bpf_map *map, void *key, u32 *value);
 
+int bpf_get_file_flag(int flags);
+
 /* memcpy that is used with 8-byte aligned pointers, power-of-8 size and
  * forced to use 'long' read/writes to try to atomically copy long counters.
  * Best-effort only.  No barriers here, since it _will_ race with concurrent
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 6db9e1d679cd..9cb50a228c39 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -217,6 +217,10 @@ enum bpf_attach_type {
 
 #define BPF_OBJ_NAME_LEN 16U
 
+/* Flags for accessing BPF object */
+#define BPF_F_RDONLY		(1U << 3)
+#define BPF_F_WRONLY		(1U << 4)
+
 union bpf_attr {
 	struct { /* anonymous struct used by BPF_MAP_CREATE command */
 		__u32	map_type;	/* one of enum bpf_map_type */
@@ -259,6 +263,7 @@ union bpf_attr {
 	struct { /* anonymous struct used by BPF_OBJ_* commands */
 		__aligned_u64	pathname;
 		__u32		bpf_fd;
+		__u32		file_flags;
 	};
 
 	struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */
@@ -286,6 +291,7 @@ union bpf_attr {
 			__u32		map_id;
 		};
 		__u32		next_id;
+		__u32		open_flags;
 	};
 
 	struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 68d866628be0..f869e48ef2f6 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -19,6 +19,9 @@
 
 #include "map_in_map.h"
 
+#define ARRAY_CREATE_FLAG_MASK \
+	(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
+
 static void bpf_array_free_percpu(struct bpf_array *array)
 {
 	int i;
@@ -56,8 +59,8 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
 
 	/* check sanity of attributes */
 	if (attr->max_entries == 0 || attr->key_size != 4 ||
-	    attr->value_size == 0 || attr->map_flags & ~BPF_F_NUMA_NODE ||
-	    (percpu && numa_node != NUMA_NO_NODE))
+	    attr->value_size == 0 || attr->map_flags &
+	    ~ARRAY_CREATE_FLAG_MASK || (percpu && numa_node != NUMA_NO_NODE))
 		return ERR_PTR(-EINVAL);
 
 	if (attr->value_size > KMALLOC_MAX_SIZE)
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index e093d9a2c4dd..e5d3de7cff2e 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -50,6 +50,9 @@
 #include <linux/bpf.h>
 #include <linux/filter.h>
 
+#define DEV_CREATE_FLAG_MASK \
+	(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
+
 struct bpf_dtab_netdev {
 	struct net_device *dev;
 	struct bpf_dtab *dtab;
@@ -80,7 +83,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
 
 	/* check sanity of attributes */
 	if (attr->max_entries == 0 || attr->key_size != 4 ||
-	    attr->value_size != 4 || attr->map_flags & ~BPF_F_NUMA_NODE)
+	    attr->value_size != 4 || attr->map_flags & ~DEV_CREATE_FLAG_MASK)
 		return ERR_PTR(-EINVAL);
 
 	dtab = kzalloc(sizeof(*dtab), GFP_USER);
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 431126f31ea3..919955236e63 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -18,8 +18,9 @@
 #include "bpf_lru_list.h"
 #include "map_in_map.h"
 
-#define HTAB_CREATE_FLAG_MASK \
-	(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE)
+#define HTAB_CREATE_FLAG_MASK						\
+	(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE |	\
+	 BPF_F_RDONLY | BPF_F_WRONLY)
 
 struct bucket {
 	struct hlist_nulls_head head;
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index e833ed914358..7d8c6dd8dd5d 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -295,7 +295,7 @@ int bpf_obj_pin_user(u32 ufd, const char __user *pathname)
 }
 
 static void *bpf_obj_do_get(const struct filename *pathname,
-			    enum bpf_type *type)
+			    enum bpf_type *type, int flags)
 {
 	struct inode *inode;
 	struct path path;
@@ -307,7 +307,7 @@ static void *bpf_obj_do_get(const struct filename *pathname,
 		return ERR_PTR(ret);
 
 	inode = d_backing_inode(path.dentry);
-	ret = inode_permission(inode, MAY_WRITE);
+	ret = inode_permission(inode, ACC_MODE(flags));
 	if (ret)
 		goto out;
 
@@ -326,18 +326,23 @@ static void *bpf_obj_do_get(const struct filename *pathname,
 	return ERR_PTR(ret);
 }
 
-int bpf_obj_get_user(const char __user *pathname)
+int bpf_obj_get_user(const char __user *pathname, int flags)
 {
 	enum bpf_type type = BPF_TYPE_UNSPEC;
 	struct filename *pname;
 	int ret = -ENOENT;
+	int f_flags;
 	void *raw;
 
+	f_flags = bpf_get_file_flag(flags);
+	if (f_flags < 0)
+		return f_flags;
+
 	pname = getname(pathname);
 	if (IS_ERR(pname))
 		return PTR_ERR(pname);
 
-	raw = bpf_obj_do_get(pname, &type);
+	raw = bpf_obj_do_get(pname, &type, f_flags);
 	if (IS_ERR(raw)) {
 		ret = PTR_ERR(raw);
 		goto out;
@@ -346,7 +351,7 @@ int bpf_obj_get_user(const char __user *pathname)
 	if (type == BPF_TYPE_PROG)
 		ret = bpf_prog_new_fd(raw);
 	else if (type == BPF_TYPE_MAP)
-		ret = bpf_map_new_fd(raw);
+		ret = bpf_map_new_fd(raw, f_flags);
 	else
 		goto out;
 
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index 34d8a690ea05..885e45479680 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -495,7 +495,8 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)
 #define LPM_KEY_SIZE_MAX	LPM_KEY_SIZE(LPM_DATA_SIZE_MAX)
 #define LPM_KEY_SIZE_MIN	LPM_KEY_SIZE(LPM_DATA_SIZE_MIN)
 
-#define LPM_CREATE_FLAG_MASK	(BPF_F_NO_PREALLOC | BPF_F_NUMA_NODE)
+#define LPM_CREATE_FLAG_MASK	(BPF_F_NO_PREALLOC | BPF_F_NUMA_NODE |	\
+				 BPF_F_RDONLY | BPF_F_WRONLY)
 
 static struct bpf_map *trie_alloc(union bpf_attr *attr)
 {
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index a298d6666698..86ec846f2d5e 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -40,6 +40,9 @@
 #include <linux/list.h>
 #include <net/strparser.h>
 
+#define SOCK_CREATE_FLAG_MASK \
+	(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
+
 struct bpf_stab {
 	struct bpf_map map;
 	struct sock **sock_map;
@@ -489,7 +492,7 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr)
 
 	/* check sanity of attributes */
 	if (attr->max_entries == 0 || attr->key_size != 4 ||
-	    attr->value_size != 4 || attr->map_flags & ~BPF_F_NUMA_NODE)
+	    attr->value_size != 4 || attr->map_flags & ~SOCK_CREATE_FLAG_MASK)
 		return ERR_PTR(-EINVAL);
 
 	if (attr->value_size > KMALLOC_MAX_SIZE)
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index 135be433e9a0..a15bc636cc98 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -11,6 +11,9 @@
 #include <linux/perf_event.h>
 #include "percpu_freelist.h"
 
+#define STACK_CREATE_FLAG_MASK \
+	(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
+
 struct stack_map_bucket {
 	struct pcpu_freelist_node fnode;
 	u32 hash;
@@ -60,7 +63,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
 	if (!capable(CAP_SYS_ADMIN))
 		return ERR_PTR(-EPERM);
 
-	if (attr->map_flags & ~BPF_F_NUMA_NODE)
+	if (attr->map_flags & ~STACK_CREATE_FLAG_MASK)
 		return ERR_PTR(-EINVAL);
 
 	/* check sanity of attributes */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index d124e702e040..b02582ead9a4 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -294,17 +294,48 @@ static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
 }
 #endif
 
+static ssize_t bpf_dummy_read(struct file *filp, char __user *buf, size_t siz,
+			      loff_t *ppos)
+{
+	/* We need this handler such that alloc_file() enables
+	 * f_mode with FMODE_CAN_READ.
+	 */
+	return -EINVAL;
+}
+
+static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
+			       size_t siz, loff_t *ppos)
+{
+	/* We need this handler such that alloc_file() enables
+	 * f_mode with FMODE_CAN_WRITE.
+	 */
+	return -EINVAL;
+}
+
 static const struct file_operations bpf_map_fops = {
 #ifdef CONFIG_PROC_FS
 	.show_fdinfo	= bpf_map_show_fdinfo,
 #endif
 	.release	= bpf_map_release,
+	.read		= bpf_dummy_read,
+	.write		= bpf_dummy_write,
 };
 
-int bpf_map_new_fd(struct bpf_map *map)
+int bpf_map_new_fd(struct bpf_map *map, int flags)
 {
 	return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
-				O_RDWR | O_CLOEXEC);
+				flags | O_CLOEXEC);
+}
+
+int bpf_get_file_flag(int flags)
+{
+	if ((flags & BPF_F_RDONLY) && (flags & BPF_F_WRONLY))
+		return -EINVAL;
+	if (flags & BPF_F_RDONLY)
+		return O_RDONLY;
+	if (flags & BPF_F_WRONLY)
+		return O_WRONLY;
+	return O_RDWR;
 }
 
 /* helper macro to check that unused fields 'union bpf_attr' are zero */
@@ -344,12 +375,17 @@ static int map_create(union bpf_attr *attr)
 {
 	int numa_node = bpf_map_attr_numa_node(attr);
 	struct bpf_map *map;
+	int f_flags;
 	int err;
 
 	err = CHECK_ATTR(BPF_MAP_CREATE);
 	if (err)
 		return -EINVAL;
 
+	f_flags = bpf_get_file_flag(attr->map_flags);
+	if (f_flags < 0)
+		return f_flags;
+
 	if (numa_node != NUMA_NO_NODE &&
 	    ((unsigned int)numa_node >= nr_node_ids ||
 	     !node_online(numa_node)))
@@ -375,7 +411,7 @@ static int map_create(union bpf_attr *attr)
 	if (err)
 		goto free_map;
 
-	err = bpf_map_new_fd(map);
+	err = bpf_map_new_fd(map, f_flags);
 	if (err < 0) {
 		/* failed to allocate fd.
 		 * bpf_map_put() is needed because the above
@@ -490,6 +526,11 @@ static int map_lookup_elem(union bpf_attr *attr)
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
+	if (!(f.file->f_mode & FMODE_CAN_READ)) {
+		err = -EPERM;
+		goto err_put;
+	}
+
 	key = memdup_user(ukey, map->key_size);
 	if (IS_ERR(key)) {
 		err = PTR_ERR(key);
@@ -570,6 +611,11 @@ static int map_update_elem(union bpf_attr *attr)
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
+	if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
+		err = -EPERM;
+		goto err_put;
+	}
+
 	key = memdup_user(ukey, map->key_size);
 	if (IS_ERR(key)) {
 		err = PTR_ERR(key);
@@ -653,6 +699,11 @@ static int map_delete_elem(union bpf_attr *attr)
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
+	if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
+		err = -EPERM;
+		goto err_put;
+	}
+
 	key = memdup_user(ukey, map->key_size);
 	if (IS_ERR(key)) {
 		err = PTR_ERR(key);
@@ -696,6 +747,11 @@ static int map_get_next_key(union bpf_attr *attr)
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
+	if (!(f.file->f_mode & FMODE_CAN_READ)) {
+		err = -EPERM;
+		goto err_put;
+	}
+
 	if (ukey) {
 		key = memdup_user(ukey, map->key_size);
 		if (IS_ERR(key)) {
@@ -902,6 +958,8 @@ static const struct file_operations bpf_prog_fops = {
 	.show_fdinfo	= bpf_prog_show_fdinfo,
 #endif
 	.release	= bpf_prog_release,
+	.read		= bpf_dummy_read,
+	.write		= bpf_dummy_write,
 };
 
 int bpf_prog_new_fd(struct bpf_prog *prog)
@@ -1111,11 +1169,11 @@ static int bpf_prog_load(union bpf_attr *attr)
 	return err;
 }
 
-#define BPF_OBJ_LAST_FIELD bpf_fd
+#define BPF_OBJ_LAST_FIELD file_flags
 
 static int bpf_obj_pin(const union bpf_attr *attr)
 {
-	if (CHECK_ATTR(BPF_OBJ))
+	if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0)
 		return -EINVAL;
 
 	return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
@@ -1126,7 +1184,8 @@ static int bpf_obj_get(const union bpf_attr *attr)
 	if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0)
 		return -EINVAL;
 
-	return bpf_obj_get_user(u64_to_user_ptr(attr->pathname));
+	return bpf_obj_get_user(u64_to_user_ptr(attr->pathname),
+				attr->file_flags);
 }
 
 #ifdef CONFIG_CGROUP_BPF
@@ -1386,12 +1445,13 @@ static int bpf_prog_get_fd_by_id(const union bpf_attr *attr)
 	return fd;
 }
 
-#define BPF_MAP_GET_FD_BY_ID_LAST_FIELD map_id
+#define BPF_MAP_GET_FD_BY_ID_LAST_FIELD open_flags
 
 static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
 {
 	struct bpf_map *map;
 	u32 id = attr->map_id;
+	int f_flags;
 	int fd;
 
 	if (CHECK_ATTR(BPF_MAP_GET_FD_BY_ID))
@@ -1400,6 +1460,10 @@ static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+	f_flags = bpf_get_file_flag(attr->open_flags);
+	if (f_flags < 0)
+		return f_flags;
+
 	spin_lock_bh(&map_idr_lock);
 	map = idr_find(&map_idr, id);
 	if (map)
@@ -1411,7 +1475,7 @@ static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
-	fd = bpf_map_new_fd(map);
+	fd = bpf_map_new_fd(map, f_flags);
 	if (fd < 0)
 		bpf_map_put(map);
 
-- 
2.14.2.920.gcf0c67979c-goog

^ permalink raw reply related

* [PATCH net-next v2 3/5] security: bpf: Add LSM hooks for bpf object related syscall
From: Chenbo Feng @ 2017-10-09 22:20 UTC (permalink / raw)
  To: linux-security-module, netdev, SELinux
  Cc: Jeffrey Vander Stoep, Alexei Starovoitov, lorenzo,
	Daniel Borkmann, Stephen Smalley, Chenbo Feng
In-Reply-To: <20171009222028.13096-1-chenbofeng.kernel@gmail.com>

From: Chenbo Feng <fengc@google.com>

Introduce several LSM hooks for the syscalls that will allow the
userspace to access to eBPF object such as eBPF programs and eBPF maps.
The security check is aimed to enforce a per object security protection
for eBPF object so only processes with the right priviliges can
read/write to a specific map or use a specific eBPF program. Besides
that, a general security hook is added before the multiplexer of bpf
syscall to check the cmd and the attribute used for the command. The
actual security module can decide which command need to be checked and
how the cmd should be checked.

Signed-off-by: Chenbo Feng <fengc@google.com>
---
 include/linux/bpf.h       |  6 ++++++
 include/linux/lsm_hooks.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/security.h  | 45 +++++++++++++++++++++++++++++++++++++++
 kernel/bpf/syscall.c      | 28 ++++++++++++++++++++++--
 security/security.c       | 32 ++++++++++++++++++++++++++++
 5 files changed, 163 insertions(+), 2 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 0e9ca2555d7f..225740688ab7 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -57,6 +57,9 @@ struct bpf_map {
 	atomic_t usercnt;
 	struct bpf_map *inner_map_meta;
 	char name[BPF_OBJ_NAME_LEN];
+#ifdef CONFIG_SECURITY
+	void *security;
+#endif
 };
 
 /* function argument constraints */
@@ -190,6 +193,9 @@ struct bpf_prog_aux {
 	struct user_struct *user;
 	u64 load_time; /* ns since boottime */
 	char name[BPF_OBJ_NAME_LEN];
+#ifdef CONFIG_SECURITY
+	void *security;
+#endif
 	union {
 		struct work_struct work;
 		struct rcu_head	rcu;
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index c9258124e417..7161d8e7ee79 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1351,6 +1351,40 @@
  *	@inode we wish to get the security context of.
  *	@ctx is a pointer in which to place the allocated security context.
  *	@ctxlen points to the place to put the length of @ctx.
+ *
+ * Security hooks for using the eBPF maps and programs functionalities through
+ * eBPF syscalls.
+ *
+ * @bpf:
+ *	Do a initial check for all bpf syscalls after the attribute is copied
+ *	into the kernel. The actual security module can implement their own
+ *	rules to check the specific cmd they need.
+ *
+ * @bpf_map:
+ *	Do a check when the kernel generate and return a file descriptor for
+ *	eBPF maps.
+ *
+ *	@map: bpf map that we want to access
+ *	@mask: the access flags
+ *
+ * @bpf_prog:
+ *	Do a check when the kernel generate and return a file descriptor for
+ *	eBPF programs.
+ *
+ *	@prog: bpf prog that userspace want to use.
+ *
+ * @bpf_map_alloc_security:
+ *	Initialize the security field inside bpf map.
+ *
+ * @bpf_map_free_security:
+ *	Clean up the security information stored inside bpf map.
+ *
+ * @bpf_prog_alloc_security:
+ *	Initialize the security field inside bpf program.
+ *
+ * @bpf_prog_free_security:
+ *	Clean up the security information stored inside bpf prog.
+ *
  */
 union security_list_options {
 	int (*binder_set_context_mgr)(struct task_struct *mgr);
@@ -1682,6 +1716,17 @@ union security_list_options {
 				struct audit_context *actx);
 	void (*audit_rule_free)(void *lsmrule);
 #endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_BPF_SYSCALL
+	int (*bpf)(int cmd, union bpf_attr *attr,
+				 unsigned int size);
+	int (*bpf_map)(struct bpf_map *map, fmode_t fmode);
+	int (*bpf_prog)(struct bpf_prog *prog);
+	int (*bpf_map_alloc_security)(struct bpf_map *map);
+	void (*bpf_map_free_security)(struct bpf_map *map);
+	int (*bpf_prog_alloc_security)(struct bpf_prog_aux *aux);
+	void (*bpf_prog_free_security)(struct bpf_prog_aux *aux);
+#endif /* CONFIG_BPF_SYSCALL */
 };
 
 struct security_hook_heads {
@@ -1901,6 +1946,15 @@ struct security_hook_heads {
 	struct list_head audit_rule_match;
 	struct list_head audit_rule_free;
 #endif /* CONFIG_AUDIT */
+#ifdef CONFIG_BPF_SYSCALL
+	struct list_head bpf;
+	struct list_head bpf_map;
+	struct list_head bpf_prog;
+	struct list_head bpf_map_alloc_security;
+	struct list_head bpf_map_free_security;
+	struct list_head bpf_prog_alloc_security;
+	struct list_head bpf_prog_free_security;
+#endif /* CONFIG_BPF_SYSCALL */
 } __randomize_layout;
 
 /*
diff --git a/include/linux/security.h b/include/linux/security.h
index ce6265960d6c..18800b0911e5 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -31,6 +31,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <linux/bpf.h>
 
 struct linux_binprm;
 struct cred;
@@ -1730,6 +1731,50 @@ static inline void securityfs_remove(struct dentry *dentry)
 
 #endif
 
+#ifdef CONFIG_BPF_SYSCALL
+#ifdef CONFIG_SECURITY
+extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size);
+extern int security_bpf_map(struct bpf_map *map, fmode_t fmode);
+extern int security_bpf_prog(struct bpf_prog *prog);
+extern int security_bpf_map_alloc(struct bpf_map *map);
+extern void security_bpf_map_free(struct bpf_map *map);
+extern int security_bpf_prog_alloc(struct bpf_prog_aux *aux);
+extern void security_bpf_prog_free(struct bpf_prog_aux *aux);
+#else
+static inline int security_bpf(int cmd, union bpf_attr *attr,
+					     unsigned int size)
+{
+	return 0;
+}
+
+static inline int security_bpf_map(struct bpf_map *map, fmode_t fmode)
+{
+	return 0;
+}
+
+static inline int security_bpf_prog(struct bpf_prog *prog)
+{
+	return 0;
+}
+
+static inline int security_bpf_map_alloc(struct bpf_map *map)
+{
+	return 0;
+}
+
+static inline void security_bpf_map_free(struct bpf_map *map)
+{ }
+
+static inline int security_bpf_prog_alloc(struct bpf_prog_aux *aux)
+{
+	return 0;
+}
+
+static inline void security_bpf_prog_free(struct bpf_prog_aux *aux)
+{ }
+#endif /* CONFIG_SECURITY */
+#endif /* CONFIG_BPF_SYSCALL */
+
 #ifdef CONFIG_SECURITY
 
 static inline char *alloc_secdata(void)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index b02582ead9a4..1cf31ddd7616 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -210,6 +210,7 @@ static void bpf_map_free_deferred(struct work_struct *work)
 	struct bpf_map *map = container_of(work, struct bpf_map, work);
 
 	bpf_map_uncharge_memlock(map);
+	security_bpf_map_free(map);
 	/* implementation dependent freeing */
 	map->ops->map_free(map);
 }
@@ -323,6 +324,9 @@ static const struct file_operations bpf_map_fops = {
 
 int bpf_map_new_fd(struct bpf_map *map, int flags)
 {
+	if (security_bpf_map(map, OPEN_FMODE(flags)))
+		return -EPERM;
+
 	return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
 				flags | O_CLOEXEC);
 }
@@ -403,10 +407,14 @@ static int map_create(union bpf_attr *attr)
 	atomic_set(&map->refcnt, 1);
 	atomic_set(&map->usercnt, 1);
 
-	err = bpf_map_charge_memlock(map);
+	err = security_bpf_map_alloc(map);
 	if (err)
 		goto free_map_nouncharge;
 
+	err = bpf_map_charge_memlock(map);
+	if (err)
+		goto free_map_sec;
+
 	err = bpf_map_alloc_id(map);
 	if (err)
 		goto free_map;
@@ -428,6 +436,8 @@ static int map_create(union bpf_attr *attr)
 
 free_map:
 	bpf_map_uncharge_memlock(map);
+free_map_sec:
+	security_bpf_map_free(map);
 free_map_nouncharge:
 	map->ops->map_free(map);
 	return err;
@@ -906,6 +916,7 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu)
 
 	free_used_maps(aux);
 	bpf_prog_uncharge_memlock(aux->prog);
+	security_bpf_prog_free(aux);
 	bpf_prog_free(aux->prog);
 }
 
@@ -964,6 +975,9 @@ static const struct file_operations bpf_prog_fops = {
 
 int bpf_prog_new_fd(struct bpf_prog *prog)
 {
+	if (security_bpf_prog(prog))
+		return -EPERM;
+
 	return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
 				O_RDWR | O_CLOEXEC);
 }
@@ -1103,10 +1117,14 @@ static int bpf_prog_load(union bpf_attr *attr)
 	if (!prog)
 		return -ENOMEM;
 
-	err = bpf_prog_charge_memlock(prog);
+	err = security_bpf_prog_alloc(prog->aux);
 	if (err)
 		goto free_prog_nouncharge;
 
+	err = bpf_prog_charge_memlock(prog);
+	if (err)
+		goto free_prog_sec;
+
 	prog->len = attr->insn_cnt;
 
 	err = -EFAULT;
@@ -1164,6 +1182,8 @@ static int bpf_prog_load(union bpf_attr *attr)
 	free_used_maps(prog->aux);
 free_prog:
 	bpf_prog_uncharge_memlock(prog);
+free_prog_sec:
+	security_bpf_prog_free(prog->aux);
 free_prog_nouncharge:
 	bpf_prog_free(prog);
 	return err;
@@ -1630,6 +1650,10 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
 	if (copy_from_user(&attr, uattr, size) != 0)
 		return -EFAULT;
 
+	err = security_bpf(cmd, &attr, size);
+	if (err)
+		return -EPERM;
+
 	switch (cmd) {
 	case BPF_MAP_CREATE:
 		err = map_create(&attr);
diff --git a/security/security.c b/security/security.c
index 4bf0f571b4ef..1cd8526cb0b7 100644
--- a/security/security.c
+++ b/security/security.c
@@ -12,6 +12,7 @@
  *	(at your option) any later version.
  */
 
+#include <linux/bpf.h>
 #include <linux/capability.h>
 #include <linux/dcache.h>
 #include <linux/module.h>
@@ -1703,3 +1704,34 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
 				actx);
 }
 #endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_BPF_SYSCALL
+int security_bpf(int cmd, union bpf_attr *attr, unsigned int size)
+{
+	return call_int_hook(bpf, 0, cmd, attr, size);
+}
+int security_bpf_map(struct bpf_map *map, fmode_t fmode)
+{
+	return call_int_hook(bpf_map, 0, map, fmode);
+}
+int security_bpf_prog(struct bpf_prog *prog)
+{
+	return call_int_hook(bpf_prog, 0, prog);
+}
+int security_bpf_map_alloc(struct bpf_map *map)
+{
+	return call_int_hook(bpf_map_alloc_security, 0, map);
+}
+int security_bpf_prog_alloc(struct bpf_prog_aux *aux)
+{
+	return call_int_hook(bpf_prog_alloc_security, 0, aux);
+}
+void security_bpf_map_free(struct bpf_map *map)
+{
+	call_void_hook(bpf_map_free_security, map);
+}
+void security_bpf_prog_free(struct bpf_prog_aux *aux)
+{
+	call_void_hook(bpf_prog_free_security, aux);
+}
+#endif /* CONFIG_BPF_SYSCALL */
-- 
2.14.2.920.gcf0c67979c-goog

^ permalink raw reply related

* [PATCH net-next v2 4/5] selinux: bpf: Add selinux check for eBPF syscall operations
From: Chenbo Feng @ 2017-10-09 22:20 UTC (permalink / raw)
  To: linux-security-module, netdev, SELinux
  Cc: Jeffrey Vander Stoep, Alexei Starovoitov, lorenzo,
	Daniel Borkmann, Stephen Smalley, Chenbo Feng
In-Reply-To: <20171009222028.13096-1-chenbofeng.kernel@gmail.com>

From: Chenbo Feng <fengc@google.com>

Implement the actual checks introduced to eBPF related syscalls. This
implementation use the security field inside bpf object to store a sid that
identify the bpf object. And when processes try to access the object,
selinux will check if processes have the right privileges. The creation
of eBPF object are also checked at the general bpf check hook and new
cmd introduced to eBPF domain can also be checked there.

Signed-off-by: Chenbo Feng <fengc@google.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 security/selinux/hooks.c            | 111 ++++++++++++++++++++++++++++++++++++
 security/selinux/include/classmap.h |   2 +
 security/selinux/include/objsec.h   |   4 ++
 3 files changed, 117 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f5d304736852..41aba4e3d57c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -85,6 +85,7 @@
 #include <linux/export.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
+#include <linux/bpf.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -6252,6 +6253,106 @@ static void selinux_ib_free_security(void *ib_sec)
 }
 #endif
 
+#ifdef CONFIG_BPF_SYSCALL
+static int selinux_bpf(int cmd, union bpf_attr *attr,
+				     unsigned int size)
+{
+	u32 sid = current_sid();
+	int ret;
+
+	switch (cmd) {
+	case BPF_MAP_CREATE:
+		ret = avc_has_perm(sid, sid, SECCLASS_BPF_MAP, BPF_MAP__CREATE,
+				   NULL);
+		break;
+	case BPF_PROG_LOAD:
+		ret = avc_has_perm(sid, sid, SECCLASS_BPF_PROG, BPF_PROG__LOAD,
+				   NULL);
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	return ret;
+}
+
+static u32 bpf_map_fmode_to_av(fmode_t fmode)
+{
+	u32 av = 0;
+
+	if (f_mode & FMODE_READ)
+		av |= BPF_MAP__READ;
+	if (f_mode & FMODE_WRITE)
+		av |= BPF_MAP__WRITE;
+	return av;
+}
+
+static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
+{
+	u32 sid = current_sid();
+	struct bpf_security_struct *bpfsec;
+
+	bpfsec = map->security;
+	return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF_MAP,
+			    bpf_map_fmode_to_av(fmode), NULL);
+}
+
+static int selinux_bpf_prog(struct bpf_prog *prog)
+{
+	u32 sid = current_sid();
+	struct bpf_security_struct *bpfsec;
+
+	bpfsec = prog->aux->security;
+	return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF_PROG,
+			    BPF_PROG__USE, NULL);
+}
+
+static int selinux_bpf_map_alloc(struct bpf_map *map)
+{
+	struct bpf_security_struct *bpfsec;
+
+	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
+	if (!bpfsec)
+		return -ENOMEM;
+
+	bpfsec->sid = current_sid();
+	map->security = bpfsec;
+
+	return 0;
+}
+
+static void selinux_bpf_map_free(struct bpf_map *map)
+{
+	struct bpf_security_struct *bpfsec = map->security;
+
+	map->security = NULL;
+	kfree(bpfsec);
+}
+
+static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
+{
+	struct bpf_security_struct *bpfsec;
+
+	bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
+	if (!bpfsec)
+		return -ENOMEM;
+
+	bpfsec->sid = current_sid();
+	aux->security = bpfsec;
+
+	return 0;
+}
+
+static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
+{
+	struct bpf_security_struct *bpfsec = aux->security;
+
+	aux->security = NULL;
+	kfree(bpfsec);
+}
+#endif
+
 static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
 	LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
@@ -6471,6 +6572,16 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
 	LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
 #endif
+
+#ifdef CONFIG_BPF_SYSCALL
+	LSM_HOOK_INIT(bpf, selinux_bpf),
+	LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
+	LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
+	LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
+	LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
+	LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
+	LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
+#endif
 };
 
 static __init int selinux_init(void)
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 35ffb29a69cb..7253c5eea59c 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -237,6 +237,8 @@ struct security_class_mapping secclass_map[] = {
 	  { "access", NULL } },
 	{ "infiniband_endport",
 	  { "manage_subnet", NULL } },
+	{ "bpf_map", {"create", "read", "write"} },
+	{ "bpf_prog", {"load", "use"} },
 	{ NULL }
   };
 
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 1649cd18eb0b..3d54468ce334 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -150,6 +150,10 @@ struct pkey_security_struct {
 	u32	sid;	/* SID of pkey */
 };
 
+struct bpf_security_struct {
+	u32 sid;  /*SID of bpf obj creater*/
+};
+
 extern unsigned int selinux_checkreqprot;
 
 #endif /* _SELINUX_OBJSEC_H_ */
-- 
2.14.2.920.gcf0c67979c-goog

^ permalink raw reply related

* [PATCH net-next v2 5/5] selinux: bpf: Add addtional check for bpf object file receive
From: Chenbo Feng @ 2017-10-09 22:20 UTC (permalink / raw)
  To: linux-security-module, netdev, SELinux
  Cc: Jeffrey Vander Stoep, Alexei Starovoitov, lorenzo,
	Daniel Borkmann, Stephen Smalley, Chenbo Feng
In-Reply-To: <20171009222028.13096-1-chenbofeng.kernel@gmail.com>

From: Chenbo Feng <fengc@google.com>

Introduce a bpf object related check when sending and receiving files
through unix domain socket as well as binder. It checks if the receiving
process have privilege to read/write the bpf map or use the bpf program.
This check is necessary because the bpf maps and programs are using a
anonymous inode as their shared inode so the normal way of checking the
files and sockets when passing between processes cannot work properly on
eBPF object. This check only works when the BPF_SYSCALL is configured.
The information stored inside the file security struct is the same as
the information in bpf object security struct.

Signed-off-by: Chenbo Feng <fengc@google.com>
---
 include/linux/bpf.h       |  3 +++
 include/linux/lsm_hooks.h | 17 +++++++++++++
 include/linux/security.h  |  9 +++++++
 kernel/bpf/syscall.c      |  4 ++--
 security/security.c       |  8 +++++++
 security/selinux/hooks.c  | 61 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 225740688ab7..81d6c01b8825 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -285,6 +285,9 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
 #ifdef CONFIG_BPF_SYSCALL
 DECLARE_PER_CPU(int, bpf_prog_active);
 
+extern const struct file_operations bpf_map_fops;
+extern const struct file_operations bpf_prog_fops;
+
 #define BPF_PROG_TYPE(_id, _ops) \
 	extern const struct bpf_verifier_ops _ops;
 #define BPF_MAP_TYPE(_id, _ops) \
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 7161d8e7ee79..517dea60b87b 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1385,6 +1385,19 @@
  * @bpf_prog_free_security:
  *	Clean up the security information stored inside bpf prog.
  *
+ * @bpf_map_file:
+ *	When creating a bpf map fd, set up the file security information with
+ *	the bpf security information stored in the map struct. So when the map
+ *	fd is passed between processes, the security module can directly read
+ *	the security information from file security struct rather than the bpf
+ *	security struct.
+ *
+ * @bpf_prog_file:
+ *	When creating a bpf prog fd, set up the file security information with
+ *	the bpf security information stored in the prog struct. So when the prog
+ *	fd is passed between processes, the security module can directly read
+ *	the security information from file security struct rather than the bpf
+ *	security struct.
  */
 union security_list_options {
 	int (*binder_set_context_mgr)(struct task_struct *mgr);
@@ -1726,6 +1739,8 @@ union security_list_options {
 	void (*bpf_map_free_security)(struct bpf_map *map);
 	int (*bpf_prog_alloc_security)(struct bpf_prog_aux *aux);
 	void (*bpf_prog_free_security)(struct bpf_prog_aux *aux);
+	void (*bpf_map_file)(struct bpf_map *map, struct file *file);
+	void (*bpf_prog_file)(struct bpf_prog_aux *aux, struct file *file);
 #endif /* CONFIG_BPF_SYSCALL */
 };
 
@@ -1954,6 +1969,8 @@ struct security_hook_heads {
 	struct list_head bpf_map_free_security;
 	struct list_head bpf_prog_alloc_security;
 	struct list_head bpf_prog_free_security;
+	struct list_head bpf_map_file;
+	struct list_head bpf_prog_file;
 #endif /* CONFIG_BPF_SYSCALL */
 } __randomize_layout;
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 18800b0911e5..57573b794e2d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1740,6 +1740,8 @@ extern int security_bpf_map_alloc(struct bpf_map *map);
 extern void security_bpf_map_free(struct bpf_map *map);
 extern int security_bpf_prog_alloc(struct bpf_prog_aux *aux);
 extern void security_bpf_prog_free(struct bpf_prog_aux *aux);
+extern void security_bpf_map_file(struct bpf_map *map, struct file *file);
+extern void security_bpf_prog_file(struct bpf_prog_aux *aux, struct file *file);
 #else
 static inline int security_bpf(int cmd, union bpf_attr *attr,
 					     unsigned int size)
@@ -1772,6 +1774,13 @@ static inline int security_bpf_prog_alloc(struct bpf_prog_aux *aux)
 
 static inline void security_bpf_prog_free(struct bpf_prog_aux *aux)
 { }
+
+static inline void security_bpf_map_file(struct bpf_map *map, struct file *file)
+{ }
+
+static inline void security_bpf_prog_file(struct bpf_prog_aux *aux,
+					  struct file *file)
+{ }
 #endif /* CONFIG_SECURITY */
 #endif /* CONFIG_BPF_SYSCALL */
 
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 1cf31ddd7616..b144181d3f3a 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -313,7 +313,7 @@ static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
 	return -EINVAL;
 }
 
-static const struct file_operations bpf_map_fops = {
+const struct file_operations bpf_map_fops = {
 #ifdef CONFIG_PROC_FS
 	.show_fdinfo	= bpf_map_show_fdinfo,
 #endif
@@ -964,7 +964,7 @@ static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
 }
 #endif
 
-static const struct file_operations bpf_prog_fops = {
+const struct file_operations bpf_prog_fops = {
 #ifdef CONFIG_PROC_FS
 	.show_fdinfo	= bpf_prog_show_fdinfo,
 #endif
diff --git a/security/security.c b/security/security.c
index 1cd8526cb0b7..dacf649b8cfa 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1734,4 +1734,12 @@ void security_bpf_prog_free(struct bpf_prog_aux *aux)
 {
 	call_void_hook(bpf_prog_free_security, aux);
 }
+void security_bpf_map_file(struct bpf_map *map, struct file *file)
+{
+	call_void_hook(bpf_map_file, map, file);
+}
+void security_bpf_prog_file(struct bpf_prog_aux *aux, struct file *file)
+{
+	call_void_hook(bpf_prog_file, aux, file);
+}
 #endif /* CONFIG_BPF_SYSCALL */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 41aba4e3d57c..fea88655e0ee 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1815,6 +1815,10 @@ static inline int file_path_has_perm(const struct cred *cred,
 	return inode_has_perm(cred, file_inode(file), av, &ad);
 }
 
+#ifdef CONFIG_BPF_SYSCALL
+static int bpf_file_check(struct file *file, u32 sid);
+#endif
+
 /* Check whether a task can use an open file descriptor to
    access an inode in a given way.  Check access to the
    descriptor itself, and then use dentry_has_perm to
@@ -1845,6 +1849,12 @@ static int file_has_perm(const struct cred *cred,
 			goto out;
 	}
 
+#ifdef CONFIG_BPF_SYSCALL
+	rc = bpf_file_check(file, cred_sid(cred));
+	if (rc)
+		goto out;
+#endif
+
 	/* av is zero if only checking access to the descriptor. */
 	rc = 0;
 	if (av)
@@ -2165,6 +2175,12 @@ static int selinux_binder_transfer_file(struct task_struct *from,
 			return rc;
 	}
 
+#ifdef CONFIG_BPF_SYSCALL
+	rc = bpf_file_check(file, sid);
+	if (rc)
+		return rc;
+#endif
+
 	if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
 		return 0;
 
@@ -6288,6 +6304,33 @@ static u32 bpf_map_fmode_to_av(fmode_t fmode)
 	return av;
 }
 
+/* This function will check the file pass through unix socket or binder to see
+ * if it is a bpf related object. And apply correspinding checks on the bpf
+ * object based on the type. The bpf maps and programs, not like other files and
+ * socket, are using a shared anonymous inode inside the kernel as their inode.
+ * So checking that inode cannot identify if the process have privilege to
+ * access the bpf object and that's why we have to add this additional check in
+ * selinux_file_receive and selinux_binder_transfer_files.
+ */
+static int bpf_file_check(struct file *file, u32 sid)
+{
+	struct file_security_struct *fsec = file->f_security;
+	int ret;
+
+	if (file->f_op == &bpf_map_fops) {
+		ret = avc_has_perm(sid, fsec->sid, SECCLASS_BPF_MAP,
+				   bpf_map_fmode_to_av(file->f_mode), NULL);
+		if (ret)
+			return ret;
+	} else if (file->f_op == &bpf_prog_fops) {
+		ret = avc_has_perm(sid, fsec->sid, SECCLASS_BPF_PROG,
+				   BPF_PROG__USE, NULL);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
 static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
 {
 	u32 sid = current_sid();
@@ -6351,6 +6394,22 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 	aux->security = NULL;
 	kfree(bpfsec);
 }
+
+static void selinux_bpf_map_file(struct bpf_map *map, struct file *file)
+{
+	struct bpf_security_struct *bpfsec = map->security;
+	struct file_security_struct *fsec = file->f_security;
+
+	fsec->sid = bpfsec->sid;
+}
+
+static void selinux_bpf_prog_file(struct bpf_prog_aux *aux, struct file *file)
+{
+	struct bpf_security_struct *bpfsec = aux->security;
+	struct file_security_struct *fsec = file->f_security;
+
+	fsec->sid = bpfsec->sid;
+}
 #endif
 
 static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
@@ -6581,6 +6640,8 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
 	LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
 	LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
+	LSM_HOOK_INIT(bpf_map_file, selinux_bpf_map_file),
+	LSM_HOOK_INIT(bpf_prog_file, selinux_bpf_prog_file),
 #endif
 };
 
-- 
2.14.2.920.gcf0c67979c-goog

^ permalink raw reply related

* [net-next 00/14][pull request] 40GbE Intel Wired LAN Driver Updates 2017-10-09
From: Jeff Kirsher @ 2017-10-09 22:38 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, nhorman, sassmann, jogreene

This series contains updates to i40e and i40evf only.

Jake fixes missed flag conversion from u64 to u32.  Fixes a deafult ITR
value issue where the driver defaults to an ITR value of half the
expected value (in terms of minimum microseconds between interrupts).  So
fix this by changing the default values to be calculated using the
ITR_REG_TO_USEC() macro which indicates that we are converting from the
register units into microseconds. Updates the drivers to bump the tail in
increments of 8 and double the number of descriptors we will bundle into
one tail bump when receiving.  With the recent kernel support for
enabling XPS and QoS at the same time, we no longer need to worry about
the number of traffic classes when enabling XPS.

Lihong converts the use of hash_for_each() to hash_for_each_safe() to
safely remove a hash entry.  Adds a check for the return value for
find_first_bit() in the case that it returns the size passed to search.

Alan fixes a bug in which filters are erroneously removed if they are
removed and then added again.  So make sure that when adding a filter, if
we find it already existed in our list, make sure it is not marked to be
removed.

Jayaprakash adds the retrying of PHY reads when the I2C is busy for a
maximum period of 500ms.

Rami fixes code comment typo.

Stefano Brivio simplifies the code by removing the use of a local
return code variable and simply return the results of the read function.

The following are changes since commit 2e997d8b12d2933d7640bb3a43af8eb6857a73af:
  Merge branch 'ipv6-addrlabel-avoid-dirtying-ip6addrlbl_entry'
and are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue 40GbE

Alan Brady (1):
  i40evf: fix mac filter removal timing issue

Jacob Keller (7):
  i40e: fix flags declaration
  i40e/i40evf: fix incorrect default ITR values on driver load
  i40e/i40evf: always set the CLEARPBA flag when re-enabling interrupts
  i40e: reduce lrxqthresh from 2 to 1
  i40e/i40evf: bump tail only in multiples of 8
  i40e/i40evf: bundle more descriptors when allocating buffers
  i40e: allow XPS with QoS enabled

Jayaprakash Shanmugam (1):
  i40e: Retry AQC GetPhyAbilities to overcome I2CRead hangs

Lihong Yang (3):
  i40e: use the safe hash table iterator when deleting mac filters
  i40e: add check for return from find_first_bit call
  i40e: use a local variable instead of calculating multiple times

Rami Rosen (1):
  i40e: fix a typo

Stefano Brivio (1):
  i40e: Avoid some useless variables and initializers in NVM functions

 drivers/net/ethernet/intel/i40e/i40e.h             |  7 ++--
 drivers/net/ethernet/intel/i40e/i40e_common.c      | 42 +++++++++++++++-------
 drivers/net/ethernet/intel/i40e/i40e_main.c        | 36 ++++++++-----------
 drivers/net/ethernet/intel/i40e/i40e_nvm.c         | 20 ++++-------
 drivers/net/ethernet/intel/i40e/i40e_txrx.c        | 15 +++++---
 drivers/net/ethernet/intel/i40e/i40e_txrx.h        |  8 +++--
 drivers/net/ethernet/intel/i40e/i40e_type.h        |  3 ++
 drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 27 +++++++-------
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c      | 13 +++++--
 drivers/net/ethernet/intel/i40evf/i40e_txrx.h      |  8 +++--
 drivers/net/ethernet/intel/i40evf/i40e_type.h      |  3 ++
 drivers/net/ethernet/intel/i40evf/i40evf_main.c    |  6 ++--
 12 files changed, 107 insertions(+), 81 deletions(-)

-- 
2.14.2

^ permalink raw reply

* [net-next 03/14] i40evf: fix mac filter removal timing issue
From: Jeff Kirsher @ 2017-10-09 22:38 UTC (permalink / raw)
  To: davem; +Cc: Alan Brady, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20171009223841.2557-1-jeffrey.t.kirsher@intel.com>

From: Alan Brady <alan.brady@intel.com>

Due to the asynchronous nature in which mac filters are added and
deleted, there exists a bug in which filters are erroneously removed if
removed then added again quickly.

The events are as such:
    - filter marked for removal
    - same filter is re-added before watchdog that cleans up filters
    - we skip re-adding the filter because we have it already in the
list
    - watchdog filter cleanup kicks off and filter is removed

So when we were re-adding the same filter, it didn't actually get added
because it already existed in the list, but was marked for removal and
had yet to actually be removed.

This patch fixes the issue by making sure that when adding a filter, if
we find it already existing in our list, make sure it is not marked to
be removed.

Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 1d2fc898b664..f62d9565c7b5 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -880,6 +880,8 @@ i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter,
 		list_add_tail(&f->list, &adapter->mac_filter_list);
 		f->add = true;
 		adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+	} else {
+		f->remove = false;
 	}
 
 	clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-- 
2.14.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox