|
@@ -1762,6 +1762,37 @@ static const struct bpf_func_proto bpf_skb_pull_data_proto = {
|
|
|
.arg2_type = ARG_ANYTHING,
|
|
|
};
|
|
|
|
|
|
+static inline int sk_skb_try_make_writable(struct sk_buff *skb,
|
|
|
+ unsigned int write_len)
|
|
|
+{
|
|
|
+ int err = __bpf_try_make_writable(skb, write_len);
|
|
|
+
|
|
|
+ bpf_compute_data_end_sk_skb(skb);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+BPF_CALL_2(sk_skb_pull_data, struct sk_buff *, skb, u32, len)
|
|
|
+{
|
|
|
+ /* Idea is the following: should the needed direct read/write
|
|
|
+ * test fail during runtime, we can pull in more data and redo
|
|
|
+ * again, since implicitly, we invalidate previous checks here.
|
|
|
+ *
|
|
|
+ * Or, since we know how much we need to make read/writeable,
|
|
|
+ * this can be done once at the program beginning for direct
|
|
|
+ * access case. By this we overcome limitations of only current
|
|
|
+ * headroom being accessible.
|
|
|
+ */
|
|
|
+ return sk_skb_try_make_writable(skb, len ? : skb_headlen(skb));
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto sk_skb_pull_data_proto = {
|
|
|
+ .func = sk_skb_pull_data,
|
|
|
+ .gpl_only = false,
|
|
|
+ .ret_type = RET_INTEGER,
|
|
|
+ .arg1_type = ARG_PTR_TO_CTX,
|
|
|
+ .arg2_type = ARG_ANYTHING,
|
|
|
+};
|
|
|
+
|
|
|
BPF_CALL_5(bpf_l3_csum_replace, struct sk_buff *, skb, u32, offset,
|
|
|
u64, from, u64, to, u64, flags)
|
|
|
{
|
|
@@ -2864,8 +2895,8 @@ static int bpf_skb_trim_rcsum(struct sk_buff *skb, unsigned int new_len)
|
|
|
return __skb_trim_rcsum(skb, new_len);
|
|
|
}
|
|
|
|
|
|
-BPF_CALL_3(bpf_skb_change_tail, struct sk_buff *, skb, u32, new_len,
|
|
|
- u64, flags)
|
|
|
+static inline int __bpf_skb_change_tail(struct sk_buff *skb, u32 new_len,
|
|
|
+ u64 flags)
|
|
|
{
|
|
|
u32 max_len = __bpf_skb_max_len(skb);
|
|
|
u32 min_len = __bpf_skb_min_len(skb);
|
|
@@ -2901,6 +2932,13 @@ BPF_CALL_3(bpf_skb_change_tail, struct sk_buff *, skb, u32, new_len,
|
|
|
if (!ret && skb_is_gso(skb))
|
|
|
skb_gso_reset(skb);
|
|
|
}
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+BPF_CALL_3(bpf_skb_change_tail, struct sk_buff *, skb, u32, new_len,
|
|
|
+ u64, flags)
|
|
|
+{
|
|
|
+ int ret = __bpf_skb_change_tail(skb, new_len, flags);
|
|
|
|
|
|
bpf_compute_data_pointers(skb);
|
|
|
return ret;
|
|
@@ -2915,8 +2953,26 @@ static const struct bpf_func_proto bpf_skb_change_tail_proto = {
|
|
|
.arg3_type = ARG_ANYTHING,
|
|
|
};
|
|
|
|
|
|
-BPF_CALL_3(bpf_skb_change_head, struct sk_buff *, skb, u32, head_room,
|
|
|
+BPF_CALL_3(sk_skb_change_tail, struct sk_buff *, skb, u32, new_len,
|
|
|
u64, flags)
|
|
|
+{
|
|
|
+ int ret = __bpf_skb_change_tail(skb, new_len, flags);
|
|
|
+
|
|
|
+ bpf_compute_data_end_sk_skb(skb);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto sk_skb_change_tail_proto = {
|
|
|
+ .func = sk_skb_change_tail,
|
|
|
+ .gpl_only = false,
|
|
|
+ .ret_type = RET_INTEGER,
|
|
|
+ .arg1_type = ARG_PTR_TO_CTX,
|
|
|
+ .arg2_type = ARG_ANYTHING,
|
|
|
+ .arg3_type = ARG_ANYTHING,
|
|
|
+};
|
|
|
+
|
|
|
+static inline int __bpf_skb_change_head(struct sk_buff *skb, u32 head_room,
|
|
|
+ u64 flags)
|
|
|
{
|
|
|
u32 max_len = __bpf_skb_max_len(skb);
|
|
|
u32 new_len = skb->len + head_room;
|
|
@@ -2942,8 +2998,16 @@ BPF_CALL_3(bpf_skb_change_head, struct sk_buff *, skb, u32, head_room,
|
|
|
skb_reset_mac_header(skb);
|
|
|
}
|
|
|
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+BPF_CALL_3(bpf_skb_change_head, struct sk_buff *, skb, u32, head_room,
|
|
|
+ u64, flags)
|
|
|
+{
|
|
|
+ int ret = __bpf_skb_change_head(skb, head_room, flags);
|
|
|
+
|
|
|
bpf_compute_data_pointers(skb);
|
|
|
- return 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static const struct bpf_func_proto bpf_skb_change_head_proto = {
|
|
@@ -2955,6 +3019,23 @@ static const struct bpf_func_proto bpf_skb_change_head_proto = {
|
|
|
.arg3_type = ARG_ANYTHING,
|
|
|
};
|
|
|
|
|
|
+BPF_CALL_3(sk_skb_change_head, struct sk_buff *, skb, u32, head_room,
|
|
|
+ u64, flags)
|
|
|
+{
|
|
|
+ int ret = __bpf_skb_change_head(skb, head_room, flags);
|
|
|
+
|
|
|
+ bpf_compute_data_end_sk_skb(skb);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto sk_skb_change_head_proto = {
|
|
|
+ .func = sk_skb_change_head,
|
|
|
+ .gpl_only = false,
|
|
|
+ .ret_type = RET_INTEGER,
|
|
|
+ .arg1_type = ARG_PTR_TO_CTX,
|
|
|
+ .arg2_type = ARG_ANYTHING,
|
|
|
+ .arg3_type = ARG_ANYTHING,
|
|
|
+};
|
|
|
static unsigned long xdp_get_metalen(const struct xdp_buff *xdp)
|
|
|
{
|
|
|
return xdp_data_meta_unsupported(xdp) ? 0 :
|
|
@@ -4618,9 +4699,12 @@ bool bpf_helper_changes_pkt_data(void *func)
|
|
|
func == bpf_skb_store_bytes ||
|
|
|
func == bpf_skb_change_proto ||
|
|
|
func == bpf_skb_change_head ||
|
|
|
+ func == sk_skb_change_head ||
|
|
|
func == bpf_skb_change_tail ||
|
|
|
+ func == sk_skb_change_tail ||
|
|
|
func == bpf_skb_adjust_room ||
|
|
|
func == bpf_skb_pull_data ||
|
|
|
+ func == sk_skb_pull_data ||
|
|
|
func == bpf_clone_redirect ||
|
|
|
func == bpf_l3_csum_replace ||
|
|
|
func == bpf_l4_csum_replace ||
|
|
@@ -4872,11 +4956,11 @@ sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
case BPF_FUNC_skb_load_bytes:
|
|
|
return &bpf_skb_load_bytes_proto;
|
|
|
case BPF_FUNC_skb_pull_data:
|
|
|
- return &bpf_skb_pull_data_proto;
|
|
|
+ return &sk_skb_pull_data_proto;
|
|
|
case BPF_FUNC_skb_change_tail:
|
|
|
- return &bpf_skb_change_tail_proto;
|
|
|
+ return &sk_skb_change_tail_proto;
|
|
|
case BPF_FUNC_skb_change_head:
|
|
|
- return &bpf_skb_change_head_proto;
|
|
|
+ return &sk_skb_change_head_proto;
|
|
|
case BPF_FUNC_get_socket_cookie:
|
|
|
return &bpf_get_socket_cookie_proto;
|
|
|
case BPF_FUNC_get_socket_uid:
|