[RHEL8,COMMIT] netlink: add an option to set sk->err from userspace

Submitted by Konstantin Khorenko on Dec. 21, 2020, 3:51 p.m.

Details

Message ID 202012211551.0BLFpVHS226514@finist-co8.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Konstantin Khorenko Dec. 21, 2020, 3:51 p.m.
The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.3
------>
commit 1855f8f5de8bcdeaa58557cdcbfc52e11f970936
Author: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
Date:   Mon Dec 21 18:51:31 2020 +0300

    netlink: add an option to set sk->err from userspace
    
    Sometimes during dump criu can encounter sockets with overflown kernel
    buffer, which results in ENOBUFS error during next read.
    We need a reliable way to restore sk->sk_err.
    
    https://jira.sw.ru/browse/PSBM-120976
    
    Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
---
 include/uapi/linux/netlink.h |  1 +
 net/netlink/af_netlink.c     | 10 ++++++++++
 2 files changed, 11 insertions(+)

Patch hide | download patch | download mbox

diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index 67ea114f19a4..4360186183d4 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -157,6 +157,7 @@  enum nlmsgerr_attrs {
 #define NETLINK_EXT_ACK			11
 #define NETLINK_GET_STRICT_CHK		12
 #define NETLINK_REPAIR			127
+#define NETLINK_SETERR			128
 
 struct nl_pktinfo {
 	__u32	group;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 9889446b9653..4f06946c9923 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1685,6 +1685,16 @@  static int netlink_setsockopt(struct socket *sock, int level, int optname,
 			nlk->flags &= ~NETLINK_F_REPAIR;
 		err = 0;
 		break;
+	case NETLINK_SETERR:
+		err = -ENOPROTOOPT;
+		if (nlk->flags & NETLINK_F_REPAIR) {
+			if (!val || val > MAX_ERRNO)
+				return -EINVAL;
+			sk->sk_err = val;
+			sk->sk_error_report(sk);
+			err = 0;
+		}
+		break;
 	case NETLINK_PKTINFO:
 		if (val)
 			nlk->flags |= NETLINK_F_RECV_PKTINFO;