1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/kernel.h> 3 #include <linux/syscalls.h> 4 #include <linux/fdtable.h> 5 #include <linux/string.h> 6 #include <linux/random.h> 7 #include <linux/module.h> 8 #include <linux/ptrace.h> 9 #include <linux/init.h> 10 #include <linux/errno.h> 11 #include <linux/cache.h> 12 #include <linux/bug.h> 13 #include <linux/err.h> 14 #include <linux/kcmp.h> 15 #include <linux/capability.h> 16 #include <linux/list.h> 17 #include <linux/eventpoll.h> 18 #include <linux/file.h> 19 20 #include <asm/unistd.h> 21 22 /* 23 * We don't expose the real in-memory order of objects for security reasons. 24 * But still the comparison results should be suitable for sorting. So we 25 * obfuscate kernel pointers values and compare the production instead. 26 * 27 * The obfuscation is done in two steps. First we xor the kernel pointer with 28 * a random value, which puts pointer into a new position in a reordered space. 29 * Secondly we multiply the xor production with a large odd random number to 30 * permute its bits even more (the odd multiplier guarantees that the product 31 * is unique ever after the high bits are truncated, since any odd number is 32 * relative prime to 2^n). 33 * 34 * Note also that the obfuscation itself is invisible to userspace and if needed 35 * it can be changed to an alternate scheme. 36 */ 37 static unsigned long cookies[KCMP_TYPES][2] __read_mostly; 38 39 static long kptr_obfuscate(long v, int type) 40 { 41 return (v ^ cookies[type][0]) * cookies[type][1]; 42 } 43 44 /* 45 * 0 - equal, i.e. v1 = v2 46 * 1 - less than, i.e. v1 < v2 47 * 2 - greater than, i.e. v1 > v2 48 * 3 - not equal but ordering unavailable (reserved for future) 49 */ 50 static int kcmp_ptr(void *v1, void *v2, enum kcmp_type type) 51 { 52 long t1, t2; 53 54 t1 = kptr_obfuscate((long)v1, type); 55 t2 = kptr_obfuscate((long)v2, type); 56 57 return (t1 < t2) | ((t1 > t2) << 1); 58 } 59 60 /* The caller must have pinned the task */ 61 static struct file * 62 get_file_raw_ptr(struct task_struct *task, unsigned int idx) 63 { 64 struct file *file = NULL; 65 66 task_lock(task); 67 rcu_read_lock(); 68 69 if (task->files) 70 file = fcheck_files(task->files, idx); 71 72 rcu_read_unlock(); 73 task_unlock(task); 74 75 return file; 76 } 77 78 static void kcmp_unlock(struct mutex *m1, struct mutex *m2) 79 { 80 if (likely(m2 != m1)) 81 mutex_unlock(m2); 82 mutex_unlock(m1); 83 } 84 85 static int kcmp_lock(struct mutex *m1, struct mutex *m2) 86 { 87 int err; 88 89 if (m2 > m1) 90 swap(m1, m2); 91 92 err = mutex_lock_killable(m1); 93 if (!err && likely(m1 != m2)) { 94 err = mutex_lock_killable_nested(m2, SINGLE_DEPTH_NESTING); 95 if (err) 96 mutex_unlock(m1); 97 } 98 99 return err; 100 } 101 102 #ifdef CONFIG_EPOLL 103 static int kcmp_epoll_target(struct task_struct *task1, 104 struct task_struct *task2, 105 unsigned long idx1, 106 struct kcmp_epoll_slot __user *uslot) 107 { 108 struct file *filp, *filp_epoll, *filp_tgt; 109 struct kcmp_epoll_slot slot; 110 struct files_struct *files; 111 112 if (copy_from_user(&slot, uslot, sizeof(slot))) 113 return -EFAULT; 114 115 filp = get_file_raw_ptr(task1, idx1); 116 if (!filp) 117 return -EBADF; 118 119 files = get_files_struct(task2); 120 if (!files) 121 return -EBADF; 122 123 spin_lock(&files->file_lock); 124 filp_epoll = fcheck_files(files, slot.efd); 125 if (filp_epoll) 126 get_file(filp_epoll); 127 else 128 filp_tgt = ERR_PTR(-EBADF); 129 spin_unlock(&files->file_lock); 130 put_files_struct(files); 131 132 if (filp_epoll) { 133 filp_tgt = get_epoll_tfile_raw_ptr(filp_epoll, slot.tfd, slot.toff); 134 fput(filp_epoll); 135 } 136 137 if (IS_ERR(filp_tgt)) 138 return PTR_ERR(filp_tgt); 139 140 return kcmp_ptr(filp, filp_tgt, KCMP_FILE); 141 } 142 #else 143 static int kcmp_epoll_target(struct task_struct *task1, 144 struct task_struct *task2, 145 unsigned long idx1, 146 struct kcmp_epoll_slot __user *uslot) 147 { 148 return -EOPNOTSUPP; 149 } 150 #endif 151 152 SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type, 153 unsigned long, idx1, unsigned long, idx2) 154 { 155 struct task_struct *task1, *task2; 156 int ret; 157 158 rcu_read_lock(); 159 160 /* 161 * Tasks are looked up in caller's PID namespace only. 162 */ 163 task1 = find_task_by_vpid(pid1); 164 task2 = find_task_by_vpid(pid2); 165 if (!task1 || !task2) 166 goto err_no_task; 167 168 get_task_struct(task1); 169 get_task_struct(task2); 170 171 rcu_read_unlock(); 172 173 /* 174 * One should have enough rights to inspect task details. 175 */ 176 ret = kcmp_lock(&task1->signal->cred_guard_mutex, 177 &task2->signal->cred_guard_mutex); 178 if (ret) 179 goto err; 180 if (!ptrace_may_access(task1, PTRACE_MODE_READ_REALCREDS) || 181 !ptrace_may_access(task2, PTRACE_MODE_READ_REALCREDS)) { 182 ret = -EPERM; 183 goto err_unlock; 184 } 185 186 switch (type) { 187 case KCMP_FILE: { 188 struct file *filp1, *filp2; 189 190 filp1 = get_file_raw_ptr(task1, idx1); 191 filp2 = get_file_raw_ptr(task2, idx2); 192 193 if (filp1 && filp2) 194 ret = kcmp_ptr(filp1, filp2, KCMP_FILE); 195 else 196 ret = -EBADF; 197 break; 198 } 199 case KCMP_VM: 200 ret = kcmp_ptr(task1->mm, task2->mm, KCMP_VM); 201 break; 202 case KCMP_FILES: 203 ret = kcmp_ptr(task1->files, task2->files, KCMP_FILES); 204 break; 205 case KCMP_FS: 206 ret = kcmp_ptr(task1->fs, task2->fs, KCMP_FS); 207 break; 208 case KCMP_SIGHAND: 209 ret = kcmp_ptr(task1->sighand, task2->sighand, KCMP_SIGHAND); 210 break; 211 case KCMP_IO: 212 ret = kcmp_ptr(task1->io_context, task2->io_context, KCMP_IO); 213 break; 214 case KCMP_SYSVSEM: 215 #ifdef CONFIG_SYSVIPC 216 ret = kcmp_ptr(task1->sysvsem.undo_list, 217 task2->sysvsem.undo_list, 218 KCMP_SYSVSEM); 219 #else 220 ret = -EOPNOTSUPP; 221 #endif 222 break; 223 case KCMP_EPOLL_TFD: 224 ret = kcmp_epoll_target(task1, task2, idx1, (void *)idx2); 225 break; 226 default: 227 ret = -EINVAL; 228 break; 229 } 230 231 err_unlock: 232 kcmp_unlock(&task1->signal->cred_guard_mutex, 233 &task2->signal->cred_guard_mutex); 234 err: 235 put_task_struct(task1); 236 put_task_struct(task2); 237 238 return ret; 239 240 err_no_task: 241 rcu_read_unlock(); 242 return -ESRCH; 243 } 244 245 static __init int kcmp_cookies_init(void) 246 { 247 int i; 248 249 get_random_bytes(cookies, sizeof(cookies)); 250 251 for (i = 0; i < KCMP_TYPES; i++) 252 cookies[i][1] |= (~(~0UL >> 1) | 1); 253 254 return 0; 255 } 256 arch_initcall(kcmp_cookies_init); 257