Sample program to protect GUID partition table. Uses IO filter bpf program type. Signed-off-by: Kjetil Ørbekk <orbekk@xxxxxxxxxx> Signed-off-by: Harshad Shirwadkar <harshads@xxxxxxxxxx> Signed-off-by: Leah Rumancik <leah.rumancik@xxxxxxxxx> --- samples/bpf/Makefile | 3 + samples/bpf/protect_gpt_kern.c | 21 ++++++ samples/bpf/protect_gpt_user.c | 133 +++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 samples/bpf/protect_gpt_kern.c create mode 100644 samples/bpf/protect_gpt_user.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 8403e4762306..f02ae9b2a283 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -53,6 +53,7 @@ tprogs-y += task_fd_query tprogs-y += xdp_sample_pkts tprogs-y += ibumad tprogs-y += hbm +tprogs-y += protect_gpt # Libbpf dependencies LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a @@ -109,6 +110,7 @@ task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS) xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS) ibumad-objs := bpf_load.o ibumad_user.o $(TRACE_HELPERS) hbm-objs := bpf_load.o hbm.o $(CGROUP_HELPERS) +protect_gpt-objs := bpf_load.o protect_gpt_user.o $(TRACE_HELPERS) # Tell kbuild to always build the programs always-y := $(tprogs-y) @@ -170,6 +172,7 @@ always-y += ibumad_kern.o always-y += hbm_out_kern.o always-y += hbm_edt_kern.o always-y += xdpsock_kern.o +always-y += protect_gpt_kern.o ifeq ($(ARCH), arm) # Strip all except -D__LINUX_ARM_ARCH__ option needed to handle linux diff --git a/samples/bpf/protect_gpt_kern.c b/samples/bpf/protect_gpt_kern.c new file mode 100644 index 000000000000..cc49d66c120a --- /dev/null +++ b/samples/bpf/protect_gpt_kern.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/bpf.h> +#include <linux/blk_types.h> +#include "bpf/bpf_helpers.h" + +char _license[] SEC("license") = "GPL"; + +#define GPT_SECTORS 34 + +SEC("gpt_io_filter") +int protect_gpt(struct bpf_io_request *io_req) +{ + /* within GPT and not a read operation */ + if (io_req->sector_start < GPT_SECTORS && (io_req->opf & REQ_OP_MASK) != REQ_OP_READ) + return IO_BLOCK; + + return IO_ALLOW; +} + + diff --git a/samples/bpf/protect_gpt_user.c b/samples/bpf/protect_gpt_user.c new file mode 100644 index 000000000000..21ca25bc78af --- /dev/null +++ b/samples/bpf/protect_gpt_user.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <linux/bpf.h> +#include <errno.h> +#include "trace_helpers.h" +#include "bpf_load.h" + +/* + * user program to load bpf program (protect_gpt_kern) to prevent + * writing to GUID parititon table + * + * argument 1: device where program will be attached (ie. /dev/sda) + * argument 2: name for pinned program + * argument 3: --attach or --detach to attach/detach program + */ + +static int attach(char *dev, char *path) +{ + struct bpf_object *obj; + int ret, devfd, progfd; + + progfd = bpf_obj_get(path); + if (progfd >= 0) { + fprintf(stderr, "Error: object already pinned at given location (%s)\n", path); + return 1; + } + + ret = bpf_prog_load("protect_gpt_kern.o", + BPF_PROG_TYPE_IO_FILTER, &obj, &progfd); + if (ret) { + fprintf(stderr, "Error: failed to load program\n"); + return 1; + } + + devfd = open(dev, O_RDONLY); + if (devfd == -1) { + fprintf(stderr, "Error: failed to open block device %s\n", dev); + return 1; + } + + ret = bpf_prog_attach(progfd, devfd, BPF_BIO_SUBMIT, 0); + if (ret) { + fprintf(stderr, "Error: failed to attach program to device\n"); + close(devfd); + return 1; + } + + ret = bpf_obj_pin(progfd, path); + if (ret != 0) { + fprintf(stderr, "Error pinning program: %s\n", strerror(errno)); + fprintf(stderr, "Detaching program from device\n"); + + if (bpf_prog_detach2(progfd, devfd, BPF_BIO_SUBMIT)) + fprintf(stderr, "Error: failed to detach program\n"); + + close(devfd); + return 1; + } + + close(devfd); + printf("Attached protect_gpt program to device %s.\n", dev); + printf("Program pinned to %s.\n", path); + return 0; +} + +static int detach(char *dev, char *path) +{ + int ret, devfd, progfd; + + progfd = bpf_obj_get(path); + if (progfd < 0) { + fprintf(stderr, "Error: failed to get pinned program from path %s\n", path); + return 1; + } + + devfd = open(dev, O_RDONLY); + if (devfd == -1) { + fprintf(stderr, "Error: failed to open block device %s\n", dev); + return 1; + } + + ret = bpf_prog_detach2(progfd, devfd, BPF_BIO_SUBMIT); + if (ret) { + fprintf(stderr, "Error: failed to detach program\n"); + close(devfd); + return 1; + } + + close(devfd); + + ret = unlink(path); + if (ret < 0) { + fprintf(stderr, "Error unpinning map at %s: %s\n", path, strerror(errno)); + return 1; + } + + printf("Detached and unpinned program.\n"); + return 0; +} + +static void usage(char *exec) +{ + printf("Usage:\n"); + printf("\t %s <device> <prog name> --attach\n", exec); + printf("\t %s <device> <prog name> --detach\n", exec); +} + +int main(int argc, char **argv) +{ + char path[256]; + + if (argc != 4) { + usage(argv[0]); + return 1; + } + + strcpy(path, "/sys/fs/bpf/"); + strcat(path, argv[2]); + + if (strcmp(argv[3], "--attach") == 0) + return attach(argv[1], path); + else if (strcmp(argv[3], "--detach") == 0) + return detach(argv[1], path); + + fprintf(stderr, "Error: invalid flag, please specify --attach or --detach"); + return 1; +} + -- 2.28.0.236.gb10cc79966-goog