diff options
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.patch | 218 |
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) { |
