0001
0002
0003
0004
0005
0006
0007 #include "lkdtm.h"
0008 #include <linux/string.h>
0009 #include <linux/slab.h>
0010
0011 static volatile int fortify_scratch_space;
0012
0013 static void lkdtm_FORTIFIED_OBJECT(void)
0014 {
0015 struct target {
0016 char a[10];
0017 } target[2] = {};
0018
0019
0020
0021
0022
0023 volatile int size = 11;
0024
0025 pr_info("trying to read past the end of a struct\n");
0026
0027
0028 fortify_scratch_space = memcmp(&target[0], &target[1], size);
0029
0030 pr_err("FAIL: fortify did not block an object overread!\n");
0031 pr_expected_config(CONFIG_FORTIFY_SOURCE);
0032 }
0033
0034 static void lkdtm_FORTIFIED_SUBOBJECT(void)
0035 {
0036 struct target {
0037 char a[10];
0038 char b[10];
0039 } target;
0040 volatile int size = 20;
0041 char *src;
0042
0043 src = kmalloc(size, GFP_KERNEL);
0044 strscpy(src, "over ten bytes", size);
0045 size = strlen(src) + 1;
0046
0047 pr_info("trying to strncpy past the end of a member of a struct\n");
0048
0049
0050
0051
0052
0053
0054 strncpy(target.a, src, size);
0055
0056
0057 fortify_scratch_space = target.a[3];
0058
0059 pr_err("FAIL: fortify did not block an sub-object overrun!\n");
0060 pr_expected_config(CONFIG_FORTIFY_SOURCE);
0061
0062 kfree(src);
0063 }
0064
0065
0066
0067
0068
0069
0070 static void lkdtm_FORTIFIED_STRSCPY(void)
0071 {
0072 char *src;
0073 char dst[5];
0074
0075 struct {
0076 union {
0077 char big[10];
0078 char src[5];
0079 };
0080 } weird = { .big = "hello!" };
0081 char weird_dst[sizeof(weird.src) + 1];
0082
0083 src = kstrdup("foobar", GFP_KERNEL);
0084
0085 if (src == NULL)
0086 return;
0087
0088
0089 if (strscpy(dst, src, 0) != -E2BIG)
0090 pr_warn("FAIL: strscpy() of 0 length did not return -E2BIG\n");
0091
0092
0093 if (strscpy(dst, src, sizeof(dst)) != -E2BIG)
0094 pr_warn("FAIL: strscpy() did not return -E2BIG while src is truncated\n");
0095
0096
0097 if (strncmp(dst, "foob", sizeof(dst)) != 0)
0098 pr_warn("FAIL: after strscpy() dst does not contain \"foob\" but \"%s\"\n",
0099 dst);
0100
0101
0102 src[3] = '\0';
0103
0104
0105
0106
0107
0108 if (strscpy(dst, src, sizeof(dst)) != 3)
0109 pr_warn("FAIL: strscpy() did not return 3 while src was copied entirely truncated\n");
0110
0111
0112 if (strncmp(dst, "foo", sizeof(dst)) != 0)
0113 pr_warn("FAIL: after strscpy() dst does not contain \"foo\" but \"%s\"\n",
0114 dst);
0115
0116
0117 strscpy(weird_dst, weird.src, sizeof(weird_dst));
0118
0119 if (strcmp(weird_dst, "hello") != 0)
0120 pr_warn("FAIL: after strscpy() weird_dst does not contain \"hello\" but \"%s\"\n",
0121 weird_dst);
0122
0123
0124 src[3] = 'b';
0125
0126
0127
0128
0129
0130 strscpy(dst, src, strlen(src));
0131
0132 pr_err("FAIL: strscpy() overflow not detected!\n");
0133 pr_expected_config(CONFIG_FORTIFY_SOURCE);
0134
0135 kfree(src);
0136 }
0137
0138 static struct crashtype crashtypes[] = {
0139 CRASHTYPE(FORTIFIED_OBJECT),
0140 CRASHTYPE(FORTIFIED_SUBOBJECT),
0141 CRASHTYPE(FORTIFIED_STRSCPY),
0142 };
0143
0144 struct crashtype_category fortify_crashtypes = {
0145 .crashtypes = crashtypes,
0146 .len = ARRAY_SIZE(crashtypes),
0147 };