Loading drivers/char/adsprpc.c +122 −1 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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) \ Loading Loading @@ -211,6 +215,11 @@ struct secure_vm { int vmcount; }; struct gid_list { unsigned int *gids; unsigned int gidcount; }; struct fastrpc_file; struct fastrpc_buf { Loading Loading @@ -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 { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -2356,6 +2392,22 @@ static int fastrpc_get_spd_session(char *name, int *session, int *cid) 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) { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -4578,6 +4662,41 @@ static void init_secure_vmid_list(struct device *dev, char *prop_name, } } 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; Loading Loading @@ -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); Loading Loading @@ -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 Loading
drivers/char/adsprpc.c +122 −1 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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) \ Loading Loading @@ -211,6 +215,11 @@ struct secure_vm { int vmcount; }; struct gid_list { unsigned int *gids; unsigned int gidcount; }; struct fastrpc_file; struct fastrpc_buf { Loading Loading @@ -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 { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -2356,6 +2392,22 @@ static int fastrpc_get_spd_session(char *name, int *session, int *cid) 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) { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -4578,6 +4662,41 @@ static void init_secure_vmid_list(struct device *dev, char *prop_name, } } 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; Loading Loading @@ -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); Loading Loading @@ -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