diff mbox series

[v28,03/12] landlock: Set up the security framework and manage credentials

Message ID 20210202162710.657398-4-mic@digikod.net
State Superseded
Headers show
Series Landlock LSM | expand

Commit Message

Mickaël Salaün Feb. 2, 2021, 4:27 p.m. UTC
From: Mickaël Salaün <mic@linux.microsoft.com>

Process's credentials point to a Landlock domain, which is underneath
implemented with a ruleset.  In the following commits, this domain is
used to check and enforce the ptrace and filesystem security policies.
A domain is inherited from a parent to its child the same way a thread
inherits a seccomp policy.

Cc: James Morris <jmorris@namei.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Serge E. Hallyn <serge@hallyn.com>
Signed-off-by: Mickaël Salaün <mic@linux.microsoft.com>
Reviewed-by: Jann Horn <jannh@google.com>
---

Changes since v25:
* Rename function to landlock_add_cred_hooks().

Changes since v23:
* Add an early check for the current domain in hook_cred_free() to avoid
  superfluous call.
* Cosmetic cleanup to make the code more readable.

Changes since v22:
* Add Reviewed-by: Jann Horn <jannh@google.com>

Changes since v21:
* Fix copyright dates.

Changes since v17:
* Constify returned domain pointers from landlock_get_current_domain()
  and landlock_get_task_domain() helpers.

Changes since v15:
* Optimize landlocked() for current thread.
* Display the greeting message when everything is initialized.

Changes since v14:
* Uses pr_fmt from common.h .
* Constify variables.
* Remove useless NULL initialization.

Changes since v13:
* totally get ride of the seccomp dependency
* only keep credential management and LSM setup.

Previous changes:
https://lore.kernel.org/lkml/20191104172146.30797-4-mic@digikod.net/
---
 security/Kconfig           | 10 +++----
 security/landlock/Makefile |  3 +-
 security/landlock/common.h | 20 +++++++++++++
 security/landlock/cred.c   | 46 ++++++++++++++++++++++++++++++
 security/landlock/cred.h   | 58 ++++++++++++++++++++++++++++++++++++++
 security/landlock/setup.c  | 31 ++++++++++++++++++++
 security/landlock/setup.h  | 16 +++++++++++
 7 files changed, 178 insertions(+), 6 deletions(-)
 create mode 100644 security/landlock/common.h
 create mode 100644 security/landlock/cred.c
 create mode 100644 security/landlock/cred.h
 create mode 100644 security/landlock/setup.c
 create mode 100644 security/landlock/setup.h

Comments

Serge E. Hallyn Feb. 4, 2021, 3:46 a.m. UTC | #1
On Tue, Feb 02, 2021 at 05:27:01PM +0100, Mickaël Salaün wrote:
> From: Mickaël Salaün <mic@linux.microsoft.com>

> 

> Process's credentials point to a Landlock domain, which is underneath

> implemented with a ruleset.  In the following commits, this domain is

> used to check and enforce the ptrace and filesystem security policies.

> A domain is inherited from a parent to its child the same way a thread

> inherits a seccomp policy.

> 

> Cc: James Morris <jmorris@namei.org>

> Cc: Kees Cook <keescook@chromium.org>

> Cc: Serge E. Hallyn <serge@hallyn.com>


Acked-by: Serge Hallyn <serge@hallyn.com>


> Signed-off-by: Mickaël Salaün <mic@linux.microsoft.com>

> Reviewed-by: Jann Horn <jannh@google.com>

> ---

> 

> Changes since v25:

> * Rename function to landlock_add_cred_hooks().

> 

> Changes since v23:

> * Add an early check for the current domain in hook_cred_free() to avoid

>   superfluous call.

> * Cosmetic cleanup to make the code more readable.

> 

> Changes since v22:

> * Add Reviewed-by: Jann Horn <jannh@google.com>

> 

> Changes since v21:

> * Fix copyright dates.

> 

> Changes since v17:

> * Constify returned domain pointers from landlock_get_current_domain()

>   and landlock_get_task_domain() helpers.

> 

> Changes since v15:

> * Optimize landlocked() for current thread.

> * Display the greeting message when everything is initialized.

> 

> Changes since v14:

> * Uses pr_fmt from common.h .

> * Constify variables.

> * Remove useless NULL initialization.

> 

> Changes since v13:

> * totally get ride of the seccomp dependency

> * only keep credential management and LSM setup.

> 

> Previous changes:

> https://lore.kernel.org/lkml/20191104172146.30797-4-mic@digikod.net/

> ---

>  security/Kconfig           | 10 +++----

>  security/landlock/Makefile |  3 +-

>  security/landlock/common.h | 20 +++++++++++++

>  security/landlock/cred.c   | 46 ++++++++++++++++++++++++++++++

>  security/landlock/cred.h   | 58 ++++++++++++++++++++++++++++++++++++++

>  security/landlock/setup.c  | 31 ++++++++++++++++++++

>  security/landlock/setup.h  | 16 +++++++++++

>  7 files changed, 178 insertions(+), 6 deletions(-)

>  create mode 100644 security/landlock/common.h

>  create mode 100644 security/landlock/cred.c

>  create mode 100644 security/landlock/cred.h

>  create mode 100644 security/landlock/setup.c

>  create mode 100644 security/landlock/setup.h

> 

> diff --git a/security/Kconfig b/security/Kconfig

> index 15a4342b5d01..0ced7fd33e4d 100644

> --- a/security/Kconfig

> +++ b/security/Kconfig

> @@ -278,11 +278,11 @@ endchoice

>  

>  config LSM

>  	string "Ordered list of enabled LSMs"

> -	default "lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK

> -	default "lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR

> -	default "lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO

> -	default "lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC

> -	default "lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"

> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK

> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR

> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO

> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC

> +	default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"

>  	help

>  	  A comma-separated list of LSMs, in initialization order.

>  	  Any LSMs left off this list will be ignored. This can be

> diff --git a/security/landlock/Makefile b/security/landlock/Makefile

> index d846eba445bb..041ea242e627 100644

> --- a/security/landlock/Makefile

> +++ b/security/landlock/Makefile

> @@ -1,3 +1,4 @@

>  obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o

>  

> -landlock-y := object.o ruleset.o

> +landlock-y := setup.o object.o ruleset.o \

> +	cred.o

> diff --git a/security/landlock/common.h b/security/landlock/common.h

> new file mode 100644

> index 000000000000..5dc0fe15707d

> --- /dev/null

> +++ b/security/landlock/common.h

> @@ -0,0 +1,20 @@

> +/* SPDX-License-Identifier: GPL-2.0-only */

> +/*

> + * Landlock LSM - Common constants and helpers

> + *

> + * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>

> + * Copyright © 2018-2020 ANSSI

> + */

> +

> +#ifndef _SECURITY_LANDLOCK_COMMON_H

> +#define _SECURITY_LANDLOCK_COMMON_H

> +

> +#define LANDLOCK_NAME "landlock"

> +

> +#ifdef pr_fmt

> +#undef pr_fmt

> +#endif

> +

> +#define pr_fmt(fmt) LANDLOCK_NAME ": " fmt

> +

> +#endif /* _SECURITY_LANDLOCK_COMMON_H */

> diff --git a/security/landlock/cred.c b/security/landlock/cred.c

> new file mode 100644

> index 000000000000..6725af24c684

> --- /dev/null

> +++ b/security/landlock/cred.c

> @@ -0,0 +1,46 @@

> +// SPDX-License-Identifier: GPL-2.0-only

> +/*

> + * Landlock LSM - Credential hooks

> + *

> + * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>

> + * Copyright © 2018-2020 ANSSI

> + */

> +

> +#include <linux/cred.h>

> +#include <linux/lsm_hooks.h>

> +

> +#include "common.h"

> +#include "cred.h"

> +#include "ruleset.h"

> +#include "setup.h"

> +

> +static int hook_cred_prepare(struct cred *const new,

> +		const struct cred *const old, const gfp_t gfp)

> +{

> +	struct landlock_ruleset *const old_dom = landlock_cred(old)->domain;

> +

> +	if (old_dom) {

> +		landlock_get_ruleset(old_dom);

> +		landlock_cred(new)->domain = old_dom;

> +	}

> +	return 0;

> +}

> +

> +static void hook_cred_free(struct cred *const cred)

> +{

> +	struct landlock_ruleset *const dom = landlock_cred(cred)->domain;

> +

> +	if (dom)

> +		landlock_put_ruleset_deferred(dom);

> +}

> +

> +static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {

> +	LSM_HOOK_INIT(cred_prepare, hook_cred_prepare),

> +	LSM_HOOK_INIT(cred_free, hook_cred_free),

> +};

> +

> +__init void landlock_add_cred_hooks(void)

> +{

> +	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),

> +			LANDLOCK_NAME);

> +}

> diff --git a/security/landlock/cred.h b/security/landlock/cred.h

> new file mode 100644

> index 000000000000..5f99d3decade

> --- /dev/null

> +++ b/security/landlock/cred.h

> @@ -0,0 +1,58 @@

> +/* SPDX-License-Identifier: GPL-2.0-only */

> +/*

> + * Landlock LSM - Credential hooks

> + *

> + * Copyright © 2019-2020 Mickaël Salaün <mic@digikod.net>

> + * Copyright © 2019-2020 ANSSI

> + */

> +

> +#ifndef _SECURITY_LANDLOCK_CRED_H

> +#define _SECURITY_LANDLOCK_CRED_H

> +

> +#include <linux/cred.h>

> +#include <linux/init.h>

> +#include <linux/rcupdate.h>

> +

> +#include "ruleset.h"

> +#include "setup.h"

> +

> +struct landlock_cred_security {

> +	struct landlock_ruleset *domain;

> +};

> +

> +static inline struct landlock_cred_security *landlock_cred(

> +		const struct cred *cred)

> +{

> +	return cred->security + landlock_blob_sizes.lbs_cred;

> +}

> +

> +static inline const struct landlock_ruleset *landlock_get_current_domain(void)

> +{

> +	return landlock_cred(current_cred())->domain;

> +}

> +

> +/*

> + * The call needs to come from an RCU read-side critical section.

> + */

> +static inline const struct landlock_ruleset *landlock_get_task_domain(

> +		const struct task_struct *const task)

> +{

> +	return landlock_cred(__task_cred(task))->domain;

> +}

> +

> +static inline bool landlocked(const struct task_struct *const task)

> +{

> +	bool has_dom;

> +

> +	if (task == current)

> +		return !!landlock_get_current_domain();

> +

> +	rcu_read_lock();

> +	has_dom = !!landlock_get_task_domain(task);

> +	rcu_read_unlock();

> +	return has_dom;

> +}

> +

> +__init void landlock_add_cred_hooks(void);

> +

> +#endif /* _SECURITY_LANDLOCK_CRED_H */

> diff --git a/security/landlock/setup.c b/security/landlock/setup.c

> new file mode 100644

> index 000000000000..8661112fb238

> --- /dev/null

> +++ b/security/landlock/setup.c

> @@ -0,0 +1,31 @@

> +// SPDX-License-Identifier: GPL-2.0-only

> +/*

> + * Landlock LSM - Security framework setup

> + *

> + * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>

> + * Copyright © 2018-2020 ANSSI

> + */

> +

> +#include <linux/init.h>

> +#include <linux/lsm_hooks.h>

> +

> +#include "common.h"

> +#include "cred.h"

> +#include "setup.h"

> +

> +struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {

> +	.lbs_cred = sizeof(struct landlock_cred_security),

> +};

> +

> +static int __init landlock_init(void)

> +{

> +	landlock_add_cred_hooks();

> +	pr_info("Up and running.\n");

> +	return 0;

> +}

> +

> +DEFINE_LSM(LANDLOCK_NAME) = {

> +	.name = LANDLOCK_NAME,

> +	.init = landlock_init,

> +	.blobs = &landlock_blob_sizes,

> +};

> diff --git a/security/landlock/setup.h b/security/landlock/setup.h

> new file mode 100644

> index 000000000000..9fdbf33fcc33

> --- /dev/null

> +++ b/security/landlock/setup.h

> @@ -0,0 +1,16 @@

> +/* SPDX-License-Identifier: GPL-2.0-only */

> +/*

> + * Landlock LSM - Security framework setup

> + *

> + * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>

> + * Copyright © 2018-2020 ANSSI

> + */

> +

> +#ifndef _SECURITY_LANDLOCK_SETUP_H

> +#define _SECURITY_LANDLOCK_SETUP_H

> +

> +#include <linux/lsm_hooks.h>

> +

> +extern struct lsm_blob_sizes landlock_blob_sizes;

> +

> +#endif /* _SECURITY_LANDLOCK_SETUP_H */

> -- 

> 2.30.0
diff mbox series

Patch

diff --git a/security/Kconfig b/security/Kconfig
index 15a4342b5d01..0ced7fd33e4d 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -278,11 +278,11 @@  endchoice
 
 config LSM
 	string "Ordered list of enabled LSMs"
-	default "lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
-	default "lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
-	default "lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
-	default "lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC
-	default "lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC
+	default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"
 	help
 	  A comma-separated list of LSMs, in initialization order.
 	  Any LSMs left off this list will be ignored. This can be
diff --git a/security/landlock/Makefile b/security/landlock/Makefile
index d846eba445bb..041ea242e627 100644
--- a/security/landlock/Makefile
+++ b/security/landlock/Makefile
@@ -1,3 +1,4 @@ 
 obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o
 
-landlock-y := object.o ruleset.o
+landlock-y := setup.o object.o ruleset.o \
+	cred.o
diff --git a/security/landlock/common.h b/security/landlock/common.h
new file mode 100644
index 000000000000..5dc0fe15707d
--- /dev/null
+++ b/security/landlock/common.h
@@ -0,0 +1,20 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Landlock LSM - Common constants and helpers
+ *
+ * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>
+ * Copyright © 2018-2020 ANSSI
+ */
+
+#ifndef _SECURITY_LANDLOCK_COMMON_H
+#define _SECURITY_LANDLOCK_COMMON_H
+
+#define LANDLOCK_NAME "landlock"
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+
+#define pr_fmt(fmt) LANDLOCK_NAME ": " fmt
+
+#endif /* _SECURITY_LANDLOCK_COMMON_H */
diff --git a/security/landlock/cred.c b/security/landlock/cred.c
new file mode 100644
index 000000000000..6725af24c684
--- /dev/null
+++ b/security/landlock/cred.c
@@ -0,0 +1,46 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Landlock LSM - Credential hooks
+ *
+ * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
+ * Copyright © 2018-2020 ANSSI
+ */
+
+#include <linux/cred.h>
+#include <linux/lsm_hooks.h>
+
+#include "common.h"
+#include "cred.h"
+#include "ruleset.h"
+#include "setup.h"
+
+static int hook_cred_prepare(struct cred *const new,
+		const struct cred *const old, const gfp_t gfp)
+{
+	struct landlock_ruleset *const old_dom = landlock_cred(old)->domain;
+
+	if (old_dom) {
+		landlock_get_ruleset(old_dom);
+		landlock_cred(new)->domain = old_dom;
+	}
+	return 0;
+}
+
+static void hook_cred_free(struct cred *const cred)
+{
+	struct landlock_ruleset *const dom = landlock_cred(cred)->domain;
+
+	if (dom)
+		landlock_put_ruleset_deferred(dom);
+}
+
+static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
+	LSM_HOOK_INIT(cred_prepare, hook_cred_prepare),
+	LSM_HOOK_INIT(cred_free, hook_cred_free),
+};
+
+__init void landlock_add_cred_hooks(void)
+{
+	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
+			LANDLOCK_NAME);
+}
diff --git a/security/landlock/cred.h b/security/landlock/cred.h
new file mode 100644
index 000000000000..5f99d3decade
--- /dev/null
+++ b/security/landlock/cred.h
@@ -0,0 +1,58 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Landlock LSM - Credential hooks
+ *
+ * Copyright © 2019-2020 Mickaël Salaün <mic@digikod.net>
+ * Copyright © 2019-2020 ANSSI
+ */
+
+#ifndef _SECURITY_LANDLOCK_CRED_H
+#define _SECURITY_LANDLOCK_CRED_H
+
+#include <linux/cred.h>
+#include <linux/init.h>
+#include <linux/rcupdate.h>
+
+#include "ruleset.h"
+#include "setup.h"
+
+struct landlock_cred_security {
+	struct landlock_ruleset *domain;
+};
+
+static inline struct landlock_cred_security *landlock_cred(
+		const struct cred *cred)
+{
+	return cred->security + landlock_blob_sizes.lbs_cred;
+}
+
+static inline const struct landlock_ruleset *landlock_get_current_domain(void)
+{
+	return landlock_cred(current_cred())->domain;
+}
+
+/*
+ * The call needs to come from an RCU read-side critical section.
+ */
+static inline const struct landlock_ruleset *landlock_get_task_domain(
+		const struct task_struct *const task)
+{
+	return landlock_cred(__task_cred(task))->domain;
+}
+
+static inline bool landlocked(const struct task_struct *const task)
+{
+	bool has_dom;
+
+	if (task == current)
+		return !!landlock_get_current_domain();
+
+	rcu_read_lock();
+	has_dom = !!landlock_get_task_domain(task);
+	rcu_read_unlock();
+	return has_dom;
+}
+
+__init void landlock_add_cred_hooks(void);
+
+#endif /* _SECURITY_LANDLOCK_CRED_H */
diff --git a/security/landlock/setup.c b/security/landlock/setup.c
new file mode 100644
index 000000000000..8661112fb238
--- /dev/null
+++ b/security/landlock/setup.c
@@ -0,0 +1,31 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Landlock LSM - Security framework setup
+ *
+ * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>
+ * Copyright © 2018-2020 ANSSI
+ */
+
+#include <linux/init.h>
+#include <linux/lsm_hooks.h>
+
+#include "common.h"
+#include "cred.h"
+#include "setup.h"
+
+struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
+	.lbs_cred = sizeof(struct landlock_cred_security),
+};
+
+static int __init landlock_init(void)
+{
+	landlock_add_cred_hooks();
+	pr_info("Up and running.\n");
+	return 0;
+}
+
+DEFINE_LSM(LANDLOCK_NAME) = {
+	.name = LANDLOCK_NAME,
+	.init = landlock_init,
+	.blobs = &landlock_blob_sizes,
+};
diff --git a/security/landlock/setup.h b/security/landlock/setup.h
new file mode 100644
index 000000000000..9fdbf33fcc33
--- /dev/null
+++ b/security/landlock/setup.h
@@ -0,0 +1,16 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Landlock LSM - Security framework setup
+ *
+ * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>
+ * Copyright © 2018-2020 ANSSI
+ */
+
+#ifndef _SECURITY_LANDLOCK_SETUP_H
+#define _SECURITY_LANDLOCK_SETUP_H
+
+#include <linux/lsm_hooks.h>
+
+extern struct lsm_blob_sizes landlock_blob_sizes;
+
+#endif /* _SECURITY_LANDLOCK_SETUP_H */