lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200129002222.213154-1-shakeelb@google.com>
Date:   Tue, 28 Jan 2020 16:22:22 -0800
From:   Shakeel Butt <shakeelb@...gle.com>
To:     Reinette Chatre <reinette.chatre@...el.com>,
        Fenghua Yu <fenghua.yu@...el.com>
Cc:     Thomas Gleixner <tglx@...utronix.de>,
        Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
        "H . Peter Anvin" <hpa@...or.com>,
        Stephane Eranian <eranian@...gle.com>, x86@...nel.org,
        linux-kernel@...r.kernel.org, Shakeel Butt <shakeelb@...gle.com>
Subject: [PATCH] x86/resctrl: fix redundant task movement

Currently a task can be moved to a rdtgroup multiple times or between
resource or monitoring groups. This can cause multiple task works are
added, waste memory and degrade performance.

To fix the issue, only move the task to a rdtgroup when the task
is not in the rdgroup. Don't try to move the task to the rdtgroup
again when the task is already in the rdtgroup.

Also move the setting of tsk->closid and tsk->rmid before task_work_add
to remove a potential race where the task start executing the registered
callback before the request set its closid and rmid.

Signed-off-by: Shakeel Butt <shakeelb@...gle.com>
Signed-off-by: Fenghua Yu <fenghua.yu@...el.com>
---
 arch/x86/kernel/cpu/resctrl/rdtgroup.c | 61 ++++++++++++++++++--------
 1 file changed, 43 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
index dac7209a0708..8ef10c626862 100644
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -543,15 +543,57 @@ static void move_myself(struct callback_head *head)
 static int __rdtgroup_move_task(struct task_struct *tsk,
 				struct rdtgroup *rdtgrp)
 {
+	struct callback_head *head;
 	struct task_move_callback *callback;
 	int ret;
 
-	callback = kzalloc(sizeof(*callback), GFP_KERNEL);
+	/* If the task is already in rdtgrp, don't move the task. */
+	if ((rdtgrp->type == RDTCTRL_GROUP && tsk->closid == rdtgrp->closid &&
+	     tsk->rmid == rdtgrp->mon.rmid) ||
+	    (rdtgrp->type == RDTMON_GROUP &&
+	     rdtgrp->mon.parent->closid == tsk->closid &&
+	     tsk->rmid == rdtgrp->mon.rmid)) {
+		rdt_last_cmd_puts("Task is already in the rdgroup\n");
+		return 0;
+	}
+
+	/*
+	 * For monitor groups, we can move the tasks only from their parent
+	 * CTRL group.
+	 */
+	if (rdtgrp->type == RDTMON_GROUP &&
+	    rdtgrp->mon.parent->closid != tsk->closid) {
+		rdt_last_cmd_puts("Can't move task to different control group\n");
+		return -EINVAL;
+	}
+
+	/* Cancel exiting request and reuse the memory. */
+	head = task_work_cancel(tsk, move_myself);
+	if (head) {
+		callback = container_of(head, struct task_move_callback, work);
+		if (atomic_dec_and_test(&callback->rdtgrp->waitcount) &&
+		    (callback->rdtgrp->flags & RDT_DELETED))
+			kfree(callback->rdtgrp);
+	} else
+		callback = kzalloc(sizeof(*callback), GFP_KERNEL);
+
 	if (!callback)
 		return -ENOMEM;
 	callback->work.func = move_myself;
 	callback->rdtgrp = rdtgrp;
 
+	/*
+	 * For ctrl_mon groups move both closid and rmid.
+	 * For monitor groups, move the tasks only from their parent
+	 * CTRL group.
+	 */
+	if (rdtgrp->type == RDTCTRL_GROUP) {
+		tsk->closid = rdtgrp->closid;
+		tsk->rmid = rdtgrp->mon.rmid;
+	} else if (rdtgrp->type == RDTMON_GROUP &&
+		   rdtgrp->mon.parent->closid == tsk->closid) {
+		tsk->rmid = rdtgrp->mon.rmid;
+	}
 	/*
 	 * Take a refcount, so rdtgrp cannot be freed before the
 	 * callback has been invoked.
@@ -567,23 +609,6 @@ static int __rdtgroup_move_task(struct task_struct *tsk,
 		atomic_dec(&rdtgrp->waitcount);
 		kfree(callback);
 		rdt_last_cmd_puts("Task exited\n");
-	} else {
-		/*
-		 * For ctrl_mon groups move both closid and rmid.
-		 * For monitor groups, can move the tasks only from
-		 * their parent CTRL group.
-		 */
-		if (rdtgrp->type == RDTCTRL_GROUP) {
-			tsk->closid = rdtgrp->closid;
-			tsk->rmid = rdtgrp->mon.rmid;
-		} else if (rdtgrp->type == RDTMON_GROUP) {
-			if (rdtgrp->mon.parent->closid == tsk->closid) {
-				tsk->rmid = rdtgrp->mon.rmid;
-			} else {
-				rdt_last_cmd_puts("Can't move task to different control group\n");
-				ret = -EINVAL;
-			}
-		}
 	}
 	return ret;
 }
-- 
2.25.0.341.g760bfbb309-goog

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ