Check for abstract sockets only once.
authorAndre Noll <maan@tuebingen.mpg.de>
Mon, 30 Apr 2018 18:31:05 +0000 (20:31 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 12 Aug 2018 08:00:49 +0000 (10:00 +0200)
In net.c there is a static variable which is supposed to cache whether
the abstract local socket namespace is supported. This variable is
pointless because it is only ever set by command handlers, which exit
after the command completed. Hence the command handler process of
each subsequent afs command checks again. To make the caching work as
intended we must initialize the variable in the *parent* process. The
parent process, however, does not create any local sockets.

This patch changes init_unix_addr() to initialize the variable
without creating a socket when NULL is passed as the name parameter.
The server process passes NULL to initialize the static variable
while command handlers pass non NULL.

net.c
server.c

diff --git a/net.c b/net.c
index ba19408..d1dcba0 100644 (file)
--- a/net.c
+++ b/net.c
@@ -886,14 +886,13 @@ int dccp_available_ccids(uint8_t **ccid_array)
  * The first call to this function tries to bind a socket to the abstract name
  * space. The result of this test is stored in a static variable. Subsequent
  * calls read this variable and create abstract sockets on systems that support
- * them.
+ * them. If a NULL pointer is passed as the name, the function only
+ * initializes the static variable.
  */
 static int init_unix_addr(struct sockaddr_un *u, const char *name)
 {
        static int use_abstract;
 
-       if (strlen(name) + 1 >= UNIX_PATH_MAX)
-               return -E_NAME_TOO_LONG;
        memset(u->sun_path, 0, UNIX_PATH_MAX);
        u->sun_family = PF_UNIX;
        if (use_abstract == 0) { /* executed only once */
@@ -907,6 +906,10 @@ static int init_unix_addr(struct sockaddr_un *u, const char *name)
                PARA_NOTICE_LOG("%susing abstract socket namespace\n",
                        use_abstract == 1? "" : "not ");
        }
+       if (!name)
+               return 0;
+       if (strlen(name) + 1 >= UNIX_PATH_MAX)
+               return -E_NAME_TOO_LONG;
        strcpy(u->sun_path + (use_abstract == 1? 1 : 0), name);
        return 1;
 }
@@ -931,7 +934,7 @@ int create_local_socket(const char *name)
        int fd, ret;
 
        ret = init_unix_addr(&unix_addr, name);
-       if (ret < 0)
+       if (ret <= 0) /* error, or name was NULL */
                return ret;
        ret = socket(PF_UNIX, SOCK_STREAM, 0);
        if (ret < 0)
index eee0a41..6370cef 100644 (file)
--- a/server.c
+++ b/server.c
@@ -488,6 +488,13 @@ static void init_server_command_task(struct server_command_task *sct,
                .post_select = command_post_select,
                .context = sct,
        }, &sched);
+       /*
+        * Detect whether the abstract Unix domain socket space is supported,
+        * but do not create the socket. We check this once in server context
+        * so that the command handlers inherit this bit of information and
+        * don't need to check again.
+        */
+       create_local_socket(NULL);
        return;
 err:
        PARA_EMERG_LOG("%s\n", para_strerror(-ret));