1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2019 Google LLC
4*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2021 Joerg Vehlow <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker */
6*49cdfc7eSAndroid Build Coastguard Worker
7*49cdfc7eSAndroid Build Coastguard Worker /*
8*49cdfc7eSAndroid Build Coastguard Worker * Regression test for kernel commit 21d4120ec6f5 ("crypto: user - prevent
9*49cdfc7eSAndroid Build Coastguard Worker * operating on larval algorithms"). See the commit message for a detailed
10*49cdfc7eSAndroid Build Coastguard Worker * explanation of the problem. Basically, this test tries to cause a NULL
11*49cdfc7eSAndroid Build Coastguard Worker * pointer dereference in the kernel by abusing the CRYPTO_MSG_DELALG message in
12*49cdfc7eSAndroid Build Coastguard Worker * the NETLINK_CRYPTO interface to try to delete a "larval" algorithm, which is
13*49cdfc7eSAndroid Build Coastguard Worker * a kernel-internal marker for an algorithm which has been registered but isn't
14*49cdfc7eSAndroid Build Coastguard Worker * ready yet (e.g., hasn't completed the in-kernel crypto self-tests yet).
15*49cdfc7eSAndroid Build Coastguard Worker *
16*49cdfc7eSAndroid Build Coastguard Worker * CRYPTO_MSG_NEWALG will create such a larval algorithm. However, it waits
17*49cdfc7eSAndroid Build Coastguard Worker * (killably) for the larval to mature before returning, and it holds a lock
18*49cdfc7eSAndroid Build Coastguard Worker * that prevents CRYPTO_MSG_DELALG from running. To get around this, this test
19*49cdfc7eSAndroid Build Coastguard Worker * sends a fatal signal to the process executing CRYPTO_MSG_NEWALG.
20*49cdfc7eSAndroid Build Coastguard Worker */
21*49cdfc7eSAndroid Build Coastguard Worker
22*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
23*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
25*49cdfc7eSAndroid Build Coastguard Worker
26*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
27*49cdfc7eSAndroid Build Coastguard Worker #include "tst_crypto.h"
28*49cdfc7eSAndroid Build Coastguard Worker #include "tst_timer.h"
29*49cdfc7eSAndroid Build Coastguard Worker
30*49cdfc7eSAndroid Build Coastguard Worker /*
31*49cdfc7eSAndroid Build Coastguard Worker * List of possible algorithms to use try (not exhaustive).
32*49cdfc7eSAndroid Build Coastguard Worker * The algorithm has to be valid (i.e. the drivers must exists
33*49cdfc7eSAndroid Build Coastguard Worker * and be a valid combination) and it has to be deleteable.
34*49cdfc7eSAndroid Build Coastguard Worker * To be deletable it cannot be used by someone else.
35*49cdfc7eSAndroid Build Coastguard Worker * The first algorithm, that fullfils the criteria is used for the test.
36*49cdfc7eSAndroid Build Coastguard Worker */
37*49cdfc7eSAndroid Build Coastguard Worker static const char * const ALGORITHM_CANDIDATES[] = {
38*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha1-generic)",
39*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha224-generic)",
40*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha256-generic)",
41*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha384-generic)",
42*49cdfc7eSAndroid Build Coastguard Worker "hmac(md5-generic)",
43*49cdfc7eSAndroid Build Coastguard Worker "hmac(sm3-generic)",
44*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha512-generic)",
45*49cdfc7eSAndroid Build Coastguard Worker "hmac(rmd160-generic)",
46*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha3-224-generic)",
47*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha3-256-generic)",
48*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha3-384-generic)",
49*49cdfc7eSAndroid Build Coastguard Worker "hmac(sha3-512-generic)",
50*49cdfc7eSAndroid Build Coastguard Worker "hmac(streebog256-generic)",
51*49cdfc7eSAndroid Build Coastguard Worker "hmac(streebog512-generic)"
52*49cdfc7eSAndroid Build Coastguard Worker };
53*49cdfc7eSAndroid Build Coastguard Worker
54*49cdfc7eSAndroid Build Coastguard Worker static const char* algorithm = NULL;
55*49cdfc7eSAndroid Build Coastguard Worker static struct tst_netlink_context *ctx;
56*49cdfc7eSAndroid Build Coastguard Worker
57*49cdfc7eSAndroid Build Coastguard Worker
setup(void)58*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
59*49cdfc7eSAndroid Build Coastguard Worker {
60*49cdfc7eSAndroid Build Coastguard Worker int rc;
61*49cdfc7eSAndroid Build Coastguard Worker unsigned i;
62*49cdfc7eSAndroid Build Coastguard Worker struct crypto_user_alg alg;
63*49cdfc7eSAndroid Build Coastguard Worker
64*49cdfc7eSAndroid Build Coastguard Worker ctx = NETLINK_CREATE_CONTEXT(NETLINK_CRYPTO);
65*49cdfc7eSAndroid Build Coastguard Worker
66*49cdfc7eSAndroid Build Coastguard Worker /* find an algorithm, that is not in use */
67*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(ALGORITHM_CANDIDATES); ++i) {
68*49cdfc7eSAndroid Build Coastguard Worker memset(&alg, 0, sizeof(alg));
69*49cdfc7eSAndroid Build Coastguard Worker strcpy(alg.cru_driver_name, ALGORITHM_CANDIDATES[i]);
70*49cdfc7eSAndroid Build Coastguard Worker
71*49cdfc7eSAndroid Build Coastguard Worker /* try to add it, to see if it is valid */
72*49cdfc7eSAndroid Build Coastguard Worker rc = tst_crypto_add_alg(ctx, &alg);
73*49cdfc7eSAndroid Build Coastguard Worker if (rc != 0)
74*49cdfc7eSAndroid Build Coastguard Worker continue;
75*49cdfc7eSAndroid Build Coastguard Worker
76*49cdfc7eSAndroid Build Coastguard Worker /* it also has to be deletable */
77*49cdfc7eSAndroid Build Coastguard Worker rc = tst_crypto_del_alg(ctx, &alg, 1000);
78*49cdfc7eSAndroid Build Coastguard Worker if (rc == 0) {
79*49cdfc7eSAndroid Build Coastguard Worker algorithm = ALGORITHM_CANDIDATES[i];
80*49cdfc7eSAndroid Build Coastguard Worker break;
81*49cdfc7eSAndroid Build Coastguard Worker }
82*49cdfc7eSAndroid Build Coastguard Worker }
83*49cdfc7eSAndroid Build Coastguard Worker
84*49cdfc7eSAndroid Build Coastguard Worker if (!algorithm)
85*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "No viable algorithm found");
86*49cdfc7eSAndroid Build Coastguard Worker }
87*49cdfc7eSAndroid Build Coastguard Worker
run(void)88*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
89*49cdfc7eSAndroid Build Coastguard Worker {
90*49cdfc7eSAndroid Build Coastguard Worker struct crypto_user_alg alg = {};
91*49cdfc7eSAndroid Build Coastguard Worker pid_t pid;
92*49cdfc7eSAndroid Build Coastguard Worker int status;
93*49cdfc7eSAndroid Build Coastguard Worker
94*49cdfc7eSAndroid Build Coastguard Worker strcpy(alg.cru_driver_name, algorithm);
95*49cdfc7eSAndroid Build Coastguard Worker
96*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO,
97*49cdfc7eSAndroid Build Coastguard Worker "Starting crypto_user larval deletion test using algorithm %s. May crash buggy kernels.",
98*49cdfc7eSAndroid Build Coastguard Worker algorithm);
99*49cdfc7eSAndroid Build Coastguard Worker
100*49cdfc7eSAndroid Build Coastguard Worker tst_timer_start(CLOCK_MONOTONIC);
101*49cdfc7eSAndroid Build Coastguard Worker
102*49cdfc7eSAndroid Build Coastguard Worker while (!tst_timer_expired_ms(1000)) {
103*49cdfc7eSAndroid Build Coastguard Worker pid = SAFE_FORK();
104*49cdfc7eSAndroid Build Coastguard Worker
105*49cdfc7eSAndroid Build Coastguard Worker if (pid == 0) {
106*49cdfc7eSAndroid Build Coastguard Worker /* Child process: execute CRYPTO_MSG_NEWALG. */
107*49cdfc7eSAndroid Build Coastguard Worker ctx = NETLINK_CREATE_CONTEXT(NETLINK_CRYPTO);
108*49cdfc7eSAndroid Build Coastguard Worker for (;;) {
109*49cdfc7eSAndroid Build Coastguard Worker TEST(tst_crypto_add_alg(ctx, &alg));
110*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET && TST_RET != -EEXIST)
111*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TRERRNO,
112*49cdfc7eSAndroid Build Coastguard Worker "unexpected error from tst_crypto_add_alg()");
113*49cdfc7eSAndroid Build Coastguard Worker }
114*49cdfc7eSAndroid Build Coastguard Worker }
115*49cdfc7eSAndroid Build Coastguard Worker
116*49cdfc7eSAndroid Build Coastguard Worker /*
117*49cdfc7eSAndroid Build Coastguard Worker * Parent process: kill the child process (hopefully while it's
118*49cdfc7eSAndroid Build Coastguard Worker * executing CRYPTO_MSG_NEWALG) and execute CRYPTO_MSG_DELALG.
119*49cdfc7eSAndroid Build Coastguard Worker * Buggy kernels sometimes dereferenced a NULL pointer during
120*49cdfc7eSAndroid Build Coastguard Worker * CRYPTO_MSG_DELALG here.
121*49cdfc7eSAndroid Build Coastguard Worker */
122*49cdfc7eSAndroid Build Coastguard Worker usleep(rand() % 5000);
123*49cdfc7eSAndroid Build Coastguard Worker kill(pid, SIGKILL);
124*49cdfc7eSAndroid Build Coastguard Worker SAFE_WAIT(&status);
125*49cdfc7eSAndroid Build Coastguard Worker if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL)
126*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "child %s", tst_strstatus(status));
127*49cdfc7eSAndroid Build Coastguard Worker TEST(tst_crypto_del_alg(ctx, &alg, 1000));
128*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET && TST_RET != -ENOENT)
129*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TRERRNO,
130*49cdfc7eSAndroid Build Coastguard Worker "unexpected error from tst_crypto_del_alg()");
131*49cdfc7eSAndroid Build Coastguard Worker }
132*49cdfc7eSAndroid Build Coastguard Worker
133*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "didn't crash");
134*49cdfc7eSAndroid Build Coastguard Worker }
135*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)136*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
137*49cdfc7eSAndroid Build Coastguard Worker {
138*49cdfc7eSAndroid Build Coastguard Worker NETLINK_DESTROY_CONTEXT(ctx);
139*49cdfc7eSAndroid Build Coastguard Worker }
140*49cdfc7eSAndroid Build Coastguard Worker
141*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
142*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
143*49cdfc7eSAndroid Build Coastguard Worker .test_all = run,
144*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
145*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
146*49cdfc7eSAndroid Build Coastguard Worker .forks_child = 1,
147*49cdfc7eSAndroid Build Coastguard Worker .tags = (const struct tst_tag[]) {
148*49cdfc7eSAndroid Build Coastguard Worker {"linux-git", "21d4120ec6f5"},
149*49cdfc7eSAndroid Build Coastguard Worker {}
150*49cdfc7eSAndroid Build Coastguard Worker }
151*49cdfc7eSAndroid Build Coastguard Worker };
152