msm: ipc: Security updates to IPC Router
In order to provide fine-grained access control to QMI services, a security script from user-space will feed the security rules to IPC Router. The security rule implies that in order to send a QMI message to a service, a client process should belong to a specific Linux/Android group. IPC Router, after receiving the security rules, will enforce the access control rules. Change-Id: I49f8d7c0067fc37cb0b4de2ccb46a575905ef64f Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org> Signed-off-by: Mekala Natarajan <mekalan@codeaurora.org>
This commit is contained in:
committed by
Iliyan Malchev
parent
7e0cc6f69e
commit
e63c5a50c9
@@ -1493,6 +1493,16 @@ config MSM_IPC_ROUTER_SMD_XPRT
|
||||
help
|
||||
SMD Transport Layer for IPC Router
|
||||
|
||||
config MSM_IPC_ROUTER_SECURITY
|
||||
depends on MSM_IPC_ROUTER
|
||||
bool "MSM IPC Router Security support"
|
||||
help
|
||||
This feature of IPC Router will enforce security rules
|
||||
configured by a security script from the user-space. IPC Router
|
||||
once configured with the security rules will ensure that the
|
||||
sender of the message to a service belongs to the relevant
|
||||
Linux group as configured by the security script.
|
||||
|
||||
config MSM_ONCRPCROUTER_DEBUG
|
||||
depends on MSM_ONCRPCROUTER
|
||||
default y
|
||||
|
||||
@@ -138,6 +138,7 @@ obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter.o
|
||||
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_device.o
|
||||
obj-$(CONFIG_MSM_IPC_ROUTER) += ipc_router.o
|
||||
obj-$(CONFIG_MSM_IPC_ROUTER)+= ipc_socket.o
|
||||
obj-$(CONFIG_MSM_IPC_ROUTER_SECURITY)+= msm_ipc_router_security.o
|
||||
obj-$(CONFIG_DEBUG_FS) += smd_rpc_sym.o
|
||||
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_servers.o
|
||||
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "ipc_router.h"
|
||||
#include "modem_notifier.h"
|
||||
#include "msm_ipc_router_security.h"
|
||||
|
||||
enum {
|
||||
SMEM_LOG = 1U << 0,
|
||||
@@ -111,6 +112,7 @@ static wait_queue_head_t newserver_wait;
|
||||
struct msm_ipc_server {
|
||||
struct list_head list;
|
||||
struct msm_ipc_port_name name;
|
||||
int synced_sec_rule;
|
||||
struct list_head server_port_list;
|
||||
};
|
||||
|
||||
@@ -129,6 +131,7 @@ struct msm_ipc_router_remote_port {
|
||||
wait_queue_head_t quota_wait;
|
||||
uint32_t tx_quota_cnt;
|
||||
struct mutex quota_lock;
|
||||
void *sec_rule;
|
||||
};
|
||||
|
||||
struct msm_ipc_router_xprt_info {
|
||||
@@ -552,6 +555,7 @@ static struct msm_ipc_router_remote_port *msm_ipc_router_create_remote_port(
|
||||
rport_ptr->port_id = port_id;
|
||||
rport_ptr->node_id = node_id;
|
||||
rport_ptr->restart_state = RESTART_NORMAL;
|
||||
rport_ptr->sec_rule = NULL;
|
||||
rport_ptr->tx_quota_cnt = 0;
|
||||
init_waitqueue_head(&rport_ptr->quota_wait);
|
||||
mutex_init(&rport_ptr->quota_lock);
|
||||
@@ -667,6 +671,7 @@ static struct msm_ipc_server *msm_ipc_router_create_server(
|
||||
}
|
||||
server->name.service = service;
|
||||
server->name.instance = instance;
|
||||
server->synced_sec_rule = 0;
|
||||
INIT_LIST_HEAD(&server->server_port_list);
|
||||
list_add_tail(&server->list, &server_list[key]);
|
||||
|
||||
@@ -1199,6 +1204,95 @@ static void modem_reset_cleanup(struct msm_ipc_router_xprt_info *xprt_info)
|
||||
msm_ipc_cleanup_routing_table(xprt_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* sync_sec_rule() - Synchrnoize the security rule into the server structure
|
||||
* @server: Server structure where the rule has to be synchronized.
|
||||
* @rule: Security tule to be synchronized.
|
||||
*
|
||||
* This function is used to update the server structure with the security
|
||||
* rule configured for the <service:instance> corresponding to that server.
|
||||
*/
|
||||
static void sync_sec_rule(struct msm_ipc_server *server, void *rule)
|
||||
{
|
||||
struct msm_ipc_server_port *server_port;
|
||||
struct msm_ipc_router_remote_port *rport_ptr = NULL;
|
||||
|
||||
list_for_each_entry(server_port, &server->server_port_list, list) {
|
||||
rport_ptr = msm_ipc_router_lookup_remote_port(
|
||||
server_port->server_addr.node_id,
|
||||
server_port->server_addr.port_id);
|
||||
if (!rport_ptr)
|
||||
continue;
|
||||
rport_ptr->sec_rule = rule;
|
||||
}
|
||||
server->synced_sec_rule = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* msm_ipc_sync_sec_rule() - Sync the security rule to the service
|
||||
* @service: Service for which the rule has to be synchronized.
|
||||
* @instance: Instance for which the rule has to be synchronized.
|
||||
* @rule: Security rule to be synchronized.
|
||||
*
|
||||
* This function is used to syncrhonize the security rule with the server
|
||||
* hash table, if the user-space script configures the rule after the service
|
||||
* has come up. This function is used to synchronize the security rule to a
|
||||
* specific service and optionally a specific instance.
|
||||
*/
|
||||
void msm_ipc_sync_sec_rule(uint32_t service, uint32_t instance, void *rule)
|
||||
{
|
||||
int key = (service & (SRV_HASH_SIZE - 1));
|
||||
struct msm_ipc_server *server;
|
||||
|
||||
mutex_lock(&server_list_lock);
|
||||
list_for_each_entry(server, &server_list[key], list) {
|
||||
if (server->name.service != service)
|
||||
continue;
|
||||
|
||||
if (server->name.instance != instance &&
|
||||
instance != ALL_INSTANCE)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the rule applies to all instances and if the specific
|
||||
* instance of a service has a rule synchronized already,
|
||||
* do not apply the rule for that specific instance.
|
||||
*/
|
||||
if (instance == ALL_INSTANCE && server->synced_sec_rule)
|
||||
continue;
|
||||
|
||||
sync_sec_rule(server, rule);
|
||||
}
|
||||
mutex_unlock(&server_list_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* msm_ipc_sync_default_sec_rule() - Default security rule to all services
|
||||
* @rule: Security rule to be synchronized.
|
||||
*
|
||||
* This function is used to syncrhonize the security rule with the server
|
||||
* hash table, if the user-space script configures the rule after the service
|
||||
* has come up. This function is used to synchronize the security rule that
|
||||
* applies to all services, if the concerned service do not have any rule
|
||||
* defined.
|
||||
*/
|
||||
void msm_ipc_sync_default_sec_rule(void *rule)
|
||||
{
|
||||
int key;
|
||||
struct msm_ipc_server *server;
|
||||
|
||||
mutex_lock(&server_list_lock);
|
||||
for (key = 0; key < SRV_HASH_SIZE; key++) {
|
||||
list_for_each_entry(server, &server_list[key], list) {
|
||||
if (server->synced_sec_rule)
|
||||
continue;
|
||||
|
||||
sync_sec_rule(server, rule);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&server_list_lock);
|
||||
}
|
||||
|
||||
static int process_hello_msg(struct msm_ipc_router_xprt_info *xprt_info,
|
||||
struct rr_header *hdr)
|
||||
{
|
||||
@@ -1379,6 +1473,9 @@ static int process_control_msg(struct msm_ipc_router_xprt_info *xprt_info,
|
||||
if (!rport_ptr)
|
||||
pr_err("%s: Remote port create "
|
||||
"failed\n", __func__);
|
||||
rport_ptr->sec_rule =
|
||||
msm_ipc_get_security_rule(
|
||||
msg->srv.service, msg->srv.instance);
|
||||
}
|
||||
wake_up(&newserver_wait);
|
||||
}
|
||||
@@ -1895,6 +1992,15 @@ int msm_ipc_router_send_to(struct msm_ipc_port *src,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (src->check_send_permissions) {
|
||||
ret = src->check_send_permissions(rport_ptr->sec_rule);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: permission failure for %s\n",
|
||||
__func__, current->comm);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
pkt = create_pkt(data);
|
||||
if (!pkt) {
|
||||
pr_err("%s: Pkt creation failed\n", __func__);
|
||||
@@ -2640,6 +2746,10 @@ static int __init msm_ipc_router_init(void)
|
||||
if (ret < 0)
|
||||
pr_err("%s: Init sockets failed\n", __func__);
|
||||
|
||||
ret = msm_ipc_router_security_init();
|
||||
if (ret < 0)
|
||||
pr_err("%s: Security Init failed\n", __func__);
|
||||
|
||||
complete_all(&msm_ipc_local_router_up);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -58,6 +58,9 @@
|
||||
|
||||
#define ALIGN_SIZE(x) ((4 - ((x) & 3)) & 3)
|
||||
|
||||
#define ALL_SERVICE 0xFFFFFFFF
|
||||
#define ALL_INSTANCE 0xFFFFFFFF
|
||||
|
||||
enum {
|
||||
MSM_IPC_ROUTER_READ_CB = 0,
|
||||
MSM_IPC_ROUTER_WRITE_DONE,
|
||||
@@ -127,6 +130,7 @@ struct msm_ipc_port {
|
||||
|
||||
void *endpoint;
|
||||
void (*notify)(unsigned event, void *data, void *addr, void *priv);
|
||||
int (*check_send_permissions)(void *data);
|
||||
|
||||
uint32_t num_tx;
|
||||
uint32_t num_rx;
|
||||
@@ -206,6 +210,10 @@ int msm_ipc_router_unregister_server(struct msm_ipc_port *server_port);
|
||||
int msm_ipc_router_init_sockets(void);
|
||||
void msm_ipc_router_exit_sockets(void);
|
||||
|
||||
void msm_ipc_sync_sec_rule(uint32_t service, uint32_t instance, void *rule);
|
||||
|
||||
void msm_ipc_sync_default_sec_rule(void *rule);
|
||||
|
||||
#if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT
|
||||
extern void *msm_ipc_load_default_node(void);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -21,16 +21,13 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/msm_ipc.h>
|
||||
|
||||
#ifdef CONFIG_ANDROID_PARANOID_NETWORK
|
||||
#include <linux/android_aid.h>
|
||||
#endif
|
||||
|
||||
#include <asm/string.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#include <net/sock.h>
|
||||
|
||||
#include "ipc_router.h"
|
||||
#include "msm_ipc_router_security.h"
|
||||
|
||||
#define msm_ipc_sk(sk) ((struct msm_ipc_sock *)(sk))
|
||||
#define msm_ipc_sk_port(sk) ((struct msm_ipc_port *)(msm_ipc_sk(sk)->port))
|
||||
@@ -39,21 +36,6 @@ static int sockets_enabled;
|
||||
static struct proto msm_ipc_proto;
|
||||
static const struct proto_ops msm_ipc_proto_ops;
|
||||
|
||||
#ifdef CONFIG_ANDROID_PARANOID_NETWORK
|
||||
static inline int check_permissions(void)
|
||||
{
|
||||
int rc = 0;
|
||||
if (!current_euid() || in_egroup_p(AID_NET_RAW))
|
||||
rc = 1;
|
||||
return rc;
|
||||
}
|
||||
# else
|
||||
static inline int check_permissions(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sk_buff_head *msm_ipc_router_build_msg(unsigned int num_sect,
|
||||
struct iovec const *msg_sect,
|
||||
size_t total_len)
|
||||
@@ -191,7 +173,8 @@ static int msm_ipc_router_create(struct net *net,
|
||||
void *pil;
|
||||
|
||||
if (!check_permissions()) {
|
||||
pr_err("%s: Do not have permissions\n", __func__);
|
||||
pr_err("%s: %s Do not have permissions\n",
|
||||
__func__, current->comm);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@@ -221,6 +204,7 @@ static int msm_ipc_router_create(struct net *net,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
port_ptr->check_send_permissions = msm_ipc_check_send_permissions;
|
||||
sock->ops = &msm_ipc_proto_ops;
|
||||
sock_init_data(sock, sk);
|
||||
sk->sk_rcvtimeo = DEFAULT_RCV_TIMEO;
|
||||
@@ -443,6 +427,10 @@ static int msm_ipc_router_ioctl(struct socket *sock,
|
||||
ret = msm_ipc_router_bind_control_port(port_ptr);
|
||||
break;
|
||||
|
||||
case IPC_ROUTER_IOCTL_CONFIG_SEC_RULES:
|
||||
ret = msm_ipc_config_sec_rules((void *)arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
271
arch/arm/mach-msm/msm_ipc_router_security.c
Normal file
271
arch/arm/mach-msm/msm_ipc_router_security.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/msm_ipc.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <net/sock.h>
|
||||
#include "ipc_router.h"
|
||||
#include "msm_ipc_router_security.h"
|
||||
|
||||
#define SEC_RULES_HASH_SZ 32
|
||||
struct security_rule {
|
||||
struct list_head list;
|
||||
uint32_t service_id;
|
||||
uint32_t instance_id;
|
||||
unsigned reserved;
|
||||
int num_group_info;
|
||||
int *group_id;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(security_rules_lock);
|
||||
static struct list_head security_rules[SEC_RULES_HASH_SZ];
|
||||
|
||||
/**
|
||||
* check_permisions() - Check whether the process has permissions to
|
||||
* create an interface handle with IPC Router
|
||||
*
|
||||
* @return: true if the process has permissions, else false.
|
||||
*/
|
||||
int check_permissions(void)
|
||||
{
|
||||
int rc = 0;
|
||||
if (!current_euid() || in_egroup_p(AID_NET_RAW))
|
||||
rc = 1;
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(check_permissions);
|
||||
|
||||
/**
|
||||
* msm_ipc_config_sec_rules() - Add a security rule to the database
|
||||
* @arg: Pointer to the buffer containing the rule.
|
||||
*
|
||||
* @return: 0 if successfully added, < 0 for error.
|
||||
*
|
||||
* A security rule is defined using <Service_ID: Group_ID> tuple. The rule
|
||||
* implies that a user-space process in order to send a QMI message to
|
||||
* service Service_ID should belong to the Linux group Group_ID.
|
||||
*/
|
||||
int msm_ipc_config_sec_rules(void *arg)
|
||||
{
|
||||
struct config_sec_rules_args sec_rules_arg;
|
||||
struct security_rule *rule, *temp_rule;
|
||||
int key;
|
||||
int ret;
|
||||
|
||||
if (current_euid())
|
||||
return -EPERM;
|
||||
|
||||
ret = copy_from_user(&sec_rules_arg, (void *)arg,
|
||||
sizeof(sec_rules_arg));
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
|
||||
if (sec_rules_arg.num_group_info <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
rule = kzalloc(sizeof(struct security_rule), GFP_KERNEL);
|
||||
if (!rule) {
|
||||
pr_err("%s: security_rule alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rule->group_id = kzalloc((sec_rules_arg.num_group_info * sizeof(int)),
|
||||
GFP_KERNEL);
|
||||
if (!rule->group_id) {
|
||||
pr_err("%s: group_id alloc failed\n", __func__);
|
||||
kfree(rule);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rule->service_id = sec_rules_arg.service_id;
|
||||
rule->instance_id = sec_rules_arg.instance_id;
|
||||
rule->reserved = sec_rules_arg.reserved;
|
||||
rule->num_group_info = sec_rules_arg.num_group_info;
|
||||
ret = copy_from_user(rule->group_id,
|
||||
((void *)(arg + sizeof(sec_rules_arg))),
|
||||
(rule->num_group_info * sizeof(uint32_t)));
|
||||
if (ret) {
|
||||
kfree(rule->group_id);
|
||||
kfree(rule);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
key = rule->service_id & (SEC_RULES_HASH_SZ - 1);
|
||||
mutex_lock(&security_rules_lock);
|
||||
if (rule->service_id == ALL_SERVICE) {
|
||||
temp_rule = list_first_entry(&security_rules[key],
|
||||
struct security_rule, list);
|
||||
list_del(&temp_rule->list);
|
||||
kfree(temp_rule->group_id);
|
||||
kfree(temp_rule);
|
||||
}
|
||||
list_add_tail(&rule->list, &security_rules[key]);
|
||||
mutex_unlock(&security_rules_lock);
|
||||
|
||||
if (rule->service_id == ALL_SERVICE)
|
||||
msm_ipc_sync_default_sec_rule((void *)rule);
|
||||
else
|
||||
msm_ipc_sync_sec_rule(rule->service_id, rule->instance_id,
|
||||
(void *)rule);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_ipc_config_sec_rules);
|
||||
|
||||
/**
|
||||
* msm_ipc_add_default_rule() - Add default security rule
|
||||
*
|
||||
* @return: 0 on success, < 0 on error/
|
||||
*
|
||||
* This function is used to ensure the basic security, if there is no
|
||||
* security rule defined for a service. It can be overwritten by the
|
||||
* default security rule from user-space script.
|
||||
*/
|
||||
static int msm_ipc_add_default_rule(void)
|
||||
{
|
||||
struct security_rule *rule;
|
||||
int key;
|
||||
|
||||
rule = kzalloc(sizeof(struct security_rule), GFP_KERNEL);
|
||||
if (!rule) {
|
||||
pr_err("%s: security_rule alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rule->group_id = kzalloc(sizeof(int), GFP_KERNEL);
|
||||
if (!rule->group_id) {
|
||||
pr_err("%s: group_id alloc failed\n", __func__);
|
||||
kfree(rule);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rule->service_id = ALL_SERVICE;
|
||||
rule->instance_id = ALL_INSTANCE;
|
||||
rule->num_group_info = 1;
|
||||
*(rule->group_id) = AID_NET_RAW;
|
||||
mutex_lock(&security_rules_lock);
|
||||
key = (ALL_SERVICE & (SEC_RULES_HASH_SZ - 1));
|
||||
list_add_tail(&rule->list, &security_rules[key]);
|
||||
mutex_unlock(&security_rules_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* msm_ipc_get_security_rule() - Get the security rule corresponding to a
|
||||
* service
|
||||
* @service_id: Service ID for which the rule has to be got.
|
||||
* @instance_id: Instance ID for which the rule has to be got.
|
||||
*
|
||||
* @return: Returns the rule info on success, NULL on error.
|
||||
*
|
||||
* This function is used when the service comes up and gets registered with
|
||||
* the IPC Router.
|
||||
*/
|
||||
void *msm_ipc_get_security_rule(uint32_t service_id, uint32_t instance_id)
|
||||
{
|
||||
int key;
|
||||
struct security_rule *rule;
|
||||
|
||||
key = (service_id & (SEC_RULES_HASH_SZ - 1));
|
||||
mutex_lock(&security_rules_lock);
|
||||
/* Return the rule for a specific <service:instance>, if found. */
|
||||
list_for_each_entry(rule, &security_rules[key], list) {
|
||||
if ((rule->service_id == service_id) &&
|
||||
(rule->instance_id == instance_id)) {
|
||||
mutex_unlock(&security_rules_lock);
|
||||
return (void *)rule;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the rule for a specific service, if found. */
|
||||
list_for_each_entry(rule, &security_rules[key], list) {
|
||||
if ((rule->service_id == service_id) &&
|
||||
(rule->instance_id == ALL_INSTANCE)) {
|
||||
mutex_unlock(&security_rules_lock);
|
||||
return (void *)rule;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the default rule, if no rule defined for a service. */
|
||||
key = (ALL_SERVICE & (SEC_RULES_HASH_SZ - 1));
|
||||
list_for_each_entry(rule, &security_rules[key], list) {
|
||||
if ((rule->service_id == ALL_SERVICE) &&
|
||||
(rule->instance_id == ALL_INSTANCE)) {
|
||||
mutex_unlock(&security_rules_lock);
|
||||
return (void *)rule;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_ipc_get_security_rule);
|
||||
|
||||
/**
|
||||
* msm_ipc_check_send_permissions() - Check if the sendng process has
|
||||
* permissions specified as per the rule
|
||||
* @data: Security rule to be checked.
|
||||
*
|
||||
* @return: true if the process has permissions, else false.
|
||||
*
|
||||
* This function is used to check if the current executing process has
|
||||
* permissions to send message to the remote entity. The security rule
|
||||
* corresponding to the remote entity is specified by "data" parameter
|
||||
*/
|
||||
int msm_ipc_check_send_permissions(void *data)
|
||||
{
|
||||
int i;
|
||||
struct security_rule *rule = (struct security_rule *)data;
|
||||
|
||||
/* Source/Sender is Root user */
|
||||
if (!current_euid())
|
||||
return 1;
|
||||
|
||||
/* Destination has no rules defined, possibly a client. */
|
||||
if (!rule)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < rule->num_group_info; i++) {
|
||||
if (in_egroup_p(rule->group_id[i]))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_ipc_check_send_permissions);
|
||||
|
||||
/**
|
||||
* msm_ipc_router_security_init() - Initialize the security rule database
|
||||
*
|
||||
* @return: 0 if successful, < 0 for error.
|
||||
*/
|
||||
int msm_ipc_router_security_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SEC_RULES_HASH_SZ; i++)
|
||||
INIT_LIST_HEAD(&security_rules[i]);
|
||||
|
||||
msm_ipc_add_default_rule();
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_ipc_router_security_init);
|
||||
104
arch/arm/mach-msm/msm_ipc_router_security.h
Normal file
104
arch/arm/mach-msm/msm_ipc_router_security.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_IPC_ROUTER_SECURITY_H
|
||||
#define _MSM_IPC_ROUTER_SECURITY_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#ifdef CONFIG_MSM_IPC_ROUTER_SECURITY
|
||||
#include <linux/android_aid.h>
|
||||
|
||||
/**
|
||||
* check_permisions() - Check whether the process has permissions to
|
||||
* create an interface handle with IPC Router
|
||||
*
|
||||
* @return: true if the process has permissions, else false.
|
||||
*/
|
||||
int check_permissions(void);
|
||||
|
||||
/**
|
||||
* msm_ipc_config_sec_rules() - Add a security rule to the database
|
||||
* @arg: Pointer to the buffer containing the rule.
|
||||
*
|
||||
* @return: 0 if successfully added, < 0 for error.
|
||||
*
|
||||
* A security rule is defined using <Service_ID: Group_ID> tuple. The rule
|
||||
* implies that a user-space process in order to send a QMI message to
|
||||
* service Service_ID should belong to the Linux group Group_ID.
|
||||
*/
|
||||
int msm_ipc_config_sec_rules(void *arg);
|
||||
|
||||
/**
|
||||
* msm_ipc_get_security_rule() - Get the security rule corresponding to a
|
||||
* service
|
||||
* @service_id: Service ID for which the rule has to be got.
|
||||
* @instance_id: Instance ID for which the rule has to be got.
|
||||
*
|
||||
* @return: Returns the rule info on success, NULL on error.
|
||||
*
|
||||
* This function is used when the service comes up and gets registered with
|
||||
* the IPC Router.
|
||||
*/
|
||||
void *msm_ipc_get_security_rule(uint32_t service_id, uint32_t instance_id);
|
||||
|
||||
/**
|
||||
* msm_ipc_check_send_permissions() - Check if the sendng process has
|
||||
* permissions specified as per the rule
|
||||
* @data: Security rule to be checked.
|
||||
*
|
||||
* @return: true if the process has permissions, else false.
|
||||
*
|
||||
* This function is used to check if the current executing process has
|
||||
* permissions to send message to the remote entity. The security rule
|
||||
* corresponding to the remote entity is specified by "data" parameter
|
||||
*/
|
||||
int msm_ipc_check_send_permissions(void *data);
|
||||
|
||||
/**
|
||||
* msm_ipc_router_security_init() - Initialize the security rule database
|
||||
*
|
||||
* @return: 0 if successful, < 0 for error.
|
||||
*/
|
||||
int msm_ipc_router_security_init(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline int check_permissions(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int msm_ipc_config_sec_rules(void *arg)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void *msm_ipc_get_security_rule(uint32_t service_id,
|
||||
uint32_t instance_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int msm_ipc_check_send_permissions(void *data)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int msm_ipc_router_security_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -45,6 +45,14 @@ struct sockaddr_msm_ipc {
|
||||
unsigned char reserved;
|
||||
};
|
||||
|
||||
struct config_sec_rules_args {
|
||||
int num_group_info;
|
||||
uint32_t service_id;
|
||||
uint32_t instance_id;
|
||||
unsigned reserved;
|
||||
gid_t group_id[0];
|
||||
};
|
||||
|
||||
#define IPC_ROUTER_IOCTL_MAGIC (0xC3)
|
||||
|
||||
#define IPC_ROUTER_IOCTL_GET_VERSION \
|
||||
@@ -62,6 +70,9 @@ struct sockaddr_msm_ipc {
|
||||
#define IPC_ROUTER_IOCTL_BIND_CONTROL_PORT \
|
||||
_IOR(IPC_ROUTER_IOCTL_MAGIC, 4, unsigned int)
|
||||
|
||||
#define IPC_ROUTER_IOCTL_CONFIG_SEC_RULES \
|
||||
_IOR(IPC_ROUTER_IOCTL_MAGIC, 5, struct config_sec_rules_args)
|
||||
|
||||
struct msm_ipc_server_info {
|
||||
uint32_t node_id;
|
||||
uint32_t port_id;
|
||||
|
||||
Reference in New Issue
Block a user