]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: slight rework of getpeersec()
authorLennart Poettering <lennart@poettering.net>
Sat, 30 Dec 2017 14:15:44 +0000 (15:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 4 Jan 2018 12:28:24 +0000 (13:28 +0100)
Let's call getsockopt() in a loop, so that we can deal correctly with
the label changing while we are trying to read it.

(also, while we are at it, let's make sure that there's always one
trailing NUL byte at the end of the buffer, after all SO_PEERSEC has
zero documentation, and multiple implementing backends, hence let's
better be safe than sorry)

src/basic/socket-util.c

index d67fbd21372dced5cdec29f213f47ca85b1543ac..cb10a1dd07a6217d954d480774e0f944df117fb4 100644 (file)
@@ -979,41 +979,32 @@ int getpeercred(int fd, struct ucred *ucred) {
 }
 
 int getpeersec(int fd, char **ret) {
+        _cleanup_free_ char *s = NULL;
         socklen_t n = 64;
-        char *s;
-        int r;
 
         assert(fd >= 0);
         assert(ret);
 
-        s = new0(char, n);
-        if (!s)
-                return -ENOMEM;
+        for (;;) {
+                s = new0(char, n+1);
+                if (!s)
+                        return -ENOMEM;
 
-        r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
-        if (r < 0) {
-                free(s);
+                if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0)
+                        break;
 
                 if (errno != ERANGE)
                         return -errno;
 
-                s = new0(char, n);
-                if (!s)
-                        return -ENOMEM;
-
-                r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
-                if (r < 0) {
-                        free(s);
-                        return -errno;
-                }
+                s = mfree(s);
         }
 
-        if (isempty(s)) {
-                free(s);
+        if (isempty(s))
                 return -EOPNOTSUPP;
-        }
 
         *ret = s;
+        s = NULL;
+
         return 0;
 }