ANDROID: nf: IDLETIMER: Fix possible use before initialization in idletimer_resume
idletimer_resume() assumes that the PM_SUSPEND_PREPARE notifier is sent
before PM_POST_SUSPEND so that timer->last_suspend_time is initialized.
However, it is possible for PM_POST_SUSPEND to be sent first if there is an
error returned from another driver's PM_SUSPEND_PREPARE notifier. As a
result, structures are accessed without initialization.
The arguments to set_normalized_timespec are very large and unexpected.
timer->last_suspend_time has the value of
{.tv_sec = 0x6b6b6b6b6b6b6b6b, .tv_nsec=0x6b6b6b6b6b6b6b6b}. Since really
large iterations are required, this operation takes more than a minute
and causes the CPU to trigger a spinbug since the timestamp lock is held.
Call stack -
- set_normalized_timespec
- timespec_sub
- idletimer_resume
- notifier_call_chain
- __blocking_notifier_call_chain
- pm_notifier_call_chain
Add a flag indicating whether the current value of timer->last_suspend is
valid.
Detected with CONFIG_SLUB_DEBUG & CONFIG_DEBUG_SPINLOCK in arm64.
Bug: 140404598
Fixes: f0c2df2b12 ("ANDROID: netfilter: xt_IDLETIMER: Add new
netlink msg type")
Change-Id: I95328b0ac85dba819ff9cef751c3d07300c232f1
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Signed-off-by: Todd Kjos <tkjos@google.com>
This commit is contained in:
parent
8d0e6ae64f
commit
7ded435968
1 changed files with 7 additions and 1 deletions
|
|
@ -57,6 +57,7 @@ struct idletimer_tg {
|
|||
bool send_nl_msg;
|
||||
bool active;
|
||||
uid_t uid;
|
||||
bool suspend_time_valid;
|
||||
};
|
||||
|
||||
static LIST_HEAD(idletimer_tg_list);
|
||||
|
|
@ -226,8 +227,13 @@ static int idletimer_resume(struct notifier_block *notifier,
|
|||
case PM_SUSPEND_PREPARE:
|
||||
timer->last_suspend_time =
|
||||
ktime_to_timespec64(ktime_get_boottime());
|
||||
timer->suspend_time_valid = true;
|
||||
break;
|
||||
case PM_POST_SUSPEND:
|
||||
if (!timer->suspend_time_valid)
|
||||
break;
|
||||
timer->suspend_time_valid = false;
|
||||
|
||||
spin_lock_bh(×tamp_lock);
|
||||
if (!timer->active) {
|
||||
spin_unlock_bh(×tamp_lock);
|
||||
|
|
@ -278,7 +284,7 @@ static int idletimer_tg_create(struct idletimer_tg_info *info)
|
|||
{
|
||||
int ret;
|
||||
|
||||
info->timer = kmalloc(sizeof(*info->timer), GFP_KERNEL);
|
||||
info->timer = kzalloc(sizeof(*info->timer), GFP_KERNEL);
|
||||
if (!info->timer) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue