summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhyunho kang <hhstark.kang@samsung.com>2015-10-27 17:13:53 +0900
committerhyunho kang <hhstark.kang@samsung.com>2015-10-27 19:30:29 +0900
commit693dbd6d00af80f9cfa025bcfc7cdd50c551460e (patch)
tree5055122b5e77947dda368f314fd5c167a24250b2
parent1fde74eb0bdfdb6e3e7f880532460f65bd0022d2 (diff)
downloadaul-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.c2
-rw-r--r--am_daemon/amd_request.c168
-rw-r--r--am_daemon/amd_request.h2
-rw-r--r--include/app_sock.h2
-rw-r--r--include/aul.h1
-rw-r--r--src/app_sock.c191
-rw-r--r--src/launch.c98
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)
{