1// SPDX-License-Identifier: GPL-2.0 2/* 3 * fs/ioprio.c 4 * 5 * Copyright (C) 2004 Jens Axboe <axboe@kernel.dk> 6 * 7 * Helper functions for setting/querying io priorities of processes. The 8 * system calls closely mimmick getpriority/setpriority, see the man page for 9 * those. The prio argument is a composite of prio class and prio data, where 10 * the data argument has meaning within that class. The standard scheduling 11 * classes have 8 distinct prio levels, with 0 being the highest prio and 7 12 * being the lowest. 13 * 14 * IOW, setting BE scheduling class with prio 2 is done ala: 15 * 16 * unsigned int prio = (IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT) | 2; 17 * 18 * ioprio_set(PRIO_PROCESS, pid, prio); 19 * 20 * See also Documentation/block/ioprio.rst 21 * 22 */ 23#include <linux/gfp.h> 24#include <linux/kernel.h> 25#include <linux/export.h> 26#include <linux/ioprio.h> 27#include <linux/cred.h> 28#include <linux/blkdev.h> 29#include <linux/capability.h> 30#include <linux/sched/user.h> 31#include <linux/sched/task.h> 32#include <linux/syscalls.h> 33#include <linux/security.h> 34#include <linux/pid_namespace.h> 35 36int set_task_ioprio(struct task_struct *task, int ioprio) 37{ 38 int err; 39 struct io_context *ioc; 40 const struct cred *cred = current_cred(), *tcred; 41 42 rcu_read_lock(); 43 tcred = __task_cred(task); 44 if (!uid_eq(tcred->uid, cred->euid) && 45 !uid_eq(tcred->uid, cred->uid) && !capable(CAP_SYS_NICE)) { 46 rcu_read_unlock(); 47 return -EPERM; 48 } 49 rcu_read_unlock(); 50 51 err = security_task_setioprio(task, ioprio); 52 if (err) 53 return err; 54 55 ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); 56 if (ioc) { 57 ioc->ioprio = ioprio; 58 put_io_context(ioc); 59 } 60 61 return err; 62} 63EXPORT_SYMBOL_GPL(set_task_ioprio); 64 65int ioprio_check_cap(int ioprio) 66{ 67 int class = IOPRIO_PRIO_CLASS(ioprio); 68 int data = IOPRIO_PRIO_DATA(ioprio); 69 70 switch (class) { 71 case IOPRIO_CLASS_RT: 72 /* 73 * Originally this only checked for CAP_SYS_ADMIN, 74 * which was implicitly allowed for pid 0 by security 75 * modules such as SELinux. Make sure we check 76 * CAP_SYS_ADMIN first to avoid a denial/avc for 77 * possibly missing CAP_SYS_NICE permission. 78 */ 79 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_NICE)) 80 return -EPERM; 81 fallthrough; 82 /* rt has prio field too */ 83 case IOPRIO_CLASS_BE: 84 if (data >= IOPRIO_BE_NR || data < 0) 85 return -EINVAL; 86 87 break; 88 case IOPRIO_CLASS_IDLE: 89 break; 90 case IOPRIO_CLASS_NONE: 91 if (data) 92 return -EINVAL; 93 break; 94 default: 95 return -EINVAL; 96 } 97 98 return 0; 99} 100 101SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) 102{ 103 struct task_struct *p, *g; 104 struct user_struct *user; 105 struct pid *pgrp; 106 kuid_t uid; 107 int ret; 108 109 ret = ioprio_check_cap(ioprio); 110 if (ret) 111 return ret; 112 113 ret = -ESRCH; 114 rcu_read_lock(); 115 switch (which) { 116 case IOPRIO_WHO_PROCESS: 117 if (!who) 118 p = current; 119 else 120 p = find_task_by_vpid(who); 121 if (p) 122 ret = set_task_ioprio(p, ioprio); 123 break; 124 case IOPRIO_WHO_PGRP: 125 if (!who) 126 pgrp = task_pgrp(current); 127 else 128 pgrp = find_vpid(who); 129 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { 130 ret = set_task_ioprio(p, ioprio); 131 if (ret) 132 break; 133 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 134 break; 135 case IOPRIO_WHO_USER: 136 uid = make_kuid(current_user_ns(), who); 137 if (!uid_valid(uid)) 138 break; 139 if (!who) 140 user = current_user(); 141 else 142 user = find_user(uid); 143 144 if (!user) 145 break; 146 147 for_each_process_thread(g, p) { 148 if (!uid_eq(task_uid(p), uid) || 149 !task_pid_vnr(p)) 150 continue; 151 ret = set_task_ioprio(p, ioprio); 152 if (ret) 153 goto free_uid; 154 } 155free_uid: 156 if (who) 157 free_uid(user); 158 break; 159 default: 160 ret = -EINVAL; 161 } 162 163 rcu_read_unlock(); 164 return ret; 165} 166 167static int get_task_ioprio(struct task_struct *p) 168{ 169 int ret; 170 171 ret = security_task_getioprio(p); 172 if (ret) 173 goto out; 174 ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM); 175 task_lock(p); 176 if (p->io_context) 177 ret = p->io_context->ioprio; 178 task_unlock(p); 179out: 180 return ret; 181} 182 183int ioprio_best(unsigned short aprio, unsigned short bprio) 184{ 185 if (!ioprio_valid(aprio)) 186 aprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM); 187 if (!ioprio_valid(bprio)) 188 bprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM); 189 190 return min(aprio, bprio); 191} 192 193SYSCALL_DEFINE2(ioprio_get, int, which, int, who) 194{ 195 struct task_struct *g, *p; 196 struct user_struct *user; 197 struct pid *pgrp; 198 kuid_t uid; 199 int ret = -ESRCH; 200 int tmpio; 201 202 rcu_read_lock(); 203 switch (which) { 204 case IOPRIO_WHO_PROCESS: 205 if (!who) 206 p = current; 207 else 208 p = find_task_by_vpid(who); 209 if (p) 210 ret = get_task_ioprio(p); 211 break; 212 case IOPRIO_WHO_PGRP: 213 if (!who) 214 pgrp = task_pgrp(current); 215 else 216 pgrp = find_vpid(who); 217 read_lock(&tasklist_lock); 218 do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { 219 tmpio = get_task_ioprio(p); 220 if (tmpio < 0) 221 continue; 222 if (ret == -ESRCH) 223 ret = tmpio; 224 else 225 ret = ioprio_best(ret, tmpio); 226 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 227 read_unlock(&tasklist_lock); 228 229 break; 230 case IOPRIO_WHO_USER: 231 uid = make_kuid(current_user_ns(), who); 232 if (!who) 233 user = current_user(); 234 else 235 user = find_user(uid); 236 237 if (!user) 238 break; 239 240 for_each_process_thread(g, p) { 241 if (!uid_eq(task_uid(p), user->uid) || 242 !task_pid_vnr(p)) 243 continue; 244 tmpio = get_task_ioprio(p); 245 if (tmpio < 0) 246 continue; 247 if (ret == -ESRCH) 248 ret = tmpio; 249 else 250 ret = ioprio_best(ret, tmpio); 251 } 252 253 if (who) 254 free_uid(user); 255 break; 256 default: 257 ret = -EINVAL; 258 } 259 260 rcu_read_unlock(); 261 return ret; 262} 263