/* * We don't expose the real in-memory order of objects for security reasons. * But still the comparison results should be suitable for sorting. So we * obfuscate kernel pointers values and compare the production instead. * * The obfuscation is done in two steps. First we xor the kernel pointer with * a random value, which puts pointer into a new position in a reordered space. * Secondly we multiply the xor production with a large odd random number to * permute its bits even more (the odd multiplier guarantees that the product * is unique ever after the high bits are truncated, since any odd number is * relative prime to 2^n). * * Note also that the obfuscation itself is invisible to userspace and if needed * it can be changed to an alternate scheme.
*/ staticunsignedlong cookies[KCMP_TYPES][2] __read_mostly;
staticlong kptr_obfuscate(long v, int type)
{ return (v ^ cookies[type][0]) * cookies[type][1];
}
/* * 0 - equal, i.e. v1 = v2 * 1 - less than, i.e. v1 < v2 * 2 - greater than, i.e. v1 > v2 * 3 - not equal but ordering unavailable (reserved for future)
*/ staticint kcmp_ptr(void *v1, void *v2, enum kcmp_type type)
{ long t1, t2;
/* * Tasks are looked up in caller's PID namespace only.
*/
task1 = find_task_by_vpid(pid1);
task2 = find_task_by_vpid(pid2); if (unlikely(!task1 || !task2)) goto err_no_task;
get_task_struct(task1);
get_task_struct(task2);
rcu_read_unlock();
/* * One should have enough rights to inspect task details.
*/
ret = kcmp_lock(&task1->signal->exec_update_lock,
&task2->signal->exec_update_lock); if (ret) goto err; if (!ptrace_may_access(task1, PTRACE_MODE_READ_REALCREDS) ||
!ptrace_may_access(task2, PTRACE_MODE_READ_REALCREDS)) {
ret = -EPERM; goto err_unlock;
}
switch (type) { case KCMP_FILE: { struct file *filp1, *filp2;
if (filp1 && filp2)
ret = kcmp_ptr(filp1, filp2, KCMP_FILE); else
ret = -EBADF; break;
} case KCMP_VM:
ret = kcmp_ptr(task1->mm, task2->mm, KCMP_VM); break; case KCMP_FILES:
ret = kcmp_ptr(task1->files, task2->files, KCMP_FILES); break; case KCMP_FS:
ret = kcmp_ptr(task1->fs, task2->fs, KCMP_FS); break; case KCMP_SIGHAND:
ret = kcmp_ptr(task1->sighand, task2->sighand, KCMP_SIGHAND); break; case KCMP_IO:
ret = kcmp_ptr(task1->io_context, task2->io_context, KCMP_IO); break; case KCMP_SYSVSEM: #ifdef CONFIG_SYSVIPC
ret = kcmp_ptr(task1->sysvsem.undo_list,
task2->sysvsem.undo_list,
KCMP_SYSVSEM); #else
ret = -EOPNOTSUPP; #endif break; case KCMP_EPOLL_TFD:
ret = kcmp_epoll_target(task1, task2, idx1, (void *)idx2); break; default:
ret = -EINVAL; break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.