Code Review
/
kvmfornfv.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
Upgrade to 4.4.50-rt62
[kvmfornfv.git]
/
kernel
/
net
/
core
/
filter.c
diff --git
a/kernel/net/core/filter.c
b/kernel/net/core/filter.c
index
37157c4
..
e943554
100644
(file)
--- a/
kernel/net/core/filter.c
+++ b/
kernel/net/core/filter.c
@@
-52,9
+52,10
@@
#include <net/dst.h>
/**
#include <net/dst.h>
/**
- * sk_filter - run a packet through a socket filter
+ * sk_filter
_trim_cap
- run a packet through a socket filter
* @sk: sock associated with &sk_buff
* @skb: buffer to filter
* @sk: sock associated with &sk_buff
* @skb: buffer to filter
+ * @cap: limit on how short the eBPF program may trim the packet
*
* Run the eBPF program and then cut skb->data to correct size returned by
* the program. If pkt_len is 0 we toss packet. If skb->len is smaller
*
* Run the eBPF program and then cut skb->data to correct size returned by
* the program. If pkt_len is 0 we toss packet. If skb->len is smaller
@@
-63,7
+64,7
@@
* be accepted or -EPERM if the packet should be tossed.
*
*/
* be accepted or -EPERM if the packet should be tossed.
*
*/
-int sk_filter
(struct sock *sk, struct sk_buff *skb
)
+int sk_filter
_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap
)
{
int err;
struct sk_filter *filter;
{
int err;
struct sk_filter *filter;
@@
-84,14
+85,13
@@
int sk_filter(struct sock *sk, struct sk_buff *skb)
filter = rcu_dereference(sk->sk_filter);
if (filter) {
unsigned int pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
filter = rcu_dereference(sk->sk_filter);
if (filter) {
unsigned int pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
-
- err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
+ err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM;
}
rcu_read_unlock();
return err;
}
}
rcu_read_unlock();
return err;
}
-EXPORT_SYMBOL(sk_filter);
+EXPORT_SYMBOL(sk_filter
_trim_cap
);
static u64 __skb_get_pay_offset(u64 ctx, u64 a, u64 x, u64 r4, u64 r5)
{
static u64 __skb_get_pay_offset(u64 ctx, u64 a, u64 x, u64 r4, u64 r5)
{
@@
-1139,7
+1139,8
@@
void bpf_prog_destroy(struct bpf_prog *fp)
}
EXPORT_SYMBOL_GPL(bpf_prog_destroy);
}
EXPORT_SYMBOL_GPL(bpf_prog_destroy);
-static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk)
+static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk,
+ bool locked)
{
struct sk_filter *fp, *old_fp;
{
struct sk_filter *fp, *old_fp;
@@
-1155,10
+1156,8
@@
static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk)
return -ENOMEM;
}
return -ENOMEM;
}
- old_fp = rcu_dereference_protected(sk->sk_filter,
- sock_owned_by_user(sk));
+ old_fp = rcu_dereference_protected(sk->sk_filter, locked);
rcu_assign_pointer(sk->sk_filter, fp);
rcu_assign_pointer(sk->sk_filter, fp);
-
if (old_fp)
sk_filter_uncharge(sk, old_fp);
if (old_fp)
sk_filter_uncharge(sk, old_fp);
@@
-1175,7
+1174,8
@@
static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk)
* occurs or there is insufficient memory for the filter a negative
* errno code is returned. On success the return is zero.
*/
* occurs or there is insufficient memory for the filter a negative
* errno code is returned. On success the return is zero.
*/
-int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
+int __sk_attach_filter(struct sock_fprog *fprog, struct sock *sk,
+ bool locked)
{
unsigned int fsize = bpf_classic_proglen(fprog);
unsigned int bpf_fsize = bpf_prog_size(fprog->len);
{
unsigned int fsize = bpf_classic_proglen(fprog);
unsigned int bpf_fsize = bpf_prog_size(fprog->len);
@@
-1213,7
+1213,7
@@
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
if (IS_ERR(prog))
return PTR_ERR(prog);
if (IS_ERR(prog))
return PTR_ERR(prog);
- err = __sk_attach_prog(prog, sk);
+ err = __sk_attach_prog(prog, sk
, locked
);
if (err < 0) {
__bpf_prog_release(prog);
return err;
if (err < 0) {
__bpf_prog_release(prog);
return err;
@@
-1221,7
+1221,12
@@
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
return 0;
}
return 0;
}
-EXPORT_SYMBOL_GPL(sk_attach_filter);
+EXPORT_SYMBOL_GPL(__sk_attach_filter);
+
+int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
+{
+ return __sk_attach_filter(fprog, sk, sock_owned_by_user(sk));
+}
int sk_attach_bpf(u32 ufd, struct sock *sk)
{
int sk_attach_bpf(u32 ufd, struct sock *sk)
{
@@
-1240,7
+1245,7
@@
int sk_attach_bpf(u32 ufd, struct sock *sk)
return -EINVAL;
}
return -EINVAL;
}
- err = __sk_attach_prog(prog, sk);
+ err = __sk_attach_prog(prog, sk
, sock_owned_by_user(sk)
);
if (err < 0) {
bpf_prog_put(prog);
return err;
if (err < 0) {
bpf_prog_put(prog);
return err;
@@
-1270,9
+1275,7
@@
static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags)
*/
if (unlikely((u32) offset > 0xffff || len > sizeof(buf)))
return -EFAULT;
*/
if (unlikely((u32) offset > 0xffff || len > sizeof(buf)))
return -EFAULT;
-
- if (unlikely(skb_cloned(skb) &&
- !skb_clone_writable(skb, offset + len)))
+ if (unlikely(skb_try_make_writable(skb, offset + len)))
return -EFAULT;
ptr = skb_header_pointer(skb, offset, len, buf);
return -EFAULT;
ptr = skb_header_pointer(skb, offset, len, buf);
@@
-1316,8
+1319,7
@@
static u64 bpf_l3_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
if (unlikely((u32) offset > 0xffff))
return -EFAULT;
if (unlikely((u32) offset > 0xffff))
return -EFAULT;
- if (unlikely(skb_cloned(skb) &&
- !skb_clone_writable(skb, offset + sizeof(sum))))
+ if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum))))
return -EFAULT;
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
return -EFAULT;
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
@@
-1362,9
+1364,7
@@
static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
if (unlikely((u32) offset > 0xffff))
return -EFAULT;
if (unlikely((u32) offset > 0xffff))
return -EFAULT;
-
- if (unlikely(skb_cloned(skb) &&
- !skb_clone_writable(skb, offset + sizeof(sum))))
+ if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum))))
return -EFAULT;
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
return -EFAULT;
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
@@
-1549,6
+1549,13
@@
bool bpf_helper_changes_skb_data(void *func)
return true;
if (func == bpf_skb_vlan_pop)
return true;
return true;
if (func == bpf_skb_vlan_pop)
return true;
+ if (func == bpf_skb_store_bytes)
+ return true;
+ if (func == bpf_l3_csum_replace)
+ return true;
+ if (func == bpf_l4_csum_replace)
+ return true;
+
return false;
}
return false;
}
@@
-1913,7
+1920,7
@@
static int __init register_sk_filter_ops(void)
}
late_initcall(register_sk_filter_ops);
}
late_initcall(register_sk_filter_ops);
-int
sk_detach_filter(struct sock *sk
)
+int
__sk_detach_filter(struct sock *sk, bool locked
)
{
int ret = -ENOENT;
struct sk_filter *filter;
{
int ret = -ENOENT;
struct sk_filter *filter;
@@
-1921,8
+1928,7
@@
int sk_detach_filter(struct sock *sk)
if (sock_flag(sk, SOCK_FILTER_LOCKED))
return -EPERM;
if (sock_flag(sk, SOCK_FILTER_LOCKED))
return -EPERM;
- filter = rcu_dereference_protected(sk->sk_filter,
- sock_owned_by_user(sk));
+ filter = rcu_dereference_protected(sk->sk_filter, locked);
if (filter) {
RCU_INIT_POINTER(sk->sk_filter, NULL);
sk_filter_uncharge(sk, filter);
if (filter) {
RCU_INIT_POINTER(sk->sk_filter, NULL);
sk_filter_uncharge(sk, filter);
@@
-1931,7
+1937,12
@@
int sk_detach_filter(struct sock *sk)
return ret;
}
return ret;
}
-EXPORT_SYMBOL_GPL(sk_detach_filter);
+EXPORT_SYMBOL_GPL(__sk_detach_filter);
+
+int sk_detach_filter(struct sock *sk)
+{
+ return __sk_detach_filter(sk, sock_owned_by_user(sk));
+}
int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
unsigned int len)
int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
unsigned int len)