| From: Arnd Bergmann <arnd@arndb.de> |
| Date: Tue, 7 Jan 2020 21:15:49 +0100 |
| Subject: scsi: fnic: fix invalid stack access |
| |
| commit 42ec15ceaea74b5f7a621fc6686cbf69ca66c4cf upstream. |
| |
| gcc -O3 warns that some local variables are not properly initialized: |
| |
| drivers/scsi/fnic/vnic_dev.c: In function 'fnic_dev_hang_notify': |
| drivers/scsi/fnic/vnic_dev.c:511:16: error: 'a0' is used uninitialized in this function [-Werror=uninitialized] |
| vdev->args[0] = *a0; |
| ~~~~~~~~~~~~~~^~~~~ |
| drivers/scsi/fnic/vnic_dev.c:691:6: note: 'a0' was declared here |
| u64 a0, a1; |
| ^~ |
| drivers/scsi/fnic/vnic_dev.c:512:16: error: 'a1' is used uninitialized in this function [-Werror=uninitialized] |
| vdev->args[1] = *a1; |
| ~~~~~~~~~~~~~~^~~~~ |
| drivers/scsi/fnic/vnic_dev.c:691:10: note: 'a1' was declared here |
| u64 a0, a1; |
| ^~ |
| drivers/scsi/fnic/vnic_dev.c: In function 'fnic_dev_mac_addr': |
| drivers/scsi/fnic/vnic_dev.c:512:16: error: 'a1' is used uninitialized in this function [-Werror=uninitialized] |
| vdev->args[1] = *a1; |
| ~~~~~~~~~~~~~~^~~~~ |
| drivers/scsi/fnic/vnic_dev.c:698:10: note: 'a1' was declared here |
| u64 a0, a1; |
| ^~ |
| |
| Apparently the code relies on the local variables occupying adjacent memory |
| locations in the same order, but this is of course not guaranteed. |
| |
| Use an array of two u64 variables where needed to make it work correctly. |
| |
| I suspect there is also an endianness bug here, but have not digged in deep |
| enough to be sure. |
| |
| Fixes: 5df6d737dd4b ("[SCSI] fnic: Add new Cisco PCI-Express FCoE HBA") |
| Fixes: mmtom ("init/Kconfig: enable -O3 for all arches") |
| Link: https://lore.kernel.org/r/20200107201602.4096790-1-arnd@arndb.de |
| Signed-off-by: Arnd Bergmann <arnd@arndb.de> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/scsi/fnic/vnic_dev.c | 20 ++++++++++---------- |
| 1 file changed, 10 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/scsi/fnic/vnic_dev.c |
| +++ b/drivers/scsi/fnic/vnic_dev.c |
| @@ -445,26 +445,26 @@ int vnic_dev_soft_reset_done(struct vnic |
| |
| int vnic_dev_hang_notify(struct vnic_dev *vdev) |
| { |
| - u64 a0, a1; |
| + u64 a0 = 0, a1 = 0; |
| int wait = 1000; |
| return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait); |
| } |
| |
| int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) |
| { |
| - u64 a0, a1; |
| + u64 a[2] = {}; |
| int wait = 1000; |
| int err, i; |
| |
| for (i = 0; i < ETH_ALEN; i++) |
| mac_addr[i] = 0; |
| |
| - err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); |
| + err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a[0], &a[1], wait); |
| if (err) |
| return err; |
| |
| for (i = 0; i < ETH_ALEN; i++) |
| - mac_addr[i] = ((u8 *)&a0)[i]; |
| + mac_addr[i] = ((u8 *)&a)[i]; |
| |
| return 0; |
| } |
| @@ -489,15 +489,15 @@ void vnic_dev_packet_filter(struct vnic_ |
| |
| void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) |
| { |
| - u64 a0 = 0, a1 = 0; |
| + u64 a[2] = {}; |
| int wait = 1000; |
| int err; |
| int i; |
| |
| for (i = 0; i < ETH_ALEN; i++) |
| - ((u8 *)&a0)[i] = addr[i]; |
| + ((u8 *)&a)[i] = addr[i]; |
| |
| - err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); |
| + err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a[0], &a[1], wait); |
| if (err) |
| printk(KERN_ERR |
| "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", |
| @@ -507,15 +507,15 @@ void vnic_dev_add_addr(struct vnic_dev * |
| |
| void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) |
| { |
| - u64 a0 = 0, a1 = 0; |
| + u64 a[2] = {}; |
| int wait = 1000; |
| int err; |
| int i; |
| |
| for (i = 0; i < ETH_ALEN; i++) |
| - ((u8 *)&a0)[i] = addr[i]; |
| + ((u8 *)&a)[i] = addr[i]; |
| |
| - err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); |
| + err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a[0], &a[1], wait); |
| if (err) |
| printk(KERN_ERR |
| "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", |