diff --git a/newip/src/common/nip_addr.c b/newip/src/common/nip_addr.c index eb88a3cb9117eb0167a496c6f72f37c58a552ce3..31105bc57918de2dba7c451bfc31f4aba5a36fdb 100644 --- a/newip/src/common/nip_addr.c +++ b/newip/src/common/nip_addr.c @@ -403,21 +403,26 @@ unsigned char *build_nip_addr(const struct nip_addr *addr, unsigned char *buf) return p; } -unsigned char *decode_nip_addr(unsigned char *buf, struct nip_addr *addr) +unsigned char *decode_nip_addr(struct nip_buff *nbuf, struct nip_addr *addr) { int i; int ret; int addr_len; - unsigned char *p = buf; - addr->NIP_ADDR_FIELD8[0] = *p; + if (nbuf->remaining_len < sizeof(unsigned char)) + return 0; + + addr->NIP_ADDR_FIELD8[0] = *nbuf->data; addr_len = get_nip_addr_len(addr); if (addr_len == 0) return 0; + if (nbuf->remaining_len < addr_len) + return 0; + for (i = 0; i < addr_len; i++) { - addr->NIP_ADDR_FIELD8[i] = *p; - p++; + addr->NIP_ADDR_FIELD8[i] = *nbuf->data; + nip_buff_pull(nbuf, sizeof(unsigned char)); } addr->bitlen = addr_len * NIP_ADDR_BIT_LEN_8; @@ -425,6 +430,6 @@ unsigned char *decode_nip_addr(unsigned char *buf, struct nip_addr *addr) if (ret) return 0; - return p; + return nbuf->data; } diff --git a/newip/src/common/nip_addr.h b/newip/src/common/nip_addr.h index 370007f20a549bdac9e0e804f7a5a1c79681e084..833202fc2fce5fb346ccd4154efdf3804c16b5ab 100644 --- a/newip/src/common/nip_addr.h +++ b/newip/src/common/nip_addr.h @@ -109,12 +109,26 @@ enum nip_index { extern const struct nip_addr nip_any_addr; extern const struct nip_addr nip_broadcast_addr_arp; +struct nip_buff { + unsigned char *data; + unsigned int remaining_len; +}; + +static inline void nip_buff_pull(struct nip_buff *nbuf, unsigned int len) +{ + if (len > nbuf->remaining_len) + return; + + nbuf->data += len; + nbuf->remaining_len -= len; +} + int nip_addr_invalid(const struct nip_addr *addr); int nip_addr_public(const struct nip_addr *addr); int nip_addr_any(const struct nip_addr *addr); int get_nip_addr_len(const struct nip_addr *addr); unsigned char *build_nip_addr(const struct nip_addr *addr, unsigned char *buf); -unsigned char *decode_nip_addr(unsigned char *buf, struct nip_addr *addr); +unsigned char *decode_nip_addr(struct nip_buff *nbuf, struct nip_addr *addr); int is_nip_local_addr(const struct nip_addr *addr); #endif /* _UAPI_NEWIP_ADDR_H */ diff --git a/newip/src/common/nip_hdr_decap.c b/newip/src/common/nip_hdr_decap.c index 21444c843073db02ad5b1288c00d8fea621f54a9..abec609d3179d956adcbdca898b682490c34c385 100644 --- a/newip/src/common/nip_hdr_decap.c +++ b/newip/src/common/nip_hdr_decap.c @@ -12,81 +12,98 @@ #include "nip_hdr.h" /* Must carry the current field */ -static int _get_nip_hdr_bitmap(unsigned char *buf, +static int _get_nip_hdr_bitmap(struct nip_buff *nbuf, unsigned char bitmap[], unsigned char bitmap_index_max) { int i = 0; - unsigned char *p = buf; - if (*p & NIP_BITMAP_INVALID_SET) + if (nbuf->remaining_len < sizeof(unsigned char)) + return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + + if (*nbuf->data & NIP_BITMAP_INVALID_SET) return -NIP_HDR_BITMAP_INVALID; do { if (i >= bitmap_index_max) return -NIP_HDR_BITMAP_NUM_OUT_RANGE; - bitmap[i] = *p; - p++; + if (nbuf->remaining_len < sizeof(unsigned char)) + return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + + bitmap[i] = *nbuf->data; + nip_buff_pull(nbuf, sizeof(unsigned char)); } while (bitmap[i++] & NIP_BITMAP_HAVE_MORE_BIT); return i; } /* Must carry the current field */ -static int _get_nip_hdr_ttl(const unsigned char *buf, +static int _get_nip_hdr_ttl(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { if (!(bitmap & NIP_BITMAP_INCLUDE_TTL)) return -NIP_HDR_NO_TTL; - niph->ttl = *buf; + if (nbuf->remaining_len < sizeof(niph->ttl)) + return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + + niph->ttl = *nbuf->data; niph->include_ttl = 1; + nip_buff_pull(nbuf, sizeof(niph->ttl)); - return sizeof(niph->ttl); + return 0; } /* Optional fields */ /* Communication between devices of the same version may not carry packet Header length, * but communication between devices of different versions must carry packet header length */ -static int _get_nip_hdr_len(const unsigned char *buf, +static int _get_nip_hdr_len(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { if (!(bitmap & NIP_BITMAP_INCLUDE_HDR_LEN)) return 0; + if (nbuf->remaining_len < sizeof(niph->hdr_len)) + return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + /* Total_len is a network sequence and cannot be * compared directly with the local sequence */ - niph->hdr_len = *buf; + niph->hdr_len = *nbuf->data; niph->include_hdr_len = 1; + nip_buff_pull(nbuf, sizeof(niph->hdr_len)); if (niph->include_total_len && niph->hdr_len >= niph->rcv_buf_len) return -NIP_HDR_LEN_OUT_RANGE; - return sizeof(niph->hdr_len); + return 0; } /* Must carry the current field */ -static int _get_nip_hdr_nexthdr(const unsigned char *buf, +static int _get_nip_hdr_nexthdr(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { if (!(bitmap & NIP_BITMAP_INCLUDE_NEXT_HDR)) return -NIP_HDR_NO_NEXT_HDR; - niph->nexthdr = *buf; + if (nbuf->remaining_len < sizeof(niph->nexthdr)) + return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + + niph->nexthdr = *nbuf->data; niph->include_nexthdr = 1; + nip_buff_pull(nbuf, sizeof(niph->nexthdr)); - return sizeof(niph->nexthdr); + return 0; } /* Must carry the current field */ /* Note: niph->saddr is network order.(big end) */ -static int _get_nip_hdr_daddr(unsigned char *buf, +static int _get_nip_hdr_daddr(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { @@ -95,7 +112,7 @@ static int _get_nip_hdr_daddr(unsigned char *buf, if (!(bitmap & NIP_BITMAP_INCLUDE_DADDR)) return -NIP_HDR_NO_DADDR; - p = decode_nip_addr(buf, &niph->daddr); + p = decode_nip_addr(nbuf, &niph->daddr); if (!p) return -NIP_HDR_DECAP_DADDR_ERR; @@ -103,12 +120,12 @@ static int _get_nip_hdr_daddr(unsigned char *buf, return -NIP_HDR_DADDR_INVALID; niph->include_daddr = 1; - return (niph->daddr.bitlen / NIP_ADDR_BIT_LEN_8); + return 0; } /* Optional fields */ /* Note: niph->daddr is network order.(big end) */ -static int _get_nip_hdr_saddr(unsigned char *buf, +static int _get_nip_hdr_saddr(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { @@ -117,7 +134,7 @@ static int _get_nip_hdr_saddr(unsigned char *buf, if (!(bitmap & NIP_BITMAP_INCLUDE_SADDR)) return 0; - p = decode_nip_addr(buf, &niph->saddr); + p = decode_nip_addr(nbuf, &niph->saddr); if (!p) return -NIP_HDR_DECAP_SADDR_ERR; @@ -125,84 +142,80 @@ static int _get_nip_hdr_saddr(unsigned char *buf, return -NIP_HDR_SADDR_INVALID; niph->include_saddr = 1; - return (niph->saddr.bitlen / NIP_ADDR_BIT_LEN_8); + return 0; } /* Optional fields: tcp/arp need, udp needless */ /* Note: niph->total_len is network order.(big end), need change to host order */ -static int _get_nip_total_len(unsigned char *buf, +static int _get_nip_total_len(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { if (!(bitmap & NIP_BITMAP_INCLUDE_TOTAL_LEN)) return 0; + if (nbuf->remaining_len < sizeof(niph->total_len)) + return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + /* Total_len is a network sequence and cannot be * compared directly with the local sequence */ - niph->total_len = *((unsigned short *)buf); + niph->total_len = *((unsigned short *)nbuf->data); niph->include_total_len = 1; + nip_buff_pull(nbuf, sizeof(niph->total_len)); - return sizeof(niph->total_len); + return 0; } -static int _nip_hdr_bitmap0_parse(unsigned char *buf, +static int _nip_hdr_bitmap0_parse(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { - int len; - int len_total = 0; + int err; - len = _get_nip_hdr_ttl(buf, bitmap, niph); - if (len < 0) - return len; - len_total += len; + err = _get_nip_hdr_ttl(nbuf, bitmap, niph); + if (err < 0) + return err; /* Optional fields */ - len = _get_nip_total_len(buf + len_total, bitmap, niph); - if (len < 0) - return len; - len_total += len; - - len = _get_nip_hdr_nexthdr(buf + len_total, bitmap, niph); - if (len < 0) - return len; - len_total += len; - - len = _get_nip_hdr_daddr(buf + len_total, bitmap, niph); - if (len < 0) - return len; - len_total += len; - - len = _get_nip_hdr_saddr(buf + len_total, bitmap, niph); - if (len < 0) - return len; - len_total += len; - - return len_total; + err = _get_nip_total_len(nbuf, bitmap, niph); + if (err < 0) + return err; + + err = _get_nip_hdr_nexthdr(nbuf, bitmap, niph); + if (err < 0) + return err; + + err = _get_nip_hdr_daddr(nbuf, bitmap, niph); + if (err < 0) + return err; + + err = _get_nip_hdr_saddr(nbuf, bitmap, niph); + if (err < 0) + return err; + + return 0; } -static int _nip_hdr_bitmap1_parse(unsigned char *buf, +static int _nip_hdr_bitmap1_parse(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { - int len; - int len_total = 0; + int err; /* If add new field needs to be modified with the macro definition */ if (bitmap & NIP_INVALID_BITMAP_2) niph->include_unknown_bit = 1; /* Optional fields */ - len = _get_nip_hdr_len(buf + len_total, bitmap, niph); - if (len < 0) - return len; - len_total += len; + err = _get_nip_hdr_len(nbuf, bitmap, niph); + if (err < 0) + return err; - return len_total; + return 0; } -static int _nip_hdr_unknown_bit_check(unsigned char *buf, +static int _nip_hdr_unknown_bit_check(struct nip_buff *nbuf, unsigned char bitmap, struct nip_hdr_decap *niph) { @@ -211,7 +224,7 @@ static int _nip_hdr_unknown_bit_check(unsigned char *buf, } #define FACTORY_NUM_MAX 3 -static int (*hdr_parse_factory[FACTORY_NUM_MAX])(unsigned char *, +static int (*hdr_parse_factory[FACTORY_NUM_MAX])(struct nip_buff *, unsigned char, struct nip_hdr_decap *) = { _nip_hdr_bitmap0_parse, @@ -242,33 +255,37 @@ int nip_hdr_parse(unsigned char *rcv_buf, unsigned int buf_len, struct nip_hdr_d { int i = 0; int ret; - unsigned char *buf = rcv_buf; unsigned char bitmap[BITMAP_MAX] = {0}; - int num = _get_nip_hdr_bitmap(buf, bitmap, BITMAP_MAX); + int num; + struct nip_buff nbuf; - if (num <= 0 || !rcv_buf) - return num; + nbuf.data = rcv_buf; + if (!nbuf.data) + return 0; - niph->hdr_real_len = num * sizeof(bitmap[0]); - buf += niph->hdr_real_len; + nbuf.remaining_len = buf_len; + num = _get_nip_hdr_bitmap(&nbuf, bitmap, BITMAP_MAX); + if (num <= 0) + return num; niph->rcv_buf_len = buf_len; while (i < num) { - int len; + int err; if (i >= FACTORY_NUM_MAX) break; - len = hdr_parse_factory[i](buf, bitmap[i], niph); - if (len < 0) - return len; - buf += len; - niph->hdr_real_len += len; - if (niph->hdr_real_len >= buf_len) - return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + err = hdr_parse_factory[i](&nbuf, bitmap[i], niph); + if (err < 0) + return err; + i++; } + if (buf_len < nbuf.remaining_len) + return -NIP_HDR_RCV_BUF_READ_OUT_RANGE; + + niph->hdr_real_len = buf_len - nbuf.remaining_len; ret = nip_hdr_check(niph); if (ret < 0) return ret; diff --git a/newip/third_party/linux-5.10/include/net/nip.h b/newip/third_party/linux-5.10/include/net/nip.h index 236ba3a1a91eb3c33868d35361eef8422a8902b0..78806663f3245f3cd512038a0760ebaaa5f9e277 100644 --- a/newip/third_party/linux-5.10/include/net/nip.h +++ b/newip/third_party/linux-5.10/include/net/nip.h @@ -133,10 +133,9 @@ int nip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen); int nip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); -void nip_sock_debug(const struct sock *sk, const char *name, int state); +void nip_sock_debug(const struct sock *sk, const char *name); void nip_sock_debug_output(const struct nip_addr *nip_daddr, const struct nip_addr *nip_saddr, - __be16 dport, __be16 sport, - const char *name, int state); + __be16 dport, __be16 sport, const char *name); /* functions defined in nip_addrconf.c */ int nip_addrconf_get_ifaddr(struct net *net, unsigned int cmd, void __user *arg); diff --git a/newip/third_party/linux-5.10/net/newip/icmp.c b/newip/third_party/linux-5.10/net/newip/icmp.c index 8202c37f0890089b0bcb9c446649c213563ac53c..39b1aa7d6b18ec36390ddd428625c7342c180b60 100644 --- a/newip/third_party/linux-5.10/net/newip/icmp.c +++ b/newip/third_party/linux-5.10/net/newip/icmp.c @@ -45,9 +45,16 @@ int nip_icmp_rcv(struct sk_buff *skb) { int ret = 0; - struct nip_icmp_hdr *hdr = nip_icmp_header(skb); - u8 type = hdr->nip_icmp_type; + struct nip_icmp_hdr *hdr; + u8 type; + if (!pskb_may_pull(skb, sizeof(struct nip_icmp_hdr))) { + nip_dbg("invalid ICMP packet"); + return -EINVAL; + } + + hdr = nip_icmp_header(skb); + type = hdr->nip_icmp_type; nip_dbg("rcv newip icmp packet. type=%u", type); switch (type) { case NIP_ARP_NS: diff --git a/newip/third_party/linux-5.10/net/newip/nip_sockglue.c b/newip/third_party/linux-5.10/net/newip/nip_sockglue.c index f3f7ac90d35e0931903d45cea1719e9d4a41cfd7..2080424ce64bc40969d818fe29886df6464a62c9 100644 --- a/newip/third_party/linux-5.10/net/newip/nip_sockglue.c +++ b/newip/third_party/linux-5.10/net/newip/nip_sockglue.c @@ -179,8 +179,7 @@ int nip_getsockopt(struct sock *sk, int level, } void nip_sock_debug_output(const struct nip_addr *nip_daddr, const struct nip_addr *nip_saddr, - __be16 dport, __be16 sport, - const char *name, int state) + __be16 dport, __be16 sport, const char *name) { if (get_nip_debug()) { char saddr[NIP_ADDR_BIT_LEN_MAX] = {0}; @@ -189,20 +188,18 @@ void nip_sock_debug_output(const struct nip_addr *nip_daddr, const struct nip_ad nip_addr_to_str(nip_daddr, daddr, NIP_ADDR_BIT_LEN_MAX); nip_addr_to_str(nip_saddr, saddr, NIP_ADDR_BIT_LEN_MAX); - nip_dbg("%s :%s (saddr=%s, daddr=%s, sport=%u, dport=%u)", - name, state ? "success" : "failed", saddr, daddr, - ntohs(sport), ntohs(dport)); + nip_dbg("%s (saddr=%s, daddr=%s, sport=%u, dport=%u)", + name, saddr, daddr, ntohs(sport), ntohs(dport)); } } -void nip_sock_debug(const struct sock *sk, const char *name, int state) +void nip_sock_debug(const struct sock *sk, const char *name) { if (sk) { struct inet_sock *inet = inet_sk(sk); nip_sock_debug_output(&sk->SK_NIP_DADDR, &sk->SK_NIP_RCV_SADDR, - inet->inet_dport, inet->inet_sport, - name, state); + inet->inet_dport, inet->inet_sport, name); } } diff --git a/newip/third_party/linux-5.10/net/newip/nndisc.c b/newip/third_party/linux-5.10/net/newip/nndisc.c index 6d1e4d2a5734803ed83f2a8a052950bd1fd8ab7a..27b48bc5205199cffd86994ce0cc4112c69c9953 100644 --- a/newip/third_party/linux-5.10/net/newip/nndisc.c +++ b/newip/third_party/linux-5.10/net/newip/nndisc.c @@ -495,16 +495,27 @@ out: int nndisc_rcv_ns(struct sk_buff *skb) { - struct nnd_msg *msg = (struct nnd_msg *)skb_transport_header(skb); - u_char *p = msg->data; + struct nnd_msg *msg; + u_char *p; u_char *lladdr; struct nip_addr addr = {0}; struct neighbour *neigh; struct ethhdr *eth; struct net_device *dev = skb->dev; int err = 0; + struct nip_buff nbuf; + + if (!pskb_may_pull(skb, sizeof(struct nnd_msg))) { + nip_dbg("invalid ns packet"); + err = -EFAULT; + goto out; + } + + msg = (struct nnd_msg *)skb->data; + nbuf.data = msg->data; + nbuf.remaining_len = skb->len - sizeof(struct nip_icmp_hdr); - p = decode_nip_addr(p, &addr); + p = decode_nip_addr(&nbuf, &addr); if (!p) { nip_dbg("failure when decode source address"); err = -EFAULT; @@ -526,7 +537,7 @@ int nndisc_rcv_ns(struct sk_buff *skb) lladdr = eth->h_source; /* checksum parse */ - if (!nip_get_nndisc_rcv_checksum(skb, p)) { + if (!nip_get_nndisc_rcv_checksum(skb, nbuf.data)) { nip_dbg("ns ICMP checksum failed, drop the packet"); err = -EINVAL; goto out; @@ -546,16 +557,40 @@ out: int nndisc_rcv_na(struct sk_buff *skb) { - struct nnd_msg *msg = (struct nnd_msg *)skb_transport_header(skb); - u_char *p = msg->data; + struct nnd_msg *msg; + u_char *p; u_char len; u8 lladdr[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; struct net_device *dev = skb->dev; struct neighbour *neigh; + if (!pskb_may_pull(skb, sizeof(struct nnd_msg))) { + nip_dbg("invalid na packet"); + kfree_skb(skb); + return -EINVAL; + } + + msg = (struct nnd_msg *)skb->data; + p = msg->data; + if (skb->len - sizeof(struct nip_icmp_hdr) < sizeof(unsigned char)) { + nip_dbg("invalid msg data"); + kfree_skb(skb); + return -EINVAL; + } len = *p; + if (len > MAX_ADDR_LEN) { + nip_dbg("Invalid length, drop the packet(len=%u)", len); + kfree_skb(skb); + return 0; + } + p++; memset(lladdr, 0, ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))); + if (skb->len - sizeof(struct nip_icmp_hdr) - sizeof(unsigned char) < len) { + nip_dbg("invalid msg data"); + kfree_skb(skb); + return -EINVAL; + } memcpy(lladdr, p, len); if (!nip_get_nndisc_rcv_checksum(skb, p + len)) { diff --git a/newip/third_party/linux-5.10/net/newip/tcp_nip.c b/newip/third_party/linux-5.10/net/newip/tcp_nip.c index f01eac49d6a455f235f3994c38a96c9d3118f96f..2ca6bef915b3260949c7fdd69ef0607fd3906831 100644 --- a/newip/third_party/linux-5.10/net/newip/tcp_nip.c +++ b/newip/third_party/linux-5.10/net/newip/tcp_nip.c @@ -407,8 +407,6 @@ #define TCP_WINDOW_RAISE_THRESHOLD 2 #define TCP_BACKLOG_HEADROOM (64 * 1024) #define BYTES_PER_TCP_HEADER 4 -#define TRUE 1 -#define FALSE 0 static const struct inet_connection_sock_af_ops newip_specific; @@ -525,7 +523,7 @@ void tcp_nip_close(struct sock *sk, long timeout) if (data_was_unread) { tcp_set_state(sk, TCP_CLOSE); - nip_sock_debug(sk, __func__, TRUE); + nip_sock_debug(sk, __func__); tcp_nip_send_active_reset(sk, sk->sk_allocation); } else if (tcp_nip_close_state(sk)) { /* RED-PEN. Formally speaking, we have broken TCP state @@ -536,7 +534,7 @@ void tcp_nip_close(struct sock *sk, long timeout) * TCP_CLOSE_WAIT -> TCP_LAST_ACK */ nip_dbg("ready to send fin, sk_state=%d", sk->sk_state); - nip_sock_debug(sk, __func__, TRUE); + nip_sock_debug(sk, __func__); tcp_nip_send_fin(sk); } @@ -722,7 +720,7 @@ static int tcp_nip_connect(struct sock *sk, struct sockaddr *uaddr, err = __tcp_nip_connect(sk); if (err) goto late_failure; - nip_sock_debug(sk, __func__, TRUE); + nip_sock_debug(sk, __func__); return 0; /* failure after tcp_set_state(sk, TCP_SYN_SENT) */ @@ -730,8 +728,7 @@ late_failure: tcp_set_state(sk, TCP_CLOSE); failure: nip_sock_debug_output(&usin->sin_addr, &sk->SK_NIP_RCV_SADDR, - usin->sin_port, inet->inet_sport, - __func__, FALSE); + usin->sin_port, inet->inet_sport, __func__); sk->sk_route_caps = 0; inet->inet_dport = 0; return err; @@ -1710,6 +1707,26 @@ static bool tcp_nip_add_backlog(struct sock *sk, struct sk_buff *skb) return false; } +static int nip_skb_precheck(struct sk_buff *skb) +{ + if (!pskb_may_pull(skb, sizeof(struct tcphdr))) { + nip_dbg("invalid tcp packet length, drop the packet(skb->len=%u)", skb->len); + return -EINVAL; + } + + if (skb->pkt_type != PACKET_HOST) { + nip_dbg("unknown pkt-type(%u), drop skb", skb->pkt_type); + return -EINVAL; + } + + if (!nip_get_tcp_input_checksum(skb)) { + nip_dbg("checksum fail, drop skb"); + return -EINVAL; + } + + return 0; +} + /* Function * TCP is the gateway from the network layer to the transport layer * and receives data packets from the network layer @@ -1724,15 +1741,8 @@ static int tcp_nip_rcv(struct sk_buff *skb) int ret; int dif = skb->skb_iif; - if (skb->pkt_type != PACKET_HOST) { - nip_dbg("unknown pkt-type(%u), drop skb", skb->pkt_type); - goto discard_it; - } - - if (!nip_get_tcp_input_checksum(skb)) { - nip_dbg("checksum fail, drop skb"); + if (nip_skb_precheck(skb)) goto discard_it; - } th = (const struct tcphdr *)skb->data; @@ -1824,12 +1834,12 @@ no_tcp_socket: discard_it: kfree_skb(skb); - nip_sock_debug(sk, __func__, FALSE); + nip_sock_debug(sk, __func__); return 0; discard_and_relse: sk_drops_add(sk, skb); - nip_sock_debug(sk, __func__, FALSE); + nip_sock_debug(sk, __func__); if (refcounted) sock_put(sk); goto discard_it; diff --git a/newip/third_party/linux-5.10/net/newip/udp.c b/newip/third_party/linux-5.10/net/newip/udp.c index 5ff0c6044ce2a54df4b9fca468f87902d6bd512a..cd4a0b49484afe4b4f952f7ce071368653db791b 100644 --- a/newip/third_party/linux-5.10/net/newip/udp.c +++ b/newip/third_party/linux-5.10/net/newip/udp.c @@ -362,13 +362,27 @@ bool nip_get_udp_input_checksum(struct sk_buff *skb) int nip_udp_input(struct sk_buff *skb) { struct sock *sk; - int rc = 0; - struct udphdr *udphead = udp_hdr(skb); + int rc = -EINVAL; + struct udphdr *udphead; + + if (!pskb_may_pull(skb, sizeof(struct udphdr))) { + nip_dbg("invalid skb length, drop the packet(skb->len=%u)", skb->len); + kfree_skb(skb); + goto end; + } + + udphead = udp_hdr(skb); + if (ntohs(udphead->len) < sizeof(struct udphdr) || + ntohs(udphead->len) > skb->len) { + nip_dbg("invalid udp packet length, drop the packet(udphead->len=%u)", + ntohs(udphead->len)); + kfree_skb(skb); + goto end; + } if (!nip_get_udp_input_checksum(skb)) { nip_dbg("checksum failed, drop the packet"); kfree_skb(skb); - rc = -1; goto end; } @@ -378,7 +392,6 @@ int nip_udp_input(struct sk_buff *skb) nip_dbg("dport not match, drop the packet. sport=%u, dport=%u, data_len=%u", ntohs(udphead->source), ntohs(udphead->dest), ntohs(udphead->len)); kfree_skb(skb); - rc = -1; goto end; }