Skip to content

Commit 554971d

Browse files
bhyve: Use getaddrinfo(3) consistently for AF_UNIX.
The FreeBSD getaddrinfo(3) function also supports the AF_UNIX address family. Use it the same way as inet and inet6 so that we can share the same code. However, the getaddrinfo(3) accepts an absolute path only. The path string that follows 'unix:' will be resolved by the realpath(3) function. The freeaddrinfo(3) function also supports a NULL argument, as does free(3). No need to check a NULL pointer. While I'm here, the UNIX domain socket should allow all users to access it as if it were a TCP port. Changes umask to 0 before bind(2), and restores the previous value after the bind(2). Signed-off-by: Yuichiro NAITO <[email protected]>
1 parent 17ba6f4 commit 554971d

File tree

2 files changed

+47
-35
lines changed

2 files changed

+47
-35
lines changed

usr.sbin/bhyve/pci_fbuf.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
#include <errno.h>
4444
#include <unistd.h>
45+
#include <libgen.h>
4546

4647
#include "bhyvegc.h"
4748
#include "bhyverun.h"
@@ -240,6 +241,30 @@ pci_fbuf_baraddr(struct pci_devinst *pi, int baridx, int enabled,
240241
}
241242
}
242243

244+
static char *
245+
abspath(const char *origpath)
246+
{
247+
char *ret, *dn, *cp;
248+
249+
if ((cp = strdup(origpath)) == NULL)
250+
return (NULL);
251+
if ((dn = realpath(dirname(cp), NULL)) == NULL) {
252+
EPRINTLN("fbuf: Invalid path: \"%s\"", origpath);
253+
goto error;
254+
}
255+
strcpy(cp, origpath);
256+
if (asprintf(&ret, "%s/%s", dn, basename(cp)) < 0)
257+
goto error_2;
258+
free(dn);
259+
free(cp);
260+
return (ret);
261+
262+
error_2:
263+
free(dn);
264+
error:
265+
free(cp);
266+
return (NULL);
267+
}
243268

244269
static int
245270
pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl)
@@ -295,7 +320,7 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl)
295320
return (-1);
296321
} else {
297322
sc->rfb_family = AF_UNIX;
298-
sc->rfb_host = strdup(value + 5);
323+
sc->rfb_host = abspath(value + 5);
299324
}
300325
} else {
301326
sc->rfb_family = AF_UNSPEC;

usr.sbin/bhyve/rfb.c

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
#include <sys/endian.h>
3535
#include <sys/socket.h>
3636
#include <sys/select.h>
37+
#include <sys/stat.h>
3738
#include <sys/time.h>
38-
#include <sys/un.h>
3939
#include <arpa/inet.h>
4040
#include <stdatomic.h>
4141
#include <machine/cpufunc.h>
@@ -1263,9 +1263,9 @@ rfb_init(sa_family_t family, const char *hostname, int port, int wait,
12631263
struct rfb_softc *rc;
12641264
struct addrinfo *ai = NULL;
12651265
struct addrinfo hints;
1266-
struct sockaddr_un sun;
12671266
int on = 1;
12681267
int cnt;
1268+
mode_t omask;
12691269
#ifndef WITHOUT_CAPSICUM
12701270
cap_rights_t rights;
12711271
#endif
@@ -1304,28 +1304,19 @@ rfb_init(sa_family_t family, const char *hostname, int port, int wait,
13041304
hostname = "[::1]";
13051305
#endif
13061306

1307-
if (family == AF_UNIX) {
1308-
memset(&sun, 0, sizeof(sun));
1309-
sun.sun_family = AF_UNIX;
1310-
if (strlcpy(sun.sun_path, hostname, sizeof(sun.sun_path)) >=
1311-
sizeof(sun.sun_path)) {
1312-
EPRINTLN("rfb: socket path too long");
1313-
goto error;
1314-
}
1315-
rc->sfd = socket(AF_UNIX, SOCK_STREAM, 0);
1316-
} else {
1317-
memset(&hints, 0, sizeof(hints));
1318-
hints.ai_socktype = SOCK_STREAM;
1319-
hints.ai_family = family;
1320-
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE;
1321-
1322-
if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) {
1323-
EPRINTLN("getaddrinfo: %s", gai_strerror(e));
1324-
goto error;
1325-
}
1326-
rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0);
1327-
}
1307+
memset(&hints, 0, sizeof(hints));
1308+
hints.ai_family = family;
1309+
hints.ai_socktype = SOCK_STREAM;
1310+
hints.ai_flags = AI_PASSIVE;
1311+
if (family != AF_UNIX)
1312+
hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV;
13281313

1314+
if ((e = getaddrinfo(hostname, family == AF_UNIX ? NULL : servname,
1315+
&hints, &ai)) != 0) {
1316+
EPRINTLN("getaddrinfo: %s", gai_strerror(e));
1317+
goto error;
1318+
}
1319+
rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0);
13291320
if (rc->sfd < 0) {
13301321
perror("socket");
13311322
goto error;
@@ -1334,15 +1325,15 @@ rfb_init(sa_family_t family, const char *hostname, int port, int wait,
13341325
/* No effect for UNIX domain sockets. */
13351326
setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
13361327

1337-
if (family == AF_UNIX) {
1328+
if (family == AF_UNIX)
13381329
unlink(hostname);
1339-
e = bind(rc->sfd, (struct sockaddr *)&sun, SUN_LEN(&sun));
1340-
} else
1341-
e = bind(rc->sfd, ai->ai_addr, ai->ai_addrlen);
1342-
if (e < 0) {
1330+
omask = umask(0);
1331+
if (bind(rc->sfd, ai->ai_addr, ai->ai_addrlen) < 0) {
13431332
perror("bind");
1333+
umask(omask);
13441334
goto error;
13451335
}
1336+
umask(omask);
13461337

13471338
if (listen(rc->sfd, 1) < 0) {
13481339
perror("listen");
@@ -1375,17 +1366,13 @@ rfb_init(sa_family_t family, const char *hostname, int port, int wait,
13751366
DPRINTF(("rfb client connected"));
13761367
}
13771368

1378-
if (family != AF_UNIX)
1379-
freeaddrinfo(ai);
1369+
freeaddrinfo(ai);
13801370
return (0);
13811371

13821372
error:
13831373
if (rc->pixfmt_mtx)
13841374
pthread_mutex_destroy(&rc->pixfmt_mtx);
1385-
if (ai != NULL) {
1386-
assert(family != AF_UNIX);
1387-
freeaddrinfo(ai);
1388-
}
1375+
freeaddrinfo(ai);
13891376
if (rc->sfd != -1)
13901377
close(rc->sfd);
13911378
free(rc->crc);

0 commit comments

Comments
 (0)