faf29cf04baa695e33cd00d939e1c3a5cc9a78fb
[linux-2.6-microblaze.git] / drivers / misc / lkdtm / fortify.c
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_warn("FAIL: No overflow in above strscpy()\n");
80
81         kfree(src);
82 }