Fix bad memory access at client disconnection 02/21902/1
authorJosé Bollo <jose.bollo@iot.bzh>
Tue, 9 Jul 2019 22:06:36 +0000 (00:06 +0200)
committerJose Bollo <jose.bollo@iot.bzh>
Thu, 18 Jul 2019 13:38:02 +0000 (15:38 +0200)
The management of structures handling a client
connection to a exported --ws-server was accessing
freed memory. Tha commit fixes that issue.

Bug-AGL: SPEC-2651

Change-Id: I511218afc907308347bc422a8aead32ca00bdae6
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
src/afb-api-ws.c
src/afb-proto-ws.c
src/afb-ws.c
src/afs-supervisor.c

index 3d2445a..6b242e1 100644 (file)
@@ -130,7 +130,9 @@ static void api_ws_server_accept(struct api_ws_server *apiws)
                        close(fd);
                } else {
                        server = afb_stub_ws_create_server(fdev, &apiws->uri[apiws->offapi], apiws->apiset);
-                       if (!server)
+                       if (server)
+                               afb_stub_ws_set_on_hangup(server, afb_stub_ws_unref);
+                       else
                                ERROR("can't serve accepted connection to %s: %m", apiws->uri);
                }
        }
@@ -144,7 +146,7 @@ static void api_ws_server_listen_callback(void *closure, uint32_t revents, struc
 
        if ((revents & EPOLLIN) != 0)
                api_ws_server_accept(apiws);
-       if ((revents & EPOLLHUP) != 0)
+       else if ((revents & EPOLLHUP) != 0)
                api_ws_server_connect(apiws);
 }
 
index fb8628d..3c26205 100644 (file)
@@ -132,9 +132,6 @@ struct afb_proto_ws
        /* count of references */
        int refcount;
 
-       /* file descriptor */
-       struct fdev *fdev;
-
        /* resource control */
        pthread_mutex_t mutex;
 
@@ -985,9 +982,9 @@ static void on_hangup(void *closure)
                free(cd);
        }
 
-       if (protows->fdev) {
-               fdev_unref(protows->fdev);
-               protows->fdev = 0;
+       if (protows->ws) {
+               afb_ws_destroy(protows->ws);
+               protows->ws = 0;
                if (protows->on_hangup)
                        protows->on_hangup(protows->closure);
        }
@@ -1027,7 +1024,6 @@ static struct afb_proto_ws *afb_proto_ws_create(struct fdev *fdev, const struct
                fcntl(fdev_fd(fdev), F_SETFL, O_NONBLOCK);
                protows->ws = afb_ws_create(fdev, itf, protows);
                if (protows->ws != NULL) {
-                       protows->fdev = fdev;
                        protows->refcount = 1;
                        protows->closure = closure;
                        protows->server_itf = itfs;
@@ -1054,7 +1050,6 @@ void afb_proto_ws_unref(struct afb_proto_ws *protows)
 {
        if (protows && !__atomic_sub_fetch(&protows->refcount, 1, __ATOMIC_RELAXED)) {
                afb_proto_ws_hangup(protows);
-               afb_ws_destroy(protows->ws);
                pthread_mutex_destroy(&protows->mutex);
                free(protows);
        }
@@ -1077,7 +1072,8 @@ int afb_proto_ws_is_server(struct afb_proto_ws *protows)
 
 void afb_proto_ws_hangup(struct afb_proto_ws *protows)
 {
-       afb_ws_hangup(protows->ws);
+       if (protows->ws)
+               afb_ws_hangup(protows->ws);
 }
 
 void afb_proto_ws_on_hangup(struct afb_proto_ws *protows, void (*on_hangup)(void *closure))
index b277646..fb31e4f 100644 (file)
@@ -120,6 +120,7 @@ static void aws_disconnect(struct afb_ws *ws, int call_on_hangup)
        struct websock *wsi = ws->ws;
        if (wsi != NULL) {
                ws->ws = NULL;
+               fdev_set_callback(ws->fdev, NULL, 0);
                fdev_unref(ws->fdev);
                websock_destroy(wsi);
                free(ws->buffer.buffer);
@@ -133,7 +134,7 @@ static void fdevcb(void *ws, uint32_t revents, struct fdev *fdev)
 {
        if ((revents & EPOLLIN) != 0)
                aws_on_readable(ws);
-       if ((revents & EPOLLHUP) != 0)
+       else if ((revents & EPOLLHUP) != 0)
                afb_ws_hangup(ws);
 }
 
index d36a340..31b8b7c 100644 (file)
@@ -282,7 +282,7 @@ static void listening(void *closure, uint32_t revents, struct fdev *fdev)
 {
        if ((revents & EPOLLIN) != 0)
                accept_supervision_link((int)(intptr_t)closure);
-       if ((revents & EPOLLHUP) != 0) {
+       else if ((revents & EPOLLHUP) != 0) {
                ERROR("supervision socket closed");
                exit(1);
        }