summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-10-15 18:02:30 +0200
committerLennart Poettering <lennart@poettering.net>2018-10-15 19:35:00 +0200
commit5cf91ea9c858fca03983c96932c886497953603e (patch)
treea8448b157f66c3eb02006ec923e3ef48549d5910 /src
parent44ed5214add7b2c1048a9b8e6ca8cb99505a78eb (diff)
downloadsystemd-5cf91ea9c858fca03983c96932c886497953603e.tar.gz
systemd-5cf91ea9c858fca03983c96932c886497953603e.tar.bz2
systemd-5cf91ea9c858fca03983c96932c886497953603e.zip
socket-util: add sockaddr_un_set_path() helper
Properly initializing sun_path from foreign data is not easy, given the size constraints, and NUL confusion. Let's add a helper function for this.
Diffstat (limited to 'src')
-rw-r--r--src/basic/socket-util.c44
-rw-r--r--src/basic/socket-util.h2
2 files changed, 46 insertions, 0 deletions
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index aa636ffd61..6b3c6592a5 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1262,3 +1262,47 @@ int sockaddr_un_unlink(const struct sockaddr_un *sa) {
return 1;
}
+
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
+ size_t l;
+
+ assert(ret);
+ assert(path);
+
+ /* Initialize ret->sun_path from the specified argument. This will interpret paths starting with '@' as
+ * abstract namespace sockets, and those starting with '/' as regular filesystem sockets. It won't accept
+ * anything else (i.e. no relative paths), to avoid ambiguities. Note that this function cannot be used to
+ * reference paths in the abstract namespace that include NUL bytes in the name. */
+
+ l = strlen(path);
+ if (l == 0)
+ return -EINVAL;
+ if (!IN_SET(path[0], '/', '@'))
+ return -EINVAL;
+ if (path[1] == 0)
+ return -EINVAL;
+
+ /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than
+ * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket
+ * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that
+ * do not expect non-NUL terminated file system path*/
+ if (l+1 > sizeof(ret->sun_path))
+ return -EINVAL;
+
+ *ret = (struct sockaddr_un) {
+ .sun_family = AF_UNIX,
+ };
+
+ if (path[0] == '@') {
+ /* Abstract namespace socket */
+ memcpy(ret->sun_path + 1, path + 1, l); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l); /* 🔥 *don't* 🔥 include trailing NUL in size */
+
+ } else {
+ assert(path[0] == '/');
+
+ /* File system socket */
+ memcpy(ret->sun_path, path, l + 1); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
+ }
+}
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 0a7d79885f..29bd85f1e0 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -188,3 +188,5 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
})
int socket_ioctl_fd(void);
+
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);