4646#include <linux/seccomp.h>
4747#include <linux/if_vlan.h>
4848#include <linux/bpf.h>
49+ #include <net/sch_generic.h>
4950
5051/**
5152 * sk_filter - run a packet through a socket filter
@@ -1463,13 +1464,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
14631464 }
14641465}
14651466
1466- static bool sk_filter_is_valid_access (int off , int size ,
1467- enum bpf_access_type type )
1467+ static bool __is_valid_access (int off , int size , enum bpf_access_type type )
14681468{
1469- /* only read is allowed */
1470- if (type != BPF_READ )
1471- return false;
1472-
14731469 /* check bounds */
14741470 if (off < 0 || off >= sizeof (struct __sk_buff ))
14751471 return false;
@@ -1485,8 +1481,42 @@ static bool sk_filter_is_valid_access(int off, int size,
14851481 return true;
14861482}
14871483
1488- static u32 sk_filter_convert_ctx_access (int dst_reg , int src_reg , int ctx_off ,
1489- struct bpf_insn * insn_buf )
1484+ static bool sk_filter_is_valid_access (int off , int size ,
1485+ enum bpf_access_type type )
1486+ {
1487+ if (type == BPF_WRITE ) {
1488+ switch (off ) {
1489+ case offsetof(struct __sk_buff , cb [0 ]) ...
1490+ offsetof(struct __sk_buff , cb [4 ]):
1491+ break ;
1492+ default :
1493+ return false;
1494+ }
1495+ }
1496+
1497+ return __is_valid_access (off , size , type );
1498+ }
1499+
1500+ static bool tc_cls_act_is_valid_access (int off , int size ,
1501+ enum bpf_access_type type )
1502+ {
1503+ if (type == BPF_WRITE ) {
1504+ switch (off ) {
1505+ case offsetof(struct __sk_buff , mark ):
1506+ case offsetof(struct __sk_buff , tc_index ):
1507+ case offsetof(struct __sk_buff , cb [0 ]) ...
1508+ offsetof(struct __sk_buff , cb [4 ]):
1509+ break ;
1510+ default :
1511+ return false;
1512+ }
1513+ }
1514+ return __is_valid_access (off , size , type );
1515+ }
1516+
1517+ static u32 bpf_net_convert_ctx_access (enum bpf_access_type type , int dst_reg ,
1518+ int src_reg , int ctx_off ,
1519+ struct bpf_insn * insn_buf )
14901520{
14911521 struct bpf_insn * insn = insn_buf ;
14921522
@@ -1538,7 +1568,15 @@ static u32 sk_filter_convert_ctx_access(int dst_reg, int src_reg, int ctx_off,
15381568 break ;
15391569
15401570 case offsetof(struct __sk_buff , mark ):
1541- return convert_skb_access (SKF_AD_MARK , dst_reg , src_reg , insn );
1571+ BUILD_BUG_ON (FIELD_SIZEOF (struct sk_buff , mark ) != 4 );
1572+
1573+ if (type == BPF_WRITE )
1574+ * insn ++ = BPF_STX_MEM (BPF_W , dst_reg , src_reg ,
1575+ offsetof(struct sk_buff , mark ));
1576+ else
1577+ * insn ++ = BPF_LDX_MEM (BPF_W , dst_reg , src_reg ,
1578+ offsetof(struct sk_buff , mark ));
1579+ break ;
15421580
15431581 case offsetof(struct __sk_buff , pkt_type ):
15441582 return convert_skb_access (SKF_AD_PKTTYPE , dst_reg , src_reg , insn );
@@ -1553,6 +1591,38 @@ static u32 sk_filter_convert_ctx_access(int dst_reg, int src_reg, int ctx_off,
15531591 case offsetof(struct __sk_buff , vlan_tci ):
15541592 return convert_skb_access (SKF_AD_VLAN_TAG ,
15551593 dst_reg , src_reg , insn );
1594+
1595+ case offsetof(struct __sk_buff , cb [0 ]) ...
1596+ offsetof(struct __sk_buff , cb [4 ]):
1597+ BUILD_BUG_ON (FIELD_SIZEOF (struct qdisc_skb_cb , data ) < 20 );
1598+
1599+ ctx_off -= offsetof(struct __sk_buff , cb [0 ]);
1600+ ctx_off += offsetof(struct sk_buff , cb );
1601+ ctx_off += offsetof(struct qdisc_skb_cb , data );
1602+ if (type == BPF_WRITE )
1603+ * insn ++ = BPF_STX_MEM (BPF_W , dst_reg , src_reg , ctx_off );
1604+ else
1605+ * insn ++ = BPF_LDX_MEM (BPF_W , dst_reg , src_reg , ctx_off );
1606+ break ;
1607+
1608+ case offsetof(struct __sk_buff , tc_index ):
1609+ #ifdef CONFIG_NET_SCHED
1610+ BUILD_BUG_ON (FIELD_SIZEOF (struct sk_buff , tc_index ) != 2 );
1611+
1612+ if (type == BPF_WRITE )
1613+ * insn ++ = BPF_STX_MEM (BPF_H , dst_reg , src_reg ,
1614+ offsetof(struct sk_buff , tc_index ));
1615+ else
1616+ * insn ++ = BPF_LDX_MEM (BPF_H , dst_reg , src_reg ,
1617+ offsetof(struct sk_buff , tc_index ));
1618+ break ;
1619+ #else
1620+ if (type == BPF_WRITE )
1621+ * insn ++ = BPF_MOV64_REG (dst_reg , dst_reg );
1622+ else
1623+ * insn ++ = BPF_MOV64_IMM (dst_reg , 0 );
1624+ break ;
1625+ #endif
15561626 }
15571627
15581628 return insn - insn_buf ;
@@ -1561,13 +1631,13 @@ static u32 sk_filter_convert_ctx_access(int dst_reg, int src_reg, int ctx_off,
15611631static const struct bpf_verifier_ops sk_filter_ops = {
15621632 .get_func_proto = sk_filter_func_proto ,
15631633 .is_valid_access = sk_filter_is_valid_access ,
1564- .convert_ctx_access = sk_filter_convert_ctx_access ,
1634+ .convert_ctx_access = bpf_net_convert_ctx_access ,
15651635};
15661636
15671637static const struct bpf_verifier_ops tc_cls_act_ops = {
15681638 .get_func_proto = tc_cls_act_func_proto ,
1569- .is_valid_access = sk_filter_is_valid_access ,
1570- .convert_ctx_access = sk_filter_convert_ctx_access ,
1639+ .is_valid_access = tc_cls_act_is_valid_access ,
1640+ .convert_ctx_access = bpf_net_convert_ctx_access ,
15711641};
15721642
15731643static struct bpf_prog_type_list sk_filter_type __read_mostly = {
0 commit comments