Skip to content

Commit e873aae

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 addrinfo structure is no longer needed after the bind(2) call. Free it after the bind(2) to remove freeaddrinfo(3) in the error label code. 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 the permission to world wide readable and writable. Signed-off-by: Yuichiro NAITO <naito.yuichiro@gmail.com>
1 parent 17ba6f4 commit e873aae

2 files changed

Lines changed: 59 additions & 45 deletions

File tree

usr.sbin/bhyve/pci_fbuf.c

Lines changed: 32 additions & 8 deletions
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,29 @@ 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, *fn;
248+
249+
if ((cp = strdup(origpath)) == NULL || cp[0] == '/')
250+
return (cp);
251+
if ((dn = realpath(dirname(cp), NULL)) == NULL) {
252+
EPRINTLN("fbuf: Invalid path: \"%s\"", origpath);
253+
goto error;
254+
}
255+
fn = strrchr(origpath, '/');
256+
if (asprintf(&ret, "%s/%s", dn, fn ? fn + 1 : origpath) < 0)
257+
goto error;
258+
free(dn);
259+
free(cp);
260+
return (ret);
261+
262+
error:
263+
free(dn);
264+
free(cp);
265+
return (NULL);
266+
}
243267

244268
static int
245269
pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl)
@@ -285,17 +309,17 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl)
285309
return (-1);
286310
}
287311
} else if (strncmp("unix:", value, 5) == 0) {
288-
if (strlen(value + 5) > SUNPATHLEN) {
312+
if (*(value + 5) == '\0') {
313+
EPRINTLN("fbuf: UNIX socket path is empty");
314+
return (-1);
315+
}
316+
sc->rfb_family = AF_UNIX;
317+
sc->rfb_host = abspath(value + 5);
318+
if (sc->rfb_host && strlen(sc->rfb_host) > SUNPATHLEN) {
289319
EPRINTLN(
290320
"fbuf: UNIX socket path too long: \"%s\"",
291-
value + 5);
321+
sc->rfb_host);
292322
return (-1);
293-
} else if (*(value + 5) == '\0') {
294-
EPRINTLN("fbuf: UNIX socket path is empty");
295-
return (-1);
296-
} else {
297-
sc->rfb_family = AF_UNIX;
298-
sc->rfb_host = strdup(value + 5);
299323
}
300324
} else {
301325
sc->rfb_family = AF_UNSPEC;

usr.sbin/bhyve/rfb.c

Lines changed: 27 additions & 37 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>
@@ -1258,12 +1258,11 @@ int
12581258
rfb_init(sa_family_t family, const char *hostname, int port, int wait,
12591259
const char *password)
12601260
{
1261-
int e;
1261+
int e, errno0;
12621262
char servname[6];
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;
12691268
#ifndef WITHOUT_CAPSICUM
@@ -1304,46 +1303,43 @@ rfb_init(sa_family_t family, const char *hostname, int port, int wait,
13041303
hostname = "[::1]";
13051304
#endif
13061305

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-
}
1306+
memset(&hints, 0, sizeof(hints));
1307+
hints.ai_family = family;
1308+
hints.ai_socktype = SOCK_STREAM;
1309+
hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE;
13281310

1311+
if ((e = getaddrinfo(hostname, family == AF_UNIX ? NULL : servname,
1312+
&hints, &ai)) != 0) {
1313+
EPRINTLN("getaddrinfo: %s", gai_strerror(e));
1314+
goto error;
1315+
}
1316+
rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0);
13291317
if (rc->sfd < 0) {
13301318
perror("socket");
1319+
freeaddrinfo(ai);
13311320
goto error;
13321321
}
13331322

1334-
/* No effect for UNIX domain sockets. */
1335-
setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1336-
1337-
if (family == AF_UNIX) {
1323+
if (family == AF_UNIX)
13381324
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);
1325+
else
1326+
setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1327+
1328+
e = bind(rc->sfd, ai->ai_addr, ai->ai_addrlen);
1329+
errno0 = errno;
1330+
freeaddrinfo(ai);
13421331
if (e < 0) {
1332+
errno = errno0;
13431333
perror("bind");
13441334
goto error;
13451335
}
13461336

1337+
if (family == AF_UNIX && chmod(hostname,
1338+
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) < 0) {
1339+
perror("chmod");
1340+
goto error;
1341+
}
1342+
13471343
if (listen(rc->sfd, 1) < 0) {
13481344
perror("listen");
13491345
goto error;
@@ -1375,17 +1371,11 @@ rfb_init(sa_family_t family, const char *hostname, int port, int wait,
13751371
DPRINTF(("rfb client connected"));
13761372
}
13771373

1378-
if (family != AF_UNIX)
1379-
freeaddrinfo(ai);
13801374
return (0);
13811375

13821376
error:
13831377
if (rc->pixfmt_mtx)
13841378
pthread_mutex_destroy(&rc->pixfmt_mtx);
1385-
if (ai != NULL) {
1386-
assert(family != AF_UNIX);
1387-
freeaddrinfo(ai);
1388-
}
13891379
if (rc->sfd != -1)
13901380
close(rc->sfd);
13911381
free(rc->crc);

0 commit comments

Comments
 (0)