Browse code

core: work around interface enum buffer overrun

When a system has too many interfaces and too many addresses,
8 kilobytes isn't enough to fit all of the netlink responses.
As the result, kamailio gets stuck in a loop where it tries
to do a 0-length recv.

Increase the buffer to 32K. It's a miniscule amount for modern
times anyway. Also, add diagnostics to make further troubleshooting
easier.

Proper fix would be to switch to libnl here, which would make a
good weekend project.

Paul Komkoff authored on 04/01/2021 14:13:28
Showing 1 changed files
... ...
@@ -1070,6 +1070,7 @@ error:
1070 1070
 	req.g.rtgen_family = family;\
1071 1071
 	} while(0);
1072 1072
 
1073
+#define NETLINK_BUFFER_SIZE 32768
1073 1074
 	
1074 1075
 static int get_flags(int family){
1075 1076
 	struct {
... ...
@@ -1079,7 +1080,7 @@ static int get_flags(int family){
1079 1080
 	int rtn = 0;
1080 1081
 	struct nlmsghdr*  nlp;
1081 1082
 	struct ifinfomsg *ifi;
1082
-	char buf[8192];
1083
+	char buf[NETLINK_BUFFER_SIZE];
1083 1084
 	char *p = buf;
1084 1085
 	int nll = 0;
1085 1086
     int nl_sock = -1;
... ...
@@ -1095,6 +1096,10 @@ static int get_flags(int family){
1095 1096
 	}
1096 1097
 
1097 1098
 	while(1) {
1099
+		if ((sizeof(buf) - nll) == 0) {
1100
+			LM_ERR("netlink buffer overflow in get_flags");
1101
+			goto error;
1102
+		}
1098 1103
 		rtn = recv(nl_sock, p, sizeof(buf) - nll, 0);
1099 1104
 		nlp = (struct nlmsghdr *) p;
1100 1105
 		if(nlp->nlmsg_type == NLMSG_DONE){
... ...
@@ -1148,7 +1153,7 @@ static int build_iface_list(void)
1148 1153
 	struct nlmsghdr*  nlp;
1149 1154
 	struct ifaddrmsg *ifi;
1150 1155
 	int rtl;
1151
-	char buf[8192];
1156
+	char buf[NETLINK_BUFFER_SIZE];
1152 1157
 	char *p = buf;
1153 1158
 	int nll = 0;
1154 1159
 	struct rtattr * rtap;
... ...
@@ -1184,6 +1189,16 @@ static int build_iface_list(void)
1184 1189
 		nll = 0;
1185 1190
 		p = buf;
1186 1191
 		while(1) {
1192
+			// This (and the loop above in get_flags) is
1193
+			// broken in more than one aspect. For example,
1194
+			// if a receive is shorter than nlmsghdr,
1195
+			// nlp->nlmsg_type will point at garbage.
1196
+			// Proper fix for this (and static buffer sizing
1197
+			// problem) would be to use libnl.
1198
+			if ((sizeof(buf) - nll) == 0) {
1199
+				LM_ERR("netlink buffer overflow in build_iface_list");
1200
+				goto error;
1201
+			}
1187 1202
 			rtn = recv(nl_sock, p, sizeof(buf) - nll, 0);
1188 1203
 			LM_DBG("received %d byles \n", rtn);
1189 1204
 			nlp = (struct nlmsghdr *) p;