Some checks failed
Build Kernel / Build all affected Kernels (push) Has been cancelled
Build all core packages / Build all core packages for selected target (push) Has been cancelled
Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
Build Toolchains / Build Toolchains for each target (push) Has been cancelled
Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
Coverity scan build / Coverity x86/64 build (push) Has been cancelled
219 lines
8.0 KiB
Diff
219 lines
8.0 KiB
Diff
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) {
|