mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-29 05:40:13 +00:00
This patch introduces a new LSM blob to the block_device structure, enabling the security subsystem to store security-sensitive data related to block devices. Currently, for a device mapper's mapped device containing a dm-verity target, critical security information such as the roothash and its signing state are not readily accessible. Specifically, while the dm-verity volume creation process passes the dm-verity roothash and its signature from userspace to the kernel, the roothash is stored privately within the dm-verity target, and its signature is discarded post-verification. This makes it extremely hard for the security subsystem to utilize these data. With the addition of the LSM blob to the block_device structure, the security subsystem can now retain and manage important security metadata such as the roothash and the signing state of a dm-verity by storing them inside the blob. Access decisions can then be based on these stored data. The implementation follows the same approach used for security blobs in other structures like struct file, struct inode, and struct superblock. The initialization of the security blob occurs after the creation of the struct block_device, performed by the security subsystem. Similarly, the security blob is freed by the security subsystem before the struct block_device is deallocated or freed. This patch also introduces a new hook security_bdev_setintegrity() to save block device's integrity data to the new LSM blob. For example, for dm-verity, it can use this hook to expose its roothash and signing state to LSMs, then LSMs can save these data into the LSM blob. Please note that the new hook should be invoked every time the security information is updated to keep these data current. For example, in dm-verity, if the mapping table is reloaded and configured to use a different dm-verity target with a new roothash and signing information, the previously stored data in the LSM blob will become obsolete. It is crucial to re-invoke the hook to refresh these data and ensure they are up to date. This necessity arises from the design of device-mapper, where a device-mapper device is first created, and then targets are subsequently loaded into it. These targets can be modified multiple times during the device's lifetime. Therefore, while the LSM blob is allocated during the creation of the block device, its actual contents are not initialized at this stage and can change substantially over time. This includes alterations from data that the LSM 'trusts' to those it does not, making it essential to handle these changes correctly. Failure to address this dynamic aspect could potentially allow for bypassing LSM checks. Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com> Signed-off-by: Fan Wu <wufan@linux.microsoft.com> [PM: merge fuzz, subject line tweaks] Signed-off-by: Paul Moore <paul@paul-moore.com>
161 lines
4.7 KiB
C
161 lines
4.7 KiB
C
/*
|
|
* Linux Security Module interfaces
|
|
*
|
|
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
|
|
* Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com>
|
|
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
|
|
* Copyright (C) 2001 James Morris <jmorris@intercode.com.au>
|
|
* Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
|
|
* Copyright (C) 2015 Intel Corporation.
|
|
* Copyright (C) 2015 Casey Schaufler <casey@schaufler-ca.com>
|
|
* Copyright (C) 2016 Mellanox Techonologies
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Due to this file being licensed under the GPL there is controversy over
|
|
* whether this permits you to write a module that #includes this file
|
|
* without placing your module under the GPL. Please consult a lawyer for
|
|
* advice before doing this.
|
|
*
|
|
*/
|
|
|
|
#ifndef __LINUX_LSM_HOOKS_H
|
|
#define __LINUX_LSM_HOOKS_H
|
|
|
|
#include <uapi/linux/lsm.h>
|
|
#include <linux/security.h>
|
|
#include <linux/init.h>
|
|
#include <linux/rculist.h>
|
|
#include <linux/xattr.h>
|
|
|
|
union security_list_options {
|
|
#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
|
|
#include "lsm_hook_defs.h"
|
|
#undef LSM_HOOK
|
|
};
|
|
|
|
struct security_hook_heads {
|
|
#define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME;
|
|
#include "lsm_hook_defs.h"
|
|
#undef LSM_HOOK
|
|
} __randomize_layout;
|
|
|
|
/**
|
|
* struct lsm_id - Identify a Linux Security Module.
|
|
* @lsm: name of the LSM, must be approved by the LSM maintainers
|
|
* @id: LSM ID number from uapi/linux/lsm.h
|
|
*
|
|
* Contains the information that identifies the LSM.
|
|
*/
|
|
struct lsm_id {
|
|
const char *name;
|
|
u64 id;
|
|
};
|
|
|
|
/*
|
|
* Security module hook list structure.
|
|
* For use with generic list macros for common operations.
|
|
*/
|
|
struct security_hook_list {
|
|
struct hlist_node list;
|
|
struct hlist_head *head;
|
|
union security_list_options hook;
|
|
const struct lsm_id *lsmid;
|
|
} __randomize_layout;
|
|
|
|
/*
|
|
* Security blob size or offset data.
|
|
*/
|
|
struct lsm_blob_sizes {
|
|
int lbs_cred;
|
|
int lbs_file;
|
|
int lbs_ib;
|
|
int lbs_inode;
|
|
int lbs_sock;
|
|
int lbs_superblock;
|
|
int lbs_ipc;
|
|
int lbs_key;
|
|
int lbs_msg_msg;
|
|
int lbs_perf_event;
|
|
int lbs_task;
|
|
int lbs_xattr_count; /* number of xattr slots in new_xattrs array */
|
|
int lbs_tun_dev;
|
|
int lbs_bdev;
|
|
};
|
|
|
|
/*
|
|
* LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void
|
|
* LSM hooks (in include/linux/lsm_hook_defs.h).
|
|
*/
|
|
#define LSM_RET_VOID ((void) 0)
|
|
|
|
/*
|
|
* Initializing a security_hook_list structure takes
|
|
* up a lot of space in a source file. This macro takes
|
|
* care of the common case and reduces the amount of
|
|
* text involved.
|
|
*/
|
|
#define LSM_HOOK_INIT(HEAD, HOOK) \
|
|
{ .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }
|
|
|
|
extern void security_add_hooks(struct security_hook_list *hooks, int count,
|
|
const struct lsm_id *lsmid);
|
|
|
|
#define LSM_FLAG_LEGACY_MAJOR BIT(0)
|
|
#define LSM_FLAG_EXCLUSIVE BIT(1)
|
|
|
|
enum lsm_order {
|
|
LSM_ORDER_FIRST = -1, /* This is only for capabilities. */
|
|
LSM_ORDER_MUTABLE = 0,
|
|
LSM_ORDER_LAST = 1, /* This is only for integrity. */
|
|
};
|
|
|
|
struct lsm_info {
|
|
const char *name; /* Required. */
|
|
enum lsm_order order; /* Optional: default is LSM_ORDER_MUTABLE */
|
|
unsigned long flags; /* Optional: flags describing LSM */
|
|
int *enabled; /* Optional: controlled by CONFIG_LSM */
|
|
int (*init)(void); /* Required. */
|
|
struct lsm_blob_sizes *blobs; /* Optional: for blob sharing. */
|
|
};
|
|
|
|
#define DEFINE_LSM(lsm) \
|
|
static struct lsm_info __lsm_##lsm \
|
|
__used __section(".lsm_info.init") \
|
|
__aligned(sizeof(unsigned long))
|
|
|
|
#define DEFINE_EARLY_LSM(lsm) \
|
|
static struct lsm_info __early_lsm_##lsm \
|
|
__used __section(".early_lsm_info.init") \
|
|
__aligned(sizeof(unsigned long))
|
|
|
|
/* DO NOT tamper with these variables outside of the LSM framework */
|
|
extern char *lsm_names;
|
|
extern struct security_hook_heads security_hook_heads;
|
|
extern struct lsm_static_calls_table static_calls_table __ro_after_init;
|
|
extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
|
|
extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
|
|
|
|
/**
|
|
* lsm_get_xattr_slot - Return the next available slot and increment the index
|
|
* @xattrs: array storing LSM-provided xattrs
|
|
* @xattr_count: number of already stored xattrs (updated)
|
|
*
|
|
* Retrieve the first available slot in the @xattrs array to fill with an xattr,
|
|
* and increment @xattr_count.
|
|
*
|
|
* Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
|
|
*/
|
|
static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
|
|
int *xattr_count)
|
|
{
|
|
if (unlikely(!xattrs))
|
|
return NULL;
|
|
return &xattrs[(*xattr_count)++];
|
|
}
|
|
|
|
#endif /* ! __LINUX_LSM_HOOKS_H */
|