mirror of
https://github.com/openharmony/kernel_linux_common_modules.git
synced 2026-08-27 01:31:36 -04:00
adjust the NewIP ioctl entry
avoiding memory leaks caused by CAP_NET_ADMIN Signed-off-by: liangbotong <liangbotong@huawei.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <linux/nip.h>
|
||||
|
||||
#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
|
||||
|
||||
+1
-1
@@ -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, <waltje@uWalt.NL.Mugnet.ORG>
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
+11
-1
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user