Demonstrate pointer injection

This exercise demonstrates how CHERI's pointer provenance validity prevents injected pointer values from being dereferenced. In this example code, a pointer is injected via pipe IPC, and then dereferenced.

  1. Compile long-over-pipe.c with a RISC-V target and a binary name of long-over-pipe-riscv, and with a CHERI-RISC-V target and a binary name of long-over-pipe-cheri.
/*
 * SPDX-License-Identifier: BSD-2-Clause-DARPA-SSITH-ECATS-HR0011-18-C-0016
 * Copyright (c) 2020 SRI International
 */
#include <err.h>
#include <stdio.h>
#include <unistd.h>

int
main(void)
{
	int fds[2];
	pid_t pid;
	long val;

	if (pipe(fds) == -1)
		err(1, "pipe");
	if ((pid = fork()) == -1)
		err(1, "fork");
	if (pid == 0) {
		val = 42;
		if (write(fds[0], &val, sizeof(val)) != sizeof(val))
			err(1, "write");
	} else {
		if (read(fds[1], &val, sizeof(val)) != sizeof(val))
			err(1, "read");
		printf("received %ld\n", val);
	}

	return 0;
}
  1. Run the two binaries, which both send long integers over pipe IPC, and print the sent and received values.
  2. Compile ptr-over-pipe.c with a RISC-V target and a binary name of ptr-over-pipe-riscv, and with a CHERI-RISC-V target and a binary name of ptr-over-pipe-cheri.
/*
 * SPDX-License-Identifier: BSD-2-Clause-DARPA-SSITH-ECATS-HR0011-18-C-0016
 * Copyright (c) 2020 SRI International
 */
#include <err.h>
#include <stdio.h>
#include <unistd.h>

const char hello[] = "Hello world!";

int
main(void)
{
	int fds[2];
	pid_t pid;
	const char *ptr;

	if (pipe(fds) == -1)
		err(1, "pipe");
	if ((pid = fork()) == -1)
		err(1, "fork");
	if (pid == 0) {
		ptr = hello;
		if (write(fds[0], &ptr, sizeof(ptr)) != sizeof(ptr))
			err(1, "write");
	} else {
		if (read(fds[1], &ptr, sizeof(ptr)) != sizeof(ptr))
			err(1, "read");
		printf("received %s\n", ptr);
	}

	return 0;
}
  1. Run the two binaries, which both send pointers over pipe IPC, and then dereference the received copy to print a string.
  2. Why does dereferencing the received pointer in a CHERI binary fail?