Commit 5dd0bf62 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux-kselftest-4.8-rc1-update' of...

Merge tag 'linux-kselftest-4.8-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kselftest updates from Shuah Khan:
 "This contains new tests and fixes:

   - a few fixes to existing tests

   - new media tests for testing driver unbind, and device removal paths
     while an user application is actively making system calls and
     ioctls"

* tag 'linux-kselftest-4.8-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  selftests: media_tests add a new video device test
  selftests: media_tests - Add media_device_open to .gitignore
  selftests: add media controller regression test scripts and document
  selftests: add media_device_open test
  selftests: media_device_test change it to randomize loop count
  selftests/vm: Don't mlockall MCL_CURRENT in on-fault-limit test
  selftests/vm: write strlen length instead of sizeof to nr_hugepages
  selftests/lib: set printf.sh executable
parents 1571a03d d78388db
File mode changed from 100644 to 100755
media_device_test
media_device_open
video_device_test
TEST_PROGS := media_device_test
TEST_PROGS := media_device_test media_device_open video_device_test
all: $(TEST_PROGS)
include ../lib.mk
clean:
rm -fr media_device_test
rm -fr media_device_test media_device_open video_device_test
#!/bin/bash
# Find device number in /sys/bus/usb/drivers/drivername
# Edit this file to update the driver numer and name
# Example test for uvcvideo driver
#i=0
# while :; do
# i=$((i+1))
# echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/unbind;
# echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/bind;
# clear
# echo $i
#done
/*
* media_device_open.c - Media Controller Device Open Test
*
* Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
*
* This file is released under the GPLv2.
*/
/*
* This file adds a test for Media Controller API.
* This test should be run as root and should not be
* included in the Kselftest run. This test should be
* run when hardware and driver that makes use Media
* Controller API are present in the system.
*
* This test opens user specified Media Device and calls
* MEDIA_IOC_DEVICE_INFO ioctl, closes the file, and exits.
*
* Usage:
* sudo ./media_device_open -d /dev/mediaX
*
* Run this test is a loop and run bind/unbind on the driver.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/media.h>
int main(int argc, char **argv)
{
int opt;
char media_device[256];
int count = 0;
struct media_device_info mdi;
int ret;
int fd;
if (argc < 2) {
printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]);
exit(-1);
}
/* Process arguments */
while ((opt = getopt(argc, argv, "d:")) != -1) {
switch (opt) {
case 'd':
strncpy(media_device, optarg, sizeof(media_device) - 1);
media_device[sizeof(media_device)-1] = '\0';
break;
default:
printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]);
exit(-1);
}
}
if (getuid() != 0) {
printf("Please run the test as root - Exiting.\n");
exit(-1);
}
/* Open Media device and keep it open */
fd = open(media_device, O_RDWR);
if (fd == -1) {
printf("Media Device open errno %s\n", strerror(errno));
exit(-1);
}
ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
if (ret < 0)
printf("Media Device Info errno %s\n", strerror(errno));
else
printf("Media device model %s driver %s\n",
mdi.model, mdi.driver);
}
/*
* media_devkref_test.c - Media Controller Device Kref API Test
* media_device_test.c - Media Controller Device ioctl loop Test
*
* Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
......@@ -35,13 +35,14 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <time.h>
#include <linux/media.h>
int main(int argc, char **argv)
{
int opt;
char media_device[256];
int count = 0;
int count;
struct media_device_info mdi;
int ret;
int fd;
......@@ -69,6 +70,10 @@ int main(int argc, char **argv)
exit(-1);
}
/* Generate random number of interations */
srand((unsigned int) time(NULL));
count = rand();
/* Open Media device and keep it open */
fd = open(media_device, O_RDWR);
if (fd == -1) {
......@@ -82,14 +87,16 @@ int main(int argc, char **argv)
"other Oops in the dmesg. Enable KaSan kernel\n"
"config option for use-after-free error detection.\n\n");
while (count < 100) {
printf("Running test for %d iternations\n", count);
while (count > 0) {
ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
if (ret < 0)
printf("Media Device Info errno %s\n", strerror(errno));
else
printf("Media device model %s driver %s\n",
mdi.model, mdi.driver);
printf("Media device model %s driver %s - count %d\n",
mdi.model, mdi.driver, count);
sleep(10);
count++;
count--;
}
}
#!/bin/bash
i=0
file=/dev/media$1
while :; do
echo $file
i=$((i+1))
R=$(./media_device_open -d $file);
# clear
echo -e "Loop $i\n$R"
done
Testing for regressions in Media Controller API register, ioctl, syscall,
and unregister paths. There have a few problems that result in user-after
free on media_device, media_devnode, and cdev pointers when the driver is
unbound while ioctl is in progress.
Test Procedure:
Run bin/unbind loop while ioctls are in progress.
Run rmmod and modprobe.
Disconnect the device.
Setup:
Build media_device_test
cd tools/testing/selftests/media_tests
make
Regressions test for cdev user-after free error on /dev/mediaX when driver
is unbound:
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
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
should stick around until this test exits.
The test for a random number of iterations or until user kills it with a
sleep 10 in between the ioctl calls.
sudo ./media_device_test -d /dev/mediaX
Regression test for media_devnode unregister race with ioctl_syscall:
Start 6 open_loop_test.sh tests with different /dev/mediaX files. When
device file goes away after unbind, device file name changes. Start the
test with possible device names. If we start with /dev/media0 for example,
after unbind, /dev/media1 or /dev/media2 could get created. The idea is
keep ioctls going while bind/unbind runs.
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
Run dmesg looking for any user-after free errors or mutex lock errors.
/*
* video_device_test - Video Device Test
*
* Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
*
* This file is released under the GPLv2.
*/
/*
* This file adds a test for Video Device. This test should not be included
* in the Kselftest run. This test should be run when hardware and driver
* that makes use of V4L2 API is present.
*
* This test opens user specified Video Device and calls video ioctls in a
* loop once every 10 seconds.
*
* Usage:
* sudo ./video_device_test -d /dev/videoX
*
* While test is running, remove the device or unbind the driver and
* ensure there are no use after free errors and other Oops in the
* dmesg.
* When possible, enable KaSan kernel config option for use-after-free
* error detection.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <time.h>
#include <linux/videodev2.h>
int main(int argc, char **argv)
{
int opt;
char video_dev[256];
int count;
struct v4l2_tuner vtuner;
struct v4l2_capability vcap;
int ret;
int fd;
if (argc < 2) {
printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
exit(-1);
}
/* Process arguments */
while ((opt = getopt(argc, argv, "d:")) != -1) {
switch (opt) {
case 'd':
strncpy(video_dev, optarg, sizeof(video_dev) - 1);
video_dev[sizeof(video_dev)-1] = '\0';
break;
default:
printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
exit(-1);
}
}
/* Generate random number of interations */
srand((unsigned int) time(NULL));
count = rand();
/* Open Video device and keep it open */
fd = open(video_dev, O_RDWR);
if (fd == -1) {
printf("Video Device open errno %s\n", strerror(errno));
exit(-1);
}
printf("\nNote:\n"
"While test is running, remove the device or unbind\n"
"driver and ensure there are no use after free errors\n"
"and other Oops in the dmesg. When possible, enable KaSan\n"
"kernel config option for use-after-free error detection.\n\n");
while (count > 0) {
ret = ioctl(fd, VIDIOC_QUERYCAP, &vcap);
if (ret < 0)
printf("VIDIOC_QUERYCAP errno %s\n", strerror(errno));
else
printf("Video device driver %s\n", vcap.driver);
ret = ioctl(fd, VIDIOC_G_TUNER, &vtuner);
if (ret < 0)
printf("VIDIOC_G_TUNER, errno %s\n", strerror(errno));
else
printf("type %d rangelow %d rangehigh %d\n",
vtuner.type, vtuner.rangelow, vtuner.rangehigh);
sleep(10);
count--;
}
}
......@@ -101,7 +101,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
/* Start with the initial condition of 0 huge pages*/
if (write(fd, "0", sizeof(char)) != sizeof(char)) {
perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
perror("Failed to write 0 to /proc/sys/vm/nr_hugepages\n");
goto close_fd;
}
......@@ -110,14 +110,14 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
/* Request a large number of huge pages. The Kernel will allocate
as much as it can */
if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) {
perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
perror("Failed to write 100000 to /proc/sys/vm/nr_hugepages\n");
goto close_fd;
}
lseek(fd, 0, SEEK_SET);
if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
perror("Failed to read from /proc/sys/vm/nr_hugepages\n");
perror("Failed to re-read from /proc/sys/vm/nr_hugepages\n");
goto close_fd;
}
......@@ -138,7 +138,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
!= strlen(initial_nr_hugepages)) {
perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
perror("Failed to write value to /proc/sys/vm/nr_hugepages\n");
goto close_fd;
}
......
......@@ -20,7 +20,7 @@ static int test_limit(void)
return ret;
}
if (mlockall(MCL_CURRENT | MCL_ONFAULT | MCL_FUTURE)) {
if (mlockall(MCL_ONFAULT | MCL_FUTURE)) {
perror("mlockall");
return ret;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment