1 /* "The sco_sock_getsockopt_old function in net/bluetooth/sco.c in the
2 Linux kernel before 2.6.39 does not initialize a certain structure,
3 which allows local users to obtain potentially sensitive information
4 from kernel stack memory via the SCO_CONNINFO option."
6 Fixed e.g. by c4c896e1471aec3b004a693c689f60be3b17ac86 on linux-2.6.39.y
9 /* { dg-do compile } */
10 /* { dg-options "-fanalyzer" } */
11 /* { dg-require-effective-target analyzer } */
12 /* { dg-skip-if "structure layout assumption not met" { default_packed } } */
16 typedef unsigned char __u8
;
17 typedef unsigned short __u16
;
19 #include "test-uaccess.h"
21 /* Adapted from include/asm-generic/uaccess.h. */
23 #define get_user(x, ptr) \
26 __get_user_fn(sizeof (*(ptr)), ptr, &(x)); \
30 static inline int __get_user_fn(size_t size
, const void __user
*ptr
, void *x
)
32 size
= copy_from_user(x
, ptr
, size
);
33 return size
? -1 : size
;
36 /* Adapted from include/linux/kernel.h. */
38 #define min_t(type, x, y) ({ \
41 __min1 < __min2 ? __min1: __min2; })
43 /* Adapted from include/linux/net.h. */
51 /* Adapted from include/net/bluetooth/sco.h. */
55 __u8 dev_class
[3]; /* { dg-message "padding after field 'dev_class' is uninitialized \\(1 byte\\)" } */
60 struct hci_conn
*hcon
;
64 #define sco_pi(sk) ((struct sco_pinfo *) sk)
68 struct sco_conn
*conn
;
71 /* Adapted from include/net/bluetooth/hci_core.h. */
81 /* Adapted from sco_sock_getsockopt_old in net/bluetooth/sco.c. */
83 static int sco_sock_getsockopt_old_broken(struct socket
*sock
, int optname
, char __user
*optval
, int __user
*optlen
)
85 struct sock
*sk
= sock
->sk
;
87 struct sco_conninfo cinfo
; /* { dg-message "region created on stack here" "where" } */
88 /* { dg-message "capacity: 6 bytes" "capacity" { target *-*-* } .-1 } */
89 /* Note: 40 bits of fields, padded to 48. */
95 if (get_user(len
, optlen
))
100 /* case SCO_CONNINFO: */
101 cinfo
.hci_handle
= sco_pi(sk
)->conn
->hcon
->handle
;
102 memcpy(cinfo
.dev_class
, sco_pi(sk
)->conn
->hcon
->dev_class
, 3);
104 len
= min_t(unsigned int, len
, sizeof(cinfo
));
105 if (copy_to_user(optval
, (char *)&cinfo
, len
)) /* { dg-warning "potential exposure of sensitive information by copying uninitialized data from stack" "warning" { target *-*-* } } */
106 /* { dg-message "1 byte is uninitialized" "how much note" { target *-*-* } .-1 } */
112 static int sco_sock_getsockopt_fixed(struct socket
*sock
, int optname
, char __user
*optval
, int __user
*optlen
)
114 struct sock
*sk
= sock
->sk
;
116 struct sco_conninfo cinfo
;
117 /* Note: 40 bits of fields, padded to 48. */
123 if (get_user(len
, optlen
))
128 /* case SCO_CONNINFO: */
129 /* Infoleak fixed by this memset call. */
130 memset(&cinfo
, 0, sizeof(cinfo
));
131 cinfo
.hci_handle
= sco_pi(sk
)->conn
->hcon
->handle
;
132 memcpy(cinfo
.dev_class
, sco_pi(sk
)->conn
->hcon
->dev_class
, 3);
134 len
= min_t(unsigned int, len
, sizeof(cinfo
));
135 if (copy_to_user(optval
, (char *)&cinfo
, len
)) /* { dg-bogus "exposure" } */