Skip to content

Commit 7303524

Browse files
liujian56borkmann
authored andcommitted
skmsg: Lose offset info in sk_psock_skb_ingress
If sockmap enable strparser, there are lose offset info in sk_psock_skb_ingress(). If the length determined by parse_msg function is not skb->len, the skb will be converted to sk_msg multiple times, and userspace app will get the data multiple times. Fix this by get the offset and length from strp_msg. And as Cong suggested, add one bit in skb->_sk_redir to distinguish enable or disable strparser. Fixes: 604326b ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: Liu Jian <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Cong Wang <[email protected]> Acked-by: John Fastabend <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 0133c20 commit 7303524

File tree

2 files changed

+49
-12
lines changed

2 files changed

+49
-12
lines changed

include/linux/skmsg.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,22 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock)
508508

509509
#if IS_ENABLED(CONFIG_NET_SOCK_MSG)
510510

511-
/* We only have one bit so far. */
512-
#define BPF_F_PTR_MASK ~(BPF_F_INGRESS)
511+
#define BPF_F_STRPARSER (1UL << 1)
512+
513+
/* We only have two bits so far. */
514+
#define BPF_F_PTR_MASK ~(BPF_F_INGRESS | BPF_F_STRPARSER)
515+
516+
static inline bool skb_bpf_strparser(const struct sk_buff *skb)
517+
{
518+
unsigned long sk_redir = skb->_sk_redir;
519+
520+
return sk_redir & BPF_F_STRPARSER;
521+
}
522+
523+
static inline void skb_bpf_set_strparser(struct sk_buff *skb)
524+
{
525+
skb->_sk_redir |= BPF_F_STRPARSER;
526+
}
513527

514528
static inline bool skb_bpf_ingress(const struct sk_buff *skb)
515529
{

net/core/skmsg.c

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk,
494494
}
495495

496496
static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
497+
u32 off, u32 len,
497498
struct sk_psock *psock,
498499
struct sock *sk,
499500
struct sk_msg *msg)
@@ -507,11 +508,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
507508
*/
508509
if (skb_linearize(skb))
509510
return -EAGAIN;
510-
num_sge = skb_to_sgvec(skb, msg->sg.data, 0, skb->len);
511+
num_sge = skb_to_sgvec(skb, msg->sg.data, off, len);
511512
if (unlikely(num_sge < 0))
512513
return num_sge;
513514

514-
copied = skb->len;
515+
copied = len;
515516
msg->sg.start = 0;
516517
msg->sg.size = copied;
517518
msg->sg.end = num_sge;
@@ -522,9 +523,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
522523
return copied;
523524
}
524525

525-
static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb);
526+
static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,
527+
u32 off, u32 len);
526528

527-
static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
529+
static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,
530+
u32 off, u32 len)
528531
{
529532
struct sock *sk = psock->sk;
530533
struct sk_msg *msg;
@@ -535,7 +538,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
535538
* correctly.
536539
*/
537540
if (unlikely(skb->sk == sk))
538-
return sk_psock_skb_ingress_self(psock, skb);
541+
return sk_psock_skb_ingress_self(psock, skb, off, len);
539542
msg = sk_psock_create_ingress_msg(sk, skb);
540543
if (!msg)
541544
return -EAGAIN;
@@ -547,7 +550,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
547550
* into user buffers.
548551
*/
549552
skb_set_owner_r(skb, sk);
550-
err = sk_psock_skb_ingress_enqueue(skb, psock, sk, msg);
553+
err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg);
551554
if (err < 0)
552555
kfree(msg);
553556
return err;
@@ -557,7 +560,8 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
557560
* skb. In this case we do not need to check memory limits or skb_set_owner_r
558561
* because the skb is already accounted for here.
559562
*/
560-
static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb)
563+
static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,
564+
u32 off, u32 len)
561565
{
562566
struct sk_msg *msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC);
563567
struct sock *sk = psock->sk;
@@ -567,7 +571,7 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb
567571
return -EAGAIN;
568572
sk_msg_init(msg);
569573
skb_set_owner_r(skb, sk);
570-
err = sk_psock_skb_ingress_enqueue(skb, psock, sk, msg);
574+
err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg);
571575
if (err < 0)
572576
kfree(msg);
573577
return err;
@@ -581,7 +585,7 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,
581585
return -EAGAIN;
582586
return skb_send_sock(psock->sk, skb, off, len);
583587
}
584-
return sk_psock_skb_ingress(psock, skb);
588+
return sk_psock_skb_ingress(psock, skb, off, len);
585589
}
586590

587591
static void sk_psock_skb_state(struct sk_psock *psock,
@@ -624,6 +628,12 @@ static void sk_psock_backlog(struct work_struct *work)
624628
while ((skb = skb_dequeue(&psock->ingress_skb))) {
625629
len = skb->len;
626630
off = 0;
631+
if (skb_bpf_strparser(skb)) {
632+
struct strp_msg *stm = strp_msg(skb);
633+
634+
off = stm->offset;
635+
len = stm->full_len;
636+
}
627637
start:
628638
ingress = skb_bpf_ingress(skb);
629639
skb_bpf_redirect_clear(skb);
@@ -863,6 +873,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb)
863873
* return code, but then didn't set a redirect interface.
864874
*/
865875
if (unlikely(!sk_other)) {
876+
skb_bpf_redirect_clear(skb);
866877
sock_drop(from->sk, skb);
867878
return -EIO;
868879
}
@@ -930,13 +941,15 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
930941
{
931942
struct sock *sk_other;
932943
int err = 0;
944+
u32 len, off;
933945

934946
switch (verdict) {
935947
case __SK_PASS:
936948
err = -EIO;
937949
sk_other = psock->sk;
938950
if (sock_flag(sk_other, SOCK_DEAD) ||
939951
!sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
952+
skb_bpf_redirect_clear(skb);
940953
goto out_free;
941954
}
942955

@@ -949,7 +962,15 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
949962
* retrying later from workqueue.
950963
*/
951964
if (skb_queue_empty(&psock->ingress_skb)) {
952-
err = sk_psock_skb_ingress_self(psock, skb);
965+
len = skb->len;
966+
off = 0;
967+
if (skb_bpf_strparser(skb)) {
968+
struct strp_msg *stm = strp_msg(skb);
969+
970+
off = stm->offset;
971+
len = stm->full_len;
972+
}
973+
err = sk_psock_skb_ingress_self(psock, skb, off, len);
953974
}
954975
if (err < 0) {
955976
spin_lock_bh(&psock->ingress_lock);
@@ -1015,6 +1036,8 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
10151036
skb_dst_drop(skb);
10161037
skb_bpf_redirect_clear(skb);
10171038
ret = bpf_prog_run_pin_on_cpu(prog, skb);
1039+
if (ret == SK_PASS)
1040+
skb_bpf_set_strparser(skb);
10181041
ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb));
10191042
skb->sk = NULL;
10201043
}

0 commit comments

Comments
 (0)