1 |
From 4d9570158b6260f449e317a5f9ed030c2504a615 Mon Sep 17 00:00:00 2001 |
2 |
From: Oleg Nesterov <oleg@redhat.com> |
3 |
Date: Thu, 4 Jan 2018 16:17:49 -0800 |
4 |
Subject: kernel/acct.c: fix the acct->needcheck check in check_free_space() |
5 |
|
6 |
From: Oleg Nesterov <oleg@redhat.com> |
7 |
|
8 |
commit 4d9570158b6260f449e317a5f9ed030c2504a615 upstream. |
9 |
|
10 |
As Tsukada explains, the time_is_before_jiffies(acct->needcheck) check |
11 |
is very wrong, we need time_is_after_jiffies() to make sys_acct() work. |
12 |
|
13 |
Ignoring the overflows, the code should "goto out" if needcheck > |
14 |
jiffies, while currently it checks "needcheck < jiffies" and thus in the |
15 |
likely case check_free_space() does nothing until jiffies overflow. |
16 |
|
17 |
In particular this means that sys_acct() is simply broken, acct_on() |
18 |
sets acct->needcheck = jiffies and expects that check_free_space() |
19 |
should set acct->active = 1 after the free-space check, but this won't |
20 |
happen if jiffies increments in between. |
21 |
|
22 |
This was broken by commit 32dc73086015 ("get rid of timer in |
23 |
kern/acct.c") in 2011, then another (correct) commit 795a2f22a8ea |
24 |
("acct() should honour the limits from the very beginning") made the |
25 |
problem more visible. |
26 |
|
27 |
Link: http://lkml.kernel.org/r/20171213133940.GA6554@redhat.com |
28 |
Fixes: 32dc73086015 ("get rid of timer in kern/acct.c") |
29 |
Reported-by: TSUKADA Koutaro <tsukada@ascade.co.jp> |
30 |
Suggested-by: TSUKADA Koutaro <tsukada@ascade.co.jp> |
31 |
Signed-off-by: Oleg Nesterov <oleg@redhat.com> |
32 |
Cc: Al Viro <viro@zeniv.linux.org.uk> |
33 |
Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
34 |
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
35 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
36 |
|
37 |
--- |
38 |
kernel/acct.c | 2 +- |
39 |
1 file changed, 1 insertion(+), 1 deletion(-) |
40 |
|
41 |
--- a/kernel/acct.c |
42 |
+++ b/kernel/acct.c |
43 |
@@ -99,7 +99,7 @@ static int check_free_space(struct bsd_a |
44 |
{ |
45 |
struct kstatfs sbuf; |
46 |
|
47 |
- if (time_is_before_jiffies(acct->needcheck)) |
48 |
+ if (time_is_after_jiffies(acct->needcheck)) |
49 |
goto out; |
50 |
|
51 |
/* May block */ |