socket-util: add more careful parsers for AF_VSOCK cid/port

Let's handle the magic CIDs, and filter out invalid ports.
This commit is contained in:
Lennart Poettering
2024-01-05 22:29:55 +01:00
parent 41dd51f8f5
commit 8e471c6a9f
2 changed files with 50 additions and 3 deletions
+47 -3
View File
@@ -1656,6 +1656,50 @@ int socket_address_parse_unix(SocketAddress *ret_address, const char *s) {
return 0;
}
int vsock_parse_port(const char *s, unsigned *ret) {
int r;
assert(ret);
if (!s)
return -EINVAL;
unsigned u;
r = safe_atou(s, &u);
if (r < 0)
return r;
/* Port 0 is apparently valid and not special in AF_VSOCK (unlike on IP). But VMADDR_PORT_ANY
* (UINT32_MAX) is. Hence refuse that. */
if (u == VMADDR_PORT_ANY)
return -EINVAL;
*ret = u;
return 0;
}
int vsock_parse_cid(const char *s, unsigned *ret) {
assert(ret);
if (!s)
return -EINVAL;
/* Parsed an AF_VSOCK "CID". This is a 32bit entity, and the usual type is "unsigned". We recognize
* the three special CIDs as strings, and otherwise parse the numeric CIDs. */
if (streq(s, "hypervisor"))
*ret = VMADDR_CID_HYPERVISOR;
else if (streq(s, "local"))
*ret = VMADDR_CID_LOCAL;
else if (streq(s, "host"))
*ret = VMADDR_CID_HOST;
else
return safe_atou(s, ret);
return 0;
}
int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
/* AF_VSOCK socket in vsock:cid:port notation */
_cleanup_free_ char *n = NULL;
@@ -1681,7 +1725,7 @@ int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
if (!e)
return -EINVAL;
r = safe_atou(e+1, &port);
r = vsock_parse_port(e+1, &port);
if (r < 0)
return r;
@@ -1692,15 +1736,15 @@ int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
if (isempty(n))
cid = VMADDR_CID_ANY;
else {
r = safe_atou(n, &cid);
r = vsock_parse_cid(n, &cid);
if (r < 0)
return r;
}
*ret_address = (SocketAddress) {
.sockaddr.vm = {
.svm_cid = cid,
.svm_family = AF_VSOCK,
.svm_cid = cid,
.svm_port = port,
},
.type = type,
+3
View File
@@ -374,6 +374,9 @@ int socket_get_mtu(int fd, int af, size_t *ret);
int connect_unix_path(int fd, int dir_fd, const char *path);
int vsock_parse_port(const char *s, unsigned *ret);
int vsock_parse_cid(const char *s, unsigned *ret);
/* Parses AF_UNIX and AF_VSOCK addresses. AF_INET[6] require some netlink calls, so it cannot be in
* src/basic/ and is done from 'socket_local_address from src/shared/. Return -EPROTO in case of
* protocol mismatch. */