Commit 03e54f10 authored by KP Singh's avatar KP Singh Committed by Daniel Borkmann
Browse files

bpf: lsm: Add selftests for BPF_PROG_TYPE_LSM



* Load/attach a BPF program that hooks to file_mprotect (int)
  and bprm_committed_creds (void).
* Perform an action that triggers the hook.
* Verify if the audit event was received using the shared global
  variables for the process executed.
* Verify if the mprotect returns a -EPERM.

Signed-off-by: default avatarKP Singh <kpsingh@google.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Reviewed-by: default avatarBrendan Jackman <jackmanb@google.com>
Reviewed-by: default avatarFlorent Revest <revest@google.com>
Reviewed-by: default avatarThomas Garnier <thgarnie@google.com>
Reviewed-by: default avatarJames Morris <jamorris@linux.microsoft.com>
Acked-by: default avatarAndrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200329004356.27286-8-kpsingh@chromium.org
parent 1e092a03
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -35,3 +35,5 @@ CONFIG_MPLS_ROUTING=m
CONFIG_MPLS_IPTUNNEL=m
CONFIG_IPV6_SIT=m
CONFIG_BPF_JIT=y
CONFIG_BPF_LSM=y
CONFIG_SECURITY=y
+86 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

/*
 * Copyright (C) 2020 Google LLC.
 */

#include <test_progs.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#include <malloc.h>
#include <stdlib.h>

#include "lsm.skel.h"

char *CMD_ARGS[] = {"true", NULL};

int heap_mprotect(void)
{
	void *buf;
	long sz;
	int ret;

	sz = sysconf(_SC_PAGESIZE);
	if (sz < 0)
		return sz;

	buf = memalign(sz, 2 * sz);
	if (buf == NULL)
		return -ENOMEM;

	ret = mprotect(buf, sz, PROT_READ | PROT_WRITE | PROT_EXEC);
	free(buf);
	return ret;
}

int exec_cmd(int *monitored_pid)
{
	int child_pid, child_status;

	child_pid = fork();
	if (child_pid == 0) {
		*monitored_pid = getpid();
		execvp(CMD_ARGS[0], CMD_ARGS);
		return -EINVAL;
	} else if (child_pid > 0) {
		waitpid(child_pid, &child_status, 0);
		return child_status;
	}

	return -EINVAL;
}

void test_test_lsm(void)
{
	struct lsm *skel = NULL;
	int err, duration = 0;

	skel = lsm__open_and_load();
	if (CHECK(!skel, "skel_load", "lsm skeleton failed\n"))
		goto close_prog;

	err = lsm__attach(skel);
	if (CHECK(err, "attach", "lsm attach failed: %d\n", err))
		goto close_prog;

	err = exec_cmd(&skel->bss->monitored_pid);
	if (CHECK(err < 0, "exec_cmd", "err %d errno %d\n", err, errno))
		goto close_prog;

	CHECK(skel->bss->bprm_count != 1, "bprm_count", "bprm_count = %d\n",
	      skel->bss->bprm_count);

	skel->bss->monitored_pid = getpid();

	err = heap_mprotect();
	if (CHECK(errno != EPERM, "heap_mprotect", "want errno=EPERM, got %d\n",
		  errno))
		goto close_prog;

	CHECK(skel->bss->mprotect_count != 1, "mprotect_count",
	      "mprotect_count = %d\n", skel->bss->mprotect_count);

close_prog:
	lsm__destroy(skel);
}
+48 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

/*
 * Copyright 2020 Google LLC.
 */

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include  <errno.h>

char _license[] SEC("license") = "GPL";

int monitored_pid = 0;
int mprotect_count = 0;
int bprm_count = 0;

SEC("lsm/file_mprotect")
int BPF_PROG(test_int_hook, struct vm_area_struct *vma,
	     unsigned long reqprot, unsigned long prot, int ret)
{
	if (ret != 0)
		return ret;

	__u32 pid = bpf_get_current_pid_tgid() >> 32;
	int is_heap = 0;

	is_heap = (vma->vm_start >= vma->vm_mm->start_brk &&
		   vma->vm_end <= vma->vm_mm->brk);

	if (is_heap && monitored_pid == pid) {
		mprotect_count++;
		ret = -EPERM;
	}

	return ret;
}

SEC("lsm/bprm_committed_creds")
int BPF_PROG(test_void_hook, struct linux_binprm *bprm)
{
	__u32 pid = bpf_get_current_pid_tgid() >> 32;

	if (monitored_pid == pid)
		bprm_count++;

	return 0;
}