stat-util: add macros for checking whether major and minor values are in range
As it turns out glibc and the Linux kernel have different ideas about the size of dev_t and how many bits exist for the major and the minor. When validating major/minor numbers we should check against the kernel's actual sizes, hence add macros for this.
This commit is contained in:
parent
192b89368e
commit
fb2430c6e5
|
@ -62,3 +62,22 @@ int fd_verify_regular(int fd);
|
|||
|
||||
int stat_verify_directory(const struct stat *st);
|
||||
int fd_verify_directory(int fd);
|
||||
|
||||
/* glibc and the Linux kernel have different ideas about the major/minor size. These calls will check whether the
|
||||
* specified major is valid by the Linux kernel's standards, not by glibc's. Linux has 20bits of minor, and 12 bits of
|
||||
* major space. See MINORBITS in linux/kdev_t.h in the kernel sources. (If you wonder why we define _y here, instead of
|
||||
* comparing directly >= 0: it's to trick out -Wtype-limits, which would otherwise complain if the type is unsigned, as
|
||||
* such a test would be pointless in such a case.) */
|
||||
|
||||
#define DEVICE_MAJOR_VALID(x) \
|
||||
({ \
|
||||
typeof(x) _x = (x), _y = 0; \
|
||||
_x >= _y && _x < (UINT32_C(1) << 12); \
|
||||
\
|
||||
})
|
||||
|
||||
#define DEVICE_MINOR_VALID(x) \
|
||||
({ \
|
||||
typeof(x) _x = (x), _y = 0; \
|
||||
_x >= _y && _x < (UINT32_C(1) << 20); \
|
||||
})
|
||||
|
|
|
@ -81,12 +81,48 @@ static void test_fd_is_network_ns(void) {
|
|||
assert_se(IN_SET(fd_is_network_ns(fd), 1, -EUCLEAN));
|
||||
}
|
||||
|
||||
static void test_device_major_minor_valid(void) {
|
||||
/* on glibc dev_t is 64bit, even though in the kernel it is only 32bit */
|
||||
assert_cc(sizeof(dev_t) == sizeof(uint64_t));
|
||||
|
||||
assert_se(DEVICE_MAJOR_VALID(0U));
|
||||
assert_se(DEVICE_MINOR_VALID(0U));
|
||||
|
||||
assert_se(DEVICE_MAJOR_VALID(1U));
|
||||
assert_se(DEVICE_MINOR_VALID(1U));
|
||||
|
||||
assert_se(!DEVICE_MAJOR_VALID(-1U));
|
||||
assert_se(!DEVICE_MINOR_VALID(-1U));
|
||||
|
||||
assert_se(DEVICE_MAJOR_VALID(1U << 10));
|
||||
assert_se(DEVICE_MINOR_VALID(1U << 10));
|
||||
|
||||
assert_se(DEVICE_MAJOR_VALID((1U << 12) - 1));
|
||||
assert_se(DEVICE_MINOR_VALID((1U << 20) - 1));
|
||||
|
||||
assert_se(!DEVICE_MAJOR_VALID((1U << 12)));
|
||||
assert_se(!DEVICE_MINOR_VALID((1U << 20)));
|
||||
|
||||
assert_se(!DEVICE_MAJOR_VALID(1U << 25));
|
||||
assert_se(!DEVICE_MINOR_VALID(1U << 25));
|
||||
|
||||
assert_se(!DEVICE_MAJOR_VALID(UINT32_MAX));
|
||||
assert_se(!DEVICE_MINOR_VALID(UINT32_MAX));
|
||||
|
||||
assert_se(!DEVICE_MAJOR_VALID(UINT64_MAX));
|
||||
assert_se(!DEVICE_MINOR_VALID(UINT64_MAX));
|
||||
|
||||
assert_se(DEVICE_MAJOR_VALID(major(0)));
|
||||
assert_se(DEVICE_MINOR_VALID(minor(0)));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_files_same();
|
||||
test_is_symlink();
|
||||
test_path_is_fs_type();
|
||||
test_path_is_temporary_fs();
|
||||
test_fd_is_network_ns();
|
||||
test_device_major_minor_valid();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue