From b0e0d8b626fe63961c8d4789d3ee5ef1abfc77d7 Mon Sep 17 00:00:00 2001 From: liangbotong Date: Fri, 26 May 2023 10:23:30 +0800 Subject: [PATCH 1/2] add annotating code for NewIp vendor hooks Signed-off-by: liangbotong --- newip/src/linux-5.10/net/newip/nip_hooks_register.c | 6 ++++++ 1 file changed, 6 insertions(+) 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 46b9bc0..0541c45 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 @@ -17,12 +17,18 @@ #include #include "tcp_nip_parameter.h" +/* call the newip hook function in sk_ehashfn function (net\ipv4\inet_hashtables.c): + * if trace_vendor_ninet_ehashfn_enabled() then call trace_vendor_ninet_ehashfn function. + */ void vendor_ninet_ehashfn(void *data, const struct sock *sk, u32 *ret) { *ret = ninet_ehashfn(sock_net(sk), &sk->sk_nip_rcv_saddr, sk->sk_num, &sk->sk_nip_daddr, sk->sk_dport); } +/* call the newip hook function in inet_gifconf function (net\ipv4\devinet.c): + * call the newip trace_vendor_ninet_gifconf function after the IPv4 process. + */ void vendor_ninet_gifconf(void *data, struct net_device *dev, char __user *buf, int len, int size, int *ret) { -- Gitee From 415578aa24b161ff4ff99e973e1eec8c96c491c7 Mon Sep 17 00:00:00 2001 From: liangbotong Date: Mon, 29 May 2023 14:36:49 +0800 Subject: [PATCH 2/2] adjust the NewIP ioctl entry avoiding memory leaks caused by CAP_NET_ADMIN Signed-off-by: liangbotong --- newip/src/common/nip_addr.c | 18 ++++++ newip/src/common/nip_addr.h | 1 + .../linux-5.10/include/net/if_ninet.h | 3 + .../linux-5.10/include/net/tcp_nip.h | 2 +- .../linux-5.10/net/newip/af_ninet.c | 63 +++++++++++++++++++ .../linux-5.10/net/newip/nip_addrconf.c | 5 -- .../third_party/linux-5.10/net/newip/route.c | 5 -- newip/third_party/linux-5.10/net/newip/udp.c | 12 +++- 8 files changed, 97 insertions(+), 12 deletions(-) diff --git a/newip/src/common/nip_addr.c b/newip/src/common/nip_addr.c index 32bc360..03f9e82 100644 --- a/newip/src/common/nip_addr.c +++ b/newip/src/common/nip_addr.c @@ -26,6 +26,12 @@ const struct nip_addr nip_broadcast_addr_arp = { .nip_addr_field8[1] = 0x04, }; +static const struct nip_addr nip_local_addr = { + .bitlen = NIP_ADDR_BIT_LEN_16, + .nip_addr_field8[0] = 0xFF, /* 0xFF00 addr, big-endian */ + .nip_addr_field8[1] = 0x00, +}; + enum addr_check_ret { NOT_CURRENT_ADDR = -1, CURRENT_ADDR_VALID = 0, @@ -122,6 +128,18 @@ static inline int is_public_addr_flag(unsigned char first_byte) return first_byte == ADDR_FIRST_FF ? NIP_TRUE : NIP_FALSE; } +int is_nip_local_addr(const struct nip_addr *ad) +{ + int result = 0; + + if (ad->bitlen == NIP_ADDR_BIT_LEN_16) { + if (ad->nip_addr_field16[0] == nip_local_addr.nip_addr_field16[0] && + ad->nip_addr_field16[1] == nip_local_addr.nip_addr_field16[1]) + result = 1; + } + return result; +} + /* Short address range: * 【1-byte】0 ~ 220 * 00 ~ DC diff --git a/newip/src/common/nip_addr.h b/newip/src/common/nip_addr.h index 5ae1425..3d9f21d 100644 --- a/newip/src/common/nip_addr.h +++ b/newip/src/common/nip_addr.h @@ -115,6 +115,7 @@ int nip_addr_any(const struct nip_addr *ad); 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); +int is_nip_local_addr(const struct nip_addr *addr); #endif /* _UAPI_NEWIP_ADDR_H */ diff --git a/newip/third_party/linux-5.10/include/net/if_ninet.h b/newip/third_party/linux-5.10/include/net/if_ninet.h index d0d99ad..21c4498 100644 --- a/newip/third_party/linux-5.10/include/net/if_ninet.h +++ b/newip/third_party/linux-5.10/include/net/if_ninet.h @@ -12,6 +12,8 @@ #include +#define NIP_IOCTL_FLAG_INVALID 35 + enum { NINET_IFADDR_STATE_NEW, NINET_IFADDR_STATE_DEAD, @@ -62,5 +64,6 @@ struct ninet_dev { }; int ninet_gifconf(struct net_device *dev, char __user *buf, int len, int size); +int ninet_ioctl_cmd(struct socket *sock, const struct iovec *iov); #endif 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 a70379b..dfd38a7 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 @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Based on include/net/tcp.h + * Based on include/net/tcp.h * Authors: Ross Biro * Fred N. van Kempen, * diff --git a/newip/third_party/linux-5.10/net/newip/af_ninet.c b/newip/third_party/linux-5.10/net/newip/af_ninet.c index 05aa1ce..5718b1c 100644 --- a/newip/third_party/linux-5.10/net/newip/af_ninet.c +++ b/newip/third_party/linux-5.10/net/newip/af_ninet.c @@ -57,6 +57,10 @@ #endif #include "tcp_nip_parameter.h" +#define NINET_IOCTL_FLAG_LEN 8 +#define NINET_IOCTL_HEAD_LEN 12 +#define NINET_IOCTL_FLAG_VALUE {0xea, 0xdd, 0xea, 0xdd, 0xea, 0xdd, 0xea, 0xdd} + MODULE_DESCRIPTION("NewIP protocol stack"); /* The inetsw_nip table contains everything that ninet_create needs to @@ -507,8 +511,67 @@ int ninet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } } EXPORT_SYMBOL_GPL(ninet_compat_ioctl); + +static int compat_select_ninet_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg, int arglen) +{ + switch (cmd) { + case SIOCADDRT: + case SIOCDELRT: + if (sizeof(struct nip_rtmsg) != arglen) { + void __user *argp = compat_ptr(arg); + struct sock *sk = sock->sk; + + return ninet_compat_routing_ioctl(sk, cmd, argp); + } + return ninet_ioctl(sock, cmd, arg); + default: + return ninet_ioctl(sock, cmd, arg); + } +} #endif /* CONFIG_COMPAT */ +static int __ninet_ioctl_cmd(struct socket *sock, unsigned int cmd, + void __user *iov_base, __kernel_size_t iov_len) +{ + unsigned long arg = (unsigned long)(iov_base + NINET_IOCTL_HEAD_LEN); +#ifdef CONFIG_COMPAT + int arglen = iov_len - NINET_IOCTL_HEAD_LEN; + + return compat_select_ninet_ioctl(sock, cmd, arg, arglen); +#else + return ninet_ioctl(sock, cmd, arg); +#endif +} + +int ninet_ioctl_cmd(struct socket *sock, const struct iovec *iov) +{ + char ioctl_flag[NINET_IOCTL_FLAG_LEN] = NINET_IOCTL_FLAG_VALUE; + char ioctl_head[NINET_IOCTL_HEAD_LEN]; + int i; + unsigned int cmd; + + if (!iov || !iov->iov_base || !sock || + iov->iov_len < NINET_IOCTL_HEAD_LEN) { + nip_dbg("invalid parameter"); + return -NIP_IOCTL_FLAG_INVALID; + } + + if (copy_from_user(ioctl_head, (void __user *)iov->iov_base, NINET_IOCTL_HEAD_LEN)) { + nip_dbg("fail to copy ioctl head"); + return -NIP_IOCTL_FLAG_INVALID; + } + + for (i = 0; i < NINET_IOCTL_FLAG_LEN; i++) { + if (ioctl_head[i] != ioctl_flag[i]) { + nip_dbg("not ninet ioctl cmd"); + return -NIP_IOCTL_FLAG_INVALID; + } + } + cmd = *(unsigned int *)(ioctl_head + NINET_IOCTL_FLAG_LEN); + return __ninet_ioctl_cmd(sock, cmd, iov->iov_base, iov->iov_len); +} + /* register new IP socket */ const struct proto_ops ninet_dgram_ops = { .family = PF_NINET, diff --git a/newip/third_party/linux-5.10/net/newip/nip_addrconf.c b/newip/third_party/linux-5.10/net/newip/nip_addrconf.c index 231cf69..043cf03 100644 --- a/newip/third_party/linux-5.10/net/newip/nip_addrconf.c +++ b/newip/third_party/linux-5.10/net/newip/nip_addrconf.c @@ -417,11 +417,6 @@ static int ninet_addr_del(struct net *net, int ifindex, u32 ifa_flags, int nip_addrconf_ifaddr_check(struct net *net, void __user *arg, struct nip_ifreq *ireq) { - if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) { - nip_dbg("not admin can`t cfg"); - return -EPERM; - } - if (copy_from_user(ireq, arg, sizeof(struct nip_ifreq))) { nip_dbg("fail to copy cfg data"); return -EFAULT; diff --git a/newip/third_party/linux-5.10/net/newip/route.c b/newip/third_party/linux-5.10/net/newip/route.c index c10b32a..d98c9ab 100644 --- a/newip/third_party/linux-5.10/net/newip/route.c +++ b/newip/third_party/linux-5.10/net/newip/route.c @@ -656,11 +656,6 @@ int nip_route_ioctl(struct net *net, unsigned int cmd, struct nip_rtmsg *rtmsg) struct nip_fib_config cfg; int err; - if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) { - nip_dbg("not admin can`t cfg"); - return -EPERM; - } - rtmsg_to_fibni_config(net, rtmsg, &cfg); if (nip_addr_invalid(&cfg.fc_dst)) { nip_dbg("nip daddr invalid, bitlen=%u", cfg.fc_dst.bitlen); 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 899f65f..b2619a9 100644 --- a/newip/third_party/linux-5.10/net/newip/udp.c +++ b/newip/third_party/linux-5.10/net/newip/udp.c @@ -398,7 +398,7 @@ int nip_udp_output(struct sock *sk, struct msghdr *msg, size_t len) struct flow_nip fln; u_short sport, dport; struct dst_entry *dst; - int err = 0; + int err; struct inet_sock *inet; if (!sin) @@ -415,6 +415,16 @@ int nip_udp_output(struct sock *sk, struct msghdr *msg, size_t len) nip_dbg("sin_addr false"); return -EFAULT; } + if (is_nip_local_addr(&sin->sin_addr)) { + err = ninet_ioctl_cmd(sk->sk_socket, msg->msg_iter.iov); + if (!err) { + nip_dbg("ninet_ioctl_cmd succeed"); + return err; + } else if (err != -NIP_IOCTL_FLAG_INVALID) { + nip_dbg("ninet_ioctl_cmd failed"); + return err; + } + } inet = inet_sk(sk); /* Destination address, port (network order) must be specified when sendto */ -- Gitee