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."
5 Fixed e.g. by 342ffc26693b528648bdc9377e51e4f2450b4860 on linux-4.13.y
8 This is a simplified version of that code (before and after the fix). */
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 } } */
17 typedef unsigned int __u32
;
18 typedef unsigned int u32
;
19 typedef unsigned char u8
;
21 #include "test-uaccess.h"
23 /* Adapted from include/uapi/linux/types.h */
26 typedef __u32 __bitwise __le32
;
28 /* Adapted from drivers/scsi/aacraid/aacraid.h */
32 u8 driver_name
[50]; /* { dg-message "field 'driver_name' is uninitialized \\(50 bytes\\)" } */
34 u8 system_io_bus_number
;
35 u8 device_number
; /* { dg-message "padding after field 'device_number' is uninitialized \\(3 bytes\\)" } */
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
;
47 u32 max_scatter_gather_from_os
;
48 u32 max_scatter_gather_to_fw
;
49 u32 max_outstanding_fibs
;
51 u32 queue_start_threshold
;
52 u32 queue_dump_threshold
;
53 u32 max_io_size_queued
;
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
;
63 u32 currentnumber_ports
;
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;
70 u8 bled_check_enabled
:1;
74 u32 reserved3
[10]; /* { dg-message "field 'reserved3' is uninitialized \\(40 bytes\\)" } */
83 struct pci_dev
*pdev
; /* Our PCI interface */
87 /* Adapted from include/linux/pci.h */
91 struct pci_bus
*bus
; /* bus this device is on */
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
;
103 unsigned char number
; /* bus number */
107 /* Adapted from drivers/scsi/aacraid/commctrl.c */
109 static int aac_get_hba_info(struct aac_dev
*dev
, void __user
*arg
)
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 } */
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);
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
;
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 } */
132 static int aac_get_hba_info_fixed(struct aac_dev
*dev
, void __user
*arg
)
134 struct aac_hba_info hbainfo
;
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);
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
;
147 if (copy_to_user(arg
, &hbainfo
, sizeof(struct aac_hba_info
))) { /* { dg-bogus "" } */
154 /* An alternate fix using "= {0}" rather than memset. */
156 static int aac_get_hba_info_fixed_alt(struct aac_dev
*dev
, void __user
*arg
)
158 struct aac_hba_info hbainfo
= {0};
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);
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
;
171 if (copy_to_user(arg
, &hbainfo
, sizeof(struct aac_hba_info
))) { /* { dg-bogus "" } */