(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
plugin/
infoleak-CVE-2017-18550-1.c
       1  /* "An issue was discovered in drivers/scsi/aacraid/commctrl.c in the 
       2     Linux kernel before 4.13. There is potential exposure of kernel stack
       3     memory because aac_get_hba_info does not initialize the hbainfo structure."
       4  
       5     Fixed e.g. by 342ffc26693b528648bdc9377e51e4f2450b4860 on linux-4.13.y
       6     in linux-stable.
       7  
       8     This is a simplified version of that code (before and after the fix). */
       9  
      10  /* { dg-do compile } */
      11  /* { dg-options "-fanalyzer" } */
      12  /* { dg-require-effective-target analyzer } */
      13  /* { dg-skip-if "structure layout assumption not met" { default_packed } } */
      14  
      15  #include <string.h>
      16  
      17  typedef unsigned int __u32;
      18  typedef unsigned int u32;
      19  typedef unsigned char u8;
      20  
      21  #include "test-uaccess.h"
      22  
      23  /* Adapted from include/uapi/linux/types.h  */
      24  
      25  #define __bitwise
      26  typedef __u32 __bitwise __le32;
      27  
      28  /* Adapted from drivers/scsi/aacraid/aacraid.h  */
      29  
      30  struct aac_hba_info {
      31  
      32  	u8	driver_name[50]; /* { dg-message "field 'driver_name' is uninitialized \\(50 bytes\\)" } */
      33  	u8	adapter_number;
      34  	u8	system_io_bus_number;
      35  	u8	device_number; /* { dg-message "padding after field 'device_number' is uninitialized \\(3 bytes\\)" } */
      36  	u32	function_number;
      37  	u32	vendor_id;
      38  	u32	device_id;
      39  	u32	sub_vendor_id;
      40  	u32	sub_system_id;
      41  	u32	mapped_base_address_size; /* { dg-message "field 'mapped_base_address_size' is uninitialized \\(4 bytes\\)"  } */
      42  	u32	base_physical_address_high_part;
      43  	u32	base_physical_address_low_part;
      44  
      45  	u32	max_command_size;
      46  	u32	max_fib_size;
      47  	u32	max_scatter_gather_from_os;
      48  	u32	max_scatter_gather_to_fw;
      49  	u32	max_outstanding_fibs;
      50  
      51  	u32	queue_start_threshold;
      52  	u32	queue_dump_threshold;
      53  	u32	max_io_size_queued;
      54  	u32	outstanding_io;
      55  
      56  	u32	firmware_build_number;
      57  	u32	bios_build_number;
      58  	u32	driver_build_number;
      59  	u32	serial_number_high_part;
      60  	u32	serial_number_low_part;
      61  	u32	supported_options;
      62  	u32	feature_bits;
      63  	u32	currentnumber_ports;
      64  
      65  	u8	new_comm_interface:1; /* { dg-message "field 'new_comm_interface' is uninitialized \\(1 bit\\)" } */
      66  	u8	new_commands_supported:1;
      67  	u8	disable_passthrough:1;
      68  	u8	expose_non_dasd:1;
      69  	u8	queue_allowed:1;
      70  	u8	bled_check_enabled:1;
      71  	u8	reserved1:1;
      72  	u8	reserted2:1;
      73  
      74  	u32	reserved3[10]; /* { dg-message "field 'reserved3' is uninitialized \\(40 bytes\\)" } */
      75  
      76  };
      77  
      78  struct aac_dev
      79  {
      80  	/* [...snip...] */
      81  	int			id;
      82  	/* [...snip...] */
      83  	struct pci_dev		*pdev;		/* Our PCI interface */
      84  	/* [...snip...] */
      85  };
      86  
      87  /* Adapted from include/linux/pci.h  */
      88  
      89  struct pci_dev {
      90  	/* [...snip...] */
      91  	struct pci_bus	*bus;		/* bus this device is on */
      92  	/* [...snip...] */
      93  	unsigned int	devfn;		/* encoded device & function index */
      94  	unsigned short	vendor;
      95  	unsigned short	device;
      96  	unsigned short	subsystem_vendor;
      97  	unsigned short	subsystem_device;
      98  	/* [...snip...] */
      99  };
     100  
     101  struct pci_bus {
     102  	/* [...snip...] */
     103  	unsigned char	number;		/* bus number */
     104  	/* [...snip...] */
     105  };
     106  
     107  /* Adapted from drivers/scsi/aacraid/commctrl.c  */
     108  
     109  static int aac_get_hba_info(struct aac_dev *dev, void __user *arg)
     110  {
     111  	struct aac_hba_info hbainfo; /* { dg-message "region created on stack here" "memspace message" } */
     112  	/* { dg-message "capacity: 200 bytes" "capacity message" { target *-*-* } .-1 } */
     113  
     114  	hbainfo.adapter_number		= (u8) dev->id;
     115  	hbainfo.system_io_bus_number	= dev->pdev->bus->number;
     116  	hbainfo.device_number		= (dev->pdev->devfn >> 3);
     117  	hbainfo.function_number		= (dev->pdev->devfn & 0x0007);
     118  
     119  	hbainfo.vendor_id		= dev->pdev->vendor;
     120  	hbainfo.device_id		= dev->pdev->device;
     121  	hbainfo.sub_vendor_id		= dev->pdev->subsystem_vendor;
     122  	hbainfo.sub_system_id		= dev->pdev->subsystem_device;
     123  
     124  	if (copy_to_user(arg, &hbainfo, sizeof(struct aac_hba_info))) { /* { dg-warning "potential exposure of sensitive information by copying uninitialized data from stack" "warning" } */
     125  		/* { dg-message "177 bytes are uninitialized" "how much" { target *-*-* } .-1 } */
     126  		/* [...snip...] */
     127  	}
     128  
     129  	return 0;
     130  }
     131  
     132  static int aac_get_hba_info_fixed(struct aac_dev *dev, void __user *arg)
     133  {
     134  	struct aac_hba_info hbainfo;
     135  
     136  	memset(&hbainfo, 0, sizeof(hbainfo));
     137  	hbainfo.adapter_number		= (u8) dev->id;
     138  	hbainfo.system_io_bus_number	= dev->pdev->bus->number;
     139  	hbainfo.device_number		= (dev->pdev->devfn >> 3);
     140  	hbainfo.function_number		= (dev->pdev->devfn & 0x0007);
     141  
     142  	hbainfo.vendor_id		= dev->pdev->vendor;
     143  	hbainfo.device_id		= dev->pdev->device;
     144  	hbainfo.sub_vendor_id		= dev->pdev->subsystem_vendor;
     145  	hbainfo.sub_system_id		= dev->pdev->subsystem_device;
     146  
     147  	if (copy_to_user(arg, &hbainfo, sizeof(struct aac_hba_info))) { /* { dg-bogus "" } */
     148  		/* [...snip...] */
     149  	}
     150  
     151  	return 0;
     152  }
     153  
     154  /* An alternate fix using "= {0}" rather than memset.  */
     155  
     156  static int aac_get_hba_info_fixed_alt(struct aac_dev *dev, void __user *arg)
     157  {
     158  	struct aac_hba_info hbainfo = {0};
     159  
     160  	memset(&hbainfo, 0, sizeof(hbainfo));
     161  	hbainfo.adapter_number		= (u8) dev->id;
     162  	hbainfo.system_io_bus_number	= dev->pdev->bus->number;
     163  	hbainfo.device_number		= (dev->pdev->devfn >> 3);
     164  	hbainfo.function_number		= (dev->pdev->devfn & 0x0007);
     165  
     166  	hbainfo.vendor_id		= dev->pdev->vendor;
     167  	hbainfo.device_id		= dev->pdev->device;
     168  	hbainfo.sub_vendor_id		= dev->pdev->subsystem_vendor;
     169  	hbainfo.sub_system_id		= dev->pdev->subsystem_device;
     170  
     171  	if (copy_to_user(arg, &hbainfo, sizeof(struct aac_hba_info))) { /* { dg-bogus "" } */
     172  		/* [...snip...] */
     173  	}
     174  
     175  	return 0;
     176  }