Codebase list libuv1 / 05d4383
linux: fix i386 sendmmsg/recvmmsg support Android/i386 doesn't have separate sendmmsg/recvmmsg system calls, they're multiplexed through the socketcall system call. (More precisely, the system calls may be present but the standard seccomp filter rejects them, whereas socketcall is whitelisted.) This commit removes the flags and timeout arguments from libuv's internal system call wrappers because they're always zero and it makes EINVAL/ENOSYS detection after a failed socketcall() easier. Fixes: https://github.com/libuv/libuv/issues/2923 PR-URL: https://github.com/libuv/libuv/pull/2925 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Ben Noordhuis authored 3 years ago cjihrig committed 3 years ago
4 changed file(s) with 55 addition(s) and 47 deletion(s). Raw diff Collapse all Expand all
263263 }
264264
265265
266 int uv__sendmmsg(int fd,
267 struct uv__mmsghdr* mmsg,
268 unsigned int vlen,
269 unsigned int flags) {
266 int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
270267 #if __FreeBSD__ >= 11
271 return sendmmsg(fd, mmsg, vlen, flags);
268 return sendmmsg(fd, mmsg, vlen, /* flags */ 0);
272269 #else
273270 return errno = ENOSYS, -1;
274271 #endif
275272 }
276273
277274
278 int uv__recvmmsg(int fd,
279 struct uv__mmsghdr* mmsg,
280 unsigned int vlen,
281 unsigned int flags,
282 struct timespec* timeout) {
275 int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
283276 #if __FreeBSD__ >= 11
284 return recvmmsg(fd, mmsg, vlen, flags, timeout);
277 return recvmmsg(fd, mmsg, vlen, 0 /* flags */, NULL /* timeout */);
285278 #else
286279 return errno = ENOSYS, -1;
287280 #endif
333333 unsigned int msg_len;
334334 };
335335
336 int uv__recvmmsg(int fd,
337 struct uv__mmsghdr* mmsg,
338 unsigned int vlen,
339 unsigned int flags,
340 struct timespec* timeout);
341 int uv__sendmmsg(int fd,
342 struct uv__mmsghdr* mmsg,
343 unsigned int vlen,
344 unsigned int flags);
336 int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen);
337 int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen);
345338 #else
346339 #define HAVE_MMSG 0
347340 #endif
3636 #ifndef __NR_recvmmsg
3737 # if defined(__x86_64__)
3838 # define __NR_recvmmsg 299
39 # elif defined(__i386__)
40 # define __NR_recvmmsg 337
4139 # elif defined(__arm__)
4240 # define __NR_recvmmsg (UV_SYSCALL_BASE + 365)
4341 # endif
4644 #ifndef __NR_sendmmsg
4745 # if defined(__x86_64__)
4846 # define __NR_sendmmsg 307
49 # elif defined(__i386__)
50 # define __NR_sendmmsg 345
5147 # elif defined(__arm__)
5248 # define __NR_sendmmsg (UV_SYSCALL_BASE + 374)
5349 # endif
145141
146142 struct uv__mmsghdr;
147143
148 int uv__sendmmsg(int fd,
149 struct uv__mmsghdr* mmsg,
150 unsigned int vlen,
151 unsigned int flags) {
152 #if defined(__NR_sendmmsg)
153 return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags);
154 #else
155 return errno = ENOSYS, -1;
156 #endif
157 }
158
159
160 int uv__recvmmsg(int fd,
161 struct uv__mmsghdr* mmsg,
162 unsigned int vlen,
163 unsigned int flags,
164 struct timespec* timeout) {
165 #if defined(__NR_recvmmsg)
166 return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout);
144 int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
145 #if defined(__i386__)
146 unsigned long args[4];
147 int rc;
148
149 args[0] = (unsigned long) fd;
150 args[1] = (unsigned long) mmsg;
151 args[2] = (unsigned long) vlen;
152 args[3] = /* flags */ 0;
153
154 /* socketcall() raises EINVAL when SYS_SENDMMSG is not supported. */
155 rc = syscall(/* __NR_socketcall */ 102, 20 /* SYS_SENDMMSG */, args);
156 if (rc == -1)
157 if (errno == EINVAL)
158 errno = ENOSYS;
159
160 return rc;
161 #elif defined(__NR_sendmmsg)
162 return syscall(__NR_sendmmsg, fd, mmsg, vlen, /* flags */ 0);
163 #else
164 return errno = ENOSYS, -1;
165 #endif
166 }
167
168
169 int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) {
170 #if defined(__i386__)
171 unsigned long args[5];
172 int rc;
173
174 args[0] = (unsigned long) fd;
175 args[1] = (unsigned long) mmsg;
176 args[2] = (unsigned long) vlen;
177 args[3] = /* flags */ 0;
178 args[4] = /* timeout */ 0;
179
180 /* socketcall() raises EINVAL when SYS_RECVMMSG is not supported. */
181 rc = syscall(/* __NR_socketcall */ 102, 19 /* SYS_RECVMMSG */, args);
182 if (rc == -1)
183 if (errno == EINVAL)
184 errno = ENOSYS;
185
186 return rc;
187 #elif defined(__NR_recvmmsg)
188 return syscall(__NR_recvmmsg, fd, mmsg, vlen, /* flags */ 0, /* timeout */ 0);
167189 #else
168190 return errno = ENOSYS, -1;
169191 #endif
7272 s = uv__socket(AF_INET, SOCK_DGRAM, 0);
7373 if (s < 0)
7474 return;
75 ret = uv__sendmmsg(s, NULL, 0, 0);
75 ret = uv__sendmmsg(s, NULL, 0);
7676 if (ret == 0 || errno != ENOSYS) {
7777 uv__sendmmsg_avail = 1;
7878 uv__recvmmsg_avail = 1;
7979 } else {
80 ret = uv__recvmmsg(s, NULL, 0, 0, NULL);
80 ret = uv__recvmmsg(s, NULL, 0);
8181 if (ret == 0 || errno != ENOSYS)
8282 uv__recvmmsg_avail = 1;
8383 }
212212 }
213213
214214 do
215 nread = uv__recvmmsg(handle->io_watcher.fd, msgs, chunks, 0, NULL);
215 nread = uv__recvmmsg(handle->io_watcher.fd, msgs, chunks);
216216 while (nread == -1 && errno == EINTR);
217217
218218 if (nread < 1) {
355355 }
356356
357357 do
358 npkts = uv__sendmmsg(handle->io_watcher.fd, h, pkts, 0);
358 npkts = uv__sendmmsg(handle->io_watcher.fd, h, pkts);
359359 while (npkts == -1 && errno == EINTR);
360360
361361 if (npkts < 1) {