blob: 1359d642b1825a37afce684c963d32064544f1cf [file] [log] [blame]
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06001/* Copyright (c) 2012-2014,2016 The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/net.h>
16#include <linux/socket.h>
17#include <linux/errno.h>
18#include <linux/mm.h>
19#include <linux/poll.h>
20#include <linux/fcntl.h>
21#include <linux/gfp.h>
22#include <linux/uaccess.h>
23#include <linux/kernel.h>
24#include <linux/msm_ipc.h>
25#include <linux/rwsem.h>
26#include <linux/uaccess.h>
27
28#include <net/sock.h>
29#include "ipc_router_private.h"
30#include "ipc_router_security.h"
31
32#define IRSC_COMPLETION_TIMEOUT_MS 30000
33#define SEC_RULES_HASH_SZ 32
34
35#ifndef SIZE_MAX
36#define SIZE_MAX ((size_t)-1)
37#endif
38
39struct security_rule {
40 struct list_head list;
41 u32 service_id;
42 u32 instance_id;
43 unsigned int reserved;
44 int num_group_info;
45 kgid_t *group_id;
46};
47
48static DECLARE_RWSEM(security_rules_lock_lha4);
49static struct list_head security_rules[SEC_RULES_HASH_SZ];
50static DECLARE_COMPLETION(irsc_completion);
51
52/**
53 * wait_for_irsc_completion() - Wait for IPC Router Security Configuration
54 * (IRSC) to complete
55 */
56void wait_for_irsc_completion(void)
57{
58 unsigned long rem_jiffies;
59
60 do {
61 rem_jiffies = wait_for_completion_timeout
62 (&irsc_completion,
63 msecs_to_jiffies(IRSC_COMPLETION_TIMEOUT_MS));
64 if (rem_jiffies)
65 return;
66 pr_err("%s: waiting for IPC Security Conf.\n", __func__);
67 } while (1);
68}
69
70/**
71 * signal_irsc_completion() - Signal the completion of IRSC
72 */
73void signal_irsc_completion(void)
74{
75 complete_all(&irsc_completion);
76}
77
78/**
79 * check_permisions() - Check whether the process has permissions to
80 * create an interface handle with IPC Router
81 *
82 * @return: true if the process has permissions, else false.
83 */
84int check_permissions(void)
85{
86 int rc = 0;
87
88 if (capable(CAP_NET_RAW) || capable(CAP_NET_BIND_SERVICE))
89 rc = 1;
90 return rc;
91}
92EXPORT_SYMBOL(check_permissions);
93
94/**
95 * msm_ipc_config_sec_rules() - Add a security rule to the database
96 * @arg: Pointer to the buffer containing the rule.
97 *
98 * @return: 0 if successfully added, < 0 for error.
99 *
100 * A security rule is defined using <Service_ID: Group_ID> tuple. The rule
101 * implies that a user-space process in order to send a QMI message to
102 * service Service_ID should belong to the Linux group Group_ID.
103 */
104int msm_ipc_config_sec_rules(void *arg)
105{
106 struct config_sec_rules_args sec_rules_arg;
107 struct security_rule *rule, *temp_rule;
108 int key;
109 size_t kgroup_info_sz;
110 int ret;
111 size_t group_info_sz;
112 gid_t *group_id = NULL;
113 int loop;
114
115 if (!uid_eq(current_euid(), GLOBAL_ROOT_UID))
116 return -EPERM;
117
118 ret = copy_from_user(&sec_rules_arg, (void *)arg,
119 sizeof(sec_rules_arg));
120 if (ret)
121 return -EFAULT;
122
123 if (sec_rules_arg.num_group_info <= 0)
124 return -EINVAL;
125
126 if (sec_rules_arg.num_group_info > (SIZE_MAX / sizeof(gid_t))) {
127 pr_err("%s: Integer Overflow %zu * %d\n", __func__,
128 sizeof(gid_t), sec_rules_arg.num_group_info);
129 return -EINVAL;
130 }
131 group_info_sz = sec_rules_arg.num_group_info * sizeof(gid_t);
132
133 if (sec_rules_arg.num_group_info > (SIZE_MAX / sizeof(kgid_t))) {
134 pr_err("%s: Integer Overflow %zu * %d\n", __func__,
135 sizeof(kgid_t), sec_rules_arg.num_group_info);
136 return -EINVAL;
137 }
138 kgroup_info_sz = sec_rules_arg.num_group_info * sizeof(kgid_t);
139
140 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
141 if (!rule)
142 return -ENOMEM;
143
144 rule->group_id = kzalloc(kgroup_info_sz, GFP_KERNEL);
145 if (!rule->group_id) {
146 kfree(rule);
147 return -ENOMEM;
148 }
149
150 group_id = kzalloc(group_info_sz, GFP_KERNEL);
151 if (!group_id) {
152 kfree(rule->group_id);
153 kfree(rule);
154 return -ENOMEM;
155 }
156
157 rule->service_id = sec_rules_arg.service_id;
158 rule->instance_id = sec_rules_arg.instance_id;
159 rule->reserved = sec_rules_arg.reserved;
160 rule->num_group_info = sec_rules_arg.num_group_info;
161 ret = copy_from_user(group_id, ((void *)(arg + sizeof(sec_rules_arg))),
162 group_info_sz);
163 if (ret) {
164 kfree(group_id);
165 kfree(rule->group_id);
166 kfree(rule);
167 return -EFAULT;
168 }
169 for (loop = 0; loop < rule->num_group_info; loop++)
170 rule->group_id[loop] = make_kgid(current_user_ns(),
171 group_id[loop]);
172 kfree(group_id);
173
174 key = rule->service_id & (SEC_RULES_HASH_SZ - 1);
175 down_write(&security_rules_lock_lha4);
176 if (rule->service_id == ALL_SERVICE) {
177 temp_rule = list_first_entry(&security_rules[key],
178 struct security_rule, list);
179 list_del(&temp_rule->list);
180 kfree(temp_rule->group_id);
181 kfree(temp_rule);
182 }
183 list_add_tail(&rule->list, &security_rules[key]);
184 up_write(&security_rules_lock_lha4);
185
186 if (rule->service_id == ALL_SERVICE)
187 msm_ipc_sync_default_sec_rule((void *)rule);
188 else
189 msm_ipc_sync_sec_rule(rule->service_id, rule->instance_id,
190 (void *)rule);
191
192 return 0;
193}
194EXPORT_SYMBOL(msm_ipc_config_sec_rules);
195
196/**
197 * msm_ipc_add_default_rule() - Add default security rule
198 *
199 * @return: 0 on success, < 0 on error/
200 *
201 * This function is used to ensure the basic security, if there is no
202 * security rule defined for a service. It can be overwritten by the
203 * default security rule from user-space script.
204 */
205static int msm_ipc_add_default_rule(void)
206{
207 struct security_rule *rule;
208 int key;
209
210 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
211 if (!rule)
212 return -ENOMEM;
213
214 rule->group_id = kzalloc(sizeof(*rule->group_id), GFP_KERNEL);
215 if (!rule->group_id) {
216 kfree(rule);
217 return -ENOMEM;
218 }
219
220 rule->service_id = ALL_SERVICE;
221 rule->instance_id = ALL_INSTANCE;
222 rule->num_group_info = 1;
223 *rule->group_id = AID_NET_RAW;
224 down_write(&security_rules_lock_lha4);
225 key = (ALL_SERVICE & (SEC_RULES_HASH_SZ - 1));
226 list_add_tail(&rule->list, &security_rules[key]);
227 up_write(&security_rules_lock_lha4);
228 return 0;
229}
230
231/**
232 * msm_ipc_get_security_rule() - Get the security rule corresponding to a
233 * service
234 * @service_id: Service ID for which the rule has to be got.
235 * @instance_id: Instance ID for which the rule has to be got.
236 *
237 * @return: Returns the rule info on success, NULL on error.
238 *
239 * This function is used when the service comes up and gets registered with
240 * the IPC Router.
241 */
242void *msm_ipc_get_security_rule(u32 service_id, u32 instance_id)
243{
244 int key;
245 struct security_rule *rule;
246
247 key = (service_id & (SEC_RULES_HASH_SZ - 1));
248 down_read(&security_rules_lock_lha4);
249 /* Return the rule for a specific <service:instance>, if found. */
250 list_for_each_entry(rule, &security_rules[key], list) {
251 if ((rule->service_id == service_id) &&
252 (rule->instance_id == instance_id)) {
253 up_read(&security_rules_lock_lha4);
254 return (void *)rule;
255 }
256 }
257
258 /* Return the rule for a specific service, if found. */
259 list_for_each_entry(rule, &security_rules[key], list) {
260 if ((rule->service_id == service_id) &&
261 (rule->instance_id == ALL_INSTANCE)) {
262 up_read(&security_rules_lock_lha4);
263 return (void *)rule;
264 }
265 }
266
267 /* Return the default rule, if no rule defined for a service. */
268 key = (ALL_SERVICE & (SEC_RULES_HASH_SZ - 1));
269 list_for_each_entry(rule, &security_rules[key], list) {
270 if ((rule->service_id == ALL_SERVICE) &&
271 (rule->instance_id == ALL_INSTANCE)) {
272 up_read(&security_rules_lock_lha4);
273 return (void *)rule;
274 }
275 }
276 up_read(&security_rules_lock_lha4);
277 return NULL;
278}
279EXPORT_SYMBOL(msm_ipc_get_security_rule);
280
281/**
282 * msm_ipc_check_send_permissions() - Check if the sendng process has
283 * permissions specified as per the rule
284 * @data: Security rule to be checked.
285 *
286 * @return: true if the process has permissions, else false.
287 *
288 * This function is used to check if the current executing process has
289 * permissions to send message to the remote entity. The security rule
290 * corresponding to the remote entity is specified by "data" parameter
291 */
292int msm_ipc_check_send_permissions(void *data)
293{
294 int i;
295 struct security_rule *rule = (struct security_rule *)data;
296
297 /* Source/Sender is Root user */
298 if (uid_eq(current_euid(), GLOBAL_ROOT_UID))
299 return 1;
300
301 /* Destination has no rules defined, possibly a client. */
302 if (!rule)
303 return 1;
304
305 for (i = 0; i < rule->num_group_info; i++) {
306 if (!gid_valid(rule->group_id[i]))
307 continue;
308 if (in_egroup_p(rule->group_id[i]))
309 return 1;
310 }
311 return 0;
312}
313EXPORT_SYMBOL(msm_ipc_check_send_permissions);
314
315/**
316 * msm_ipc_router_security_init() - Initialize the security rule database
317 *
318 * @return: 0 if successful, < 0 for error.
319 */
320int msm_ipc_router_security_init(void)
321{
322 int i;
323
324 for (i = 0; i < SEC_RULES_HASH_SZ; i++)
325 INIT_LIST_HEAD(&security_rules[i]);
326
327 msm_ipc_add_default_rule();
328 return 0;
329}
330EXPORT_SYMBOL(msm_ipc_router_security_init);