cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

evm_secfs.c (7540B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2010 IBM Corporation
      4 *
      5 * Authors:
      6 * Mimi Zohar <zohar@us.ibm.com>
      7 *
      8 * File: evm_secfs.c
      9 *	- Used to signal when key is on keyring
     10 *	- Get the key and enable EVM
     11 */
     12
     13#include <linux/audit.h>
     14#include <linux/uaccess.h>
     15#include <linux/init.h>
     16#include <linux/mutex.h>
     17#include "evm.h"
     18
     19static struct dentry *evm_dir;
     20static struct dentry *evm_init_tpm;
     21static struct dentry *evm_symlink;
     22
     23#ifdef CONFIG_EVM_ADD_XATTRS
     24static struct dentry *evm_xattrs;
     25static DEFINE_MUTEX(xattr_list_mutex);
     26static int evm_xattrs_locked;
     27#endif
     28
     29/**
     30 * evm_read_key - read() for <securityfs>/evm
     31 *
     32 * @filp: file pointer, not actually used
     33 * @buf: where to put the result
     34 * @count: maximum to send along
     35 * @ppos: where to start
     36 *
     37 * Returns number of bytes read or error code, as appropriate
     38 */
     39static ssize_t evm_read_key(struct file *filp, char __user *buf,
     40			    size_t count, loff_t *ppos)
     41{
     42	char temp[80];
     43	ssize_t rc;
     44
     45	if (*ppos != 0)
     46		return 0;
     47
     48	sprintf(temp, "%d", (evm_initialized & ~EVM_SETUP_COMPLETE));
     49	rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
     50
     51	return rc;
     52}
     53
     54/**
     55 * evm_write_key - write() for <securityfs>/evm
     56 * @file: file pointer, not actually used
     57 * @buf: where to get the data from
     58 * @count: bytes sent
     59 * @ppos: where to start
     60 *
     61 * Used to signal that key is on the kernel key ring.
     62 * - get the integrity hmac key from the kernel key ring
     63 * - create list of hmac protected extended attributes
     64 * Returns number of bytes written or error code, as appropriate
     65 */
     66static ssize_t evm_write_key(struct file *file, const char __user *buf,
     67			     size_t count, loff_t *ppos)
     68{
     69	unsigned int i;
     70	int ret;
     71
     72	if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP_COMPLETE))
     73		return -EPERM;
     74
     75	ret = kstrtouint_from_user(buf, count, 0, &i);
     76
     77	if (ret)
     78		return ret;
     79
     80	/* Reject invalid values */
     81	if (!i || (i & ~EVM_INIT_MASK) != 0)
     82		return -EINVAL;
     83
     84	/*
     85	 * Don't allow a request to enable metadata writes if
     86	 * an HMAC key is loaded.
     87	 */
     88	if ((i & EVM_ALLOW_METADATA_WRITES) &&
     89	    (evm_initialized & EVM_INIT_HMAC) != 0)
     90		return -EPERM;
     91
     92	if (i & EVM_INIT_HMAC) {
     93		ret = evm_init_key();
     94		if (ret != 0)
     95			return ret;
     96		/* Forbid further writes after the symmetric key is loaded */
     97		i |= EVM_SETUP_COMPLETE;
     98	}
     99
    100	evm_initialized |= i;
    101
    102	/* Don't allow protected metadata modification if a symmetric key
    103	 * is loaded
    104	 */
    105	if (evm_initialized & EVM_INIT_HMAC)
    106		evm_initialized &= ~(EVM_ALLOW_METADATA_WRITES);
    107
    108	return count;
    109}
    110
    111static const struct file_operations evm_key_ops = {
    112	.read		= evm_read_key,
    113	.write		= evm_write_key,
    114};
    115
    116#ifdef CONFIG_EVM_ADD_XATTRS
    117/**
    118 * evm_read_xattrs - read() for <securityfs>/evm_xattrs
    119 *
    120 * @filp: file pointer, not actually used
    121 * @buf: where to put the result
    122 * @count: maximum to send along
    123 * @ppos: where to start
    124 *
    125 * Returns number of bytes read or error code, as appropriate
    126 */
    127static ssize_t evm_read_xattrs(struct file *filp, char __user *buf,
    128			       size_t count, loff_t *ppos)
    129{
    130	char *temp;
    131	int offset = 0;
    132	ssize_t rc, size = 0;
    133	struct xattr_list *xattr;
    134
    135	if (*ppos != 0)
    136		return 0;
    137
    138	rc = mutex_lock_interruptible(&xattr_list_mutex);
    139	if (rc)
    140		return -ERESTARTSYS;
    141
    142	list_for_each_entry(xattr, &evm_config_xattrnames, list) {
    143		if (!xattr->enabled)
    144			continue;
    145
    146		size += strlen(xattr->name) + 1;
    147	}
    148
    149	temp = kmalloc(size + 1, GFP_KERNEL);
    150	if (!temp) {
    151		mutex_unlock(&xattr_list_mutex);
    152		return -ENOMEM;
    153	}
    154
    155	list_for_each_entry(xattr, &evm_config_xattrnames, list) {
    156		if (!xattr->enabled)
    157			continue;
    158
    159		sprintf(temp + offset, "%s\n", xattr->name);
    160		offset += strlen(xattr->name) + 1;
    161	}
    162
    163	mutex_unlock(&xattr_list_mutex);
    164	rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
    165
    166	kfree(temp);
    167
    168	return rc;
    169}
    170
    171/**
    172 * evm_write_xattrs - write() for <securityfs>/evm_xattrs
    173 * @file: file pointer, not actually used
    174 * @buf: where to get the data from
    175 * @count: bytes sent
    176 * @ppos: where to start
    177 *
    178 * Returns number of bytes written or error code, as appropriate
    179 */
    180static ssize_t evm_write_xattrs(struct file *file, const char __user *buf,
    181				size_t count, loff_t *ppos)
    182{
    183	int len, err;
    184	struct xattr_list *xattr, *tmp;
    185	struct audit_buffer *ab;
    186	struct iattr newattrs;
    187	struct inode *inode;
    188
    189	if (!capable(CAP_SYS_ADMIN) || evm_xattrs_locked)
    190		return -EPERM;
    191
    192	if (*ppos != 0)
    193		return -EINVAL;
    194
    195	if (count > XATTR_NAME_MAX)
    196		return -E2BIG;
    197
    198	ab = audit_log_start(audit_context(), GFP_KERNEL,
    199			     AUDIT_INTEGRITY_EVM_XATTR);
    200	if (!ab && IS_ENABLED(CONFIG_AUDIT))
    201		return -ENOMEM;
    202
    203	xattr = kmalloc(sizeof(struct xattr_list), GFP_KERNEL);
    204	if (!xattr) {
    205		err = -ENOMEM;
    206		goto out;
    207	}
    208
    209	xattr->enabled = true;
    210	xattr->name = memdup_user_nul(buf, count);
    211	if (IS_ERR(xattr->name)) {
    212		err = PTR_ERR(xattr->name);
    213		xattr->name = NULL;
    214		goto out;
    215	}
    216
    217	/* Remove any trailing newline */
    218	len = strlen(xattr->name);
    219	if (len && xattr->name[len-1] == '\n')
    220		xattr->name[len-1] = '\0';
    221
    222	audit_log_format(ab, "xattr=");
    223	audit_log_untrustedstring(ab, xattr->name);
    224
    225	if (strcmp(xattr->name, ".") == 0) {
    226		evm_xattrs_locked = 1;
    227		newattrs.ia_mode = S_IFREG | 0440;
    228		newattrs.ia_valid = ATTR_MODE;
    229		inode = evm_xattrs->d_inode;
    230		inode_lock(inode);
    231		err = simple_setattr(&init_user_ns, evm_xattrs, &newattrs);
    232		inode_unlock(inode);
    233		if (!err)
    234			err = count;
    235		goto out;
    236	}
    237
    238	if (strncmp(xattr->name, XATTR_SECURITY_PREFIX,
    239		    XATTR_SECURITY_PREFIX_LEN) != 0) {
    240		err = -EINVAL;
    241		goto out;
    242	}
    243
    244	/*
    245	 * xattr_list_mutex guards against races in evm_read_xattrs().
    246	 * Entries are only added to the evm_config_xattrnames list
    247	 * and never deleted. Therefore, the list is traversed
    248	 * using list_for_each_entry_lockless() without holding
    249	 * the mutex in evm_calc_hmac_or_hash(), evm_find_protected_xattrs()
    250	 * and evm_protected_xattr().
    251	 */
    252	mutex_lock(&xattr_list_mutex);
    253	list_for_each_entry(tmp, &evm_config_xattrnames, list) {
    254		if (strcmp(xattr->name, tmp->name) == 0) {
    255			err = -EEXIST;
    256			if (!tmp->enabled) {
    257				tmp->enabled = true;
    258				err = count;
    259			}
    260			mutex_unlock(&xattr_list_mutex);
    261			goto out;
    262		}
    263	}
    264	list_add_tail_rcu(&xattr->list, &evm_config_xattrnames);
    265	mutex_unlock(&xattr_list_mutex);
    266
    267	audit_log_format(ab, " res=0");
    268	audit_log_end(ab);
    269	return count;
    270out:
    271	audit_log_format(ab, " res=%d", (err < 0) ? err : 0);
    272	audit_log_end(ab);
    273	if (xattr) {
    274		kfree(xattr->name);
    275		kfree(xattr);
    276	}
    277	return err;
    278}
    279
    280static const struct file_operations evm_xattr_ops = {
    281	.read		= evm_read_xattrs,
    282	.write		= evm_write_xattrs,
    283};
    284
    285static int evm_init_xattrs(void)
    286{
    287	evm_xattrs = securityfs_create_file("evm_xattrs", 0660, evm_dir, NULL,
    288					    &evm_xattr_ops);
    289	if (!evm_xattrs || IS_ERR(evm_xattrs))
    290		return -EFAULT;
    291
    292	return 0;
    293}
    294#else
    295static int evm_init_xattrs(void)
    296{
    297	return 0;
    298}
    299#endif
    300
    301int __init evm_init_secfs(void)
    302{
    303	int error = 0;
    304
    305	evm_dir = securityfs_create_dir("evm", integrity_dir);
    306	if (!evm_dir || IS_ERR(evm_dir))
    307		return -EFAULT;
    308
    309	evm_init_tpm = securityfs_create_file("evm", 0660,
    310					      evm_dir, NULL, &evm_key_ops);
    311	if (!evm_init_tpm || IS_ERR(evm_init_tpm)) {
    312		error = -EFAULT;
    313		goto out;
    314	}
    315
    316	evm_symlink = securityfs_create_symlink("evm", NULL,
    317						"integrity/evm/evm", NULL);
    318	if (!evm_symlink || IS_ERR(evm_symlink)) {
    319		error = -EFAULT;
    320		goto out;
    321	}
    322
    323	if (evm_init_xattrs() != 0) {
    324		error = -EFAULT;
    325		goto out;
    326	}
    327
    328	return 0;
    329out:
    330	securityfs_remove(evm_symlink);
    331	securityfs_remove(evm_init_tpm);
    332	securityfs_remove(evm_dir);
    333	return error;
    334}