[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <87r1m6dow5.fsf@nanos.tec.linutronix.de>
Date: Wed, 27 Jan 2021 22:57:14 +0100
From: Thomas Gleixner <tglx@...utronix.de>
To: Fenghua Yu <fenghua.yu@...el.com>, Borislav Petkov <bp@...en8.de>,
Ingo Molnar <mingo@...hat.com>,
Peter Zijlstra <peterz@...radead.org>,
Tony Luck <tony.luck@...el.com>,
Randy Dunlap <rdunlap@...radead.org>,
Xiaoyao Li <xiaoyao.li@...el.com>,
Ravi V Shankar <ravi.v.shankar@...el.com>
Cc: linux-kernel <linux-kernel@...r.kernel.org>, x86 <x86@...nel.org>,
Fenghua Yu <fenghua.yu@...el.com>
Subject: Re: [PATCH v4 3/4] x86/bus_lock: Set rate limit for bus lock
On Tue, Nov 24 2020 at 20:52, Fenghua Yu wrote:
> To enforce user application throttling or mitigations, extend the
> existing split lock detect kernel parameter:
> split_lock_detect=ratelimit:N
>
> It limits bus lock rate to N per second for non-root users.
Yet another changelog which describes what it does without giving some
clue why. It also lacks the information that the ratelimiting is per UID
and not per task and why this was chosen to be per UID...
> Signed-off-by: Fenghua Yu <fenghua.yu@...el.com>
> Reviewed-by: Tony Luck <tony.luck@...el.com>
> ---
> arch/x86/kernel/cpu/intel.c | 35 ++++++++++++++++++++++++++++++-----
> include/linux/sched/user.h | 4 +++-
> kernel/user.c | 7 +++++++
> 3 files changed, 40 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
> index 77c3e33f41c7..5eb5822a446d 100644
> --- a/arch/x86/kernel/cpu/intel.c
> +++ b/arch/x86/kernel/cpu/intel.c
> @@ -10,6 +10,9 @@
> #include <linux/thread_info.h>
> #include <linux/init.h>
> #include <linux/uaccess.h>
> +#include <linux/cred.h>
> +#include <linux/delay.h>
> +#include <linux/sched/user.h>
>
> #include <asm/cpufeature.h>
> #include <asm/msr.h>
> @@ -40,6 +43,7 @@ enum split_lock_detect_state {
> sld_off = 0,
> sld_warn,
> sld_fatal,
> + sld_ratelimit,
> };
>
> /*
> @@ -998,13 +1002,25 @@ static const struct {
> { "off", sld_off },
> { "warn", sld_warn },
> { "fatal", sld_fatal },
> + { "ratelimit:", sld_ratelimit },
> };
>
> static inline bool match_option(const char *arg, int arglen, const char *opt)
> {
> - int len = strlen(opt);
>
> - return len == arglen && !strncmp(arg, opt, len);
> + int len = strlen(opt), ratelimit;
> +
> + if (strncmp(arg, opt, len))
> + return false;
> +
> + if (sscanf(arg, "ratelimit:%d", &ratelimit) == 1 && ratelimit > 0 &&
> + ratelimit_bl <= HZ / 2) {
That last part condition of the condition is always true because
ratelimit_bl is a global variable in the BSS and nothing else than the
below writes to it. So INT_MAX is a valid argument ....
> + ratelimit_bl = ratelimit;
Can you please use consistent name spaces? bld_XXX all over the place?
> static void split_lock_init(void)
> {
> /*
> - * If supported, #DB for bus lock will handle warn
> + * If supported, #DB for bus lock will handle warn or ratelimit
> * and #AC for split lock is disabled.
> */
> - if (bld && sld_state == sld_warn) {
> + if ((bld && sld_state == sld_warn) || sld_state == sld_ratelimit) {
...
> - if ((regs->flags & X86_EFLAGS_AC) || !sld || sld_state == sld_fatal)
> + if ((regs->flags & X86_EFLAGS_AC) || !sld || sld_state == sld_fatal ||
> + sld_state == sld_ratelimit)
These conditions are uncomprehensible by now
> return false;
> split_lock_warn(regs->ip);
> return true;
> @@ -1168,6 +1185,10 @@ void handle_bus_lock(struct pt_regs *regs)
> case sld_fatal:
> force_sig_fault(SIGBUS, BUS_ADRALN, NULL);
> break;
> + case sld_ratelimit:
> + while (!__ratelimit(&get_current_user()->ratelimit_bl))
> + msleep(1000 / ratelimit_bl);
Yikes. That's really creative abuse of the ratelimit mechanics of course
without any comment how this is supposed to work.
> diff --git a/include/linux/sched/user.h b/include/linux/sched/user.h
> index a8ec3b6093fc..79f95002a123 100644
> --- a/include/linux/sched/user.h
> +++ b/include/linux/sched/user.h
> @@ -40,8 +40,9 @@ struct user_struct {
> atomic_t nr_watches; /* The number of watches this user currently has */
> #endif
>
> - /* Miscellaneous per-user rate limit */
> + /* Miscellaneous per-user rate limits */
> struct ratelimit_state ratelimit;
> + struct ratelimit_state ratelimit_bl;
Why has every architecture to carry this if only one out of N uses it?
Thanks,
tglx
Powered by blists - more mailing lists