summaryrefslogtreecommitdiffstats
path: root/kernel/user.c
diff options
context:
space:
mode:
authorLuck, Tony <tony.luck@intel.com>2018-02-22 09:15:06 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-22 10:21:02 -0800
commitbef3efbeb897b56867e271cdbc5f8adaacaeb9cd (patch)
treed3635a816ed945d7790b0202b3b40d6785ac7c8b /kernel/user.c
parent28128c61e08eaeced9cc8ec0e6b5d677b5b94690 (diff)
downloadlinux-bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.tar.gz
linux-bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.tar.bz2
linux-bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.zip
efivarfs: Limit the rate for non-root to read files
Each read from a file in efivarfs results in two calls to EFI (one to get the file size, another to get the actual data). On X86 these EFI calls result in broadcast system management interrupts (SMI) which affect performance of the whole system. A malicious user can loop performing reads from efivarfs bringing the system to its knees. Linus suggested per-user rate limit to solve this. So we add a ratelimit structure to "user_struct" and initialize it for the root user for no limit. When allocating user_struct for other users we set the limit to 100 per second. This could be used for other places that want to limit the rate of some detrimental user action. In efivarfs if the limit is exceeded when reading, we take an interruptible nap for 50ms and check the rate limit again. Signed-off-by: Tony Luck <tony.luck@intel.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/user.c')
-rw-r--r--kernel/user.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/kernel/user.c b/kernel/user.c
index 9a20acce460d..36288d840675 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -101,6 +101,7 @@ struct user_struct root_user = {
.sigpending = ATOMIC_INIT(0),
.locked_shm = 0,
.uid = GLOBAL_ROOT_UID,
+ .ratelimit = RATELIMIT_STATE_INIT(root_user.ratelimit, 0, 0),
};
/*
@@ -191,6 +192,8 @@ struct user_struct *alloc_uid(kuid_t uid)
new->uid = uid;
atomic_set(&new->__count, 1);
+ ratelimit_state_init(&new->ratelimit, HZ, 100);
+ ratelimit_set_flags(&new->ratelimit, RATELIMIT_MSG_ON_RELEASE);
/*
* Before adding this, check whether we raced