From 2a942238d9637ddd7b4595acf34e5e7ba6e0fb07 Mon Sep 17 00:00:00 2001 From: sunchanglong Date: Tue, 27 Feb 2024 20:37:55 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E7=BC=96=E8=AF=91=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20Team=EF=BC=9AH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I2feca9028aad1df3bed9088844362aab8671cbb8 --- qos_auth/auth_ctl/qos_ctrl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qos_auth/auth_ctl/qos_ctrl.c b/qos_auth/auth_ctl/qos_ctrl.c index 9f51767..11d3f23 100644 --- a/qos_auth/auth_ctl/qos_ctrl.c +++ b/qos_auth/auth_ctl/qos_ctrl.c @@ -456,12 +456,11 @@ static long ctrl_qos_operation(int abi, void __user *uarg) int ret = -1; #pragma GCC diagnostic push -#pragma GCC diagonstic ignored "-Wpointer-to-int-cast" switch (abi) { case QOS_IOCTL_ABI_ARM32: ret = copy_from_user(&qos_data, - (void __user *)compat_ptr((compat_uptr_t)uarg), + (void __user *)compat_ptr((compat_uptr_t)(uintptr_t)uarg), sizeof(struct qos_ctrl_data)); break; case QOS_IOCTL_ABI_AARCH64: -- Gitee From 8fcfc5a41580db73cab4b8659f5a58596d092c78 Mon Sep 17 00:00:00 2001 From: 17786508361 Date: Wed, 20 Mar 2024 10:12:02 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E5=8D=95=E5=8F=B7=EF=BC=9A#I99XSE=20?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=EF=BC=9Ahidumper=20--cpuusage=20=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E6=97=A0=E6=B3=95=E6=9F=A5=E8=AF=A2cpu=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E4=BF=A1=E6=81=AF=E3=80=82=20=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E8=B7=9F=E5=9B=A0=EF=BC=9A4.1release=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=E6=94=B9=E5=8F=98cpu=E8=8E=B7=E5=8F=96=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=EF=BC=8C=E9=9C=80=E9=80=82=E9=85=8D=E4=BF=AE=E6=94=B9=E3=80=82?= =?UTF-8?q?=20=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88=EF=BC=9A=E5=90=88?= =?UTF-8?q?=E5=85=A54.1=E7=BB=9F=E4=B8=80=E6=9F=A5=E8=AF=A2=E8=8E=B7?= =?UTF-8?q?=E5=8F=96cpu=E6=96=B9=E6=A1=88=E3=80=82=20=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=BC=96=E7=A8=8B=E8=A7=84=E8=8C=83=E8=87=AA?= =?UTF-8?q?=E6=A3=80=EF=BC=9AY=20=E6=98=AF=E5=90=A6=E7=BC=96=E7=A8=8B?= =?UTF-8?q?=E4=B8=94=E9=AA=8C=E8=AF=81=E9=80=9A=E8=BF=87=EF=BC=9AY=20?= =?UTF-8?q?=E5=BD=B1=E5=93=8D=E7=9A=84=E8=AE=BE=E5=A4=87=E4=B8=8E=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E8=8C=83=E5=9B=B4=EF=BC=9Alaphone=20=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=EF=BC=9AH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I612ea0d522966f4ea754d58bff051d60645c700b --- ucollection/unified_collection_driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ucollection/unified_collection_driver.c b/ucollection/unified_collection_driver.c index be70a17..f6998be 100644 --- a/ucollection/unified_collection_driver.c +++ b/ucollection/unified_collection_driver.c @@ -19,8 +19,7 @@ static long (*unified_collection_ioctl_cb[])(unsigned int cmd, void __user *argp static long unified_collection_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - void __user *argp = u64_to_user_ptr(arg); - const char *comm = NULL; + void __user *argp = (void __user *)(arg); if ((_IOC_TYPE(cmd) >= ARRAY_SIZE(unified_collection_ioctl_cb)) || (unified_collection_ioctl_cb[_IOC_TYPE(cmd)] == NULL)) { -- Gitee From 4b7a9c30b02df6a1d63859aeaa1dff873893c01d Mon Sep 17 00:00:00 2001 From: zhao_hanqing Date: Tue, 2 Apr 2024 10:32:20 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=8D=95=E5=8F=B7=20=EF=BC=9AI9DDEW=20?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=EF=BC=9A=E3=80=90B501=E3=80=91=E3=80=90?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E8=80=85=E6=8F=90=E5=8D=95=E3=80=91=E3=80=90?= =?UTF-8?q?=E5=BF=85=E7=8E=B0=E3=80=91XPM=E6=A8=A1=E5=9D=97=E5=8F=82?= =?UTF-8?q?=E4=B8=8E=E5=86=85=E6=A0=B8=E7=BC=96=E8=AF=91=20=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=AE=8C=E6=88=90=E7=BC=96=E7=A8=8B=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E8=87=AA=E6=A3=80=EF=BC=9AY=20=E6=98=AF=E5=90=A6=E7=BC=96?= =?UTF-8?q?=E7=A8=8B=E4=B8=94=E9=AA=8C=E8=AF=81=E9=80=9A=E8=BF=87=EF=BC=9A?= =?UTF-8?q?Y=20=E5=BD=B1=E5=93=8D=E7=9A=84=E8=AE=BE=E5=A4=87=E4=B8=8E?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E8=8C=83=E5=9B=B4=EF=BC=9Alaphone=20?= =?UTF-8?q?=E5=9B=A2=E9=98=9F=EF=BC=9A=E6=B6=A6=E5=BC=80=E9=B8=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhao_hanqing --- code_sign/code_sign_elf.c | 24 ++++++++++++++++++------ code_sign/code_sign_ioctl.c | 2 +- xpm/core/xpm_security_hooks.c | 3 ++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/code_sign/code_sign_elf.c b/code_sign/code_sign_elf.c index 9c9a3dc..60ab96e 100644 --- a/code_sign/code_sign_elf.c +++ b/code_sign/code_sign_elf.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "dsmm_developer.h" #include "code_sign_elf.h" @@ -42,8 +43,9 @@ static void parse_block_hdr(block_hdr_t *out, char *ptr) static int get_block_headers(sign_block_t *sign_block, char *sign_data_ptr) { + int i; /* parse all block headers */ - for (int i = 0; i < sign_block->sign_head.sign_block_num; i++) { + for (i = 0; i < sign_block->sign_head.sign_block_num; i++) { block_hdr_t *tmp_block_hdr = (block_hdr_t *) (sign_data_ptr + sizeof(block_hdr_t) * i); if (BLOCK_TYPE_CODE_SIGNING == le32_to_cpu(tmp_block_hdr->type)) { parse_block_hdr(&sign_block->code_signing_block_hdr, sign_data_ptr + sizeof(block_hdr_t) * i); @@ -121,6 +123,8 @@ static int enable_by_sign_head(struct file *fp, struct inode *inode, long long f { sign_block_t sign_block; memset(&sign_block, 0, sizeof(sign_block)); + ssize_t cnt = 0; + int err = 0; parse_sign_head(&sign_block.sign_head, sign_head_ptr); loff_t sign_data_start = fsize - SIGN_HEAD_SIZE - sign_block.sign_head.sign_data_size; @@ -131,13 +135,13 @@ static int enable_by_sign_head(struct file *fp, struct inode *inode, long long f code_sign_log_error("kzalloc of sign_data_ptr failed"); return -ENOMEM; } - ssize_t cnt = vfs_read(fp, sign_data_ptr, sign_block.sign_head.sign_data_size, &sign_data_start); + cnt = vfs_read(fp, sign_data_ptr, sign_block.sign_head.sign_data_size, &sign_data_start); if (cnt != sign_block.sign_head.sign_data_size) { code_sign_log_error("read sign data from file failed: read value %lu, expect %u bytes", cnt, sign_block.sign_head.sign_data_size); goto out; } - int err = get_block_headers(&sign_block, sign_data_ptr); + err = get_block_headers(&sign_block, sign_data_ptr); if (err) { code_sign_log_error("get_block_headers failed, err: %d", err); goto out; @@ -202,7 +206,7 @@ int elf_file_enable_fs_verity(struct file *file) code_sign_log_info("developer mode off, elf not allowed to execute"); return -EINVAL; } - mm_segment_t fs; + mm_segment_t old_fs; char *path_buf = kzalloc(PATH_MAX, GFP_KERNEL); if (!path_buf) { code_sign_log_error("alloc mem for path_buf failed"); @@ -246,8 +250,12 @@ int elf_file_enable_fs_verity(struct file *file) goto filp_close_out; } - fs = get_fs(); +#if LINUX_VERSION_CODE > KERNEL_VERSION(5,10,0) + old_fs = force_uaccess_begin(); +#else + old_fs = get_fs(); set_fs(KERNEL_DS); +#endif ssize_t cnt = vfs_read(fp, sign_head_ptr, SIGN_HEAD_SIZE, &pos); if (cnt != SIGN_HEAD_SIZE) { @@ -278,7 +286,11 @@ int elf_file_enable_fs_verity(struct file *file) release_sign_head_out: kfree(sign_head_ptr); - set_fs(fs); +#if LINUX_VERSION_CODE > KERNEL_VERSION(5,10,0) + force_uaccess_end(old_fs); +#else + set_fs(old_fs); +#endif filp_close_out: filp_close(fp, NULL); release_path_buf_out: diff --git a/code_sign/code_sign_ioctl.c b/code_sign/code_sign_ioctl.c index 18767cb..ccd6a1a 100644 --- a/code_sign/code_sign_ioctl.c +++ b/code_sign/code_sign_ioctl.c @@ -184,7 +184,7 @@ int code_sign_avc_has_perm(u16 tclass, u32 requested) rc = avc_has_perm_noaudit(&selinux_state, sid, sid, tclass, requested, AVC_STRICT, &avd); rc2 = avc_audit(&selinux_state, sid, sid, tclass, requested, &avd, rc, - NULL, AVC_STRICT); + NULL); if (rc2) return rc2; diff --git a/xpm/core/xpm_security_hooks.c b/xpm/core/xpm_security_hooks.c index 5fe5b37..f44dc13 100644 --- a/xpm/core/xpm_security_hooks.c +++ b/xpm/core/xpm_security_hooks.c @@ -27,6 +27,7 @@ static uint32_t ownerid_policy[PROCESS_OWNERID_MAX][FILE_OWNERID_MAX] __ro_after static void init_ownerid_policy(void) { + int i; ownerid_policy[PROCESS_OWNERID_SYSTEM][FILE_OWNERID_SYSTEM] = ALLOW; ownerid_policy[PROCESS_OWNERID_APP][FILE_OWNERID_SYSTEM] = ALLOW; @@ -40,7 +41,7 @@ static void init_ownerid_policy(void) ownerid_policy[PROCESS_OWNERID_COMPAT][FILE_OWNERID_SYSTEM] = ALLOW; ownerid_policy[PROCESS_OWNERID_COMPAT][FILE_OWNERID_COMPAT] = ALLOW; - for (int i = 0; i < FILE_OWNERID_MAX; i++) { + for (i = 0; i < FILE_OWNERID_MAX; i++) { ownerid_policy[PROCESS_OWNERID_EXTEND][i] = ALLOW; } } -- Gitee From 61cf7a0025a8f63fa64b85b97939f32582871aac Mon Sep 17 00:00:00 2001 From: zhao_hanqing Date: Tue, 2 Apr 2024 03:24:20 +0000 Subject: [PATCH 4/5] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20ucol?= =?UTF-8?q?lection/unified=5Fcollection=5Fdriver.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ucollection/unified_collection_driver.c | 89 ------------------------- 1 file changed, 89 deletions(-) delete mode 100644 ucollection/unified_collection_driver.c diff --git a/ucollection/unified_collection_driver.c b/ucollection/unified_collection_driver.c deleted file mode 100644 index f6998be..0000000 --- a/ucollection/unified_collection_driver.c +++ /dev/null @@ -1,89 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - */ -#include -#include -#include -#include - -#ifdef CONFIG_COMPAT -#include -#endif // CONFIG_COMPAT - -#include "ucollection_process_cpu.h" - -static long (*unified_collection_ioctl_cb[])(unsigned int cmd, void __user *argp) = { - unified_collection_collect_process_cpu /* IOCTRL_COLLECT_CPU */ -}; - -static long unified_collection_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)(arg); - - if ((_IOC_TYPE(cmd) >= ARRAY_SIZE(unified_collection_ioctl_cb)) || - (unified_collection_ioctl_cb[_IOC_TYPE(cmd)] == NULL)) { - pr_err("invalid ioctrl cmd %u, _IOC_TYPE(cmd)=%d", cmd, _IOC_TYPE(cmd)); - return -EINVAL; - } - - return unified_collection_ioctl_cb[_IOC_TYPE(cmd)](cmd, argp); -} - -#ifdef CONFIG_COMPAT -static long unified_collection_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - return unified_collection_ioctl(filp, cmd, (unsigned long) compat_ptr(arg)); -} -#endif // CONFIG_COMPAT - -static int unified_collection_open(struct inode *inode, struct file *filp) -{ - return 0; -} - -static int unified_collection_release(struct inode *inode, struct file *filp) -{ - return 0; -} - -static const struct file_operations unified_collection_device_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = unified_collection_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = unified_collection_compat_ioctl, -#endif // CONFIG_COMPAT - .open = unified_collection_open, - .release = unified_collection_release, -}; - -static struct miscdevice unified_collection_device = { - .name = "ucollection", - .fops = &unified_collection_device_fops, - .minor = MISC_DYNAMIC_MINOR, -}; - -static int __init unified_collection_init(void) -{ - int ret = misc_register(&unified_collection_device); - if (ret) { - pr_err("failed to register unified collection device"); - return ret; - } - - pr_info("register unified collection device successful"); - return 0; -} - -static void __exit unified_collection_exit(void) -{ - pr_info("deregister unified collection device successful"); - misc_deregister(&unified_collection_device); -} - -module_init(unified_collection_init); -module_exit(unified_collection_exit); - -MODULE_AUTHOR("OHOS"); -MODULE_DESCRIPTION("Unified Collection Driver"); -MODULE_LICENSE("GPL"); \ No newline at end of file -- Gitee From 7079ac935a1898327825e6cfa3d6d2937f1b754c Mon Sep 17 00:00:00 2001 From: zhao_hanqing Date: Tue, 2 Apr 2024 03:24:36 +0000 Subject: [PATCH 5/5] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20qos?= =?UTF-8?q?=5Fauth/auth=5Fctl/qos=5Fctrl.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- qos_auth/auth_ctl/qos_ctrl.c | 696 ----------------------------------- 1 file changed, 696 deletions(-) delete mode 100644 qos_auth/auth_ctl/qos_ctrl.c diff --git a/qos_auth/auth_ctl/qos_ctrl.c b/qos_auth/auth_ctl/qos_ctrl.c deleted file mode 100644 index 11d3f23..0000000 --- a/qos_auth/auth_ctl/qos_ctrl.c +++ /dev/null @@ -1,696 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * drivers/auth_ctl/auth_ctrl.c - * - * Copyright (c) 2022 Huawei Device Co., Ltd. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "auth_ctrl.h" -#include "qos_ctrl.h" - -typedef long (*qos_ctrl_func)(int abi, void __user *uarg); - -static long ctrl_qos_operation(int abi, void __user *uarg); -static long ctrl_qos_policy(int abi, void __user *uarg); - -#define QOS_LEVEL_SET_MAX 5 - -static qos_ctrl_func g_func_array[QOS_CTRL_MAX_NR] = { - NULL, /* reserved */ - ctrl_qos_operation, - ctrl_qos_policy, -}; - -static struct qos_policy_map qos_policy_array[QOS_POLICY_MAX_NR]; - -void remove_qos_tasks(struct auth_struct *auth) -{ - int i; - struct qos_task_struct *tmp, *next; - struct task_struct *p; - - mutex_lock(&auth->mutex); - for (i = QOS_POLICY_MIN_LEVEL; i < NR_QOS; ++i) { - list_for_each_entry_safe(tmp, next, &auth->tasks[i], qos_list) { - p = container_of(tmp, struct task_struct, qts); - if (!list_empty(&tmp->qos_list)) { - list_del_init(&tmp->qos_list); - tmp->in_qos = NO_QOS; - put_task_struct(p); - } - } - } - mutex_unlock(&auth->mutex); -} - -static void init_sched_attr(struct sched_attr *attr) -{ - memset(attr, 0, sizeof(struct sched_attr)); -} - -static inline bool is_system(unsigned int uid) -{ - return uid == SYSTEM_UID; -} - -/* This function must be called when p is valid. That means the p's refcount must exist */ -static int sched_set_task_qos_attr(struct task_struct *p, int level, int status) -{ - struct qos_policy_item *item; - struct qos_policy_map *policy_map; - struct sched_attr attr; - - read_lock(&qos_policy_array[status].lock); - if (!qos_policy_array[status].initialized) { - pr_err("[QOS_CTRL] dirty qos policy, pid=%d, uid=%d, status=%d\n", - p->pid, p->cred->uid.val, status); - read_unlock(&qos_policy_array[status].lock); - return -DIRTY_QOS_POLICY; - } - - policy_map = &qos_policy_array[status]; - item = &policy_map->levels[level]; - - init_sched_attr(&attr); - attr.size = sizeof(struct sched_attr); - attr.sched_policy = SCHED_NORMAL; - - if (policy_map->policy_flag & QOS_FLAG_NICE) - attr.sched_nice = item->nice; - - if (policy_map->policy_flag & QOS_FLAG_LATENCY_NICE) { - attr.sched_flags |= SCHED_FLAG_LATENCY_NICE; - attr.sched_latency_nice = item->latency_nice; - } - - if ((policy_map->policy_flag & QOS_FLAG_RT) && item->rt_sched_priority) { - attr.sched_policy = SCHED_FIFO; - attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; - attr.sched_priority = item->rt_sched_priority; - } - - read_unlock(&qos_policy_array[status].lock); - - if (unlikely(p->flags & PF_EXITING)) { - pr_info("[QOS_CTRL] dying task, no need to set qos\n"); - return -THREAD_EXITING; - } - - return sched_setattr_nocheck(p, &attr); -} - -/* - * Switch qos mode when status changed. - * Lock auth before calling this function - */ -void qos_switch(struct auth_struct *auth, int target_status) -{ - int i; - int ret; - struct task_struct *task; - struct qos_task_struct *qts; - - if (!auth) { - pr_err("[QOS_CTRL] auth no exist, qos switch failed\n"); - return; - } - - lockdep_assert_held(&auth->mutex); - - if (auth->status == target_status) { - pr_info("[QOS_CTRL] same status, no need to switch qos\n"); - return; - } - - for (i = QOS_POLICY_MIN_LEVEL; i < NR_QOS; ++i) { - list_for_each_entry(qts, &auth->tasks[i], qos_list) { - task = container_of(qts, struct task_struct, qts); - ret = sched_set_task_qos_attr(task, i, target_status); - if (ret) - pr_err("[QOS_CTRL] set qos attr failed, qos switch failed\n"); - } - } -} - -static int qos_insert_task(struct task_struct *p, struct list_head *head, unsigned int level) -{ - struct qos_task_struct *qts = &p->qts; - - if (qts->in_qos > NO_QOS) { - pr_err("[QOS_CTRL] qos apply still active, no duplicate add\n"); - return -PID_DUPLICATE; - } - - if (likely(list_empty(&qts->qos_list))) { - get_task_struct(p); - list_add(&qts->qos_list, head); - qts->in_qos = level; - } - - return 0; -} - -static int qos_remove_task(struct task_struct *p) -{ - struct qos_task_struct *qts = (struct qos_task_struct *) &p->qts; - - if (qts->in_qos == NO_QOS) { - pr_err("[QOS_CTRL] task not in qos, no need to remove\n"); - return -PID_NOT_EXIST; - } - - if (likely(!list_empty(&qts->qos_list))) { - list_del_init(&qts->qos_list); - qts->in_qos = NO_QOS; - put_task_struct(p); - } - - return 0; -} - -static inline bool super_user(struct task_struct *p) -{ - return super_uid(task_uid(p).val); -} - -/* - * judge permission for changing tasks' qos - */ -static bool can_change_qos(struct task_struct *p, unsigned int qos_level) -{ - struct auth_struct *auth; - auth = get_authority(p); - /* just system & root user can set(be setted) high qos level */ - if (!auth || (auth && !super_user(p) && qos_level > QOS_LEVEL_SET_MAX)) { - pr_err("[QOS_CTRL] %d have no permission to change qos\n", p->pid); - return false; - } - - return true; -} - -int qos_apply(struct qos_ctrl_data *data) -{ - unsigned int level = data->level; - struct auth_struct *auth; - struct task_struct *p; - struct qos_task_struct *qts; - int pid = data->pid; - int ret; - - if (level >= NR_QOS || level == NO_QOS) { - pr_err("[QOS_CTRL] no this qos level, qos apply failed\n"); - ret = -ARG_INVALID; - goto out; - } - - p = find_get_task_by_vpid((pid_t)pid); - if (unlikely(!p)) { - pr_err("[QOS_CTRL] no matching task for this pid, qos apply failed\n"); - ret = -ESRCH; - goto out; - } - - if (unlikely(p->flags & PF_EXITING)) { - pr_info("[QOS_CTRL] dying task, no need to set qos\n"); - ret = -THREAD_EXITING; - goto out_put_task; - } - - if (!can_change_qos(current, level)) { - pr_err("[QOS_CTRL] QOS apply not permit\n"); - ret = -ARG_INVALID; - goto out_put_task; - } - - auth = get_authority(p); - if (!auth) { - pr_err("[QOS_CTRL] no auth data for pid=%d(%s), qos apply failed\n", - p->tgid, p->comm); - ret = -PID_NOT_FOUND; - goto out_put_task; - } - - mutex_lock(&auth->mutex); - if (auth->status == AUTH_STATUS_DEAD) { - pr_err("[QOS_CTRL] this auth data has been deleted\n"); - ret = -INVALID_AUTH; - goto out_unlock; - } - - if (auth->num[level] >= QOS_NUM_MAX) { - pr_err("[QOS_CTRL] qos num exceeds limit, cached only\n"); - ret = -QOS_THREAD_NUM_EXCEED_LIMIT; - goto out_unlock; - } - - qts = (struct qos_task_struct *) &p->qts; - - /* effective qos must in range [NO_QOS, NR_QOS) */ - if (qts->in_qos != NO_QOS) { - if (qts->in_qos == level) { - ret = 0; - goto out_unlock; - } - - --auth->num[qts->in_qos]; - qos_remove_task(p); - } - - ret = qos_insert_task(p, &auth->tasks[level], level); - if (ret < 0) { - pr_err("[QOS_CTRL] insert task to qos list %d failed\n", level); - goto out_unlock; - } - - ++auth->num[level]; - - ret = sched_set_task_qos_attr(p, level, auth->status); - if (ret) { - pr_err("[QOS_CTRL] set qos_level %d for thread %d on status %d failed\n", - level, p->pid, auth->status); - --auth->num[level]; - qos_remove_task(p); - } - -out_unlock: - mutex_unlock(&auth->mutex); - put_auth_struct(auth); -out_put_task: - put_task_struct(p); -out: - return ret; -} - -int qos_leave(struct qos_ctrl_data *data) -{ - unsigned int level; - struct auth_struct *auth; - struct task_struct *p; - struct qos_task_struct *qts; - int pid = data->pid; - int ret; - - p = find_get_task_by_vpid((pid_t)pid); - if (!p) { - pr_err("[QOS_CTRL] no matching task for this pid, qos apply failed\n"); - ret = -ESRCH; - goto out; - } - - if (unlikely(p->flags & PF_EXITING)) { - pr_info("[QOS_CTRL] dying task, no need to set qos\n"); - ret = -THREAD_EXITING; - goto out_put_task; - } - - auth = get_authority(p); - if (!auth) { - pr_err("[QOS_CTRL] no auth data for pid=%d(%s), qos stop failed\n", - p->tgid, p->comm); - ret = -PID_NOT_FOUND; - goto out_put_task; - } - - mutex_lock(&auth->mutex); - - qts = (struct qos_task_struct *) &p->qts; - - level = qts->in_qos; - if (level == NO_QOS) { - pr_err("[QOS_CTRL] task not in qos list, qos stop failed\n"); - ret = -ARG_INVALID; - goto out_unlock; - } - - if (!can_change_qos(current, 0)) { - pr_err("[QOS_CTRL] apply for others not permit\n"); - ret = -ARG_INVALID; - goto out_unlock; - } - - if (auth->status == AUTH_STATUS_DEAD) { - pr_err("[QOS_CTRL] this auth data has been deleted\n"); - ret = -INVALID_AUTH; - goto out_unlock; - } - - ret = qos_remove_task(p); - if (ret < 0) { - pr_err("[QOS_CTRL] remove task from qos list %d failed\n", level); - goto out_unlock; - } - - --auth->num[level]; - - /* - * NO NEED to judge whether current status is AUTH_STATUS_DISABLE. - * In the auth destoring context, the removing of thread's sched attr was protected by - * auth->mutex, AUTH_STATUS_DISABLED will never appear here. - * - * The second param 3 means nothing, actually you can use any valid level here, cause the - * policy matching AUTH_STATUS_DISABLED has default parameters for all qos level, which can - * keep a powerful thread to behave like a ordinary thread. - */ - ret = sched_set_task_qos_attr(p, 3, AUTH_STATUS_DISABLED); - if (ret) - pr_err("[QOS_CTRL] set qos_level %d for thread %d on status %d to default failed\n", - level, p->pid, auth->status); - -out_unlock: - mutex_unlock(&auth->mutex); - put_auth_struct(auth); -out_put_task: - put_task_struct(p); -out: - return ret; -} - -void init_task_qos(struct task_struct *p) -{ - struct qos_task_struct *qts = (struct qos_task_struct *) &p->qts; - - INIT_LIST_HEAD(&qts->qos_list); - qts->in_qos = NO_QOS; -} - -/* - * Remove statistic info in auth when task exit - */ -void sched_exit_qos_list(struct task_struct *p) -{ - struct auth_struct *auth; - struct qos_task_struct *qts = (struct qos_task_struct *) &p->qts; - - /* - * For common tasks(the vast majority): - * skip get authority, fast return here. - * - * For qos tasks: - * If contend with auth_delete() happens, - * 1. function return here, auth_delete() will do the clean up - * 2. function go on, either no auth return, either do clean up here - * Both cases guarantee data synchronization - */ - if (likely(qts->in_qos == NO_QOS)) - return; - - auth = get_authority(p); - if (!auth) - goto out; - - mutex_lock(&auth->mutex); - if (qts->in_qos == NO_QOS) { - mutex_unlock(&auth->mutex); - goto out_put_auth; - } - --auth->num[qts->in_qos]; - list_del_init(&qts->qos_list); - qts->in_qos = NO_QOS; - put_task_struct(p); - mutex_unlock(&auth->mutex); - -out_put_auth: - put_auth_struct(auth); -out: - return; -} - -typedef int (*qos_manipulate_func)(struct qos_ctrl_data *data); - -static qos_manipulate_func qos_func_array[QOS_OPERATION_CMD_MAX_NR] = { - NULL, - qos_apply, //1 - qos_leave, -}; - -static long do_qos_manipulate(struct qos_ctrl_data *data) -{ - long ret = 0; - unsigned int type = data->type; - - if (type <= 0 || type >= QOS_OPERATION_CMD_MAX_NR) { - pr_err("[QOS_CTRL] CMD_ID_QOS_MANIPULATE type not valid\n"); - return -ARG_INVALID; - } - - if (qos_func_array[type]) - ret = (long)(*qos_func_array[type])(data); - - return ret; -} - -static long ctrl_qos_operation(int abi, void __user *uarg) -{ - struct qos_ctrl_data qos_data; - int ret = -1; - -#pragma GCC diagnostic push - - switch (abi) { - case QOS_IOCTL_ABI_ARM32: - ret = copy_from_user(&qos_data, - (void __user *)compat_ptr((compat_uptr_t)(uintptr_t)uarg), - sizeof(struct qos_ctrl_data)); - break; - case QOS_IOCTL_ABI_AARCH64: - ret = copy_from_user(&qos_data, uarg, sizeof(struct qos_ctrl_data)); - break; - default: - pr_err("[QOS_CTRL] abi format error\n"); - break; - } - -#pragma GCC diagnostic pop - - if (ret) { - pr_err("[QOS_CTRL] %s copy user data failed\n", __func__); - return ret; - } - - return do_qos_manipulate(&qos_data); -} - -#define MAX_LATENCY_NICE 19 -#define MIN_LATENCY_NICE -20 - -static inline bool valid_nice(int nice) -{ - return nice >= MIN_NICE && nice <= MAX_NICE; -} - -static inline bool valid_latency_nice(int latency_nice) -{ - return latency_nice >= MIN_LATENCY_NICE && latency_nice <= MAX_LATENCY_NICE; -} - -static inline bool valid_uclamp(int uclamp_min, int uclamp_max) -{ - if (uclamp_min > uclamp_max) - return false; - if (uclamp_max > SCHED_CAPACITY_SCALE) - return false; - - return true; -} - -static inline bool valid_rt(int sched_priority) -{ - if (sched_priority > MAX_USER_RT_PRIO - 1 || sched_priority < 0) - return false; - - return true; -} - -static bool valid_qos_flag(unsigned int qos_flag) -{ - if (qos_flag & ~QOS_FLAG_ALL) - return false; - - return true; -} - -static inline bool valid_qos_item(struct qos_policy_datas *datas) -{ - int i; - int type = datas->policy_type; - struct qos_policy_data *data; - - if (type <= 0 || type >= QOS_POLICY_MAX_NR) { - pr_err("[QOS_CTRL] not valid qos policy type, policy change failed\n"); - goto out_failed; - } - - if (!valid_qos_flag(datas->policy_flag)) { - pr_err("[QOS_CTRL] not valid qos flag, policy change failed\n"); - goto out_failed; - } - - /* check user space qos polcicy data, level 0 reserved */ - for (i = 0; i < NR_QOS; ++i) { - data = &datas->policys[i]; - - if (!valid_nice(data->nice)) { - pr_err("[QOS_CTRL] invalid nice, policy change failed\n"); - goto out_failed; - } - - if (!valid_latency_nice(data->latency_nice)) { - pr_err("[QOS_CTRL] invalid latency_nice, policy change failed\n"); - goto out_failed; - } - - if (!valid_uclamp(data->uclamp_min, data->uclamp_max)) { - pr_err("[QOS_CTRL] invalid uclamp, policy change failed\n"); - goto out_failed; - } - - if (!valid_rt(data->rt_sched_priority)) { - pr_err("[QOS_CTRL] invalid rt, policy change failed\n"); - goto out_failed; - } - } - - return true; - -out_failed: - pr_err("[QOS_CTRL] not valid qos policy params\n"); - return false; -} - -static long do_qos_policy_change(struct qos_policy_datas *datas) -{ - long ret = 0; - int i; - struct qos_policy_item *item; - struct qos_policy_data *data; - int type = datas->policy_type; - - if (type >= QOS_POLICY_MAX_NR) { - pr_err("[QOS_CTRL] not valid policy type\n"); - goto out_failed; - } - - if (!valid_qos_item(datas)) - goto out_failed; - - write_lock(&qos_policy_array[type].lock); - for (i = QOS_POLICY_MIN_LEVEL; i < NR_QOS; ++i) { - item = &qos_policy_array[type].levels[i]; - - /* user space policy params */ - data = &datas->policys[i]; - - item->nice = data->nice; - item->latency_nice = data->latency_nice; - item->uclamp_min = data->uclamp_min; - item->uclamp_max = data->uclamp_max; - /* only specific qos level could use SCHED_FIFO */ - item->rt_sched_priority = (i < MIN_RT_QOS_LEVEL) ? 0 : - data->rt_sched_priority; - } - qos_policy_array[type].policy_flag = datas->policy_flag; - qos_policy_array[type].initialized = true; - write_unlock(&qos_policy_array[type].lock); - - return ret; - -out_failed: - return -ARG_INVALID; -} - -static long ctrl_qos_policy(int abi, void __user *uarg) -{ - struct qos_policy_datas policy_datas; - long ret = -1; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" - - switch (abi) { - case QOS_IOCTL_ABI_ARM32: - ret = copy_from_user(&policy_datas, - (void __user *)compat_ptr((compat_uptr_t)uarg), - sizeof(struct qos_policy_datas)); - break; - case QOS_IOCTL_ABI_AARCH64: - ret = copy_from_user(&policy_datas, uarg, sizeof(struct qos_policy_datas)); - break; - default: - pr_err("[QOS_CTRL] abi format error\n"); - break; - } - -#pragma GCC diagnostic pop - - if (ret) { - pr_err("[QOS_RTG] %s copy user data failed\n", __func__); - return ret; - } - - return do_qos_policy_change(&policy_datas); -} - -long do_qos_ctrl_ioctl(int abi, struct file *file, unsigned int cmd, unsigned long arg) -{ - void __user *uarg = (void __user *)arg; - unsigned int func_cmd = _IOC_NR(cmd); - - if (uarg == NULL) { - pr_err("%s: invalid user uarg\n", __func__); - return -EINVAL; - } - - if (_IOC_TYPE(cmd) != QOS_CTRL_IPC_MAGIG) { - pr_err("%s: qos ctrl magic fail, TYPE=%d\n", - __func__, _IOC_TYPE(cmd)); - return -EINVAL; - } - - if (func_cmd >= QOS_CTRL_MAX_NR) { - pr_err("%s: qos ctrl cmd error, cmd:%d\n", - __func__, _IOC_TYPE(cmd)); - return -EINVAL; - } - -#ifdef CONFIG_QOS_AUTHORITY - if (!check_authorized(func_cmd, QOS_AUTH_FLAG)) { - pr_err("[QOS_CTRL] %s: pid not authorized\n", __func__); - return -PID_NOT_AUTHORIZED; - } -#endif - - if (g_func_array[func_cmd]) - return (*g_func_array[func_cmd])(abi, uarg); - - return -EINVAL; -} - -static void init_qos_policy_array(void) -{ - int i; - - /* index 0 reserved */ - for (i = 1; i < QOS_POLICY_MAX_NR; ++i) - rwlock_init(&qos_policy_array[i].lock); - - pr_info("[QOS_CTRL] lock in qos policy initialized\n"); -} - -int __init init_qos_ctrl(void) -{ - init_qos_policy_array(); - - return 0; -} - -- Gitee