Home | History | Annotate | Download | only in keyctl
      1 /*
      2  * Copyright (c) 2017 Google, Inc.
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program, if not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 /*
     19  * Regression test for commit 63a0b0509e70 ("KEYS: fix freeing uninitialized
     20  * memory in key_update()").  Try to reproduce the crash in two different ways:
     21  *
     22  * 1. Try to update a key of a type that has a ->preparse() method but not an
     23  *    ->update() method.  Examples are the "asymmetric" and "dns_resolver" key
     24  *    types.  It crashes reliably for the "asymmetric" key type, since the
     25  *    "asymmetric" key type's ->free_preparse() method will dereference a
     26  *    pointer in the uninitialized memory, whereas other key types often just
     27  *    free a pointer which tends be NULL in practice, depending on how the stack
     28  *    is laid out.  However, to actually be able to add an "asymmetric" key, we
     29  *    need a specially-formatted payload and several kernel config options.  We
     30  *    do try it, but for completeness we also try the "dns_resolver" key type
     31  *    (though that's not guaranteed to be available either).
     32  *
     33  * 2. Race keyctl_update() with another task removing write permission from the
     34  *    key using keyctl_setperm().  This can cause a crash with almost any key
     35  *    type.  "user" is a good one to try, since it's always available if
     36  *    keyrings are supported at all.  However, depending on how the stack is
     37  *    laid out the crash may not actually occur.
     38  */
     39 
     40 #include <errno.h>
     41 #include <stdlib.h>
     42 
     43 #include "tst_test.h"
     44 #include "lapi/keyctl.h"
     45 
     46 /*
     47  * A valid payload for the "asymmetric" key type.  This is an x509 certificate
     48  * in DER format, generated using:
     49  *
     50  *	openssl req -x509 -newkey rsa:512 -batch -nodes -outform der \
     51  *		| ~/linux/scripts/bin2c
     52  */
     53 static const char x509_cert[] =
     54 	"\x30\x82\x01\xd3\x30\x82\x01\x7d\xa0\x03\x02\x01\x02\x02\x09\x00"
     55 	"\x92\x2a\x76\xff\x0c\x00\xfb\x9a\x30\x0d\x06\x09\x2a\x86\x48\x86"
     56 	"\xf7\x0d\x01\x01\x0b\x05\x00\x30\x45\x31\x0b\x30\x09\x06\x03\x55"
     57 	"\x04\x06\x13\x02\x41\x55\x31\x13\x30\x11\x06\x03\x55\x04\x08\x0c"
     58 	"\x0a\x53\x6f\x6d\x65\x2d\x53\x74\x61\x74\x65\x31\x21\x30\x1f\x06"
     59 	"\x03\x55\x04\x0a\x0c\x18\x49\x6e\x74\x65\x72\x6e\x65\x74\x20\x57"
     60 	"\x69\x64\x67\x69\x74\x73\x20\x50\x74\x79\x20\x4c\x74\x64\x30\x1e"
     61 	"\x17\x0d\x31\x37\x30\x37\x32\x38\x32\x31\x34\x31\x33\x34\x5a\x17"
     62 	"\x0d\x31\x37\x30\x38\x32\x37\x32\x31\x34\x31\x33\x34\x5a\x30\x45"
     63 	"\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x55\x31\x13\x30"
     64 	"\x11\x06\x03\x55\x04\x08\x0c\x0a\x53\x6f\x6d\x65\x2d\x53\x74\x61"
     65 	"\x74\x65\x31\x21\x30\x1f\x06\x03\x55\x04\x0a\x0c\x18\x49\x6e\x74"
     66 	"\x65\x72\x6e\x65\x74\x20\x57\x69\x64\x67\x69\x74\x73\x20\x50\x74"
     67 	"\x79\x20\x4c\x74\x64\x30\x5c\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7"
     68 	"\x0d\x01\x01\x01\x05\x00\x03\x4b\x00\x30\x48\x02\x41\x00\xde\x0b"
     69 	"\x1c\x24\xe2\x0d\xf8\x17\xf2\xc3\x6f\xc9\x72\x3e\x9d\xb0\x2d\x47"
     70 	"\xe4\xc4\x85\x87\xed\xde\x06\xe3\xf3\xe9\x4c\x35\x6c\xe4\xcb\x0e"
     71 	"\x44\x28\x23\x66\x76\xec\x4e\xdf\x10\x93\x92\x1e\x52\xfb\xdf\x5c"
     72 	"\x08\xe7\x24\x04\x66\xe3\x06\x05\x27\x56\xfb\x3e\x91\x31\x02\x03"
     73 	"\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16"
     74 	"\x04\x14\x6f\x39\x3a\x46\xdf\x29\x63\xde\x54\x7b\x6c\x31\x06\xd0"
     75 	"\x9f\x36\x16\xfb\x9c\xbf\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30"
     76 	"\x16\x80\x14\x6f\x39\x3a\x46\xdf\x29\x63\xde\x54\x7b\x6c\x31\x06"
     77 	"\xd0\x9f\x36\x16\xfb\x9c\xbf\x30\x0c\x06\x03\x55\x1d\x13\x04\x05"
     78 	"\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01"
     79 	"\x01\x0b\x05\x00\x03\x41\x00\x73\xf0\x4b\x62\x56\xed\xf0\x8b\x7e"
     80 	"\xc4\x75\x78\x98\xa2\x7a\x6e\x75\x1f\xde\x9b\xa0\xbe\x1a\x1f\x86"
     81 	"\x44\x13\xcd\x45\x06\x7f\x86\xde\xf6\x36\x4e\xb6\x15\xfa\xf5\xb0"
     82 	"\x34\xd2\x5e\x0b\xb3\x2c\x03\x5a\x5a\x28\x97\x5e\x7b\xdf\x63\x75"
     83 	"\x83\x8d\x69\xda\xd6\x59\xbd"
     84 	;
     85 
     86 static void new_session_keyring(void)
     87 {
     88 	TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL));
     89 	if (TST_RET < 0)
     90 		tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
     91 }
     92 
     93 static void test_update_nonupdatable(const char *type,
     94 				     const void *payload, size_t plen)
     95 {
     96 	key_serial_t keyid;
     97 
     98 	new_session_keyring();
     99 
    100 	TEST(add_key(type, "desc", payload, plen, KEY_SPEC_SESSION_KEYRING));
    101 	if (TST_RET < 0) {
    102 		if (TST_ERR == ENODEV) {
    103 			tst_res(TCONF, "kernel doesn't support key type '%s'",
    104 				type);
    105 			return;
    106 		}
    107 		if (TST_ERR == EBADMSG && !strcmp(type, "asymmetric")) {
    108 			tst_res(TCONF, "kernel is missing x509 cert parser "
    109 				"(CONFIG_X509_CERTIFICATE_PARSER)");
    110 			return;
    111 		}
    112 		if (TST_ERR == ENOENT && !strcmp(type, "asymmetric")) {
    113 			tst_res(TCONF, "kernel is missing crypto algorithms "
    114 				"needed to parse x509 cert (CONFIG_CRYPTO_RSA "
    115 				"and/or CONFIG_CRYPTO_SHA256)");
    116 			return;
    117 		}
    118 		tst_res(TBROK | TTERRNO, "unexpected error adding '%s' key",
    119 			type);
    120 		return;
    121 	}
    122 	keyid = TST_RET;
    123 
    124 	/*
    125 	 * Non-updatable keys don't start with write permission, so we must
    126 	 * explicitly grant it.
    127 	 */
    128 	TEST(keyctl(KEYCTL_SETPERM, keyid, KEY_POS_ALL));
    129 	if (TST_RET != 0) {
    130 		tst_res(TBROK | TTERRNO,
    131 			"failed to grant write permission to '%s' key", type);
    132 		return;
    133 	}
    134 
    135 	tst_res(TINFO, "Try to update the '%s' key...", type);
    136 	TEST(keyctl(KEYCTL_UPDATE, keyid, payload, plen));
    137 	if (TST_RET == 0) {
    138 		tst_res(TBROK,
    139 			"updating '%s' key unexpectedly succeeded", type);
    140 		return;
    141 	}
    142 	if (TST_ERR != EOPNOTSUPP) {
    143 		tst_res(TBROK | TTERRNO,
    144 			"updating '%s' key unexpectedly failed", type);
    145 		return;
    146 	}
    147 	tst_res(TPASS, "updating '%s' key expectedly failed with EOPNOTSUPP",
    148 		type);
    149 }
    150 
    151 /*
    152  * Try to update a key, racing with removing write permission.
    153  * This may crash buggy kernels.
    154  */
    155 static void test_update_setperm_race(void)
    156 {
    157 	static const char payload[] = "payload";
    158 	key_serial_t keyid;
    159 	int i;
    160 
    161 	new_session_keyring();
    162 
    163 	TEST(add_key("user", "desc", payload, sizeof(payload),
    164 		KEY_SPEC_SESSION_KEYRING));
    165 	if (TST_RET < 0) {
    166 		tst_res(TBROK | TTERRNO, "failed to add 'user' key");
    167 		return;
    168 	}
    169 	keyid = TST_RET;
    170 
    171 	if (SAFE_FORK() == 0) {
    172 		uint32_t perm = KEY_POS_ALL;
    173 
    174 		for (i = 0; i < 10000; i++) {
    175 			perm ^= KEY_POS_WRITE;
    176 			TEST(keyctl(KEYCTL_SETPERM, keyid, perm));
    177 			if (TST_RET != 0)
    178 				tst_brk(TBROK | TTERRNO, "setperm failed");
    179 		}
    180 		exit(0);
    181 	}
    182 
    183 	tst_res(TINFO, "Try to update the 'user' key...");
    184 	for (i = 0; i < 10000; i++) {
    185 		TEST(keyctl(KEYCTL_UPDATE, keyid, payload, sizeof(payload)));
    186 		if (TST_RET != 0 && TST_ERR != EACCES) {
    187 			tst_res(TBROK | TTERRNO, "failed to update 'user' key");
    188 			return;
    189 		}
    190 	}
    191 	tst_reap_children();
    192 	tst_res(TPASS, "didn't crash while racing to update 'user' key");
    193 }
    194 
    195 static void do_test(unsigned int i)
    196 {
    197 	/*
    198 	 * We need to pass check in dns_resolver_preparse(),
    199 	 * give it dummy server list request.
    200 	 */
    201 	static char dns_res_payload[] = { 0x00, 0x00, 0x01, 0xff, 0x00 };
    202 
    203 	switch (i) {
    204 	case 0:
    205 		test_update_nonupdatable("asymmetric",
    206 					 x509_cert, sizeof(x509_cert));
    207 		break;
    208 	case 1:
    209 		test_update_nonupdatable("dns_resolver", dns_res_payload,
    210 			sizeof(dns_res_payload));
    211 		break;
    212 	case 2:
    213 		test_update_setperm_race();
    214 		break;
    215 	}
    216 }
    217 
    218 static struct tst_test test = {
    219 	.tcnt = 3,
    220 	.test = do_test,
    221 	.forks_child = 1,
    222 };
    223