mirror of
https://github.com/systemd/systemd.git
synced 2025-08-30 05:49:54 +03:00
blockdev-util: fix access to possibly invalidated dirent struct
Let's copy out the string we need from the dirent, there's no reason to believe the dirent struct might live for longer than one loop iteration.
This commit is contained in:
@ -94,7 +94,8 @@ int block_get_originating(dev_t dt, dev_t *ret) {
|
|||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
char p[SYS_BLOCK_PATH_MAX("/slaves")];
|
char p[SYS_BLOCK_PATH_MAX("/slaves")];
|
||||||
struct dirent *de, *found = NULL;
|
_cleanup_free_ char *first_found = NULL;
|
||||||
|
struct dirent *de;
|
||||||
const char *q;
|
const char *q;
|
||||||
dev_t devt;
|
dev_t devt;
|
||||||
int r;
|
int r;
|
||||||
@ -115,20 +116,22 @@ int block_get_originating(dev_t dt, dev_t *ret) {
|
|||||||
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
|
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (found) {
|
if (first_found) {
|
||||||
_cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
|
_cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
|
||||||
|
|
||||||
/* We found a device backed by multiple other devices. We don't really support automatic
|
/* We found a device backed by multiple other devices. We don't really support
|
||||||
* discovery on such setups, with the exception of dm-verity partitions. In this case there are
|
* automatic discovery on such setups, with the exception of dm-verity partitions. In
|
||||||
* two backing devices: the data partition and the hash partition. We are fine with such
|
* this case there are two backing devices: the data partition and the hash
|
||||||
* setups, however, only if both partitions are on the same physical device. Hence, let's
|
* partition. We are fine with such setups, however, only if both partitions are on
|
||||||
* verify this. */
|
* the same physical device. Hence, let's verify this by iterating over every node
|
||||||
|
* in the 'slaves/' directory and comparing them with the first that gets returned by
|
||||||
|
* readdir(), to ensure they all point to the same device. */
|
||||||
|
|
||||||
u = path_join(p, de->d_name, "../dev");
|
u = path_join(p, de->d_name, "../dev");
|
||||||
if (!u)
|
if (!u)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
v = path_join(p, found->d_name, "../dev");
|
v = path_join(p, first_found, "../dev");
|
||||||
if (!v)
|
if (!v)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -144,15 +147,17 @@ int block_get_originating(dev_t dt, dev_t *ret) {
|
|||||||
* different physical devices, and we don't support that. */
|
* different physical devices, and we don't support that. */
|
||||||
if (!streq(a, b))
|
if (!streq(a, b))
|
||||||
return -ENOTUNIQ;
|
return -ENOTUNIQ;
|
||||||
|
} else {
|
||||||
|
first_found = strdup(de->d_name);
|
||||||
|
if (!first_found)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
found = de;
|
if (!first_found)
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
q = strjoina(p, "/", found->d_name, "/dev");
|
q = strjoina(p, "/", first_found, "/dev");
|
||||||
|
|
||||||
r = read_one_line_file(q, &t);
|
r = read_one_line_file(q, &t);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
Reference in New Issue
Block a user