tizen 2.3 release
[framework/system/deviced.git] / src / tima / tima-lkm.c
1 /*
2  * LKM in TIMA(TZ based Integrity Measurement Architecture)
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <assert.h>
21 #include <limits.h>
22 #include <libudev.h>
23 #include <Ecore.h>
24
25 #include "core/log.h"
26 #include "core/common.h"
27 #include "core/devices.h"
28 #include "core/udev.h"
29
30 #include "noti.h"
31
32 /*
33  * tzapp interface
34  */
35 #define LKM_FAIL                -1
36 #define LKM_SUCCESS             0
37 #define LKM_ERROR               1
38
39 /*
40  * udev
41  */
42 #define TIMA_SUBSYSTEM          "tima"
43 #define TIMA_STATUS             "TIMA_STATUS"
44 #define TIMA_RESULT             "TIMA_RESULT"
45
46 static struct udev *udev;
47 static struct udev_monitor *mon;
48 static int ufd;
49 static Ecore_Fd_Handler *ufdh;
50
51 static int noti_id = 0;
52
53 static void tima_notification(int status)
54 {
55         switch (status) {
56         case LKM_FAIL:
57                 _I("certification failed");
58                 break;
59         default:
60                 _E("internal error (%d)", status);
61                 break;
62         }
63
64         noti_id = tima_lkm_prevention_noti_on();
65         if (noti_id < 0) {
66                 _E("FAIL: tima_lkm_prevention_noti_on()");
67                 noti_id = 0;
68         }
69 }
70
71 /*
72  * tima_uevent_cb - uevent callback
73  *
74  * This callback receive the uevent from kernel module driver
75  */
76 static Eina_Bool tima_uevent_cb(void *data, Ecore_Fd_Handler *handler)
77 {
78         struct udev_device *dev;
79         struct udev_list_entry *list, *entry;
80         const char *name, *value, *msg;
81         int status;
82
83         dev = udev_monitor_receive_device(mon);
84         if (!dev)
85                 return EINA_TRUE;
86
87         /* Getting the First element of the device entry list */
88         list = udev_device_get_properties_list_entry(dev);
89         if (!list) {
90                 _E("can't get udev_device_get_properties_list_entry()");
91                 goto err_unref_dev;
92         }
93
94         udev_list_entry_foreach(entry, list) {
95                 name = udev_list_entry_get_name(entry);
96
97                 if (!strcmp(name, TIMA_RESULT)) {
98                         msg = udev_list_entry_get_value(entry);
99                         _D("tzapp: msg(%s)", msg);
100                 }
101
102                 if (!strcmp(name, TIMA_STATUS)) {
103                         value = udev_list_entry_get_value(entry);
104                         status = atoi(value);
105                         _D("tzapp: ret(%d)", status);
106
107                         if (status != LKM_SUCCESS) {
108                                 tima_notification(status);
109                                 goto err_unref_dev;
110                         }
111                 }
112         }
113         udev_device_unref(dev);
114         return EINA_TRUE;
115
116 err_unref_dev:
117         udev_device_unref(dev);
118 err:
119         return EINA_FALSE;
120 }
121
122 /*
123  * tima_uevent_stop - disable udev event control
124  */
125 static int tima_uevent_stop(void)
126 {
127         if (ufdh) {
128                 ecore_main_fd_handler_del(ufdh);
129                 ufdh = NULL;
130         }
131
132         if (ufd >= 0) {
133                 close(ufd);
134                 ufd = -1;
135         }
136
137         if (mon) {
138                 struct udev_device *dev = udev_monitor_receive_device(mon);
139                 if (dev) {
140                         udev_device_unref(dev);
141                         dev = NULL;
142                 }
143                 udev_monitor_unref(mon);
144                 mon = NULL;
145         }
146
147         if (udev) {
148                 udev_unref(udev);
149                 udev = NULL;
150         }
151
152         return 0;
153 }
154
155 /*
156  * tima_uevent_start - enable udev event for TIMA
157  */
158 static int tima_uevent_start(void)
159 {
160         int ret;
161
162         udev = udev_new();
163         if (!udev) {
164                 _E("can't create udev");
165                 goto stop;
166         }
167
168         mon = udev_monitor_new_from_netlink(udev, UDEV);
169         if (!mon) {
170                 _E("can't udev_monitor create");
171                 goto stop;
172         }
173
174         ret = udev_monitor_set_receive_buffer_size(mon, 1024);
175         if (ret < 0) {
176                 _E("fail to set receive buffer size");
177                 goto stop;
178         }
179
180         ret = udev_monitor_filter_add_match_subsystem_devtype(mon, TIMA_SUBSYSTEM, NULL);
181         if (ret < 0) {
182                 _E("can't apply subsystem filter");
183                 goto stop;
184         }
185
186         ret = udev_monitor_filter_update(mon);
187         if (ret < 0)
188                 _E("error udev_monitor_filter_update");
189
190         ufd = udev_monitor_get_fd(mon);
191         if (ufd < 0) {
192                 _E("can't udev_monitor_get_fd");
193                 goto stop;
194         }
195
196         ufdh = ecore_main_fd_handler_add(ufd, ECORE_FD_READ, tima_uevent_cb, NULL, NULL, NULL);
197         if (!ufdh) {
198                 _E("can't ecore_main_fd_handler_add");
199                 goto stop;
200         }
201
202         ret = udev_monitor_enable_receiving(mon);
203         if (ret < 0) {
204                 _E("can't unable to subscribe to udev events");
205                 goto stop;
206         }
207
208         return 0;
209 stop:
210         tima_uevent_stop();
211         return -EINVAL;
212 }
213
214 void tima_lkm_init(void)
215 {
216         tima_uevent_start();
217 }
218
219 void tima_lkm_exit(void)
220 {
221         tima_uevent_stop();
222 }