fixed smack define related build error
[framework/appfw/debug-launchpad.git] / src / app_sock.c
1 /*
2  *  debug-launchpad
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jungmin Cho <chivalry.cho@samsung.com>, Gwangho Hwang <gwang.hwang@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <sys/types.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/smack.h>
29 #include <errno.h>
30 #include <fcntl.h>
31
32 #include "app_sock.h"
33 #include "simple_util.h"
34
35 static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen,
36                    int nsec);
37
38
39 static inline void __set_sock_option(int fd, int cli)
40 {
41         int size;
42         struct timeval tv = { 3, 200 * 1000 };  /*  3.2 sec */
43
44         size = AUL_SOCK_MAXBUFF;
45         setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
46         setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
47         if (cli)
48                 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
49 }
50
51 int __create_server_sock(int pid)
52 {
53         struct sockaddr_un saddr;
54         struct sockaddr_un p_saddr;
55         int fd;
56         mode_t orig_mask;
57
58         /* Create basedir for our sockets */
59         orig_mask = umask(0);
60         (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
61         umask(orig_mask);
62
63         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
64         /*  support above version 2.6.27*/
65         if (fd < 0) {
66                 if (errno == EINVAL) {
67                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
68                         if (fd < 0) {
69                                 _E("second chance - socket create error");
70                                 return -1;
71                         }
72                 } else {
73                         _E("socket error");
74                         return -1;
75                 }
76         }
77
78         memset(&saddr, 0, sizeof(saddr));
79         saddr.sun_family = AF_UNIX;
80         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
81         unlink(saddr.sun_path);
82
83         /* labeling to socket for SMACK */
84         if(getuid() == 0) {     // this is meaningful iff current user is ROOT
85                 if(smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) {
86                         /* in case of unsupported filesystem on 'socket' */
87                         /* or permission error by using 'emulator', bypass*/
88                         if((errno != EOPNOTSUPP) && (errno != EPERM)) {
89                                 _E("labeling to socket(IPOUT) error");
90                                 close(fd);
91                                 return -1;
92                         }
93                 }
94                 if(smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) {
95                         /* in case of unsupported filesystem on 'socket' */
96                         /* or permission error by using 'emulator', bypass*/
97                         if((errno != EOPNOTSUPP) && (errno != EPERM)) {
98                                 _E("labeling to socket(IPIN) error");
99                                 close(fd);
100                                 return -1;
101                         }
102                 }
103         }
104
105         if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
106                 _E("bind error");
107                 close(fd);
108                 return -1;
109         }
110
111         if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
112                 /* Flawfinder: ignore*/
113                 _E("failed to change the socket permission");
114                 close(fd);
115                 return -1;
116         }
117
118         __set_sock_option(fd, 0);
119
120         if (listen(fd, 128) == -1) {
121                 _E("listen error");
122                 close(fd);
123                 return -1;
124         }
125
126         /* support app launched by shell script */
127         /*if (pid != LAUNCHPAD_PID) {
128                 int pgid;
129                 pgid = getpgid(pid);
130                 if (pgid > 1) {
131                         snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d",
132                                  AUL_SOCK_PREFIX, pgid);
133                         if (link(saddr.sun_path, p_saddr.sun_path) < 0) {
134                                 if (errno == EEXIST)
135                                         _D("pg path - already exists");
136                                 else
137                                         _E("pg path - unknown create error");
138                         }
139                 }
140         }*/
141
142         return fd;
143 }
144
145 int __create_client_sock(int pid)
146 {
147         int fd = -1;
148         struct sockaddr_un saddr = { 0, };
149         int retry = 1;
150         int ret = -1;
151
152         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);    
153         /*  support above version 2.6.27*/
154         if (fd < 0) {
155                 if (errno == EINVAL) {
156                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
157                         if (fd < 0) {
158                                 _E("second chance - socket create error");
159                                 return -1;
160                         }
161                 } else {
162                         _E("socket error");
163                         return -1;
164                 }
165         }
166
167         saddr.sun_family = AF_UNIX;
168         snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid);
169  retry_con:
170         ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
171                         100 * 1000);
172         if (ret < -1) {
173                 _E("maybe peer not launched or peer daed\n");
174                 if (retry > 0) {
175                         usleep(100 * 1000);
176                         retry--;
177                         goto retry_con;
178                 }
179         }
180         if (ret < 0) {
181                 close(fd);
182                 return -1;
183         }
184
185         __set_sock_option(fd, 1);
186
187         return fd;
188 }
189
190 static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
191                    int nsec)
192 {
193         int flags;
194         int ret;
195         int error;
196         socklen_t len;
197         fd_set readfds;
198         fd_set writefds;
199         struct timeval timeout;
200
201         flags = fcntl(fd, F_GETFL, 0);
202         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
203
204         error = 0;
205         if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) {
206                 if (errno != EAGAIN && errno != EINPROGRESS) {
207                         fcntl(fd, F_SETFL, flags);      
208                         return (-2);
209                 }
210         }
211
212         /* Do whatever we want while the connect is taking place. */
213         if (ret == 0)
214                 goto done;      /* connect completed immediately */
215
216         FD_ZERO(&readfds);
217         FD_SET(fd, &readfds);
218         writefds = readfds;
219         timeout.tv_sec = 0;
220         timeout.tv_usec = nsec;
221
222         if ((ret = select(fd + 1, &readfds, &writefds, NULL, 
223                         nsec ? &timeout : NULL)) == 0) {
224                 close(fd);      /* timeout */
225                 errno = ETIMEDOUT;
226                 return (-1);
227         }
228
229         if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
230                 len = sizeof(error);
231                 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
232                         return (-1);    /* Solaris pending error */
233         } else
234                 return (-1);    /* select error: sockfd not set*/
235
236  done:
237         (void) fcntl(fd, F_SETFL, flags);
238         if (error) {
239                 close(fd);
240                 errno = error;
241                 return (-1);
242         }
243         return (0);
244 }
245
246 /**
247  * @brief       Send data (in raw) to the process with 'pid' via socket
248  */
249 int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen)
250 {
251         int fd;
252         int len;
253         int ret;
254         int res = 0;
255         app_pkt_t *pkt = NULL;
256
257         if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
258                 _E("keybundle error\n");
259                 return -EINVAL;
260         }
261
262         _D("pid(%d) : cmd(%d)", pid, cmd);
263
264         fd = __create_client_sock(pid);
265         if (fd < 0)
266                 return -ECOMM;
267
268         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
269         if (NULL == pkt) {
270                 _E("Malloc Failed!");
271                 return -ENOMEM;
272         }
273         memset(pkt, 0, AUL_SOCK_MAXBUFF);
274
275         pkt->cmd = cmd;
276         pkt->len = datalen;
277         memcpy(pkt->data, kb_data, datalen);
278
279         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
280                 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
281                 if(len > 0) {
282                         while (len != datalen + 8) {
283                                 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
284                                 if (ret < 0) {
285                                         _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
286                                         if (errno == EPIPE) {
287                                                 _E("pid:%d, fd:%d\n", pid, fd);
288                                         }
289                                         close(fd);
290                                         if (pkt) {
291                                                 free(pkt);
292                                                 pkt = NULL;
293                                         }
294                                         return -ECOMM;
295                                 }
296                                 len += ret;
297                                 _D("sendto() len - %d %d", len, datalen + 8);
298                         }
299                 } else {
300                         if (errno == EPIPE) {
301                                 _E("pid:%d, fd:%d\n", pid, fd);
302                         }
303                         close(fd);
304                         if (pkt) {
305                                 free(pkt);
306                                 pkt = NULL;
307                         }
308                         return -ECOMM;
309                 }
310         }
311         if (pkt) {
312                 free(pkt);
313                 pkt = NULL;
314         }
315
316         len = recv(fd, &res, sizeof(int), 0);
317         if (len == -1) {
318                 if (errno == EAGAIN) {
319                         _E("recv timeout \n");
320                         res = -EAGAIN;
321                 } else {
322                         _E("recv error\n");
323                         res = -ECOMM;
324                 }
325         }
326         close(fd);
327
328         return res;
329 }
330
331 int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen)
332 {
333         int fd;
334         int len;
335         int ret;
336         int res = 0;
337         app_pkt_t *pkt = NULL;
338
339         if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) {
340                 _E("keybundle error\n");
341                 return -EINVAL;
342         }
343
344         _D("pid(%d) : cmd(%d)", pid, cmd);
345
346         fd = __create_client_sock(pid);
347         if (fd < 0)
348                 return -ECOMM;
349
350         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
351         if (NULL == pkt) {
352                 _E("Malloc Failed!");
353                 return -ENOMEM;
354         }
355         memset(pkt, 0, AUL_SOCK_MAXBUFF);
356
357         pkt->cmd = cmd;
358         pkt->len = datalen;
359         memcpy(pkt->data, kb_data, datalen);
360
361         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
362                 _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno);
363                 if(len > 0) {
364                         while (len != datalen + 8) {
365                                 ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0);
366                                 if (ret < 0) {
367                                         _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno);
368                                         if (errno == EPIPE) {
369                                                 _E("pid:%d, fd:%d\n", pid, fd);
370                                         }
371                                         close(fd);
372                                         if (pkt) {
373                                                 free(pkt);
374                                                 pkt = NULL;
375                                         }
376                                         return -ECOMM;
377                                 }
378                                 len += ret;
379                                 _D("sendto() len - %d %d", len, datalen + 8);
380                         }
381                 } else {
382                         if (errno == EPIPE) {
383                                 _E("pid:%d, fd:%d\n", pid, fd);
384                         }
385                         close(fd);
386                         if (pkt) {
387                                 free(pkt);
388                                 pkt = NULL;
389                         }
390                         return -ECOMM;
391                 }
392         }
393         if (pkt) {
394                 free(pkt);
395                 pkt = NULL;
396         }
397
398         close(fd);
399
400         return res;
401 }
402
403 app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr)
404 {
405         int len;
406         int ret;
407         struct sockaddr_un aul_addr = { 0, };
408         int sun_size;
409         app_pkt_t *pkt = NULL;
410         int cl = sizeof(struct ucred);
411
412         sun_size = sizeof(struct sockaddr_un);
413
414         if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
415                              (socklen_t *) &sun_size)) == -1) {
416                 if (errno != EINTR)
417                         _E("accept error");
418                 return NULL;
419         }
420
421         if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
422                        (socklen_t *) &cl) < 0) {
423                 _E("peer information error");
424                 close(*clifd);
425                 return NULL;
426         }
427
428         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
429         if(pkt == NULL) {
430                 close(*clifd);
431                 return NULL;
432         }
433         memset(pkt, 0, AUL_SOCK_MAXBUFF);
434
435         __set_sock_option(*clifd, 1);
436
437  retry_recv:
438         /* receive single packet from socket */
439         len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0);
440         if (len < 0)
441                 if (errno == EINTR)
442                         goto retry_recv;
443
444         if (len < 8) {
445                 _E("recv error %d %d", len, pkt->len);
446                 free(pkt);
447                 close(*clifd);
448                 return NULL;
449         }
450
451         while( len != (pkt->len + 8) ) {
452                 ret = recv(*clifd, &pkt->data[len-8], AUL_SOCK_MAXBUFF, 0);
453                 if (ret < 0) {
454                         _E("recv error %d %d", len, pkt->len);
455                         free(pkt);
456                         close(*clifd);
457                         return NULL;
458                 }
459                 len += ret;
460                 _D("recv len %d %d", len, pkt->len);
461         }
462
463         return pkt;
464 }
465
466 app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen)
467 {
468         int fd;
469         int len;
470         app_pkt_t *pkt = NULL;
471
472         fd = __create_client_sock(pid);
473         if (fd < 0)
474                 return NULL;
475
476         pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
477         if (NULL == pkt) {
478                 _E("Malloc Failed!");
479                 return NULL;
480         }
481         memset(pkt, 0, AUL_SOCK_MAXBUFF);
482
483         pkt->cmd = cmd;
484         pkt->len = datalen;
485         if(kb_data) {
486                 memcpy(pkt->data, kb_data, datalen);
487         }
488
489         if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) {
490                 _E("sendto() failed - %d", len);
491                 if (errno == EPIPE) {
492                         _E("pid:%d, fd:%d\n", pid, fd);
493                 }
494                 close(fd);
495
496                 free(pkt);
497                 return NULL;
498         }
499
500 retry_recv:
501        /* receive single packet from socket */
502         len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
503         if (len == -1) {
504                 if (errno == EAGAIN) {
505                         _E("recv timeout \n");
506                         free(pkt);
507                         close(fd);
508                         return NULL;
509                 } else if (errno == EINTR) {
510                         goto retry_recv;
511                 } else {
512                         _E("recv error %s\n", strerror(errno));
513                         free(pkt);
514                         close(fd);
515                         return NULL;
516                 }
517         } else
518                 _D("recv result  = %d", len);
519         close(fd);
520
521         return pkt;
522 }
523
524