diff options
author | hyunho kang <hhstark.kang@samsung.com> | 2015-10-27 17:13:53 +0900 |
---|---|---|
committer | hyunho kang <hhstark.kang@samsung.com> | 2015-10-27 19:30:29 +0900 |
commit | 693dbd6d00af80f9cfa025bcfc7cdd50c551460e (patch) | |
tree | 5055122b5e77947dda368f314fd5c167a24250b2 | |
parent | 1fde74eb0bdfdb6e3e7f880532460f65bd0022d2 (diff) | |
download | aul-1-693dbd6d00af80f9cfa025bcfc7cdd50c551460e.tar.gz aul-1-693dbd6d00af80f9cfa025bcfc7cdd50c551460e.tar.bz2 aul-1-693dbd6d00af80f9cfa025bcfc7cdd50c551460e.zip |
Add fd passing feature for data-control
Change-Id: I9106541404b4f0c439b89b31f8e6f0efe3258d33
Signed-off-by: hyunho kang <hhstark.kang@samsung.com>
-rw-r--r-- | am_daemon/amd_main.c | 2 | ||||
-rw-r--r-- | am_daemon/amd_request.c | 168 | ||||
-rw-r--r-- | am_daemon/amd_request.h | 2 | ||||
-rw-r--r-- | include/app_sock.h | 2 | ||||
-rw-r--r-- | include/aul.h | 1 | ||||
-rw-r--r-- | src/app_sock.c | 191 | ||||
-rw-r--r-- | src/launch.c | 98 |
7 files changed, 461 insertions, 3 deletions
diff --git a/am_daemon/amd_main.c b/am_daemon/amd_main.c index a19142ab..e7846a66 100644 --- a/am_daemon/amd_main.c +++ b/am_daemon/amd_main.c @@ -276,7 +276,7 @@ static int __init() return -1; } - _requset_init(); + _request_init(); app_group_init(); if (vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, diff --git a/am_daemon/amd_request.c b/am_daemon/amd_request.c index efb8761c..1c41f57f 100644 --- a/am_daemon/amd_request.c +++ b/am_daemon/amd_request.c @@ -55,6 +55,9 @@ #define PRIVILEGE_APPMANAGER_KILL "http://tizen.org/privilege/appmanager.kill" #define PRIVILEGE_APPMANAGER_KILL_BGAPP "http://tizen.org/privilege/appmanager.kill.bgapp" +#define MAX_NR_OF_DESCRIPTORS 2 +static GHashTable *__socket_pair_hash = NULL; + typedef int (*app_cmd_dispatch_func)(int clifd, const app_pkt_t *pkt, struct ucred *cr); static cynara *r_cynara = NULL; @@ -62,6 +65,58 @@ static cynara *r_cynara = NULL; static int __send_result_to_client(int fd, int res); static gboolean __request_handler(gpointer data); +static int __send_message(int sock, const struct iovec *vec, int vec_size, const int *desc, int nr_desc) +{ + struct msghdr msg = {0}; + int sndret; + + if (vec == NULL || vec_size < 1) + return -EINVAL; + if (nr_desc < 0 || nr_desc > MAX_NR_OF_DESCRIPTORS) + return -EINVAL; + if (desc == NULL) + nr_desc = 0; + + msg.msg_iov = (struct iovec *)vec; + msg.msg_iovlen = vec_size; + + /* sending ancillary data */ + if (nr_desc > 0) { + int desclen = 0; + struct cmsghdr *cmsg = NULL; + char buff[CMSG_SPACE(sizeof(int) * MAX_NR_OF_DESCRIPTORS)] = {0}; + + msg.msg_control = buff; + msg.msg_controllen = sizeof(buff); + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg == NULL) + return -EINVAL; + + /* packing files descriptors */ + if (nr_desc > 0) { + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + desclen = cmsg->cmsg_len = CMSG_LEN(sizeof(int) * nr_desc); + memcpy((int *)CMSG_DATA(cmsg), desc, sizeof(int) * nr_desc); + cmsg = CMSG_NXTHDR(&msg, cmsg); + + _D("packing file descriptors done"); + } + + /* finished packing updating the corect length */ + msg.msg_controllen = desclen; + } else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + } + + sndret = sendmsg(sock, &msg, 0); + + _D("sendmsg ret : %d", sndret); + if(sndret < 0) return -errno; + else return sndret; +} + static int __send_result_data(int fd, int cmd, unsigned char *kb_data, int datalen) { int len; @@ -260,6 +315,114 @@ static void __handle_agent_dead_signal(struct ucred *pcr) __agent_dead_handler(pcr->uid); } +static int __dispatch_get_socket_pair(int clifd, const app_pkt_t *pkt, struct ucred *cr) +{ + + char *caller; + char *callee; + char *socket_pair_key; + int socket_pair_key_len; + int *handles; + struct iovec vec[3]; + int msglen; + char buffer[1024]; + struct sockaddr_un saddr; + char *datacontrol_type; + bundle *kb; + + kb = bundle_decode(pkt->data, pkt->len); + caller = (char *)bundle_get_val(kb, AUL_K_CALLER_APPID); + callee = (char *)bundle_get_val(kb, AUL_K_CALLEE_APPID); + datacontrol_type = (char *)bundle_get_val(kb, "DATA_CONTOL_TYPE"); + + socket_pair_key_len = strlen(caller) + strlen(callee) + 2; + + socket_pair_key = (char *)calloc(socket_pair_key_len, sizeof(char)); + + if (socket_pair_key == NULL) { + _E("calloc fail"); + goto err_out; + } + + snprintf(socket_pair_key, socket_pair_key_len, "%s_%s", caller, callee); + _E("socket pair key : %s", socket_pair_key); + + handles = g_hash_table_lookup(__socket_pair_hash, socket_pair_key); + + if (handles == NULL) { + + handles = (int *)calloc(2, sizeof(int)); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) { + _E("error create socket pair"); + __send_result_to_client(clifd, -1); + goto err_out; + } + + if(handles[0] == -1) { + _E("error socket open"); + __send_result_to_client(clifd, -1); + goto err_out; + } + g_hash_table_insert(__socket_pair_hash, strdup(socket_pair_key), + handles); + + _E("New socket pair insert done."); + } + + + memset(&saddr, 0, sizeof(saddr)); + saddr.sun_family = AF_UNIX; + + SECURE_LOGD("amd send fd : [%d, %d]", handles[0], handles[1]); + vec[0].iov_base = buffer; + vec[0].iov_len = strlen(buffer) + 1; + + if (datacontrol_type != NULL) { + _E("datacontrol_type : %s", datacontrol_type); + if (strcmp(datacontrol_type, "consumer") == 0) { + + msglen = __send_message(clifd, vec, 1, &handles[0], 1); + if(msglen < 0) { + _E("Error[%d]: while sending message\n", -msglen); + __send_result_to_client(clifd, -1); + goto err_out; + } + close(handles[0]); + handles[0] = -1; + if (handles[1] == -1) { + _E("remove from hash : %s", socket_pair_key); + g_hash_table_remove(__socket_pair_hash, socket_pair_key); + } + + } + else { + msglen = __send_message(clifd, vec, 1, &handles[1], 1); + if(msglen < 0) { + _E("Error[%d]: while sending message\n", -msglen); + __send_result_to_client(clifd, -1); + goto err_out; + } + close(handles[1]); + handles[1] = -1; + if (handles[0] == -1) { + _E("remove from hash : %s", socket_pair_key); + g_hash_table_remove(__socket_pair_hash, socket_pair_key); + } + } + } + SECURE_LOGD("send_message msglen : [%d]\n", msglen); + + return 0; + +err_out: + if (handles) + free(handles); + if (socket_pair_key) + free(socket_pair_key); + + return -1; +} + static int __dispatch_app_group_add(int clifd, const app_pkt_t *pkt, struct ucred *cr) { bundle *b; @@ -767,6 +930,7 @@ end: } static app_cmd_dispatch_func dispatch_table[APP_CMD_MAX] = { + [APP_GET_SOCKET_PAIR] = __dispatch_get_socket_pair, [APP_START] = __dispatch_app_start, [APP_OPEN] = __dispatch_app_start, [APP_RESUME] = __dispatch_app_start, @@ -884,13 +1048,15 @@ static GSourceFuncs funcs = { .finalize = NULL }; -int _requset_init(void) +int _request_init(void) { int fd; int r; GPollFD *gpollfd; GSource *src; + __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); + fd = __create_sock_activation(); if (fd == -1) { _D("Create server socket without socket activation"); diff --git a/am_daemon/amd_request.h b/am_daemon/amd_request.h index 812fa032..db963fed 100644 --- a/am_daemon/amd_request.h +++ b/am_daemon/amd_request.h @@ -23,7 +23,7 @@ #ifndef __AUL_AMD_REQUEST_H_ #define __AUL_AMD_REQUEST_H_ -int _requset_init(void); +int _request_init(void); #endif diff --git a/include/app_sock.h b/include/app_sock.h index 342efb60..b9c5411e 100644 --- a/include/app_sock.h +++ b/include/app_sock.h @@ -66,6 +66,7 @@ enum app_cmd { APP_GROUP_RESUME, APP_GROUP_GET_LEADER_PID, APP_GET_STATUS, + APP_GET_SOCKET_PAIR, /* for special purpose */ AMD_RELOAD_APPINFO, @@ -105,6 +106,7 @@ int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int da int __app_send_raw_with_noreply_for_uid(int pid, uid_t uid, int cmd, unsigned char *kb_data, int datalen); int __app_send_raw_with_delay_reply(int pid, int cmd, unsigned char *kb_data, int datalen); int __app_send_raw_with_delay_reply_for_uid(int pid, uid_t uid, int cmd, unsigned char *kb_data, int datalen); +int __app_send_raw_with_fd_reply(int pid, uid_t uid, int cmd, unsigned char *kb_data, int datalen, int *ret_fd); int __app_agent_send_raw(int uid, int cmd, unsigned char *kb_data, int datalen); int __app_agent_send_raw_with_noreply(int uid, int cmd, unsigned char *kb_data, int datalen); app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr); diff --git a/include/aul.h b/include/aul.h index 42f99416..6e27d9bf 100644 --- a/include/aul.h +++ b/include/aul.h @@ -1697,6 +1697,7 @@ int aul_app_group_get_leader_pid(int pid); int aul_app_group_clear_top(void); int aul_app_group_is_top(void); +int aul_request_data_control_socket_pair(bundle *b, int *fd); /** @} */ diff --git a/src/app_sock.c b/src/app_sock.c index cf661b10..8d2d4f4a 100644 --- a/src/app_sock.c +++ b/src/app_sock.c @@ -33,6 +33,8 @@ #include "app_sock.h" #include "simple_util.h" +#define MAX_NR_OF_DESCRIPTORS 2 + static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec); @@ -416,6 +418,195 @@ retry_recv: } +static int __get_descriptors(struct cmsghdr *cmsg, struct msghdr *msg, int *fds, int maxdesc) +{ + int retnr = 0; + if (cmsg == NULL || msg == NULL) + return 0; + if (cmsg->cmsg_type != SCM_RIGHTS) + return 0; + + if (msg->msg_controllen > 0) { + int nrdesc; + int payload = cmsg->cmsg_len - sizeof(*cmsg); + int *recvdesc = (int *)CMSG_DATA(cmsg); + int i; + + nrdesc = payload / sizeof(int); + retnr = nrdesc < maxdesc ? nrdesc : maxdesc; + for (i = 0; i < nrdesc; ++i) { + if (maxdesc-- > 0) + *fds++ = *recvdesc++; + else + close(*recvdesc++); + } + } + return retnr; +} + +static int __recv_message(int sock, struct iovec *vec, int vec_max_size, int *vec_size, + int *fds, int *nr_fds) +{ + + char buff[CMSG_SPACE(sizeof(int) * MAX_NR_OF_DESCRIPTORS) + CMSG_SPACE(50)] = {0}; + struct msghdr msg = {0}; + struct cmsghdr *cmsg = NULL; + int ret; + + if (vec == NULL || vec_max_size < 1 || vec_size == NULL) + return -EINVAL; + + msg.msg_iov = vec; + msg.msg_iovlen = vec_max_size; + msg.msg_control = buff; + msg.msg_controllen = sizeof(buff); + + ret = recvmsg(sock, &msg, 0); + if (ret < 0) + return -errno; + *vec_size = msg.msg_iovlen; + + /* get the ANCILLARY data */ + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg == NULL) { + if(nr_fds != NULL) + *nr_fds = 0; + } else { + int iter = 0; + int fdnum = 0; + + for (; cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg), iter ++) { + switch(cmsg->cmsg_type) { + case SCM_RIGHTS: + if (fds != NULL) + fdnum = __get_descriptors(cmsg, &msg, fds, MAX_NR_OF_DESCRIPTORS); + if (nr_fds != NULL) + *nr_fds = fdnum; + break; + } + } + } + return ret; +} + +int __app_send_raw_with_fd_reply(int pid, uid_t uid, int cmd, unsigned char *kb_data, int datalen, int *ret_fd) +{ + int fd; + int len; + int ret; + int res = 0; + app_pkt_t *pkt = NULL; + + if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) { + _E("keybundle error\n"); + return -EINVAL; + } + + _D("pid(%d) : cmd(%d)", pid, cmd); + + fd = __create_client_sock(pid, uid); + if (fd < 0) { + _E("cannot create a client socket: %d", fd); + return -ECOMM; + } + + pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); + if (NULL == pkt) { + _E("Malloc Failed!"); + return -ENOMEM; + } + memset(pkt, 0, AUL_SOCK_MAXBUFF); + + pkt->cmd = cmd; + pkt->len = datalen; + memcpy(pkt->data, kb_data, datalen); + + if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) { + _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno); + if(len > 0) { + while (len != datalen + 8) { + ret = send(fd, &pkt->data[len - 8], datalen + 8 - len, 0); + if (ret < 0) { + _E("second send() failed - %d %d (errno: %d)", ret, datalen + 8, errno); + if (errno == EPIPE) { + _E("pid:%d, fd:%d\n", pid, fd); + } + close(fd); + if (pkt) { + free(pkt); + pkt = NULL; + } + return -ECOMM; + } + len += ret; + _D("send() len - %d %d", len, datalen + 8); + } + } else { + if (errno == EPIPE) { + _E("pid:%d, fd:%d\n", pid, fd); + } + close(fd); + if (pkt) { + free(pkt); + pkt = NULL; + } + + _E("send() failed: %d %s", errno, strerror(errno)); + return -ECOMM; + } + } + if (pkt) { + free(pkt); + pkt = NULL; + } + +retry_recv: + + if(cmd == APP_GET_SOCKET_PAIR) { + + char recv_buff[1024]; + struct iovec vec[3]; + int ret = 0; + int vec_len = 0; + int fds_len = 0; + int fds[1] = {0}; + + vec[0].iov_base = recv_buff; + vec[0].iov_len = 1024; + ret = __recv_message(fd, vec, 1, &vec_len, fds, &fds_len); + if (ret < 0) { + _E("Error[%d]. while receiving message\n", -ret); + if (fds_len > 0) + close(fds[0]); + return -ECOMM; + } else + recv_buff[ret] = '\0'; + + if(fds_len > 0){ + _E("fds : %d", fds[0]); + ret_fd[0] = fds[0]; + } + + } else { + len = recv(fd, &res, sizeof(int), 0); + if (len == -1) { + if (errno == EAGAIN) { + _E("recv timeout : cmd(%d) %s", cmd, strerror(errno)); + res = -EAGAIN; + } else if (errno == EINTR) { + _E("recv : %s", strerror(errno)); + goto retry_recv; + } else { + _E("recv error : %s", strerror(errno)); + res = -ECOMM; + } + } + } + close(fd); + + return res; +} + int __app_agent_send_raw(int uid, int cmd, unsigned char *kb_data, int datalen) { int fd; diff --git a/src/launch.c b/src/launch.c index 0ff4b795..e3dc7d78 100644 --- a/src/launch.c +++ b/src/launch.c @@ -151,6 +151,56 @@ static int __get_aul_error(int res) return ret; } +static int __app_send_cmd_with_fd(int pid, int uid, int cmd, bundle *kb, int *ret_fd) +{ + int datalen; + bundle_raw *kb_data = NULL; + int res = AUL_R_OK; + + res = bundle_encode(kb, &kb_data, &datalen); + if (res != BUNDLE_ERROR_NONE) { + return AUL_R_EINVAL; + } + if ((res = __app_send_raw_with_fd_reply(pid, uid, cmd, kb_data, datalen, ret_fd)) < 0) { + switch (res) { + case -EINVAL: + res = AUL_R_EINVAL; + break; + case -ECOMM: + res = AUL_R_ECOMM; + break; + case -EAGAIN: + res = AUL_R_ETIMEOUT; + break; + case -ELOCALLAUNCH_ID: + res = AUL_R_LOCAL; + break; + case -EILLEGALACCESS: + res = AUL_R_EILLACC; + break; + case -ETERMINATING: + res = AUL_R_ETERMINATING; + break; + case -ENOLAUNCHPAD: + res = AUL_R_ENOLAUNCHPAD; + break; +#ifdef _APPFW_FEATURE_APP_CONTROL_LITE + case -EUGLOCAL_LAUNCH: + res = AUL_R_UG_LOCAL; + break; +#endif + case -EREJECTED: + res = AUL_R_EREJECTED; + break; + default: + res = AUL_R_ERROR; + } + } + free(kb_data); + + return res; +} + /** * @brief encode kb and send it to 'pid' * @param[in] pid receiver's pid @@ -278,6 +328,50 @@ static int __app_resume_local() return 0; } +int app_request_to_launchpad_with_fd(int cmd, const char *appid, bundle *kb, int *fd, int uid) +{ + int must_free = 0; + int ret = 0; + + SECURE_LOGD("launch request : %s", appid); + if (kb == NULL) { + kb = bundle_create(); + must_free = 1; + } else + __clear_internal_key(kb); + + ret = __app_send_cmd_with_fd(AUL_UTIL_PID, uid, cmd, kb, fd); + + _D("launch request result : %d", ret); + if (ret == AUL_R_LOCAL) { + _E("app_request_to_launchpad : Same Process Send Local"); + bundle *b; + + switch (cmd) { + case APP_START: + case APP_START_RES: + b = bundle_dup(kb); + ret = __app_launch_local(b); + break; + case APP_OPEN: + case APP_RESUME: + case APP_RESUME_BY_PID: + ret = __app_resume_local(); + break; + default: + _E("no support packet"); + } + + } + + /* cleanup */ + if (must_free) + bundle_free(kb); + + return ret; +} + + /** * @brief start caller with kb * @return callee's pid @@ -524,6 +618,10 @@ SLPAPI void aul_finalize() return; } +SLPAPI int aul_request_data_control_socket_pair(bundle *kb, int *fd) +{ + return app_request_to_launchpad_with_fd(APP_GET_SOCKET_PAIR, NULL, kb, fd, getuid()); +} SLPAPI int aul_launch_app(const char *appid, bundle *kb) { |