2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-17 17:53:56 +08:00

Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull security subsystem updates from James Morris:

 - kstrdup() return value fix from Eric Biggers

 - Add new security_load_data hook to differentiate security checking of
   kernel-loaded binaries in the case of there being no associated file
   descriptor, from Mimi Zohar.

 - Add ability to IMA to specify a policy at build-time, rather than
   just via command line params or by loading a custom policy, from
   Mimi.

 - Allow IMA and LSMs to prevent sysfs firmware load fallback (e.g. if
   using signed firmware), from Mimi.

 - Allow IMA to deny loading of kexec kernel images, as they cannot be
   measured by IMA, from Mimi.

* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  security: check for kstrdup() failure in lsm_append()
  security: export security_kernel_load_data function
  ima: based on policy warn about loading firmware (pre-allocated buffer)
  module: replace the existing LSM hook in init_module
  ima: add build time policy
  ima: based on policy require signed firmware (sysfs fallback)
  firmware: add call to LSM hook before firmware sysfs fallback
  ima: based on policy require signed kexec kernel images
  kexec: add call to LSM hook in original kexec_load syscall
  security: define new LSM hook named security_kernel_load_data
  MAINTAINERS: remove the outdated "LINUX SECURITY MODULE (LSM) FRAMEWORK" entry
This commit is contained in:
Linus Torvalds 2018-08-15 10:25:26 -07:00
commit 92d4a03674
14 changed files with 248 additions and 23 deletions

View File

@ -8342,11 +8342,6 @@ F: Documentation/core-api/atomic_ops.rst
F: Documentation/core-api/refcount-vs-atomic.rst
F: Documentation/memory-barriers.txt
LINUX SECURITY MODULE (LSM) FRAMEWORK
M: Chris Wright <chrisw@sous-sol.org>
L: linux-security-module@vger.kernel.org
S: Supported
LIS3LV02D ACCELEROMETER DRIVER
M: Eric Piel <eric.piel@tremplin-utc.net>
S: Maintained

View File

@ -651,6 +651,8 @@ static bool fw_force_sysfs_fallback(enum fw_opt opt_flags)
static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
{
int ret;
if (fw_fallback_config.ignore_sysfs_fallback) {
pr_info_once("Ignoring firmware sysfs fallback due to sysctl knob\n");
return false;
@ -659,6 +661,11 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
if ((opt_flags & FW_OPT_NOFALLBACK))
return false;
/* Also permit LSMs and IMA to fail firmware sysfs fallback */
ret = security_kernel_load_data(LOADING_FIRMWARE);
if (ret < 0)
return ret;
return fw_force_sysfs_fallback(opt_flags);
}

View File

@ -11,6 +11,7 @@
#define _LINUX_IMA_H
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/kexec.h>
struct linux_binprm;
@ -19,6 +20,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_file_check(struct file *file, int mask);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern int ima_load_data(enum kernel_load_data_id id);
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
enum kernel_read_file_id id);
@ -49,6 +51,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
return 0;
}
static inline int ima_load_data(enum kernel_load_data_id id)
{
return 0;
}
static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
{
return 0;

View File

@ -576,6 +576,10 @@
* userspace to load a kernel module with the given name.
* @kmod_name name of the module requested by the kernel
* Return 0 if successful.
* @kernel_load_data:
* Load data provided by userspace.
* @id kernel load data identifier
* Return 0 if permission is granted.
* @kernel_read_file:
* Read a file specified by userspace.
* @file contains the file structure pointing to the file being read
@ -1582,6 +1586,7 @@ union security_list_options {
int (*kernel_act_as)(struct cred *new, u32 secid);
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_load_data)(enum kernel_load_data_id id);
int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id);
int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
enum kernel_read_file_id id);
@ -1872,6 +1877,7 @@ struct security_hook_heads {
struct hlist_head cred_getsecid;
struct hlist_head kernel_act_as;
struct hlist_head kernel_create_files_as;
struct hlist_head kernel_load_data;
struct hlist_head kernel_read_file;
struct hlist_head kernel_post_read_file;
struct hlist_head kernel_module_request;

View File

@ -159,6 +159,27 @@ extern int mmap_min_addr_handler(struct ctl_table *table, int write,
typedef int (*initxattrs) (struct inode *inode,
const struct xattr *xattr_array, void *fs_data);
/* Keep the kernel_load_data_id enum in sync with kernel_read_file_id */
#define __data_id_enumify(ENUM, dummy) LOADING_ ## ENUM,
#define __data_id_stringify(dummy, str) #str,
enum kernel_load_data_id {
__kernel_read_file_id(__data_id_enumify)
};
static const char * const kernel_load_data_str[] = {
__kernel_read_file_id(__data_id_stringify)
};
static inline const char *kernel_load_data_id_str(enum kernel_load_data_id id)
{
if ((unsigned)id >= LOADING_MAX_ID)
return kernel_load_data_str[LOADING_UNKNOWN];
return kernel_load_data_str[id];
}
#ifdef CONFIG_SECURITY
struct security_mnt_opts {
@ -320,6 +341,7 @@ void security_cred_getsecid(const struct cred *c, u32 *secid);
int security_kernel_act_as(struct cred *new, u32 secid);
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
int security_kernel_module_request(char *kmod_name);
int security_kernel_load_data(enum kernel_load_data_id id);
int security_kernel_read_file(struct file *file, enum kernel_read_file_id id);
int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
enum kernel_read_file_id id);
@ -908,6 +930,11 @@ static inline int security_kernel_module_request(char *kmod_name)
return 0;
}
static inline int security_kernel_load_data(enum kernel_load_data_id id)
{
return 0;
}
static inline int security_kernel_read_file(struct file *file,
enum kernel_read_file_id id)
{

View File

@ -11,6 +11,7 @@
#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/security.h>
#include <linux/kexec.h>
#include <linux/mutex.h>
#include <linux/list.h>
@ -195,10 +196,17 @@ out:
static inline int kexec_load_check(unsigned long nr_segments,
unsigned long flags)
{
int result;
/* We only trust the superuser with rebooting the system. */
if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
return -EPERM;
/* Permit LSMs and IMA to fail the kexec */
result = security_kernel_load_data(LOADING_KEXEC_IMAGE);
if (result < 0)
return result;
/*
* Verify we have a legal set of flags
* This leaves us room for future extensions.

View File

@ -2876,7 +2876,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
if (info->len < sizeof(*(info->hdr)))
return -ENOEXEC;
err = security_kernel_read_file(NULL, READING_MODULE);
err = security_kernel_load_data(LOADING_MODULE);
if (err)
return err;

View File

@ -156,6 +156,64 @@ config IMA_APPRAISE
<http://linux-ima.sourceforge.net>
If unsure, say N.
config IMA_APPRAISE_BUILD_POLICY
bool "IMA build time configured policy rules"
depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
default n
help
This option defines an IMA appraisal policy at build time, which
is enforced at run time without having to specify a builtin
policy name on the boot command line. The build time appraisal
policy rules persist after loading a custom policy.
Depending on the rules configured, this policy may require kernel
modules, firmware, the kexec kernel image, and/or the IMA policy
to be signed. Unsigned files might prevent the system from
booting or applications from working properly.
config IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS
bool "Appraise firmware signatures"
depends on IMA_APPRAISE_BUILD_POLICY
default n
help
This option defines a policy requiring all firmware to be signed,
including the regulatory.db. If both this option and
CFG80211_REQUIRE_SIGNED_REGDB are enabled, then both signature
verification methods are necessary.
config IMA_APPRAISE_REQUIRE_KEXEC_SIGS
bool "Appraise kexec kernel image signatures"
depends on IMA_APPRAISE_BUILD_POLICY
default n
help
Enabling this rule will require all kexec'ed kernel images to
be signed and verified by a public key on the trusted IMA
keyring.
Kernel image signatures can not be verified by the original
kexec_load syscall. Enabling this rule will prevent its
usage.
config IMA_APPRAISE_REQUIRE_MODULE_SIGS
bool "Appraise kernel modules signatures"
depends on IMA_APPRAISE_BUILD_POLICY
default n
help
Enabling this rule will require all kernel modules to be signed
and verified by a public key on the trusted IMA keyring.
Kernel module signatures can only be verified by IMA-appraisal,
via the finit_module syscall. Enabling this rule will prevent
the usage of the init_module syscall.
config IMA_APPRAISE_REQUIRE_POLICY_SIGS
bool "Appraise IMA policy signature"
depends on IMA_APPRAISE_BUILD_POLICY
default n
help
Enabling this rule will require the IMA policy to be signed and
and verified by a key on the trusted IMA keyring.
config IMA_APPRAISE_BOOTPARAM
bool "ima_appraise boot parameter"
depends on IMA_APPRAISE

View File

@ -232,6 +232,7 @@ int ima_policy_show(struct seq_file *m, void *v);
#define IMA_APPRAISE_MODULES 0x08
#define IMA_APPRAISE_FIRMWARE 0x10
#define IMA_APPRAISE_POLICY 0x20
#define IMA_APPRAISE_KEXEC 0x40
#ifdef CONFIG_IMA_APPRAISE
int ima_appraise_measurement(enum ima_hooks func,

View File

@ -429,16 +429,14 @@ void ima_post_path_mknod(struct dentry *dentry)
*/
int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
{
bool sig_enforce = is_module_sig_enforced();
if (!file && read_id == READING_MODULE) {
if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) &&
(ima_appraise & IMA_APPRAISE_ENFORCE)) {
pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
return 0; /* We rely on module signature checking */
}
/*
* READING_FIRMWARE_PREALLOC_BUFFER
*
* Do devices using pre-allocated memory run the risk of the
* firmware being accessible to the device prior to the completion
* of IMA's signature verification any more than when using two
* buffers?
*/
return 0;
}
@ -472,14 +470,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
if (!file && read_id == READING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
(ima_appraise & IMA_APPRAISE_ENFORCE))
(ima_appraise & IMA_APPRAISE_ENFORCE)) {
pr_err("Prevent firmware loading_store.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
return 0;
}
if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
return 0;
/* permit signed certs */
if (!file && read_id == READING_X509_CERTIFICATE)
return 0;
@ -496,6 +493,49 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
MAY_READ, func);
}
/**
* ima_load_data - appraise decision based on policy
* @id: kernel load data caller identifier
*
* Callers of this LSM hook can not measure, appraise, or audit the
* data provided by userspace. Enforce policy rules requring a file
* signature (eg. kexec'ed kernel image).
*
* For permission return 0, otherwise return -EACCES.
*/
int ima_load_data(enum kernel_load_data_id id)
{
bool sig_enforce;
if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
return 0;
switch (id) {
case LOADING_KEXEC_IMAGE:
if (ima_appraise & IMA_APPRAISE_KEXEC) {
pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
break;
case LOADING_FIRMWARE:
if (ima_appraise & IMA_APPRAISE_FIRMWARE) {
pr_err("Prevent firmware sysfs fallback loading.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
break;
case LOADING_MODULE:
sig_enforce = is_module_sig_enforced();
if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
default:
break;
}
return 0;
}
static int __init init_ima(void)
{
int error;

View File

@ -49,6 +49,7 @@
int ima_policy_flag;
static int temp_ima_appraise;
static int build_ima_appraise __ro_after_init;
#define MAX_LSM_RULES 6
enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
@ -162,6 +163,25 @@ static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
#endif
};
static struct ima_rule_entry build_appraise_rules[] __ro_after_init = {
#ifdef CONFIG_IMA_APPRAISE_REQUIRE_MODULE_SIGS
{.action = APPRAISE, .func = MODULE_CHECK,
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
#endif
#ifdef CONFIG_IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS
{.action = APPRAISE, .func = FIRMWARE_CHECK,
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
#endif
#ifdef CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS
{.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
#endif
#ifdef CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS
{.action = APPRAISE, .func = POLICY_CHECK,
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
#endif
};
static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
{.action = APPRAISE, .func = MODULE_CHECK,
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
@ -435,7 +455,7 @@ void ima_update_policy_flag(void)
ima_policy_flag |= entry->action;
}
ima_appraise |= temp_ima_appraise;
ima_appraise |= (build_ima_appraise | temp_ima_appraise);
if (!ima_appraise)
ima_policy_flag &= ~IMA_APPRAISE;
}
@ -448,6 +468,8 @@ static int ima_appraise_flag(enum ima_hooks func)
return IMA_APPRAISE_FIRMWARE;
else if (func == POLICY_CHECK)
return IMA_APPRAISE_POLICY;
else if (func == KEXEC_KERNEL_CHECK)
return IMA_APPRAISE_KEXEC;
return 0;
}
@ -486,8 +508,8 @@ void __init ima_init_policy(void)
}
/*
* Insert the appraise rules requiring file signatures, prior to
* any other appraise rules.
* Insert the builtin "secure_boot" policy rules requiring file
* signatures, prior to any other appraise rules.
*/
for (i = 0; i < secure_boot_entries; i++) {
list_add_tail(&secure_boot_rules[i].list, &ima_default_rules);
@ -495,6 +517,26 @@ void __init ima_init_policy(void)
ima_appraise_flag(secure_boot_rules[i].func);
}
/*
* Insert the build time appraise rules requiring file signatures
* for both the initial and custom policies, prior to other appraise
* rules.
*/
for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) {
struct ima_rule_entry *entry;
if (!secure_boot_entries)
list_add_tail(&build_appraise_rules[i].list,
&ima_default_rules);
entry = kmemdup(&build_appraise_rules[i], sizeof(*entry),
GFP_KERNEL);
if (entry)
list_add_tail(&entry->list, &ima_policy_rules);
build_ima_appraise |=
ima_appraise_flag(build_appraise_rules[i].func);
}
for (i = 0; i < appraise_entries; i++) {
list_add_tail(&default_appraise_rules[i].list,
&ima_default_rules);

View File

@ -173,9 +173,15 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
return 0;
}
static int loadpin_load_data(enum kernel_load_data_id id)
{
return loadpin_read_file(NULL, (enum kernel_read_file_id) id);
}
static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
};
void __init loadpin_add_hooks(void)

View File

@ -118,6 +118,8 @@ static int lsm_append(char *new, char **result)
if (*result == NULL) {
*result = kstrdup(new, GFP_KERNEL);
if (*result == NULL)
return -ENOMEM;
} else {
/* Check if it is the last registered name */
if (match_last_lsm(*result, new))
@ -1056,6 +1058,17 @@ int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
}
EXPORT_SYMBOL_GPL(security_kernel_post_read_file);
int security_kernel_load_data(enum kernel_load_data_id id)
{
int ret;
ret = call_int_hook(kernel_load_data, 0, id);
if (ret)
return ret;
return ima_load_data(id);
}
EXPORT_SYMBOL_GPL(security_kernel_load_data);
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{

View File

@ -4073,6 +4073,20 @@ static int selinux_kernel_read_file(struct file *file,
return rc;
}
static int selinux_kernel_load_data(enum kernel_load_data_id id)
{
int rc = 0;
switch (id) {
case LOADING_MODULE:
rc = selinux_kernel_module_from_file(NULL);
default:
break;
}
return rc;
}
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
{
return avc_has_perm(&selinux_state,
@ -6972,6 +6986,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),