* [PATCH net 1/2] rose: limit sk_filter trim to payload
@ 2016-07-12 22:30 Willem de Bruijn
0 siblings, 0 replies; 3+ messages in thread
From: Willem de Bruijn @ 2016-07-12 22:30 UTC (permalink / raw)
To: netdev
Cc: alexei.starovoitov, daniel, davem, hannes, eric.dumazet,
Willem de Bruijn
From: Willem de Bruijn <willemb@google.com>
Sockets can have a filter program attached that drops or trims
incoming packets based on the filter program return value.
Rose requires data packets to have at least ROSE_MIN_LEN bytes. It
verifies this on arrival in rose_route_frame and unconditionally pulls
the bytes in rose_recvmsg. The filter can trim packets to below this
value in-between, causing pull to fail, leaving the partial header at
the time of skb_copy_datagram_msg.
Place a lower bound on the size to which sk_filter may trim packets
by introducing sk_filter_trim_cap and call this for rose packets.
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
No Fixes tag, because this codepath goes back to the start of the
git repo history.
---
include/linux/filter.h | 6 +++++-
net/core/filter.c | 10 +++++-----
net/rose/rose_in.c | 3 ++-
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 6fc31ef..8f74f3d 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -467,7 +467,11 @@ static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
}
#endif /* CONFIG_DEBUG_SET_MODULE_RONX */
-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);
+static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
+{
+ return sk_filter_trim_cap(sk, skb, 1);
+}
struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err);
void bpf_prog_free(struct bpf_prog *fp);
diff --git a/net/core/filter.c b/net/core/filter.c
index c4b330c..e759d90 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -53,9 +53,10 @@
#include <net/sock_reuseport.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
+ * @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
@@ -64,7 +65,7 @@
* 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;
@@ -85,14 +86,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);
-
- 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;
}
-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)
{
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 79c4abc..0a63947 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -164,7 +164,8 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
rose_frames_acked(sk, nr);
if (ns == rose->vr) {
rose_start_idletimer(sk);
- if (sock_queue_rcv_skb(sk, skb) == 0) {
+ if (sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN) == 0 &&
+ __sock_queue_rcv_skb(sk, skb) == 0) {
rose->vr = (rose->vr + 1) % ROSE_MODULUS;
queued = 1;
} else {
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH net 0/2] limit sk_filter trim to payload
@ 2016-07-12 22:18 Willem de Bruijn
2016-07-12 22:18 ` [PATCH net 1/2] rose: " Willem de Bruijn
0 siblings, 1 reply; 3+ messages in thread
From: Willem de Bruijn @ 2016-07-12 22:18 UTC (permalink / raw)
To: netdev
Cc: alexei.starovoitov, daniel, davem, hannes, eric.dumazet,
Willem de Bruijn
From: Willem de Bruijn <willemb@google.com>
Sockets can apply a filter to incoming packets to drop or trim them.
Fix two codepaths that call skb_pull/__skb_pull after sk_filter
without checking for packet length.
Reading beyond skb->tail after trimming happens in more codepaths, but
safety of reading in the linear segment is based on minimum allocation
size (MAX_HEADER, GRO_MAX_HEAD, ..).
Willem de Bruijn (2):
rose: limit sk_filter trim to payload
dccp: limit sk_filter trim to payload
include/linux/filter.h | 6 +++++-
include/net/sock.h | 8 +++++++-
net/core/filter.c | 10 +++++-----
net/core/sock.c | 7 ++++---
net/dccp/ipv4.c | 2 +-
net/dccp/ipv6.c | 2 +-
net/rose/rose_in.c | 3 ++-
7 files changed, 25 insertions(+), 13 deletions(-)
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH net 1/2] rose: limit sk_filter trim to payload
2016-07-12 22:18 [PATCH net 0/2] " Willem de Bruijn
@ 2016-07-12 22:18 ` Willem de Bruijn
2016-07-12 22:49 ` Daniel Borkmann
0 siblings, 1 reply; 3+ messages in thread
From: Willem de Bruijn @ 2016-07-12 22:18 UTC (permalink / raw)
To: netdev
Cc: alexei.starovoitov, daniel, davem, hannes, eric.dumazet,
Willem de Bruijn
From: Willem de Bruijn <willemb@google.com>
Sockets can have a filter program attached that drops or trims
incoming packets based on the filter program return value.
Rose requires data packets to have at least ROSE_MIN_LEN bytes. It
verifies this on arrival in rose_route_frame and unconditionally pulls
the bytes in rose_recvmsg. The filter can trim packets to below this
value in-between, causing pull to fail, leaving the partial header at
the time of skb_copy_datagram_msg.
Place a lower bound on the size to which sk_filter may trim packets
by introducing sk_filter_trim_cap and call this for rose packets.
Signed-off-by: Willem de Bruijn <willemb@google.com>
---
No Fixes tag, because this codepath goes back to the start of the
git repo history.
---
include/linux/filter.h | 6 +++++-
net/core/filter.c | 10 +++++-----
net/rose/rose_in.c | 3 ++-
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 6fc31ef..8f74f3d 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -467,7 +467,11 @@ static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
}
#endif /* CONFIG_DEBUG_SET_MODULE_RONX */
-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);
+static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
+{
+ return sk_filter_trim_cap(sk, skb, 1);
+}
struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err);
void bpf_prog_free(struct bpf_prog *fp);
diff --git a/net/core/filter.c b/net/core/filter.c
index c4b330c..e759d90 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -53,9 +53,10 @@
#include <net/sock_reuseport.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
+ * @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
@@ -64,7 +65,7 @@
* 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;
@@ -85,14 +86,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);
-
- 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;
}
-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)
{
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 79c4abc..0a63947 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -164,7 +164,8 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
rose_frames_acked(sk, nr);
if (ns == rose->vr) {
rose_start_idletimer(sk);
- if (sock_queue_rcv_skb(sk, skb) == 0) {
+ if (sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN) == 0 &&
+ __sock_queue_rcv_skb(sk, skb) == 0) {
rose->vr = (rose->vr + 1) % ROSE_MODULUS;
queued = 1;
} else {
--
2.8.0.rc3.226.g39d4020
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net 1/2] rose: limit sk_filter trim to payload
2016-07-12 22:18 ` [PATCH net 1/2] rose: " Willem de Bruijn
@ 2016-07-12 22:49 ` Daniel Borkmann
0 siblings, 0 replies; 3+ messages in thread
From: Daniel Borkmann @ 2016-07-12 22:49 UTC (permalink / raw)
To: Willem de Bruijn, netdev
Cc: alexei.starovoitov, davem, hannes, eric.dumazet, Willem de Bruijn
On 07/13/2016 12:18 AM, Willem de Bruijn wrote:
> From: Willem de Bruijn <willemb@google.com>
>
> Sockets can have a filter program attached that drops or trims
> incoming packets based on the filter program return value.
>
> Rose requires data packets to have at least ROSE_MIN_LEN bytes. It
> verifies this on arrival in rose_route_frame and unconditionally pulls
> the bytes in rose_recvmsg. The filter can trim packets to below this
> value in-between, causing pull to fail, leaving the partial header at
> the time of skb_copy_datagram_msg.
>
> Place a lower bound on the size to which sk_filter may trim packets
> by introducing sk_filter_trim_cap and call this for rose packets.
>
> Signed-off-by: Willem de Bruijn <willemb@google.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-07-12 22:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-12 22:30 [PATCH net 1/2] rose: limit sk_filter trim to payload Willem de Bruijn
-- strict thread matches above, loose matches on Subject: below --
2016-07-12 22:18 [PATCH net 0/2] " Willem de Bruijn
2016-07-12 22:18 ` [PATCH net 1/2] rose: " Willem de Bruijn
2016-07-12 22:49 ` Daniel Borkmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).