Modified aul socket functions 95/189195/17
authorHwankyu Jhun <h.jhun@samsung.com>
Fri, 14 Sep 2018 06:31:50 +0000 (15:31 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 20 Sep 2018 01:04:07 +0000 (10:04 +0900)
To prevent deadlock issue, aul socket checks whether the return value
is zero or not.

Change-Id: I177fb916db643a04106b5bf73ac6847582d687ca
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/aul_sock.c

index f2c2c01..5e0b094 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2000 - 2018 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 #define _GNU_SOURCE
-#include <sys/types.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/xattr.h>
 #include <errno.h>
 #define PATH_AMD_SOCK "/run/aul/daemons/.amd-sock"
 
 #define REGULAR_UID_MIN 5000
+
+typedef struct app_pkt_header_s {
+       int cmd;
+       int len;
+       int opt;
+} app_pkt_header_t;
+
 static int socket_timeout_initialized;
 
 static struct timeval tv = { 5, 200 * 1000 }; /* 5.2 */
@@ -44,6 +52,89 @@ static struct timeval tv = { 5, 200 * 1000 }; /* 5.2 */
 static int __connect_client_sock(int sockfd, const struct sockaddr *saptr,
                socklen_t salen, int nsec);
 
+static int __recv_raw(int fd, unsigned char *data, size_t data_size)
+{
+       ssize_t recv_size = 0;
+       ssize_t r;
+       size_t size = data_size;
+       bool is_blocking;
+
+       if (fcntl(fd, F_GETFL, 0) & O_NONBLOCK)
+               is_blocking = false;
+       else
+               is_blocking = true;
+
+       while (size > 0) {
+               r = recv(fd, data, size, 0);
+               if (r == 0) {
+                       _W("Socket was disconnected. fd(%d)", fd);
+                       return -ECOMM;
+               } else if (r < 0) {
+                       if (errno == EINTR || errno == EAGAIN) {
+                               if (is_blocking && errno == EAGAIN) {
+                                       _E("recv timeout. fd(%d)", fd);
+                                       return -EAGAIN;
+                               }
+
+                               continue;
+                       }
+
+                       _E("recv error. fd(%d), errno(%d)",
+                                       fd, errno);
+                       return -ECOMM;
+               }
+
+               size -= r;
+               data += r;
+               recv_size += r;
+       }
+
+       if (recv_size != data_size) {
+               _E("Failed to receive messages. fd(%d)", fd);
+               return -ECOMM;
+       }
+
+       return 0;
+}
+
+static int __recv_pkt(int fd, app_pkt_t **out_pkt)
+{
+       app_pkt_header_t header = { 0, };
+       app_pkt_t *pkt;
+       int r;
+
+       *out_pkt = NULL;
+       r = __recv_raw(fd, (unsigned char *)&header, sizeof(header));
+       if (r < 0) {
+               _E("Failed to receive packet header");
+               return r;
+       }
+
+       if (header.len < 0 || header.len > MAX_PAYLOAD_SIZE) {
+               _E("Invalid protocol. length(%d)", header.len);
+               return -ECOMM;
+       }
+
+       pkt = calloc(1, sizeof(app_pkt_t) + header.len);
+       if (!pkt) {
+               _E("Out of memory");
+               return -ECOMM;
+       }
+       pkt->cmd = header.cmd;
+       pkt->len = header.len;
+       pkt->opt = header.opt;
+
+       r = __recv_raw(fd, (unsigned char *)pkt->data, pkt->len);
+       if (r < 0) {
+               free(pkt);
+               return r;
+       }
+
+       *out_pkt = pkt;
+
+       return 0;
+}
+
 static void __set_timeval(double sec)
 {
        char buf[12];
@@ -405,7 +496,6 @@ API int aul_sock_send_raw_with_fd(int fd, int cmd, unsigned char *kb_data, int d
 {
        int len;
        int res;
-       char buf[1024];
 
        _D("fd(%d): cmd(%d)", fd, cmd);
 
@@ -419,21 +509,9 @@ API int aul_sock_send_raw_with_fd(int fd, int cmd, unsigned char *kb_data, int d
        if (opt & AUL_SOCK_ASYNC)
                return fd;
 
-retry_recv:
-       len = recv(fd, &res, sizeof(int), 0);
-       if (len <= 0) {
-               if (errno == EAGAIN) {
-                       _E("recv timeout : %s",
-                                       strerror_r(errno, buf, sizeof(buf)));
-                       res = -EAGAIN;
-               } else if (errno == EINTR) {
-                       _D("recv : %s", strerror_r(errno, buf, sizeof(buf)));
-                       goto retry_recv;
-               } else {
-                       _E("recv error : %s", strerror_r(errno, buf, sizeof(buf)));
-                       res = -ECOMM;
-               }
-       }
+       len = __recv_raw(fd, (unsigned char *)&res, sizeof(int));
+       if (len < 0)
+               res = len;
 
        close(fd);
 
@@ -508,154 +586,50 @@ API int aul_sock_send_bundle(int pid, uid_t uid, int cmd, bundle *kb, int opt)
 
 API app_pkt_t *aul_sock_recv_pkt(int fd, int *clifd, struct ucred *cr)
 {
-       int len;
-       int ret;
        struct sockaddr_un aul_addr = { 0, };
-       int sun_size;
-       app_pkt_t *pkt = NULL;
+       int sun_size = sizeof(struct sockaddr_un);
        int cl = sizeof(struct ucred);
-       unsigned char buf[AUL_PKT_HEADER_SIZE];
-       int cmd;
-       int datalen;
-       int opt;
-
-       sun_size = sizeof(struct sockaddr_un);
+       app_pkt_t *pkt = NULL;
+       int client_fd;
+       int ret;
 
-       *clifd = accept(fd, (struct sockaddr *)&aul_addr,
+       client_fd = accept(fd, (struct sockaddr *)&aul_addr,
                        (socklen_t *)&sun_size);
-       if (*clifd == -1) {
+       if (client_fd == -1) {
                if (errno != EINTR)
                        _E("accept error");
                return NULL;
        }
 
-       if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
-                      (socklen_t *) &cl) < 0) {
+       ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED,
+                       cr, (socklen_t *)&cl);
+       if (ret < 0) {
                _E("peer information error");
-               close(*clifd);
+               close(client_fd);
                return NULL;
        }
 
-       aul_sock_set_sock_option(*clifd, 1);
-
- retry_recv:
-       /* receive header(cmd, datalen) */
-       len = recv(*clifd, buf, sizeof(buf), 0);
-       if (len <= 0)
-               if (errno == EINTR)
-                       goto retry_recv;
-
-       if (len < AUL_PKT_HEADER_SIZE) {
-               _E("recv error");
-               close(*clifd);
-               return NULL;
-       }
-       memcpy(&cmd, buf, sizeof(int));
-       memcpy(&datalen, buf + sizeof(int), sizeof(int));
-       memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
+       aul_sock_set_sock_option(client_fd, 1);
 
-       if (datalen < 0 || datalen > MAX_PAYLOAD_SIZE) {
-               close(*clifd);
+       ret = __recv_pkt(client_fd, &pkt);
+       if (ret < 0) {
+               close(client_fd);
                return NULL;
        }
 
-       /* allocate for a null byte */
-       pkt = (app_pkt_t *)calloc(1, sizeof(app_pkt_t) + datalen);
-       if (pkt == NULL) {
-               close(*clifd);
-               return NULL;
-       }
-       pkt->cmd = cmd;
-       pkt->len = datalen;
-       pkt->opt = opt;
-
-       len = 0;
-       while (len != pkt->len) {
-               ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
-               if (ret <= 0) {
-                       _E("recv error %d %d", len, pkt->len);
-                       free(pkt);
-                       close(*clifd);
-                       return NULL;
-               }
-               len += ret;
-               _D("recv len %d %d", len, pkt->len);
-       }
+       *clifd = client_fd;
 
        return pkt;
 }
 
 API int aul_sock_recv_reply_pkt(int fd, app_pkt_t **ret_pkt)
 {
-       int len;
-       int cmd;
        int ret;
-       int recv_opt;
-       app_pkt_t *pkt = NULL;
-       unsigned char buf[AUL_PKT_HEADER_SIZE];
-       char err_buf[1024];
-
-retry_recv:
-       /* receive header(cmd, datalen) */
-       len = recv(fd, buf, sizeof(buf), 0);
-       if (len <= 0)
-               if (errno == EINTR)
-                       goto retry_recv;
-
-       if (len < AUL_PKT_HEADER_SIZE) {
-               _E("recv error");
-               close(fd);
-               if (len == sizeof(int)) {
-                       memcpy(&ret, buf, sizeof(int));
-                       return ret;
-               }
 
-               *ret_pkt = NULL;
-               return -ECOMM;
-       }
-       memcpy(&cmd, buf, sizeof(int));
-       memcpy(&len, buf + sizeof(int), sizeof(int));
-       memcpy(&recv_opt, buf + sizeof(int) + sizeof(int), sizeof(int));
-
-       if (len < 0 || len > MAX_PAYLOAD_SIZE) {
-               close(fd);
-               *ret_pkt = NULL;
-               return -ECOMM;
-       }
-
-       /* allocate for a null byte */
-       pkt = (app_pkt_t *)calloc(1, sizeof(app_pkt_t) + len);
-       if (pkt == NULL) {
-               close(fd);
-               *ret_pkt = NULL;
-               return -ECOMM;
-       }
-       pkt->cmd = cmd;
-       pkt->len = len;
-       pkt->opt = recv_opt;
-
-       len = 0;
-       while (len != pkt->len) {
-               ret = recv(fd, pkt->data + len, pkt->len - len, 0);
-               if (ret <= 0) {
-                       if (errno == EINTR) {
-                               continue;
-                       } else {
-                               _E("recv error %s", strerror_r(errno,
-                                               err_buf, sizeof(err_buf)));
-                               free(pkt);
-                               close(fd);
-                               *ret_pkt = NULL;
-                               return -ECOMM;
-                       }
-               }
-               len += ret;
-               _D("recv len %d %d", len, pkt->len);
-       }
+       ret = __recv_pkt(fd, ret_pkt);
        close(fd);
 
-       *ret_pkt = pkt;
-       return 0;
+       return ret;
 }
 
 static int __get_descriptors(struct cmsghdr *cmsg, struct msghdr *msg, int *fds, int maxdesc)
@@ -811,54 +785,17 @@ retry_con:
        return fd;
 }
 
-static int __recv_raw_with_fd(int fd, unsigned int size,
-               unsigned char *data, unsigned int *datalen)
-{
-       int ret;
-       unsigned int len = size;
-       int retry = 2;
-
-       *datalen = 0;
-       while (len > 0 && retry) {
-               ret = recv(fd, data, len, 0);
-               if (ret <= 0) {
-                       if (errno == EINTR || errno == EAGAIN) {
-                               retry--;
-                               continue;
-                       }
-
-                       _E("recv error - fd: %d, errno: %d", fd, errno);
-                       return -ECOMM;
-               }
-
-               len -= ret;
-               data += ret;
-               *datalen += ret;
-               _D("recv len - %d:%d", size, *datalen);
-               if (*datalen == size)
-                       retry = 0;
-       }
-
-       return 0;
-}
-
-
 int aul_sock_recv_pkt_with_cb(int fd,
                void (*callback)(app_pkt_t *pkt, void *data),
                void *user_data)
 {
-       int i;
-       int count = 0;
-       unsigned int recv_size;
-       int ret = 0;
        app_pkt_t **pkt;
-       unsigned char buf[AUL_PKT_HEADER_SIZE];
-       int cmd;
-       int len;
-       int opt;
+       int count = 0;
        size_t size;
+       int ret;
+       int i;
 
-       if (fd < 0) {
+       if (fd < 0 || fd > sysconf(_SC_OPEN_MAX)) {
                _E("Invalid parameter");
                return -1;
        }
@@ -869,18 +806,15 @@ int aul_sock_recv_pkt_with_cb(int fd,
                return -1;
        }
 
-       ret = __recv_raw_with_fd(fd, sizeof(int),
-                       (unsigned char *)(intptr_t)&count, &recv_size);
+       ret = __recv_raw(fd, (unsigned char *)&count, sizeof(int));
        if (ret < 0) {
                _E("recv error - %d", ret);
                close(fd);
-               return -ECOMM;
-       } else if (count <= 0 || count > MAX_RUNNING_INSTANCE ||
-                       recv_size != sizeof(int)) {
-               _E("error - count: %d, recv_size: %d",
-                               count, recv_size);
+               return ret;
+       } else if (count <= 0 || count > MAX_RUNNING_INSTANCE) {
+               _E("error - count: %d", count);
                close(fd);
-               return count;
+               return -ECOMM;
        }
 
        size = sizeof(app_pkt_t *) * count;
@@ -893,56 +827,18 @@ int aul_sock_recv_pkt_with_cb(int fd,
        }
 
        for (i = 0; i < count; ++i) {
-               ret = __recv_raw_with_fd(fd, sizeof(buf), buf,
-                               &recv_size);
-               if (ret < 0) {
-                       _E("recv error - %d", ret);
-                       break;
-               } else if (recv_size != sizeof(buf)) {
-                       _E("recv error - recv_size: %d", recv_size);
-                       ret = -ECOMM;
-                       break;
-               }
-               memcpy(&cmd, buf, sizeof(int));
-               memcpy(&len, buf + sizeof(int), sizeof(int));
-               memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
-
-               if (len < 0 || len > MAX_PAYLOAD_SIZE) {
-                       ret = -ECOMM;
-                       break;
-               }
-
-               pkt[i] = (app_pkt_t *)calloc(1, sizeof(app_pkt_t) + len);
-               if (pkt[i] == NULL) {
-                       _E("out of memory");
-                       ret = -1;
-                       break;
-               }
-               pkt[i]->cmd = cmd;
-               pkt[i]->len = len;
-               pkt[i]->opt = opt;
-
-               ret = __recv_raw_with_fd(fd, pkt[i]->len, pkt[i]->data,
-                               &recv_size);
+               ret = __recv_pkt(fd, &pkt[i]);
                if (ret < 0) {
-                       _E("recv error - %d", ret);
-                       free(pkt[i]);
-                       pkt[i] = NULL;
-                       break;
-               } else if (recv_size != pkt[i]->len) {
-                       _E("error - recv_size: %d", recv_size);
-                       free(pkt[i]);
-                       pkt[i] = NULL;
+                       _E("Failed to receive packet");
                        break;
                }
-
-               memset(buf, 0, sizeof(buf));
        }
 
        for (i = 0; i < count; ++i) {
                callback(pkt[i], user_data);
                free(pkt[i]);
        }
+
        free(pkt);
        close(fd);
 
@@ -953,27 +849,11 @@ API int aul_sock_recv_result_with_fd(int fd)
 {
        int len;
        int res;
-       char buf[1024];
-
-retry_recv:
-       len = recv(fd, &res, sizeof(int), 0);
-       if (len <= 0) {
-               if (errno == EAGAIN) {
-                       _E("recv timeout: %s, fd: %d ",
-                                       strerror_r(errno, buf, sizeof(buf)),
-                                       fd);
-                       res = -EAGAIN;
-               } else if (errno == EINTR) {
-                       _D("recv: %s, fd: %d",
-                                       strerror_r(errno, buf, sizeof(buf)),
-                                       fd);
-                       goto retry_recv;
-               } else {
-                       _E("recv error: %s, fd: %d",
-                                       strerror_r(errno, buf, sizeof(buf)),
-                                       fd);
-                       res = -ECOMM;
-               }
+
+       len = __recv_raw(fd, (unsigned char *)&res, sizeof(int));
+       if (len < 0) {
+               _E("Failed to receive the result. fd(%d)", fd);
+               res = -ECOMM;
        }
 
        return res;