aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/ppp/patches/144-pppd-Retry-registering-interface-when-on-rtnetlink-E.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/network/services/ppp/patches/144-pppd-Retry-registering-interface-when-on-rtnetlink-E.patch')
-rw-r--r--package/network/services/ppp/patches/144-pppd-Retry-registering-interface-when-on-rtnetlink-E.patch218
1 files changed, 218 insertions, 0 deletions
diff --git a/package/network/services/ppp/patches/144-pppd-Retry-registering-interface-when-on-rtnetlink-E.patch b/package/network/services/ppp/patches/144-pppd-Retry-registering-interface-when-on-rtnetlink-E.patch
new file mode 100644
index 00000000000..26c1e34683a
--- /dev/null
+++ b/package/network/services/ppp/patches/144-pppd-Retry-registering-interface-when-on-rtnetlink-E.patch
@@ -0,0 +1,218 @@
+From 089687fbcc6524809ae9f4b2f8145fe3c2a91147 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Sat, 7 Aug 2021 19:48:01 +0200
+Subject: [PATCH] pppd: Retry registering interface when on rtnetlink -EBUSY
+ error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Due to workaround in kernel module ppp_generic.ko in function
+ppp_nl_newlink(), kernel may return -EBUSY error to prevent possible
+mutex deadlock. In this case userspace needs to retry its request.
+
+Proper way would be to fix kernel module to order requests and mutex
+locking, so prevent deadlock in kernel and so never return this error to
+userspace. Until it happens we need retry code in userspace.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+[ backport to ppp 2.4.9 ]
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ pppd/sys-linux.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/pppd/sys-linux.c
++++ b/pppd/sys-linux.c
+@@ -707,99 +707,101 @@ static int make_ppp_unit_rtnetlink(void)
+ int one;
+ int fd;
+
+- fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+- if (fd < 0) {
+- error("make_ppp_unit_rtnetlink: socket(NETLINK_ROUTE): %m (line %d)", __LINE__);
+- return 0;
+- }
+-
+- /* Tell kernel to not send to us payload of acknowledgment error message. */
+- one = 1;
+- setsockopt(fd, SOL_NETLINK, NETLINK_CAP_ACK, &one, sizeof(one));
++ do {
++ fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
++ if (fd < 0) {
++ error("make_ppp_unit_rtnetlink: socket(NETLINK_ROUTE): %m (line %d)", __LINE__);
++ return 0;
++ }
++
++ /* Tell kernel to not send to us payload of acknowledgment error message. */
++ one = 1;
++ setsockopt(fd, SOL_NETLINK, NETLINK_CAP_ACK, &one, sizeof(one));
++
++ memset(&nladdr, 0, sizeof(nladdr));
++ nladdr.nl_family = AF_NETLINK;
++
++ if (bind(fd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) {
++ error("make_ppp_unit_rtnetlink: bind(AF_NETLINK): %m (line %d)", __LINE__);
++ close(fd);
++ return 0;
++ }
++
++ memset(&nlreq, 0, sizeof(nlreq));
++ nlreq.nlh.nlmsg_len = sizeof(nlreq);
++ nlreq.nlh.nlmsg_type = RTM_NEWLINK;
++ nlreq.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
++ nlreq.ifm.ifi_family = AF_UNSPEC;
++ nlreq.ifm.ifi_type = ARPHRD_NETROM;
++ nlreq.ifn.rta.rta_len = sizeof(nlreq.ifn);
++ nlreq.ifn.rta.rta_type = IFLA_IFNAME;
++ strlcpy(nlreq.ifn.ifname, req_ifname, sizeof(nlreq.ifn.ifname));
++ nlreq.ifli.rta.rta_len = sizeof(nlreq.ifli);
++ nlreq.ifli.rta.rta_type = IFLA_LINKINFO;
++ nlreq.ifli.ifik.rta.rta_len = sizeof(nlreq.ifli.ifik);
++ nlreq.ifli.ifik.rta.rta_type = IFLA_INFO_KIND;
++ strcpy(nlreq.ifli.ifik.ifkind, "ppp");
++ nlreq.ifli.ifid.rta.rta_len = sizeof(nlreq.ifli.ifid);
++ nlreq.ifli.ifid.rta.rta_type = IFLA_INFO_DATA;
++ nlreq.ifli.ifid.ifdata[0].rta.rta_len = sizeof(nlreq.ifli.ifid.ifdata[0]);
++ nlreq.ifli.ifid.ifdata[0].rta.rta_type = IFLA_PPP_DEV_FD;
++ nlreq.ifli.ifid.ifdata[0].ppp.ppp_dev_fd = ppp_dev_fd;
++
++ memset(&nladdr, 0, sizeof(nladdr));
++ nladdr.nl_family = AF_NETLINK;
++
++ memset(&iov, 0, sizeof(iov));
++ iov.iov_base = &nlreq;
++ iov.iov_len = sizeof(nlreq);
++
++ memset(&msg, 0, sizeof(msg));
++ msg.msg_name = &nladdr;
++ msg.msg_namelen = sizeof(nladdr);
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++
++ if (sendmsg(fd, &msg, 0) < 0) {
++ error("make_ppp_unit_rtnetlink: sendmsg(RTM_NEWLINK/NLM_F_CREATE): %m (line %d)", __LINE__);
++ close(fd);
++ return 0;
++ }
++
++ memset(&iov, 0, sizeof(iov));
++ iov.iov_base = &nlresp;
++ iov.iov_len = sizeof(nlresp);
++
++ memset(&msg, 0, sizeof(msg));
++ msg.msg_name = &nladdr;
++ msg.msg_namelen = sizeof(nladdr);
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++
++ nlresplen = recvmsg(fd, &msg, 0);
++
++ if (nlresplen < 0) {
++ error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): %m (line %d)", __LINE__);
++ close(fd);
++ return 0;
++ }
+
+- memset(&nladdr, 0, sizeof(nladdr));
+- nladdr.nl_family = AF_NETLINK;
+-
+- if (bind(fd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) {
+- error("make_ppp_unit_rtnetlink: bind(AF_NETLINK): %m (line %d)", __LINE__);
+ close(fd);
+- return 0;
+- }
+-
+- memset(&nlreq, 0, sizeof(nlreq));
+- nlreq.nlh.nlmsg_len = sizeof(nlreq);
+- nlreq.nlh.nlmsg_type = RTM_NEWLINK;
+- nlreq.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
+- nlreq.ifm.ifi_family = AF_UNSPEC;
+- nlreq.ifm.ifi_type = ARPHRD_NETROM;
+- nlreq.ifn.rta.rta_len = sizeof(nlreq.ifn);
+- nlreq.ifn.rta.rta_type = IFLA_IFNAME;
+- strlcpy(nlreq.ifn.ifname, req_ifname, sizeof(nlreq.ifn.ifname));
+- nlreq.ifli.rta.rta_len = sizeof(nlreq.ifli);
+- nlreq.ifli.rta.rta_type = IFLA_LINKINFO;
+- nlreq.ifli.ifik.rta.rta_len = sizeof(nlreq.ifli.ifik);
+- nlreq.ifli.ifik.rta.rta_type = IFLA_INFO_KIND;
+- strcpy(nlreq.ifli.ifik.ifkind, "ppp");
+- nlreq.ifli.ifid.rta.rta_len = sizeof(nlreq.ifli.ifid);
+- nlreq.ifli.ifid.rta.rta_type = IFLA_INFO_DATA;
+- nlreq.ifli.ifid.ifdata[0].rta.rta_len = sizeof(nlreq.ifli.ifid.ifdata[0]);
+- nlreq.ifli.ifid.ifdata[0].rta.rta_type = IFLA_PPP_DEV_FD;
+- nlreq.ifli.ifid.ifdata[0].ppp.ppp_dev_fd = ppp_dev_fd;
+-
+- memset(&nladdr, 0, sizeof(nladdr));
+- nladdr.nl_family = AF_NETLINK;
+-
+- memset(&iov, 0, sizeof(iov));
+- iov.iov_base = &nlreq;
+- iov.iov_len = sizeof(nlreq);
+-
+- memset(&msg, 0, sizeof(msg));
+- msg.msg_name = &nladdr;
+- msg.msg_namelen = sizeof(nladdr);
+- msg.msg_iov = &iov;
+- msg.msg_iovlen = 1;
+-
+- if (sendmsg(fd, &msg, 0) < 0) {
+- error("make_ppp_unit_rtnetlink: sendmsg(RTM_NEWLINK/NLM_F_CREATE): %m (line %d)", __LINE__);
+- close(fd);
+- return 0;
+- }
+-
+- memset(&iov, 0, sizeof(iov));
+- iov.iov_base = &nlresp;
+- iov.iov_len = sizeof(nlresp);
+-
+- memset(&msg, 0, sizeof(msg));
+- msg.msg_name = &nladdr;
+- msg.msg_namelen = sizeof(nladdr);
+- msg.msg_iov = &iov;
+- msg.msg_iovlen = 1;
+-
+- nlresplen = recvmsg(fd, &msg, 0);
+-
+- if (nlresplen < 0) {
+- error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): %m (line %d)", __LINE__);
+- close(fd);
+- return 0;
+- }
+-
+- close(fd);
+
+- if (nladdr.nl_family != AF_NETLINK) {
+- error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): Not a netlink packet (line %d)", __LINE__);
+- return 0;
+- }
+-
+- if ((size_t)nlresplen < sizeof(nlresp) || nlresp.nlh.nlmsg_len < sizeof(nlresp)) {
+- error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): Acknowledgment netlink packet too short (line %d)", __LINE__);
+- return 0;
+- }
+-
+- /* acknowledgment packet for NLM_F_ACK is NLMSG_ERROR */
+- if (nlresp.nlh.nlmsg_type != NLMSG_ERROR) {
+- error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): Not an acknowledgment netlink packet (line %d)", __LINE__);
+- return 0;
+- }
++ if (nladdr.nl_family != AF_NETLINK) {
++ error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): Not a netlink packet (line %d)", __LINE__);
++ return 0;
++ }
++
++ if ((size_t)nlresplen < sizeof(nlresp) || nlresp.nlh.nlmsg_len < sizeof(nlresp)) {
++ error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): Acknowledgment netlink packet too short (line %d)", __LINE__);
++ return 0;
++ }
++
++ /* acknowledgment packet for NLM_F_ACK is NLMSG_ERROR */
++ if (nlresp.nlh.nlmsg_type != NLMSG_ERROR) {
++ error("make_ppp_unit_rtnetlink: recvmsg(NLM_F_ACK): Not an acknowledgment netlink packet (line %d)", __LINE__);
++ return 0;
++ }
++ } while (nlresp.nlerr.error == -EBUSY);
+
+ /* error == 0 indicates success, negative value is errno code */
+ if (nlresp.nlerr.error != 0) {