libcutils: Split uevent_open_socket()

The best time to attach a BPF filter to a socket is before a socket
starts receiving data. Netlink sockets start receiving data after bind()
has been called. uevent_open_socket() calls socket() and bind(). Hence
split uevent_open_socket() into two functions: one function that calls
socket() and another function that calls bind().

Bug: 203462310
Change-Id: Ia41dee4683358cf9fbb6288fad863cd4f4ac9924
Signed-off-by: Bart Van Assche <bvanassche@google.com>
diff --git a/libcutils/uevent.cpp b/libcutils/uevent.cpp
index 40bbd5c..f01a479 100644
--- a/libcutils/uevent.cpp
+++ b/libcutils/uevent.cpp
@@ -92,20 +92,22 @@
     return -1;
 }
 
-int uevent_open_socket(int buf_sz, bool passcred) {
-    struct sockaddr_nl addr;
-    int on = passcred;
+/*
+ * Creates an unbound netlink socket for receiving uevent messages.
+ * @buf_sz: socket receive buffer size.
+ * @passcred: whether or not to enable receiving the SCM_CREDENTIALS control
+ *	message.
+ *
+ * Returns: a socket descriptor upon success or -1 upon failure.
+ */
+int uevent_create_socket(int buf_sz, bool passcred) {
+    int s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
+    if (s < 0) {
+        return -1;
+    }
+
     int buf_sz_readback = 0;
     socklen_t optlen = sizeof(buf_sz_readback);
-    int s;
-
-    memset(&addr, 0, sizeof(addr));
-    addr.nl_family = AF_NETLINK;
-    addr.nl_pid = 0;
-    addr.nl_groups = 0xffffffff;
-
-    s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
-    if (s < 0) return -1;
 
     if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0 ||
           getsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz_readback, &optlen) < 0) {
@@ -123,9 +125,43 @@
         }
     }
 
+    int on = passcred;
+
     setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
 
-    if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+    return s;
+}
+
+/*
+ * Binds a netlink socket. Binding a netlink socket makes the kernel start
+ * sending netlink messages to that netlink socket.
+ *
+ * Returns: 0 upon success; -1 upon error.
+ */
+int uevent_bind(int socket) {
+    struct sockaddr_nl addr = {
+            .nl_family = AF_NETLINK,
+            .nl_pid = 0,
+            .nl_groups = 0xffffffff,
+    };
+    return bind(socket, (struct sockaddr*)&addr, sizeof(addr));
+}
+
+/*
+ * Creates a bound netlink socket for receiving uevent messages.
+ * @buf_sz: socket receive buffer size.
+ * @passcred: whether or not to enable receiving the SCM_CREDENTIALS control
+ *	message.
+ *
+ * Returns: a socket descriptor upon success or -1 upon failure.
+ */
+int uevent_open_socket(int buf_sz, bool passcred) {
+    int s = uevent_create_socket(buf_sz, passcred);
+    if (s < 0) {
+        return -1;
+    }
+
+    if (uevent_bind(s) < 0) {
         close(s);
         return -1;
     }