Skip to content

Commit 09207c9

Browse files
committed
Merge: net/other: phase-2 backports for RHEL-9.7
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6751 JIRA: https://issues.redhat.com/browse/RHEL-84598 Upstream Status: all mainline in net-next.git Tested: boot-tested only Conflicts: None Signed-off-by: Davide Caratti <dcaratti@redhat.com> Approved-by: Florian Westphal <fwestpha@redhat.com> Approved-by: Xin Long <lxin@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
2 parents e007270 + 2c54bdb commit 09207c9

File tree

3 files changed

+93
-9
lines changed

3 files changed

+93
-9
lines changed

include/linux/if_vlan.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -588,13 +588,16 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
588588
* vlan_get_protocol - get protocol EtherType.
589589
* @skb: skbuff to query
590590
* @type: first vlan protocol
591+
* @mac_offset: MAC offset
591592
* @depth: buffer to store length of eth and vlan tags in bytes
592593
*
593594
* Returns the EtherType of the packet, regardless of whether it is
594595
* vlan encapsulated (normal or hardware accelerated) or not.
595596
*/
596-
static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
597-
int *depth)
597+
static inline __be16 __vlan_get_protocol_offset(const struct sk_buff *skb,
598+
__be16 type,
599+
int mac_offset,
600+
int *depth)
598601
{
599602
unsigned int vlan_depth = skb->mac_len, parse_depth = VLAN_MAX_DEPTH;
600603

@@ -613,7 +616,8 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
613616
do {
614617
struct vlan_hdr vhdr, *vh;
615618

616-
vh = skb_header_pointer(skb, vlan_depth, sizeof(vhdr), &vhdr);
619+
vh = skb_header_pointer(skb, mac_offset + vlan_depth,
620+
sizeof(vhdr), &vhdr);
617621
if (unlikely(!vh || !--parse_depth))
618622
return 0;
619623

@@ -628,6 +632,12 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
628632
return type;
629633
}
630634

635+
static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
636+
int *depth)
637+
{
638+
return __vlan_get_protocol_offset(skb, type, 0, depth);
639+
}
640+
631641
/**
632642
* vlan_get_protocol - get protocol EtherType.
633643
* @skb: skbuff to query

net/packet/af_packet.c

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,47 @@ static void *packet_current_frame(struct packet_sock *po,
503503
return packet_lookup_frame(po, rb, rb->head, status);
504504
}
505505

506+
static u16 vlan_get_tci(const struct sk_buff *skb, struct net_device *dev)
507+
{
508+
struct vlan_hdr vhdr, *vh;
509+
unsigned int header_len;
510+
511+
if (!dev)
512+
return 0;
513+
514+
/* In the SOCK_DGRAM scenario, skb data starts at the network
515+
* protocol, which is after the VLAN headers. The outer VLAN
516+
* header is at the hard_header_len offset in non-variable
517+
* length link layer headers. If it's a VLAN device, the
518+
* min_header_len should be used to exclude the VLAN header
519+
* size.
520+
*/
521+
if (dev->min_header_len == dev->hard_header_len)
522+
header_len = dev->hard_header_len;
523+
else if (is_vlan_dev(dev))
524+
header_len = dev->min_header_len;
525+
else
526+
return 0;
527+
528+
vh = skb_header_pointer(skb, skb_mac_offset(skb) + header_len,
529+
sizeof(vhdr), &vhdr);
530+
if (unlikely(!vh))
531+
return 0;
532+
533+
return ntohs(vh->h_vlan_TCI);
534+
}
535+
536+
static __be16 vlan_get_protocol_dgram(const struct sk_buff *skb)
537+
{
538+
__be16 proto = skb->protocol;
539+
540+
if (unlikely(eth_type_vlan(proto)))
541+
proto = __vlan_get_protocol_offset(skb, proto,
542+
skb_mac_offset(skb), NULL);
543+
544+
return proto;
545+
}
546+
506547
static void prb_del_retire_blk_timer(struct tpacket_kbdq_core *pkc)
507548
{
508549
del_timer_sync(&pkc->retire_blk_timer);
@@ -972,10 +1013,16 @@ static void prb_clear_rxhash(struct tpacket_kbdq_core *pkc,
9721013
static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc,
9731014
struct tpacket3_hdr *ppd)
9741015
{
1016+
struct packet_sock *po = container_of(pkc, struct packet_sock, rx_ring.prb_bdqc);
1017+
9751018
if (skb_vlan_tag_present(pkc->skb)) {
9761019
ppd->hv1.tp_vlan_tci = skb_vlan_tag_get(pkc->skb);
9771020
ppd->hv1.tp_vlan_tpid = ntohs(pkc->skb->vlan_proto);
9781021
ppd->tp_status = TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
1022+
} else if (unlikely(po->sk.sk_type == SOCK_DGRAM && eth_type_vlan(pkc->skb->protocol))) {
1023+
ppd->hv1.tp_vlan_tci = vlan_get_tci(pkc->skb, pkc->skb->dev);
1024+
ppd->hv1.tp_vlan_tpid = ntohs(pkc->skb->protocol);
1025+
ppd->tp_status = TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
9791026
} else {
9801027
ppd->hv1.tp_vlan_tci = 0;
9811028
ppd->hv1.tp_vlan_tpid = 0;
@@ -2395,6 +2442,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
23952442
h.h2->tp_vlan_tci = skb_vlan_tag_get(skb);
23962443
h.h2->tp_vlan_tpid = ntohs(skb->vlan_proto);
23972444
status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
2445+
} else if (unlikely(sk->sk_type == SOCK_DGRAM && eth_type_vlan(skb->protocol))) {
2446+
h.h2->tp_vlan_tci = vlan_get_tci(skb, skb->dev);
2447+
h.h2->tp_vlan_tpid = ntohs(skb->protocol);
2448+
status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
23982449
} else {
23992450
h.h2->tp_vlan_tci = 0;
24002451
h.h2->tp_vlan_tpid = 0;
@@ -2424,7 +2475,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
24242475
sll->sll_halen = dev_parse_header(skb, sll->sll_addr);
24252476
sll->sll_family = AF_PACKET;
24262477
sll->sll_hatype = dev->type;
2427-
sll->sll_protocol = skb->protocol;
2478+
sll->sll_protocol = (sk->sk_type == SOCK_DGRAM) ?
2479+
vlan_get_protocol_dgram(skb) : skb->protocol;
24282480
sll->sll_pkttype = skb->pkt_type;
24292481
if (unlikely(packet_sock_flag(po, PACKET_SOCK_ORIGDEV)))
24302482
sll->sll_ifindex = orig_dev->ifindex;
@@ -3000,8 +3052,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
30003052
if (err)
30013053
goto out_free;
30023054

3003-
if (sock->type == SOCK_RAW &&
3004-
!dev_validate_header(dev, skb->data, len)) {
3055+
if ((sock->type == SOCK_RAW &&
3056+
!dev_validate_header(dev, skb->data, len)) || !skb->len) {
30053057
err = -EINVAL;
30063058
goto out_free;
30073059
}
@@ -3441,7 +3493,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
34413493
/* Original length was stored in sockaddr_ll fields */
34423494
origlen = PACKET_SKB_CB(skb)->sa.origlen;
34433495
sll->sll_family = AF_PACKET;
3444-
sll->sll_protocol = skb->protocol;
3496+
sll->sll_protocol = (sock->type == SOCK_DGRAM) ?
3497+
vlan_get_protocol_dgram(skb) : skb->protocol;
34453498
}
34463499

34473500
sock_recv_ts_and_drops(msg, sk, skb);
@@ -3498,6 +3551,21 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
34983551
aux.tp_vlan_tci = skb_vlan_tag_get(skb);
34993552
aux.tp_vlan_tpid = ntohs(skb->vlan_proto);
35003553
aux.tp_status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
3554+
} else if (unlikely(sock->type == SOCK_DGRAM && eth_type_vlan(skb->protocol))) {
3555+
struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
3556+
struct net_device *dev;
3557+
3558+
rcu_read_lock();
3559+
dev = dev_get_by_index_rcu(sock_net(sk), sll->sll_ifindex);
3560+
if (dev) {
3561+
aux.tp_vlan_tci = vlan_get_tci(skb, dev);
3562+
aux.tp_vlan_tpid = ntohs(skb->protocol);
3563+
aux.tp_status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
3564+
} else {
3565+
aux.tp_vlan_tci = 0;
3566+
aux.tp_vlan_tpid = 0;
3567+
}
3568+
rcu_read_unlock();
35013569
} else {
35023570
aux.tp_vlan_tci = 0;
35033571
aux.tp_vlan_tpid = 0;

net/unix/af_unix.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,6 @@ static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
539539
sk_error_report(other);
540540
}
541541
}
542-
other->sk_state = TCP_CLOSE;
543542
}
544543

545544
static void unix_sock_destructor(struct sock *sk)
@@ -1351,8 +1350,15 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
13511350

13521351
unix_state_double_unlock(sk, other);
13531352

1354-
if (other != old_peer)
1353+
if (other != old_peer) {
13551354
unix_dgram_disconnected(sk, old_peer);
1355+
1356+
unix_state_lock(old_peer);
1357+
if (!unix_peer(old_peer))
1358+
WRITE_ONCE(old_peer->sk_state, TCP_CLOSE);
1359+
unix_state_unlock(old_peer);
1360+
}
1361+
13561362
sock_put(old_peer);
13571363
} else {
13581364
unix_peer(sk) = other;

0 commit comments

Comments
 (0)