hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/scripts/dtc/libfdt/fdt.c
....@@ -1,52 +1,7 @@
1
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
12 /*
23 * libfdt - Flat Device Tree manipulation
34 * Copyright (C) 2006 David Gibson, IBM Corporation.
4
- *
5
- * libfdt is dual licensed: you can use it either under the terms of
6
- * the GPL, or the BSD license, at your option.
7
- *
8
- * a) This library is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU General Public License as
10
- * published by the Free Software Foundation; either version 2 of the
11
- * License, or (at your option) any later version.
12
- *
13
- * This library is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public
19
- * License along with this library; if not, write to the Free
20
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21
- * MA 02110-1301 USA
22
- *
23
- * Alternatively,
24
- *
25
- * b) Redistribution and use in source and binary forms, with or
26
- * without modification, are permitted provided that the following
27
- * conditions are met:
28
- *
29
- * 1. Redistributions of source code must retain the above
30
- * copyright notice, this list of conditions and the following
31
- * disclaimer.
32
- * 2. Redistributions in binary form must reproduce the above
33
- * copyright notice, this list of conditions and the following
34
- * disclaimer in the documentation and/or other materials
35
- * provided with the distribution.
36
- *
37
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
505 */
516 #include "libfdt_env.h"
527
....@@ -55,20 +10,123 @@
5510
5611 #include "libfdt_internal.h"
5712
58
-int fdt_check_header(const void *fdt)
13
+/*
14
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
15
+ * that the given buffer contains what appears to be a flattened
16
+ * device tree with sane information in its header.
17
+ */
18
+int32_t fdt_ro_probe_(const void *fdt)
5919 {
20
+ uint32_t totalsize = fdt_totalsize(fdt);
21
+
22
+ if (can_assume(VALID_DTB))
23
+ return totalsize;
24
+
6025 if (fdt_magic(fdt) == FDT_MAGIC) {
6126 /* Complete tree */
62
- if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
63
- return -FDT_ERR_BADVERSION;
64
- if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
65
- return -FDT_ERR_BADVERSION;
27
+ if (!can_assume(LATEST)) {
28
+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
29
+ return -FDT_ERR_BADVERSION;
30
+ if (fdt_last_comp_version(fdt) >
31
+ FDT_LAST_SUPPORTED_VERSION)
32
+ return -FDT_ERR_BADVERSION;
33
+ }
6634 } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
6735 /* Unfinished sequential-write blob */
68
- if (fdt_size_dt_struct(fdt) == 0)
36
+ if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
6937 return -FDT_ERR_BADSTATE;
7038 } else {
7139 return -FDT_ERR_BADMAGIC;
40
+ }
41
+
42
+ if (totalsize < INT32_MAX)
43
+ return totalsize;
44
+ else
45
+ return -FDT_ERR_TRUNCATED;
46
+}
47
+
48
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
49
+{
50
+ return (off >= hdrsize) && (off <= totalsize);
51
+}
52
+
53
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
54
+ uint32_t base, uint32_t size)
55
+{
56
+ if (!check_off_(hdrsize, totalsize, base))
57
+ return 0; /* block start out of bounds */
58
+ if ((base + size) < base)
59
+ return 0; /* overflow */
60
+ if (!check_off_(hdrsize, totalsize, base + size))
61
+ return 0; /* block end out of bounds */
62
+ return 1;
63
+}
64
+
65
+size_t fdt_header_size_(uint32_t version)
66
+{
67
+ if (version <= 1)
68
+ return FDT_V1_SIZE;
69
+ else if (version <= 2)
70
+ return FDT_V2_SIZE;
71
+ else if (version <= 3)
72
+ return FDT_V3_SIZE;
73
+ else if (version <= 16)
74
+ return FDT_V16_SIZE;
75
+ else
76
+ return FDT_V17_SIZE;
77
+}
78
+
79
+size_t fdt_header_size(const void *fdt)
80
+{
81
+ return can_assume(LATEST) ? FDT_V17_SIZE :
82
+ fdt_header_size_(fdt_version(fdt));
83
+}
84
+
85
+int fdt_check_header(const void *fdt)
86
+{
87
+ size_t hdrsize;
88
+
89
+ if (fdt_magic(fdt) != FDT_MAGIC)
90
+ return -FDT_ERR_BADMAGIC;
91
+ if (!can_assume(LATEST)) {
92
+ if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
93
+ || (fdt_last_comp_version(fdt) >
94
+ FDT_LAST_SUPPORTED_VERSION))
95
+ return -FDT_ERR_BADVERSION;
96
+ if (fdt_version(fdt) < fdt_last_comp_version(fdt))
97
+ return -FDT_ERR_BADVERSION;
98
+ }
99
+ hdrsize = fdt_header_size(fdt);
100
+ if (!can_assume(VALID_DTB)) {
101
+
102
+ if ((fdt_totalsize(fdt) < hdrsize)
103
+ || (fdt_totalsize(fdt) > INT_MAX))
104
+ return -FDT_ERR_TRUNCATED;
105
+
106
+ /* Bounds check memrsv block */
107
+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
108
+ fdt_off_mem_rsvmap(fdt)))
109
+ return -FDT_ERR_TRUNCATED;
110
+ }
111
+
112
+ if (!can_assume(VALID_DTB)) {
113
+ /* Bounds check structure block */
114
+ if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
115
+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
116
+ fdt_off_dt_struct(fdt)))
117
+ return -FDT_ERR_TRUNCATED;
118
+ } else {
119
+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
120
+ fdt_off_dt_struct(fdt),
121
+ fdt_size_dt_struct(fdt)))
122
+ return -FDT_ERR_TRUNCATED;
123
+ }
124
+
125
+ /* Bounds check strings block */
126
+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
127
+ fdt_off_dt_strings(fdt),
128
+ fdt_size_dt_strings(fdt)))
129
+ return -FDT_ERR_TRUNCATED;
72130 }
73131
74132 return 0;
....@@ -76,15 +134,20 @@
76134
77135 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
78136 {
79
- unsigned absoffset = offset + fdt_off_dt_struct(fdt);
137
+ unsigned int uoffset = offset;
138
+ unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
80139
81
- if ((absoffset < offset)
82
- || ((absoffset + len) < absoffset)
83
- || (absoffset + len) > fdt_totalsize(fdt))
140
+ if (offset < 0)
84141 return NULL;
85142
86
- if (fdt_version(fdt) >= 0x11)
87
- if (((offset + len) < offset)
143
+ if (!can_assume(VALID_INPUT))
144
+ if ((absoffset < uoffset)
145
+ || ((absoffset + len) < absoffset)
146
+ || (absoffset + len) > fdt_totalsize(fdt))
147
+ return NULL;
148
+
149
+ if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
150
+ if (((uoffset + len) < uoffset)
88151 || ((offset + len) > fdt_size_dt_struct(fdt)))
89152 return NULL;
90153
....@@ -100,7 +163,7 @@
100163
101164 *nextoffset = -FDT_ERR_TRUNCATED;
102165 tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
103
- if (!tagp)
166
+ if (!can_assume(VALID_DTB) && !tagp)
104167 return FDT_END; /* premature end */
105168 tag = fdt32_to_cpu(*tagp);
106169 offset += FDT_TAGSIZE;
....@@ -112,18 +175,19 @@
112175 do {
113176 p = fdt_offset_ptr(fdt, offset++, 1);
114177 } while (p && (*p != '\0'));
115
- if (!p)
178
+ if (!can_assume(VALID_DTB) && !p)
116179 return FDT_END; /* premature end */
117180 break;
118181
119182 case FDT_PROP:
120183 lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
121
- if (!lenp)
184
+ if (!can_assume(VALID_DTB) && !lenp)
122185 return FDT_END; /* premature end */
123186 /* skip-name offset, length and value */
124187 offset += sizeof(struct fdt_property) - FDT_TAGSIZE
125188 + fdt32_to_cpu(*lenp);
126
- if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
189
+ if (!can_assume(LATEST) &&
190
+ fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
127191 ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
128192 offset += 4;
129193 break;
....@@ -146,8 +210,11 @@
146210
147211 int fdt_check_node_offset_(const void *fdt, int offset)
148212 {
149
- if ((offset < 0) || (offset % FDT_TAGSIZE)
150
- || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
213
+ if (!can_assume(VALID_INPUT)
214
+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
215
+ return -FDT_ERR_BADOFFSET;
216
+
217
+ if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
151218 return -FDT_ERR_BADOFFSET;
152219
153220 return offset;
....@@ -155,8 +222,11 @@
155222
156223 int fdt_check_prop_offset_(const void *fdt, int offset)
157224 {
158
- if ((offset < 0) || (offset % FDT_TAGSIZE)
159
- || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
225
+ if (!can_assume(VALID_INPUT)
226
+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
227
+ return -FDT_ERR_BADOFFSET;
228
+
229
+ if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
160230 return -FDT_ERR_BADOFFSET;
161231
162232 return offset;
....@@ -244,9 +314,12 @@
244314
245315 int fdt_move(const void *fdt, void *buf, int bufsize)
246316 {
247
- FDT_CHECK_HEADER(fdt);
317
+ if (!can_assume(VALID_INPUT) && bufsize < 0)
318
+ return -FDT_ERR_NOSPACE;
248319
249
- if (fdt_totalsize(fdt) > bufsize)
320
+ FDT_RO_PROBE(fdt);
321
+
322
+ if (fdt_totalsize(fdt) > (unsigned int)bufsize)
250323 return -FDT_ERR_NOSPACE;
251324
252325 memmove(buf, fdt, fdt_totalsize(fdt));