mirror of
https://github.com/openharmony/kernel_linux_common_modules.git
synced 2026-08-26 17:16:37 -04:00
!40 NewIP code security issue remediation
Merge pull request !40 from liangbotong/master
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
niph->include_ttl = 1;
|
||||
if (nbuf->remaining_len < sizeof(niph->ttl))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
return sizeof(niph->ttl);
|
||||
niph->ttl = *nbuf->data;
|
||||
niph->include_ttl = 1;
|
||||
nip_buff_pull(nbuf, 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;
|
||||
niph->include_nexthdr = 1;
|
||||
if (nbuf->remaining_len < sizeof(niph->nexthdr))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
return sizeof(niph->nexthdr);
|
||||
niph->nexthdr = *nbuf->data;
|
||||
niph->include_nexthdr = 1;
|
||||
nip_buff_pull(nbuf, 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;
|
||||
err = _get_nip_total_len(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
len = _get_nip_hdr_nexthdr(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_nexthdr(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
len = _get_nip_hdr_daddr(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_daddr(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
len = _get_nip_hdr_saddr(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_saddr(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return len_total;
|
||||
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)
|
||||
nbuf.data = rcv_buf;
|
||||
if (!nbuf.data)
|
||||
return 0;
|
||||
|
||||
nbuf.remaining_len = buf_len;
|
||||
num = _get_nip_hdr_bitmap(&nbuf, bitmap, BITMAP_MAX);
|
||||
if (num <= 0)
|
||||
return num;
|
||||
|
||||
niph->hdr_real_len = num * sizeof(bitmap[0]);
|
||||
buf += niph->hdr_real_len;
|
||||
|
||||
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;
|
||||
|
||||
+2
-3
@@ -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);
|
||||
|
||||
+9
-2
@@ -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:
|
||||
|
||||
+5
-8
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+41
-6
@@ -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;
|
||||
|
||||
p = decode_nip_addr(p, &addr);
|
||||
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(&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)) {
|
||||
|
||||
+27
-17
@@ -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);
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+17
-4
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user