aboutsummaryrefslogtreecommitdiffstats
path: root/package/libs/libubox/patches/0009-blobmsg-add-_len-variants-for-all-attribute-checking.patch
blob: 7f90df1638cb62bd5bbd88e7bd06d0925ab97c4b (plain)
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
From ad29d0304983e283d4aec4ee5462942eaf5c03ac Mon Sep 17 00:00:00 2001
From: Tobias Schramm <tobleminer@gmail.com>
Date: Thu, 15 Nov 2018 03:42:48 +0100
Subject: blobmsg: add _len variants for all attribute checking methods
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Introduce _len variants of blobmsg attribute checking functions which
aims to provide safer implementation as those functions should limit all
memory accesses performed on the blob to the range [attr, attr + len]
(upper bound non inclusive) and thus should be suited for checking of
untrusted blob attributes.

While at it add some comments in order to make it clear.

Signed-off-by: Tobias Schramm <tobleminer@gmail.com>
[_safe -> _len, blobmsg_check_array_len fix, commit subject/desc facelift]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
 blobmsg.c | 21 ++++++++++++++++++---
 blobmsg.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 4 deletions(-)

--- a/blobmsg.c
+++ b/blobmsg.c
@@ -101,11 +101,21 @@ bool blobmsg_check_attr_len(const struct
 
 int blobmsg_check_array(const struct blob_attr *attr, int type)
 {
+	return blobmsg_check_array_len(attr, type, blob_raw_len(attr));
+}
+
+int blobmsg_check_array_len(const struct blob_attr *attr, int type, size_t len)
+{
 	struct blob_attr *cur;
 	bool name;
-	int rem;
 	int size = 0;
 
+	if (type > BLOBMSG_TYPE_LAST)
+		return -1;
+
+	if (!blobmsg_check_attr_len(attr, false, len))
+		return -1;
+
 	switch (blobmsg_type(attr)) {
 	case BLOBMSG_TYPE_TABLE:
 		name = true;
@@ -117,11 +127,11 @@ int blobmsg_check_array(const struct blo
 		return -1;
 	}
 
-	blobmsg_for_each_attr(cur, attr, rem) {
+	__blobmsg_for_each_attr(cur, attr, len) {
 		if (type != BLOBMSG_TYPE_UNSPEC && blobmsg_type(cur) != type)
 			return -1;
 
-		if (!blobmsg_check_attr(cur, name))
+		if (!blobmsg_check_attr_len(cur, name, len))
 			return -1;
 
 		size++;
@@ -135,6 +145,11 @@ bool blobmsg_check_attr_list(const struc
 	return blobmsg_check_array(attr, type) >= 0;
 }
 
+bool blobmsg_check_attr_list_len(const struct blob_attr *attr, int type, size_t len)
+{
+	return blobmsg_check_array_len(attr, type, len) >= 0;
+}
+
 int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len,
 			struct blob_attr **tb, void *data, unsigned int len)
 {
--- a/blobmsg.h
+++ b/blobmsg.h
@@ -104,19 +104,66 @@ static inline int blobmsg_len(const stru
 	return blobmsg_data_len(attr);
 }
 
+/*
+ * blobmsg_check_attr: validate a list of attributes
+ *
+ * This method may be used with trusted data only. Providing
+ * malformed blobs will cause out of bounds memory access.
+ */
 bool blobmsg_check_attr(const struct blob_attr *attr, bool name);
-bool blobmsg_check_attr_list(const struct blob_attr *attr, int type);
 
+/*
+ * blobmsg_check_attr_len: validate a list of attributes
+ *
+ * This method should be safer implementation of blobmsg_check_attr.
+ * It will limit all memory access performed on the blob to the
+ * range [attr, attr + len] (upper bound non inclusive) and is
+ * thus suited for checking of untrusted blob attributes.
+ */
 bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len);
 
 /*
+ * blobmsg_check_attr_list: validate a list of attributes
+ *
+ * This method may be used with trusted data only. Providing
+ * malformed blobs will cause out of bounds memory access.
+ */
+bool blobmsg_check_attr_list(const struct blob_attr *attr, int type);
+
+/*
+ * blobmsg_check_attr_list_len: validate a list of untrusted attributes
+ *
+ * This method should be safer implementation of blobmsg_check_attr_list.
+ * It will limit all memory access performed on the blob to the
+ * range [attr, attr + len] (upper bound non inclusive) and is
+ * thus suited for checking of untrusted blob attributes.
+ */
+bool blobmsg_check_attr_list_len(const struct blob_attr *attr, int type, size_t len);
+
+/*
  * blobmsg_check_array: validate array/table and return size
  *
  * Checks if all elements of an array or table are valid and have
  * the specified type. Returns the number of elements in the array
+ *
+ * This method may be used with trusted data only. Providing
+ * malformed blobs will cause out of bounds memory access.
  */
 int blobmsg_check_array(const struct blob_attr *attr, int type);
 
+/*
+ * blobmsg_check_array_len: validate untrusted array/table and return size
+ *
+ * Checks if all elements of an array or table are valid and have
+ * the specified type. Returns the number of elements in the array.
+ *
+ * This method should be safer implementation of blobmsg_check_array.
+ * It will limit all memory access performed on the blob to the
+ * range [attr, attr + len] (upper bound non inclusive) and is
+ * thus suited for checking of untrusted blob attributes.
+ */
+int blobmsg_check_array_len(const struct blob_attr *attr, int type, size_t len);
+
 int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len,
                   struct blob_attr **tb, void *data, unsigned int len);
 int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len,
@@ -271,5 +318,11 @@ int blobmsg_printf(struct blob_buf *buf,
 	     rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
 	     (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
 	     rem -= blob_pad_len(pos), pos = blob_next(pos))
+
+#define __blobmsg_for_each_attr(pos, attr, rem) \
+	for (pos = (struct blob_attr *) (attr ? blobmsg_data(attr) : NULL); \
+	     rem >= sizeof(struct blob_attr) && (blob_pad_len(pos) <= rem) && \
+	     (blob_pad_len(pos) >= sizeof(struct blob_attr)); \
+	     rem -= blob_pad_len(pos), pos = blob_next(pos))
 
 #endif