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_init_tpm; 23 24 /** 25 * evm_read_key - read() for <securityfs>/evm 26 * 27 * @filp: file pointer, not actually used 28 * @buf: where to put the result 29 * @count: maximum to send along 30 * @ppos: where to start 31 * 32 * Returns number of bytes read or error code, as appropriate 33 */ 34 static ssize_t evm_read_key(struct file *filp, char __user *buf, 35 size_t count, loff_t *ppos) 36 { 37 char temp[80]; 38 ssize_t rc; 39 40 if (*ppos != 0) 41 return 0; 42 43 sprintf(temp, "%d", (evm_initialized & ~EVM_SETUP_COMPLETE)); 44 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); 45 46 return rc; 47 } 48 49 /** 50 * evm_write_key - write() for <securityfs>/evm 51 * @file: file pointer, not actually used 52 * @buf: where to get the data from 53 * @count: bytes sent 54 * @ppos: where to start 55 * 56 * Used to signal that key is on the kernel key ring. 57 * - get the integrity hmac key from the kernel key ring 58 * - create list of hmac protected extended attributes 59 * Returns number of bytes written or error code, as appropriate 60 */ 61 static ssize_t evm_write_key(struct file *file, const char __user *buf, 62 size_t count, loff_t *ppos) 63 { 64 int i, ret; 65 66 if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP_COMPLETE)) 67 return -EPERM; 68 69 ret = kstrtoint_from_user(buf, count, 0, &i); 70 71 if (ret) 72 return ret; 73 74 /* Reject invalid values */ 75 if (!i || (i & ~EVM_INIT_MASK) != 0) 76 return -EINVAL; 77 78 /* Don't allow a request to freshly enable metadata writes if 79 * keys are loaded. 80 */ 81 if ((i & EVM_ALLOW_METADATA_WRITES) && 82 ((evm_initialized & EVM_KEY_MASK) != 0) && 83 !(evm_initialized & EVM_ALLOW_METADATA_WRITES)) 84 return -EPERM; 85 86 if (i & EVM_INIT_HMAC) { 87 ret = evm_init_key(); 88 if (ret != 0) 89 return ret; 90 /* Forbid further writes after the symmetric key is loaded */ 91 i |= EVM_SETUP_COMPLETE; 92 } 93 94 evm_initialized |= i; 95 96 /* Don't allow protected metadata modification if a symmetric key 97 * is loaded 98 */ 99 if (evm_initialized & EVM_INIT_HMAC) 100 evm_initialized &= ~(EVM_ALLOW_METADATA_WRITES); 101 102 return count; 103 } 104 105 static const struct file_operations evm_key_ops = { 106 .read = evm_read_key, 107 .write = evm_write_key, 108 }; 109 110 int __init evm_init_secfs(void) 111 { 112 int error = 0; 113 114 evm_init_tpm = securityfs_create_file("evm", S_IRUSR | S_IRGRP, 115 NULL, NULL, &evm_key_ops); 116 if (!evm_init_tpm || IS_ERR(evm_init_tpm)) 117 error = -EFAULT; 118 return error; 119 } 120