OSDN Git Service

Merge tag 'linux-kselftest-4.8-rc1-update' of git://git.kernel.org/pub/scm/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Aug 2016 20:52:08 +0000 (16:52 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Aug 2016 20:52:08 +0000 (16:52 -0400)
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

tools/testing/selftests/lib/printf.sh [changed mode: 0644->0755]
tools/testing/selftests/media_tests/.gitignore
tools/testing/selftests/media_tests/Makefile
tools/testing/selftests/media_tests/bind_unbind_sample.sh [new file with mode: 0755]
tools/testing/selftests/media_tests/media_device_open.c [new file with mode: 0644]
tools/testing/selftests/media_tests/media_device_test.c
tools/testing/selftests/media_tests/open_loop_test.sh [new file with mode: 0755]
tools/testing/selftests/media_tests/regression_test.txt [new file with mode: 0644]
tools/testing/selftests/media_tests/video_device_test.c [new file with mode: 0644]
tools/testing/selftests/vm/compaction_test.c
tools/testing/selftests/vm/on-fault-limit.c

old mode 100644 (file)
new mode 100755 (executable)
index 7071bcc..6b34a01 100644 (file)
@@ -1,7 +1,7 @@
-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
diff --git a/tools/testing/selftests/media_tests/bind_unbind_sample.sh b/tools/testing/selftests/media_tests/bind_unbind_sample.sh
new file mode 100755 (executable)
index 0000000..9f362f1
--- /dev/null
@@ -0,0 +1,12 @@
+#!/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
diff --git a/tools/testing/selftests/media_tests/media_device_open.c b/tools/testing/selftests/media_tests/media_device_open.c
new file mode 100644 (file)
index 0000000..44343c0
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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);
+}
index cbf53a0..5d49943 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
 #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--;
        }
 }
diff --git a/tools/testing/selftests/media_tests/open_loop_test.sh b/tools/testing/selftests/media_tests/open_loop_test.sh
new file mode 100755 (executable)
index 0000000..dcd3c17
--- /dev/null
@@ -0,0 +1,10 @@
+#!/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
diff --git a/tools/testing/selftests/media_tests/regression_test.txt b/tools/testing/selftests/media_tests/regression_test.txt
new file mode 100644 (file)
index 0000000..2627367
--- /dev/null
@@ -0,0 +1,43 @@
+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.
diff --git a/tools/testing/selftests/media_tests/video_device_test.c b/tools/testing/selftests/media_tests/video_device_test.c
new file mode 100644 (file)
index 0000000..66d419c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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--;
+       }
+}
index 00c4f65..6d1437f 100644 (file)
@@ -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 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;
        }
 
index 245accc..0ae458f 100644 (file)
@@ -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;
        }