mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-19 12:58:20 +07:00
de78a9c42a
This patch implements a framework for Kernel Userspace Access Protection. Then subarches will have the possibility to provide their own implementation by providing setup_kuap() and allow/prevent_user_access(). Some platforms will need to know the area accessed and whether it is accessed from read, write or both. Therefore source, destination and size and handed over to the two functions. mpe: Rename to allow/prevent rather than unlock/lock, and add read/write wrappers. Drop the 32-bit code for now until we have an implementation for it. Add kuap to pt_regs for 64-bit as well as 32-bit. Don't split strings, use pr_crit_ratelimited(). Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Russell Currey <ruscur@russell.cc> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
107 lines
2.4 KiB
C
107 lines
2.4 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* Copyright (C) IBM Corporation, 2010
|
|
*
|
|
* Author: Anton Blanchard <anton@au.ibm.com>
|
|
*/
|
|
#include <linux/export.h>
|
|
#include <linux/compiler.h>
|
|
#include <linux/types.h>
|
|
#include <asm/checksum.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
__wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
|
int len, __wsum sum, int *err_ptr)
|
|
{
|
|
unsigned int csum;
|
|
|
|
might_sleep();
|
|
allow_read_from_user(src, len);
|
|
|
|
*err_ptr = 0;
|
|
|
|
if (!len) {
|
|
csum = 0;
|
|
goto out;
|
|
}
|
|
|
|
if (unlikely((len < 0) || !access_ok(src, len))) {
|
|
*err_ptr = -EFAULT;
|
|
csum = (__force unsigned int)sum;
|
|
goto out;
|
|
}
|
|
|
|
csum = csum_partial_copy_generic((void __force *)src, dst,
|
|
len, sum, err_ptr, NULL);
|
|
|
|
if (unlikely(*err_ptr)) {
|
|
int missing = __copy_from_user(dst, src, len);
|
|
|
|
if (missing) {
|
|
memset(dst + len - missing, 0, missing);
|
|
*err_ptr = -EFAULT;
|
|
} else {
|
|
*err_ptr = 0;
|
|
}
|
|
|
|
csum = csum_partial(dst, len, sum);
|
|
}
|
|
|
|
out:
|
|
prevent_read_from_user(src, len);
|
|
return (__force __wsum)csum;
|
|
}
|
|
EXPORT_SYMBOL(csum_and_copy_from_user);
|
|
|
|
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
|
|
__wsum sum, int *err_ptr)
|
|
{
|
|
unsigned int csum;
|
|
|
|
might_sleep();
|
|
allow_write_to_user(dst, len);
|
|
|
|
*err_ptr = 0;
|
|
|
|
if (!len) {
|
|
csum = 0;
|
|
goto out;
|
|
}
|
|
|
|
if (unlikely((len < 0) || !access_ok(dst, len))) {
|
|
*err_ptr = -EFAULT;
|
|
csum = -1; /* invalid checksum */
|
|
goto out;
|
|
}
|
|
|
|
csum = csum_partial_copy_generic(src, (void __force *)dst,
|
|
len, sum, NULL, err_ptr);
|
|
|
|
if (unlikely(*err_ptr)) {
|
|
csum = csum_partial(src, len, sum);
|
|
|
|
if (copy_to_user(dst, src, len)) {
|
|
*err_ptr = -EFAULT;
|
|
csum = -1; /* invalid checksum */
|
|
}
|
|
}
|
|
|
|
out:
|
|
prevent_write_to_user(dst, len);
|
|
return (__force __wsum)csum;
|
|
}
|
|
EXPORT_SYMBOL(csum_and_copy_to_user);
|