Re: [PATCH] add param that allows bootline control of hardened usercopy

From: Christoph von Recklinghausen
Date: Mon Jun 25 2018 - 18:29:17 EST


On 06/25/2018 03:44 PM, Laura Abbott wrote:
> On 06/25/2018 08:22 AM, Christoph von Recklinghausen wrote:
>> Add correct address for linux-mm
>>
>> On 06/25/2018 11:08 AM, Chris von Recklinghausen wrote:
>>> Enabling HARDENED_USER_COPY causes measurable regressions in the
>>> networking performances, up to 8% under UDP flood.
>>>
>>> A generic distro may want to enable HARDENED_USER_COPY in their default
>>> kernel config, but at the same time, such distro may want to be able to
>>> avoid the performance penalties in with the default configuration and
>>> enable the stricter check on a per-boot basis.
>>>
>>> This change adds a config variable and a boot parameter to
>>> conditionally
>>> enable HARDENED_USER_COPY at boot time, and switch HUC to off if
>>> HUC_DEFAULT_OFF is set.
>>>
>>> Signed-off-by: Chris von Recklinghausen <crecklin@xxxxxxxxxx>
>>> ---
>>> Â .../admin-guide/kernel-parameters.rstÂÂÂÂÂÂÂÂ |Â 2 ++
>>> Â .../admin-guide/kernel-parameters.txtÂÂÂÂÂÂÂÂ |Â 3 ++
>>> Â include/linux/thread_info.hÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ |Â 7 +++++
>>> Â mm/usercopy.cÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ | 28
>>> +++++++++++++++++++
>>> Â security/KconfigÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ | 10 +++++++
>>> Â 5 files changed, 50 insertions(+)
>>>
>>> diff --git a/Documentation/admin-guide/kernel-parameters.rst
>>> b/Documentation/admin-guide/kernel-parameters.rst
>>> index b8d0bc07ed0a..c3035038e3ae 100644
>>> --- a/Documentation/admin-guide/kernel-parameters.rst
>>> +++ b/Documentation/admin-guide/kernel-parameters.rst
>>> @@ -100,6 +100,8 @@ parameter is applicable::
>>> ÂÂÂÂÂ FBÂÂÂ The frame buffer device is enabled.
>>> ÂÂÂÂÂ FTRACEÂÂÂ Function tracing enabled.
>>> ÂÂÂÂÂ GCOVÂÂÂ GCOV profiling is enabled.
>>> +ÂÂÂ HUCÂÂÂ Hardened usercopy is enabled
>>> +ÂÂÂ HUCFÂÂÂ Hardened usercopy disabled at boot
>>> ÂÂÂÂÂ HWÂÂÂ Appropriate hardware is enabled.
>>> ÂÂÂÂÂ IA-64ÂÂÂ IA-64 architecture is enabled.
>>> ÂÂÂÂÂ IMAÂÂÂÂ Integrity measurement architecture is enabled.
>>> diff --git a/Documentation/admin-guide/kernel-parameters.txt
>>> b/Documentation/admin-guide/kernel-parameters.txt
>>> index efc7aa7a0670..cd3354bc14d3 100644
>>> --- a/Documentation/admin-guide/kernel-parameters.txt
>>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>>> @@ -816,6 +816,9 @@
>>> ÂÂÂÂÂ disable=ÂÂÂ [IPV6]
>>> ÂÂÂÂÂÂÂÂÂÂÂÂÂ See Documentation/networking/ipv6.txt.
>>> Â +ÂÂÂ enable_hardened_usercopy [HUC,HUCF]
>>> +ÂÂÂÂÂÂÂÂÂÂÂ Enable hardened usercopy checks
>>> +
>>> ÂÂÂÂÂ disable_radixÂÂÂ [PPC]
>>> ÂÂÂÂÂÂÂÂÂÂÂÂÂ Disable RADIX MMU mode on POWER9
>>> Â diff --git a/include/linux/thread_info.h
>>> b/include/linux/thread_info.h
>>> index 8d8821b3689a..140a36cc1c2c 100644
>>> --- a/include/linux/thread_info.h
>>> +++ b/include/linux/thread_info.h
>>> @@ -109,12 +109,19 @@ static inline int
>>> arch_within_stack_frames(const void * const stack,
>>> Â #endif
>>> Â Â #ifdef CONFIG_HARDENED_USERCOPY
>>> +#include <linux/jump_label.h>
>>> +
>>> +DECLARE_STATIC_KEY_FALSE(bypass_usercopy_checks);
>>> +
>>> Â extern void __check_object_size(const void *ptr, unsigned long n,
>>> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ bool to_user);
>>> Â Â static __always_inline void check_object_size(const void *ptr,
>>> unsigned long n,
>>> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ bool to_user)
>>> Â {
>>> +ÂÂÂ if (static_branch_likely(&bypass_usercopy_checks))
>>> +ÂÂÂÂÂÂÂ return;
>>> +
>>> ÂÂÂÂÂ if (!__builtin_constant_p(n))
>>> ÂÂÂÂÂÂÂÂÂ __check_object_size(ptr, n, to_user);
>>> Â }
>>> diff --git a/mm/usercopy.c b/mm/usercopy.c
>>> index e9e9325f7638..ce3996da1b2e 100644
>>> --- a/mm/usercopy.c
>>> +++ b/mm/usercopy.c
>>> @@ -279,3 +279,31 @@ void __check_object_size(const void *ptr,
>>> unsigned long n, bool to_user)
>>> ÂÂÂÂÂ check_kernel_text_object((const unsigned long)ptr, n, to_user);
>>> Â }
>>> Â EXPORT_SYMBOL(__check_object_size);
>>> +
>>> +DEFINE_STATIC_KEY_FALSE(bypass_usercopy_checks);
>>> +EXPORT_SYMBOL(bypass_usercopy_checks);
>>> +
>>> +#ifdef CONFIG_HUC_DEFAULT_OFF
>>> +#define HUC_DEFAULT false
>>> +#else
>>> +#define HUC_DEFAULT true
>>> +#endif
>>> +
>>> +static bool enable_huc_atboot = HUC_DEFAULT;
>>> +
>>> +static int __init parse_enable_usercopy(char *str)
>>> +{
>>> +ÂÂÂ enable_huc_atboot = true;
>>> +ÂÂÂ return 1;
>>> +}
>>> +
>>> +static int __init set_enable_usercopy(void)
>>> +{
>>> +ÂÂÂ if (enable_huc_atboot == false)
>>> +ÂÂÂÂÂÂÂ static_branch_enable(&bypass_usercopy_checks);
>>> +ÂÂÂ return 1;
>>> +}
>>> +
>>> +__setup("enable_hardened_usercopy", parse_enable_usercopy);
>>> +
>>> +late_initcall(set_enable_usercopy);
>>> diff --git a/security/Kconfig b/security/Kconfig
>>> index c4302067a3ad..a6173897b85c 100644
>>> --- a/security/Kconfig
>>> +++ b/security/Kconfig
>>> @@ -189,6 +189,16 @@ config HARDENED_USERCOPY_PAGESPAN
>>> ÂÂÂÂÂÂÂ been removed. This config is intended to be used only while
>>> ÂÂÂÂÂÂÂ trying to find such users.
>>> Â +config HUC_DEFAULT_OFF
>>> +ÂÂÂ bool "allow CONFIG_HARDENED_USERCOPY to be configured but
>>> disabled"
>>> +ÂÂÂ depends on HARDENED_USERCOPY
>>> +ÂÂÂ help
>>> +ÂÂÂÂÂ When CONFIG_HARDENED_USERCOPY is enabled, disable its
>>> +ÂÂÂÂÂ functionality unless it is enabled via at boot time
>>> +ÂÂÂÂÂ via the "enable_hardened_usercopy" boot parameter. This allows
>>> +ÂÂÂÂÂ the functionality of hardened usercopy to be present but not
>>> +ÂÂÂÂÂ impact performance unless it is needed.
>>> +
>>> Â config FORTIFY_SOURCE
>>> ÂÂÂÂÂ bool "Harden common str/mem functions against buffer overflows"
>>> ÂÂÂÂÂ depends on ARCH_HAS_FORTIFY_SOURCE
>>
>>
>
> This seems a bit backwards, I'd much rather see hardened user copy
> default to on with the basic config option and then just have a command
> line option to turn it off.
>
> Thanks,
> Laura

I have a small set of customers that want CONFIG_HARDENED_USERCOPY
enabled, and a large number of customers who would be impacted by its
default behavior (before my change). The desire was to have the smaller
number of users need to change their boot lines to get the behavior they
wanted. Adding CONFIG_HUC_DEFAULT_OFF was an attempt to preserve the
default behavior of existing users of CONFIG_HARDENED_USERCOPY (default
enabled) and allowing that to coexist with the desires of the greater
number of my customers (default disabled).

If folks think that it's better to have it enabled by default and the
command line option to turn it off I can do that (it is simpler). Does
anyone else have opinions one way or the other?

Thanks,

Chris