| From 92e75428ffc90e2a0321062379f883f3671cfebe Mon Sep 17 00:00:00 2001 |
| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Wed, 7 Jun 2017 19:01:32 -0400 |
| Subject: random: use lockless method of accessing and updating f->reg_idx |
| |
| From: Theodore Ts'o <tytso@mit.edu> |
| |
| commit 92e75428ffc90e2a0321062379f883f3671cfebe upstream. |
| |
| Linus pointed out that there is a much more efficient way of avoiding |
| the problem that we were trying to address in commit 9dfa7bba35ac0: |
| "fix race in drivers/char/random.c:get_reg()". |
| |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Cc: Michael Schmitz <schmitzmic@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/char/random.c | 12 ++++++------ |
| 1 file changed, 6 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/char/random.c |
| +++ b/drivers/char/random.c |
| @@ -1115,15 +1115,15 @@ static void add_interrupt_bench(cycles_t |
| static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs) |
| { |
| __u32 *ptr = (__u32 *) regs; |
| - unsigned long flags; |
| + unsigned int idx; |
| |
| if (regs == NULL) |
| return 0; |
| - local_irq_save(flags); |
| - if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32)) |
| - f->reg_idx = 0; |
| - ptr += f->reg_idx++; |
| - local_irq_restore(flags); |
| + idx = READ_ONCE(f->reg_idx); |
| + if (idx >= sizeof(struct pt_regs) / sizeof(__u32)) |
| + idx = 0; |
| + ptr += idx++; |
| + WRITE_ONCE(f->reg_idx, idx); |
| return *ptr; |
| } |
| |