Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/ap: use generic driver_override infrastructure

When the AP masks are updated via apmask_store() or aqmask_store(),
ap_bus_revise_bindings() is called after ap_attr_mutex has been
released.

This calls __ap_revise_reserved(), which accesses the driver_override
field without holding any lock, racing against a concurrent
driver_override_store() that may free the old string, resulting in a
potential UAF.

Fix this by using the driver-core driver_override infrastructure, which
protects all accesses with an internal spinlock.

Note that unlike most other buses, the AP bus does not check
driver_override in its match() callback; the override is checked in
ap_device_probe() and __ap_revise_reserved() instead.

Also note that we do not enable the driver_override feature of struct
bus_type, as AP - in contrast to most other buses - passes "" to
sysfs_emit() when the driver_override pointer is NULL. Thus, printing
"\n" instead of "(null)\n".

Additionally, AP has a custom counter that is modified in the
corresponding custom driver_override_store().

Fixes: d38a87d7c064 ("s390/ap: Support driver_override for AP queue devices")
Tested-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Link: https://patch.msgid.link/20260324005919.2408620-11-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

+23 -36
+17 -17
drivers/s390/crypto/ap_bus.c
··· 859 859 860 860 static int __ap_revise_reserved(struct device *dev, void *dummy) 861 861 { 862 - int rc, card, queue, devres, drvres; 862 + int rc, card, queue, devres, drvres, ovrd; 863 863 864 864 if (is_queue_dev(dev)) { 865 865 struct ap_driver *ap_drv = to_ap_drv(dev->driver); 866 866 struct ap_queue *aq = to_ap_queue(dev); 867 - struct ap_device *ap_dev = &aq->ap_dev; 868 867 869 868 card = AP_QID_CARD(aq->qid); 870 869 queue = AP_QID_QUEUE(aq->qid); 871 870 872 - if (ap_dev->driver_override) { 873 - if (strcmp(ap_dev->driver_override, 874 - ap_drv->driver.name)) { 875 - pr_debug("reprobing queue=%02x.%04x\n", card, queue); 876 - rc = device_reprobe(dev); 877 - if (rc) { 878 - AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n", 879 - __func__, card, queue); 880 - } 871 + ovrd = device_match_driver_override(dev, &ap_drv->driver); 872 + if (ovrd > 0) { 873 + /* override set and matches, nothing to do */ 874 + } else if (ovrd == 0) { 875 + pr_debug("reprobing queue=%02x.%04x\n", card, queue); 876 + rc = device_reprobe(dev); 877 + if (rc) { 878 + AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n", 879 + __func__, card, queue); 881 880 } 882 881 } else { 883 882 mutex_lock(&ap_attr_mutex); ··· 927 928 if (aq) { 928 929 const struct device_driver *drv = aq->ap_dev.device.driver; 929 930 const struct ap_driver *ap_drv = to_ap_drv(drv); 930 - bool override = !!aq->ap_dev.driver_override; 931 + bool override = device_has_driver_override(&aq->ap_dev.device); 931 932 932 933 if (override && drv && ap_drv->flags & AP_DRIVER_FLAG_DEFAULT) 933 934 rc = 1; ··· 976 977 { 977 978 struct ap_device *ap_dev = to_ap_dev(dev); 978 979 struct ap_driver *ap_drv = to_ap_drv(dev->driver); 979 - int card, queue, devres, drvres, rc = -ENODEV; 980 + int card, queue, devres, drvres, rc = -ENODEV, ovrd; 980 981 981 982 if (!get_device(dev)) 982 983 return rc; ··· 990 991 */ 991 992 card = AP_QID_CARD(to_ap_queue(dev)->qid); 992 993 queue = AP_QID_QUEUE(to_ap_queue(dev)->qid); 993 - if (ap_dev->driver_override) { 994 - if (strcmp(ap_dev->driver_override, 995 - ap_drv->driver.name)) 996 - goto out; 994 + ovrd = device_match_driver_override(dev, &ap_drv->driver); 995 + if (ovrd > 0) { 996 + /* override set and matches, nothing to do */ 997 + } else if (ovrd == 0) { 998 + goto out; 997 999 } else { 998 1000 mutex_lock(&ap_attr_mutex); 999 1001 devres = test_bit_inv(card, ap_perms.apm) &&
-1
drivers/s390/crypto/ap_bus.h
··· 166 166 struct ap_device { 167 167 struct device device; 168 168 int device_type; /* AP device type. */ 169 - const char *driver_override; 170 169 }; 171 170 172 171 #define to_ap_dev(x) container_of((x), struct ap_device, device)
+6 -18
drivers/s390/crypto/ap_queue.c
··· 734 734 struct device_attribute *attr, 735 735 char *buf) 736 736 { 737 - struct ap_queue *aq = to_ap_queue(dev); 738 - struct ap_device *ap_dev = &aq->ap_dev; 739 - int rc; 740 - 741 - device_lock(dev); 742 - if (ap_dev->driver_override) 743 - rc = sysfs_emit(buf, "%s\n", ap_dev->driver_override); 744 - else 745 - rc = sysfs_emit(buf, "\n"); 746 - device_unlock(dev); 747 - 748 - return rc; 737 + guard(spinlock)(&dev->driver_override.lock); 738 + return sysfs_emit(buf, "%s\n", dev->driver_override.name ?: ""); 749 739 } 750 740 751 741 static ssize_t driver_override_store(struct device *dev, 752 742 struct device_attribute *attr, 753 743 const char *buf, size_t count) 754 744 { 755 - struct ap_queue *aq = to_ap_queue(dev); 756 - struct ap_device *ap_dev = &aq->ap_dev; 757 745 int rc = -EINVAL; 758 746 bool old_value; 759 747 ··· 752 764 if (ap_apmask_aqmask_in_use) 753 765 goto out; 754 766 755 - old_value = ap_dev->driver_override ? true : false; 756 - rc = driver_set_override(dev, &ap_dev->driver_override, buf, count); 767 + old_value = device_has_driver_override(dev); 768 + rc = __device_set_driver_override(dev, buf, count); 757 769 if (rc) 758 770 goto out; 759 - if (old_value && !ap_dev->driver_override) 771 + if (old_value && !device_has_driver_override(dev)) 760 772 --ap_driver_override_ctr; 761 - else if (!old_value && ap_dev->driver_override) 773 + else if (!old_value && device_has_driver_override(dev)) 762 774 ++ap_driver_override_ctr; 763 775 764 776 rc = count;