Michal Suchanek b25333
From 319fa1a52e438a6e028329187783a25ad498c4e6 Mon Sep 17 00:00:00 2001
Michal Suchanek b25333
From: Nathan Lynch <nathanl@linux.ibm.com>
Michal Suchanek b25333
Date: Wed, 20 Oct 2021 14:47:03 -0500
Michal Suchanek b25333
Subject: [PATCH] powerpc/pseries/mobility: ignore ibm, platform-facilities
Michal Suchanek b25333
 updates
Michal Suchanek b25333
MIME-Version: 1.0
Michal Suchanek b25333
Content-Type: text/plain; charset=UTF-8
Michal Suchanek b25333
Content-Transfer-Encoding: 8bit
Michal Suchanek b25333
Michal Suchanek b25333
References: bsc#1065729
Michal Suchanek b25333
Patch-mainline: v5.16-rc1
Michal Suchanek b25333
Git-commit: 319fa1a52e438a6e028329187783a25ad498c4e6
Michal Suchanek b25333
Michal Suchanek b25333
On VMs with NX encryption, compression, and/or RNG offload, these
Michal Suchanek b25333
capabilities are described by nodes in the ibm,platform-facilities device
Michal Suchanek b25333
tree hierarchy:
Michal Suchanek b25333
Michal Suchanek b25333
  $ tree -d /sys/firmware/devicetree/base/ibm,platform-facilities/
Michal Suchanek b25333
  /sys/firmware/devicetree/base/ibm,platform-facilities/
Michal Suchanek b25333
  ├── ibm,compression-v1
Michal Suchanek b25333
  ├── ibm,random-v1
Michal Suchanek b25333
  └── ibm,sym-encryption-v1
Michal Suchanek b25333
Michal Suchanek b25333
  3 directories
Michal Suchanek b25333
Michal Suchanek b25333
The acceleration functions that these nodes describe are not disrupted by
Michal Suchanek b25333
live migration, not even temporarily.
Michal Suchanek b25333
Michal Suchanek b25333
But the post-migration ibm,update-nodes sequence firmware always sends
Michal Suchanek b25333
"delete" messages for this hierarchy, followed by an "add" directive to
Michal Suchanek b25333
reconstruct it via ibm,configure-connector (log with debugging statements
Michal Suchanek b25333
enabled in mobility.c):
Michal Suchanek b25333
Michal Suchanek b25333
  mobility: removing node /ibm,platform-facilities/ibm,random-v1:4294967285
Michal Suchanek b25333
  mobility: removing node /ibm,platform-facilities/ibm,compression-v1:4294967284
Michal Suchanek b25333
  mobility: removing node /ibm,platform-facilities/ibm,sym-encryption-v1:4294967283
Michal Suchanek b25333
  mobility: removing node /ibm,platform-facilities:4294967286
Michal Suchanek b25333
  ...
Michal Suchanek b25333
  mobility: added node /ibm,platform-facilities:4294967286
Michal Suchanek b25333
Michal Suchanek b25333
Note we receive a single "add" message for the entire hierarchy, and what
Michal Suchanek b25333
we receive from the ibm,configure-connector sequence is the top-level
Michal Suchanek b25333
platform-facilities node along with its three children. The debug message
Michal Suchanek b25333
simply reports the parent node and not the whole subtree.
Michal Suchanek b25333
Michal Suchanek b25333
Also, significantly, the nodes added are almost completely equivalent to
Michal Suchanek b25333
the ones removed; even phandles are unchanged. ibm,shared-interrupt-pool in
Michal Suchanek b25333
the leaf nodes is the only property I've observed to differ, and Linux does
Michal Suchanek b25333
not use that. So in practice, the sum of update messages Linux receives for
Michal Suchanek b25333
this hierarchy is equivalent to minor property updates.
Michal Suchanek b25333
Michal Suchanek b25333
We succeed in removing the original hierarchy from the device tree. But the
Michal Suchanek b25333
vio bus code is ignorant of this, and does not unbind or relinquish its
Michal Suchanek b25333
references. The leaf nodes, still reachable through sysfs, of course still
Michal Suchanek b25333
refer to the now-freed ibm,platform-facilities parent node, which makes
Michal Suchanek b25333
use-after-free possible:
Michal Suchanek b25333
Michal Suchanek b25333
  refcount_t: addition on 0; use-after-free.
Michal Suchanek b25333
  WARNING: CPU: 3 PID: 1706 at lib/refcount.c:25 refcount_warn_saturate+0x164/0x1f0
Michal Suchanek b25333
  refcount_warn_saturate+0x160/0x1f0 (unreliable)
Michal Suchanek b25333
  kobject_get+0xf0/0x100
Michal Suchanek b25333
  of_node_get+0x30/0x50
Michal Suchanek b25333
  of_get_parent+0x50/0xb0
Michal Suchanek b25333
  of_fwnode_get_parent+0x54/0x90
Michal Suchanek b25333
  fwnode_count_parents+0x50/0x150
Michal Suchanek b25333
  fwnode_full_name_string+0x30/0x110
Michal Suchanek b25333
  device_node_string+0x49c/0x790
Michal Suchanek b25333
  vsnprintf+0x1c0/0x4c0
Michal Suchanek b25333
  sprintf+0x44/0x60
Michal Suchanek b25333
  devspec_show+0x34/0x50
Michal Suchanek b25333
  dev_attr_show+0x40/0xa0
Michal Suchanek b25333
  sysfs_kf_seq_show+0xbc/0x200
Michal Suchanek b25333
  kernfs_seq_show+0x44/0x60
Michal Suchanek b25333
  seq_read_iter+0x2a4/0x740
Michal Suchanek b25333
  kernfs_fop_read_iter+0x254/0x2e0
Michal Suchanek b25333
  new_sync_read+0x120/0x190
Michal Suchanek b25333
  vfs_read+0x1d0/0x240
Michal Suchanek b25333
Michal Suchanek b25333
Moreover, the "new" replacement subtree is not correctly added to the
Michal Suchanek b25333
device tree, resulting in ibm,platform-facilities parent node without the
Michal Suchanek b25333
appropriate leaf nodes, and broken symlinks in the sysfs device hierarchy:
Michal Suchanek b25333
Michal Suchanek b25333
  $ tree -d /sys/firmware/devicetree/base/ibm,platform-facilities/
Michal Suchanek b25333
  /sys/firmware/devicetree/base/ibm,platform-facilities/
Michal Suchanek b25333
Michal Suchanek b25333
  0 directories
Michal Suchanek b25333
Michal Suchanek b25333
  $ cd /sys/devices/vio ; find . -xtype l -exec file {} +
Michal Suchanek b25333
  ./ibm,sym-encryption-v1/of_node: broken symbolic link to
Michal Suchanek b25333
    ../../../firmware/devicetree/base/ibm,platform-facilities/ibm,sym-encryption-v1
Michal Suchanek b25333
  ./ibm,random-v1/of_node:         broken symbolic link to
Michal Suchanek b25333
    ../../../firmware/devicetree/base/ibm,platform-facilities/ibm,random-v1
Michal Suchanek b25333
  ./ibm,compression-v1/of_node:    broken symbolic link to
Michal Suchanek b25333
    ../../../firmware/devicetree/base/ibm,platform-facilities/ibm,compression-v1
Michal Suchanek b25333
Michal Suchanek b25333
This is because add_dt_node() -> dlpar_attach_node() attaches only the
Michal Suchanek b25333
parent node returned from configure-connector, ignoring any children. This
Michal Suchanek b25333
should be corrected for the general case, but fixing that won't help with
Michal Suchanek b25333
the stale OF node references, which is the more urgent problem.
Michal Suchanek b25333
Michal Suchanek b25333
One way to address that would be to make the drivers respond to node
Michal Suchanek b25333
removal notifications, so that node references can be dropped
Michal Suchanek b25333
appropriately. But this would likely force the drivers to disrupt active
Michal Suchanek b25333
clients for no useful purpose: equivalent nodes are immediately re-added.
Michal Suchanek b25333
And recall that the acceleration capabilities described by the nodes remain
Michal Suchanek b25333
available throughout the whole process.
Michal Suchanek b25333
Michal Suchanek b25333
The solution I believe to be robust for this situation is to convert
Michal Suchanek b25333
remove+add of a node with an unchanged phandle to an update of the node's
Michal Suchanek b25333
properties in the Linux device tree structure. That would involve changing
Michal Suchanek b25333
and adding a fair amount of code, and may take several iterations to land.
Michal Suchanek b25333
Michal Suchanek b25333
Until that can be realized we have a confirmed use-after-free and the
Michal Suchanek b25333
possibility of memory corruption. So add a limited workaround that
Michal Suchanek b25333
discriminates on the node type, ignoring adds and removes. This should be
Michal Suchanek b25333
amenable to backporting in the meantime.
Michal Suchanek b25333
Michal Suchanek b25333
Fixes: 410bccf97881 ("powerpc/pseries: Partition migration in the kernel")
Michal Suchanek b25333
Cc: stable@vger.kernel.org
Michal Suchanek b25333
Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Michal Suchanek b25333
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek b25333
Link: https://lore.kernel.org/r/20211020194703.2613093-1-nathanl@linux.ibm.com
Michal Suchanek b25333
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek b25333
---
Michal Suchanek b25333
 arch/powerpc/platforms/pseries/mobility.c | 34 +++++++++++++++++++++++
Michal Suchanek b25333
 1 file changed, 34 insertions(+)
Michal Suchanek b25333
Michal Suchanek b25333
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
Michal Suchanek b25333
index e83e0891272d..210a37a065fb 100644
Michal Suchanek b25333
--- a/arch/powerpc/platforms/pseries/mobility.c
Michal Suchanek b25333
+++ b/arch/powerpc/platforms/pseries/mobility.c
Michal Suchanek b25333
@@ -63,6 +63,27 @@ static int mobility_rtas_call(int token, char *buf, s32 scope)
Michal Suchanek b25333
 
Michal Suchanek b25333
 static int delete_dt_node(struct device_node *dn)
Michal Suchanek b25333
 {
Michal Suchanek b25333
+	struct device_node *pdn;
Michal Suchanek b25333
+	bool is_platfac;
Michal Suchanek b25333
+
Michal Suchanek b25333
+	pdn = of_get_parent(dn);
Michal Suchanek b25333
+	is_platfac = of_node_is_type(dn, "ibm,platform-facilities") ||
Michal Suchanek b25333
+		     of_node_is_type(pdn, "ibm,platform-facilities");
Michal Suchanek b25333
+	of_node_put(pdn);
Michal Suchanek b25333
+
Michal Suchanek b25333
+	/*
Michal Suchanek b25333
+	 * The drivers that bind to nodes in the platform-facilities
Michal Suchanek b25333
+	 * hierarchy don't support node removal, and the removal directive
Michal Suchanek b25333
+	 * from firmware is always followed by an add of an equivalent
Michal Suchanek b25333
+	 * node. The capability (e.g. RNG, encryption, compression)
Michal Suchanek b25333
+	 * represented by the node is never interrupted by the migration.
Michal Suchanek b25333
+	 * So ignore changes to this part of the tree.
Michal Suchanek b25333
+	 */
Michal Suchanek b25333
+	if (is_platfac) {
Michal Suchanek b25333
+		pr_notice("ignoring remove operation for %pOFfp\n", dn);
Michal Suchanek b25333
+		return 0;
Michal Suchanek b25333
+	}
Michal Suchanek b25333
+
Michal Suchanek b25333
 	pr_debug("removing node %pOFfp\n", dn);
Michal Suchanek b25333
 	dlpar_detach_node(dn);
Michal Suchanek b25333
 	return 0;
Michal Suchanek b25333
@@ -222,6 +243,19 @@ static int add_dt_node(struct device_node *parent_dn, __be32 drc_index)
Michal Suchanek b25333
 	if (!dn)
Michal Suchanek b25333
 		return -ENOENT;
Michal Suchanek b25333
 
Michal Suchanek b25333
+	/*
Michal Suchanek b25333
+	 * Since delete_dt_node() ignores this node type, this is the
Michal Suchanek b25333
+	 * necessary counterpart. We also know that a platform-facilities
Michal Suchanek b25333
+	 * node returned from dlpar_configure_connector() has children
Michal Suchanek b25333
+	 * attached, and dlpar_attach_node() only adds the parent, leaking
Michal Suchanek b25333
+	 * the children. So ignore these on the add side for now.
Michal Suchanek b25333
+	 */
Michal Suchanek b25333
+	if (of_node_is_type(dn, "ibm,platform-facilities")) {
Michal Suchanek b25333
+		pr_notice("ignoring add operation for %pOF\n", dn);
Michal Suchanek b25333
+		dlpar_free_cc_nodes(dn);
Michal Suchanek b25333
+		return 0;
Michal Suchanek b25333
+	}
Michal Suchanek b25333
+
Michal Suchanek b25333
 	rc = dlpar_attach_node(dn, parent_dn);
Michal Suchanek b25333
 	if (rc)
Michal Suchanek b25333
 		dlpar_free_cc_nodes(dn);
Michal Suchanek b25333
-- 
Michal Suchanek b25333
2.31.1
Michal Suchanek b25333