qcacmn: Add support to use generic netlink sockets for userspace apps
Currently user space communication functions[cnss diag, PTT socket app] in host driver uses netlink user sockets which is a security concern from Linux Android SE policies. Add support for to use netlink family cld80211 which uses generic netlink sockets. Change-Id: Ia833249c1f312415e38563d90214979cea3d9f0e CRs-Fixed: 2015931
Tento commit je obsažen v:

odevzdal
Sandeep Puligilla

rodič
ca0e169743
revize
7c6b935c64
@@ -54,7 +54,15 @@ void nl_srv_exit(void);
|
||||
int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler);
|
||||
int nl_srv_unregister(tWlanNlModTypes msg_type,
|
||||
nl_srv_msg_callback msg_handler);
|
||||
|
||||
#ifdef CNSS_GENL
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
|
||||
int app_id, int mcgroup_id);
|
||||
int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id);
|
||||
#else
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag);
|
||||
int nl_srv_bcast(struct sk_buff *skb);
|
||||
#endif
|
||||
|
||||
int nl_srv_is_initialized(void);
|
||||
#endif
|
||||
|
@@ -51,6 +51,13 @@
|
||||
#include <wlan_nlink_srv.h>
|
||||
#include <qdf_trace.h>
|
||||
|
||||
#ifdef CNSS_GENL
|
||||
#include <qdf_mem.h>
|
||||
#include <wlan_nlink_common.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <net/cnss_nl.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CNSS_LOGGER)
|
||||
|
||||
#include <net/cnss_logger.h>
|
||||
@@ -358,6 +365,195 @@ int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
#ifdef CNSS_GENL
|
||||
/**
|
||||
* nl80211hdr_put() - API to fill genlmsg header
|
||||
* @skb: Sk buffer
|
||||
* @portid: Port ID
|
||||
* @seq: Sequence number
|
||||
* @flags: Flags
|
||||
* @cmd: Command id
|
||||
*
|
||||
* API to fill genl message header for brodcast events to user space
|
||||
*
|
||||
* Return: Pointer to user specific header/payload
|
||||
*/
|
||||
static inline void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid,
|
||||
uint32_t seq, int flags, uint8_t cmd)
|
||||
{
|
||||
struct genl_family *cld80211_fam = cld80211_get_genl_family();
|
||||
|
||||
return genlmsg_put(skb, portid, seq, cld80211_fam, flags, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* cld80211_fill_data() - API to fill payload to nl message
|
||||
* @msg: Sk buffer
|
||||
* @portid: Port ID
|
||||
* @seq: Sequence number
|
||||
* @flags: Flags
|
||||
* @cmd: Command ID
|
||||
* @buf: data buffer/payload to be filled
|
||||
* @len: length of the payload ie. @buf
|
||||
*
|
||||
* API to fill the payload/data of the nl message to be sent
|
||||
*
|
||||
* Return: zero on success
|
||||
*/
|
||||
static int cld80211_fill_data(struct sk_buff *msg, uint32_t portid,
|
||||
uint32_t seq, int flags, uint8_t cmd,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
void *hdr;
|
||||
struct nlattr *nest;
|
||||
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
|
||||
if (!hdr) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nl80211 hdr put failed");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA);
|
||||
if (!nest) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nla_nest_start failed");
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (nla_put(msg, CLD80211_ATTR_DATA, len, buf)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nla_put failed");
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
nla_nest_end(msg, nest);
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/**
|
||||
* send_msg_to_cld80211() - API to send message to user space Application
|
||||
* @mcgroup_id: Multicast group ID
|
||||
* @pid: Port ID
|
||||
* @app_id: Application ID
|
||||
* @buf: Data/payload buffer to be sent
|
||||
* @len: Length of the data ie. @buf
|
||||
*
|
||||
* API to send the nl message to user space application.
|
||||
*
|
||||
* Return: zero on success
|
||||
*/
|
||||
static int send_msg_to_cld80211(int mcgroup_id, int pid, int app_id,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
struct genl_family *cld80211_fam = cld80211_get_genl_family();
|
||||
int status;
|
||||
int flags = GFP_KERNEL;
|
||||
|
||||
if (in_interrupt() || irqs_disabled() || in_atomic())
|
||||
flags = GFP_ATOMIC;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, flags);
|
||||
if (!msg) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"nlmsg malloc fails");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
status = cld80211_fill_data(msg, pid, 0, 0, app_id, buf, len);
|
||||
if (status) {
|
||||
nlmsg_free(msg);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0,
|
||||
mcgroup_id, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_bcast() - wrapper function to do broadcast events to user space apps
|
||||
* @skb: the socket buffer to send
|
||||
* @mcgroup_id: multicast group id
|
||||
* @app_id: application id
|
||||
*
|
||||
* This function is common wrapper to send broadcast events to different
|
||||
* user space applications.
|
||||
*
|
||||
* return: none
|
||||
*/
|
||||
int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id)
|
||||
{
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
|
||||
void *msg = NLMSG_DATA(nlh);
|
||||
uint32_t msg_len = nlmsg_len(nlh);
|
||||
uint8_t *tempbuf;
|
||||
int status;
|
||||
|
||||
tempbuf = (uint8_t *)qdf_mem_malloc(msg_len);
|
||||
qdf_mem_copy(tempbuf, msg, msg_len);
|
||||
status = send_msg_to_cld80211(mcgroup_id, 0, app_id, tempbuf, msg_len);
|
||||
if (status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"send msg to cld80211 fails for app id %d", app_id);
|
||||
dev_kfree_skb(skb);
|
||||
qdf_mem_free(tempbuf);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
qdf_mem_free(tempbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nl_srv_ucast() - wrapper function to do unicast events to user space apps
|
||||
* @skb: the socket buffer to send
|
||||
* @dst_pid: destination process IF
|
||||
* @flag: flags
|
||||
* @app_id: application id
|
||||
* @mcgroup_id: Multicast group ID
|
||||
*
|
||||
* This function is common wrapper to send unicast events to different
|
||||
* user space applications. This internally used broadcast API with multicast
|
||||
* group mcgrp_id. This wrapper serves as a common API in both
|
||||
* new generic netlink infra and legacy implementation.
|
||||
*
|
||||
* return: zero on success, error code otherwise
|
||||
*/
|
||||
int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag,
|
||||
int app_id, int mcgroup_id)
|
||||
{
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
|
||||
void *msg = NLMSG_DATA(nlh);
|
||||
uint32_t msg_len = nlmsg_len(nlh);
|
||||
uint8_t *tempbuf;
|
||||
int status;
|
||||
|
||||
tempbuf = (uint8_t *)qdf_mem_malloc(msg_len);
|
||||
qdf_mem_copy(tempbuf, msg, msg_len);
|
||||
status = send_msg_to_cld80211(mcgroup_id, dst_pid, app_id,
|
||||
tempbuf, msg_len);
|
||||
if (status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
|
||||
"send msg to cld80211 fails for app id %d", app_id);
|
||||
dev_kfree_skb(skb);
|
||||
qdf_mem_free(tempbuf);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
qdf_mem_free(tempbuf);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* Unicast the message to the process in user space identfied
|
||||
* by the dst-pid
|
||||
@@ -410,6 +606,7 @@ int nl_srv_bcast(struct sk_buff *skb)
|
||||
dev_kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Processes the Netlink socket input queue.
|
||||
|
Odkázat v novém úkolu
Zablokovat Uživatele