merge back from tizen_2.1_smack
[framework/security/security-server.git] / src / server / security-server-system-observer.c
1 /*
2  * security-server
3  *
4  *  Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  *  Contact: Bumjin Im <bj.im@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 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <linux/netlink.h>
24 #include <linux/connector.h>
25 #include <linux/cn_proc.h>
26
27 #include <unistd.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <stdio.h>
31 #include <errno.h>
32
33 #include <security-server-common.h>
34 #include <security-server-system-observer.h>
35
36 #define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \
37                      sizeof(int))
38
39 static int nl_sock;
40
41 int connect_to_netlink()
42 {
43     struct sockaddr_nl sa_nl; /* netlink interface info */
44     char buff[NL_MESSAGE_SIZE];
45     struct nlmsghdr *hdr; /* for telling netlink what we want */
46     struct cn_msg *msg;   /* the actual connector message */
47
48     /* connect to netlink socket */
49     nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
50
51     if (-1 == nl_sock) {
52         SEC_SVR_DBG("socket failed: %s", strerror(errno));
53         return SECURITY_SERVER_ERROR_SOCKET;
54     }
55
56     bzero(&sa_nl, sizeof(sa_nl));
57     sa_nl.nl_family = AF_NETLINK;
58     sa_nl.nl_groups = CN_IDX_PROC;
59     sa_nl.nl_pid    = getpid();
60
61     if (-1 == bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl))) {
62         SEC_SVR_DBG("bind failed: %s", strerror(errno));
63         close(nl_sock);
64         return SECURITY_SERVER_ERROR_SOCKET;
65     }
66
67     /* Fill header */
68     hdr = (struct nlmsghdr *)buff;
69     hdr->nlmsg_len = NL_MESSAGE_SIZE;
70     hdr->nlmsg_type = NLMSG_DONE;
71     hdr->nlmsg_flags = 0;
72     hdr->nlmsg_seq = 0;
73     hdr->nlmsg_pid = getpid();
74
75     /* Fill message */
76     msg = (struct cn_msg *)NLMSG_DATA(hdr);
77     msg->id.idx = CN_IDX_PROC;  /* Connecting to process information */
78     msg->id.val = CN_VAL_PROC;
79     msg->seq = 0;
80     msg->ack = 0;
81     msg->flags = 0;
82     msg->len = sizeof(int);
83     *(int*)msg->data = PROC_CN_MCAST_LISTEN;
84
85     if (-1 == send(nl_sock, hdr, hdr->nlmsg_len, 0)) {
86         SEC_SVR_DBG("send failed: %s", strerror(errno));
87         close(nl_sock);
88         return SECURITY_SERVER_ERROR_SOCKET;
89     }
90
91     return SECURITY_SERVER_SUCCESS;
92 }
93
94 void handle_events(system_observer_config *data)
95 {
96     char buff[CONNECTOR_MAX_MSG_SIZE];
97     struct nlmsghdr *hdr;
98     struct proc_event *event;
99
100     fd_set fds;
101
102     while (1) {
103         FD_ZERO(&fds);
104         FD_SET(nl_sock, &fds);
105
106         if (0 > select(nl_sock + 1, &fds, NULL, NULL, NULL)) {
107             SEC_SVR_DBG("select failed: %s", strerror(errno));
108             return ;
109         }
110
111         /* If there were no events detected, return */
112         if (! FD_ISSET(nl_sock, &fds)) {
113             return ;
114         }
115
116         /* if there are events, make calls */
117         if (-1 == recv(nl_sock, buff, sizeof(buff), 0)) {
118             SEC_SVR_DBG("recv failed: %s", strerror(errno));
119             return ;
120         }
121
122         hdr = (struct nlmsghdr *)buff;
123
124         if (NLMSG_ERROR == hdr->nlmsg_type) {
125             SEC_SVR_DBG("%s", "NLMSG_ERROR");
126         } else if (NLMSG_DONE == hdr->nlmsg_type) {
127             event = (struct proc_event *)((struct cn_msg *)NLMSG_DATA(hdr))->data;
128             if (data->event_callback)
129                 (data->event_callback)(event);
130         }
131     }
132 }
133
134 void* system_observer_main(void *data) {
135     if (SECURITY_SERVER_SUCCESS == connect_to_netlink()) {
136         handle_events((system_observer_config *)data);
137         close(nl_sock);
138     }
139     return NULL;
140 }
141