mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
Merge "msm: adsprpc: detect privileged processes based on group ID"
This commit is contained in:
commit
0d234d7b41
1 changed files with 122 additions and 1 deletions
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/cma.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/sort.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/msm_dma_iommu_mapping.h>
|
||||
#include "adsprpc_compat.h"
|
||||
#include "adsprpc_shared.h"
|
||||
|
|
@ -135,6 +136,9 @@
|
|||
#define INIT_MEMLEN_MAX (8*1024*1024)
|
||||
#define MAX_CACHE_BUF_SIZE (8*1024*1024)
|
||||
|
||||
/* Position of privilege bit in remote process attribute */
|
||||
#define FASTRPC_MODE_PRIVILEGED (1 << 6)
|
||||
|
||||
#define PERF_END (void)0
|
||||
|
||||
#define PERF(enb, cnt, ff) \
|
||||
|
|
@ -211,6 +215,11 @@ struct secure_vm {
|
|||
int vmcount;
|
||||
};
|
||||
|
||||
struct gid_list {
|
||||
unsigned int *gids;
|
||||
unsigned int gidcount;
|
||||
};
|
||||
|
||||
struct fastrpc_file;
|
||||
|
||||
struct fastrpc_buf {
|
||||
|
|
@ -360,6 +369,7 @@ struct fastrpc_apps {
|
|||
struct wakeup_source *wake_source_secure;
|
||||
/* Non-secure subsystem like CDSP will use regular client */
|
||||
struct wakeup_source *wake_source;
|
||||
struct gid_list gidlist;
|
||||
};
|
||||
|
||||
struct fastrpc_mmap {
|
||||
|
|
@ -443,6 +453,7 @@ struct fastrpc_file {
|
|||
char *debug_buf;
|
||||
/* Flag to enable PM wake/relax voting for every remote invoke */
|
||||
int wake_enable;
|
||||
struct gid_list gidlist;
|
||||
};
|
||||
|
||||
static struct fastrpc_apps gfa;
|
||||
|
|
@ -1193,7 +1204,32 @@ static int context_restore_interrupted(struct fastrpc_file *fl,
|
|||
return err;
|
||||
}
|
||||
|
||||
static unsigned int sorted_lists_intersection(unsigned int *listA,
|
||||
unsigned int lenA, unsigned int *listB, unsigned int lenB)
|
||||
{
|
||||
unsigned int i = 0, j = 0;
|
||||
|
||||
while (i < lenA && j < lenB) {
|
||||
if (listA[i] < listB[j])
|
||||
i++;
|
||||
else if (listA[i] > listB[j])
|
||||
j++;
|
||||
else
|
||||
return listA[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CMP(aa, bb) ((aa) == (bb) ? 0 : (aa) < (bb) ? -1 : 1)
|
||||
|
||||
static int uint_cmp_func(const void *p1, const void *p2)
|
||||
{
|
||||
unsigned int a1 = *((unsigned int *)p1);
|
||||
unsigned int a2 = *((unsigned int *)p2);
|
||||
|
||||
return CMP(a1, a2);
|
||||
}
|
||||
|
||||
static int overlap_ptr_cmp(const void *a, const void *b)
|
||||
{
|
||||
struct overlap *pa = *((struct overlap **)a);
|
||||
|
|
@ -2356,6 +2392,22 @@ bail:
|
|||
static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl);
|
||||
static int fastrpc_channel_open(struct fastrpc_file *fl);
|
||||
static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl);
|
||||
|
||||
static void fastrpc_check_privileged_process(struct fastrpc_file *fl,
|
||||
struct fastrpc_ioctl_init_attrs *uproc)
|
||||
{
|
||||
unsigned int gid = sorted_lists_intersection(fl->gidlist.gids,
|
||||
fl->gidlist.gidcount, gfa.gidlist.gids, gfa.gidlist.gidcount);
|
||||
|
||||
/* disregard any privilege bits from userspace */
|
||||
uproc->attrs &= (~FASTRPC_MODE_PRIVILEGED);
|
||||
if (gid) {
|
||||
pr_info("adsprpc: %s: %s (PID %d, GID %u) is a privileged process\n",
|
||||
__func__, current->comm, fl->tgid, gid);
|
||||
uproc->attrs |= FASTRPC_MODE_PRIVILEGED;
|
||||
}
|
||||
}
|
||||
|
||||
static int fastrpc_init_process(struct fastrpc_file *fl,
|
||||
struct fastrpc_ioctl_init_attrs *uproc)
|
||||
{
|
||||
|
|
@ -2434,6 +2486,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
|
|||
}
|
||||
inbuf.pageslen = 1;
|
||||
|
||||
fastrpc_check_privileged_process(fl, uproc);
|
||||
|
||||
VERIFY(err, !init->mem);
|
||||
if (err) {
|
||||
err = -EINVAL;
|
||||
|
|
@ -3492,6 +3546,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl)
|
|||
hlist_del_init(&fl->hn);
|
||||
spin_unlock(&fl->apps->hlock);
|
||||
kfree(fl->debug_buf);
|
||||
kfree(fl->gidlist.gids);
|
||||
|
||||
if (!fl->sctx) {
|
||||
kfree(fl);
|
||||
|
|
@ -3896,6 +3951,34 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fastrpc_get_process_gids(struct gid_list *gidlist)
|
||||
{
|
||||
struct group_info *group_info = get_current_groups();
|
||||
int i = 0, err = 0, num_gids = group_info->ngroups + 1;
|
||||
unsigned int *gids = NULL;
|
||||
|
||||
gids = kcalloc(num_gids, sizeof(unsigned int), GFP_KERNEL);
|
||||
if (!gids) {
|
||||
err = -ENOMEM;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Get the real GID */
|
||||
gids[0] = __kgid_val(current_gid());
|
||||
|
||||
/* Get the supplemental GIDs */
|
||||
for (i = 1; i < num_gids; i++)
|
||||
gids[i] = __kgid_val(group_info->gid[i - 1]);
|
||||
|
||||
sort(gids, num_gids, sizeof(*gids), uint_cmp_func, NULL);
|
||||
gidlist->gids = gids;
|
||||
gidlist->gidcount = num_gids;
|
||||
bail:
|
||||
if (err)
|
||||
kfree(gids);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
|
||||
{
|
||||
int err = 0;
|
||||
|
|
@ -3904,6 +3987,7 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
|
|||
VERIFY(err, fl != NULL);
|
||||
if (err)
|
||||
goto bail;
|
||||
fastrpc_get_process_gids(&fl->gidlist);
|
||||
if (fl->cid == -1) {
|
||||
cid = *info;
|
||||
VERIFY(err, cid < NUM_CHANNELS);
|
||||
|
|
@ -4578,6 +4662,41 @@ bail:
|
|||
}
|
||||
}
|
||||
|
||||
static void fastrpc_init_privileged_gids(struct device *dev, char *prop_name,
|
||||
struct gid_list *gidlist)
|
||||
{
|
||||
int err = 0;
|
||||
u32 len = 0, i = 0;
|
||||
u32 *gids = NULL;
|
||||
|
||||
if (!of_find_property(dev->of_node, prop_name, &len))
|
||||
goto bail;
|
||||
if (len == 0)
|
||||
goto bail;
|
||||
len /= sizeof(u32);
|
||||
gids = kcalloc(len, sizeof(u32), GFP_KERNEL);
|
||||
if (!gids) {
|
||||
err = ENOMEM;
|
||||
goto bail;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
err = of_property_read_u32_index(dev->of_node, prop_name,
|
||||
i, &gids[i]);
|
||||
if (err) {
|
||||
pr_err("Error: adsprpc: %s: failed to read GID %u\n",
|
||||
__func__, i);
|
||||
goto bail;
|
||||
}
|
||||
pr_info("adsprpc: %s: privileged GID: %u\n", __func__, gids[i]);
|
||||
}
|
||||
sort(gids, len, sizeof(*gids), uint_cmp_func, NULL);
|
||||
gidlist->gids = gids;
|
||||
gidlist->gidcount = len;
|
||||
bail:
|
||||
if (err)
|
||||
kfree(gids);
|
||||
}
|
||||
|
||||
static void configure_secure_channels(uint32_t secure_domains)
|
||||
{
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
|
|
@ -4610,7 +4729,8 @@ static int fastrpc_probe(struct platform_device *pdev)
|
|||
"qcom,msm-fastrpc-compute")) {
|
||||
init_secure_vmid_list(dev, "qcom,adsp-remoteheap-vmid",
|
||||
&gcinfo[0].rhvm);
|
||||
|
||||
fastrpc_init_privileged_gids(dev, "qcom,fastrpc-gids",
|
||||
&me->gidlist);
|
||||
|
||||
of_property_read_u32(dev->of_node, "qcom,rpc-latency-us",
|
||||
&me->latency);
|
||||
|
|
@ -4907,6 +5027,7 @@ static void __exit fastrpc_device_exit(void)
|
|||
wakeup_source_unregister(me->wake_source);
|
||||
if (me->wake_source_secure)
|
||||
wakeup_source_unregister(me->wake_source_secure);
|
||||
kfree(me->gidlist.gids);
|
||||
debugfs_remove_recursive(debugfs_root);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue