1 /* 2 * Copyright (C) 2010 IBM Corporation 3 * 4 * Authors: 5 * Mimi Zohar <zohar@us.ibm.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, version 2 of the License. 10 * 11 * File: evm_secfs.c 12 * - Used to signal when key is on keyring 13 * - Get the key and enable EVM 14 */ 15 16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17 18 #include <linux/uaccess.h> 19 #include <linux/module.h> 20 #include "evm.h" 21 22 static struct dentry *evm_dir; 23 static struct dentry *evm_init_tpm; 24 static struct dentry *evm_symlink; 25 26 /** 27 * evm_read_key - read() for <securityfs>/evm 28 * 29 * @filp: file pointer, not actually used 30 * @buf: where to put the result 31 * @count: maximum to send along 32 * @ppos: where to start 33 * 34 * Returns number of bytes read or error code, as appropriate 35 */ 36 static ssize_t evm_read_key(struct file *filp, char __user *buf, 37 size_t count, loff_t *ppos) 38 { 39 char temp[80]; 40 ssize_t rc; 41 42 if (*ppos != 0) 43 return 0; 44 45 sprintf(temp, "%d", (evm_initialized & ~EVM_SETUP_COMPLETE)); 46 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); 47 48 return rc; 49 } 50 51 /** 52 * evm_write_key - write() for <securityfs>/evm 53 * @file: file pointer, not actually used 54 * @buf: where to get the data from 55 * @count: bytes sent 56 * @ppos: where to start 57 * 58 * Used to signal that key is on the kernel key ring. 59 * - get the integrity hmac key from the kernel key ring 60 * - create list of hmac protected extended attributes 61 * Returns number of bytes written or error code, as appropriate 62 */ 63 static ssize_t evm_write_key(struct file *file, const char __user *buf, 64 size_t count, loff_t *ppos) 65 { 66 int i, ret; 67 68 if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP_COMPLETE)) 69 return -EPERM; 70 71 ret = kstrtoint_from_user(buf, count, 0, &i); 72 73 if (ret) 74 return ret; 75 76 /* Reject invalid values */ 77 if (!i || (i & ~EVM_INIT_MASK) != 0) 78 return -EINVAL; 79 80 /* Don't allow a request to freshly enable metadata writes if 81 * keys are loaded. 82 */ 83 if ((i & EVM_ALLOW_METADATA_WRITES) && 84 ((evm_initialized & EVM_KEY_MASK) != 0) && 85 !(evm_initialized & EVM_ALLOW_METADATA_WRITES)) 86 return -EPERM; 87 88 if (i & EVM_INIT_HMAC) { 89 ret = evm_init_key(); 90 if (ret != 0) 91 return ret; 92 /* Forbid further writes after the symmetric key is loaded */ 93 i |= EVM_SETUP_COMPLETE; 94 } 95 96 evm_initialized |= i; 97 98 /* Don't allow protected metadata modification if a symmetric key 99 * is loaded 100 */ 101 if (evm_initialized & EVM_INIT_HMAC) 102 evm_initialized &= ~(EVM_ALLOW_METADATA_WRITES); 103 104 return count; 105 } 106 107 static const struct file_operations evm_key_ops = { 108 .read = evm_read_key, 109 .write = evm_write_key, 110 }; 111 112 int __init evm_init_secfs(void) 113 { 114 int error = 0; 115 116 evm_dir = securityfs_create_dir("evm", integrity_dir); 117 if (!evm_dir || IS_ERR(evm_dir)) 118 return -EFAULT; 119 120 evm_init_tpm = securityfs_create_file("evm", 0660, 121 evm_dir, NULL, &evm_key_ops); 122 if (!evm_init_tpm || IS_ERR(evm_init_tpm)) { 123 error = -EFAULT; 124 goto out; 125 } 126 127 evm_symlink = securityfs_create_symlink("evm", NULL, 128 "integrity/evm/evm", NULL); 129 if (!evm_symlink || IS_ERR(evm_symlink)) { 130 error = -EFAULT; 131 goto out; 132 } 133 134 return 0; 135 out: 136 securityfs_remove(evm_symlink); 137 securityfs_remove(evm_init_tpm); 138 securityfs_remove(evm_dir); 139 return error; 140 } 141