diff options
| author | Willem de Bruijn <willemb@google.com> | 2016-07-12 18:18:56 -0400 |
|---|---|---|
| committer | Ben Hutchings <ben@decadent.org.uk> | 2017-02-23 03:51:05 +0000 |
| commit | d0e04e049a62ad9e7371bbd6897f17e56900c48f (patch) | |
| tree | 6599d375db99f6353a8223f3eb4bed893aab287f /include | |
| parent | 55ea1559fb24cb9cf5f81d28d6a760c8fdf62d1c (diff) | |
| download | linux-d0e04e049a62ad9e7371bbd6897f17e56900c48f.tar.gz linux-d0e04e049a62ad9e7371bbd6897f17e56900c48f.tar.bz2 linux-d0e04e049a62ad9e7371bbd6897f17e56900c48f.zip | |
rose: limit sk_filter trim to payload
commit f4979fcea7fd36d8e2f556abef86f80e0d5af1ba upstream.
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/filter.h | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/include/linux/filter.h b/include/linux/filter.h index 8eeb205f298b..f4805e15b29b 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -150,7 +150,11 @@ static inline unsigned int sk_filter_len(const struct sk_filter *fp) return fp->len * sizeof(struct sock_filter) + sizeof(*fp); } -extern 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); +} extern unsigned int sk_run_filter(const struct sk_buff *skb, const struct sock_filter *filter); extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk); |
