4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
6 * Contact: Bumjin Im <bj.im@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
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>
33 #include <security-server-common.h>
34 #include <security-server-system-observer.h>
36 #define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \
41 int connect_to_netlink()
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 */
48 /* connect to netlink socket */
49 nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
52 SEC_SVR_DBG("socket failed: %s", strerror(errno));
53 return SECURITY_SERVER_ERROR_SOCKET;
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();
61 if (-1 == bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl))) {
62 SEC_SVR_DBG("bind failed: %s", strerror(errno));
64 return SECURITY_SERVER_ERROR_SOCKET;
68 hdr = (struct nlmsghdr *)buff;
69 hdr->nlmsg_len = NL_MESSAGE_SIZE;
70 hdr->nlmsg_type = NLMSG_DONE;
73 hdr->nlmsg_pid = getpid();
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;
82 msg->len = sizeof(int);
83 *(int*)msg->data = PROC_CN_MCAST_LISTEN;
85 if (-1 == send(nl_sock, hdr, hdr->nlmsg_len, 0)) {
86 SEC_SVR_DBG("send failed: %s", strerror(errno));
88 return SECURITY_SERVER_ERROR_SOCKET;
91 return SECURITY_SERVER_SUCCESS;
94 void handle_events(system_observer_config *data)
96 char buff[CONNECTOR_MAX_MSG_SIZE];
98 struct proc_event *event;
104 FD_SET(nl_sock, &fds);
106 if (0 > select(nl_sock + 1, &fds, NULL, NULL, NULL)) {
107 SEC_SVR_DBG("select failed: %s", strerror(errno));
111 /* If there were no events detected, return */
112 if (! FD_ISSET(nl_sock, &fds)) {
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));
122 hdr = (struct nlmsghdr *)buff;
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);
134 void* system_observer_main(void *data) {
135 if (SECURITY_SERVER_SUCCESS == connect_to_netlink()) {
136 handle_events((system_observer_config *)data);