Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751797AbdFEIkN (ORCPT ); Mon, 5 Jun 2017 04:40:13 -0400 Received: from mo1501.tsb.2iij.net ([210.149.48.173]:33229 "EHLO mo.tsb.2iij.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751503AbdFEIkH (ORCPT ); Mon, 5 Jun 2017 04:40:07 -0400 X-MXL-Hash: 593518cb091cdf4b-60efd0d2844528c59c83e5b6bc37c0f90a199860 From: To: , , , , Subject: RE: [RFC 1/3] WhiteEgret: Add WhiteEgret core functions. Thread-Topic: [RFC 1/3] WhiteEgret: Add WhiteEgret core functions. Thread-Index: AQHS2Wo0yMYWtXWn0EmFVbRubErQw6IVstsw Date: Mon, 5 Jun 2017 08:39:35 +0000 Message-ID: <5ae30605933148f499831fbbf2cde991@TGXML276.toshiba.local> References: <20170530111354.5255-1-masanobu2.koike@toshiba.co.jp> <8de78503-c4ec-9b87-cef9-ac6f6c5d8e94@schaufler-ca.com> In-Reply-To: <8de78503-c4ec-9b87-cef9-ac6f6c5d8e94@schaufler-ca.com> Accept-Language: ja-JP, en-US Content-Language: ja-JP x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [133.196.2.199] msscp.transfermailtomossagent: 103 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 X-MAIL-FROM: X-SOURCE-IP: [172.27.153.184] X-Spam: exempt Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by mail.home.local id v558eK2T027464 Content-Length: 45664 Lines: 1738 Casey Schaufler wrote: > On 5/30/2017 4:13 AM, Masanobu Koike wrote: > > This RFC provides implementation of WhiteEgret. > > > > Signed-off-by: Masanobu Koike > > --- > > security/Kconfig | 7 +- > > security/Makefile | 2 + > > security/whiteegret/Kconfig | 21 ++ > > security/whiteegret/Makefile | 7 + > > security/whiteegret/auth.c | 19 ++ > > security/whiteegret/auth.h | 12 ++ > > security/whiteegret/dd_com.c | 79 ++++++++ > > security/whiteegret/dd_com.h | 19 ++ > > security/whiteegret/gennl.c | 382 > +++++++++++++++++++++++++++++++++++++ > > security/whiteegret/gennl.h | 32 ++++ > > security/whiteegret/gennl_common.h | 43 +++++ > > security/whiteegret/init.c | 69 +++++++ > > security/whiteegret/main.c | 340 > +++++++++++++++++++++++++++++++++ > > security/whiteegret/print_msg.h | 19 ++ > > security/whiteegret/request.c | 248 ++++++++++++++++++++++++ > > security/whiteegret/request.h | 79 ++++++++ > > security/whiteegret/returntoexec.h | 14 ++ > > security/whiteegret/we.h | 72 +++++++ > > security/whiteegret/we_common.h | 19 ++ > > 19 files changed, 1482 insertions(+), 1 deletion(-) > > create mode 100644 security/whiteegret/Kconfig > > create mode 100644 security/whiteegret/Makefile > > create mode 100644 security/whiteegret/auth.c > > create mode 100644 security/whiteegret/auth.h > > create mode 100644 security/whiteegret/dd_com.c > > create mode 100644 security/whiteegret/dd_com.h > > create mode 100644 security/whiteegret/gennl.c > > create mode 100644 security/whiteegret/gennl.h > > create mode 100644 security/whiteegret/gennl_common.h > > create mode 100644 security/whiteegret/init.c > > create mode 100644 security/whiteegret/main.c > > create mode 100644 security/whiteegret/print_msg.h > > create mode 100644 security/whiteegret/request.c > > create mode 100644 security/whiteegret/request.h > > create mode 100644 security/whiteegret/returntoexec.h > > create mode 100644 security/whiteegret/we.h > > create mode 100644 security/whiteegret/we_common.h > > > > diff --git a/security/Kconfig b/security/Kconfig > > index 93027fd..acfafb0 100644 > > --- a/security/Kconfig > > +++ b/security/Kconfig > > @@ -195,6 +195,7 @@ source security/tomoyo/Kconfig > > source security/apparmor/Kconfig > > source security/loadpin/Kconfig > > source security/yama/Kconfig > > +source security/whiteegret/Kconfig > > > > source security/integrity/Kconfig > > > > @@ -204,6 +205,7 @@ choice > > default DEFAULT_SECURITY_SMACK if SECURITY_SMACK > > default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO > > default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR > > + default DEFAULT_SECURITY_WHITEEGRET if SECURITY_WHITEEGRET > > default DEFAULT_SECURITY_DAC > > > > help > > @@ -222,6 +224,9 @@ choice > > config DEFAULT_SECURITY_APPARMOR > > bool "AppArmor" if SECURITY_APPARMOR=y > > > > + config DEFAULT_SECURITY_WHITEEGRET > > + bool "WhiteEgret" if SECURITY_WHITEEGRET=y > > + > > config DEFAULT_SECURITY_DAC > > bool "Unix Discretionary Access Controls" > > > > @@ -233,7 +238,7 @@ config DEFAULT_SECURITY > > default "smack" if DEFAULT_SECURITY_SMACK > > default "tomoyo" if DEFAULT_SECURITY_TOMOYO > > default "apparmor" if DEFAULT_SECURITY_APPARMOR > > + default "whiteegret" if DEFAULT_SECURITY_WHITEEGRET > > default "" if DEFAULT_SECURITY_DAC > > > > endmenu > > - > > diff --git a/security/Makefile b/security/Makefile > > index f2d71cd..4fd9ff9 100644 > > --- a/security/Makefile > > +++ b/security/Makefile > > @@ -9,6 +9,7 @@ subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo > > subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor > > subdir-$(CONFIG_SECURITY_YAMA) += yama > > subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin > > +subdir-$(CONFIG_SECURITY_WHITEEGRET) += whiteegret > > > > # always enable default capabilities > > obj-y += commoncap.o > > @@ -24,6 +25,7 @@ obj-$(CONFIG_SECURITY_TOMOYO) += > tomoyo/ > > obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ > > obj-$(CONFIG_SECURITY_YAMA) += yama/ > > obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ > > +obj-$(CONFIG_SECURITY_WHITEEGRET) += whiteegret/ > > obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o > > > > # Object integrity file lists > > diff --git a/security/whiteegret/Kconfig b/security/whiteegret/Kconfig > > new file mode 100644 > > index 0000000..923316f > > --- /dev/null > > +++ b/security/whiteegret/Kconfig > > @@ -0,0 +1,21 @@ > > +config SECURITY_WHITEEGRET > > + bool "WhiteEgret support" > > + depends on SECURITY > > + default n > > + help > > + This enables the WhiteEgret security module. > > + WhiteEgret provides a whitelisting execution control > capability, > > + which helps to stop the execution of unauthorized software > > + such as malware. > > + You will also need a user application and an execution whitelist. > > + If you are unsure how to answer this question, answer N. > > + > > +config SECURITY_WHITEEGRET_DRIVER > > + bool "Use device driver in communication with user space" > > + depends on SECURITY_WHITEEGRET > > + default n > > + help > > + This option selects whether you use a device driver > > + for communication between kernel space and user space. > > + If you do not set this option, netlink is selected for > > + communication between two spaces. > > diff --git a/security/whiteegret/Makefile > b/security/whiteegret/Makefile > > new file mode 100644 > > index 0000000..ed8eb9f > > --- /dev/null > > +++ b/security/whiteegret/Makefile > > @@ -0,0 +1,7 @@ > > +obj-$(CONFIG_SECURITY_WHITEEGRET) += whiteegret.o > > +whiteegret-y := init.o main.o request.o > > +ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > +whiteegret-y += dd_com.o > > +else > > +whiteegret-y += gennl.o auth.o > > +endif > > diff --git a/security/whiteegret/auth.c b/security/whiteegret/auth.c > > new file mode 100644 > > index 0000000..dd2c9eb > > --- /dev/null > > +++ b/security/whiteegret/auth.c > > @@ -0,0 +1,19 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#include "auth.h" > > + > > +/** > > + * userproc_auth - Authenticate user's whitelisting application process. > > + * > > + * @authinfo: authentication credentials > > + * > > + * Returns 1 if authenticated, 0 otherwise. > > + */ > > +int userproc_auth(char *authinfo) > > +{ > > + return 1; > > +} > > diff --git a/security/whiteegret/auth.h b/security/whiteegret/auth.h > > new file mode 100644 > > index 0000000..ddcd2dd > > --- /dev/null > > +++ b/security/whiteegret/auth.h > > @@ -0,0 +1,12 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _AUTH_H > > +#define _AUTH_H > > + > > +int userproc_auth(char *authinfo); > > + > > +#endif > > diff --git a/security/whiteegret/dd_com.c > b/security/whiteegret/dd_com.c > > new file mode 100644 > > index 0000000..534c4d5 > > --- /dev/null > > +++ b/security/whiteegret/dd_com.c > > @@ -0,0 +1,79 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#include "dd_com.h" > > +#include "request.h" > > +#include "we.h" > > +#include "print_msg.h" > > + > > +struct task_struct *from_task; > > + > > +/** > > + * start_we - Enable WhiteEgret. > > + * > > + * Returns pointer to we_req_q_head. > > + */ > > +struct we_req_q_head *start_we(void) > > +{ > > + if (from_task) { > > + PRINT_WARNING("WhiteEgret has already started.\n"); > > + return NULL; > > + } > > + > > + write_lock(&(we_q_head.lock)); > > + from_task = current; > > + write_unlock(&(we_q_head.lock)); > > + > > + return &we_q_head; > > +} > > +EXPORT_SYMBOL(start_we); > > + > > +/** > > + * stop_we - Disable WhiteEgret. > > + * > > + * Returns -EPERM if the task invoking this function is not valid, > > + * 0 otherwise. > > + */ > > +int stop_we(void) > > +{ > > + if (!from_task) { > > + PRINT_WARNING("WhiteEgret has not started.\n"); > > + return -EPERM; > > + } > > + if (from_task != current) { > > + PRINT_WARNING("This task is not registered to > WhiteEgret.\n"); > > + return -EPERM; > > + } > > + > > + we_req_q_cleanup(); > > + > > + write_lock(&(we_q_head.lock)); > > + from_task = NULL; > > + write_unlock(&(we_q_head.lock)); > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(stop_we); > > + > > +/** > > + * send_we_obj_info - Wait response from user's whitelisting application. > > + * > > + * @req: Pointer to struct we_req_q. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int send_we_obj_info(struct we_req_q *req) > > +{ > > + /* If there exists queue waiting for this request req done, > > + * then wake up it. > > + */ > > + if (waitqueue_active(&(we_q_head.waitq))) > > + wake_up(&(we_q_head.waitq)); > > + > > + return wait_event_interruptible_timeout(req->waitq, > > + (req->finish_flag == START_EXEC), > > + WERESULTTIMEOUT); > > +} > > diff --git a/security/whiteegret/dd_com.h > b/security/whiteegret/dd_com.h > > new file mode 100644 > > index 0000000..9c7c5b8 > > --- /dev/null > > +++ b/security/whiteegret/dd_com.h > > @@ -0,0 +1,19 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _DD_COM_H > > +#define _DD_COM_H > > + > > +#include "request.h" > > + > > +extern struct task_struct *from_task; > > + > > +extern struct we_req_q_head *start_we(void); > > +extern int stop_we(void); > > + > > +int send_we_obj_info(struct we_req_q *req); > > + > > +#endif /* _DD_COM_H */ > > diff --git a/security/whiteegret/gennl.c b/security/whiteegret/gennl.c > > new file mode 100644 > > index 0000000..10a1113 > > --- /dev/null > > +++ b/security/whiteegret/gennl.c > > @@ -0,0 +1,382 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#include "auth.h" > > +#include "gennl_common.h" > > +#include "gennl.h" > > +#include "returntoexec.h" > > +#include "we_common.h" > > +#include "we.h" > > +#include "request.h" > > +#include "print_msg.h" > > + > > +/* global variables */ > > +int from_pid = -1; /* pid of user's whitelisting application */ > > +struct net *from_net; > > +u32 seq; /* sequence number */ > > + > > +/* attribute policy */ > > +static struct nla_policy we_genl_policy[WE_A_MAX + 1] = { > > + [WE_A_UNSPEC] = { .type = NLA_STRING }, > > + [WE_A_AUTHINFO] = { .type = NLA_BINARY, > > + .len = AUTHINFOLENGTH }, > > + [WE_A_SHORTNAME] = { .type = NLA_STRING, > > + .len = SHORTNAMELENGTH }, > > + [WE_A_PATH] = { .type = NLA_STRING }, > > + [WE_A_EXECPERMISSION] = { .type = NLA_FLAG }, > > +}; > > + > > +/* operation definition */ > > +static struct genl_ops we_gnl_opses[] = { > > + { > > + .cmd = WE_C_UNSPEC, > > + .flags = 0, > > + .policy = we_genl_policy, > > + .doit = we_unspec, > > + .dumpit = NULL, > > + }, > > + { > > + .cmd = WE_C_USERREGISTER, > > + .flags = 0, > > + .policy = we_genl_policy, > > + .doit = we_userregister, > > + .dumpit = NULL, > > + }, > > + { > > + .cmd = WE_C_USERUNREGISTER, > > + .flags = 0, > > + .policy = we_genl_policy, > > + .doit = we_userunregister, > > + .dumpit = NULL, > > + }, > > + { > > + .cmd = WE_C_EXECPERMISSION, > > + .flags = 0, > > + .policy = we_genl_policy, > > + .doit = we_execpermission, > > + .dumpit = NULL, > > + }, > > +}; > > + > > +/* family definition */ > > +static struct genl_family we_gnl_family = { > > + .name = WE_FAMILY_NAME, > > + .version = WE_FAMILY_VERSION, > > + .maxattr = WE_A_MAX, > > + .ops = we_gnl_opses, > > + .n_ops = ARRAY_SIZE(we_gnl_opses), > > + .module = THIS_MODULE, > > +}; > > + > > +/** > > + * we_netlink_register - Initialize netlink. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_netlink_register(void) > > +{ > > + int rc; > > + > > + PRINT_INFO("%s starts.\n", __func__); > > + > > + rc = genl_register_family(&we_gnl_family); > > + if (rc != 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + from_net = kmalloc(sizeof(struct net), GFP_KERNEL); > > + if (!from_net) { > > + rc = -ENOMEM; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + PRINT_WARNING("Netlink is registered by WhiteEgret.\n"); > > + > > + return 0; > > +} > > + > > +/** > > + * we_netlink_unregister - Close netlink. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_netlink_unregister(void) > > +{ > > + int rc; > > + > > + PRINT_INFO("%s starts.\n", __func__); > > + > > + rc = genl_unregister_family(&we_gnl_family); > > + if (rc != 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + if (from_net != NULL) { > > + kfree(from_net); > > + from_net = NULL; > > + } > > + > > + PRINT_WARNING("Netlink is unregistered by WhiteEgret.\n"); > > + > > + return 0; > > +} > > + > > +/** > > + * we_unspec - Receive handler for unspecified. > > + * > > + * @buf: Pointer to struct sk_buff. > > + * @info: Pointer to struct genl_info. > > + * > > + * Returns 0. > > + */ > > +int we_unspec(struct sk_buff *buf, struct genl_info *info) > > +{ > > + PRINT_INFO("Some message is handled at %s.\n", __func__); > > + > > + /* do something if necessary */ > > + > > + return 0; > > +} > > + > > +/** > > + * we_userregister - Register user's whitelisting application. > > + * > > + * @buf: Pointer to struct sk_buff. > > + * @info: Pointer to struct genl_info. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_userregister(struct sk_buff *buf, struct genl_info *info) > > +{ > > + int rc; > > + struct pid *usrpid; > > + struct task_struct *usrtask; > > +#ifdef CONFIG_NET_NS > > + const struct cred *usrcred; > > +#endif > > + > > + PRINT_INFO("Some message is handled at %s.\n", __func__); > > + > > + if (from_pid != -1) { > > + PRINT_WARNING > > + ("The pid %d is already registered to > WhiteEgret.\n", > > + from_pid); > > + rc = -EACCES; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + usrpid = find_get_pid(info->snd_portid); > > + if (usrpid == NULL) { > > + rc = -EACCES; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + usrtask = get_pid_task(usrpid, PIDTYPE_PID); > > + if (usrtask == NULL) { > > + rc = -EACCES; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > +#ifdef CONFIG_NET_NS > > + usrcred = get_task_cred(usrtask); > > + if (usrcred == NULL) { > > + rc = -EACCES; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + if ((security_capable(usrcred, genl_info_net(info)->user_ns, > > Do not use the LSM interfaces (security_xxx) inside security modules. > In this case you're probably looking for cap_capable() instead. Thank you for all your advice. I'll use cap_capable() instead. > > > + CAP_NET_ADMIN)) != 0) { > > + rc = -EACCES; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > +#endif > > + > > + rc = userproc_auth((char > *)nla_data(info->attrs[WE_A_AUTHINFO])); > > + if (rc <= 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + from_pid = info->snd_portid; > > + memcpy(from_net, genl_info_net(info), sizeof(struct net)); > > + > > + seq = info->snd_seq; > > + > > + PRINT_WARNING("The pid %d is registered to WhiteEgret.\n", > from_pid); > > + > > + return 0; > > +} > > + > > +/** > > + * we_userunregister - Unregister user's whitelisting application > > + * invoked by itself. > > + * > > + * @buf: Pointer to struct sk_buff. > > + * @info: Pointer to struct genl_info. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_userunregister(struct sk_buff *buf, struct genl_info *info) > > +{ > > + int rc; > > + > > + PRINT_INFO("Some message is handled at %s.\n", __func__); > > + > > + if (from_pid != info->snd_portid) { > > + rc = -EACCES; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + rc = userproc_auth((char > *)nla_data(info->attrs[WE_A_AUTHINFO])); > > + if (rc <= 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + PRINT_WARNING("The pid %d is unregistered to WhiteEgret.\n", > from_pid); > > + > > + from_pid = -1; > > + > > + return 0; > > +} > > + > > +/** > > + * we_execpermission - Receive handler for execution permission. > > + * > > + * @buf: Pointer to struct sk_buff. > > + * @info: Pointer to struct genl_info. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_execpermission(struct sk_buff *buf, struct genl_info *info) > > +{ > > + int rc = 0; > > + struct we_req_data data; > > + > > + PRINT_INFO("Some message is handled at %s.\n", __func__); > > + > > + if (from_pid != info->snd_portid) { > > + rc = -EACCES; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + data.seq = info->snd_seq; > > + memcpy(&(data.shortname), > nla_data(info->attrs[WE_A_SHORTNAME]), > > + SHORTNAMELENGTH); > > + if (we_req_q_search(&data) == NULL) { > > + PRINT_INFO("(%s, %d) is not waiting for execution.\n", > > + data.shortname, data.seq); > > + return 0; > > + } > > + > > + rc = > returntoexec(nla_get_flag(info->attrs[WE_A_EXECPERMISSION]), > > + &data); > > + if (rc != 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + we_req_q_specific_pull(&data); > > + > > + PRINT_INFO("%s done (%s, %d).\n", __func__, data.shortname, > data.seq); > > + > > + return 0; > > +} > > + > > +/** > > + * send_we_obj_info - Send request for matching white list. > > + * > > + * @we_info: Pointer to struct we_obj_info. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int send_we_obj_info(struct we_obj_info *we_info) > > +{ > > + int rc = 0; > > + void *msg_head; > > + struct sk_buff *send_skb; > > + > > + if ((from_pid == -1) || (from_net == NULL)) { > > + rc = -EINVAL; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + send_skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); > > + if (send_skb == NULL) { > > + rc = -ENOMEM; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + msg_head = genlmsg_put(send_skb, 0, seq, &we_gnl_family, 0, > > + WE_C_EXECPERMISSION); > > + if (msg_head == NULL) { > > + rc = -ENOMEM; > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + rc = nla_put_string(send_skb, WE_A_SHORTNAME, > > + we_info->shortname); > > + if (rc != 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + rc = nla_put_string(send_skb, WE_A_PATH, we_info->path); > > + if (rc != 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + genlmsg_end(send_skb, msg_head); > > + > > + PRINT_INFO("Msg (%s, %s) sent to the pid %d (current > process: %d)\n", > > + we_info->shortname, we_info->path, > > + from_pid, we_info->pid); > > + > > + rc = genlmsg_unicast(from_net, send_skb, from_pid); > > + if (rc != 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + return 0; > > +} > > + > > +/** > > + * inc_seq - Increment sequence number. > > + */ > > +void inc_seq(void) > > +{ > > + seq += 1; > > +} > > + > > +/** > > + * get_seq - Return sequence number. > > + * > > + * Returns sequence number. > > + */ > > +int get_seq(void) > > +{ > > + return seq; > > +} > > diff --git a/security/whiteegret/gennl.h b/security/whiteegret/gennl.h > > new file mode 100644 > > index 0000000..8b751b2 > > --- /dev/null > > +++ b/security/whiteegret/gennl.h > > @@ -0,0 +1,32 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _GENNL_H > > +#define _GENNL_H > > + > > +#include > > +#include "we.h" > > + > > +extern int from_pid; > > + > > +/* handler */ > > +int we_unspec(struct sk_buff *buf, struct genl_info *info); > > +int we_userregister(struct sk_buff *buf, struct genl_info *info); > > +int we_userunregister(struct sk_buff *buf, struct genl_info *info); > > +int we_execpermission(struct sk_buff *buf, struct genl_info *info); > > + > > +/* register/unregister */ > > +int we_netlink_register(void); > > +int we_netlink_unregister(void); > > + > > +/* send message to user space */ > > +int send_we_obj_info(struct we_obj_info *info); > > + > > +/* manipulate sequence number */ > > +void inc_seq(void); > > +int get_seq(void); > > + > > +#endif /* _GENNL_H */ > > diff --git a/security/whiteegret/gennl_common.h > b/security/whiteegret/gennl_common.h > > new file mode 100644 > > index 0000000..e59615b > > --- /dev/null > > +++ b/security/whiteegret/gennl_common.h > > @@ -0,0 +1,43 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _GENNL_COMMON_H > > +#define _GENNL_COMMON_H > > + > > +/* UWA stands for User's Whitelisting Application */ > > + > > +/* Netlink attributes */ > > +enum { > > + WE_A_UNSPEC, /* unspecified message */ > > + WE_A_AUTHINFO, /* authentication info for UWA registration */ > > + WE_A_SHORTNAME, /* short name for an object to be examined */ > > + WE_A_PATH, /* full path for an object to be examined */ > > + WE_A_EXECPERMISSION, /* flag if the object is in the whitelist */ > > + __WE_A_MAX, > > +}; > > + > > +/* Number of netlink attributes */ > > +#define WE_A_MAX (__WE_A_MAX - 1) > > + > > +/* Name of genl_family */ > > +#define WE_FAMILY_NAME "WhiteEgret" > > + > > +/* Version number of genl_family */ > > +#define WE_FAMILY_VERSION 1 > > + > > +/* Netlink commands */ > > +enum { > > + WE_C_UNSPEC, /* unspecified message */ > > + WE_C_USERREGISTER, /* register UWA */ > > + WE_C_USERUNREGISTER, > > + WE_C_EXECPERMISSION, /* execution permission */ > > + __WE_C_MAX, > > +}; > > + > > +/* Number of netlink commands */ > > +#define WE_C_MAX (__WE_C_MAX - 1) > > + > > +#endif /* _GENNL_COMMON_H */ > > diff --git a/security/whiteegret/init.c b/security/whiteegret/init.c > > new file mode 100644 > > index 0000000..76254ef > > --- /dev/null > > +++ b/security/whiteegret/init.c > > @@ -0,0 +1,69 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "we.h" > > +#include "print_msg.h" > > + > > +MODULE_LICENSE("GPL"); > > +MODULE_DESCRIPTION("WhiteEgret Linux Security Module"); > > +MODULE_VERSION("1.0.0"); > > + > > +static int we_security_bprm_check(struct linux_binprm *bprm) > > +{ > > + if (we_security_bprm_check_main(bprm) == -EPERM) > > EPERM means that you tried to do a privileged operation, > but didn't have the required capabilities. This is more like > EACCES, where you are asking to perform a mundane operation > but don't have access to the object. > > This applies to most of the cases where you return EPERM. I'll replace EPERM with EACCES. Thank you. Masanobu Koike > > > + return -EPERM; > > + > > + return 0; > > +} > > + > > +static int we_security_mmap_check(struct file *file, unsigned long > reqprot, > > + unsigned long prot, unsigned long flags) > > +{ > > + if (we_security_mmap_check_main(file, reqprot, flags) == -EPERM) > > + return -EPERM; > > + > > + return 0; > > +} > > + > > +static struct security_hook_list we_hooks[] = { > > + LSM_HOOK_INIT(bprm_check_security, we_security_bprm_check), > > + LSM_HOOK_INIT(mmap_file, we_security_mmap_check), > > +}; > > + > > +static int __init we_init(void) > > +{ > > + int rc; > > + > > + if (!security_module_enable("whiteegret")) > > + return 0; > > + > > + security_add_hooks(we_hooks, ARRAY_SIZE(we_hooks), > "whiteegret"); > > + > > + rc = we_specific_init(); > > + if (rc) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + PRINT_WARNING("WhiteEgret (LSM) initialized.\n"); > > + > > + return 0; > > +} > > + > > +static void __exit we_exit(void) > > +{ > > + we_specific_exit(); > > + > > + PRINT_WARNING("WhiteEgret (LSM) exited.\n"); > > +} > > + > > +module_init(we_init); > > +module_exit(we_exit); > > diff --git a/security/whiteegret/main.c b/security/whiteegret/main.c > > new file mode 100644 > > index 0000000..8ba97db > > --- /dev/null > > +++ b/security/whiteegret/main.c > > @@ -0,0 +1,340 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "we_common.h" > > +#include "we.h" > > +#include "request.h" > > +#include "print_msg.h" > > + > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + > > +#include > > +#include > > +#include > > +#include "dd_com.h" > > + > > +#else > > + > > +#include "gennl.h" > > +#include "returntoexec.h" > > + > > +struct we_req_data reqdata; /* data of executable */ > > +struct semaphore we_result_lock; > > +int result = -1; /* result of matching to white list > */ > > + > > +#endif > > + > > +static int send_receive_we_obj_info( > > + struct we_obj_info *we_obj_info, int *checkresult); > > + > > +/** > > + * we_specific_init - Initialize netlink and semaphore. > > + * > > + * Returns 0. > > + */ > > +int we_specific_init(void) > > +{ > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + int rc = 0; > > + > > + rc = we_netlink_register(); > > + if (rc < 0) { > > + PRINT_ERROR(rc); > > + return rc; > > + } > > + > > + sema_init(&we_result_lock, 1); > > +#endif > > + we_req_q_head_init(); > > + > > + return 0; > > +} > > + > > +/** > > + * we_specific_exit - Close netlink. > > + * > > + * Returns 0. > > + */ > > +int we_specific_exit(void) > > +{ > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + we_netlink_unregister(); > > +#endif > > + > > + return 0; > > +} > > + > > +/** > > + * we_check_main - Common function for security_bprm_check and mmap_file. > > + * > > + * @file: Pointer to struct file. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_check_main(struct file *file) > > +{ > > + struct we_obj_info we_obj_info; > > + char *pathnamebuf; > > + char *new_pathnamebuf; > > + char *pathname; > > + char *shortnamebuf; > > + int pathsize; > > + int rc; > > + int i; > > + int checkresult; > > + > > + if (unlikely(file == NULL)) > > + return 0; > > + > > + pathsize = EXPECTPATHSIZE; > > + pathnamebuf = kmalloc(pathsize, GFP_KERNEL); > > + if (unlikely(!pathnamebuf)) { > > + rc = -ENOMEM; > > + PRINT_ERROR(rc); > > + goto failure; > > + } > > + while (pathsize <= MAXPATHSIZE) { > > + pathname = d_absolute_path(&file->f_path, pathnamebuf, > > + pathsize-1); > > + if (!IS_ERR(pathname)) > > + break; > > + > > + pathsize += ADDEDEXPECTPATHSIZE; > > + new_pathnamebuf = krealloc(pathnamebuf, pathsize, > > + GFP_KERNEL); > > + if (unlikely(!new_pathnamebuf)) { > > + rc = -ENOMEM; > > + PRINT_ERROR(rc); > > + goto failure; > > + } > > + pathnamebuf = new_pathnamebuf; > > + } > > + if (unlikely(pathsize >= MAXPATHSIZE)) { > > + rc = -ENOMEM; > > + PRINT_ERROR(rc); > > + goto failure; > > + } > > + > > + shortnamebuf = pathname; > > + for (i = 0; i < pathsize; i++) { > > + if (pathname[i] == '\0') > > + break; > > + if (pathname[i] == '/') > > + shortnamebuf = pathname + (i + 1); > > + } > > + strncpy(we_obj_info.shortname, shortnamebuf, SHORTNAMELENGTH); > > + we_obj_info.path = pathname; > > + we_obj_info.pid = current->pid; > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + we_obj_info.pathsize = strlen(pathname); > > + we_obj_info.ppid = current->tgid; > > +#endif > > + > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + rc = down_timeout(&we_result_lock, WERESULTTIMEOUT); > > + if (rc != 0) > > + goto failure; > > + inc_seq(); > > +#endif > > + rc = send_receive_we_obj_info(&we_obj_info, &checkresult); > > + if (rc < 0) > > + goto failure; > > + > > + rc = checkresult; > > + > > + if (rc == -EPERM) > > + PRINT_WARNING("block %s.\n", pathname); > > + else > > + PRINT_INFO("permit %s.\n", pathname); > > + > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + up(&we_result_lock); > > +#endif > > + > > +failure: > > + if (pathnamebuf != NULL) { > > + kfree(pathnamebuf); > > + pathnamebuf = NULL; > > + } > > + > > + if ((rc != 0) && (rc != -EPERM)) > > + PRINT_WARNING("Checking white list does not work.\n"); > > + > > + return rc; > > +} > > + > > +/** > > + * send_receive_we_obj_info - Send message and wait. > > + * > > + * @we_obj_info: Pointer to struct we_obj_info. > > + * @result: Pointer to result of matching to white list. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +static int send_receive_we_obj_info( > > + struct we_obj_info *we_obj_info, int *checkresult) > > +{ > > + int i; > > + int rc; > > + struct we_req_q req; > > + > > + we_req_q_init(&req, we_obj_info); > > + > > + if ((we_req_q_search(&(req.data))) == NULL) { > > + rc = we_req_q_push(&req); > > + if (rc < 0) { > > + PRINT_ERROR(rc); > > + goto failure; > > + } > > + } > > + > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + > > + for (i = 0; i < MAXCOMRETRY; i++) { > > + rc = send_we_obj_info(&req); > > + > > + if (likely(req.finish_flag == START_EXEC)) { > > + break; > > + } else if (unlikely(rc == -ERESTARTSYS)) { > > + rc = -EINVAL; > > + break; > > + } > > + } > > + > > + we_req_q_pop(&req); > > + > > + if (unlikely(i >= MAXCOMRETRY) && req.finish_flag != START_EXEC) > { > > + rc = -EINVAL; > > + PRINT_ERROR(rc); > > + } > > + > > + *checkresult = req.permit; > > + > > + return rc; > > + > > +#else > > + > > + for (i = 0; i < MAXCOMRETRY; i++) { > > + rc = send_we_obj_info(we_obj_info); > > + if (rc < 0) > > + continue; > > + > > + rc = > wait_for_completion_interruptible_timeout(&(req.evt), > > + WEGENNLTIMEOUT); > > + if (rc <= 0) { > > + if (unlikely(rc == -ERESTARTSYS)) { > > + we_req_q_del(&(req.data)); > > + rc = -EINVAL; > > + PRINT_ERROR(rc); > > + goto failure; > > + } > > + if (rc == 0) > > + rc = -ETIMEDOUT; > > + continue; > > + } else { > > + break; > > + } > > + } > > + > > + if (unlikely(i >= MAXCOMRETRY)) { > > + we_req_q_del(&(req.data)); > > + rc = -EINVAL; > > + PRINT_ERROR(rc); > > + goto failure; > > + } > > + > > + *checkresult = result; > > + > > + return 0; > > + > > +#endif /* CONFIG_SECURITY_WHITEEGRET_DRIVER */ > > + > > +failure: > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + up(&we_result_lock); > > +#endif > > + return rc; > > +} > > + > > +/** > > + * we_security_bprm_check_main - Target for security_bprm_check. > > + * > > + * @bprm: Pointer to struct linux_binprm. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_security_bprm_check_main(struct linux_binprm *bprm) > > +{ > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + if (unlikely(!from_task)) > > +#else > > + if (unlikely(from_pid == -1)) > > +#endif > > + return 0; > > + > > + return we_check_main(bprm->file); > > +} > > + > > +/** > > + * we_security_mmap_check_main - Target for mmap_file. > > + * > > + * @file: Pointer to struct file to map. > > + * @reqprot: Protection requested by the application. > > + * @flags: Operational flags. > > + * > > + * Returns 0 if succeeded, < 0 otherwise. > > + */ > > +int we_security_mmap_check_main(struct file *file, > > + unsigned long reqprot, unsigned long flags) { > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + if (unlikely(!from_task)) > > +#else > > + if (unlikely(from_pid == -1)) > > +#endif > > + return 0; > > + > > + if (!(reqprot & PROT_EXEC)) > > + return 0; > > + > > + if ((flags & MAP_EXECUTABLE)) > > + return 0; > > + > > + if (!file) > > + return 0; > > + > > + if (!file->f_path.dentry) > > + return 0; > > + > > + return we_check_main(file); > > +} > > + > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + > > +/** > > + * returntoexec - Record matching data and result. > > + * > > + * @result_: Result whether targeted object is included in the white > list. > > + * @reqdata_: Pointer to struct we_req_data. > > + * > > + * Returns 0. > > + */ > > +int returntoexec(int result_, struct we_req_data *reqdata_) > > +{ > > + if (!result_) > > + result = -EPERM; > > + else > > + result = 0; > > + memcpy(&reqdata, reqdata_, sizeof(struct we_req_data)); > > + > > + return 0; > > +} > > + > > +#endif > > diff --git a/security/whiteegret/print_msg.h > b/security/whiteegret/print_msg.h > > new file mode 100644 > > index 0000000..2d6fe86 > > --- /dev/null > > +++ b/security/whiteegret/print_msg.h > > @@ -0,0 +1,19 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _PRINT_MSG_H > > +#define _PRINT_MSG_H > > + > > +#include > > + > > +#define __STR(x) #x > > +#define __STR2(x) __STR(x) > > +#define ERROR_MSG "error %d at "__STR2(__LINE__)" on " > __STR2(__FILE__)"\n" > > +#define PRINT_ERROR(errno) pr_err("WhiteEgret: " ERROR_MSG, errno) > > +#define PRINT_WARNING(fmt, ...) pr_warn("WhiteEgret: " fmt, > ##__VA_ARGS__) > > +#define PRINT_INFO(fmt, ...) pr_info("WhiteEgret: " fmt, ##__VA_ARGS__) > > + > > +#endif > > diff --git a/security/whiteegret/request.c > b/security/whiteegret/request.c > > new file mode 100644 > > index 0000000..fc1da9b > > --- /dev/null > > +++ b/security/whiteegret/request.c > > @@ -0,0 +1,248 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "we_common.h" > > +#include "request.h" > > +#include "print_msg.h" > > + > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > +#include "gennl.h" > > +#endif > > + > > +struct we_req_q_head we_q_head; > > + > > +static int match_we_req_data(struct we_req_data *data1, > > + struct we_req_data *data2); > > + > > +/** > > + * we_req_q_init - Initialize the global variable we_q_head. > > + * > > + * Returns 0. > > + */ > > +int we_req_q_head_init(void) > > +{ > > + rwlock_init(&(we_q_head.lock)); > > + INIT_LIST_HEAD(&(we_q_head.head)); > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + init_waitqueue_head(&(we_q_head.waitq)); > > +#endif > > + > > + return 0; > > +} > > + > > +/** > > + * we_req_q_push - Add queue to tail of the list. > > + * > > + * @queue: Pointer to we_req_q to be added to the list. > > + * > > + * Returns 0. > > + */ > > +int we_req_q_push(struct we_req_q *queue) > > +{ > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + init_completion(&(queue->evt)); > > +#endif > > + > > + write_lock(&(we_q_head.lock)); > > + list_add_tail(&(queue->queue), &we_q_head.head); > > + write_unlock(&(we_q_head.lock)); > > + > > + return 0; > > +} > > + > > +/** > > + * we_req_q_search - Search data in the list. > > + * > > + * @data: Pointer to we_req_data to be searched in the list. > > + * > > + * Returns pointer to data if data is found in the list, > > + * NULL otherwise. > > + */ > > +struct we_req_q *we_req_q_search(struct we_req_data *data) > > +{ > > + struct list_head *p; > > + struct we_req_q *req; > > + > > + read_lock(&(we_q_head.lock)); > > + > > + list_for_each(p, &(we_q_head.head)) { > > + req = list_entry(p, struct we_req_q, queue); > > + > > + if (match_we_req_data(data, &(req->data))) { > > + read_unlock(&(we_q_head.lock)); > > + return req; > > + } > > + } > > + > > + read_unlock(&(we_q_head.lock)); > > + > > + return NULL; > > +} > > + > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + > > +/** > > + * we_req_q_init - Initialize queue. > > + * > > + * @req: Pointer to we_req_q to be initialized. > > + * @info: Pointer to we_obj_info. > > + * > > + * Returns 0. > > + */ > > +int we_req_q_init(struct we_req_q *req, struct we_obj_info *info) > > +{ > > + req->finish_flag = STOP_EXEC; > > + req->data.we_obj_info = info; > > + req->permit = -EPERM; > > + init_waitqueue_head(&req->waitq); > > + > > + return 0; > > +} > > + > > +/** > > + * we_req_q_pop - Delete queue in the list. > > + * > > + * Returns 0. > > + */ > > +int we_req_q_pop(struct we_req_q *queue) > > +{ > > + write_lock(&(we_q_head.lock)); > > + list_del(&queue->queue); > > + write_unlock(&(we_q_head.lock)); > > + > > + return 0; > > +} > > + > > +/** > > + * match_we_req_data - Compare two we_req_data data. > > + * > > + * @data1: Pointer to we_req_data > > + * @data2: Pointer to we_req_data > > + * > > + * Returns 1 if all members of both we_req_data data are equal, > > + * 0 otherwise. > > + */ > > +static int match_we_req_data(struct we_req_data *data1, > > + struct we_req_data *data2) > > +{ > > + if (data1->we_obj_info->ppid == data2->we_obj_info->ppid) > > + return 1; > > + > > + return 0; > > +} > > + > > +/** > > + * we_req_q_cleanup - Cleaning up queues. > > + * > > + * Returns 0. > > + */ > > +int we_req_q_cleanup(void) > > +{ > > + struct list_head *p; > > + struct we_req_q *req; > > + > > + write_lock(&(we_q_head.lock)); > > + list_for_each(p, &we_q_head.head) { > > + req = list_entry(p, struct we_req_q, queue); > > + req->finish_flag = START_EXEC; > > + req->permit = -EINVAL; > > + } > > + write_unlock(&(we_q_head.lock)); > > + > > + return 0; > > +} > > + > > +#else /* CONFIG_SECURITY_WHITEEGRET_DRIVER */ > > + > > +/** > > + * we_req_q_init - Initialize queue. > > + * > > + * @req: Pointer to we_req_q to be initialized. > > + * @info: Pointer to we_obj_info. > > + * > > + * Returns 0. > > + */ > > +int we_req_q_init(struct we_req_q *req, struct we_obj_info *info) > > +{ > > + strncpy(req->data.shortname, info->shortname, SHORTNAMELENGTH); > > + req->data.seq = get_seq(); > > + > > + return 0; > > +} > > + > > +/** > > + * we_req_q_specific_pull - Wait completion and delete queue in the list. > > + * > > + * @data: Pointer to we_req_data to be deleteed in the list. > > + * > > + * Returns WE_FOUND_REQUEST if data is found in the list, > > + * WE_NOT_FOUND_REQUEST otherwise. > > + */ > > +int we_req_q_specific_pull(struct we_req_data *data) > > +{ > > + struct we_req_q *req; > > + > > + req = we_req_q_search(data); > > + if (req != NULL) { > > + write_lock(&(we_q_head.lock)); > > + complete_all(&(req->evt)); > > + list_del(&req->queue); > > + write_unlock(&(we_q_head.lock)); > > + return WE_FOUND_REQUEST; > > + } > > + > > + return WE_NOTFOUND_REQUEST; > > +} > > + > > +/** > > + * we_req_q_del - Delete queue in the list. > > + * > > + * @data: Pointer to we_req_data to be deleteed in the list. > > + * > > + * Returns WE_FOUND_REQUEST if data is found in the list, > > + * WE_NOT_FOUND_REQUEST otherwise. > > + */ > > +int we_req_q_del(struct we_req_data *data) > > +{ > > + struct we_req_q *req; > > + > > + req = we_req_q_search(data); > > + if (req != NULL) { > > + write_lock(&(we_q_head.lock)); > > + list_del(&req->queue); > > + write_unlock(&(we_q_head.lock)); > > + return WE_FOUND_REQUEST; > > + } > > + > > + return WE_NOTFOUND_REQUEST; > > +} > > + > > +/** > > + * match_we_req_data - Compare two we_req_data data. > > + * > > + * @data1: Pointer to we_req_data > > + * @data2: Pointer to we_req_data > > + * > > + * Returns 1 if all members of both we_req_data data are equal, > > + * 0 otherwise. > > + */ > > +static int match_we_req_data(struct we_req_data *data1, > > + struct we_req_data *data2) > > +{ > > + if (strncmp(data1->shortname, data2->shortname, SHORTNAMELENGTH) > == 0) { > > + if (data1->seq == data2->seq) > > + return 1; > > + } > > + > > + return 0; > > +} > > + > > +#endif /* CONFIG_SECURITY_WHITEEGRET_DRIVER */ > > diff --git a/security/whiteegret/request.h > b/security/whiteegret/request.h > > new file mode 100644 > > index 0000000..1ad9439 > > --- /dev/null > > +++ b/security/whiteegret/request.h > > @@ -0,0 +1,79 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _REQUEST_H > > +#define _REQUEST_H > > + > > +#include > > +#include > > + > > +#include "we.h" > > + > > +struct we_req_q_head { > > + struct list_head head; > > + rwlock_t lock; > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + wait_queue_head_t waitq; > > +#endif > > +}; > > + > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + > > +#define STOP_EXEC 0 > > +#define START_EXEC 1 > > + > > +extern struct we_req_q_head we_q_head; > > + > > +/* Structure for information of request from kernel space to user space > */ > > +struct we_req_data { > > + struct we_obj_info *we_obj_info; > > +}; > > + > > +struct we_req_q { > > + struct list_head queue; > > + int finish_flag; > > + struct we_req_data data; > > + int permit; > > + wait_queue_head_t waitq; > > +}; > > + > > +int we_req_q_pop(struct we_req_q *queue); > > +int we_req_q_cleanup(void); > > + > > +#else /* CONFIG_SECURITY_WHITEEGRET_DRIVER */ > > + > > +#include > > + > > +/* Return values of searching queue of requests */ > > +enum { > > + WE_NOTFOUND_REQUEST, > > + WE_FOUND_REQUEST > > +}; > > + > > +/* Structure for information of request from kernel space to user space > */ > > +struct we_req_data { > > + char shortname[SHORTNAMELENGTH]; /* file name */ > > + u32 seq; /* sequence number */ > > +}; > > + > > +/* Structure for queue of requests */ > > +struct we_req_q { > > + struct list_head queue; > > + struct completion evt; > > + struct we_req_data data; > > +}; > > + > > +int we_req_q_specific_pull(struct we_req_data *data); > > +int we_req_q_del(struct we_req_data *data); > > + > > +#endif /* CONFIG_SECURITY_WHITEEGRET_DRIVER */ > > + > > +int we_req_q_head_init(void); > > +int we_req_q_init(struct we_req_q *req, struct we_obj_info *info); > > +int we_req_q_push(struct we_req_q *queue); > > +struct we_req_q *we_req_q_search(struct we_req_data *data); > > + > > +#endif /* _REQUEST_H */ > > diff --git a/security/whiteegret/returntoexec.h > b/security/whiteegret/returntoexec.h > > new file mode 100644 > > index 0000000..7fae897 > > --- /dev/null > > +++ b/security/whiteegret/returntoexec.h > > @@ -0,0 +1,14 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _RETURNTOEXEC_H > > +#define _RETURNTOEXEC_H > > + > > +#include "request.h" > > + > > +int returntoexec(int result_, struct we_req_data *reqdata_); > > + > > +#endif > > diff --git a/security/whiteegret/we.h b/security/whiteegret/we.h > > new file mode 100644 > > index 0000000..4a357e6 > > --- /dev/null > > +++ b/security/whiteegret/we.h > > @@ -0,0 +1,72 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _WE_H > > +#define _WE_H > > + > > +#include > > +#include > > +#include "we_common.h" > > + > > +/* > > + * Initial size in byte of memory allocation to store the path > > + * of an object file > > + */ > > +#define EXPECTPATHSIZE 1023 > > + > > +/* > > + * Default size in byte to expand block that stores the path > > + * of an object file when the memory block is too small > > + * to store the path > > + */ > > +#define ADDEDEXPECTPATHSIZE 1023 > > + > > +/* Maximum length in byte of path of object file */ > > +#define MAXPATHSIZE 8184 > > + > > +/* > > + * Maximum number of retry for sending the same message > > + * to user whitelisting application > > + */ > > +#define MAXCOMRETRY 3 > > + > > +/* Timeout value in millisecond to aquire the semaphore */ > > +#define WERESULTTIMEOUT 1000 > > + > > +#ifndef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + > > +/* > > + * Timeout value in jiffies to wait response from > > + * user whitelisting application > > + */ > > +#define WEGENNLTIMEOUT 1000 > > + > > +#endif > > + > > +/* > > + * Structure for an object to be tested whether it is contained > > + * in the whitelist or not > > + */ > > +struct we_obj_info { > > + char shortname[SHORTNAMELENGTH]; /* short name for the object */ > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + int pathsize; > > +#endif > > + char *path; /* full path to the object */ > > + pid_t pid; > > +#ifdef CONFIG_SECURITY_WHITEEGRET_DRIVER > > + pid_t ppid; > > +#endif > > +}; > > + > > +int we_security_bprm_check_main(struct linux_binprm *bprm); > > +int we_security_mmap_check_main(struct file *file, > > + unsigned long reqprot, unsigned long flags); > > + > > +int we_specific_init(void); > > +int we_specific_exit(void); > > + > > +#endif /* _WE_H */ > > diff --git a/security/whiteegret/we_common.h > b/security/whiteegret/we_common.h > > new file mode 100644 > > index 0000000..1288562 > > --- /dev/null > > +++ b/security/whiteegret/we_common.h > > @@ -0,0 +1,19 @@ > > +/* > > + * WhiteEgret Linux Security Module > > + * > > + * Copyright (C) 2017 Toshiba Corporation > > + */ > > + > > +#ifndef _WE_COMMON_H > > +#define _WE_COMMON_H > > + > > +/* > > + * Maximum length in byte of authentication credentials > > + * of user's whitelisting application > > + */ > > +#define AUTHINFOLENGTH 0 > > + > > +/* Maximum length in byte of name of executable file */ > > +#define SHORTNAMELENGTH 256 > > + > > +#endif /* _WE_COMMON_H */ >