Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca165875 authored by Jim Blackler's avatar Jim Blackler Committed by Srinivasarao P
Browse files

ANDROID: Avoid taking multiple locks in handle_lmk_event



Conflicting lock events have been reported resulting from
rcu_read_lock, mmap_sem (in get_cmdline) and  lmk_event_lock.

This CL avoids the possibility of these conditions by moving
handle_lmk_event outside rcu_read_lock and invoking get_cmdline before
lmk_event_lock is taken.

Bug: 133479338, 133829075
Signed-off-by: default avatarJim Blackler <jimblackler@google.com>
Change-Id: I1c060dbd6200940d3b624ec275f31eedb5e2086d
Git-commit: c93a1fab248c46487da803590a0f1cec135cd96a
Git-repo: https://android.googlesource.com/kernel/common/


[spathi@codeaurora.org: resolved trivial merge conflicts]
Signed-off-by: default avatarSrinivasarao P <spathi@codeaurora.org>
parent 972f7208
Loading
Loading
Loading
Loading
+16 −12
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ void handle_lmk_event(struct task_struct *selected, short min_score_adj)
	struct lmk_event *event;
	int res;
	long rss_in_pages = -1;
	char taskname[MAX_TASKNAME];
	struct mm_struct *mm = get_task_mm(selected);

	if (mm) {
@@ -134,6 +135,17 @@ void handle_lmk_event(struct task_struct *selected, short min_score_adj)
		mmput(mm);
	}

	res = get_cmdline(selected, taskname, MAX_TASKNAME - 1);

	/* No valid process name means this is definitely not associated with a
	 * userspace activity.
	 */

	if (res <= 0 || res >= MAX_TASKNAME)
		return;

	taskname[res] = '\0';

	spin_lock(&lmk_event_lock);

	head = event_buffer.head;
@@ -148,18 +160,8 @@ void handle_lmk_event(struct task_struct *selected, short min_score_adj)
	events = (struct lmk_event *) event_buffer.buf;
	event = &events[head];

	res = get_cmdline(selected, event->taskname, MAX_TASKNAME - 1);

	/* No valid process name means this is definitely not associated with a
	 * userspace activity.
	 */

	if (res <= 0 || res >= MAX_TASKNAME) {
		spin_unlock(&lmk_event_lock);
		return;
	}
	memcpy(event->taskname, taskname, res + 1);

	event->taskname[res] = '\0';
	event->pid = selected->pid;
	event->uid = from_kuid_munged(current_user_ns(), task_uid(selected));
	if (selected->group_leader)
@@ -786,7 +788,6 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
		lowmem_deathpending_timeout = jiffies + HZ;
		rem += selected_tasksize;
		rcu_read_unlock();
		handle_lmk_event(selected, min_score_adj);
		/* give the system time to free up the memory */
		msleep_interruptible(20);
		trace_almk_shrink(selected_tasksize, ret,
@@ -801,6 +802,9 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
		     sc->nr_to_scan, sc->gfp_mask, rem);
	mutex_unlock(&scan_mutex);

	if (selected)
		handle_lmk_event(selected, min_score_adj);

	return rem;
}