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