1 // SPDX-License-Identifier: GPL-2.0
2 /* Lock down the kernel
4 * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
13 #include <linux/security.h>
14 #include <linux/export.h>
15 #include <linux/lsm_hooks.h>
17 static enum lockdown_reason kernel_locked_down
;
19 static const enum lockdown_reason lockdown_levels
[] = {LOCKDOWN_NONE
,
20 LOCKDOWN_INTEGRITY_MAX
,
21 LOCKDOWN_CONFIDENTIALITY_MAX
};
24 * Put the kernel into lock-down mode.
26 static int lock_kernel_down(const char *where
, enum lockdown_reason level
)
28 if (kernel_locked_down
>= level
)
31 kernel_locked_down
= level
;
32 pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",
37 static int __init
lockdown_param(char *level
)
42 if (strcmp(level
, "integrity") == 0)
43 lock_kernel_down("command line", LOCKDOWN_INTEGRITY_MAX
);
44 else if (strcmp(level
, "confidentiality") == 0)
45 lock_kernel_down("command line", LOCKDOWN_CONFIDENTIALITY_MAX
);
52 early_param("lockdown", lockdown_param
);
55 * lockdown_is_locked_down - Find out if the kernel is locked down
56 * @what: Tag to use in notice generated if lockdown is in effect
58 static int lockdown_is_locked_down(enum lockdown_reason what
)
60 if (WARN(what
>= LOCKDOWN_CONFIDENTIALITY_MAX
,
61 "Invalid lockdown reason"))
64 if (kernel_locked_down
>= what
) {
65 if (lockdown_reasons
[what
])
66 pr_notice("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
67 current
->comm
, lockdown_reasons
[what
]);
74 static struct security_hook_list lockdown_hooks
[] __lsm_ro_after_init
= {
75 LSM_HOOK_INIT(locked_down
, lockdown_is_locked_down
),
78 static int __init
lockdown_lsm_init(void)
80 #if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY)
81 lock_kernel_down("Kernel configuration", LOCKDOWN_INTEGRITY_MAX
);
82 #elif defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY)
83 lock_kernel_down("Kernel configuration", LOCKDOWN_CONFIDENTIALITY_MAX
);
85 security_add_hooks(lockdown_hooks
, ARRAY_SIZE(lockdown_hooks
),
90 static ssize_t
lockdown_read(struct file
*filp
, char __user
*buf
, size_t count
,
96 for (i
= 0; i
< ARRAY_SIZE(lockdown_levels
); i
++) {
97 enum lockdown_reason level
= lockdown_levels
[i
];
99 if (lockdown_reasons
[level
]) {
100 const char *label
= lockdown_reasons
[level
];
102 if (kernel_locked_down
== level
)
103 offset
+= sprintf(temp
+offset
, "[%s] ", label
);
105 offset
+= sprintf(temp
+offset
, "%s ", label
);
109 /* Convert the last space to a newline if needed. */
111 temp
[offset
-1] = '\n';
113 return simple_read_from_buffer(buf
, count
, ppos
, temp
, strlen(temp
));
116 static ssize_t
lockdown_write(struct file
*file
, const char __user
*buf
,
117 size_t n
, loff_t
*ppos
)
120 int i
, len
, err
= -EINVAL
;
122 state
= memdup_user_nul(buf
, n
);
124 return PTR_ERR(state
);
127 if (len
&& state
[len
-1] == '\n') {
132 for (i
= 0; i
< ARRAY_SIZE(lockdown_levels
); i
++) {
133 enum lockdown_reason level
= lockdown_levels
[i
];
134 const char *label
= lockdown_reasons
[level
];
136 if (label
&& !strcmp(state
, label
))
137 err
= lock_kernel_down("securityfs", level
);
141 return err
? err
: n
;
144 static const struct file_operations lockdown_ops
= {
145 .read
= lockdown_read
,
146 .write
= lockdown_write
,
149 static int __init
lockdown_secfs_init(void)
151 struct dentry
*dentry
;
153 dentry
= securityfs_create_file("lockdown", 0644, NULL
, NULL
,
155 return PTR_ERR_OR_ZERO(dentry
);
158 core_initcall(lockdown_secfs_init
);
160 #ifdef CONFIG_SECURITY_LOCKDOWN_LSM_EARLY
161 DEFINE_EARLY_LSM(lockdown
) = {
163 DEFINE_LSM(lockdown
) = {
166 .init
= lockdown_lsm_init
,