2018-08-21 00:07:02

by Schaufler, Casey

[permalink] [raw]
Subject: [PATCH RFC v3 0/5] LSM: Add and use a hook for side-channel safety checks

v3: get_task_cred wasn't a good choice due to refcounts.
Use lower level protection instead
v2: SELinux access policy corrected.
Use real_cred instead of cred.

This patchset provide a mechanism by which a security module
can advise the system about potential side-channel vulnerabilities.
If security_safe_sidechannel() returns 0 the security modules do
not know of any data that would be subject to a side-channel
attack. If the security module maintains data that it believes
may be susceptible to a side-channel attack it will return -EACCES.

Simple hooks are provided for SELinux and Smack. A new security
module is provided to make determinations regarding traditional
task attributes, including user IDs, capability sets and namespaces.

Signed-off-by: Casey Schaufler <[email protected]>

---
MAINTAINERS | 6 ++
arch/x86/mm/tlb.c | 12 ++-
include/linux/lsm_hooks.h | 12 +++
include/linux/security.h | 1 +
security/Kconfig | 1 +
security/Makefile | 2 +
security/security.c | 6 ++
security/selinux/hooks.c | 9 +++
security/sidechannel/Kconfig | 60 ++++++++++++++
security/sidechannel/Makefile | 1 +
security/sidechannel/sidechannel.c | 162 +++++++++++++++++++++++++++++++++++++
security/smack/smack_lsm.c | 18 +++++
12 files changed, 286 insertions(+), 4 deletions(-)


2018-08-21 00:07:02

by Schaufler, Casey

[permalink] [raw]
Subject: [PATCH v3 4/5] Smack: Support determination of side-channel

Smack considers its private task data safe if the current task
has read access to the passed task.

Signed-off-by: Casey Schaufler <[email protected]>
---
security/smack/smack_lsm.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 91750205a5de..85dc053e610c 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2299,6 +2299,23 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
isp->smk_inode = skp;
}

+/**
+ * smack_task_safe_sidechannel - Are the task and current sidechannel safe?
+ * @p: task to check on
+ *
+ * A crude value for sidechannel safety is that the current task is
+ * already allowed to read from the other.
+ *
+ * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
+ */
+static int smack_task_safe_sidechannel(struct task_struct *p)
+{
+ struct smack_known *skp = smk_of_task_struct(p);
+ struct smack_known *ckp = smk_of_task_struct(current);
+
+ return smk_access(ckp, skp, MAY_READ, NULL);
+}
+
/*
* Socket hooks.
*/
@@ -4718,6 +4735,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_movememory, smack_task_movememory),
LSM_HOOK_INIT(task_kill, smack_task_kill),
LSM_HOOK_INIT(task_to_inode, smack_task_to_inode),
+ LSM_HOOK_INIT(task_safe_sidechannel, smack_task_safe_sidechannel),

LSM_HOOK_INIT(ipc_permission, smack_ipc_permission),
LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid),
--
2.17.1


2018-08-21 00:07:02

by Schaufler, Casey

[permalink] [raw]
Subject: [PATCH v3 5/5] SELinux: Support SELinux determination of side-channel

SELinux considers tasks to be side-channel safe if they
have FILE__READ access.

Signed-off-by: Casey Schaufler <[email protected]>
---
security/selinux/hooks.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a8bf324130f5..992f2402edaa 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4219,6 +4219,14 @@ static void selinux_task_to_inode(struct task_struct *p,
spin_unlock(&isec->lock);
}

+static int selinux_task_safe_sidechannel(struct task_struct *p)
+{
+ struct av_decision avd;
+
+ return avc_has_perm_noaudit(&selinux_state, current_sid(), task_sid(p),
+ SECCLASS_FILE, FILE__READ, 0, &avd);
+}
+
/* Returns error only if unable to parse addresses */
static int selinux_parse_skb_ipv4(struct sk_buff *skb,
struct common_audit_data *ad, u8 *proto)
@@ -7002,6 +7010,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
LSM_HOOK_INIT(task_kill, selinux_task_kill),
LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
+ LSM_HOOK_INIT(task_safe_sidechannel, selinux_task_safe_sidechannel),

LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
--
2.17.1


2018-08-21 00:07:02

by Schaufler, Casey

[permalink] [raw]
Subject: [PATCH v3 2/5] X86: Support LSM determination of side-channel

When switching between tasks it may be necessary
to set an indirect branch prediction barrier if the
tasks are potentially vulnerable to side-channel
attacks. This adds a call to security_task_safe_sidechannel
so that security modules can weigh in on the decision.

Signed-off-by: Casey Schaufler <[email protected]>
---
arch/x86/mm/tlb.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 6eb1f34c3c85..8714d4af06aa 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -7,6 +7,7 @@
#include <linux/export.h>
#include <linux/cpu.h>
#include <linux/debugfs.h>
+#include <linux/security.h>

#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
@@ -270,11 +271,14 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
* threads. It will also not flush if we switch to idle
* thread and back to the same process. It will flush if we
* switch to a different non-dumpable process.
+ * If a security module thinks that the transition
+ * is unsafe do the flush.
*/
- if (tsk && tsk->mm &&
- tsk->mm->context.ctx_id != last_ctx_id &&
- get_dumpable(tsk->mm) != SUID_DUMP_USER)
- indirect_branch_prediction_barrier();
+ if (tsk && tsk->mm && tsk->mm->context.ctx_id != last_ctx_id) {
+ if (get_dumpable(tsk->mm) != SUID_DUMP_USER ||
+ security_task_safe_sidechannel(tsk) != 0)
+ indirect_branch_prediction_barrier();
+ }

if (IS_ENABLED(CONFIG_VMAP_STACK)) {
/*
--
2.17.1


2018-08-21 00:07:02

by Schaufler, Casey

[permalink] [raw]
Subject: [PATCH v3 1/5] LSM: Introduce a hook for side-channel danger

There may be cases where the data maintained for
security controls is more sensitive than general
process information and that may be subjected to
side-channel attacks. An LSM hook is provided so
that this can be check for where the system would
take action should the current task have potential
access to the passed task.

Signed-off-by: Casey Schaufler <[email protected]>
---
include/linux/lsm_hooks.h | 7 +++++++
include/linux/security.h | 1 +
security/security.c | 5 +++++
3 files changed, 13 insertions(+)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index a08bc2587b96..fd2a7e6beb01 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -698,6 +698,11 @@
* security attributes, e.g. for /proc/pid inodes.
* @p contains the task_struct for the task.
* @inode contains the inode structure for the inode.
+ * @task_safe_sidechannel:
+ * Check if a side channel attack is harmless for the current task and @p.
+ * The caller may have determined that no attack is possible, in which
+ * case this hook won't get called.
+ * @p contains the task_struct for the task.
*
* Security hooks for Netlink messaging.
*
@@ -1611,6 +1616,7 @@ union security_list_options {
int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
+ int (*task_safe_sidechannel)(struct task_struct *p);

int (*ipc_permission)(struct kern_ipc_perm *ipcp, short flag);
void (*ipc_getsecid)(struct kern_ipc_perm *ipcp, u32 *secid);
@@ -1897,6 +1903,7 @@ struct security_hook_heads {
struct hlist_head task_kill;
struct hlist_head task_prctl;
struct hlist_head task_to_inode;
+ struct hlist_head task_safe_sidechannel;
struct hlist_head ipc_permission;
struct hlist_head ipc_getsecid;
struct hlist_head msg_msg_alloc_security;
diff --git a/include/linux/security.h b/include/linux/security.h
index 3410acfe139c..69a5526f789f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -366,6 +366,7 @@ int security_task_kill(struct task_struct *p, struct siginfo *info,
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
void security_task_to_inode(struct task_struct *p, struct inode *inode);
+int security_task_safe_sidechannel(struct task_struct *p);
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
int security_msg_msg_alloc(struct msg_msg *msg);
diff --git a/security/security.c b/security/security.c
index 4927e7cc7d96..353b711e635a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1165,6 +1165,11 @@ void security_task_to_inode(struct task_struct *p, struct inode *inode)
call_void_hook(task_to_inode, p, inode);
}

+int security_task_safe_sidechannel(struct task_struct *p)
+{
+ return call_int_hook(task_safe_sidechannel, 0, p);
+}
+
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
return call_int_hook(ipc_permission, 0, ipcp, flag);
--
2.17.1


2018-08-21 00:07:33

by Schaufler, Casey

[permalink] [raw]
Subject: [PATCH v3 3/5] LSM: Security module checking for side-channel dangers

The sidechannel LSM checks for cases where a side-channel
attack may be dangerous based on security attributes of tasks.
This includes:
Effective UID of the tasks is different
Capablity sets are different
Tasks are in different namespaces
An option is also provided to assert that task are never
to be considered safe. This is high paranoia, and expensive
as well.

Signed-off-by: Casey Schaufler <[email protected]>
---
MAINTAINERS | 6 ++
include/linux/lsm_hooks.h | 5 +
security/Kconfig | 1 +
security/Makefile | 2 +
security/security.c | 1 +
security/sidechannel/Kconfig | 60 +++++++++++
security/sidechannel/Makefile | 1 +
security/sidechannel/sidechannel.c | 162 +++++++++++++++++++++++++++++
8 files changed, 238 insertions(+)
create mode 100644 security/sidechannel/Kconfig
create mode 100644 security/sidechannel/Makefile
create mode 100644 security/sidechannel/sidechannel.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3119bba7971c..d078d6a5b471 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13066,6 +13066,12 @@ F: drivers/slimbus/
F: Documentation/devicetree/bindings/slimbus/
F: include/linux/slimbus.h

+SIDECHANNEL SECURITY MODULE
+M: Casey Schaufler <[email protected]>
+L: [email protected]
+S: Maintained
+F: security/sidechannel/
+
SMACK SECURITY MODULE
M: Casey Schaufler <[email protected]>
L: [email protected]
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index fd2a7e6beb01..d48e4a085fe2 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2088,5 +2088,10 @@ void __init loadpin_add_hooks(void);
#else
static inline void loadpin_add_hooks(void) { };
#endif
+#ifdef CONFIG_SECURITY_SIDECHANNEL
+void __init sidechannel_add_hooks(void);
+#else
+static inline void sidechannel_add_hooks(void) { };
+#endif

#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/Kconfig b/security/Kconfig
index c4302067a3ad..28cb7b2939ee 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -237,6 +237,7 @@ source security/tomoyo/Kconfig
source security/apparmor/Kconfig
source security/loadpin/Kconfig
source security/yama/Kconfig
+source security/sidechannel/Kconfig

source security/integrity/Kconfig

diff --git a/security/Makefile b/security/Makefile
index 4d2d3782ddef..d0c9e1b227f9 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -10,6 +10,7 @@ subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
subdir-$(CONFIG_SECURITY_YAMA) += yama
subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin
+subdir-$(CONFIG_SECURITY_SIDECHANNEL) += sidechannel

# always enable default capabilities
obj-y += commoncap.o
@@ -25,6 +26,7 @@ obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/
obj-$(CONFIG_SECURITY_YAMA) += yama/
obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/
+obj-$(CONFIG_SECURITY_SIDECHANNEL) += sidechannel/
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o

# Object integrity file lists
diff --git a/security/security.c b/security/security.c
index 353b711e635a..777919349751 100644
--- a/security/security.c
+++ b/security/security.c
@@ -80,6 +80,7 @@ int __init security_init(void)
capability_add_hooks();
yama_add_hooks();
loadpin_add_hooks();
+ sidechannel_add_hooks();

/*
* Load all the remaining security modules.
diff --git a/security/sidechannel/Kconfig b/security/sidechannel/Kconfig
new file mode 100644
index 000000000000..af9396534128
--- /dev/null
+++ b/security/sidechannel/Kconfig
@@ -0,0 +1,60 @@
+config SECURITY_SIDECHANNEL
+ bool "Sidechannel attack safety extra checks"
+ depends on SECURITY
+ default n
+ help
+ Look for a variety of cases where a side-channel attack
+ could potentially be exploited. Instruct the switching
+ code to use the indirect_branch_prediction_barrier in
+ cases where the passed task and the current task may be
+ at risk.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_SIDECHANNEL_UIDS
+ bool "Sidechannel check on UID"
+ depends on SECURITY_SIDECHANNEL
+ default n
+ help
+ Assume that tasks with different effective UIDs may be
+ subject to side-channel attacks. As most task switching
+ occurs between tasks with different effective UIDs this
+ can have a significant performance impact.
+
+ If you are unsure how to answer this question, answer N.
+
+
+config SECURITY_SIDECHANNEL_CAPABILITIES
+ bool "Sidechannel check on capability sets"
+ depends on SECURITY_SIDECHANNEL
+ default n
+ help
+ Assume that tasks with different sets of privilege may be
+ subject to side-channel attacks. Potential interactions
+ where the attacker lacks capabilities the attacked has
+ are blocked.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_SIDECHANNEL_NAMESPACES
+ bool "Sidechannel check on namespaces"
+ depends on SECURITY_SIDECHANNEL
+ depends on NAMESPACES
+ default n
+ help
+ Assume that tasks in different namespaces may be
+ subject to side-channel attacks. User, PID and cgroup
+ namespaces are checked.
+
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_SIDECHANNEL_ALWAYS
+ bool "Sidechannel assumed to always be possible"
+ depends on SECURITY_SIDECHANNEL
+ default n
+ help
+ Assume that all tasks may be subject to side-channel attacks.
+ Always instruct the system to use countermeasures regardless
+ of the potential impact.
+
+ If you are unsure how to answer this question, answer N.
diff --git a/security/sidechannel/Makefile b/security/sidechannel/Makefile
new file mode 100644
index 000000000000..f61d83f28035
--- /dev/null
+++ b/security/sidechannel/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SECURITY_SIDECHANNEL) += sidechannel.o
diff --git a/security/sidechannel/sidechannel.c b/security/sidechannel/sidechannel.c
new file mode 100644
index 000000000000..4da7d6dafdc5
--- /dev/null
+++ b/security/sidechannel/sidechannel.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Side Channel Safety Security Module
+ *
+ * Copyright (C) 2018 Intel Corporation.
+ *
+ */
+
+#define pr_fmt(fmt) "SideChannel: " fmt
+
+#include <linux/types.h>
+#include <linux/lsm_hooks.h>
+#include <linux/capability.h>
+#include <linux/cred.h>
+#include <linux/sched.h>
+#include <linux/string_helpers.h>
+#include <linux/nsproxy.h>
+#include <linux/pid_namespace.h>
+
+#ifdef CONFIG_SECURITY_SIDECHANNEL_ALWAYS
+static int sidechannel_task_safe_sidechannel(struct task_struct *p)
+{
+ return -EACCES;
+}
+#else
+/*
+ * safe_by_uid - Are task and current sidechannel safe?
+ * @p: task to check on
+ *
+ * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
+ */
+#ifdef CONFIG_SECURITY_SIDECHANNEL_UIDS
+static int safe_by_uid(struct task_struct *p)
+{
+ const struct cred *ccred = current_real_cred();
+ const struct cred *pcred = rcu_dereference_protected(p->real_cred, 1);
+
+ /*
+ * Credential checks. Considered safe if:
+ * UIDs are the same
+ */
+ if (ccred != pcred && ccred->euid.val != pcred->euid.val)
+ return -EACCES;
+ return 0;
+}
+#else
+static inline int safe_by_uid(struct task_struct *p)
+{
+ return 0;
+}
+#endif
+
+/*
+ * safe_by_capability - Are task and current sidechannel safe?
+ * @p: task to check on
+ *
+ * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
+ */
+#ifdef CONFIG_SECURITY_SIDECHANNEL_CAPABILITIES
+static int safe_by_capability(struct task_struct *p)
+{
+ const struct cred *ccred = current_real_cred();
+ const struct cred *pcred = rcu_dereference_protected(p->real_cred, 1);
+
+ /*
+ * Capabilities checks. Considered safe if:
+ * current has all the capabilities p does
+ */
+ if (ccred != pcred &&
+ !cap_issubset(pcred->cap_effective, ccred->cap_effective))
+ return -EACCES;
+ return 0;
+}
+#else
+static inline int safe_by_capability(struct task_struct *p)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SECURITY_SIDECHANNEL_NAMESPACES
+/**
+ * safe_by_namespace - Are task and current sidechannel safe?
+ * @p: task to check on
+ *
+ * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
+ */
+static int safe_by_namespace(struct task_struct *p)
+{
+ struct cgroup_namespace *ccgn = NULL;
+ struct cgroup_namespace *pcgn = NULL;
+ const struct cred *ccred;
+ const struct cred *pcred;
+
+ /*
+ * Namespace checks. Considered safe if:
+ * cgroup namespace is the same
+ * User namespace is the same
+ * PID namespace is the same
+ */
+ if (current->nsproxy)
+ ccgn = current->nsproxy->cgroup_ns;
+ if (p->nsproxy)
+ pcgn = p->nsproxy->cgroup_ns;
+ if (ccgn != pcgn)
+ return -EACCES;
+
+ ccred = current_real_cred();
+ pcred = rcu_dereference_protected(p->real_cred, 1);
+
+ if (ccred->user_ns != pcred->user_ns)
+ return -EACCES;
+ if (task_active_pid_ns(current) != task_active_pid_ns(p))
+ return -EACCES;
+ return 0;
+}
+#else
+static inline int safe_by_namespace(struct task_struct *p)
+{
+ return 0;
+}
+#endif
+
+/**
+ * sidechannel_task_safe_sidechannel - Are task and current sidechannel safe?
+ * @p: task to check on
+ *
+ * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
+ */
+static int sidechannel_task_safe_sidechannel(struct task_struct *p)
+{
+ int rc;
+
+ /*
+ * Easy optimizations
+ */
+ if (p == current || p->pid == current->pid)
+ return 0;
+
+ rc = safe_by_uid(p);
+ if (rc)
+ return rc;
+ rc = safe_by_capability(p);
+ if (rc)
+ return rc;
+ rc = safe_by_namespace(p);
+ if (rc)
+ return rc;
+ return 0;
+}
+#endif /* CONFIG_SECURITY_SIDECHANNEL_ALWAYS */
+
+static struct security_hook_list sidechannel_hooks[] __lsm_ro_after_init = {
+ LSM_HOOK_INIT(task_safe_sidechannel, sidechannel_task_safe_sidechannel),
+};
+
+void __init sidechannel_add_hooks(void)
+{
+ pr_info("Extra sidechannel checks enabled\n");
+ security_add_hooks(sidechannel_hooks, ARRAY_SIZE(sidechannel_hooks),
+ "sidechannel");
+}
--
2.17.1


2018-08-21 17:26:19

by Jann Horn

[permalink] [raw]
Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel dangers

On Tue, Aug 21, 2018 at 2:05 AM Casey Schaufler
<[email protected]> wrote:
>
> The sidechannel LSM checks for cases where a side-channel
> attack may be dangerous based on security attributes of tasks.
> This includes:
> Effective UID of the tasks is different
> Capablity sets are different
> Tasks are in different namespaces
> An option is also provided to assert that task are never
> to be considered safe. This is high paranoia, and expensive
> as well.
>
> Signed-off-by: Casey Schaufler <[email protected]>
> ---
[...]
> diff --git a/security/sidechannel/Kconfig b/security/sidechannel/Kconfig
> new file mode 100644
> index 000000000000..af9396534128
> --- /dev/null
> +++ b/security/sidechannel/Kconfig
[...]
> +config SECURITY_SIDECHANNEL_CAPABILITIES
> + bool "Sidechannel check on capability sets"
> + depends on SECURITY_SIDECHANNEL
> + default n
> + help
> + Assume that tasks with different sets of privilege may be
> + subject to side-channel attacks. Potential interactions
> + where the attacker lacks capabilities the attacked has
> + are blocked.
> +
> + If you are unsure how to answer this question, answer N.
> +
> +config SECURITY_SIDECHANNEL_NAMESPACES
> + bool "Sidechannel check on namespaces"
> + depends on SECURITY_SIDECHANNEL
> + depends on NAMESPACES
> + default n
> + help
> + Assume that tasks in different namespaces may be
> + subject to side-channel attacks. User, PID and cgroup
> + namespaces are checked.
> +
> + If you are unsure how to answer this question, answer N.
[...]
> diff --git a/security/sidechannel/sidechannel.c b/security/sidechannel/sidechannel.c
> new file mode 100644
> index 000000000000..4da7d6dafdc5
> --- /dev/null
> +++ b/security/sidechannel/sidechannel.c
[...]
> +/*
> + * safe_by_capability - Are task and current sidechannel safe?
> + * @p: task to check on
> + *
> + * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
> + */
> +#ifdef CONFIG_SECURITY_SIDECHANNEL_CAPABILITIES
> +static int safe_by_capability(struct task_struct *p)
> +{
> + const struct cred *ccred = current_real_cred();
> + const struct cred *pcred = rcu_dereference_protected(p->real_cred, 1);
> +
> + /*
> + * Capabilities checks. Considered safe if:
> + * current has all the capabilities p does
> + */
> + if (ccred != pcred &&
> + !cap_issubset(pcred->cap_effective, ccred->cap_effective))
> + return -EACCES;
> + return 0;
> +}

On its own (without safe_by_namespace()), this check makes no sense, I
think. You're performing a test on the namespaced capability sets
without looking at which user namespaces they are relative to. Maybe
either introduce a configuration dependency or add an extra namespace
check here?

> +static int safe_by_namespace(struct task_struct *p)
> +{
> + struct cgroup_namespace *ccgn = NULL;
> + struct cgroup_namespace *pcgn = NULL;
> + const struct cred *ccred;
> + const struct cred *pcred;
> +
> + /*
> + * Namespace checks. Considered safe if:
> + * cgroup namespace is the same
> + * User namespace is the same
> + * PID namespace is the same
> + */
> + if (current->nsproxy)
> + ccgn = current->nsproxy->cgroup_ns;
> + if (p->nsproxy)
> + pcgn = p->nsproxy->cgroup_ns;
> + if (ccgn != pcgn)
> + return -EACCES;
> +
> + ccred = current_real_cred();
> + pcred = rcu_dereference_protected(p->real_cred, 1);
> +
> + if (ccred->user_ns != pcred->user_ns)
> + return -EACCES;
> + if (task_active_pid_ns(current) != task_active_pid_ns(p))
> + return -EACCES;
> + return 0;
> +}

2018-08-21 23:51:45

by Schaufler, Casey

[permalink] [raw]
Subject: RE: [PATCH v3 3/5] LSM: Security module checking for side-channel dangers

> -----Original Message-----
> From: Jann Horn [mailto:[email protected]]
> Sent: Tuesday, August 21, 2018 10:24 AM
> To: Schaufler, Casey <[email protected]>
> Cc: Kernel Hardening <[email protected]>; kernel list
> <[email protected]>; linux-security-module <linux-security-
> [email protected]>; [email protected]; Hansen, Dave
> <[email protected]>; Dock, Deneen T <[email protected]>;
> [email protected]; Arjan van de Ven <[email protected]>
> Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel
> dangers
>
> On Tue, Aug 21, 2018 at 2:05 AM Casey Schaufler
> <[email protected]> wrote:
> >
> > The sidechannel LSM checks for cases where a side-channel
> > attack may be dangerous based on security attributes of tasks.
> > This includes:
> > Effective UID of the tasks is different
> > Capablity sets are different
> > Tasks are in different namespaces
> > An option is also provided to assert that task are never
> > to be considered safe. This is high paranoia, and expensive
> > as well.
> >
> > Signed-off-by: Casey Schaufler <[email protected]>
> > ---
> [...]
> > diff --git a/security/sidechannel/Kconfig b/security/sidechannel/Kconfig
> > new file mode 100644
> > index 000000000000..af9396534128
> > --- /dev/null
> > +++ b/security/sidechannel/Kconfig
> [...]
> > +config SECURITY_SIDECHANNEL_CAPABILITIES
> > + bool "Sidechannel check on capability sets"
> > + depends on SECURITY_SIDECHANNEL
> > + default n
> > + help
> > + Assume that tasks with different sets of privilege may be
> > + subject to side-channel attacks. Potential interactions
> > + where the attacker lacks capabilities the attacked has
> > + are blocked.
> > +
> > + If you are unsure how to answer this question, answer N.
> > +
> > +config SECURITY_SIDECHANNEL_NAMESPACES
> > + bool "Sidechannel check on namespaces"
> > + depends on SECURITY_SIDECHANNEL
> > + depends on NAMESPACES
> > + default n
> > + help
> > + Assume that tasks in different namespaces may be
> > + subject to side-channel attacks. User, PID and cgroup
> > + namespaces are checked.
> > +
> > + If you are unsure how to answer this question, answer N.
> [...]
> > diff --git a/security/sidechannel/sidechannel.c
> b/security/sidechannel/sidechannel.c
> > new file mode 100644
> > index 000000000000..4da7d6dafdc5
> > --- /dev/null
> > +++ b/security/sidechannel/sidechannel.c
> [...]
> > +/*
> > + * safe_by_capability - Are task and current sidechannel safe?
> > + * @p: task to check on
> > + *
> > + * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
> > + */
> > +#ifdef CONFIG_SECURITY_SIDECHANNEL_CAPABILITIES
> > +static int safe_by_capability(struct task_struct *p)
> > +{
> > + const struct cred *ccred = current_real_cred();
> > + const struct cred *pcred = rcu_dereference_protected(p->real_cred, 1);
> > +
> > + /*
> > + * Capabilities checks. Considered safe if:
> > + * current has all the capabilities p does
> > + */
> > + if (ccred != pcred &&
> > + !cap_issubset(pcred->cap_effective, ccred->cap_effective))
> > + return -EACCES;
> > + return 0;
> > +}
>
> On its own (without safe_by_namespace()), this check makes no sense, I
> think. You're performing a test on the namespaced capability sets
> without looking at which user namespaces they are relative to. Maybe
> either introduce a configuration dependency or add an extra namespace
> check here?

If you don't have namespaces the check is correct. If you do, and use
safe_by_namespace() you're also correct. If you use namespaces and
care about side-channel attacks you should enable the namespace checks.
I don't see real value in adding namespace checks in the capability checks
for the event where someone has said they don't want namespace checks.

I got early feedback that configurability was considered important.
This is the correct behavior if you want namespace checks to be
separately configurable from capability checks. You could ask for
distinct configuration options for each kind of namespace, but, well, yuck.

> > +static int safe_by_namespace(struct task_struct *p)
> > +{
> > + struct cgroup_namespace *ccgn = NULL;
> > + struct cgroup_namespace *pcgn = NULL;
> > + const struct cred *ccred;
> > + const struct cred *pcred;
> > +
> > + /*
> > + * Namespace checks. Considered safe if:
> > + * cgroup namespace is the same
> > + * User namespace is the same
> > + * PID namespace is the same
> > + */
> > + if (current->nsproxy)
> > + ccgn = current->nsproxy->cgroup_ns;
> > + if (p->nsproxy)
> > + pcgn = p->nsproxy->cgroup_ns;
> > + if (ccgn != pcgn)
> > + return -EACCES;
> > +
> > + ccred = current_real_cred();
> > + pcred = rcu_dereference_protected(p->real_cred, 1);
> > +
> > + if (ccred->user_ns != pcred->user_ns)
> > + return -EACCES;
> > + if (task_active_pid_ns(current) != task_active_pid_ns(p))
> > + return -EACCES;
> > + return 0;
> > +}

2018-08-22 01:25:03

by Jann Horn

[permalink] [raw]
Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel dangers

On Wed, Aug 22, 2018 at 1:44 AM Schaufler, Casey
<[email protected]> wrote:
>
> > -----Original Message-----
> > From: Jann Horn [mailto:[email protected]]
> > Sent: Tuesday, August 21, 2018 10:24 AM
> > To: Schaufler, Casey <[email protected]>
> > Cc: Kernel Hardening <[email protected]>; kernel list
> > <[email protected]>; linux-security-module <linux-security-
> > [email protected]>; [email protected]; Hansen, Dave
> > <[email protected]>; Dock, Deneen T <[email protected]>;
> > [email protected]; Arjan van de Ven <[email protected]>
> > Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel
> > dangers
> >
> > On Tue, Aug 21, 2018 at 2:05 AM Casey Schaufler
> > <[email protected]> wrote:
> > >
> > > The sidechannel LSM checks for cases where a side-channel
> > > attack may be dangerous based on security attributes of tasks.
> > > This includes:
> > > Effective UID of the tasks is different
> > > Capablity sets are different
> > > Tasks are in different namespaces
> > > An option is also provided to assert that task are never
> > > to be considered safe. This is high paranoia, and expensive
> > > as well.
> > >
> > > Signed-off-by: Casey Schaufler <[email protected]>
> > > ---
> > [...]
> > > diff --git a/security/sidechannel/Kconfig b/security/sidechannel/Kconfig
> > > new file mode 100644
> > > index 000000000000..af9396534128
> > > --- /dev/null
> > > +++ b/security/sidechannel/Kconfig
> > [...]
> > > +config SECURITY_SIDECHANNEL_CAPABILITIES
> > > + bool "Sidechannel check on capability sets"
> > > + depends on SECURITY_SIDECHANNEL
> > > + default n
> > > + help
> > > + Assume that tasks with different sets of privilege may be
> > > + subject to side-channel attacks. Potential interactions
> > > + where the attacker lacks capabilities the attacked has
> > > + are blocked.
> > > +
> > > + If you are unsure how to answer this question, answer N.
> > > +
> > > +config SECURITY_SIDECHANNEL_NAMESPACES
> > > + bool "Sidechannel check on namespaces"
> > > + depends on SECURITY_SIDECHANNEL
> > > + depends on NAMESPACES
> > > + default n
> > > + help
> > > + Assume that tasks in different namespaces may be
> > > + subject to side-channel attacks. User, PID and cgroup
> > > + namespaces are checked.
> > > +
> > > + If you are unsure how to answer this question, answer N.
> > [...]
> > > diff --git a/security/sidechannel/sidechannel.c
> > b/security/sidechannel/sidechannel.c
> > > new file mode 100644
> > > index 000000000000..4da7d6dafdc5
> > > --- /dev/null
> > > +++ b/security/sidechannel/sidechannel.c
> > [...]
> > > +/*
> > > + * safe_by_capability - Are task and current sidechannel safe?
> > > + * @p: task to check on
> > > + *
> > > + * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
> > > + */
> > > +#ifdef CONFIG_SECURITY_SIDECHANNEL_CAPABILITIES
> > > +static int safe_by_capability(struct task_struct *p)
> > > +{
> > > + const struct cred *ccred = current_real_cred();
> > > + const struct cred *pcred = rcu_dereference_protected(p->real_cred, 1);
> > > +
> > > + /*
> > > + * Capabilities checks. Considered safe if:
> > > + * current has all the capabilities p does
> > > + */
> > > + if (ccred != pcred &&
> > > + !cap_issubset(pcred->cap_effective, ccred->cap_effective))
> > > + return -EACCES;
> > > + return 0;
> > > +}
> >
> > On its own (without safe_by_namespace()), this check makes no sense, I
> > think. You're performing a test on the namespaced capability sets
> > without looking at which user namespaces they are relative to. Maybe
> > either introduce a configuration dependency or add an extra namespace
> > check here?
>
> If you don't have namespaces the check is correct. If you do, and use
> safe_by_namespace() you're also correct. If you use namespaces and
> care about side-channel attacks you should enable the namespace checks.

By "use namespaces", you mean "have CONFIG_USER_NS=y set in the kernel
config", right?
It doesn't matter much whether processes on your system are
intentionally using namespaces; what matters is whether some random
process can just use unshare(CLONE_NEWUSER) to increase its apparent
capabilities and bypass the checks performed by this LSM.
My expectation is that unshare(CLONE_NEWUSER) should not increase the
caller's abilities. Your patch seems to violate that expectation.

> I don't see real value in adding namespace checks in the capability checks
> for the event where someone has said they don't want namespace checks.

Capabilities are meaningless if you don't consider the namespaces
relative to which they are effective. Anyone can get CAP_SYS_ADMIN or
whatever other capabilities they want, by design - just not relative
to objects they don't own. Look:

$ grep ^Cap /proc/self/status
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
$ unshare -Ur grep ^Cap /proc/self/status
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

Ta-daa! Full capability set.

> I got early feedback that configurability was considered important.
> This is the correct behavior if you want namespace checks to be
> separately configurable from capability checks. You could ask for
> distinct configuration options for each kind of namespace, but, well, yuck.
>
> > > +static int safe_by_namespace(struct task_struct *p)
> > > +{
> > > + struct cgroup_namespace *ccgn = NULL;
> > > + struct cgroup_namespace *pcgn = NULL;
> > > + const struct cred *ccred;
> > > + const struct cred *pcred;
> > > +
> > > + /*
> > > + * Namespace checks. Considered safe if:
> > > + * cgroup namespace is the same
> > > + * User namespace is the same
> > > + * PID namespace is the same
> > > + */
> > > + if (current->nsproxy)
> > > + ccgn = current->nsproxy->cgroup_ns;
> > > + if (p->nsproxy)
> > > + pcgn = p->nsproxy->cgroup_ns;
> > > + if (ccgn != pcgn)
> > > + return -EACCES;
> > > +
> > > + ccred = current_real_cred();
> > > + pcred = rcu_dereference_protected(p->real_cred, 1);
> > > +
> > > + if (ccred->user_ns != pcred->user_ns)
> > > + return -EACCES;
> > > + if (task_active_pid_ns(current) != task_active_pid_ns(p))
> > > + return -EACCES;
> > > + return 0;
> > > +}

2018-08-22 16:41:32

by Schaufler, Casey

[permalink] [raw]
Subject: RE: [PATCH v3 3/5] LSM: Security module checking for side-channel dangers

> -----Original Message-----
> From: Jann Horn [mailto:[email protected]]
> Sent: Tuesday, August 21, 2018 6:01 PM
> To: Schaufler, Casey <[email protected]>
> Cc: Kernel Hardening <[email protected]>; kernel list
> <[email protected]>; linux-security-module <linux-security-
> [email protected]>; [email protected]; Hansen, Dave
> <[email protected]>; Dock, Deneen T <[email protected]>;
> [email protected]; Arjan van de Ven <[email protected]>
> Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel
> dangers
>
> On Wed, Aug 22, 2018 at 1:44 AM Schaufler, Casey
> <[email protected]> wrote:
> >
> > > -----Original Message-----
> > > From: Jann Horn [mailto:[email protected]]
> > > Sent: Tuesday, August 21, 2018 10:24 AM
> > > To: Schaufler, Casey <[email protected]>
> > > Cc: Kernel Hardening <[email protected]>; kernel list
> > > <[email protected]>; linux-security-module <linux-security-
> > > [email protected]>; [email protected]; Hansen, Dave
> > > <[email protected]>; Dock, Deneen T <[email protected]>;
> > > [email protected]; Arjan van de Ven <[email protected]>
> > > Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel
> > > dangers
> > >
> > > On Tue, Aug 21, 2018 at 2:05 AM Casey Schaufler
> > > <[email protected]> wrote:
> > > >
> > > > The sidechannel LSM checks for cases where a side-channel
> > > > attack may be dangerous based on security attributes of tasks.
> > > > This includes:
> > > > Effective UID of the tasks is different
> > > > Capablity sets are different
> > > > Tasks are in different namespaces
> > > > An option is also provided to assert that task are never
> > > > to be considered safe. This is high paranoia, and expensive
> > > > as well.
> > > >
> > > > Signed-off-by: Casey Schaufler <[email protected]>
> > > > ---
> > > [...]
> > > > diff --git a/security/sidechannel/Kconfig b/security/sidechannel/Kconfig
> > > > new file mode 100644
> > > > index 000000000000..af9396534128
> > > > --- /dev/null
> > > > +++ b/security/sidechannel/Kconfig
> > > [...]
> > > > +config SECURITY_SIDECHANNEL_CAPABILITIES
> > > > + bool "Sidechannel check on capability sets"
> > > > + depends on SECURITY_SIDECHANNEL
> > > > + default n
> > > > + help
> > > > + Assume that tasks with different sets of privilege may be
> > > > + subject to side-channel attacks. Potential interactions
> > > > + where the attacker lacks capabilities the attacked has
> > > > + are blocked.
> > > > +
> > > > + If you are unsure how to answer this question, answer N.
> > > > +
> > > > +config SECURITY_SIDECHANNEL_NAMESPACES
> > > > + bool "Sidechannel check on namespaces"
> > > > + depends on SECURITY_SIDECHANNEL
> > > > + depends on NAMESPACES
> > > > + default n
> > > > + help
> > > > + Assume that tasks in different namespaces may be
> > > > + subject to side-channel attacks. User, PID and cgroup
> > > > + namespaces are checked.
> > > > +
> > > > + If you are unsure how to answer this question, answer N.
> > > [...]
> > > > diff --git a/security/sidechannel/sidechannel.c
> > > b/security/sidechannel/sidechannel.c
> > > > new file mode 100644
> > > > index 000000000000..4da7d6dafdc5
> > > > --- /dev/null
> > > > +++ b/security/sidechannel/sidechannel.c
> > > [...]
> > > > +/*
> > > > + * safe_by_capability - Are task and current sidechannel safe?
> > > > + * @p: task to check on
> > > > + *
> > > > + * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
> > > > + */
> > > > +#ifdef CONFIG_SECURITY_SIDECHANNEL_CAPABILITIES
> > > > +static int safe_by_capability(struct task_struct *p)
> > > > +{
> > > > + const struct cred *ccred = current_real_cred();
> > > > + const struct cred *pcred = rcu_dereference_protected(p->real_cred,
> 1);
> > > > +
> > > > + /*
> > > > + * Capabilities checks. Considered safe if:
> > > > + * current has all the capabilities p does
> > > > + */
> > > > + if (ccred != pcred &&
> > > > + !cap_issubset(pcred->cap_effective, ccred->cap_effective))
> > > > + return -EACCES;
> > > > + return 0;
> > > > +}
> > >
> > > On its own (without safe_by_namespace()), this check makes no sense, I
> > > think. You're performing a test on the namespaced capability sets
> > > without looking at which user namespaces they are relative to. Maybe
> > > either introduce a configuration dependency or add an extra namespace
> > > check here?
> >
> > If you don't have namespaces the check is correct. If you do, and use
> > safe_by_namespace() you're also correct. If you use namespaces and
> > care about side-channel attacks you should enable the namespace checks.
>
> By "use namespaces", you mean "have CONFIG_USER_NS=y set in the kernel
> config", right?

That's correct.

> It doesn't matter much whether processes on your system are
> intentionally using namespaces;

Also correct.

> what matters is whether some random
> process can just use unshare(CLONE_NEWUSER) to increase its apparent
> capabilities and bypass the checks performed by this LSM.

Which puts it in a new user namespace, which gets caught by the
safe_by_namespace() check.

> My expectation is that unshare(CLONE_NEWUSER) should not increase the
> caller's abilities. Your patch seems to violate that expectation.

If you have CONFIG_USER_NS and not
CONFIG_SECURITY_SIDECHANNEL_NAMESPACES you do not increase the
caller's abilities from what you have without safesidechannel. If you have
CONFIG_SECURITY_SIDECHANNEL_NAMESPACES you have additional
restriction (assuming one considers setting the barrier a restriction) that
the tasks must be in the same namespace(s). As I said, if you care about
namespace implications you should configure the system accordingly.

> > I don't see real value in adding namespace checks in the capability checks
> > for the event where someone has said they don't want namespace checks.
>
> Capabilities are meaningless if you don't consider the namespaces
> relative to which they are effective.

Agreed. But if CONFIG_NAMESPACES is off you are always in the same
namespace and if it is on you should use the sidechannel namespace check.

> Anyone can get CAP_SYS_ADMIN or
> whatever other capabilities they want, by design - just not relative
> to objects they don't own. Look:
>
> $ grep ^Cap /proc/self/status
> CapInh: 0000000000000000
> CapPrm: 0000000000000000
> CapEff: 0000000000000000
> CapBnd: 0000003fffffffff
> CapAmb: 0000000000000000
> $ unshare -Ur grep ^Cap /proc/self/status
> CapInh: 0000000000000000
> CapPrm: 0000003fffffffff
> CapEff: 0000003fffffffff
> CapBnd: 0000003fffffffff
> CapAmb: 0000000000000000
>
> Ta-daa! Full capability set.

Yes, but in a different namespace. Hence the namespace check.

What I hear you saying is that you don't want the capability check
to be independent of the namespace check. This conflicts with the
strong desire expressed to me when I started this that the configuration
should be flexible. I can beef up the description of the various options.
Would that address the issue?

>
> > I got early feedback that configurability was considered important.
> > This is the correct behavior if you want namespace checks to be
> > separately configurable from capability checks. You could ask for
> > distinct configuration options for each kind of namespace, but, well, yuck.
> >
> > > > +static int safe_by_namespace(struct task_struct *p)
> > > > +{
> > > > + struct cgroup_namespace *ccgn = NULL;
> > > > + struct cgroup_namespace *pcgn = NULL;
> > > > + const struct cred *ccred;
> > > > + const struct cred *pcred;
> > > > +
> > > > + /*
> > > > + * Namespace checks. Considered safe if:
> > > > + * cgroup namespace is the same
> > > > + * User namespace is the same
> > > > + * PID namespace is the same
> > > > + */
> > > > + if (current->nsproxy)
> > > > + ccgn = current->nsproxy->cgroup_ns;
> > > > + if (p->nsproxy)
> > > > + pcgn = p->nsproxy->cgroup_ns;
> > > > + if (ccgn != pcgn)
> > > > + return -EACCES;
> > > > +
> > > > + ccred = current_real_cred();
> > > > + pcred = rcu_dereference_protected(p->real_cred, 1);
> > > > +
> > > > + if (ccred->user_ns != pcred->user_ns)
> > > > + return -EACCES;
> > > > + if (task_active_pid_ns(current) != task_active_pid_ns(p))
> > > > + return -EACCES;
> > > > + return 0;
> > > > +}

2018-08-22 17:05:35

by Jann Horn

[permalink] [raw]
Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel dangers

On Wed, Aug 22, 2018 at 6:39 PM Schaufler, Casey
<[email protected]> wrote:
>
> > -----Original Message-----
> > From: Jann Horn [mailto:[email protected]]
> > Sent: Tuesday, August 21, 2018 6:01 PM
> > To: Schaufler, Casey <[email protected]>
> > Cc: Kernel Hardening <[email protected]>; kernel list
> > <[email protected]>; linux-security-module <linux-security-
> > [email protected]>; [email protected]; Hansen, Dave
> > <[email protected]>; Dock, Deneen T <[email protected]>;
> > [email protected]; Arjan van de Ven <[email protected]>
> > Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel
> > dangers
> >
> > On Wed, Aug 22, 2018 at 1:44 AM Schaufler, Casey
> > <[email protected]> wrote:
> > >
> > > > -----Original Message-----
> > > > From: Jann Horn [mailto:[email protected]]
> > > > Sent: Tuesday, August 21, 2018 10:24 AM
> > > > To: Schaufler, Casey <[email protected]>
> > > > Cc: Kernel Hardening <[email protected]>; kernel list
> > > > <[email protected]>; linux-security-module <linux-security-
> > > > [email protected]>; [email protected]; Hansen, Dave
> > > > <[email protected]>; Dock, Deneen T <[email protected]>;
> > > > [email protected]; Arjan van de Ven <[email protected]>
> > > > Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel
> > > > dangers
> > > >
> > > > On Tue, Aug 21, 2018 at 2:05 AM Casey Schaufler
> > > > <[email protected]> wrote:
> > > > >
> > > > > The sidechannel LSM checks for cases where a side-channel
> > > > > attack may be dangerous based on security attributes of tasks.
> > > > > This includes:
> > > > > Effective UID of the tasks is different
> > > > > Capablity sets are different
> > > > > Tasks are in different namespaces
> > > > > An option is also provided to assert that task are never
> > > > > to be considered safe. This is high paranoia, and expensive
> > > > > as well.
> > > > >
> > > > > Signed-off-by: Casey Schaufler <[email protected]>
> > > > > ---
> > > > [...]
> > > > > diff --git a/security/sidechannel/Kconfig b/security/sidechannel/Kconfig
> > > > > new file mode 100644
> > > > > index 000000000000..af9396534128
> > > > > --- /dev/null
> > > > > +++ b/security/sidechannel/Kconfig
> > > > [...]
> > > > > +config SECURITY_SIDECHANNEL_CAPABILITIES
> > > > > + bool "Sidechannel check on capability sets"
> > > > > + depends on SECURITY_SIDECHANNEL
> > > > > + default n
> > > > > + help
> > > > > + Assume that tasks with different sets of privilege may be
> > > > > + subject to side-channel attacks. Potential interactions
> > > > > + where the attacker lacks capabilities the attacked has
> > > > > + are blocked.
> > > > > +
> > > > > + If you are unsure how to answer this question, answer N.
> > > > > +
> > > > > +config SECURITY_SIDECHANNEL_NAMESPACES
> > > > > + bool "Sidechannel check on namespaces"
> > > > > + depends on SECURITY_SIDECHANNEL
> > > > > + depends on NAMESPACES
> > > > > + default n
> > > > > + help
> > > > > + Assume that tasks in different namespaces may be
> > > > > + subject to side-channel attacks. User, PID and cgroup
> > > > > + namespaces are checked.
> > > > > +
> > > > > + If you are unsure how to answer this question, answer N.
> > > > [...]
> > > > > diff --git a/security/sidechannel/sidechannel.c
> > > > b/security/sidechannel/sidechannel.c
> > > > > new file mode 100644
> > > > > index 000000000000..4da7d6dafdc5
> > > > > --- /dev/null
> > > > > +++ b/security/sidechannel/sidechannel.c
> > > > [...]
> > > > > +/*
> > > > > + * safe_by_capability - Are task and current sidechannel safe?
> > > > > + * @p: task to check on
> > > > > + *
> > > > > + * Returns 0 if the tasks are sidechannel safe, -EACCES otherwise.
> > > > > + */
> > > > > +#ifdef CONFIG_SECURITY_SIDECHANNEL_CAPABILITIES
> > > > > +static int safe_by_capability(struct task_struct *p)
> > > > > +{
> > > > > + const struct cred *ccred = current_real_cred();
> > > > > + const struct cred *pcred = rcu_dereference_protected(p->real_cred,
> > 1);
> > > > > +
> > > > > + /*
> > > > > + * Capabilities checks. Considered safe if:
> > > > > + * current has all the capabilities p does
> > > > > + */
> > > > > + if (ccred != pcred &&
> > > > > + !cap_issubset(pcred->cap_effective, ccred->cap_effective))
> > > > > + return -EACCES;
> > > > > + return 0;
> > > > > +}
> > > >
> > > > On its own (without safe_by_namespace()), this check makes no sense, I
> > > > think. You're performing a test on the namespaced capability sets
> > > > without looking at which user namespaces they are relative to. Maybe
> > > > either introduce a configuration dependency or add an extra namespace
> > > > check here?
> > >
> > > If you don't have namespaces the check is correct. If you do, and use
> > > safe_by_namespace() you're also correct. If you use namespaces and
> > > care about side-channel attacks you should enable the namespace checks.
> >
> > By "use namespaces", you mean "have CONFIG_USER_NS=y set in the kernel
> > config", right?
>
> That's correct.
>
> > It doesn't matter much whether processes on your system are
> > intentionally using namespaces;
>
> Also correct.
>
> > what matters is whether some random
> > process can just use unshare(CLONE_NEWUSER) to increase its apparent
> > capabilities and bypass the checks performed by this LSM.
>
> Which puts it in a new user namespace, which gets caught by the
> safe_by_namespace() check.
>
> > My expectation is that unshare(CLONE_NEWUSER) should not increase the
> > caller's abilities. Your patch seems to violate that expectation.
>
> If you have CONFIG_USER_NS and not
> CONFIG_SECURITY_SIDECHANNEL_NAMESPACES you do not increase the
> caller's abilities from what you have without safesidechannel. If you have
> CONFIG_SECURITY_SIDECHANNEL_NAMESPACES you have additional
> restriction (assuming one considers setting the barrier a restriction) that
> the tasks must be in the same namespace(s). As I said, if you care about
> namespace implications you should configure the system accordingly.
>
> > > I don't see real value in adding namespace checks in the capability checks
> > > for the event where someone has said they don't want namespace checks.
> >
> > Capabilities are meaningless if you don't consider the namespaces
> > relative to which they are effective.
>
> Agreed. But if CONFIG_NAMESPACES is off you are always in the same
> namespace and if it is on you should use the sidechannel namespace check.
>
> > Anyone can get CAP_SYS_ADMIN or
> > whatever other capabilities they want, by design - just not relative
> > to objects they don't own. Look:
> >
> > $ grep ^Cap /proc/self/status
> > CapInh: 0000000000000000
> > CapPrm: 0000000000000000
> > CapEff: 0000000000000000
> > CapBnd: 0000003fffffffff
> > CapAmb: 0000000000000000
> > $ unshare -Ur grep ^Cap /proc/self/status
> > CapInh: 0000000000000000
> > CapPrm: 0000003fffffffff
> > CapEff: 0000003fffffffff
> > CapBnd: 0000003fffffffff
> > CapAmb: 0000000000000000
> >
> > Ta-daa! Full capability set.
>
> Yes, but in a different namespace. Hence the namespace check.
>
> What I hear you saying is that you don't want the capability check
> to be independent of the namespace check.

The capability check doesn't always require a namespace match, and I
don't care about non-user namespaces here, but I would prefer it if
A->B with A having some capabilities required A's user namespace to be
ancestor-or-self of B's user namespace. But alternatively:

> This conflicts with the
> strong desire expressed to me when I started this that the configuration
> should be flexible. I can beef up the description of the various options.
> Would that address the issue?

It seems to me that it would make sense to express this as something
like a Kconfig dependency. But I guess if you document that the
combination of CONFIG_USER_NS=y,
CONFIG_SECURITY_SIDECHANNEL_NAMESPACES=n and
SECURITY_SIDECHANNEL_CAPABILITIES=y is nonsensical, that works too. I
just don't see why you'd want to provide such a footgun?
Configurability is nice, but if we know that one of the possible
configurations doesn't make sense, it seems like a good idea to just
not allow the system to be configured that way.

You say that you were asked to make the configuration flexible. Did
whoever told you that actually want the ability to compare raw
capability sets on a system with CONFIG_USER_NS=y, and understand what
semantics that has (and doesn't have)? Or was their intent more along
the lines of "we want to flush if the new task has higher privileges,
capability-wise, than the old task; but we don't explicitly care about
namespaces"?

> > > I got early feedback that configurability was considered important.
> > > This is the correct behavior if you want namespace checks to be
> > > separately configurable from capability checks. You could ask for
> > > distinct configuration options for each kind of namespace, but, well, yuck.
> > >
> > > > > +static int safe_by_namespace(struct task_struct *p)
> > > > > +{
> > > > > + struct cgroup_namespace *ccgn = NULL;
> > > > > + struct cgroup_namespace *pcgn = NULL;
> > > > > + const struct cred *ccred;
> > > > > + const struct cred *pcred;
> > > > > +
> > > > > + /*
> > > > > + * Namespace checks. Considered safe if:
> > > > > + * cgroup namespace is the same
> > > > > + * User namespace is the same
> > > > > + * PID namespace is the same
> > > > > + */
> > > > > + if (current->nsproxy)
> > > > > + ccgn = current->nsproxy->cgroup_ns;
> > > > > + if (p->nsproxy)
> > > > > + pcgn = p->nsproxy->cgroup_ns;
> > > > > + if (ccgn != pcgn)
> > > > > + return -EACCES;
> > > > > +
> > > > > + ccred = current_real_cred();
> > > > > + pcred = rcu_dereference_protected(p->real_cred, 1);
> > > > > +
> > > > > + if (ccred->user_ns != pcred->user_ns)
> > > > > + return -EACCES;
> > > > > + if (task_active_pid_ns(current) != task_active_pid_ns(p))
> > > > > + return -EACCES;
> > > > > + return 0;
> > > > > +}

2018-08-22 17:49:28

by Schaufler, Casey

[permalink] [raw]
Subject: RE: [PATCH v3 3/5] LSM: Security module checking for side-channel dangers

> -----Original Message-----
> From: Jann Horn [mailto:[email protected]]
> Sent: Wednesday, August 22, 2018 10:04 AM
> To: Schaufler, Casey <[email protected]>
> Cc: Kernel Hardening <[email protected]>; kernel list
> <[email protected]>; linux-security-module <linux-security-
> [email protected]>; [email protected]; Hansen, Dave
> <[email protected]>; Dock, Deneen T <[email protected]>;
> [email protected]; Arjan van de Ven <[email protected]>
> Subject: Re: [PATCH v3 3/5] LSM: Security module checking for side-channel
> dangers
>
> [SNIP]

> > Yes, but in a different namespace. Hence the namespace check.
> >
> > What I hear you saying is that you don't want the capability check
> > to be independent of the namespace check.
>
> The capability check doesn't always require a namespace match, and I
> don't care about non-user namespaces here, but I would prefer it if
> A->B with A having some capabilities required A's user namespace to be
> ancestor-or-self of B's user namespace. But alternatively:

Looking at ancestor relations starts to get us pretty close to the
point where the cost of checking will overwhelm the savings. This
is something we have to be very careful of.

> > This conflicts with the
> > strong desire expressed to me when I started this that the configuration
> > should be flexible. I can beef up the description of the various options.
> > Would that address the issue?
>
> It seems to me that it would make sense to express this as something
> like a Kconfig dependency.

I thought about that. It could be the best choice. I will investigate
further.

> But I guess if you document that the
> combination of CONFIG_USER_NS=y,
> CONFIG_SECURITY_SIDECHANNEL_NAMESPACES=n and
> SECURITY_SIDECHANNEL_CAPABILITIES=y is nonsensical, that works too. I
> just don't see why you'd want to provide such a footgun?

Point.

> Configurability is nice, but if we know that one of the possible
> configurations doesn't make sense, it seems like a good idea to just
> not allow the system to be configured that way.

Another point.

> You say that you were asked to make the configuration flexible. Did
> whoever told you that actually want the ability to compare raw
> capability sets on a system with CONFIG_USER_NS=y, and understand what
> semantics that has (and doesn't have)? Or was their intent more along
> the lines of "we want to flush if the new task has higher privileges,
> capability-wise, than the old task; but we don't explicitly care about
> namespaces"?

Without going into too much detail, it's a matter of people who
understand chips and performance better than they understand
security or the user experience.