[Devel] [PATCH RH9 4/5] netlink: add an ability to restore messages in a receive queue
Cyrill Gorcunov
gorcunov at gmail.com
Tue Oct 5 20:54:49 MSK 2021
From: Andrey Vagin <avagin at openvz.org>
This patch adds an repair mode for netlink sockets. sendmsg queues
messages into a receive queue if a socket is in the repair mode.
https://jira.sw.ru/browse/PSBM-28386
Signed-off-by: Andrey Vagin <avagin at virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
https://jira.sw.ru/browse/PSBM-101289
vz7 commit: 2f8d39b73cfca ("netlink: add an ability to restore messages in a
receive queue")
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
+++
netlink: protect NETLINK_REPAIR
Prevent using netlink repair mode from containers.
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
---
include/uapi/linux/netlink.h | 1 +
net/netlink/af_netlink.c | 56 ++++++++++++++++++++++++++----------
net/netlink/af_netlink.h | 2 ++
3 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index 4c0cde075c27..cdab1c041913 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -159,6 +159,7 @@ enum nlmsgerr_attrs {
#define NETLINK_CAP_ACK 10
#define NETLINK_EXT_ACK 11
#define NETLINK_GET_STRICT_CHK 12
+#define NETLINK_REPAIR 127
struct nl_pktinfo {
__u32 group;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 6042bbc8c560..7eadbb5f01c4 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1343,6 +1343,7 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb,
int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
u32 portid, int nonblock)
{
+ struct netlink_sock *nlk = nlk_sk(ssk);
struct sock *sk;
int err;
long timeo;
@@ -1351,19 +1352,24 @@ int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
timeo = sock_sndtimeo(ssk, nonblock);
retry:
- sk = netlink_getsockbyportid(ssk, portid);
- if (IS_ERR(sk)) {
- kfree_skb(skb);
- return PTR_ERR(sk);
- }
- if (netlink_is_kernel(sk))
- return netlink_unicast_kernel(sk, skb, ssk);
+ if (nlk->flags & NETLINK_F_REPAIR) {
+ sk = ssk;
+ sock_hold(sk);
+ } else {
+ sk = netlink_getsockbyportid(ssk, portid);
+ if (IS_ERR(sk)) {
+ kfree_skb(skb);
+ return PTR_ERR(sk);
+ }
+ if (netlink_is_kernel(sk))
+ return netlink_unicast_kernel(sk, skb, ssk);
- if (sk_filter(sk, skb)) {
- err = skb->len;
- kfree_skb(skb);
- sock_put(sk);
- return err;
+ if (sk_filter(sk, skb)) {
+ err = skb->len;
+ kfree_skb(skb);
+ sock_put(sk);
+ return err;
+ }
}
err = netlink_attachskb(sk, skb, &timeo, ssk);
@@ -1666,6 +1672,20 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
return -EFAULT;
switch (optname) {
+ case NETLINK_REPAIR:
+#ifdef CONFIG_VE
+ {
+ struct ve_struct *ve = get_exec_env();
+ if (!ve_is_super(ve) && !ve->is_pseudosuper)
+ return -ENOPROTOOPT;
+ }
+#endif
+ if (val)
+ nlk->flags |= NETLINK_F_REPAIR;
+ else
+ nlk->flags &= ~NETLINK_F_REPAIR;
+ err = 0;
+ break;
case NETLINK_PKTINFO:
if (val)
nlk->flags |= NETLINK_F_RECV_PKTINFO;
@@ -1882,6 +1902,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
int err;
struct scm_cookie scm;
u32 netlink_skb_flags = 0;
+ bool repair = nlk->flags & NETLINK_F_REPAIR;
if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP;
@@ -1900,7 +1921,8 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
dst_group = ffs(addr->nl_groups);
err = -EPERM;
if ((dst_group || dst_portid) &&
- !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
+ !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND &&
+ !repair))
goto out;
netlink_skb_flags |= NETLINK_SKB_DST;
} else {
@@ -1925,7 +1947,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
if (skb == NULL)
goto out;
- NETLINK_CB(skb).portid = nlk->portid;
+ if (unlikely(repair))
+ NETLINK_CB(skb).portid = dst_portid;
+ else
+ NETLINK_CB(skb).portid = nlk->portid;
+
NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).creds = scm.creds;
NETLINK_CB(skb).flags = netlink_skb_flags;
@@ -1942,7 +1968,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
goto out;
}
- if (dst_group) {
+ if (dst_group && !repair) {
refcount_inc(&skb->users);
netlink_broadcast(sk, skb, dst_portid, dst_group, GFP_KERNEL);
}
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index 5f454c8de6a4..7e82297fdd8c 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -17,6 +17,8 @@
#define NETLINK_F_EXT_ACK 0x40
#define NETLINK_F_STRICT_CHK 0x80
+#define NETLINK_F_REPAIR 0x80000000
+
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
#define NLGRPLONGS(x) (NLGRPSZ(x)/sizeof(unsigned long))
--
2.31.1
More information about the Devel
mailing list