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_checksum.c b/newip/src/common/nip_checksum.c index e2ba185922d83826ada8c8919fd56b8a10303fff..a5ecef1f3c0dc20d28d931cf6764e35d1d110238 100644 --- a/newip/src/common/nip_checksum.c +++ b/newip/src/common/nip_checksum.c @@ -38,7 +38,7 @@ unsigned int _nip_header_chksum(struct nip_pseudo_header *chksum_header) unsigned short hdr_len = 0; addr_len = chksum_header->saddr.bitlen / NIP_ADDR_BIT_LEN_8; - if (addr_len) { + if (addr_len && addr_len < NIP_HDR_MAX) { j = 0; for (i = 0; i < addr_len; i++, j++) pseudo_header[j] = chksum_header->saddr.NIP_ADDR_FIELD8[i]; @@ -46,7 +46,7 @@ unsigned int _nip_header_chksum(struct nip_pseudo_header *chksum_header) } addr_len = chksum_header->daddr.bitlen / NIP_ADDR_BIT_LEN_8; - if (addr_len) { + if (addr_len && addr_len < NIP_HDR_MAX) { j = hdr_len; for (i = 0; i < addr_len; i++, j++) pseudo_header[j] = chksum_header->daddr.NIP_ADDR_FIELD8[i]; @@ -54,10 +54,15 @@ unsigned int _nip_header_chksum(struct nip_pseudo_header *chksum_header) } /* chksum_header->check_len is network order.(big end) */ - *(unsigned short *)(pseudo_header + hdr_len) = chksum_header->check_len; - hdr_len += sizeof(chksum_header->check_len); - *(pseudo_header + hdr_len) = chksum_header->nexthdr; - hdr_len += sizeof(chksum_header->nexthdr); + if (hdr_len < NIP_HDR_MAX) { + *(unsigned short *)(pseudo_header + hdr_len) = chksum_header->check_len; + hdr_len += sizeof(chksum_header->check_len); + } + + if (hdr_len < NIP_HDR_MAX) { + *(pseudo_header + hdr_len) = chksum_header->nexthdr; + hdr_len += sizeof(chksum_header->nexthdr); + } return _nip_check_sum(pseudo_header, hdr_len); } diff --git a/newip/src/common/nip_hdr.h b/newip/src/common/nip_hdr.h index 70b1eab1bfd1848e49337a82ed370d77b90ca716..03c16efb886f865e3c864ca95bce8ac822a1db4f 100644 --- a/newip/src/common/nip_hdr.h +++ b/newip/src/common/nip_hdr.h @@ -34,7 +34,8 @@ */ #define NIP_HDR_MAX 24 #define NIP_UDP_HDR_LEN 8 -#define NIP_MIN_MTU (NIP_HDR_MAX + NIP_UDP_HDR_LEN) +#define NIP_TCP_HDR_LEN 20 +#define NIP_MIN_MTU (NIP_HDR_MAX + NIP_TCP_HDR_LEN) #define NIP_BYTE_ALIGNMENT 2 #define NIP_BITMAP_HAVE_MORE_BIT 0x01 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/src/common/nip_hdr_encap.c b/newip/src/common/nip_hdr_encap.c index 9e2cef14138d29e0f8d8a9a0a932009db17d5d01..b9718346ab18b1e14a5c3901f2959d9a4bbf5cee 100644 --- a/newip/src/common/nip_hdr_encap.c +++ b/newip/src/common/nip_hdr_encap.c @@ -128,6 +128,15 @@ static inline void _nip_hdr_encap_comm_bitmap(struct nip_hdr_encap *head) void nip_hdr_udp_encap(struct nip_hdr_encap *head) { + int len; + + if (!head) + return; + + len = get_nip_hdr_len(NIP_HDR_UDP, &head->saddr, &head->daddr); + if (len == 0 || len > NIP_HDR_MAX) + return; + /* Encapsulate the bitmap into the newIP packet header BUF */ #if (NEWIP_BYTE_ALIGNMENT_ENABLE == 1) _nip_hdr_encap_udp_bitmap(head); @@ -146,6 +155,15 @@ void nip_hdr_udp_encap(struct nip_hdr_encap *head) /* need update total len after this func, call nip_update_total_len */ void nip_hdr_comm_encap(struct nip_hdr_encap *head) { + int len; + + if (!head) + return; + + len = get_nip_hdr_len(NIP_HDR_COMM, &head->saddr, &head->daddr); + if (len == 0 || len > NIP_HDR_MAX) + return; + /* Encapsulate the bitmap into the newIP packet header BUF */ #if (NEWIP_BYTE_ALIGNMENT_ENABLE == 1) _nip_hdr_encap_comm_bitmap(head); diff --git a/newip/src/linux-5.10/drivers/net/bt/btdev.c b/newip/src/linux-5.10/drivers/net/bt/btdev.c index 4a5fcf8cc51cda42faad627a41c4b351efcf442c..2f621c7855dd414cf1addf22e3fbea0231a2fce2 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.c +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.c @@ -195,15 +195,15 @@ static ssize_t bt_io_file_read(struct file *filp, btdev_dbg_err("%s invalid skb", cdev_name(vnet)); return -EINVAL; } - out_sz = skb->len - MACADDR_LEN; - if (unlikely(out_sz > size)) { + out_sz = skb->len > MACADDR_LEN ? (skb->len - MACADDR_LEN) : 0; + if (unlikely(out_sz > size) || unlikely(out_sz == 0)) { /* Obtain the skb pointer from the ring buf and ask whether the user-state buf * length can store data in the skb. If the user-state buf length is not enough, * the skb cannot be released at this time, because the skb is still unchained * on the ring buf. */ - btdev_dbg_err("%s usr-buf too small, skb-len=%ld, usr-buf-len=%ld", - cdev_name(vnet), (long)out_sz, (long)size); + btdev_dbg_err("%s usr-buf too small, skb-len=%ld, usr-buf-len=%ld, skb-len=%u", + cdev_name(vnet), (long)out_sz, (long)size, skb->len); return -EINVAL; } @@ -854,8 +854,10 @@ static int bt_ring_is_full(const struct bt_ring *ring) static void bt_ring_produce(struct bt_ring *ring, void *data) { smp_mb(); // Make sure the read and write order is correct - ring->data[ring->head] = data; - ring->head = (ring->head + 1) % ring->size; + if (likely(ring->head < ring->size)) { + ring->data[ring->head] = data; + ring->head = (ring->head + 1) % ring->size; + } smp_wmb(); // Make sure the write order is correct } @@ -863,7 +865,7 @@ static void *bt_ring_current(struct bt_ring *ring) { void *data = NULL; - if (unlikely(!ring)) + if (unlikely(!ring) || unlikely(ring->tail > ring->size)) return data; data = ring->data[ring->tail]; diff --git a/newip/src/linux-5.10/drivers/net/bt/btdev.h b/newip/src/linux-5.10/drivers/net/bt/btdev.h index d6f46d5bf4b5cb260386bbaef3a163eeaee8ed22..b39dee9fbb298e86814df6b4843527a83cc165b0 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.h +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.h @@ -221,6 +221,9 @@ static inline const char *bt_virnet_get_ndev_name(const struct bt_virnet *vn) static inline const char *bt_virnet_get_state_rep(const struct bt_virnet *vn) { + if (unlikely(vn->state > BT_VIRNET_STAET_NUM)) + return g_bt_virnet_state_rep[BT_VIRNET_STATE_DELETED]; + return g_bt_virnet_state_rep[vn->state]; } diff --git a/newip/src/linux-5.10/net/newip/nip_hooks_register.c b/newip/src/linux-5.10/net/newip/nip_hooks_register.c index 0fc022dd1745b37f30566148499b1f8cd2d95cf3..bf01f9677b727a381381f3633f8a99d32093545d 100644 --- a/newip/src/linux-5.10/net/newip/nip_hooks_register.c +++ b/newip/src/linux-5.10/net/newip/nip_hooks_register.c @@ -24,6 +24,9 @@ */ void nip_ninet_ehashfn(const struct sock *sk, u32 *ret) { + if (!sk || !ret) + return; + *ret = ninet_ehashfn(sock_net(sk), &sk->SK_NIP_RCV_SADDR, sk->sk_num, &sk->SK_NIP_DADDR, sk->sk_dport); } diff --git a/newip/third_party/linux-5.10/include/net/tcp_nip.h b/newip/third_party/linux-5.10/include/net/tcp_nip.h index 1e30efd30329dc1c4dd816da30e373e585897783..feece7a67641bebdedb5f4224792b4d5a8f5d447 100644 --- a/newip/third_party/linux-5.10/include/net/tcp_nip.h +++ b/newip/third_party/linux-5.10/include/net/tcp_nip.h @@ -163,6 +163,12 @@ static inline struct tcp_nip_request_sock *tcp_nip_rsk(const struct request_sock return (struct tcp_nip_request_sock *)req; } +static inline void tcp_nip_modify_send_head(struct sock *sk, const struct sk_buff *skb) +{ + if (tcp_skb_is_last(sk, skb)) + sk->sk_send_head = NULL; +} + /* connect */ int __tcp_nip_connect(struct sock *sk); int _tcp_nip_conn_request(struct request_sock_ops *rsk_ops, 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..013e0555a4a0f61d950d2fff730ce965c902c1c7 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: @@ -60,7 +67,20 @@ int nip_icmp_rcv(struct sk_buff *skb) return ret; } +static void nip_icmp_early_demux(struct sk_buff *skb) +{ +} + +static void nip_icmp_err_handler(struct sk_buff *skb, + struct ninet_skb_parm *opt, + u8 type, u8 code, + int offset, __be32 info) +{ +} + static const struct ninet_protocol nip_icmp_protocol = { + .early_demux = nip_icmp_early_demux, + .err_handler = nip_icmp_err_handler, .handler = nip_icmp_rcv, .flags = 0, }; diff --git a/newip/third_party/linux-5.10/net/newip/ninet_hashtables.c b/newip/third_party/linux-5.10/net/newip/ninet_hashtables.c index 5c39a3a48a96a313587b1e9f69a1cf25c5f1f25d..33f7c5ebc83437bf2f2d2a6665f21ae469fe58bc 100644 --- a/newip/third_party/linux-5.10/net/newip/ninet_hashtables.c +++ b/newip/third_party/linux-5.10/net/newip/ninet_hashtables.c @@ -241,7 +241,8 @@ static void ninet_unhash2(struct inet_hashinfo *h, struct sock *sk) spin_lock(&ilb2->lock); hlist_del_init_rcu(&inet_csk(sk)->icsk_listen_portaddr_node); - ilb2->count--; + if (ilb2->count) + ilb2->count--; spin_unlock(&ilb2->lock); } @@ -254,7 +255,8 @@ static void __ninet_unhash(struct sock *sk, struct inet_listen_hashbucket *ilb) struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; ninet_unhash2(hashinfo, sk); - ilb->count--; + if (ilb->count) + ilb->count--; } __sk_nulls_del_node_init_rcu(sk); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); @@ -311,10 +313,9 @@ struct sock *__ninet_lookup_established(struct net *net, const struct hlist_nulls_node *node; const __portpair ports = INET_COMBINED_PORTS(sport, hnum); - + /* mask ensures that the hash index is valid without memory overruns */ unsigned int hash = ninet_ehashfn(net, daddr, hnum, saddr, sport); unsigned int slot = hash & hashinfo->ehash_mask; - struct inet_ehash_bucket *head = &hashinfo->ehash[slot]; begin: @@ -434,7 +435,7 @@ struct sock *ninet_lookup_listener(struct net *net, saddr, sport, &nip_any_addr, hnum, dif, sdif); done: - if (IS_ERR(result)) + if (IS_ERR_OR_NULL(result)) return NULL; return result; } diff --git a/newip/third_party/linux-5.10/net/newip/nip_fib.c b/newip/third_party/linux-5.10/net/newip/nip_fib.c index dfdc4ce34c26065212a8c519640d6f796fc8bba1..45d487b8df696be57141851242215cce58a9888e 100644 --- a/newip/third_party/linux-5.10/net/newip/nip_fib.c +++ b/newip/third_party/linux-5.10/net/newip/nip_fib.c @@ -88,6 +88,7 @@ struct nip_fib_node *nip_fib_locate(struct hlist_head *nip_tb_head, struct hlist_head *h; unsigned int hash; + /* hash calc ensures that the hash index is valid without memory overruns */ hash = ninet_route_hash(daddr); h = &nip_tb_head[hash]; @@ -97,6 +98,7 @@ struct nip_fib_node *nip_fib_locate(struct hlist_head *nip_tb_head, } /* find default route */ + /* hash calc ensures that the hash index is valid without memory overruns */ hash = ninet_route_hash(&nip_any_addr); h = &nip_tb_head[hash]; @@ -139,6 +141,7 @@ int nip_fib_add(struct nip_fib_table *table, struct nip_rt_info *rt) char dst[NIP_ADDR_BIT_LEN_MAX] = {0}; char gateway[NIP_ADDR_BIT_LEN_MAX] = {0}; + /* hash calc ensures that the hash index is valid without memory overruns */ hash = ninet_route_hash(&rt->rt_dst); h = &table->nip_tb_head[hash]; diff --git a/newip/third_party/linux-5.10/net/newip/nip_input.c b/newip/third_party/linux-5.10/net/newip/nip_input.c index 462c300de0b5123f9b0486244cea159e1da3f29c..3e35157bdb0222092d32a4515e7ce78c89156a35 100644 --- a/newip/third_party/linux-5.10/net/newip/nip_input.c +++ b/newip/third_party/linux-5.10/net/newip/nip_input.c @@ -101,7 +101,7 @@ int nip_rcv(struct sk_buff *skb, struct net_device *dev, memset(nipcb(skb), 0, sizeof(struct ninet_skb_parm)); offset = nip_hdr_parse(skb->data, skb->len, &niph); - if (offset <= 0) { + if (offset <= 0 || offset > skb->len) { nip_dbg("check in failure, errcode=%d, Drop a packet (nexthdr=%u, hdr_len=%u)", offset, niph.nexthdr, niph.hdr_len); goto drop; diff --git a/newip/third_party/linux-5.10/net/newip/nip_output.c b/newip/third_party/linux-5.10/net/newip/nip_output.c index 3aeb7c11ca1a607d19e8b2a12221e5b80a51f9c1..e41ee1e101342b80bcd88a9f0480aac437581198 100644 --- a/newip/third_party/linux-5.10/net/newip/nip_output.c +++ b/newip/third_party/linux-5.10/net/newip/nip_output.c @@ -54,15 +54,18 @@ void update_memory_rate(const char *upper_fun) struct sysinfo mem_info; unsigned long total; unsigned long free; - unsigned long used; unsigned int uint_kb; si_meminfo(&mem_info); uint_kb = mem_info.mem_unit / NIP_BIT_TO_BYTE; total = (unsigned long)mem_info.totalram * uint_kb; free = (unsigned long)mem_info.freeram * uint_kb; - used = total - free; - nip_dbg("%s call cur-func mem total: %ld KB, mem used: %ld KB", upper_fun, total, used); + if (total > free) + nip_dbg("%s call cur-func mem total: %ld KB, mem used: %ld KB", + upper_fun, total, total - free); + else + nip_dbg("%s call cur-func mem total: %ld KB, mem free: %ld KB", + upper_fun, total, free); } int nip_output(struct net *net, struct sock *sk, struct sk_buff *skb) 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..79c7fc871dbbac0c1b425368af5362d16e9e431e 100644 --- a/newip/third_party/linux-5.10/net/newip/nndisc.c +++ b/newip/third_party/linux-5.10/net/newip/nndisc.c @@ -87,11 +87,16 @@ static void nndisc_error_report(struct neighbour *neigh, struct sk_buff *skb) kfree_skb(skb); } +static void nndisc_generic_error_report(struct neighbour *neigh, struct sk_buff *skb) +{ +} + static const struct neigh_ops nndisc_generic_ops = { .family = AF_NINET, .solicit = nndisc_solicit, .output = neigh_resolve_output, .connected_output = neigh_connected_output, + .error_report = nndisc_generic_error_report, }; static const struct neigh_ops nndisc_hh_ops = { @@ -121,6 +126,15 @@ static const struct neigh_ops nndisc_direct_ops = { #define NIP_NEIGH_GC_THRESH_2 512 #define NIP_NEIGH_GC_THRESH_3 1024 +static void nndisc_proxy_redo(struct sk_buff *skb) +{ +} + +static int nndisc_is_multicast(const void *pkey) +{ + return -EINVAL; +} + struct neigh_table nnd_tbl = { .family = AF_NINET, .key_len = sizeof(struct nip_addr), @@ -128,6 +142,8 @@ struct neigh_table nnd_tbl = { .hash = nndisc_hash, .key_eq = nndisc_key_eq, .constructor = nndisc_constructor, + .proxy_redo = nndisc_proxy_redo, + .is_multicast = nndisc_is_multicast, .id = "nndisc_cache", .parms = { .tbl = &nnd_tbl, @@ -495,16 +511,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 +553,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 +573,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 63e2ff5d3c98158232cfb9a70e8b63524cfd0050..68855070b3ede9fa77e3fda0a284573255b52588 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 @@ -400,6 +400,7 @@ #include #include #include "nip_checksum.h" +#include "nip_hdr.h" #include "tcp_nip_parameter.h" #define tcp_header_length(th) ((th)->doff << 2) @@ -449,9 +450,14 @@ bool nip_get_tcp_input_checksum(struct sk_buff *skb) static int tcp_nip_close_state(struct sock *sk) { - int next = (int)new_state[sk->sk_state]; - int ns = next & TCP_STATE_MASK; + int next; + int ns; + if (sk->sk_state >= TCP_MAX_STATES) + return TCP_ACTION_FIN; + + next = (int)new_state[sk->sk_state]; + ns = next & TCP_STATE_MASK; tcp_set_state(sk, ns); return next & TCP_ACTION_FIN; @@ -787,29 +793,69 @@ static void tcp_nip_reqsk_destructor(struct request_sock *req) ; } +static void tcp_nip_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, + struct request_sock *req) +{ +} + +static void tcp_nip_reqsk_send_reset(const struct sock *sk, struct sk_buff *skb) +{ +} + +static void tcp_nip_reqsk_syn_ack_timeout(const struct request_sock *req) +{ +} + struct request_sock_ops tcp_nip_request_sock_ops __read_mostly = { - .family = AF_NINET, - .obj_size = sizeof(struct tcp_nip_request_sock), - .rtx_syn_ack = tcp_nip_rtx_synack, - .send_ack = NULL, - .destructor = tcp_nip_reqsk_destructor, - .send_reset = NULL, - .syn_ack_timeout = NULL, + .family = AF_NINET, + .obj_size = sizeof(struct tcp_nip_request_sock), + .rtx_syn_ack = tcp_nip_rtx_synack, + .send_ack = tcp_nip_reqsk_send_ack, + .destructor = tcp_nip_reqsk_destructor, + .send_reset = tcp_nip_reqsk_send_reset, + .syn_ack_timeout = tcp_nip_reqsk_syn_ack_timeout, }; +#ifdef CONFIG_TCP_MD5SIG +static int nip_calc_md5_hash(char *location, const struct tcp_md5sig_key *md5, + const struct sock *sk, const struct sk_buff *skb) +{ + return -EINVAL; +} + +static struct tcp_md5sig_key *nip_req_md5_lookup(const struct sock *sk, + const struct sock *addr_sk) +{ + return NULL; +} +#endif + +#ifdef CONFIG_SYN_COOKIES +static __u32 nip_cookie_init_seq(const struct sk_buff *skb, __u16 *mss) +{ + return 0; +} +#endif + +static u32 tcp_nip_init_ts_off(const struct net *net, const struct sk_buff *skb) +{ + return 0; +} + static const struct tcp_request_sock_ops tcp_request_sock_newip_ops = { .mss_clamp = TCP_BASE_MSS, #ifdef CONFIG_TCP_MD5SIG - .req_md5_lookup = NULL, - .calc_md5_hash = NULL, + .req_md5_lookup = nip_req_md5_lookup, + .calc_md5_hash = nip_calc_md5_hash, #endif .init_req = tcp_nip_init_req, #ifdef CONFIG_SYN_COOKIES - .cookie_init_seq = NULL, + .cookie_init_seq = nip_cookie_init_seq, #endif .route_req = tcp_nip_route_req, .init_seq = tcp_nip_init_sequence, .send_synack = tcp_nip_send_synack, + .init_ts_off = tcp_nip_init_ts_off, }; /* Function @@ -935,21 +981,37 @@ put_and_exit: goto out; } +static void tcp_nip_send_check(struct sock *sk, struct sk_buff *skb) +{ +} + +static int tcp_nip_rebuild_header(struct sock *sk) +{ + return -EINVAL; +} + +static void nip_addr2sockaddr(struct sock *sk, struct sockaddr *addr) +{ +} + +static void nip_mtu_reduced(struct sock *sk) +{ +} + static const struct inet_connection_sock_af_ops newip_specific = { - .queue_xmit = tcp_nip_queue_xmit, - .send_check = NULL, - .rebuild_header = NULL, - .sk_rx_dst_set = ninet_sk_rx_dst_set, - .conn_request = tcp_nip_conn_request, - .syn_recv_sock = tcp_nip_syn_recv_sock, - .net_header_len = 0, - .net_frag_header_len = 0, - .setsockopt = nip_setsockopt, - .getsockopt = nip_getsockopt, - .addr2sockaddr = NULL, - .sockaddr_len = sizeof(struct sockaddr_nin), - - .mtu_reduced = NULL, + .queue_xmit = tcp_nip_queue_xmit, + .send_check = tcp_nip_send_check, + .rebuild_header = tcp_nip_rebuild_header, + .sk_rx_dst_set = ninet_sk_rx_dst_set, + .conn_request = tcp_nip_conn_request, + .syn_recv_sock = tcp_nip_syn_recv_sock, + .net_header_len = 0, + .net_frag_header_len = 0, + .setsockopt = nip_setsockopt, + .getsockopt = nip_getsockopt, + .addr2sockaddr = nip_addr2sockaddr, + .sockaddr_len = sizeof(struct sockaddr_nin), + .mtu_reduced = nip_mtu_reduced, }; #if IS_ENABLED(CONFIG_NEWIP_FAST_KEEPALIVE) @@ -1135,6 +1197,162 @@ static void tcp_sock_priv_init(struct sock *sk) _tcp_sock_priv_init(sk); } +static void nip_icsk_ca_init(struct sock *sk) +{ +} + +static void nip_icsk_ca_release(struct sock *sk) +{ +} + +static u32 nip_icsk_ca_ssthresh(struct sock *sk) +{ + return 0; +} + +static void nip_icsk_ca_cong_avoid(struct sock *sk, u32 ack, u32 acked) +{ +} + +static void nip_icsk_ca_set_state(struct sock *sk, u8 new_state) +{ +} + +static void nip_icsk_ca_cwnd_event(struct sock *sk, enum tcp_ca_event ev) +{ +} + +static void nip_icsk_ca_in_ack_event(struct sock *sk, u32 flags) +{ +} + +static u32 nip_icsk_ca_undo_cwnd(struct sock *sk) +{ + return 0; +} + +static void nip_icsk_ca_pkts_acked(struct sock *sk, const struct ack_sample *sample) +{ +} + +static u32 nip_icsk_ca_min_tso_segs(struct sock *sk) +{ + return 0; +} + +static u32 nip_icsk_ca_sndbuf_expand(struct sock *sk) +{ + return 0; +} + +static void nip_icsk_ca_cong_control(struct sock *sk, const struct rate_sample *rs) +{ +} + +static size_t nip_icsk_ca_get_info(struct sock *sk, u32 ext, int *attr, + union tcp_cc_info *info) +{ + return 0; +} + +static int nip_icsk_ulp_init(struct sock *sk) +{ + return -EINVAL; +} + +static void nip_icsk_ulp_update(struct sock *sk, struct proto *p, + void (*write_space)(struct sock *sk)) +{ +} + +static void nip_icsk_ulp_release(struct sock *sk) +{ +} + +static int nip_icsk_ulp_get_info(const struct sock *sk, struct sk_buff *skb) +{ + return -EINVAL; +} + +static size_t nip_icsk_ulp_get_info_size(const struct sock *sk) +{ + return 0; +} + +static void nip_icsk_ulp_clone(const struct request_sock *req, struct sock *newsk, + const gfp_t priority) +{ +} + +static struct module nip_owner; + +struct tcp_ulp_ops nip_icsk_ulp_ops = { + .init = nip_icsk_ulp_init, + .update = nip_icsk_ulp_update, + .release = nip_icsk_ulp_release, + .get_info = nip_icsk_ulp_get_info, + .get_info_size = nip_icsk_ulp_get_info_size, + .clone = nip_icsk_ulp_clone, + .owner = &nip_owner, +}; + +struct tcp_congestion_ops nip_icsk_ca_ops = { + .init = nip_icsk_ca_init, + .release = nip_icsk_ca_release, + .ssthresh = nip_icsk_ca_ssthresh, + .cong_avoid = nip_icsk_ca_cong_avoid, + .set_state = nip_icsk_ca_set_state, + .cwnd_event = nip_icsk_ca_cwnd_event, + .in_ack_event = nip_icsk_ca_in_ack_event, + .undo_cwnd = nip_icsk_ca_undo_cwnd, + .pkts_acked = nip_icsk_ca_pkts_acked, + .min_tso_segs = nip_icsk_ca_min_tso_segs, + .sndbuf_expand = nip_icsk_ca_sndbuf_expand, + .cong_control = nip_icsk_ca_cong_control, + .get_info = nip_icsk_ca_get_info, +}; + +static void nip_icsk_clean_acked(struct sock *sk, u32 acked_seq) +{ +} + +static void inet_connection_sock_pre_init(struct inet_connection_sock *icsk) +{ + icsk->icsk_ca_ops = &nip_icsk_ca_ops; + icsk->icsk_ulp_ops = &nip_icsk_ulp_ops; + icsk->icsk_clean_acked = nip_icsk_clean_acked; +} + +#ifdef CONFIG_TCP_MD5SIG +struct tcp_md5sig_key *nip_md5_lookup(const struct sock *sk, + const struct sock *addr_sk) +{ + return NULL; +} + +int nip_md5_parse(struct sock *sk, int optname, sockptr_t optval, + int optlen) +{ + return -EINVAL; +} + +const struct tcp_sock_af_ops nip_af_specific = { + .md5_lookup = nip_md5_lookup, + .calc_md5_hash = nip_calc_md5_hash, + .md5_parse = nip_md5_parse, +}; + +struct tcp_md5sig_info __rcu nip_md5sig_info; +#endif + +static void tcp_sock_pre_init(struct tcp_sock *tp) +{ +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &nip_af_specific; + tp->md5sig_info = &nip_md5sig_info; +#endif +} + /* Function * Example Initialize sock information in TCP * Parameter @@ -1153,6 +1371,8 @@ static int tcp_nip_init_sock(struct sock *sk) tcp_nip_init_xmit_timers(sk); INIT_LIST_HEAD(&tp->tsq_node); + inet_connection_sock_pre_init(icsk); + tcp_sock_pre_init(tp); icsk->icsk_rto = get_nip_rto() == 0 ? TCP_TIMEOUT_INIT : (HZ / get_nip_rto()); icsk->icsk_rto_min = TCP_RTO_MIN; icsk->icsk_delack_max = TCP_DELACK_MAX; @@ -1206,13 +1426,15 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, int large_allowed) { struct tcp_sock *tp = tcp_sk(sk); - u32 new_size_goal, size_goal; + u32 new_size_goal = NIP_MIN_MTU; + u32 size_goal; if (!large_allowed || !mss_now) return mss_now; /* Note : tcp_tso_autosize() will eventually split this later */ - new_size_goal = sk->sk_gso_max_size - 1 - MAX_TCP_HEADER; + if (sk->sk_gso_max_size > MAX_TCP_HEADER + 1) + new_size_goal = sk->sk_gso_max_size - 1 - MAX_TCP_HEADER; new_size_goal = tcp_bound_to_half_wnd(tp, new_size_goal); /* We try hard to avoid divides here */ @@ -1352,6 +1574,7 @@ out: do_fault: if (!skb->len) { + tcp_nip_modify_send_head(sk, skb); tcp_unlink_write_queue(skb, sk); sk_wmem_free_skb(sk, skb); } @@ -1703,6 +1926,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 @@ -1713,19 +1956,12 @@ static int tcp_nip_rcv(struct sk_buff *skb) { const struct tcphdr *th; bool refcounted; - struct sock *sk; + struct sock *sk = NULL; int ret; int dif = skb->skb_iif; - if (skb->pkt_type != PACKET_HOST) { - nip_dbg("unknown pkt-type(%u), drop skb", skb->pkt_type); + if (nip_skb_precheck(skb)) goto discard_it; - } - - if (!nip_get_tcp_input_checksum(skb)) { - nip_dbg("checksum fail, drop skb"); - goto discard_it; - } th = (const struct tcphdr *)skb->data; @@ -1733,6 +1969,8 @@ static int tcp_nip_rcv(struct sk_buff *skb) nip_dbg("non-four byte alignment, drop skb"); goto discard_it; } + if (!pskb_may_pull(skb, th->doff * 4)) + goto discard_it; sk = __ninet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source, th->dest, dif, &refcounted); @@ -1814,7 +2052,7 @@ put_and_return: no_tcp_socket: tcp_nip_send_reset(NULL, skb); - goto discard_it; + discard_it: kfree_skb(skb); return 0; @@ -1997,10 +2235,22 @@ struct sock *ninet_csk_accept(struct sock *sk, int flags, int *err, bool kern) return newsk; } +static int tcp_nip_sendpage(struct sock *sk, struct page *page, int offset, size_t size, + int flags) +{ + return -EINVAL; +} + +static int tcp_nip_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + return -EINVAL; +} + struct proto tcp_nip_prot = { .name = "NIP_TCP", .owner = THIS_MODULE, .close = tcp_nip_close, + .pre_connect = tcp_nip_pre_connect, .connect = tcp_nip_connect, .disconnect = tcp_nip_disconnect, .accept = ninet_csk_accept, @@ -2013,7 +2263,7 @@ struct proto tcp_nip_prot = { .keepalive = tcp_set_keepalive, .recvmsg = tcp_nip_recvmsg, .sendmsg = tcp_nip_sendmsg, - .sendpage = NULL, + .sendpage = tcp_nip_sendpage, .backlog_rcv = tcp_nip_do_rcv, .release_cb = tcp_nip_release_cb, .hash = ninet_hash, @@ -2033,10 +2283,17 @@ struct proto tcp_nip_prot = { .no_autobind = true, }; +static void tcp_nip_err_handler(struct sk_buff *skb, + struct ninet_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ +} + static const struct ninet_protocol tcp_nip_protocol = { - .early_demux = tcp_nip_early_demux, - .handler = tcp_nip_rcv, - .flags = 0, + .early_demux = tcp_nip_early_demux, + .handler = tcp_nip_rcv, + .err_handler = tcp_nip_err_handler, + .flags = 0, }; static struct inet_protosw tcp_nip_protosw = { diff --git a/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c b/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c index ae554add78ff9e8770bfbee287d1c46e687b2410..f6f97def30f407dc8bce5bde58b4eccbf6631d82 100644 --- a/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c +++ b/newip/third_party/linux-5.10/net/newip/tcp_nip_input.c @@ -817,6 +817,7 @@ static int tcp_nip_clean_rtx_queue(struct sock *sk, ktime_t *skb_snd_tstamp) if (*skb_snd_tstamp == 0) *skb_snd_tstamp = skb->tstamp; + tcp_nip_modify_send_head(sk, skb); tcp_unlink_write_queue(skb, sk); sk_wmem_free_skb(sk, skb); } @@ -1379,7 +1380,8 @@ static void tcp_nip_dup_ack_retrans(struct sock *sk, const struct sk_buff *skb, */ int mss = tcp_nip_current_mss(sk); struct tcphdr *th = (struct tcphdr *)skb->data; - u16 discard_num = htons(th->urg_ptr); + u16 discard_num = htons(th->urg_ptr) > PKT_DISCARD_MAX ? + 0 : htons(th->urg_ptr); u32 last_nip_ssthresh = ntp->nip_ssthresh; if (tp->selective_acks[0].end_seq) @@ -1567,7 +1569,56 @@ static void tcp_nip_ack_calc_ssthresh(struct sock *sk, u32 ack, int icsk_rto_las } } -static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb) +static bool __tcp_nip_oow_rate_limited(struct net *net, int mib_idx, u32 *last_oow_ack_time) +{ + if (*last_oow_ack_time) { + s32 elapsed = (s32)(tcp_jiffies32 - *last_oow_ack_time); + + if (elapsed >= 0 && + elapsed < READ_ONCE(net->ipv4.sysctl_tcp_invalid_ratelimit)) { + NET_INC_STATS(net, mib_idx); + return true; /* rate-limited: don't send yet! */ + } + } + + *last_oow_ack_time = tcp_jiffies32; + + return false; /* not rate-limited: go ahead, send dupack now! */ +} + +static void tcp_nip_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) +{ + /* unprotected vars, we dont care of overwrites */ + static u32 nip_challenge_timestamp; + static unsigned int nip_challenge_count; + struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); + u32 count, now; + + /* First check our per-socket dupack rate limit. */ + if (__tcp_nip_oow_rate_limited(net, + LINUX_MIB_TCPACKSKIPPEDCHALLENGE, + &tp->last_oow_ack_time)) + return; + + /* Then check host-wide RFC 5961 rate limit. */ + now = jiffies / HZ; + if (now != READ_ONCE(nip_challenge_timestamp)) { + u32 ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit); + u32 half = (ack_limit + 1) >> 1; + + WRITE_ONCE(nip_challenge_timestamp, now); + WRITE_ONCE(nip_challenge_count, half + prandom_u32_max(ack_limit)); + } + count = READ_ONCE(nip_challenge_count); + if (count > 0) { + WRITE_ONCE(nip_challenge_count, count - 1); + NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK); + tcp_nip_send_ack(sk); + } +} + +static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb, int flag) { struct tcp_sock *tp = tcp_sk(sk); struct tcp_nip_common *ntp = &tcp_nip_sk(sk)->common; @@ -1578,8 +1629,15 @@ static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb) int prior_packets = tp->packets_out; ktime_t skb_snd_tstamp = 0; - if (before(ack, prior_snd_una)) + if (before(ack, prior_snd_una)) { + if (before(ack, prior_snd_una - tp->max_window)) { + if (!(flag & FLAG_NO_CHALLENGE_ACK)) + tcp_nip_send_challenge_ack(sk, skb); + return -1; + } return 0; + } + if (after(ack, tp->snd_nxt)) return -1; @@ -1730,10 +1788,13 @@ void tcp_nip_rcv_established(struct sock *sk, struct sk_buff *skb, if (unlikely(!rcu_access_pointer(sk->sk_rx_dst))) inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb); + if (skb->len < (th->doff << 2)) + return; + if (!tcp_nip_validate_incoming(sk, skb, th, 1)) return; - if (tcp_nip_ack(sk, skb) < 0) + if (tcp_nip_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0) goto discard; tcp_nip_data_queue(sk, skb); @@ -1863,7 +1924,7 @@ static int tcp_nip_rcv_synsent_state_process(struct sock *sk, struct sk_buff *sk tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); - tcp_nip_ack(sk, skb); + tcp_nip_ack(sk, skb, FLAG_SLOWPATH); tp->out_of_order_queue = RB_ROOT; /* The next data number expected to be accepted is +1 */ tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; @@ -1992,7 +2053,9 @@ int tcp_nip_rcv_state_process(struct sock *sk, struct sk_buff *skb) if (!tcp_nip_validate_incoming(sk, skb, th, 0)) return 0; - acceptable = tcp_nip_ack(sk, skb); + acceptable = tcp_nip_ack(sk, skb, FLAG_SLOWPATH | + FLAG_UPDATE_TS_RECENT | + FLAG_NO_CHALLENGE_ACK) > 0; /* If the third handshake ACK is invalid, 1 is returned * and the SKB is discarded in tcp_nip_rcv */ 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..7add3ad3ef753a1e821432055bc5dd7da5d01864 100644 --- a/newip/third_party/linux-5.10/net/newip/udp.c +++ b/newip/third_party/linux-5.10/net/newip/udp.c @@ -231,6 +231,7 @@ struct sock *__nip_udp_lib_lookup(struct net *net, struct udp_hslot *hslot2; struct sock *result; + /* mask ensures that the hash index is valid without memory overruns */ hash2 = nip_udp_portaddr_hash(net, daddr, hnum); slot2 = hash2 & udptable->mask; hslot2 = &udptable->hash2[slot2]; @@ -243,6 +244,7 @@ struct sock *__nip_udp_lib_lookup(struct net *net, goto done; /* Lookup wildcard sockets */ + /* mask ensures that the hash index is valid without memory overruns */ hash2 = nip_udp_portaddr_hash(net, &nip_any_addr, hnum); slot2 = hash2 & udptable->mask; hslot2 = &udptable->hash2[slot2]; @@ -362,13 +364,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 +394,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; } @@ -481,34 +496,68 @@ int nip_udp_getsockopt(struct sock *sk, int level, return nip_getsockopt(sk, level, optname, optval, optlen); } +int nip_udp_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + return -EINVAL; +} + +int nip_udp_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) +{ + return -EINVAL; +} + +int nip_udp_sendpage(struct sock *sk, struct page *page, int offset, + size_t size, int flags) +{ + return -EINVAL; +} + +void nip_udp_datagram_release_cb(struct sock *sk) +{ +} + +void udp_nip_rehash(struct sock *sk) +{ +} + +void nip_udp_early_demux(struct sk_buff *skb) +{ +} + static const struct ninet_protocol nip_udp_protocol = { - .handler = nip_udp_input, - .err_handler = nip_udp_err, - .flags = 0, + .handler = nip_udp_input, + .err_handler = nip_udp_err, + .early_demux = nip_udp_early_demux, + .flags = 0, }; /* Newip Udp related operations */ struct proto nip_udp_prot = { - .name = "nip_udp", - .owner = THIS_MODULE, - .close = udp_lib_close, - .disconnect = udp_disconnect, - .ioctl = udp_ioctl, - .init = udp_init_sock, - .destroy = nip_udp_destroy_sock, - .setsockopt = nip_udp_setsockopt, - .getsockopt = nip_udp_getsockopt, - .sendmsg = nip_udp_output, - .recvmsg = nip_udp_recvmsg, - .backlog_rcv = __nip_udp_queue_rcv_skb, - .hash = udp_lib_hash, - .unhash = udp_lib_unhash, - .get_port = nip_udp_get_port, - .memory_allocated = &udp_memory_allocated, - .sysctl_mem = sysctl_udp_mem, - .obj_size = sizeof(struct nip_udp_sock), - .h.udp_table = &udp_table, - .diag_destroy = udp_abort, + .name = "nip_udp", + .owner = THIS_MODULE, + .close = udp_lib_close, + .pre_connect = nip_udp_pre_connect, + .connect = nip_udp_datagram_connect, + .disconnect = udp_disconnect, + .ioctl = udp_ioctl, + .init = udp_init_sock, + .destroy = nip_udp_destroy_sock, + .setsockopt = nip_udp_setsockopt, + .getsockopt = nip_udp_getsockopt, + .sendmsg = nip_udp_output, + .recvmsg = nip_udp_recvmsg, + .sendpage = nip_udp_sendpage, + .release_cb = nip_udp_datagram_release_cb, + .backlog_rcv = __nip_udp_queue_rcv_skb, + .hash = udp_lib_hash, + .unhash = udp_lib_unhash, + .rehash = udp_nip_rehash, + .get_port = nip_udp_get_port, + .memory_allocated = &udp_memory_allocated, + .sysctl_mem = sysctl_udp_mem, + .obj_size = sizeof(struct nip_udp_sock), + .h.udp_table = &udp_table, + .diag_destroy = udp_abort, }; /* Example Create newip socket information */