Bug Summary

File:build-scan/../src/udev/udev-builtin-blkid.c
Warning:line 178, column 16
Potential leak of memory pointed to by 'root_id'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name udev-builtin-blkid.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/udev/libudev-core.a.p -I src/udev -I ../src/udev -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I ../src/udev/net -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -D LOG_REALM=LOG_REALM_UDEV -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/udev/udev-builtin-blkid.c
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * probe disks for filesystems and partitions
4 *
5 * Copyright © 2011 Karel Zak <kzak@redhat.com>
6 *
7 */
8
9#include <blkid.h>
10#include <errno(*__errno_location ()).h>
11#include <fcntl.h>
12#include <getopt.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/stat.h>
17
18#include "sd-id128.h"
19
20#include "alloc-util.h"
21#include "blkid-util.h"
22#include "efivars.h"
23#include "fd-util.h"
24#include "gpt.h"
25#include "parse-util.h"
26#include "string-util.h"
27#include "udev.h"
28
29static void print_property(struct udev_device *dev, bool_Bool test, const char *name, const char *value) {
30 char s[256];
31
32 s[0] = '\0';
33
34 if (streq(name, "TYPE")(strcmp((name),("TYPE")) == 0)) {
35 udev_builtin_add_property(dev, test, "ID_FS_TYPE", value);
36
37 } else if (streq(name, "USAGE")(strcmp((name),("USAGE")) == 0)) {
38 udev_builtin_add_property(dev, test, "ID_FS_USAGE", value);
39
40 } else if (streq(name, "VERSION")(strcmp((name),("VERSION")) == 0)) {
41 udev_builtin_add_property(dev, test, "ID_FS_VERSION", value);
42
43 } else if (streq(name, "UUID")(strcmp((name),("UUID")) == 0)) {
44 blkid_safe_string(value, s, sizeof(s));
45 udev_builtin_add_property(dev, test, "ID_FS_UUID", s);
46 blkid_encode_string(value, s, sizeof(s));
47 udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s);
48
49 } else if (streq(name, "UUID_SUB")(strcmp((name),("UUID_SUB")) == 0)) {
50 blkid_safe_string(value, s, sizeof(s));
51 udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s);
52 blkid_encode_string(value, s, sizeof(s));
53 udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s);
54
55 } else if (streq(name, "LABEL")(strcmp((name),("LABEL")) == 0)) {
56 blkid_safe_string(value, s, sizeof(s));
57 udev_builtin_add_property(dev, test, "ID_FS_LABEL", s);
58 blkid_encode_string(value, s, sizeof(s));
59 udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s);
60
61 } else if (streq(name, "PTTYPE")(strcmp((name),("PTTYPE")) == 0)) {
62 udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value);
63
64 } else if (streq(name, "PTUUID")(strcmp((name),("PTUUID")) == 0)) {
65 udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value);
66
67 } else if (streq(name, "PART_ENTRY_NAME")(strcmp((name),("PART_ENTRY_NAME")) == 0)) {
68 blkid_encode_string(value, s, sizeof(s));
69 udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s);
70
71 } else if (streq(name, "PART_ENTRY_TYPE")(strcmp((name),("PART_ENTRY_TYPE")) == 0)) {
72 blkid_encode_string(value, s, sizeof(s));
73 udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s);
74
75 } else if (startswith(name, "PART_ENTRY_")) {
76 strscpyl(s, sizeof(s), "ID_", name, NULL((void*)0));
77 udev_builtin_add_property(dev, test, s, value);
78
79 } else if (streq(name, "SYSTEM_ID")(strcmp((name),("SYSTEM_ID")) == 0)) {
80 blkid_encode_string(value, s, sizeof(s));
81 udev_builtin_add_property(dev, test, "ID_FS_SYSTEM_ID", s);
82
83 } else if (streq(name, "PUBLISHER_ID")(strcmp((name),("PUBLISHER_ID")) == 0)) {
84 blkid_encode_string(value, s, sizeof(s));
85 udev_builtin_add_property(dev, test, "ID_FS_PUBLISHER_ID", s);
86
87 } else if (streq(name, "APPLICATION_ID")(strcmp((name),("APPLICATION_ID")) == 0)) {
88 blkid_encode_string(value, s, sizeof(s));
89 udev_builtin_add_property(dev, test, "ID_FS_APPLICATION_ID", s);
90
91 } else if (streq(name, "BOOT_SYSTEM_ID")(strcmp((name),("BOOT_SYSTEM_ID")) == 0)) {
92 blkid_encode_string(value, s, sizeof(s));
93 udev_builtin_add_property(dev, test, "ID_FS_BOOT_SYSTEM_ID", s);
94 }
95}
96
97static int find_gpt_root(struct udev_device *dev, blkid_probe pr, bool_Bool test) {
98
99#if defined(GPT_ROOT_NATIVE((const sd_id128_t) { .bytes = { 0x4f, 0x68, 0xbc, 0xe3, 0xe8
, 0xcd, 0x4d, 0xb1, 0x96, 0xe7, 0xfb, 0xca, 0xf9, 0x84, 0xb7,
0x09 }})
) && ENABLE_EFI1
100
101 _cleanup_free___attribute__((cleanup(freep))) char *root_id = NULL((void*)0);
102 bool_Bool found_esp = false0;
103 blkid_partlist pl;
104 int i, nvals, r;
105
106 assert(pr)do { if ((__builtin_expect(!!(!(pr)),0))) log_assert_failed_realm
(LOG_REALM_UDEV, ("pr"), "../src/udev/udev-builtin-blkid.c", 106
, __PRETTY_FUNCTION__); } while (0)
;
27
Taking false branch
28
Loop condition is false. Exiting loop
107
108 /* Iterate through the partitions on this disk, and see if the
109 * EFI ESP we booted from is on it. If so, find the first root
110 * disk, and add a property indicating its partition UUID. */
111
112 errno(*__errno_location ()) = 0;
113 pl = blkid_probe_get_partitions(pr);
114 if (!pl)
29
Assuming 'pl' is non-null
30
Taking false branch
115 return -errno(*__errno_location ()) ?: -ENOMEM12;
116
117 nvals = blkid_partlist_numof_partitions(pl);
118 for (i = 0; i < nvals; i++) {
31
Assuming 'i' is < 'nvals'
32
Loop condition is true. Entering loop body
49
Assuming 'i' is >= 'nvals'
50
Loop condition is false. Execution continues on line 174
119 blkid_partition pp;
120 const char *stype, *sid;
121 sd_id128_t type;
122
123 pp = blkid_partlist_get_partition(pl, i);
124 if (!pp)
33
Assuming 'pp' is non-null
34
Taking false branch
125 continue;
126
127 sid = blkid_partition_get_uuid(pp);
128 if (!sid)
35
Assuming 'sid' is non-null
36
Taking false branch
129 continue;
130
131 stype = blkid_partition_get_type_string(pp);
132 if (!stype)
37
Assuming 'stype' is non-null
38
Taking false branch
133 continue;
134
135 if (sd_id128_from_string(stype, &type) < 0)
39
Assuming the condition is false
40
Taking false branch
136 continue;
137
138 if (sd_id128_equal(type, GPT_ESP((const sd_id128_t) { .bytes = { 0xc1, 0x2a, 0x73, 0x28, 0xf8
, 0x1f, 0x11, 0xd2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9,
0x3b }})
)) {
41
Taking false branch
139 sd_id128_t id, esp;
140
141 /* We found an ESP, let's see if it matches
142 * the ESP we booted from. */
143
144 if (sd_id128_from_string(sid, &id) < 0)
145 continue;
146
147 r = efi_loader_get_device_part_uuid(&esp);
148 if (r < 0)
149 return r;
150
151 if (sd_id128_equal(id, esp))
152 found_esp = true1;
153
154 } else if (sd_id128_equal(type, GPT_ROOT_NATIVE((const sd_id128_t) { .bytes = { 0x4f, 0x68, 0xbc, 0xe3, 0xe8
, 0xcd, 0x4d, 0xb1, 0x96, 0xe7, 0xfb, 0xca, 0xf9, 0x84, 0xb7,
0x09 }})
)) {
42
Taking true branch
155 unsigned long long flags;
156
157 flags = blkid_partition_get_flags(pp);
158 if (flags & GPT_FLAG_NO_AUTO(1ULL << 63))
43
Assuming the condition is false
44
Taking false branch
159 continue;
160
161 /* We found a suitable root partition, let's
162 * remember the first one. */
163
164 if (!root_id
44.1
'root_id' is null
) {
45
Taking true branch
165 root_id = strdup(sid);
46
Memory is allocated
166 if (!root_id)
47
Assuming 'root_id' is non-null
48
Taking false branch
167 return -ENOMEM12;
168 }
169 }
170 }
171
172 /* We found the ESP on this disk, and also found a root
173 * partition, nice! Let's export its UUID */
174 if (found_esp
50.1
'found_esp' is false
&& root_id)
175 udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id);
176#endif
177
178 return 0;
51
Potential leak of memory pointed to by 'root_id'
179}
180
181static int probe_superblocks(blkid_probe pr) {
182 struct stat st;
183 int rc;
184
185 if (fstat(blkid_probe_get_fd(pr), &st))
186 return -errno(*__errno_location ());
187
188 blkid_probe_enable_partitions(pr, 1);
189
190 if (!S_ISCHR(st.st_mode)((((st.st_mode)) & 0170000) == (0020000)) &&
191 blkid_probe_get_size(pr) <= 1024 * 1440 &&
192 blkid_probe_is_wholedisk(pr)) {
193 /*
194 * check if the small disk is partitioned, if yes then
195 * don't probe for filesystems.
196 */
197 blkid_probe_enable_superblocks(pr, 0);
198
199 rc = blkid_do_fullprobe(pr);
200 if (rc < 0)
201 return rc; /* -1 = error, 1 = nothing, 0 = success */
202
203 if (blkid_probe_lookup_value(pr, "PTTYPE", NULL((void*)0), NULL((void*)0)) == 0)
204 return 0; /* partition table detected */
205 }
206
207 blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS(1 << 2));
208 blkid_probe_enable_superblocks(pr, 1);
209
210 return blkid_do_safeprobe(pr);
211}
212
213static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool_Bool test) {
214 const char *root_partition;
215 int64_t offset = 0;
216 bool_Bool noraid = false0;
217 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
218 _cleanup_(blkid_free_probep)__attribute__((cleanup(blkid_free_probep))) blkid_probe pr = NULL((void*)0);
219 const char *data;
220 const char *name;
221 int nvals;
222 int i;
223 int err = 0;
224 bool_Bool is_gpt = false0;
225
226 static const struct option options[] = {
227 { "offset", required_argument1, NULL((void*)0), 'o' },
228 { "noraid", no_argument0, NULL((void*)0), 'R' },
229 {}
230 };
231
232 for (;;) {
1
Loop condition is true. Entering loop body
233 int option;
234
235 option = getopt_long(argc, argv, "o:R", options, NULL((void*)0));
236 if (option == -1)
2
Assuming the condition is true
3
Taking true branch
237 break;
4
Execution continues on line 255
238
239 switch (option) {
240 case 'o':
241 err = safe_atoi64(optarg, &offset);
242 if (err < 0)
243 goto out;
244 if (offset < 0) {
245 err = -ERANGE34;
246 goto out;
247 }
248 break;
249 case 'R':
250 noraid = true1;
251 break;
252 }
253 }
254
255 pr = blkid_new_probe();
256 if (!pr)
5
Assuming 'pr' is non-null
6
Taking false branch
257 return EXIT_FAILURE1;
258
259 blkid_probe_set_superblocks_flags(pr,
260 BLKID_SUBLKS_LABEL(1 << 1) | BLKID_SUBLKS_UUID(1 << 3) |
261 BLKID_SUBLKS_TYPE(1 << 5) | BLKID_SUBLKS_SECTYPE(1 << 6) |
262 BLKID_SUBLKS_USAGE(1 << 7) | BLKID_SUBLKS_VERSION(1 << 8));
263
264 if (noraid
6.1
'noraid' is false
)
7
Taking false branch
265 blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN1, BLKID_USAGE_RAID(1 << 2));
266
267 fd = open(udev_device_get_devnode(dev), O_RDONLY00|O_CLOEXEC02000000);
268 if (fd < 0) {
8
Assuming 'fd' is >= 0
9
Taking false branch
269 err = log_debug_errno(errno, "Failure opening block device %s: %m", udev_device_get_devnode(dev))({ int _level = ((7)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_UDEV); (log_get_max_level_realm(_realm) >= (
(_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/udev/udev-builtin-blkid.c", 269,
__func__, "Failure opening block device %s: %m", udev_device_get_devnode
(dev)) : -abs(_e); })
;
270 goto out;
271 }
272
273 err = blkid_probe_set_device(pr, fd, offset, 0);
274 if (err < 0)
10
Assuming 'err' is >= 0
11
Taking false branch
275 goto out;
276
277 log_debug("probe %s %sraid offset=%"PRIi64,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-builtin-blkid.c", 279, __func__, "probe %s %sraid offset=%"
"l" "i", udev_device_get_devnode(dev), noraid ? "no" : "", offset
) : -abs(_e); })
12
Assuming the condition is false
13
'?' condition is false
278 udev_device_get_devnode(dev),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-builtin-blkid.c", 279, __func__, "probe %s %sraid offset=%"
"l" "i", udev_device_get_devnode(dev), noraid ? "no" : "", offset
) : -abs(_e); })
279 noraid ? "no" : "", offset)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/udev/udev-builtin-blkid.c", 279, __func__, "probe %s %sraid offset=%"
"l" "i", udev_device_get_devnode(dev), noraid ? "no" : "", offset
) : -abs(_e); })
;
280
281 err = probe_superblocks(pr);
282 if (err < 0)
14
Assuming 'err' is >= 0
15
Taking false branch
283 goto out;
284
285 /* If we are a partition then our parent passed on the root
286 * partition UUID to us */
287 root_partition = udev_device_get_property_value(dev, "ID_PART_GPT_AUTO_ROOT_UUID");
288
289 nvals = blkid_probe_numof_values(pr);
290 for (i = 0; i < nvals; i++) {
16
Assuming 'i' is < 'nvals'
17
Loop condition is true. Entering loop body
23
Assuming 'i' is >= 'nvals'
24
Loop condition is false. Execution continues on line 306
291 if (blkid_probe_get_value(pr, i, &name, &data, NULL((void*)0)))
18
Assuming the condition is false
19
Taking false branch
292 continue;
293
294 print_property(dev, test, name, data);
295
296 /* Is this a disk with GPT partition table? */
297 if (streq(name, "PTTYPE")(strcmp((name),("PTTYPE")) == 0) && streq(data, "gpt")(strcmp((data),("gpt")) == 0))
20
Taking true branch
298 is_gpt = true1;
299
300 /* Is this a partition that matches the root partition
301 * property we inherited from our parent? */
302 if (root_partition && streq(name, "PART_ENTRY_UUID")(strcmp((name),("PART_ENTRY_UUID")) == 0) && streq(data, root_partition)(strcmp((data),(root_partition)) == 0))
21
Assuming 'root_partition' is non-null
22
Taking true branch
303 udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1");
304 }
305
306 if (is_gpt
24.1
'is_gpt' is true
)
25
Taking true branch
307 find_gpt_root(dev, pr, test);
26
Calling 'find_gpt_root'
308
309out:
310 if (err < 0)
311 return EXIT_FAILURE1;
312
313 return EXIT_SUCCESS0;
314}
315
316const struct udev_builtin udev_builtin_blkid = {
317 .name = "blkid",
318 .cmd = builtin_blkid,
319 .help = "Filesystem and partition probing",
320 .run_once = true1,
321};