Merge pull request #30794 from poettering/parse-vsock-better

socket-util: add more careful parsers for AF_VSOCK cid/port
This commit is contained in:
Yu Watanabe
2024-01-06 11:16:19 +09:00
committed by GitHub
3 changed files with 70 additions and 4 deletions
+20 -1
View File
@@ -6,7 +6,6 @@
#if HAVE_LINUX_VM_SOCKETS_H
#include <linux/vm_sockets.h>
#else
#define VMADDR_CID_ANY -1U
struct sockaddr_vm {
unsigned short svm_family;
unsigned short svm_reserved1;
@@ -20,6 +19,26 @@ struct sockaddr_vm {
};
#endif /* !HAVE_LINUX_VM_SOCKETS_H */
#ifndef VMADDR_CID_ANY
#define VMADDR_CID_ANY -1U
#endif
#ifndef VMADDR_CID_HYPERVISOR
#define VMADDR_CID_HYPERVISOR 0U
#endif
#ifndef VMADDR_CID_LOCAL
#define VMADDR_CID_LOCAL 1U
#endif
#ifndef VMADDR_CID_HOST
#define VMADDR_CID_HOST 2U
#endif
#ifndef VMADDR_PORT_ANY
#define VMADDR_PORT_ANY -1U
#endif
#ifndef AF_VSOCK
#define AF_VSOCK 40
#endif
+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. */