1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2020 Francis Laniel <laniel_francis@privacyrequired.com> 4 * 5 * Add tests related to fortified functions in this file. 6 */ 7 #include "lkdtm.h" 8 #include <linux/string.h> 9 #include <linux/slab.h> 10 11 12 /* 13 * Calls fortified strscpy to test that it returns the same result as vanilla 14 * strscpy and generate a panic because there is a write overflow (i.e. src 15 * length is greater than dst length). 16 */ 17 void lkdtm_FORTIFIED_STRSCPY(void) 18 { 19 char *src; 20 char dst[5]; 21 22 struct { 23 union { 24 char big[10]; 25 char src[5]; 26 }; 27 } weird = { .big = "hello!" }; 28 char weird_dst[sizeof(weird.src) + 1]; 29 30 src = kstrdup("foobar", GFP_KERNEL); 31 32 if (src == NULL) 33 return; 34 35 /* Vanilla strscpy returns -E2BIG if size is 0. */ 36 if (strscpy(dst, src, 0) != -E2BIG) 37 pr_warn("FAIL: strscpy() of 0 length did not return -E2BIG\n"); 38 39 /* Vanilla strscpy returns -E2BIG if src is truncated. */ 40 if (strscpy(dst, src, sizeof(dst)) != -E2BIG) 41 pr_warn("FAIL: strscpy() did not return -E2BIG while src is truncated\n"); 42 43 /* After above call, dst must contain "foob" because src was truncated. */ 44 if (strncmp(dst, "foob", sizeof(dst)) != 0) 45 pr_warn("FAIL: after strscpy() dst does not contain \"foob\" but \"%s\"\n", 46 dst); 47 48 /* Shrink src so the strscpy() below succeeds. */ 49 src[3] = '\0'; 50 51 /* 52 * Vanilla strscpy returns number of character copied if everything goes 53 * well. 54 */ 55 if (strscpy(dst, src, sizeof(dst)) != 3) 56 pr_warn("FAIL: strscpy() did not return 3 while src was copied entirely truncated\n"); 57 58 /* After above call, dst must contain "foo" because src was copied. */ 59 if (strncmp(dst, "foo", sizeof(dst)) != 0) 60 pr_warn("FAIL: after strscpy() dst does not contain \"foo\" but \"%s\"\n", 61 dst); 62 63 /* Test when src is embedded inside a union. */ 64 strscpy(weird_dst, weird.src, sizeof(weird_dst)); 65 66 if (strcmp(weird_dst, "hello") != 0) 67 pr_warn("FAIL: after strscpy() weird_dst does not contain \"hello\" but \"%s\"\n", 68 weird_dst); 69 70 /* Restore src to its initial value. */ 71 src[3] = 'b'; 72 73 /* 74 * Use strlen here so size cannot be known at compile time and there is 75 * a runtime write overflow. 76 */ 77 strscpy(dst, src, strlen(src)); 78 79 pr_err("FAIL: strscpy() overflow not detected!\n"); 80 pr_expected_config(CONFIG_FORTIFY_SOURCE); 81 82 kfree(src); 83 } 84