Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib: Add test module for strscpy_pad

Add a test module for the new strscpy_pad() function. Tie it into the
kselftest infrastructure for lib/ tests.

Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Tobin C. Harding <tobin@kernel.org>
Signed-off-by: Shuah Khan <shuah@kernel.org>

authored by

Tobin C. Harding and committed by
Shuah Khan
0b0600c8 458a3bf8

+159 -1
+3
lib/Kconfig.debug
··· 1769 1769 config TEST_STRING_HELPERS 1770 1770 tristate "Test functions located in the string_helpers module at runtime" 1771 1771 1772 + config TEST_STRSCPY 1773 + tristate "Test strscpy*() family of functions at runtime" 1774 + 1772 1775 config TEST_KSTRTOX 1773 1776 tristate "Test kstrto*() family of functions at runtime" 1774 1777
+1
lib/Makefile
··· 70 70 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o 71 71 obj-$(CONFIG_TEST_PRINTF) += test_printf.o 72 72 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o 73 + obj-$(CONFIG_TEST_STRSCPY) += test_strscpy.o 73 74 obj-$(CONFIG_TEST_BITFIELD) += test_bitfield.o 74 75 obj-$(CONFIG_TEST_UUID) += test_uuid.o 75 76 obj-$(CONFIG_TEST_XARRAY) += test_xarray.o
+150
lib/test_strscpy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + 3 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 4 + 5 + #include <linux/string.h> 6 + 7 + #include "../tools/testing/selftests/kselftest_module.h" 8 + 9 + /* 10 + * Kernel module for testing 'strscpy' family of functions. 11 + */ 12 + 13 + KSTM_MODULE_GLOBALS(); 14 + 15 + /* 16 + * tc() - Run a specific test case. 17 + * @src: Source string, argument to strscpy_pad() 18 + * @count: Size of destination buffer, argument to strscpy_pad() 19 + * @expected: Expected return value from call to strscpy_pad() 20 + * @terminator: 1 if there should be a terminating null byte 0 otherwise. 21 + * @chars: Number of characters from the src string expected to be 22 + * written to the dst buffer. 23 + * @pad: Number of pad characters expected (in the tail of dst buffer). 24 + * (@pad does not include the null terminator byte.) 25 + * 26 + * Calls strscpy_pad() and verifies the return value and state of the 27 + * destination buffer after the call returns. 28 + */ 29 + static int __init tc(char *src, int count, int expected, 30 + int chars, int terminator, int pad) 31 + { 32 + int nr_bytes_poison; 33 + int max_expected; 34 + int max_count; 35 + int written; 36 + char buf[6]; 37 + int index, i; 38 + const char POISON = 'z'; 39 + 40 + total_tests++; 41 + 42 + if (!src) { 43 + pr_err("null source string not supported\n"); 44 + return -1; 45 + } 46 + 47 + memset(buf, POISON, sizeof(buf)); 48 + /* Future proofing test suite, validate args */ 49 + max_count = sizeof(buf) - 2; /* Space for null and to verify overflow */ 50 + max_expected = count - 1; /* Space for the null */ 51 + if (count > max_count) { 52 + pr_err("count (%d) is too big (%d) ... aborting", count, max_count); 53 + return -1; 54 + } 55 + if (expected > max_expected) { 56 + pr_warn("expected (%d) is bigger than can possibly be returned (%d)", 57 + expected, max_expected); 58 + } 59 + 60 + written = strscpy_pad(buf, src, count); 61 + if ((written) != (expected)) { 62 + pr_err("%d != %d (written, expected)\n", written, expected); 63 + goto fail; 64 + } 65 + 66 + if (count && written == -E2BIG) { 67 + if (strncmp(buf, src, count - 1) != 0) { 68 + pr_err("buffer state invalid for -E2BIG\n"); 69 + goto fail; 70 + } 71 + if (buf[count - 1] != '\0') { 72 + pr_err("too big string is not null terminated correctly\n"); 73 + goto fail; 74 + } 75 + } 76 + 77 + for (i = 0; i < chars; i++) { 78 + if (buf[i] != src[i]) { 79 + pr_err("buf[i]==%c != src[i]==%c\n", buf[i], src[i]); 80 + goto fail; 81 + } 82 + } 83 + 84 + if (terminator) { 85 + if (buf[count - 1] != '\0') { 86 + pr_err("string is not null terminated correctly\n"); 87 + goto fail; 88 + } 89 + } 90 + 91 + for (i = 0; i < pad; i++) { 92 + index = chars + terminator + i; 93 + if (buf[index] != '\0') { 94 + pr_err("padding missing at index: %d\n", i); 95 + goto fail; 96 + } 97 + } 98 + 99 + nr_bytes_poison = sizeof(buf) - chars - terminator - pad; 100 + for (i = 0; i < nr_bytes_poison; i++) { 101 + index = sizeof(buf) - 1 - i; /* Check from the end back */ 102 + if (buf[index] != POISON) { 103 + pr_err("poison value missing at index: %d\n", i); 104 + goto fail; 105 + } 106 + } 107 + 108 + return 0; 109 + fail: 110 + failed_tests++; 111 + return -1; 112 + } 113 + 114 + static void __init selftest(void) 115 + { 116 + /* 117 + * tc() uses a destination buffer of size 6 and needs at 118 + * least 2 characters spare (one for null and one to check for 119 + * overflow). This means we should only call tc() with 120 + * strings up to a maximum of 4 characters long and 'count' 121 + * should not exceed 4. To test with longer strings increase 122 + * the buffer size in tc(). 123 + */ 124 + 125 + /* tc(src, count, expected, chars, terminator, pad) */ 126 + KSTM_CHECK_ZERO(tc("a", 0, -E2BIG, 0, 0, 0)); 127 + KSTM_CHECK_ZERO(tc("", 0, -E2BIG, 0, 0, 0)); 128 + 129 + KSTM_CHECK_ZERO(tc("a", 1, -E2BIG, 0, 1, 0)); 130 + KSTM_CHECK_ZERO(tc("", 1, 0, 0, 1, 0)); 131 + 132 + KSTM_CHECK_ZERO(tc("ab", 2, -E2BIG, 1, 1, 0)); 133 + KSTM_CHECK_ZERO(tc("a", 2, 1, 1, 1, 0)); 134 + KSTM_CHECK_ZERO(tc("", 2, 0, 0, 1, 1)); 135 + 136 + KSTM_CHECK_ZERO(tc("abc", 3, -E2BIG, 2, 1, 0)); 137 + KSTM_CHECK_ZERO(tc("ab", 3, 2, 2, 1, 0)); 138 + KSTM_CHECK_ZERO(tc("a", 3, 1, 1, 1, 1)); 139 + KSTM_CHECK_ZERO(tc("", 3, 0, 0, 1, 2)); 140 + 141 + KSTM_CHECK_ZERO(tc("abcd", 4, -E2BIG, 3, 1, 0)); 142 + KSTM_CHECK_ZERO(tc("abc", 4, 3, 3, 1, 0)); 143 + KSTM_CHECK_ZERO(tc("ab", 4, 2, 2, 1, 1)); 144 + KSTM_CHECK_ZERO(tc("a", 4, 1, 1, 1, 2)); 145 + KSTM_CHECK_ZERO(tc("", 4, 0, 0, 1, 3)); 146 + } 147 + 148 + KSTM_MODULE_LOADERS(test_strscpy); 149 + MODULE_AUTHOR("Tobin C. Harding <tobin@kernel.org>"); 150 + MODULE_LICENSE("GPL");
+1 -1
tools/testing/selftests/lib/Makefile
··· 3 3 # No binaries, but make sure arg-less "make" doesn't trigger "run_tests" 4 4 all: 5 5 6 - TEST_PROGS := printf.sh bitmap.sh prime_numbers.sh 6 + TEST_PROGS := printf.sh bitmap.sh prime_numbers.sh strscpy.sh 7 7 8 8 include ../lib.mk
+1
tools/testing/selftests/lib/config
··· 1 1 CONFIG_TEST_PRINTF=m 2 2 CONFIG_TEST_BITMAP=m 3 3 CONFIG_PRIME_NUMBERS=m 4 + CONFIG_TEST_STRSCPY=m
+3
tools/testing/selftests/lib/strscpy.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + $(dirname $0)/../kselftest_module.sh "strscpy*" test_strscpy