From patchwork Tue Aug 2 23:27:08 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 9260481 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 64FCB6089F for ; Tue, 2 Aug 2016 23:27:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 54A7A284DE for ; Tue, 2 Aug 2016 23:27:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4933428508; Tue, 2 Aug 2016 23:27:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E43C28518 for ; Tue, 2 Aug 2016 23:27:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753779AbcHBX1R (ORCPT ); Tue, 2 Aug 2016 19:27:17 -0400 Received: from mail-io0-f174.google.com ([209.85.223.174]:34619 "EHLO mail-io0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754773AbcHBX1M (ORCPT ); Tue, 2 Aug 2016 19:27:12 -0400 Received: by mail-io0-f174.google.com with SMTP id q83so228012493iod.1 for ; Tue, 02 Aug 2016 16:27:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=date:from:to:subject:message-id:mime-version:content-disposition :user-agent; bh=06KcI4hEmnzopa+f+j/vdANII1yOgDBxfsVkwlioXYo=; b=A7i6loHyqDIn5LdkHQ2CJu2NrqPile3UrOY9n4b5wGs/Tmv+lsR9HwJSWcALvcQnXw 2Da/4ykpMPqS2iacBW2J1EaZ5j7FHwxa9zYYeUQ26u5kq0jOPhLlrY9t8KQNRSCPmrWt 11I4DrkhdipP3FZlLL1kaxpgLqawt1IP8ZJXw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition:user-agent; bh=06KcI4hEmnzopa+f+j/vdANII1yOgDBxfsVkwlioXYo=; b=AriiHtF7CinADRR2eDm6mC7R8q2LDeNnPHCvmW3sEAswfxLtwWD/dRcD8TqzmnVGc7 NjU6uKbVO7R1hcQzSa+TE5QIWmyc4t1/ZFCJZQoX2X9KIOsz4lG/jHa2AKR0YFY7lLxD lPcUrHcyDLBQz+wUDdFE2Fg4SZocJDzLokhexRKoEel42M25azu5nZwm85FKe9r+xkv8 PrKRgDM80CRZqFX3ykdtsopZ8+qbrC5SyYILGUHCTtYgzpqV4i+wfPeKrtHLKqXNgrxQ wItMfnLAly2Z5GBUGQej+ctyRin3/fcRBj5Z0QosKea9XWWc5V2GwIIyzx9KshbjPVJO XT0w== X-Gm-Message-State: AEkoouukjSB6Qz75M0VKvRdgfSi72kslnB1m/x0spAJfhLxZikK0UNt529AgyHirwjRANA== X-Received: by 10.107.136.85 with SMTP id k82mr64254853iod.100.1470180430058; Tue, 02 Aug 2016 16:27:10 -0700 (PDT) Received: from ircssh.c.rugged-nimbus-611.internal (55.145.251.23.bc.googleusercontent.com. [23.251.145.55]) by smtp.gmail.com with ESMTPSA id 4sm2353399itw.4.2016.08.02.16.27.09 for (version=TLS1_2 cipher=AES128-SHA bits=128/128); Tue, 02 Aug 2016 16:27:09 -0700 (PDT) Date: Tue, 2 Aug 2016 16:27:08 -0700 From: Sargun Dhillon To: linux-security-module@vger.kernel.org Subject: [RFC 2/4] bpf, security: Add Checmate Message-ID: <20160802232707.GA25290@ircssh.c.rugged-nimbus-611.internal> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP This adds the minor LSM Checmate. The purpose of Checmate is to act as an extensible LSM in which you can load security modules. The module has a simple API, as it's meant to have most of the logic in BPF hooks. It has three APIs that are accessible via prctl. As follows: * Install hook: This appends a new BPF program to a given hook. Hook programs themselves must be unique BPF programs. * Reset hook: This detaches all bpf programs asssociated with a hook. * Deny Reset: This locks a hook, preventing reset. In production operation, it's expected that the user would lock their hooks. Signed-off-by: Sargun Dhillon --- include/linux/checmate.h | 38 ++++++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/bpf.h | 1 + include/uapi/linux/checmate.h | 65 +++++++++ include/uapi/linux/prctl.h | 3 + security/Kconfig | 1 + security/Makefile | 2 + security/checmate/Kconfig | 6 + security/checmate/Makefile | 3 + security/checmate/checmate.c | 0 security/checmate/checmate_bpf.c | 67 ++++++++++ security/checmate/checmate_lsm.c | 281 +++++++++++++++++++++++++++++++++++++++ 12 files changed, 468 insertions(+) create mode 100644 include/linux/checmate.h create mode 100644 include/uapi/linux/checmate.h create mode 100644 security/checmate/Kconfig create mode 100644 security/checmate/Makefile create mode 100644 security/checmate/checmate.c create mode 100644 security/checmate/checmate_bpf.c create mode 100644 security/checmate/checmate_lsm.c diff --git a/include/linux/checmate.h b/include/linux/checmate.h new file mode 100644 index 0000000..3e492b0 --- /dev/null +++ b/include/linux/checmate.h @@ -0,0 +1,38 @@ +#ifndef _LINUX_CHECMATE_H_ +#define _LINUX_CHECMATE_H_ 1 +#include +#include + +/* Miscellanious contexts */ +struct checmate_file_open_ctx { + struct file *file; + const struct cred *cred; +}; + +struct checmate_task_create_ctx { + unsigned long clone_flags; +}; + +struct checmate_task_free_ctx { + struct task_struct *task; +}; + +struct checmate_socket_connect_ctx { + struct socket *sock; + struct sockaddr *address; + int addrlen; +}; + +struct checmate_ctx { + int hook; + union { + /* Miscellanious contexts */ + struct checmate_file_open_ctx file_open_ctx; + struct checmate_task_create_ctx task_create_ctx; + struct checmate_task_free_ctx task_free_ctx; + /* CONFIG_SECURITY_NET contexts */ + struct checmate_socket_connect_ctx socket_connect_ctx; + }; +}; + +#endif diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index ec10cfe..f8670a7 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -82,6 +82,7 @@ header-y += cciss_defs.h header-y += cciss_ioctl.h header-y += cdrom.h header-y += cgroupstats.h +header-y += checmate.h header-y += chio.h header-y += cm4000_cs.h header-y += cn_proc.h diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index da218fe..6cafb58 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -95,6 +95,7 @@ enum bpf_prog_type { BPF_PROG_TYPE_SCHED_ACT, BPF_PROG_TYPE_TRACEPOINT, BPF_PROG_TYPE_XDP, + BPF_PROG_TYPE_CHECMATE, }; #define BPF_PSEUDO_MAP_FD 1 diff --git a/include/uapi/linux/checmate.h b/include/uapi/linux/checmate.h new file mode 100644 index 0000000..18af381 --- /dev/null +++ b/include/uapi/linux/checmate.h @@ -0,0 +1,65 @@ +#ifndef _UAPI__LINUX_CHECMATE_H__ +#define _UAPI__LINUX_CHECMATE_H__ + +#define CHECMATE_INSTALL_HOOK 1 +#define CHECMATE_DENY_RESET 2 +#define CHECMATE_RESET 3 + +enum checmate_hook { + CHECMATE_HOOK_UNSPEC, + /* CONFIG_SECURITY_NET hooks */ + CHECMATE_HOOK_UNIX_STREAM_CONNECT, + CHECMATE_HOOK_UNIX_MAY_SEND, + CHECMATE_HOOK_SOCKET_CREATE, + CHECMATE_HOOK_SOCKET_POST_CREATE, + CHECMATE_HOOK_SOCKET_BIND, + CHECMATE_HOOK_SOCKET_CONNECT, + CHECMATE_HOOK_SOCKET_LISTEN, + CHECMATE_HOOK_SOCKET_ACCEPT, + CHECMATE_HOOK_SOCKET_SENDMSG, + CHECMATE_HOOK_SOCKET_RECVMSG, + CHECMATE_HOOK_SOCKET_GETSOCKNAME, + CHECMATE_HOOK_SOCKET_GETPEERNAME, + CHECMATE_HOOK_SOCKET_GETSOCKOPT, + CHECMATE_HOOK_SOCKET_SETSOCKOPT, + CHECMATE_HOOK_SOCKET_SHUTDOWN, + CHECMATE_HOOK_SOCKET_SOCK_RCV_SKB, + CHECMATE_HOOK_SOCKET_GETPEERSEC_STREAM, + CHECMATE_HOOK_SOCKET_GETPEERSEC_DGRAM, + CHECMATE_HOOK_SK_ALLOC_SECURITY, + CHECMATE_HOOK_SK_FREE_SECURITY, + CHECMATE_HOOK_SK_CLONE_SECURITY, + CHECMATE_HOOK_SK_GETSECID, + CHECMATE_HOOK_SOCK_GRAFT, + CHECMATE_HOOK_INET_CONN_REQUEST, + CHECMATE_HOOK_INET_CSK_CLONE, + CHECMATE_HOOK_INET_CONN_ESTABLISHED, + CHECMATE_HOOK_SECMARK_RELABEL_PACKET, + CHECMATE_HOOK_SECMARK_REFCOUNT_INC, + CHECMATE_HOOK_SECMARK_REFCOUNT_DEC, + CHECMATE_HOOK_REQ_CLASSIFY_FLOW, + CHECMATE_HOOK_TUN_DEV_ALLOC_SECURITY, + CHECMATE_HOOK_TUN_DEV_FREE_SECURITY, + CHECMATE_HOOK_TUN_DEV_CREATE, + CHECMATE_HOOK_TUN_DEV_ATTACH_QUEUE, + CHECMATE_HOOK_TUN_DEV_ATTACH, + CHECMATE_HOOK_TUN_DEV_OPEN, + /* CONFIG_SECURITY_PATH hooks */ + CHECMATE_HOOK_PATH_UNLINK, + CHECMATE_HOOK_PATH_MKDIR, + CHECMATE_HOOK_PATH_RMDIR, + CHECMATE_HOOK_PATH_MKNOD, + CHECMATE_HOOK_PATH_TRUNCATE, + CHECMATE_HOOK_PATH_SYMLINK, + CHECMATE_HOOK_PATH_LINK, + CHECMATE_HOOK_PATH_RENAME, + CHECMATE_HOOK_PATH_CHMOD, + CHECMATE_HOOK_PATH_CHOWN, + CHECMATE_HOOK_PATH_CHROOT, + /* Other hooks */ + CHECMATE_HOOK_FILE_OPEN, + CHECMATE_HOOK_TASK_CREATE, + CHECMATE_HOOK_TASK_FREE, + __CHECMATE_HOOK_MAX, +}; +#endif diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index a8d0759..f520d1e 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -197,4 +197,7 @@ struct prctl_mm_map { # define PR_CAP_AMBIENT_LOWER 3 # define PR_CAP_AMBIENT_CLEAR_ALL 4 +/* (CHEC)MATE operations */ +#define PR_CHECMATE 0x43484543 + #endif /* _LINUX_PRCTL_H */ diff --git a/security/Kconfig b/security/Kconfig index 176758c..36cafc7 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -124,6 +124,7 @@ source security/tomoyo/Kconfig source security/apparmor/Kconfig source security/loadpin/Kconfig source security/yama/Kconfig +source security/checmate/Kconfig source security/integrity/Kconfig diff --git a/security/Makefile b/security/Makefile index f2d71cd..6cc3342 100644 --- a/security/Makefile +++ b/security/Makefile @@ -8,6 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor subdir-$(CONFIG_SECURITY_YAMA) += yama +subdir-$(CONFIG_SECURITY_CHECMATE) += checmate subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin # always enable default capabilities @@ -25,6 +26,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ obj-$(CONFIG_SECURITY_YAMA) += yama/ obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o +obj-$(CONFIG_SECURITY_CHECMATE) += checmate/ # Object integrity file lists subdir-$(CONFIG_INTEGRITY) += integrity diff --git a/security/checmate/Kconfig b/security/checmate/Kconfig new file mode 100644 index 0000000..6a5c3f3 --- /dev/null +++ b/security/checmate/Kconfig @@ -0,0 +1,6 @@ +config SECURITY_CHECMATE + bool "Checmate support" + depends on SECURITY + default n + help + This turns on checmate diff --git a/security/checmate/Makefile b/security/checmate/Makefile new file mode 100644 index 0000000..c676773 --- /dev/null +++ b/security/checmate/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SECURITY_CHECMATE) := checmate.o + +checmate-y := checmate_bpf.o checmate_lsm.o diff --git a/security/checmate/checmate.c b/security/checmate/checmate.c new file mode 100644 index 0000000..e69de29 diff --git a/security/checmate/checmate_bpf.c b/security/checmate/checmate_bpf.c new file mode 100644 index 0000000..5bf1a8e --- /dev/null +++ b/security/checmate/checmate_bpf.c @@ -0,0 +1,67 @@ +/* + * Checmate Linux Security Module + * + * Copyright (C) 2016 Sargun Dhillon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ + +#include +#include + +static const struct bpf_func_proto *checmate_prog_func_proto(enum bpf_func_id func_id) +{ + switch (func_id) { + case BPF_FUNC_map_lookup_elem: + return &bpf_map_lookup_elem_proto; + case BPF_FUNC_map_update_elem: + return &bpf_map_update_elem_proto; + case BPF_FUNC_map_delete_elem: + return &bpf_map_delete_elem_proto; + case BPF_FUNC_probe_read: + return &bpf_probe_read_proto; + case BPF_FUNC_tail_call: + return &bpf_tail_call_proto; + case BPF_FUNC_get_current_pid_tgid: + return &bpf_get_current_pid_tgid_proto; + case BPF_FUNC_get_current_task: + return &bpf_get_current_task_proto; + case BPF_FUNC_get_current_uid_gid: + return &bpf_get_current_uid_gid_proto; + case BPF_FUNC_get_current_comm: + return &bpf_get_current_comm_proto; + case BPF_FUNC_trace_printk: + return bpf_get_trace_printk_proto(); + default: + return NULL; + } +} + +static bool checmate_prog_is_valid_access(int off, int size, + enum bpf_access_type type, + enum bpf_reg_type *reg_type) +{ + if (type != BPF_READ) + return false; + if (off < 0 || off >= sizeof(struct checmate_ctx)) + return false; + return true; +} + +static const struct bpf_verifier_ops checmate_prog_ops = { + .get_func_proto = checmate_prog_func_proto, + .is_valid_access = checmate_prog_is_valid_access, +}; + +static struct bpf_prog_type_list checmate_tl = { + .ops = &checmate_prog_ops, + .type = BPF_PROG_TYPE_CHECMATE, +}; + +void register_checmate_prog_ops(void) +{ + bpf_register_prog_type(&checmate_tl); +} diff --git a/security/checmate/checmate_lsm.c b/security/checmate/checmate_lsm.c new file mode 100644 index 0000000..7fa1072 --- /dev/null +++ b/security/checmate/checmate_lsm.c @@ -0,0 +1,281 @@ +/* + * Checmate Linux Security Module + * + * Copyright (C) 2016 Sargun Dhillon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include + +#define HOOK_INIT(HOOK_NUM) \ + LIST_HEAD_INIT(checmate_bpf_hooks[HOOK_NUM].hook_list) + +#define CHECMATE_HOOK(HOOK_NUM) \ + [HOOK_NUM] = \ + { \ + .enabled = true, \ + .hook_list = HOOK_INIT(HOOK_NUM), \ + } +void register_checmate_prog_ops(void); + +/* + * Global write lock for all BPF program installations. This shouldn't + * see much contention, so locking is global, but it allows us to + * preserve that BPF hooks are unique. + */ +static DEFINE_MUTEX(checmate_write_lock); + +struct checmate_bpf_hook { + bool enabled; + bool deny_reset; + struct list_head hook_list; +}; + +struct checmate_bpf_hook_instance { + struct list_head list; + struct bpf_prog *prog; + struct rcu_head rcu; +}; + +static struct checmate_bpf_hook checmate_bpf_hooks[__CHECMATE_HOOK_MAX] = { + CHECMATE_HOOK(CHECMATE_HOOK_FILE_OPEN), + CHECMATE_HOOK(CHECMATE_HOOK_TASK_CREATE), + CHECMATE_HOOK(CHECMATE_HOOK_TASK_FREE), + CHECMATE_HOOK(CHECMATE_HOOK_SOCKET_CONNECT), +}; + +/* + * checmate_task_prctl_install_hook - Install a checmate hook + * @hook: Hook ID + * @prog_fd: BPF prog fd + * + * Return 0 on success + */ +static int checmate_prctl_install_hook(int hook, int prog_fd) +{ + int rc = 0; + struct bpf_prog *prog; + struct checmate_bpf_hook_instance *hook_instance; + + prog = bpf_prog_get_type(prog_fd, BPF_PROG_TYPE_CHECMATE); + if (IS_ERR(prog)) + return PTR_ERR(prog); + + mutex_lock(&checmate_write_lock); + list_for_each_entry(hook_instance, + &checmate_bpf_hooks[hook].hook_list, list) { + if (hook_instance->prog == prog) { + rc = -EEXIST; + goto err; + } + } + hook_instance = kmalloc(sizeof(*hook_instance), GFP_KERNEL); + + if (!hook_instance) { + rc = -ENOMEM; + goto err; + } + hook_instance->prog = prog; + list_add_tail_rcu(&hook_instance->list, + &checmate_bpf_hooks[hook].hook_list); + mutex_unlock(&checmate_write_lock); + return rc; + +err: + mutex_unlock(&checmate_write_lock); + bpf_prog_put(prog); + return rc; +} + +static int checmate_prctl_deny_reset(int hook) +{ + int rc = 0; + + mutex_lock(&checmate_write_lock); + checmate_bpf_hooks[hook].deny_reset = true; + mutex_unlock(&checmate_write_lock); + return rc; +} + +static void free_hook_instance(struct checmate_bpf_hook_instance *hook_instance) +{ + bpf_prog_put(hook_instance->prog); + kfree(hook_instance); +} + +static void free_hook_instance_rcu(struct rcu_head *head) +{ + struct checmate_bpf_hook_instance *hook_instance; + + hook_instance = container_of(head, struct checmate_bpf_hook_instance, + rcu); + + free_hook_instance(hook_instance); +} + +static int checmate_reset(int hook) +{ + int rc = 0; + struct checmate_bpf_hook_instance *hook_instance; + + mutex_lock(&checmate_write_lock); + if (checmate_bpf_hooks[hook].deny_reset) { + rc = -EPERM; + goto out; + } + list_for_each_entry(hook_instance, &checmate_bpf_hooks[hook].hook_list, + list) { + list_del_rcu(&hook_instance->list); + call_rcu(&hook_instance->rcu, free_hook_instance_rcu); + } +out: + mutex_unlock(&checmate_write_lock); + return rc; +} + +/* + * checmate_task_prctl - check for Checmate-specific prctl operations + * @option: operation - supports CHECMATE_INSTALL_HOOK + * @arg2: argument - Option ID + * @arg3: argument - Hook ID + * @arg4: argument - BPF Prog FD, if installing + * @arg5: argument + * + * Return 0 on success, -ve on error. -ENOSYS is returned when checmate + * does not handle the given option. + * + * The only API available today is to install a hook, to mirror the + * rest of the LSMs APIs. They don't allow unloading of security + * modules. + */ +static int checmate_task_prctl(int option, unsigned long arg2, + unsigned long hook, unsigned long ufd, + unsigned long arg5) +{ + int rc = -ENOSYS; + + switch (option) { + case PR_CHECMATE: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (!(hook > 0 && hook < __CHECMATE_HOOK_MAX)) + return -EINVAL; + if (!checmate_bpf_hooks[hook].enabled) + return -ENOTSUPP; + + if (arg2 == CHECMATE_INSTALL_HOOK) + rc = checmate_prctl_install_hook(hook, ufd); + else if (arg2 == CHECMATE_DENY_RESET) + rc = checmate_prctl_deny_reset(hook); + else if (arg2 == CHECMATE_RESET) + rc = checmate_reset(hook); + else + return -ENOTSUPP; + break; + } + return rc; +} + +static int call_bpf_int_hook(int hook, struct checmate_ctx *ctx) +{ + int rc = 0; + struct checmate_bpf_hook_instance *hook_instance; + + ctx->hook = hook; + + preempt_disable(); + rcu_read_lock(); + list_for_each_entry_rcu(hook_instance, + &checmate_bpf_hooks[hook].hook_list, list) { + rc = BPF_PROG_RUN(hook_instance->prog, (void *)ctx); + if (rc != 0) + goto out; + } +out: + rcu_read_unlock(); + preempt_enable(); + return rc; +} + +static void call_bpf_void_hook(int hook, struct checmate_ctx *ctx) +{ + struct checmate_bpf_hook_instance *hook_instance; + + ctx->hook = hook; + preempt_disable(); + rcu_read_lock(); + + list_for_each_entry_rcu(hook_instance, + &checmate_bpf_hooks[hook].hook_list, list) { + BPF_PROG_RUN(hook_instance->prog, (void *)ctx); + } + rcu_read_unlock(); + preempt_enable(); +} + +static int checmate_file_open(struct file *file, const struct cred *cred) +{ + struct checmate_ctx ctx; + + ctx.file_open_ctx.file = file; + ctx.file_open_ctx.cred = cred; + return call_bpf_int_hook(CHECMATE_HOOK_FILE_OPEN, &ctx); +} + +static int checmate_task_create(unsigned long clone_flags) +{ + struct checmate_ctx ctx; + + ctx.task_create_ctx.clone_flags = clone_flags; + return call_bpf_int_hook(CHECMATE_HOOK_TASK_CREATE, &ctx); +} + +static void checmate_task_free(struct task_struct *task) +{ + struct checmate_ctx ctx; + + ctx.task_free_ctx.task = task; + call_bpf_void_hook(CHECMATE_HOOK_TASK_FREE, &ctx); +} + +#ifdef CONFIG_SECURITY_NETWORK +static int checmate_socket_connect(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct checmate_ctx ctx; + + ctx.socket_connect_ctx.sock = sock; + ctx.socket_connect_ctx.address = address; + ctx.socket_connect_ctx.addrlen = addrlen; + return call_bpf_int_hook(CHECMATE_HOOK_SOCKET_CONNECT, &ctx); +} + +#endif /* CONFIG_SECURITY_NETWORK */ +static struct security_hook_list checmate_hooks[] = { + LSM_HOOK_INIT(task_prctl, checmate_task_prctl), + LSM_HOOK_INIT(file_open, checmate_file_open), + LSM_HOOK_INIT(task_create, checmate_task_create), + LSM_HOOK_INIT(task_free, checmate_task_free), +#ifdef CONFIG_SECURITY_NETWORK + LSM_HOOK_INIT(socket_connect, checmate_socket_connect), +#endif /* CONFIG_SECURITY_NETWORK */ +}; + +static int __init checmate_setup(void) +{ + pr_info("Checmate activating.\n"); + register_checmate_prog_ops(); + security_add_hooks(checmate_hooks, ARRAY_SIZE(checmate_hooks)); + return 0; +} +late_initcall(checmate_setup);