-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathinfoleaks.c
135 lines (119 loc) · 2.61 KB
/
infoleaks.c
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
// SPDX-License-Identifier: GPL-2.0-only
/*
* Various infoleaks (CWE-200).
*
* (C) 2021 David Malcolm, Red Hat
* Written by David Malcolm <[email protected]>
*/
#include <linux/uaccess.h>
#include <linux/slab.h>
#include "antipatterns.h"
struct infoleak_buf
{
char buf[256];
};
int infoleak_stack_no_init(void __user *dst)
{
struct infoleak_buf st;
/* No initialization of "st" at all. */
if (copy_to_user(dst, &st, sizeof(st)))
return -EFAULT;
return 0;
}
int infoleak_heap_no_init(void __user *dst)
{
struct infoleak_buf *heapbuf = kmalloc(sizeof(*heapbuf), GFP_KERNEL);
/* No initialization of "heapbuf" at all. */
if (copy_to_user(dst, heapbuf, sizeof(*heapbuf)))
return -EFAULT; /* Also a leak. */
kfree(heapbuf);
return 0;
}
struct infoleak_2
{
u32 a;
u32 b;
};
int infoleak_stack_missing_a_field(void __user *dst, u32 v)
{
struct infoleak_2 st;
st.a = v;
/* No initialization of "st.b". */
if (copy_to_user(dst, &st, sizeof(st)))
return -EFAULT;
return 0;
}
int infoleak_heap_missing_a_field(void __user *dst, u32 v)
{
struct infoleak_2 *heapbuf = kmalloc(sizeof(*heapbuf), GFP_KERNEL);
heapbuf->a = v;
/* No initialization of "heapbuf->b". */
if (copy_to_user(dst, heapbuf, sizeof(*heapbuf)))
{
kfree(heapbuf);
return -EFAULT;
}
kfree(heapbuf);
return 0;
}
struct infoleak_3
{
u8 a;
/* padding here */
u32 b;
};
int infoleak_stack_padding(void __user *dst, u8 p, u32 q)
{
struct infoleak_3 st;
st.a = p;
st.b = q;
/* No initialization of padding. */
if (copy_to_user(dst, &st, sizeof(st)))
return -EFAULT;
return 0;
}
int infoleak_stack_unchecked_err(void __user *dst, void __user *src)
{
struct infoleak_buf st;
/*
* If the copy_from_user call fails, then st is still uninitialized,
* and if the copy_to_user call succeds, we have an infoleak.
*/
int err = copy_from_user (&st, src, sizeof(st));
err |= copy_to_user (dst, &st, sizeof(st));
if (err)
return -EFAULT;
return 0;
}
struct infoleak_4
{
union {
u8 f1;
u32 f2;
} u;
};
int infoleak_stack_union(void __user *dst, u8 v)
{
struct infoleak_4 st;
/*
* This write only initializes the u8 within the union "u",
* leaving the remaining 3 bytes uninitialized.
*/
st.u.f1 = v;
if (copy_to_user(dst, &st, sizeof(st)))
return -EFAULT;
return 0;
}
struct infoleak_5
{
void *ptr;
};
int infoleak_stack_kernel_ptr(void __user *dst, void *kp)
{
struct infoleak_5 st;
/* This writes a kernel-space pointer into a user space buffer. */
st.ptr = kp;
if (copy_to_user(dst, &st, sizeof(st)))
return -EFAULT;
return 0;
}