mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 17:22:07 +00:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
This commit is contained in:
commit
410a2fb2e3
@ -24,7 +24,7 @@ int main(void)
|
|||||||
|
|
||||||
// Check if test is run a root
|
// Check if test is run a root
|
||||||
if (geteuid()) {
|
if (geteuid()) {
|
||||||
ksft_test_result_skip("This test needs root to run!\n");
|
ksft_exit_skip("This test needs root to run!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
statmount_test_ns
|
||||||
/*_test
|
/*_test
|
||||||
|
@ -194,7 +194,7 @@ int fill_msgque(struct msgque_data *msgque)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int msg, pid, err;
|
int err;
|
||||||
struct msgque_data msgque;
|
struct msgque_data msgque;
|
||||||
|
|
||||||
if (getuid() != 0)
|
if (getuid() != 0)
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
* ksft_print_msg(fmt, ...);
|
* ksft_print_msg(fmt, ...);
|
||||||
* ksft_perror(msg);
|
* ksft_perror(msg);
|
||||||
*
|
*
|
||||||
* and finally report the pass/fail/skip/xfail state of the test with one of:
|
* and finally report the pass/fail/skip/xfail/xpass state of the test
|
||||||
|
* with one of:
|
||||||
*
|
*
|
||||||
* ksft_test_result(condition, fmt, ...);
|
* ksft_test_result(condition, fmt, ...);
|
||||||
* ksft_test_result_report(result, fmt, ...);
|
* ksft_test_result_report(result, fmt, ...);
|
||||||
@ -26,6 +27,7 @@
|
|||||||
* ksft_test_result_fail(fmt, ...);
|
* ksft_test_result_fail(fmt, ...);
|
||||||
* ksft_test_result_skip(fmt, ...);
|
* ksft_test_result_skip(fmt, ...);
|
||||||
* ksft_test_result_xfail(fmt, ...);
|
* ksft_test_result_xfail(fmt, ...);
|
||||||
|
* ksft_test_result_xpass(fmt, ...);
|
||||||
* ksft_test_result_error(fmt, ...);
|
* ksft_test_result_error(fmt, ...);
|
||||||
* ksft_test_result_code(exit_code, test_name, fmt, ...);
|
* ksft_test_result_code(exit_code, test_name, fmt, ...);
|
||||||
*
|
*
|
||||||
@ -147,6 +149,11 @@ static inline void ksft_set_plan(unsigned int plan)
|
|||||||
|
|
||||||
static inline void ksft_print_cnts(void)
|
static inline void ksft_print_cnts(void)
|
||||||
{
|
{
|
||||||
|
if (ksft_cnt.ksft_xskip > 0)
|
||||||
|
printf(
|
||||||
|
"# %u skipped test(s) detected. Consider enabling relevant config options to improve coverage.\n",
|
||||||
|
ksft_cnt.ksft_xskip
|
||||||
|
);
|
||||||
if (ksft_plan != ksft_test_num())
|
if (ksft_plan != ksft_test_num())
|
||||||
printf("# Planned tests != run tests (%u != %u)\n",
|
printf("# Planned tests != run tests (%u != %u)\n",
|
||||||
ksft_plan, ksft_test_num());
|
ksft_plan, ksft_test_num());
|
||||||
@ -227,6 +234,20 @@ static inline __printf(1, 2) void ksft_test_result_xfail(const char *msg, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline __printf(1, 2) void ksft_test_result_xpass(const char *msg, ...)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
ksft_cnt.ksft_xpass++;
|
||||||
|
|
||||||
|
va_start(args, msg);
|
||||||
|
printf("ok %u # XPASS ", ksft_test_num());
|
||||||
|
errno = saved_errno;
|
||||||
|
vprintf(msg, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
static inline __printf(1, 2) void ksft_test_result_skip(const char *msg, ...)
|
static inline __printf(1, 2) void ksft_test_result_skip(const char *msg, ...)
|
||||||
{
|
{
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
@ -318,6 +339,9 @@ void ksft_test_result_code(int exit_code, const char *test_name,
|
|||||||
case KSFT_XFAIL: \
|
case KSFT_XFAIL: \
|
||||||
ksft_test_result_xfail(fmt, ##__VA_ARGS__); \
|
ksft_test_result_xfail(fmt, ##__VA_ARGS__); \
|
||||||
break; \
|
break; \
|
||||||
|
case KSFT_XPASS: \
|
||||||
|
ksft_test_result_xpass(fmt, ##__VA_ARGS__); \
|
||||||
|
break; \
|
||||||
case KSFT_SKIP: \
|
case KSFT_SKIP: \
|
||||||
ksft_test_result_skip(fmt, ##__VA_ARGS__); \
|
ksft_test_result_skip(fmt, ##__VA_ARGS__); \
|
||||||
break; \
|
break; \
|
||||||
@ -403,7 +427,7 @@ static inline __noreturn __printf(1, 2) void ksft_exit_skip(const char *msg, ...
|
|||||||
*/
|
*/
|
||||||
if (ksft_plan || ksft_test_num()) {
|
if (ksft_plan || ksft_test_num()) {
|
||||||
ksft_cnt.ksft_xskip++;
|
ksft_cnt.ksft_xskip++;
|
||||||
printf("ok %d # SKIP ", 1 + ksft_test_num());
|
printf("ok %u # SKIP ", 1 + ksft_test_num());
|
||||||
} else {
|
} else {
|
||||||
printf("1..0 # SKIP ");
|
printf("1..0 # SKIP ");
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,9 @@ def set_plan(num_tests):
|
|||||||
|
|
||||||
|
|
||||||
def print_cnts():
|
def print_cnts():
|
||||||
|
if ksft_cnt['skip'] > 0:
|
||||||
|
print(f"# {ksft_cnt['skip']} skipped test(s) detected. Consider enabling relevant config options to improve coverage.")
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f"# Totals: pass:{ksft_cnt['pass']} fail:{ksft_cnt['fail']} xfail:0 xpass:0 skip:{ksft_cnt['skip']} error:0"
|
f"# Totals: pass:{ksft_cnt['pass']} fail:{ksft_cnt['fail']} xfail:0 xpass:0 skip:{ksft_cnt['skip']} error:0"
|
||||||
)
|
)
|
||||||
|
@ -107,5 +107,9 @@ ktap_finished() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ktap_print_totals() {
|
ktap_print_totals() {
|
||||||
|
if [ "$KTAP_CNT_SKIP" -gt 0 ]; then
|
||||||
|
echo "# $KTAP_CNT_SKIP skipped test(s) detected. " \
|
||||||
|
"Consider enabling relevant config options to improve coverage."
|
||||||
|
fi
|
||||||
echo "# Totals: pass:$KTAP_CNT_PASS fail:$KTAP_CNT_FAIL xfail:0 xpass:0 skip:$KTAP_CNT_SKIP error:0"
|
echo "# Totals: pass:$KTAP_CNT_PASS fail:$KTAP_CNT_FAIL xfail:0 xpass:0 skip:$KTAP_CNT_SKIP error:0"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Testing for regressions in Media Controller API register, ioctl, syscall,
|
Testing for regressions in Media Controller API register, ioctl, syscall,
|
||||||
and unregister paths. There have a few problems that result in user-after
|
and unregister paths. There have a few problems that result in use-after
|
||||||
free on media_device, media_devnode, and cdev pointers when the driver is
|
free on media_device, media_devnode, and cdev pointers when the driver is
|
||||||
unbound while ioctl is in progress.
|
unbound while ioctl is in progress.
|
||||||
|
|
||||||
@ -15,11 +15,11 @@ Build media_device_test
|
|||||||
cd tools/testing/selftests/media_tests
|
cd tools/testing/selftests/media_tests
|
||||||
make
|
make
|
||||||
|
|
||||||
Regressions test for cdev user-after free error on /dev/mediaX when driver
|
Regressions test for cdev use-after-free error on /dev/mediaX when driver
|
||||||
is unbound:
|
is unbound:
|
||||||
|
|
||||||
Start media_device_test to regression test media devnode dynamic alloc
|
Start media_device_test to regression test media devnode dynamic alloc
|
||||||
and cdev user-after-free fixes. This opens media dev files and sits in
|
and cdev use-after-free fixes. This opens media dev files and sits in
|
||||||
a loop running media ioctl MEDIA_IOC_DEVICE_INFO command once every 10
|
a loop running media ioctl MEDIA_IOC_DEVICE_INFO command once every 10
|
||||||
seconds. The idea is when device file goes away, media devnode and cdev
|
seconds. The idea is when device file goes away, media devnode and cdev
|
||||||
should stick around until this test exits.
|
should stick around until this test exits.
|
||||||
@ -40,4 +40,4 @@ keep ioctls going while bind/unbind runs.
|
|||||||
Copy bind_unbind_sample.txt and make changes to specify the driver name
|
Copy bind_unbind_sample.txt and make changes to specify the driver name
|
||||||
and number to run bind and unbind. Start the bind_unbind.sh
|
and number to run bind and unbind. Start the bind_unbind.sh
|
||||||
|
|
||||||
Run dmesg looking for any user-after free errors or mutex lock errors.
|
Run dmesg looking for any use-after-free errors or mutex lock errors.
|
||||||
|
@ -156,7 +156,7 @@ int main(int argc, char **argv)
|
|||||||
/* Check everything is sane before we start switching asynchronously */
|
/* Check everything is sane before we start switching asynchronously */
|
||||||
if (do_sanity_check) {
|
if (do_sanity_check) {
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
printf("Validating clocksource %s\n",
|
ksft_print_msg("Validating clocksource %s\n",
|
||||||
clocksource_list[i]);
|
clocksource_list[i]);
|
||||||
if (change_clocksource(clocksource_list[i])) {
|
if (change_clocksource(clocksource_list[i])) {
|
||||||
status = -1;
|
status = -1;
|
||||||
@ -169,7 +169,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Running Asynchronous Switching Tests...\n");
|
ksft_print_msg("Running Asynchronous Switching Tests...\n");
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (!pid)
|
if (!pid)
|
||||||
return run_tests(runtime);
|
return run_tests(runtime);
|
||||||
|
@ -53,6 +53,7 @@ static struct vdso_info
|
|||||||
/* Symbol table */
|
/* Symbol table */
|
||||||
ELF(Sym) *symtab;
|
ELF(Sym) *symtab;
|
||||||
const char *symstrings;
|
const char *symstrings;
|
||||||
|
ELF(Word) *gnu_hash;
|
||||||
ELF_HASH_ENTRY *bucket, *chain;
|
ELF_HASH_ENTRY *bucket, *chain;
|
||||||
ELF_HASH_ENTRY nbucket, nchain;
|
ELF_HASH_ENTRY nbucket, nchain;
|
||||||
|
|
||||||
@ -81,6 +82,16 @@ static unsigned long elf_hash(const char *name)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t gnu_hash(const char *name)
|
||||||
|
{
|
||||||
|
const unsigned char *s = (void *)name;
|
||||||
|
uint32_t h = 5381;
|
||||||
|
|
||||||
|
for (; *s; s++)
|
||||||
|
h += h * 32 + *s;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
void vdso_init_from_sysinfo_ehdr(uintptr_t base)
|
void vdso_init_from_sysinfo_ehdr(uintptr_t base)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -123,6 +134,7 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
|
|||||||
*/
|
*/
|
||||||
ELF_HASH_ENTRY *hash = 0;
|
ELF_HASH_ENTRY *hash = 0;
|
||||||
vdso_info.symstrings = 0;
|
vdso_info.symstrings = 0;
|
||||||
|
vdso_info.gnu_hash = 0;
|
||||||
vdso_info.symtab = 0;
|
vdso_info.symtab = 0;
|
||||||
vdso_info.versym = 0;
|
vdso_info.versym = 0;
|
||||||
vdso_info.verdef = 0;
|
vdso_info.verdef = 0;
|
||||||
@ -143,6 +155,11 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
|
|||||||
((uintptr_t)dyn[i].d_un.d_ptr
|
((uintptr_t)dyn[i].d_un.d_ptr
|
||||||
+ vdso_info.load_offset);
|
+ vdso_info.load_offset);
|
||||||
break;
|
break;
|
||||||
|
case DT_GNU_HASH:
|
||||||
|
vdso_info.gnu_hash =
|
||||||
|
(ELF(Word) *)((uintptr_t)dyn[i].d_un.d_ptr +
|
||||||
|
vdso_info.load_offset);
|
||||||
|
break;
|
||||||
case DT_VERSYM:
|
case DT_VERSYM:
|
||||||
vdso_info.versym = (ELF(Versym) *)
|
vdso_info.versym = (ELF(Versym) *)
|
||||||
((uintptr_t)dyn[i].d_un.d_ptr
|
((uintptr_t)dyn[i].d_un.d_ptr
|
||||||
@ -155,17 +172,27 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!vdso_info.symstrings || !vdso_info.symtab || !hash)
|
if (!vdso_info.symstrings || !vdso_info.symtab ||
|
||||||
|
(!hash && !vdso_info.gnu_hash))
|
||||||
return; /* Failed */
|
return; /* Failed */
|
||||||
|
|
||||||
if (!vdso_info.verdef)
|
if (!vdso_info.verdef)
|
||||||
vdso_info.versym = 0;
|
vdso_info.versym = 0;
|
||||||
|
|
||||||
/* Parse the hash table header. */
|
/* Parse the hash table header. */
|
||||||
|
if (vdso_info.gnu_hash) {
|
||||||
|
vdso_info.nbucket = vdso_info.gnu_hash[0];
|
||||||
|
/* The bucket array is located after the header (4 uint32) and the bloom
|
||||||
|
* filter (size_t array of gnu_hash[2] elements).
|
||||||
|
*/
|
||||||
|
vdso_info.bucket = vdso_info.gnu_hash + 4 +
|
||||||
|
sizeof(size_t) / 4 * vdso_info.gnu_hash[2];
|
||||||
|
} else {
|
||||||
vdso_info.nbucket = hash[0];
|
vdso_info.nbucket = hash[0];
|
||||||
vdso_info.nchain = hash[1];
|
vdso_info.nchain = hash[1];
|
||||||
vdso_info.bucket = &hash[2];
|
vdso_info.bucket = &hash[2];
|
||||||
vdso_info.chain = &hash[vdso_info.nbucket + 2];
|
vdso_info.chain = &hash[vdso_info.nbucket + 2];
|
||||||
|
}
|
||||||
|
|
||||||
/* That's all we need. */
|
/* That's all we need. */
|
||||||
vdso_info.valid = true;
|
vdso_info.valid = true;
|
||||||
@ -209,6 +236,26 @@ static bool vdso_match_version(ELF(Versym) ver,
|
|||||||
&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
|
&& !strcmp(name, vdso_info.symstrings + aux->vda_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool check_sym(ELF(Sym) *sym, ELF(Word) i, const char *name,
|
||||||
|
const char *version, unsigned long ver_hash)
|
||||||
|
{
|
||||||
|
/* Check for a defined global or weak function w/ right name. */
|
||||||
|
if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
|
||||||
|
return false;
|
||||||
|
if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
|
||||||
|
ELF64_ST_BIND(sym->st_info) != STB_WEAK)
|
||||||
|
return false;
|
||||||
|
if (strcmp(name, vdso_info.symstrings + sym->st_name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Check symbol version. */
|
||||||
|
if (vdso_info.versym &&
|
||||||
|
!vdso_match_version(vdso_info.versym[i], version, ver_hash))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void *vdso_sym(const char *version, const char *name)
|
void *vdso_sym(const char *version, const char *name)
|
||||||
{
|
{
|
||||||
unsigned long ver_hash;
|
unsigned long ver_hash;
|
||||||
@ -216,29 +263,36 @@ void *vdso_sym(const char *version, const char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ver_hash = elf_hash(version);
|
ver_hash = elf_hash(version);
|
||||||
ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
|
ELF(Word) i;
|
||||||
|
|
||||||
for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
|
if (vdso_info.gnu_hash) {
|
||||||
ELF(Sym) *sym = &vdso_info.symtab[chain];
|
uint32_t h1 = gnu_hash(name), h2, *hashval;
|
||||||
|
|
||||||
/* Check for a defined global or weak function w/ right name. */
|
i = vdso_info.bucket[h1 % vdso_info.nbucket];
|
||||||
if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
|
if (i == 0)
|
||||||
continue;
|
return 0;
|
||||||
if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
|
h1 |= 1;
|
||||||
ELF64_ST_BIND(sym->st_info) != STB_WEAK)
|
hashval = vdso_info.bucket + vdso_info.nbucket +
|
||||||
continue;
|
(i - vdso_info.gnu_hash[1]);
|
||||||
if (sym->st_shndx == SHN_UNDEF)
|
for (;; i++) {
|
||||||
continue;
|
ELF(Sym) *sym = &vdso_info.symtab[i];
|
||||||
if (strcmp(name, vdso_info.symstrings + sym->st_name))
|
h2 = *hashval++;
|
||||||
continue;
|
if (h1 == (h2 | 1) &&
|
||||||
|
check_sym(sym, i, name, version, ver_hash))
|
||||||
/* Check symbol version. */
|
return (void *)(vdso_info.load_offset +
|
||||||
if (vdso_info.versym
|
sym->st_value);
|
||||||
&& !vdso_match_version(vdso_info.versym[chain],
|
if (h2 & 1)
|
||||||
version, ver_hash))
|
break;
|
||||||
continue;
|
}
|
||||||
|
} else {
|
||||||
return (void *)(vdso_info.load_offset + sym->st_value);
|
i = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
|
||||||
|
for (; i; i = vdso_info.chain[i]) {
|
||||||
|
ELF(Sym) *sym = &vdso_info.symtab[i];
|
||||||
|
if (sym->st_shndx != SHN_UNDEF &&
|
||||||
|
check_sym(sym, i, name, version, ver_hash))
|
||||||
|
return (void *)(vdso_info.load_offset +
|
||||||
|
sym->st_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
2
tools/testing/selftests/zram/.gitignore
vendored
Normal file
2
tools/testing/selftests/zram/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
err.log
|
Loading…
Reference in New Issue
Block a user