* [PATCH net-next 0/2] net: ubuf_info.refcnt conversion
From: Eric Dumazet @ 2017-08-31 20:30 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Willem de Bruijn, Eric Dumazet, Eric Dumazet
Yet another atomic_t -> refcount_t conversion, split in two patches.
First patch prepares the automatic conversion done in the second patch.
Eric Dumazet (2):
net: prepare (struct ubuf_info)->refcnt conversion
net: convert (struct ubuf_info)->refcnt to refcount_t
include/linux/skbuff.h | 5 +++--
net/core/skbuff.c | 9 +++++----
net/ipv4/tcp.c | 2 --
3 files changed, 8 insertions(+), 8 deletions(-)
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply
* [PATCH net-next 1/2] net: prepare (struct ubuf_info)->refcnt conversion
From: Eric Dumazet @ 2017-08-31 20:30 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Willem de Bruijn, Eric Dumazet, Eric Dumazet
In-Reply-To: <20170831203013.9219-1-edumazet@google.com>
In order to convert this atomic_t refcnt to refcount_t,
we need to init the refcount to one to not trigger
a 0 -> 1 transition.
This also removes one atomic operation in fast path.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/core/skbuff.c | 3 ++-
net/ipv4/tcp.c | 2 --
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 917da73d3ab3b82163cf0a9ee944da09cb5a391f..65b9ca3945f8fd2b1bef4aef5dd774be04e5d128 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -963,7 +963,7 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
uarg->len = 1;
uarg->bytelen = size;
uarg->zerocopy = 1;
- atomic_set(&uarg->refcnt, 0);
+ atomic_set(&uarg->refcnt, 1);
sock_hold(sk);
return uarg;
@@ -1005,6 +1005,7 @@ struct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size,
uarg->len++;
uarg->bytelen = bytelen;
atomic_set(&sk->sk_zckey, ++next);
+ sock_zerocopy_get(uarg);
return uarg;
}
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 21ca2df274c5130a13d31a391a1408d779af34af..fff4d7bc3b8b46174e7bd0a04d7c212307e55cb5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1190,8 +1190,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
goto out_err;
}
- /* skb may be freed in main loop, keep extra ref on uarg */
- sock_zerocopy_get(uarg);
if (!(sk_check_csum_caps(sk) && sk->sk_route_caps & NETIF_F_SG))
uarg->zerocopy = 0;
}
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply related
* [PATCH net-next 2/2] net: convert (struct ubuf_info)->refcnt to refcount_t
From: Eric Dumazet @ 2017-08-31 20:30 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Willem de Bruijn, Eric Dumazet, Eric Dumazet
In-Reply-To: <20170831203013.9219-1-edumazet@google.com>
refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/skbuff.h | 5 +++--
net/core/skbuff.c | 8 ++++----
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 7594e19bce622a38dc39c054093c3da15b99b67b..316a92b45351f53709886ee0099cbc83b66f1b15 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -22,6 +22,7 @@
#include <linux/cache.h>
#include <linux/rbtree.h>
#include <linux/socket.h>
+#include <linux/refcount.h>
#include <linux/atomic.h>
#include <asm/types.h>
@@ -456,7 +457,7 @@ struct ubuf_info {
u32 bytelen;
};
};
- atomic_t refcnt;
+ refcount_t refcnt;
struct mmpin {
struct user_struct *user;
@@ -472,7 +473,7 @@ struct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size,
static inline void sock_zerocopy_get(struct ubuf_info *uarg)
{
- atomic_inc(&uarg->refcnt);
+ refcount_inc(&uarg->refcnt);
}
void sock_zerocopy_put(struct ubuf_info *uarg);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 65b9ca3945f8fd2b1bef4aef5dd774be04e5d128..ed86ca9afd9d8d1ac47983acf6006c179285a612 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -963,7 +963,7 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
uarg->len = 1;
uarg->bytelen = size;
uarg->zerocopy = 1;
- atomic_set(&uarg->refcnt, 1);
+ refcount_set(&uarg->refcnt, 1);
sock_hold(sk);
return uarg;
@@ -1086,7 +1086,7 @@ EXPORT_SYMBOL_GPL(sock_zerocopy_callback);
void sock_zerocopy_put(struct ubuf_info *uarg)
{
- if (uarg && atomic_dec_and_test(&uarg->refcnt)) {
+ if (uarg && refcount_dec_and_test(&uarg->refcnt)) {
if (uarg->callback)
uarg->callback(uarg, uarg->zerocopy);
else
@@ -1108,7 +1108,7 @@ void sock_zerocopy_put_abort(struct ubuf_info *uarg)
* avoid an skb send inside the main loop triggering uarg free.
*/
if (sk->sk_type != SOCK_STREAM)
- atomic_inc(&uarg->refcnt);
+ refcount_inc(&uarg->refcnt);
sock_zerocopy_put(uarg);
}
@@ -1490,7 +1490,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
if (skb_orphan_frags(skb, gfp_mask))
goto nofrags;
if (skb_zcopy(skb))
- atomic_inc(&skb_uarg(skb)->refcnt);
+ refcount_inc(&skb_uarg(skb)->refcnt);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
skb_frag_ref(skb, i);
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply related
* Re: [PATCH][net-next] net: qualcomm: rmnet: remove unused variable priv
From: Subash Abhinov Kasiviswanathan @ 2017-08-31 20:34 UTC (permalink / raw)
To: Colin King; +Cc: David S . Miller, netdev, kernel-janitors, linux-kernel
In-Reply-To: <20170831140727.28170-1-colin.king@canonical.com>
On 2017-08-31 08:07, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> priv is being assigned but is never used, so remove it.
>
> Cleans up clang build warning:
> "warning: Value stored to 'priv' is never read"
>
> Fixes: ceed73a2cf4a ("drivers: net: ethernet: qualcomm: rmnet: Initial
> implementation")
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
> drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 3 ---
> 1 file changed, 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
> b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
> index c8b573d28dcf..bf7455fdafcc 100644
> --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
> +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
> @@ -73,9 +73,6 @@ static const struct net_device_ops rmnet_vnd_ops = {
> */
> void rmnet_vnd_setup(struct net_device *rmnet_dev)
> {
> - struct rmnet_priv *priv;
> -
> - priv = netdev_priv(rmnet_dev);
> netdev_dbg(rmnet_dev, "Setting up device %s\n", rmnet_dev->name);
>
> rmnet_dev->netdev_ops = &rmnet_vnd_ops;
Thanks for fixing this.
Acked-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
^ permalink raw reply
* Re: [PATCH v2 net-next 1/8] bpf: Add support for recursively running cgroup sock filters
From: David Ahern @ 2017-08-31 20:53 UTC (permalink / raw)
To: Tejun Heo, Alexei Starovoitov; +Cc: netdev, daniel, ast, davem
In-Reply-To: <20170831142201.GB1599492@devbig577.frc2.facebook.com>
On 8/31/17 8:22 AM, Tejun Heo wrote:
> On Sun, Aug 27, 2017 at 08:49:23AM -0600, David Ahern wrote:
>> On 8/25/17 8:49 PM, Alexei Starovoitov wrote:
>>>
>>>> + if (prog && curr_recursive && !new_recursive)
>>>> + /* if a parent has recursive prog attached, only
>>>> + * allow recursive programs in descendent cgroup
>>>> + */
>>>> + return -EINVAL;
>>>> +
>>>> old_prog = cgrp->bpf.prog[type];
>>>
>>> ... I'm struggling to completely understand how it interacts
>>> with BPF_F_ALLOW_OVERRIDE.
>>
>> The 2 flags are completely independent. The existing override logic is
>> unchanged. If a program can not be overridden, then the new recursive
>> flag is irrelevant.
>
> I'm not sure all four combo of the two flags makes sense. Can't we
> have something simpler like the following?
>
> 1. None: No further bpf programs allowed in the subtree.
>
> 2. Overridable: If a sub-cgroup installs the same bpf program, this
> one yields to that one.
>
> 3. Recursive: If a sub-cgroup installs the same bpf program, that
> cgroup program gets run in addition to this one.
>
> Note that we can have combinations of overridables and recursives -
> both allow further programs in the sub-hierarchy and the only
> distinction is whether that specific program behaves when that
> happens.
>
I am going to send v3 for patches 2-6 and 8 - the uncontested patches.
Alexei and I will meet in L.A. the week of Sept 11-15 to discuss the
recursive implementation (Patch 1 and its testing, patch 7).
^ permalink raw reply
* [PATCH 0/3] Security: add lsm hooks for checking permissions on eBPF objects
From: Chenbo Feng @ 2017-08-31 20:56 UTC (permalink / raw)
To: linux-security-module
Cc: Jeffrey Vander Stoep, netdev, SELinux, Alexei Starovoitov,
lorenzo, 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 object.
Selinux could use these hooks to grant the following permissions:
allow netd self:bpf { create modify read…};
allow netmonitor netd:bpf read;
In this patch series, 5 security hooks is added to the eBPF syscall
implementations to do permissions checks. The LSM hooks introduced to eBPF
maps and programs can be summarized as follows:
Bpf_map_create: check for the ability of creating eBPF maps.
Bpf_map_modify: check the ability of update and delete eBPF map
entries.
Bpf_map_read: check the ability of lookup map element as well as
get map keys.
Bpf_post_create: initialize the security struct inside struct
bpf_map
Bpf_prog_load: check the ability for loading the eBPF program.
In order to store the ownership and security information about eBPF maps,
a security field pointer is added to the struct bpf_map. And a simple
implementation of selinux check on these hooks is added in selinux
subsystem.
Chenbo Feng (3):
security: bpf: Add eBPF LSM hooks to security module
security: bpf: Add eBPF LSM hooks and security field to eBPF map
selinux: bpf: Implement the selinux checks for eBPF object
include/linux/bpf.h | 3 +++
include/linux/lsm_hooks.h | 41 ++++++++++++++++++++++++++++
include/linux/security.h | 36 +++++++++++++++++++++++++
kernel/bpf/syscall.c | 28 +++++++++++++++++++
security/security.c | 28 +++++++++++++++++++
security/selinux/hooks.c | 54 +++++++++++++++++++++++++++++++++++++
security/selinux/include/classmap.h | 2 ++
security/selinux/include/objsec.h | 4 +++
8 files changed, 196 insertions(+)
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply
* [PATCH 1/3] security: bpf: Add eBPF LSM hooks to security module
From: Chenbo Feng @ 2017-08-31 20:56 UTC (permalink / raw)
To: linux-security-module
Cc: Jeffrey Vander Stoep, netdev, SELinux, Alexei Starovoitov,
lorenzo, Chenbo Feng
In-Reply-To: <20170831205635.80256-1-chenbofeng.kernel@gmail.com>
From: Chenbo Feng <fengc@google.com>
Introduce 5 LSM hooks to provide finer granularity controls on eBPF
related operations including create eBPF maps, modify and read eBPF maps
content and load eBPF programs to the kernel. Hooks use the new security
pointer inside the eBPF map struct to store the owner's security
information and the different security modules can perform different
checks based on the information stored inside the security field.
Signed-off-by: Chenbo Feng <fengc@google.com>
---
include/linux/lsm_hooks.h | 41 +++++++++++++++++++++++++++++++++++++++++
include/linux/security.h | 36 ++++++++++++++++++++++++++++++++++++
security/security.c | 28 ++++++++++++++++++++++++++++
3 files changed, 105 insertions(+)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index ce02f76a6188..3aaf9a08a983 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1353,6 +1353,32 @@
* @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_map_create:
+ * Check permissions prior to creating a new bpf map.
+ * Return 0 if the permission is granted.
+ *
+ * @bpf_map_modify:
+ * Check permission prior to insert, update and delete map content.
+ * @map pointer to the struct bpf_map that contains map information.
+ * Return 0 if the permission is granted.
+ *
+ * @bpf_map_read:
+ * Check permission prior to read a bpf map content.
+ * @map pointer to the struct bpf_map that contains map information.
+ * Return 0 if the permission is granted.
+ *
+ * @bpf_prog_load:
+ * Check permission prior to load eBPF program.
+ * Return 0 if the permission is granted.
+ *
+ * @bpf_post_create:
+ * Initialize the bpf object security field inside struct bpf_maps and
+ * it is used for future security checks.
+ *
*/
union security_list_options {
int (*binder_set_context_mgr)(struct task_struct *mgr);
@@ -1685,6 +1711,14 @@ union security_list_options {
struct audit_context *actx);
void (*audit_rule_free)(void *lsmrule);
#endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_BPF_SYSCALL
+ int (*bpf_map_create)(void);
+ int (*bpf_map_read)(struct bpf_map *map);
+ int (*bpf_map_modify)(struct bpf_map *map);
+ int (*bpf_prog_load)(void);
+ int (*bpf_post_create)(struct bpf_map *map);
+#endif /* CONFIG_BPF_SYSCALL */
};
struct security_hook_heads {
@@ -1905,6 +1939,13 @@ 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_map_create;
+ struct list_head bpf_map_read;
+ struct list_head bpf_map_modify;
+ struct list_head bpf_prog_load;
+ struct list_head bpf_post_create;
+#endif /* CONFIG_BPF_SYSCALL */
} __randomize_layout;
/*
diff --git a/include/linux/security.h b/include/linux/security.h
index 458e24bea2d4..0656a4f74d14 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;
@@ -1735,6 +1736,41 @@ static inline void securityfs_remove(struct dentry *dentry)
#endif
+#ifdef CONFIG_BPF_SYSCALL
+#ifdef CONFIG_SECURITY
+int security_map_create(void);
+int security_map_modify(struct bpf_map *map);
+int security_map_read(struct bpf_map *map);
+int security_prog_load(void);
+int security_post_create(struct bpf_map *map);
+#else
+static inline int security_map_create(void)
+{
+ return 0;
+}
+
+static inline int security_map_read(struct bpf_map *map)
+{
+ return 0;
+}
+
+static inline int security_map_modify(struct bpf_map *map)
+{
+ return 0;
+}
+
+static inline int security_prog_load(void)
+{
+ return 0;
+}
+
+static inline int security_post_create(struct bpf_map *map)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY */
+#endif /* CONFIG_BPF_SYSCALL */
+
#ifdef CONFIG_SECURITY
static inline char *alloc_secdata(void)
diff --git a/security/security.c b/security/security.c
index 55b5997e4b72..02272f93a89e 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>
@@ -1708,3 +1709,30 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
actx);
}
#endif /* CONFIG_AUDIT */
+
+#ifdef CONFIG_BPF_SYSCALL
+int security_map_create(void)
+{
+ return call_int_hook(bpf_map_create, 0);
+}
+
+int security_map_modify(struct bpf_map *map)
+{
+ return call_int_hook(bpf_map_modify, 0, map);
+}
+
+int security_map_read(struct bpf_map *map)
+{
+ return call_int_hook(bpf_map_read, 0, map);
+}
+
+int security_prog_load(void)
+{
+ return call_int_hook(bpf_prog_load, 0);
+}
+
+int security_post_create(struct bpf_map *map)
+{
+ return call_int_hook(bpf_post_create, 0, map);
+}
+#endif /* CONFIG_BPF_SYSCALL */
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply related
* [PATCH 2/3] security: bpf: Add eBPF LSM hooks and security field to eBPF map
From: Chenbo Feng @ 2017-08-31 20:56 UTC (permalink / raw)
To: linux-security-module
Cc: Jeffrey Vander Stoep, netdev, SELinux, Alexei Starovoitov,
lorenzo, Chenbo Feng
In-Reply-To: <20170831205635.80256-1-chenbofeng.kernel@gmail.com>
From: Chenbo Feng <fengc@google.com>
Introduce a pointer into struct bpf_map to hold the security information
about the map. The actual security struct varies based on the security
models implemented. Place the LSM hooks before each of the unrestricted
eBPF operations, the map_update_elem and map_delete_elem operations are
checked by security_map_modify. The map_lookup_elem and map_get_next_key
operations are checked by securtiy_map_read.
Signed-off-by: Chenbo Feng <fengc@google.com>
---
include/linux/bpf.h | 3 +++
kernel/bpf/syscall.c | 28 ++++++++++++++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index b69e7a5869ff..ca3e6ff7091d 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -53,6 +53,9 @@ struct bpf_map {
struct work_struct work;
atomic_t usercnt;
struct bpf_map *inner_map_meta;
+#ifdef CONFIG_SECURITY
+ void *security;
+#endif
};
/* function argument constraints */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 045646da97cc..b15580bcf3b1 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -279,6 +279,10 @@ static int map_create(union bpf_attr *attr)
if (err)
return -EINVAL;
+ err = security_map_create();
+ if (err)
+ return -EACCES;
+
/* find map type and init map: hashtable vs rbtree vs bloom vs ... */
map = find_and_alloc_map(attr);
if (IS_ERR(map))
@@ -291,6 +295,10 @@ static int map_create(union bpf_attr *attr)
if (err)
goto free_map_nouncharge;
+ err = security_post_create(map);
+ if (err < 0)
+ goto free_map;
+
err = bpf_map_alloc_id(map);
if (err)
goto free_map;
@@ -410,6 +418,10 @@ static int map_lookup_elem(union bpf_attr *attr)
if (IS_ERR(map))
return PTR_ERR(map);
+ err = security_map_read(map);
+ if (err)
+ return -EACCES;
+
key = memdup_user(ukey, map->key_size);
if (IS_ERR(key)) {
err = PTR_ERR(key);
@@ -490,6 +502,10 @@ static int map_update_elem(union bpf_attr *attr)
if (IS_ERR(map))
return PTR_ERR(map);
+ err = security_map_modify(map);
+ if (err)
+ return -EACCES;
+
key = memdup_user(ukey, map->key_size);
if (IS_ERR(key)) {
err = PTR_ERR(key);
@@ -573,6 +589,10 @@ static int map_delete_elem(union bpf_attr *attr)
if (IS_ERR(map))
return PTR_ERR(map);
+ err = security_map_modify(map);
+ if (err)
+ return -EACCES;
+
key = memdup_user(ukey, map->key_size);
if (IS_ERR(key)) {
err = PTR_ERR(key);
@@ -616,6 +636,10 @@ static int map_get_next_key(union bpf_attr *attr)
if (IS_ERR(map))
return PTR_ERR(map);
+ err = security_map_read(map);
+ if (err)
+ return -EACCES;
+
if (ukey) {
key = memdup_user(ukey, map->key_size);
if (IS_ERR(key)) {
@@ -935,6 +959,10 @@ static int bpf_prog_load(union bpf_attr *attr)
if (CHECK_ATTR(BPF_PROG_LOAD))
return -EINVAL;
+ err = security_prog_load();
+ if (err)
+ return -EACCES;
+
if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
return -EINVAL;
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply related
* [PATCH 3/3] selinux: bpf: Implement the selinux checks for eBPF object
From: Chenbo Feng @ 2017-08-31 20:56 UTC (permalink / raw)
To: linux-security-module
Cc: Jeffrey Vander Stoep, netdev, SELinux, Alexei Starovoitov,
lorenzo, Chenbo Feng
In-Reply-To: <20170831205635.80256-1-chenbofeng.kernel@gmail.com>
From: Chenbo Feng <fengc@google.com>
Introduce 5 new selinux checks for eBPF object related operations. The
check is based on the ownership information of eBPF maps and the
capability of creating eBPF object.
Signed-off-by: Chenbo Feng <fengc@google.com>
---
security/selinux/hooks.c | 54 +++++++++++++++++++++++++++++++++++++
security/selinux/include/classmap.h | 2 ++
security/selinux/include/objsec.h | 4 +++
3 files changed, 60 insertions(+)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 33fd061305c4..39ad7d9f335d 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"
@@ -6245,6 +6246,52 @@ static void selinux_ib_free_security(void *ib_sec)
}
#endif
+#ifdef CONFIG_BPF_SYSCALL
+static int selinux_bpf_map_create(void)
+{
+ u32 sid = current_sid();
+
+ return avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, NULL);
+}
+
+static int selinux_bpf_map_modify(struct bpf_map *map)
+{
+ struct bpf_security_struct *bpfsec = map->security;
+
+ return avc_has_perm(current_sid(), bpfsec->sid, SECCLASS_BPF,
+ BPF__MAP_MODIFY, NULL);
+}
+
+static int selinux_bpf_map_read(struct bpf_map *map)
+{
+ struct bpf_security_struct *bpfsec = map->security;
+
+ return avc_has_perm(current_sid(), bpfsec->sid, SECCLASS_BPF,
+ BPF__MAP_READ, NULL);
+}
+
+static int selinux_bpf_prog_load(void)
+{
+ u32 sid = current_sid();
+
+ return avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, NULL);
+}
+
+static int selinux_bpf_post_create(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;
+}
+#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),
@@ -6465,6 +6512,13 @@ 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_map_create, selinux_bpf_map_create),
+ LSM_HOOK_INIT(bpf_map_modify, selinux_bpf_map_modify),
+ LSM_HOOK_INIT(bpf_map_read, selinux_bpf_map_read),
+ LSM_HOOK_INIT(bpf_prog_load, selinux_bpf_prog_load),
+ LSM_HOOK_INIT(bpf_post_create, selinux_bpf_post_create),
+#endif
};
static __init int selinux_init(void)
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index b9fe3434b036..83c880fb17b4 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -235,6 +235,8 @@ struct security_class_mapping secclass_map[] = {
{ "access", NULL } },
{ "infiniband_endport",
{ "manage_subnet", NULL } },
+ { "bpf",
+ {"map_create", "map_modify", "map_read", "prog_load" } },
{ NULL }
};
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 6ebc61e370ff..ba564f662b0d 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.1.581.gf28d330327-goog
^ permalink raw reply related
* Re: [PATCH v4 4/5] net: stmmac: dwmac-sun8i: choose internal PHY via phy-is-integrated
From: Andrew Lunn @ 2017-08-31 20:59 UTC (permalink / raw)
To: Rob Herring
Cc: Corentin Labbe, mark.rutland-5wv7dgnIgG8,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8, wens-jdAy2FN1RRM,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, peppe.cavallaro-qxv4g6HH51o,
alexandre.torgue-qxv4g6HH51o, f.fainelli-Re5JQEeQqe8AvxtiuMwx3w,
icenowy-h8G6r0blFSE, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170831201803.x6vwftfcllrfpk6q@rob-hp-laptop>
On Thu, Aug 31, 2017 at 03:18:03PM -0500, Rob Herring wrote:
> On Sat, Aug 26, 2017 at 11:20:51PM +0200, Andrew Lunn wrote:
> > Hi Corentin
> >
> > I think we have now all agreed this is an mdio-mux, plus it is also an
> > MII mux. We should represent that in device tree. This patchset does
> > this. However, as it is now, the mux structure in DT is ignored. All
> > it does is search for the phy-is-integrated flags and goes on that.
> >
> > I made the comment that the device tree representation cannot be
> > implemented using an MDIO mux driver, because of driver loading
> > issues. However, the core of the MDIO mux code is just a library,
> > symbols exported as GPL, free for anything to use.
> >
> > What i think should happen is the mdio-mux is implemented inside the
> > MAC driver, using the mux-core as a library. The device tree structure
> > of a mix is then reflected within Linux. The mux switch callback is
> > implemented within the MAC driver. So it can reset the MAC when the
> > mux is switched. The 'phy-is-integrated' property is then no longer
> > needed.
> >
> > I would suggest a binding something like:
>
> This is looks better to me, but...
>
> > emac: ethernet@1c0b000 {
> > compatible = "allwinner,sun8i-h3-emac";
> > syscon = <&syscon>;
> > reg = <0x01c0b000 0x104>;
> > interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
> > interrupt-names = "macirq";
> > resets = <&ccu RST_BUS_EMAC>;
> > reset-names = "stmmaceth";
> > clocks = <&ccu CLK_BUS_EMAC>;
> > clock-names = "stmmaceth";
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > phy-handle = <&int_mii_phy>;
> > phy-mode = "mii";
> > allwinner,leds-active-low;
> >
> > mdio: mdio {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > }
>
> Why do you need this node still?
Hi Rob
It might not be needed, depending on how it is implemented. But:
Documentation/devicetree/bindings/net/mdio-mux.txt
It is normal for an mdio bus mux to have a phandle back to the parent
mdio bus. Also, i think the stmmac driver will only instantiate the
mdio bus if there is a node for it in the device tree.
Andrew
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH net-next] doc: document MSG_ZEROCOPY
From: Willem de Bruijn @ 2017-08-31 21:00 UTC (permalink / raw)
To: netdev; +Cc: davem, Willem de Bruijn
From: Willem de Bruijn <willemb@google.com>
Documentation for this feature was missing from the patchset.
Copied a lot from the netdev 2.1 paper, addressing some small
interface changes since then.
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
Documentation/networking/msg_zerocopy.rst | 254 ++++++++++++++++++++++++++++++
1 file changed, 254 insertions(+)
create mode 100644 Documentation/networking/msg_zerocopy.rst
diff --git a/Documentation/networking/msg_zerocopy.rst b/Documentation/networking/msg_zerocopy.rst
new file mode 100644
index 000000000000..2e2a3410b947
--- /dev/null
+++ b/Documentation/networking/msg_zerocopy.rst
@@ -0,0 +1,254 @@
+
+============
+MSG_ZEROCOPY
+============
+
+Intro
+=====
+
+The MSG_ZEROCOPY flag enables copy avoidance for socket send calls.
+The feature is currently implemented for TCP sockets.
+
+
+Opportunity and Caveats
+-----------------------
+
+Copying large buffers between user process and kernel can be
+expensive. Linux supports various interfaces that eschew copying,
+such as sendpage and splice. The MSG_ZEROCOPY flag extends the
+underlying copy avoidance mechanism to common socket send calls.
+
+Copy avoidance is not a free lunch. As implemented, with page pinning,
+it replaces per byte copy cost with page accounting and completion
+notification overhead. As a result, MSG_ZEROCOPY is generally only
+effective at writes over around 10 KB.
+
+Page pinning also changes system call semantics. It temporarily shares
+the buffer between process and network stack. Unlike with copying, the
+process cannot immediately overwrite the buffer after system call
+return without possibly modifying the data in flight. Kernel integrity
+is not affected, but a buggy program can possibly corrupt its own data
+stream.
+
+The kernel returns a notification when it is safe to modify data.
+Converting an existing application to MSG_ZEROCOPY is not always as
+trivial as just passing the flag, then.
+
+
+More Info
+---------
+
+Much of this document was derived from a longer paper presented at
+netdev 2.1. For more in-depth information see that paper and talk,
+the excellent reporting over at LWN.net or read the original code.
+
+ paper, slides, video
+ https://netdevconf.org/2.1/session.html?debruijn
+
+ LWN article
+ https://lwn.net/Articles/726917/
+
+ patchset
+ [PATCH net-next v4 0/9] socket sendmsg MSG_ZEROCOPY
+ https://lwn.net/Articles/730010/
+ https://www.spinics.net/lists/netdev/msg447552.html
+
+
+Interface
+=========
+
+Passing the MSG_ZEROCOPY flag is the most obvious step to enable copy
+avoidance, but not the only one.
+
+Socket Setup
+------------
+
+The kernel is permissive when applications pass undefined flags to the
+send system call. By default it simply ignores these. To avoid enabling
+copy avoidance mode for legacy processes that accidentally pass this
+flag, a process must first signal intent by setting a socket option:
+
+::
+
+ if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &one, sizeof(one)))
+ error(1, errno, "setsockopt zerocopy");
+
+
+Transmission
+------------
+
+The change to send (or sendto, sendmsg, sendmmsg) itself is trivial.
+Pass the new flag.
+
+::
+
+ ret = send(fd, buf, sizeof(buf), MSG_ZEROCOPY);
+ if (ret != sizeof(buf))
+ error(1, errno, "send");
+
+
+Mixing copy avoidance and copying
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many workloads have a mixture of large and small buffers. Because copy
+avoidance is more expensive than copying for small packets, the
+feature is implemented as a flag. It is safe to mix calls with the flag
+with those without.
+
+
+Notifications
+-------------
+
+The kernel has to notify the process when it is safe to reuse a
+previously passed buffer. It queues completion notifications on the
+socket error queue, akin to the transmit timestamping interface.
+
+The notification itself is a simple scalar value. Each socket
+maintains an internal 32-bit counter. Each send call with MSG_ZEROCOPY
+that successfully sends data increments the counter. The counter is
+not incremented on failure or if called with length zero.
+
+
+Notification Reception
+~~~~~~~~~~~~~~~~~~~~~~
+
+The below snippet demonstrates the API. In the simplest case, each
+send syscall is followed by a poll and recvmsg on the error queue.
+
+Reading from the error queue is always a non-blocking operation. The
+poll call is there to block until an error is outstanding. It will set
+POLLERR in its output flags. That flag does not have to be set in the
+events field: errors are signaled unconditionally.
+
+::
+
+ pfd.fd = fd;
+ pfd.events = 0;
+ if (poll(&pfd, 1, -1) != 1 || pfd.revents & POLLERR == 0)
+ error(1, errno, "poll");
+
+ ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
+ if (ret == -1)
+ error(1, errno, "recvmsg");
+
+ read_notification(msg);
+
+The example is for demonstration purpose only. In practice, it is more
+efficient to not wait for notifications, but read without blocking
+every couple of send calls.
+
+Notifications can be processed out of order with other operations on
+the socket. A socket that has an error queued would normally block
+other operations until the error is read. Zerocopy notifications have
+a zero error code, however, to not block send and recv calls.
+
+
+Notification Batching
+~~~~~~~~~~~~~~~~~~~~~
+
+Multiple outstanding packets can be read at once using the recvmmsg
+call. This is often not needed. In each message the kernel returns not
+a single value, but a range. It coalesces consecutive notifications
+while one is outstanding for reception on the error queue.
+
+When a new notification is about to be queued, it checks whether the
+new value extends the range of the notification at the tail of the
+queue. If so, it drops the new notification packet and instead increases
+the range upper value of the outstanding notification.
+
+For protocols that acknowledge data in-order, like TCP, each
+notification can be squashed into the previous one, so that no more
+than one notification is outstanding at any one point.
+
+Ordered delivery is the common case, but not guaranteed. Notifications
+may arrive out of order on retransmission and socket teardown.
+
+
+Notification Parsing
+~~~~~~~~~~~~~~~~~~~~
+
+The below snippet demonstrates how to parse the control message: the
+read_notification() call in the previous snippet. A notification
+is encoded in the standard error format, sock_extended_err.
+
+The level and type fields in the control data are protocol family
+specific, IP_RECVERR or IPV6_RECVERR.
+
+Error origin is the new type SO_EE_ORIGIN_ZEROCOPY. The errno is zero,
+as explained before, to avoid blocking read and write system calls on
+the socket.
+
+The 32-bit notification range is encoded as [ee_info, ee_data]. This
+range is inclusive. Other fields in the struct must be treated as
+undefined, bar for ee_code, as discussed below.
+
+::
+
+ struct sock_extended_err *serr;
+ struct cmsghdr *cm;
+
+ cm = CMSG_FIRSTHDR(msg);
+ if (cm->cmsg_level != SOL_IP &&
+ cm->cmsg_type != IP_RECVERR)
+ error(1, 0, "cmsg");
+
+ serr = (void *) CMSG_DATA(cm);
+ if (serr->ee_errno != 0 ||
+ serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY)
+ error(1, 0, "serr");
+
+ printf("completed: %u..%u\n", serr->ee_info, serr->ee_data);
+
+
+Deferred copies
+~~~~~~~~~~~~~~~
+
+Passing flag MSG_ZEROCOPY is a hint to the kernel to apply copy
+avoidance, and a contract that the kernel will queue a completion
+notification. It is not a guarantee that the copy is elided.
+
+Copy avoidance is not always feasible. Devices that do not support
+scatter-gather I/O cannot send packets made up of kernel generated
+protocol headers plus zerocopy user data. A packet may need to be
+converted to having a private copy of data deep in the stack, say to
+compute a checksum.
+
+In all these cases, the kernel returns a completion notification when
+it releases its hold on the shared pages. The notification may arrive
+before the (copied) data is fully transmitted. A zerocopy completion
+notification is not a transmit completion notification, therefore.
+
+Deferred copies can be more expensive than a copy immediately in the
+system call, if the data is no longer warm in the cache. The process
+also incurs notification processing cost for no benefit. For this
+reason, the kernel signals if data was completed with a copy, by
+setting flag SO_EE_CODE_ZEROCOPY_COPIED in field ee_code on return.
+A process may use this signal to stop passing flag MSG_ZEROCOPY on
+subsequent requests on the same socket.
+
+Implementation
+==============
+
+Loopback
+--------
+
+Data sent to local sockets can be queued indefinitely if the receive
+process does not read its socket. Unbound notification latency is not
+acceptable. For this reason all packets generated with MSG_ZEROCOPY
+that are looped to a local socket will incur a deferred copy. This
+includes looping onto packet sockets (e.g., tcpdump) and tun devices.
+
+
+Testing
+=======
+
+More realistic example code can be found in the kernel source under
+tools/testing/selftests/net/msg_zerocopy.c.
+
+Be cognizant of the loopback constraint. The test can be run between
+a pair of hosts. But if run between a local pair of processes, for
+instance when run with msg_zerocopy.sh between a veth pair across
+namespaces, the test will not show any improvement. For testing, the
+loopback restriction can be temporarily avoided by making
+skb_orphan_frags_rx identical to skb_orphan_frags.
+
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply related
* Re: [PATCH 2/3] security: bpf: Add eBPF LSM hooks and security field to eBPF map
From: Mimi Zohar @ 2017-08-31 21:17 UTC (permalink / raw)
To: Chenbo Feng, linux-security-module
Cc: Jeffrey Vander Stoep, netdev, SELinux, Alexei Starovoitov,
lorenzo, Chenbo Feng
In-Reply-To: <20170831205635.80256-3-chenbofeng.kernel@gmail.com>
On Thu, 2017-08-31 at 13:56 -0700, Chenbo Feng wrote:
> From: Chenbo Feng <fengc@google.com>
>
> Introduce a pointer into struct bpf_map to hold the security information
> about the map. The actual security struct varies based on the security
> models implemented. Place the LSM hooks before each of the unrestricted
> eBPF operations, the map_update_elem and map_delete_elem operations are
> checked by security_map_modify. The map_lookup_elem and map_get_next_key
> operations are checked by securtiy_map_read.
>
> Signed-off-by: Chenbo Feng <fengc@google.com>
> ---
> include/linux/bpf.h | 3 +++
> kernel/bpf/syscall.c | 28 ++++++++++++++++++++++++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index b69e7a5869ff..ca3e6ff7091d 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -53,6 +53,9 @@ struct bpf_map {
> struct work_struct work;
> atomic_t usercnt;
> struct bpf_map *inner_map_meta;
> +#ifdef CONFIG_SECURITY
> + void *security;
> +#endif
> };
>
> /* function argument constraints */
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 045646da97cc..b15580bcf3b1 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -279,6 +279,10 @@ static int map_create(union bpf_attr *attr)
> if (err)
> return -EINVAL;
>
> + err = security_map_create();
> + if (err)
> + return -EACCES;
Any reason not to just return err?
Mimi
> +
> /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
> map = find_and_alloc_map(attr);
> if (IS_ERR(map))
> @@ -291,6 +295,10 @@ static int map_create(union bpf_attr *attr)
> if (err)
> goto free_map_nouncharge;
>
> + err = security_post_create(map);
> + if (err < 0)
> + goto free_map;
> +
> err = bpf_map_alloc_id(map);
> if (err)
> goto free_map;
> @@ -410,6 +418,10 @@ static int map_lookup_elem(union bpf_attr *attr)
> if (IS_ERR(map))
> return PTR_ERR(map);
>
> + err = security_map_read(map);
> + if (err)
> + return -EACCES;
> +
> key = memdup_user(ukey, map->key_size);
> if (IS_ERR(key)) {
> err = PTR_ERR(key);
> @@ -490,6 +502,10 @@ static int map_update_elem(union bpf_attr *attr)
> if (IS_ERR(map))
> return PTR_ERR(map);
>
> + err = security_map_modify(map);
> + if (err)
> + return -EACCES;
> +
> key = memdup_user(ukey, map->key_size);
> if (IS_ERR(key)) {
> err = PTR_ERR(key);
> @@ -573,6 +589,10 @@ static int map_delete_elem(union bpf_attr *attr)
> if (IS_ERR(map))
> return PTR_ERR(map);
>
> + err = security_map_modify(map);
> + if (err)
> + return -EACCES;
> +
> key = memdup_user(ukey, map->key_size);
> if (IS_ERR(key)) {
> err = PTR_ERR(key);
> @@ -616,6 +636,10 @@ static int map_get_next_key(union bpf_attr *attr)
> if (IS_ERR(map))
> return PTR_ERR(map);
>
> + err = security_map_read(map);
> + if (err)
> + return -EACCES;
> +
> if (ukey) {
> key = memdup_user(ukey, map->key_size);
> if (IS_ERR(key)) {
> @@ -935,6 +959,10 @@ static int bpf_prog_load(union bpf_attr *attr)
> if (CHECK_ATTR(BPF_PROG_LOAD))
> return -EINVAL;
>
> + err = security_prog_load();
> + if (err)
> + return -EACCES;
> +
> if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
> return -EINVAL;
>
^ permalink raw reply
* Re: [PATCH] ath9k: remove cast to void pointer
From: Joe Perches @ 2017-08-31 21:29 UTC (permalink / raw)
To: Himanshu Jha, kvalo; +Cc: ath9k-devel, linux-wireless, netdev, linux-kernel
In-Reply-To: <1504184863-9732-1-git-send-email-himanshujha199640@gmail.com>
On Thu, 2017-08-31 at 18:37 +0530, Himanshu Jha wrote:
> casting to void pointer from any pointer type and vice-versa is done
> implicitly and therefore casting is not needed in such a case.
You said you were going to remember to mention the tool
and script that did this.
^ permalink raw reply
* Re: [PATCH net-next 7/8] net: hns3: add vlan filter config of Ports
From: David Miller @ 2017-08-31 21:38 UTC (permalink / raw)
To: lipeng321; +Cc: netdev, linux-kernel, linuxarm, yisen.zhuang, salil.mehta
In-Reply-To: <1504186749-8926-8-git-send-email-lipeng321@huawei.com>
From: Lipeng <lipeng321@huawei.com>
Date: Thu, 31 Aug 2017 21:39:08 +0800
> Config the self_define vlan_type as TPID(0x8100) for vlan identification.
> When normal port initialize vlan configure, set default vlan id as 0.
>
> Signed-off-by: Mingguang Qu <qumingguang@huawei.com>
> Signed-off-by: Lipeng <lipeng321@huawei.com>
No, that's not what this patch is doing.
> @@ -3308,6 +3308,7 @@ static int hclge_add_mac_vlan_tbl(struct hclge_vport *vport,
> mc_desc[1].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
> hclge_cmd_reuse_desc(&mc_desc[2], false);
> mc_desc[2].flag &= cpu_to_le16(~HCLGE_CMD_FLAG_NEXT);
> +
> memcpy(mc_desc[0].data, req,
> sizeof(struct hclge_mac_vlan_tbl_entry));
> ret = hclge_cmd_send(&hdev->hw, mc_desc, 3);
All it does is add an empty line.
^ permalink raw reply
* Re: [PATCH net-next] net/ncsi: Define {add, kill}_vid callbacks for !CONFIG_NET_NCSI
From: Benjamin Herrenschmidt @ 2017-08-31 21:14 UTC (permalink / raw)
To: Vernon Mauery, Samuel Mendoza-Jonas
Cc: David S . Miller, netdev, linux-kernel, OpenBMC Maillist,
Gavin Shan
In-Reply-To: <20170831152414.GB69617@mauery>
On Thu, 2017-08-31 at 08:24 -0700, Vernon Mauery wrote:
> +int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
> > +{
> > + return -ENOTTY;
> > +}
> > +int ncsi_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
> > +{
> > + return -ENOTTY;
> > +}
>
> These should be static functions because they are defined in the header
> file or you will get multiple symbol definitions.
static inline even or you'll get warning about them being unused iirc.
Cheers,
Ben.
^ permalink raw reply
* Re: [patch net-next repost 0/8] mlxsw: Add IPv6 host dpipe table
From: David Miller @ 2017-08-31 21:43 UTC (permalink / raw)
To: jiri; +Cc: netdev, arkadis, idosch, mlxsw
In-Reply-To: <20170831155919.1366-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@resnulli.us>
Date: Thu, 31 Aug 2017 17:59:11 +0200
> This patchset adds IPv6 host dpipe table support. This will provide the
> ability to observe the hardware offloaded IPv6 neighbors.
Series applied, thanks.
I noticed while reviewing this we are pretty much split on how
to access neigh->primary_key.
Half the code goes "(type *) n->primary_key" and the other half
(mostly in ipv6) goes "(type *) &n->primary_key"
I know both forms are basically equivalent, but consistency
matters :-)
^ permalink raw reply
* Re: [PATCH net-next] bridge: add tracepoint in br_fdb_update
From: Jesper Dangaard Brouer @ 2017-08-31 21:50 UTC (permalink / raw)
To: David Miller; +Cc: brouer, roopa, netdev, nikolay, f.fainelli, andrew, bridge
In-Reply-To: <20170831.114325.2027598728601121750.davem@davemloft.net>
On Thu, 31 Aug 2017 11:43:25 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
> Date: Wed, 30 Aug 2017 22:18:13 -0700
>
> > From: Roopa Prabhu <roopa@cumulusnetworks.com>
> >
> > This extends bridge fdb table tracepoints to also cover
> > learned fdb entries in the br_fdb_update path. Note that
> > unlike other tracepoints I have moved this to when the fdb
> > is modified because this is in the datapath and can generate
> > a lot of noise in the trace output. br_fdb_update is also called
> > from added_by_user context in the NTF_USE case which is already
> > traced ..hence the !added_by_user check.
> >
> > Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> Applied.
>
> Let's use dev->name for now and if the tooling can eventually
> do transparent ifindex->name then we can consider redoing
> a bunch of networking tracepoints.
I agree! :-)
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* [PATCH v3 net-next 0/7] bpf: Add option to set mark and priority in cgroup sock programs
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
Add option to set mark and priority in addition to bound device for newly
created sockets. Also, allow the bpf programs to use the get_current_uid_gid
helper meaning socket marks, priority and device can be set based on the
uid/gid of the running process.
Sample programs are updated to demonstrate the new options.
v3
- no changes to Patches 1 and 2 which Alexei acked in previous versions
- dropped change related to recursive programs in a cgroup
- updated tests per dropped patch
v2
- added flag to control recursive behavior as requested by Alexei
- added comment to sock_filter_func_proto regarding use of
get_current_uid_gid helper
- updated test programs for recursive option
David Ahern (7):
bpf: Add mark and priority to sock options that can be set
bpf: Allow cgroup sock filters to use get_current_uid_gid helper
samples/bpf: Update sock test to allow setting mark and priority
samples/bpf: Add detach option to test_cgrp2_sock
samples/bpf: Add option to dump socket settings
samples/bpf: Update cgrp2 socket tests
samples/bpf: Update cgroup socket examples to use uid gid helper
include/uapi/linux/bpf.h | 2 +
net/core/filter.c | 42 ++++++-
samples/bpf/sock_flags_kern.c | 5 +
samples/bpf/test_cgrp2_sock.c | 255 ++++++++++++++++++++++++++++++++++++-----
samples/bpf/test_cgrp2_sock.sh | 162 ++++++++++++++++++++------
5 files changed, 401 insertions(+), 65 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH v3 net-next 1/7] bpf: Add mark and priority to sock options that can be set
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
In-Reply-To: <1504217150-16151-1-git-send-email-dsahern@gmail.com>
Add socket mark and priority to fields that can be set by
ebpf program when a socket is created.
Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
include/uapi/linux/bpf.h | 2 ++
net/core/filter.c | 26 ++++++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index d46cf326b95f..e9c89e20adff 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -758,6 +758,8 @@ struct bpf_sock {
__u32 family;
__u32 type;
__u32 protocol;
+ __u32 mark;
+ __u32 priority;
};
#define XDP_PACKET_HEADROOM 256
diff --git a/net/core/filter.c b/net/core/filter.c
index c6a37fe0285b..f51b9690adf3 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3455,6 +3455,10 @@ static bool sock_filter_is_valid_access(int off, int size,
switch (off) {
case offsetof(struct bpf_sock, bound_dev_if):
break;
+ case offsetof(struct bpf_sock, mark):
+ break;
+ case offsetof(struct bpf_sock, priority):
+ break;
default:
return false;
}
@@ -3958,6 +3962,28 @@ static u32 sock_filter_convert_ctx_access(enum bpf_access_type type,
offsetof(struct sock, sk_bound_dev_if));
break;
+ case offsetof(struct bpf_sock, mark):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_mark) != 4);
+
+ if (type == BPF_WRITE)
+ *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
+ offsetof(struct sock, sk_mark));
+ else
+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
+ offsetof(struct sock, sk_mark));
+ break;
+
+ case offsetof(struct bpf_sock, priority):
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_priority) != 4);
+
+ if (type == BPF_WRITE)
+ *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
+ offsetof(struct sock, sk_priority));
+ else
+ *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
+ offsetof(struct sock, sk_priority));
+ break;
+
case offsetof(struct bpf_sock, family):
BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_family) != 2);
--
2.1.4
^ permalink raw reply related
* [PATCH v3 net-next 2/7] bpf: Allow cgroup sock filters to use get_current_uid_gid helper
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
In-Reply-To: <1504217150-16151-1-git-send-email-dsahern@gmail.com>
Allow BPF programs run on sock create to use the get_current_uid_gid
helper. IPv4 and IPv6 sockets are created in a process context so
there is always a valid uid/gid
Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
net/core/filter.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/net/core/filter.c b/net/core/filter.c
index f51b9690adf3..9dad3e7e2e10 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3150,6 +3150,20 @@ bpf_base_func_proto(enum bpf_func_id func_id)
}
static const struct bpf_func_proto *
+sock_filter_func_proto(enum bpf_func_id func_id)
+{
+ switch (func_id) {
+ /* inet and inet6 sockets are created in a process
+ * context so there is always a valid uid/gid
+ */
+ case BPF_FUNC_get_current_uid_gid:
+ return &bpf_get_current_uid_gid_proto;
+ default:
+ return bpf_base_func_proto(func_id);
+ }
+}
+
+static const struct bpf_func_proto *
sk_filter_func_proto(enum bpf_func_id func_id)
{
switch (func_id) {
@@ -4233,7 +4247,7 @@ const struct bpf_verifier_ops lwt_xmit_prog_ops = {
};
const struct bpf_verifier_ops cg_sock_prog_ops = {
- .get_func_proto = bpf_base_func_proto,
+ .get_func_proto = sock_filter_func_proto,
.is_valid_access = sock_filter_is_valid_access,
.convert_ctx_access = sock_filter_convert_ctx_access,
};
--
2.1.4
^ permalink raw reply related
* [PATCH v3 net-next 4/7] samples/bpf: Add detach option to test_cgrp2_sock
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
In-Reply-To: <1504217150-16151-1-git-send-email-dsahern@gmail.com>
Add option to detach programs from a cgroup.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
samples/bpf/test_cgrp2_sock.c | 50 ++++++++++++++++++++++++++++++-------------
1 file changed, 35 insertions(+), 15 deletions(-)
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
index 681abbe6c85e..15396761c5cc 100644
--- a/samples/bpf/test_cgrp2_sock.c
+++ b/samples/bpf/test_cgrp2_sock.c
@@ -114,7 +114,12 @@ static int prog_load(__u32 idx, __u32 mark, __u32 prio)
static int usage(const char *argv0)
{
- printf("Usage: %s -b bind-to-dev -m mark -p prio cg-path\n", argv0);
+ printf("Usage:\n");
+ printf(" Attach a program\n");
+ printf(" %s -b bind-to-dev -m mark -p prio cg-path\n", argv0);
+ printf("\n");
+ printf(" Detach a program\n");
+ printf(" %s -d cg-path\n", argv0);
return EXIT_FAILURE;
}
@@ -123,10 +128,14 @@ int main(int argc, char **argv)
__u32 idx = 0, mark = 0, prio = 0;
const char *cgrp_path = NULL;
int cg_fd, prog_fd, ret;
+ int do_attach = 1;
int rc;
- while ((rc = getopt(argc, argv, "b:m:p:")) != -1) {
+ while ((rc = getopt(argc, argv, "db:m:p:")) != -1) {
switch (rc) {
+ case 'd':
+ do_attach = 0;
+ break;
case 'b':
idx = if_nametoindex(optarg);
if (!idx) {
@@ -157,7 +166,7 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
- if (!idx && !mark && !prio) {
+ if (do_attach && !idx && !mark && !prio) {
fprintf(stderr,
"One of device, mark or priority must be given\n");
return EXIT_FAILURE;
@@ -169,20 +178,31 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
- prog_fd = prog_load(idx, mark, prio);
- if (prog_fd < 0) {
- printf("Failed to load prog: '%s'\n", strerror(errno));
- printf("Output from kernel verifier:\n%s\n-------\n",
- bpf_log_buf);
- return EXIT_FAILURE;
- }
+ if (do_attach) {
+ prog_fd = prog_load(idx, mark, prio);
+ if (prog_fd < 0) {
+ printf("Failed to load prog: '%s'\n", strerror(errno));
+ printf("Output from kernel verifier:\n%s\n-------\n",
+ bpf_log_buf);
+ return EXIT_FAILURE;
+ }
- ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE, 0);
- if (ret < 0) {
- printf("Failed to attach prog to cgroup: '%s'\n",
- strerror(errno));
- return EXIT_FAILURE;
+ ret = bpf_prog_attach(prog_fd, cg_fd,
+ BPF_CGROUP_INET_SOCK_CREATE, 0);
+ if (ret < 0) {
+ printf("Failed to attach prog to cgroup: '%s'\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ } else {
+ ret = bpf_prog_detach(cg_fd, BPF_CGROUP_INET_SOCK_CREATE);
+ if (ret < 0) {
+ printf("Failed to detach prog from cgroup: '%s'\n",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
}
+ close(cg_fd);
return EXIT_SUCCESS;
}
--
2.1.4
^ permalink raw reply related
* [PATCH v3 net-next 3/7] samples/bpf: Update sock test to allow setting mark and priority
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
In-Reply-To: <1504217150-16151-1-git-send-email-dsahern@gmail.com>
Update sock test to set mark and priority on socket create.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
samples/bpf/test_cgrp2_sock.c | 134 ++++++++++++++++++++++++++++++++++++-----
samples/bpf/test_cgrp2_sock.sh | 2 +-
2 files changed, 119 insertions(+), 17 deletions(-)
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
index c3cfb23e23b5..681abbe6c85e 100644
--- a/samples/bpf/test_cgrp2_sock.c
+++ b/samples/bpf/test_cgrp2_sock.c
@@ -19,59 +19,161 @@
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
+#include <inttypes.h>
#include <linux/bpf.h>
#include "libbpf.h"
char bpf_log_buf[BPF_LOG_BUF_SIZE];
-static int prog_load(int idx)
+static int prog_load(__u32 idx, __u32 mark, __u32 prio)
{
- struct bpf_insn prog[] = {
+ /* save pointer to context */
+ struct bpf_insn prog_start[] = {
BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+ };
+ struct bpf_insn prog_end[] = {
+ BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
+ BPF_EXIT_INSN(),
+ };
+
+ /* set sk_bound_dev_if on socket */
+ struct bpf_insn prog_dev[] = {
BPF_MOV64_IMM(BPF_REG_3, idx),
BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)),
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)),
- BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
- BPF_EXIT_INSN(),
};
- size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
- return bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt,
+ /* set mark on socket */
+ struct bpf_insn prog_mark[] = {
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
+ BPF_MOV64_IMM(BPF_REG_3, mark),
+ BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, mark)),
+ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, mark)),
+ };
+
+ /* set priority on socket */
+ struct bpf_insn prog_prio[] = {
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
+ BPF_MOV64_IMM(BPF_REG_3, prio),
+ BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, priority)),
+ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, priority)),
+ };
+
+ struct bpf_insn *prog;
+ size_t insns_cnt;
+ void *p;
+ int ret;
+
+ insns_cnt = sizeof(prog_start) + sizeof(prog_end);
+ if (idx)
+ insns_cnt += sizeof(prog_dev);
+
+ if (mark)
+ insns_cnt += sizeof(prog_mark);
+
+ if (prio)
+ insns_cnt += sizeof(prog_prio);
+
+ p = prog = malloc(insns_cnt);
+ if (!prog) {
+ fprintf(stderr, "Failed to allocate memory for instructions\n");
+ return EXIT_FAILURE;
+ }
+
+ memcpy(p, prog_start, sizeof(prog_start));
+ p += sizeof(prog_start);
+
+ if (idx) {
+ memcpy(p, prog_dev, sizeof(prog_dev));
+ p += sizeof(prog_dev);
+ }
+
+ if (mark) {
+ memcpy(p, prog_mark, sizeof(prog_mark));
+ p += sizeof(prog_mark);
+ }
+
+ if (prio) {
+ memcpy(p, prog_prio, sizeof(prog_prio));
+ p += sizeof(prog_prio);
+ }
+
+ memcpy(p, prog_end, sizeof(prog_end));
+ p += sizeof(prog_end);
+
+ insns_cnt /= sizeof(struct bpf_insn);
+
+ ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt,
"GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
+
+ free(prog);
+
+ return ret;
}
static int usage(const char *argv0)
{
- printf("Usage: %s cg-path device-index\n", argv0);
+ printf("Usage: %s -b bind-to-dev -m mark -p prio cg-path\n", argv0);
return EXIT_FAILURE;
}
int main(int argc, char **argv)
{
+ __u32 idx = 0, mark = 0, prio = 0;
+ const char *cgrp_path = NULL;
int cg_fd, prog_fd, ret;
- unsigned int idx;
+ int rc;
+
+ while ((rc = getopt(argc, argv, "b:m:p:")) != -1) {
+ switch (rc) {
+ case 'b':
+ idx = if_nametoindex(optarg);
+ if (!idx) {
+ idx = strtoumax(optarg, NULL, 0);
+ if (!idx) {
+ printf("Invalid device name\n");
+ return EXIT_FAILURE;
+ }
+ }
+ break;
+ case 'm':
+ mark = strtoumax(optarg, NULL, 0);
+ break;
+ case 'p':
+ prio = strtoumax(optarg, NULL, 0);
+ break;
+ default:
+ return usage(argv[0]);
+ }
+ }
- if (argc < 2)
+ if (optind == argc)
return usage(argv[0]);
- idx = if_nametoindex(argv[2]);
- if (!idx) {
- printf("Invalid device name\n");
+ cgrp_path = argv[optind];
+ if (!cgrp_path) {
+ fprintf(stderr, "cgroup path not given\n");
return EXIT_FAILURE;
}
- cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
+ if (!idx && !mark && !prio) {
+ fprintf(stderr,
+ "One of device, mark or priority must be given\n");
+ return EXIT_FAILURE;
+ }
+
+ cg_fd = open(cgrp_path, O_DIRECTORY | O_RDONLY);
if (cg_fd < 0) {
printf("Failed to open cgroup path: '%s'\n", strerror(errno));
return EXIT_FAILURE;
}
- prog_fd = prog_load(idx);
- printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf);
-
+ prog_fd = prog_load(idx, mark, prio);
if (prog_fd < 0) {
printf("Failed to load prog: '%s'\n", strerror(errno));
+ printf("Output from kernel verifier:\n%s\n-------\n",
+ bpf_log_buf);
return EXIT_FAILURE;
}
diff --git a/samples/bpf/test_cgrp2_sock.sh b/samples/bpf/test_cgrp2_sock.sh
index 925fd467c7cc..1153c33e8964 100755
--- a/samples/bpf/test_cgrp2_sock.sh
+++ b/samples/bpf/test_cgrp2_sock.sh
@@ -20,7 +20,7 @@ function attach_bpf {
mkdir -p /tmp/cgroupv2
mount -t cgroup2 none /tmp/cgroupv2
mkdir -p /tmp/cgroupv2/foo
- test_cgrp2_sock /tmp/cgroupv2/foo foo
+ test_cgrp2_sock -b foo /tmp/cgroupv2/foo
echo $$ >> /tmp/cgroupv2/foo/cgroup.procs
}
--
2.1.4
^ permalink raw reply related
* [PATCH v3 net-next 5/7] samples/bpf: Add option to dump socket settings
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
In-Reply-To: <1504217150-16151-1-git-send-email-dsahern@gmail.com>
Add option to dump socket settings. Will be used in the next patch
to verify bpf programs are correctly setting mark, priority and
device based on the cgroup attachment for the program run.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
samples/bpf/test_cgrp2_sock.c | 75 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 73 insertions(+), 2 deletions(-)
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
index 15396761c5cc..5a688837720c 100644
--- a/samples/bpf/test_cgrp2_sock.c
+++ b/samples/bpf/test_cgrp2_sock.c
@@ -112,6 +112,70 @@ static int prog_load(__u32 idx, __u32 mark, __u32 prio)
return ret;
}
+static int get_bind_to_device(int sd, char *name, size_t len)
+{
+ socklen_t optlen = len;
+ int rc;
+
+ name[0] = '\0';
+ rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen);
+ if (rc < 0)
+ perror("setsockopt(SO_BINDTODEVICE)");
+
+ return rc;
+}
+
+static unsigned int get_somark(int sd)
+{
+ unsigned int mark = 0;
+ socklen_t optlen = sizeof(mark);
+ int rc;
+
+ rc = getsockopt(sd, SOL_SOCKET, SO_MARK, &mark, &optlen);
+ if (rc < 0)
+ perror("getsockopt(SO_MARK)");
+
+ return mark;
+}
+
+static unsigned int get_priority(int sd)
+{
+ unsigned int prio = 0;
+ socklen_t optlen = sizeof(prio);
+ int rc;
+
+ rc = getsockopt(sd, SOL_SOCKET, SO_PRIORITY, &prio, &optlen);
+ if (rc < 0)
+ perror("getsockopt(SO_PRIORITY)");
+
+ return prio;
+}
+
+static int show_sockopts(int family)
+{
+ unsigned int mark, prio;
+ char name[16];
+ int sd;
+
+ sd = socket(family, SOCK_DGRAM, 17);
+ if (sd < 0) {
+ perror("socket");
+ return 1;
+ }
+
+ if (get_bind_to_device(sd, name, sizeof(name)) < 0)
+ return 1;
+
+ mark = get_somark(sd);
+ prio = get_priority(sd);
+
+ close(sd);
+
+ printf("sd %d: dev %s, mark %u, priority %u\n", sd, name, mark, prio);
+
+ return 0;
+}
+
static int usage(const char *argv0)
{
printf("Usage:\n");
@@ -120,6 +184,9 @@ static int usage(const char *argv0)
printf("\n");
printf(" Detach a program\n");
printf(" %s -d cg-path\n", argv0);
+ printf("\n");
+ printf(" Show inherited socket settings (mark, priority, and device)\n");
+ printf(" %s [-6]\n", argv0);
return EXIT_FAILURE;
}
@@ -128,10 +195,11 @@ int main(int argc, char **argv)
__u32 idx = 0, mark = 0, prio = 0;
const char *cgrp_path = NULL;
int cg_fd, prog_fd, ret;
+ int family = PF_INET;
int do_attach = 1;
int rc;
- while ((rc = getopt(argc, argv, "db:m:p:")) != -1) {
+ while ((rc = getopt(argc, argv, "db:m:p:6")) != -1) {
switch (rc) {
case 'd':
do_attach = 0;
@@ -152,13 +220,16 @@ int main(int argc, char **argv)
case 'p':
prio = strtoumax(optarg, NULL, 0);
break;
+ case '6':
+ family = PF_INET6;
+ break;
default:
return usage(argv[0]);
}
}
if (optind == argc)
- return usage(argv[0]);
+ return show_sockopts(family);
cgrp_path = argv[optind];
if (!cgrp_path) {
--
2.1.4
^ permalink raw reply related
* [PATCH v3 net-next 6/7] samples/bpf: Update cgrp2 socket tests
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
In-Reply-To: <1504217150-16151-1-git-send-email-dsahern@gmail.com>
Update cgrp2 bpf sock tests to check that device, mark and priority
can all be set on a socket via bpf programs attached to a cgroup.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
samples/bpf/test_cgrp2_sock.sh | 162 +++++++++++++++++++++++++++++++----------
1 file changed, 124 insertions(+), 38 deletions(-)
diff --git a/samples/bpf/test_cgrp2_sock.sh b/samples/bpf/test_cgrp2_sock.sh
index 1153c33e8964..a81f38eef417 100755
--- a/samples/bpf/test_cgrp2_sock.sh
+++ b/samples/bpf/test_cgrp2_sock.sh
@@ -1,47 +1,133 @@
-#!/bin/bash
-
-function config_device {
- ip netns add at_ns0
- ip link add veth0 type veth peer name veth0b
- ip link set veth0b up
- ip link set veth0 netns at_ns0
- ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0
- ip netns exec at_ns0 ip addr add 2401:db00::1/64 dev veth0 nodad
- ip netns exec at_ns0 ip link set dev veth0 up
- ip link add foo type vrf table 1234
- ip link set foo up
- ip addr add 172.16.1.101/24 dev veth0b
- ip addr add 2401:db00::2/64 dev veth0b nodad
- ip link set veth0b master foo
+#!/bin/sh
+
+# Test various socket options that can be set by attaching programs to cgroups.
+
+CGRP_MNT="/tmp/cgroupv2-test_cgrp2_sock"
+
+################################################################################
+#
+print_result()
+{
+ local rc=$1
+ local status=" OK "
+
+ [ $rc -ne 0 ] && status="FAIL"
+
+ printf "%-50s [%4s]\n" "$2" "$status"
}
-function attach_bpf {
- rm -rf /tmp/cgroupv2
- mkdir -p /tmp/cgroupv2
- mount -t cgroup2 none /tmp/cgroupv2
- mkdir -p /tmp/cgroupv2/foo
- test_cgrp2_sock -b foo /tmp/cgroupv2/foo
- echo $$ >> /tmp/cgroupv2/foo/cgroup.procs
+check_sock()
+{
+ out=$(test_cgrp2_sock)
+ echo $out | grep -q "$1"
+ if [ $? -ne 0 ]; then
+ print_result 1 "IPv4: $2"
+ echo " expected: $1"
+ echo " have: $out"
+ rc=1
+ else
+ print_result 0 "IPv4: $2"
+ fi
}
-function cleanup {
- set +ex
- ip netns delete at_ns0
- ip link del veth0
- ip link del foo
- umount /tmp/cgroupv2
- rm -rf /tmp/cgroupv2
- set -ex
+check_sock6()
+{
+ out=$(test_cgrp2_sock -6)
+ echo $out | grep -q "$1"
+ if [ $? -ne 0 ]; then
+ print_result 1 "IPv6: $2"
+ echo " expected: $1"
+ echo " have: $out"
+ rc=1
+ else
+ print_result 0 "IPv6: $2"
+ fi
}
-function do_test {
- ping -c1 -w1 172.16.1.100
- ping6 -c1 -w1 2401:db00::1
+################################################################################
+#
+
+cleanup()
+{
+ echo $$ >> ${CGRP_MNT}/cgroup.procs
+ rmdir ${CGRP_MNT}/sockopts
}
+cleanup_and_exit()
+{
+ local rc=$1
+ local msg="$2"
+
+ [ -n "$msg" ] && echo "ERROR: $msg"
+
+ ip li del cgrp2_sock
+ umount ${CGRP_MNT}
+
+ exit $rc
+}
+
+
+################################################################################
+# main
+
+rc=0
+
+ip li add cgrp2_sock type dummy 2>/dev/null
+
+set -e
+mkdir -p ${CGRP_MNT}
+mount -t cgroup2 none ${CGRP_MNT}
+set +e
+
+
+# make sure we have a known start point
cleanup 2>/dev/null
-config_device
-attach_bpf
-do_test
-cleanup
-echo "*** PASS ***"
+
+mkdir -p ${CGRP_MNT}/sockopts
+[ $? -ne 0 ] && cleanup_and_exit 1 "Failed to create cgroup hierarchy"
+
+
+# set pid into cgroup
+echo $$ > ${CGRP_MNT}/sockopts/cgroup.procs
+
+# no bpf program attached, so socket should show no settings
+check_sock "dev , mark 0, priority 0" "No programs attached"
+check_sock6 "dev , mark 0, priority 0" "No programs attached"
+
+# verify device is set
+#
+test_cgrp2_sock -b cgrp2_sock ${CGRP_MNT}/sockopts
+if [ $? -ne 0 ]; then
+ cleanup_and_exit 1 "Failed to install program to set device"
+fi
+check_sock "dev cgrp2_sock, mark 0, priority 0" "Device set"
+check_sock6 "dev cgrp2_sock, mark 0, priority 0" "Device set"
+
+# verify mark is set
+#
+test_cgrp2_sock -m 666 ${CGRP_MNT}/sockopts
+if [ $? -ne 0 ]; then
+ cleanup_and_exit 1 "Failed to install program to set mark"
+fi
+check_sock "dev , mark 666, priority 0" "Mark set"
+check_sock6 "dev , mark 666, priority 0" "Mark set"
+
+# verify priority is set
+#
+test_cgrp2_sock -p 123 ${CGRP_MNT}/sockopts
+if [ $? -ne 0 ]; then
+ cleanup_and_exit 1 "Failed to install program to set priority"
+fi
+check_sock "dev , mark 0, priority 123" "Priority set"
+check_sock6 "dev , mark 0, priority 123" "Priority set"
+
+# all 3 at once
+#
+test_cgrp2_sock -b cgrp2_sock -m 666 -p 123 ${CGRP_MNT}/sockopts
+if [ $? -ne 0 ]; then
+ cleanup_and_exit 1 "Failed to install program to set device, mark and priority"
+fi
+check_sock "dev cgrp2_sock, mark 666, priority 123" "Priority set"
+check_sock6 "dev cgrp2_sock, mark 666, priority 123" "Priority set"
+
+cleanup_and_exit $rc
--
2.1.4
^ permalink raw reply related
* [PATCH v3 net-next 7/7] samples/bpf: Update cgroup socket examples to use uid gid helper
From: David Ahern @ 2017-08-31 22:05 UTC (permalink / raw)
To: netdev, daniel, ast; +Cc: David Ahern
In-Reply-To: <1504217150-16151-1-git-send-email-dsahern@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
samples/bpf/sock_flags_kern.c | 5 +++++
samples/bpf/test_cgrp2_sock.c | 12 +++++++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/samples/bpf/sock_flags_kern.c b/samples/bpf/sock_flags_kern.c
index 533dd11a6baa..05dcdf8a4baa 100644
--- a/samples/bpf/sock_flags_kern.c
+++ b/samples/bpf/sock_flags_kern.c
@@ -9,8 +9,13 @@ SEC("cgroup/sock1")
int bpf_prog1(struct bpf_sock *sk)
{
char fmt[] = "socket: family %d type %d protocol %d\n";
+ char fmt2[] = "socket: uid %u gid %u\n";
+ __u64 gid_uid = bpf_get_current_uid_gid();
+ __u32 uid = gid_uid & 0xffffffff;
+ __u32 gid = gid_uid >> 32;
bpf_trace_printk(fmt, sizeof(fmt), sk->family, sk->type, sk->protocol);
+ bpf_trace_printk(fmt2, sizeof(fmt2), uid, gid);
/* block PF_INET6, SOCK_RAW, IPPROTO_ICMPV6 sockets
* ie., make ping6 fail
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
index 5a688837720c..e79594dd629b 100644
--- a/samples/bpf/test_cgrp2_sock.c
+++ b/samples/bpf/test_cgrp2_sock.c
@@ -46,8 +46,18 @@ static int prog_load(__u32 idx, __u32 mark, __u32 prio)
/* set mark on socket */
struct bpf_insn prog_mark[] = {
- BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
+ /* get uid of process */
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_current_uid_gid),
+ BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff),
+
+ /* if uid is 0, use given mark, else use the uid as the mark */
+ BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
BPF_MOV64_IMM(BPF_REG_3, mark),
+
+ /* set the mark on the new socket */
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, mark)),
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, mark)),
};
--
2.1.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox