From: Casey Schaufler <casey@schaufler-ca.com>
To: casey.schaufler@intel.com, jmorris@namei.org,
linux-security-module@vger.kernel.org, selinux@vger.kernel.org
Cc: casey@schaufler-ca.com, keescook@chromium.org,
john.johansen@canonical.com, penguin-kernel@i-love.sakura.ne.jp,
paul@paul-moore.com, sds@tycho.nsa.gov
Subject: [PATCH v8 15/28] LSM: Specify which LSM to display
Date: Thu, 29 Aug 2019 16:29:22 -0700 [thread overview]
Message-ID: <20190829232935.7099-16-casey@schaufler-ca.com> (raw)
In-Reply-To: <20190829232935.7099-1-casey@schaufler-ca.com>
Create a new entry "display" in /proc/.../attr for controlling
which LSM security information is displayed for a process.
The name of an active LSM that supplies hooks for human readable
data may be written to "display" to set the value. This requires
CAP_MAC_ADMIN privilege. The name of the LSM currently in use can
be read from "display". At this point there can only be one LSM
capable of display active. A helper function lsm_task_display()
is provided to get the display slot for a task_struct.
Note that procfs restricts writes in the attr directory to 'self'.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/proc/base.c | 1 +
include/linux/lsm_hooks.h | 15 ++++
security/security.c | 148 +++++++++++++++++++++++++++++++++-----
3 files changed, 147 insertions(+), 17 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ddef482f1334..7bf70e041315 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2618,6 +2618,7 @@ static const struct pid_entry attr_dir_stuff[] = {
ATTR(NULL, "fscreate", 0666),
ATTR(NULL, "keycreate", 0666),
ATTR(NULL, "sockcreate", 0666),
+ ATTR(NULL, "display", 0666),
#ifdef CONFIG_SECURITY_SMACK
DIR("smack", 0555,
proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index fe1fb7a69ee5..33e5ab4af9f8 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2134,4 +2134,19 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
extern int lsm_inode_alloc(struct inode *inode);
+/**
+ * lsm_task_display - the "display LSM for this task
+ * @task: The task to report on
+ *
+ * Returns the task's display LSM slot.
+ */
+static inline int lsm_task_display(struct task_struct *task)
+{
+ int *display = task->security;
+
+ if (display)
+ return *display;
+ return LSMBLOB_INVALID;
+}
+
#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/security.c b/security/security.c
index 8927508b2142..c3c9bd88b7af 100644
--- a/security/security.c
+++ b/security/security.c
@@ -31,6 +31,7 @@
#include <linux/backing-dev.h>
#include <linux/string.h>
#include <linux/msg.h>
+#include <linux/binfmts.h>
#include <net/flow.h>
#include <net/sock.h>
@@ -46,7 +47,14 @@ static struct kmem_cache *lsm_file_cache;
static struct kmem_cache *lsm_inode_cache;
char *lsm_names;
-static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
+
+/*
+ * The task blob includes the "display" slot used for
+ * chosing which module presents contexts.
+ */
+static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init = {
+ .lbs_task = sizeof(int),
+};
/* Boot-time LSM user choice */
static __initdata const char *chosen_lsm_order;
@@ -423,8 +431,10 @@ static int lsm_append(const char *new, char **result)
/*
* Current index to use while initializing the lsmblob secid list.
+ * Pointers to the LSM id structures for local use.
*/
static int lsm_slot __lsm_ro_after_init;
+static struct lsm_id *lsm_slotlist[LSMBLOB_ENTRIES];
/**
* security_add_hooks - Add a modules hooks to the hook lists.
@@ -444,6 +454,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
if (lsmid->slot == LSMBLOB_NEEDED) {
if (lsm_slot >= LSMBLOB_ENTRIES)
panic("%s Too many LSMs registered.\n", __func__);
+ lsm_slotlist[lsm_slot] = lsmid;
lsmid->slot = lsm_slot++;
init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm,
lsmid->slot);
@@ -564,6 +575,8 @@ int lsm_inode_alloc(struct inode *inode)
*/
static int lsm_task_alloc(struct task_struct *task)
{
+ int *display;
+
if (blob_sizes.lbs_task == 0) {
task->security = NULL;
return 0;
@@ -572,6 +585,15 @@ static int lsm_task_alloc(struct task_struct *task)
task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL);
if (task->security == NULL)
return -ENOMEM;
+
+ /*
+ * The start of the task blob contains the "display" LSM slot number.
+ * Start with it set to the invalid slot number, indicating that the
+ * default first registered LSM be displayed.
+ */
+ display = task->security;
+ *display = LSMBLOB_INVALID;
+
return 0;
}
@@ -1563,14 +1585,26 @@ int security_file_open(struct file *file)
int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
{
+ int *odisplay = current->security;
+ int *ndisplay;
int rc = lsm_task_alloc(task);
- if (rc)
+ if (unlikely(rc))
return rc;
+
rc = call_int_hook(task_alloc, 0, task, clone_flags);
- if (unlikely(rc))
+ if (unlikely(rc)) {
security_task_free(task);
- return rc;
+ return rc;
+ }
+
+ if (odisplay) {
+ ndisplay = task->security;
+ if (ndisplay)
+ *ndisplay = *odisplay;
+ }
+
+ return 0;
}
void security_task_free(struct task_struct *task)
@@ -1967,23 +2001,89 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
char **value)
{
struct security_hook_list *hp;
+ int display = lsm_task_display(current);
+ int slot = 0;
+
+ if (!strcmp(name, "display")) {
+ /*
+ * lsm_slot will be 0 if there are no displaying modules.
+ */
+ if (lsm_slot == 0)
+ return -EINVAL;
+ if (display != LSMBLOB_INVALID)
+ slot = display;
+ *value = kstrdup(lsm_slotlist[slot]->lsm, GFP_KERNEL);
+ if (*value)
+ return strlen(*value);
+ return -ENOMEM;
+ }
hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
continue;
+ if (lsm == NULL && display != LSMBLOB_INVALID &&
+ display != hp->lsmid->slot)
+ continue;
return hp->hook.getprocattr(p, name, value);
}
return -EINVAL;
}
+/**
+ * security_setprocattr - Set process attributes via /proc
+ * @lsm: name of module involved, or NULL
+ * @name: name of the attribute
+ * @value: value to set the attribute to
+ * @size: size of the value
+ *
+ * Set the process attribute for the specified security module
+ * to the specified value. Note that this can only be used to set
+ * the process attributes for the current, or "self" process.
+ * The /proc code has already done this check.
+ *
+ * Returns 0 on success, an appropriate code otherwise.
+ */
int security_setprocattr(const char *lsm, const char *name, void *value,
size_t size)
{
struct security_hook_list *hp;
+ char *term;
+ char *cp;
+ int *display = current->security;
+ int rc = -EINVAL;
+ int slot = 0;
+
+ if (!strcmp(name, "display")) {
+ if (!capable(CAP_MAC_ADMIN))
+ return -EPERM;
+ /*
+ * lsm_slot will be 0 if there are no displaying modules.
+ */
+ if (lsm_slot == 0 || size == 0)
+ return -EINVAL;
+ term = kmemdup_nul(value, size, GFP_KERNEL);
+ if (term == NULL)
+ return -ENOMEM;
+
+ cp = strsep(&term, " \n");
+
+ for (slot = 0; slot < lsm_slot; slot++)
+ if (!strcmp(cp, lsm_slotlist[slot]->lsm)) {
+ *display = lsm_slotlist[slot]->slot;
+ rc = size;
+ break;
+ }
+
+ kfree(cp);
+ return rc;
+ }
hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
continue;
+ if (lsm == NULL && *display != LSMBLOB_INVALID &&
+ *display != hp->lsmid->slot)
+ continue;
return hp->hook.setprocattr(name, value, size);
}
return -EINVAL;
@@ -2003,15 +2103,15 @@ EXPORT_SYMBOL(security_ismaclabel);
int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen)
{
struct security_hook_list *hp;
- int rc;
+ int display = lsm_task_display(current);
hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
continue;
- rc = hp->hook.secid_to_secctx(blob->secid[hp->lsmid->slot],
- secdata, seclen);
- if (rc != 0)
- return rc;
+ if (display == LSMBLOB_INVALID || display == hp->lsmid->slot)
+ return hp->hook.secid_to_secctx(
+ blob->secid[hp->lsmid->slot],
+ secdata, seclen);
}
return 0;
}
@@ -2021,16 +2121,15 @@ int security_secctx_to_secid(const char *secdata, u32 seclen,
struct lsmblob *blob)
{
struct security_hook_list *hp;
- int rc;
+ int display = lsm_task_display(current);
lsmblob_init(blob, 0);
hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid, list) {
if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
continue;
- rc = hp->hook.secctx_to_secid(secdata, seclen,
- &blob->secid[hp->lsmid->slot]);
- if (rc != 0)
- return rc;
+ if (display == LSMBLOB_INVALID || display == hp->lsmid->slot)
+ return hp->hook.secctx_to_secid(secdata, seclen,
+ &blob->secid[hp->lsmid->slot]);
}
return 0;
}
@@ -2038,7 +2137,15 @@ EXPORT_SYMBOL(security_secctx_to_secid);
void security_release_secctx(char *secdata, u32 seclen)
{
- call_void_hook(release_secctx, secdata, seclen);
+ struct security_hook_list *hp;
+ int *display = current->security;
+
+ hlist_for_each_entry(hp, &security_hook_heads.release_secctx, list)
+ if (display == NULL || *display == LSMBLOB_INVALID ||
+ *display == hp->lsmid->slot) {
+ hp->hook.release_secctx(secdata, seclen);
+ return;
+ }
}
EXPORT_SYMBOL(security_release_secctx);
@@ -2163,8 +2270,15 @@ EXPORT_SYMBOL(security_sock_rcv_skb);
int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
int __user *optlen, unsigned len)
{
- return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock,
- optval, optlen, len);
+ int display = lsm_task_display(current);
+ struct security_hook_list *hp;
+
+ hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream,
+ list)
+ if (display == LSMBLOB_INVALID || display == hp->lsmid->slot)
+ return hp->hook.socket_getpeersec_stream(sock, optval,
+ optlen, len);
+ return -ENOPROTOOPT;
}
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
--
2.20.1
next prev parent reply other threads:[~2019-08-29 23:30 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-29 23:29 [PATCH v8 00/28] LSM: Module stacking for AppArmor Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 01/28] LSM: Infrastructure management of the superblock Casey Schaufler
2019-09-16 18:19 ` Stephen Smalley
2019-08-29 23:29 ` [PATCH v8 02/28] LSM: Infrastructure management of the sock security Casey Schaufler
2019-09-16 18:42 ` Stephen Smalley
2019-09-18 7:19 ` John Johansen
2019-08-29 23:29 ` [PATCH v8 03/28] LSM: Infrastructure management of the key blob Casey Schaufler
2019-09-16 18:47 ` Stephen Smalley
2019-08-29 23:29 ` [PATCH v8 04/28] LSM: Create and manage the lsmblob data structure Casey Schaufler
2019-09-16 19:15 ` Stephen Smalley
2019-09-23 15:56 ` Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 05/28] LSM: Use lsmblob in security_audit_rule_match Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 06/28] LSM: Use lsmblob in security_kernel_act_as Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 07/28] net: Prepare UDS for security module stacking Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 08/28] LSM: Use lsmblob in security_secctx_to_secid Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 09/28] LSM: Use lsmblob in security_secid_to_secctx Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 10/28] LSM: Use lsmblob in security_ipc_getsecid Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 11/28] LSM: Use lsmblob in security_task_getsecid Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 12/28] LSM: Use lsmblob in security_inode_getsecid Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 13/28] LSM: Use lsmblob in security_cred_getsecid Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 14/28] IMA: Change internal interfaces to use lsmblobs Casey Schaufler
2019-08-29 23:29 ` Casey Schaufler [this message]
2019-08-29 23:29 ` [PATCH v8 16/28] LSM: Ensure the correct LSM context releaser Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 17/28] LSM: Use lsmcontext in security_secid_to_secctx Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 18/28] LSM: Use lsmcontext in security_dentry_init_security Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 19/28] LSM: Use lsmcontext in security_inode_getsecctx Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 20/28] LSM: security_secid_to_secctx in netlink netfilter Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 21/28] NET: Store LSM netlabel data in a lsmblob Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 22/28] SELinux: Verify LSM display sanity in binder Casey Schaufler
2019-09-18 17:43 ` Stephen Smalley
2019-08-29 23:29 ` [PATCH v8 23/28] Audit: Add subj_LSM fields when necessary Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 24/28] Audit: Include object data for all security modules Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 25/28] LSM: Provide an user space interface for the default display Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 26/28] NET: Add SO_PEERCONTEXT for multiple LSMs Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 27/28] LSM: Add /proc attr entry for full LSM context Casey Schaufler
2019-08-29 23:29 ` [PATCH v8 28/28] AppArmor: Remove the exclusive flag Casey Schaufler
2019-09-04 19:13 ` [PATCH v8 00/28] LSM: Module stacking for AppArmor Casey Schaufler
2019-09-06 13:46 ` Stephen Smalley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190829232935.7099-16-casey@schaufler-ca.com \
--to=casey@schaufler-ca.com \
--cc=casey.schaufler@intel.com \
--cc=jmorris@namei.org \
--cc=john.johansen@canonical.com \
--cc=keescook@chromium.org \
--cc=linux-security-module@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=penguin-kernel@i-love.sakura.ne.jp \
--cc=sds@tycho.nsa.gov \
--cc=selinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).