Commit | Line | Data |
---|---|---|
66dbc325 MZ |
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 | #include <linux/uaccess.h> | |
17 | #include <linux/module.h> | |
18 | #include "evm.h" | |
19 | ||
20 | static struct dentry *evm_init_tpm; | |
21 | ||
22 | /** | |
23 | * evm_read_key - read() for <securityfs>/evm | |
24 | * | |
25 | * @filp: file pointer, not actually used | |
26 | * @buf: where to put the result | |
27 | * @count: maximum to send along | |
28 | * @ppos: where to start | |
29 | * | |
30 | * Returns number of bytes read or error code, as appropriate | |
31 | */ | |
32 | static ssize_t evm_read_key(struct file *filp, char __user *buf, | |
33 | size_t count, loff_t *ppos) | |
34 | { | |
35 | char temp[80]; | |
36 | ssize_t rc; | |
37 | ||
38 | if (*ppos != 0) | |
39 | return 0; | |
40 | ||
41 | sprintf(temp, "%d", evm_initialized); | |
42 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); | |
43 | ||
44 | return rc; | |
45 | } | |
46 | ||
47 | /** | |
48 | * evm_write_key - write() for <securityfs>/evm | |
49 | * @file: file pointer, not actually used | |
50 | * @buf: where to get the data from | |
51 | * @count: bytes sent | |
52 | * @ppos: where to start | |
53 | * | |
54 | * Used to signal that key is on the kernel key ring. | |
55 | * - get the integrity hmac key from the kernel key ring | |
56 | * - create list of hmac protected extended attributes | |
57 | * Returns number of bytes written or error code, as appropriate | |
58 | */ | |
59 | static ssize_t evm_write_key(struct file *file, const char __user *buf, | |
60 | size_t count, loff_t *ppos) | |
61 | { | |
62 | char temp[80]; | |
63 | int i, error; | |
64 | ||
65 | if (!capable(CAP_SYS_ADMIN) || evm_initialized) | |
66 | return -EPERM; | |
67 | ||
68 | if (count >= sizeof(temp) || count == 0) | |
69 | return -EINVAL; | |
70 | ||
71 | if (copy_from_user(temp, buf, count) != 0) | |
72 | return -EFAULT; | |
73 | ||
74 | temp[count] = '\0'; | |
75 | ||
76 | if ((sscanf(temp, "%d", &i) != 1) || (i != 1)) | |
77 | return -EINVAL; | |
78 | ||
79 | error = evm_init_key(); | |
80 | if (!error) { | |
81 | evm_initialized = 1; | |
82 | pr_info("EVM: initialized\n"); | |
83 | } else | |
84 | pr_err("EVM: initialization failed\n"); | |
85 | return count; | |
86 | } | |
87 | ||
88 | static const struct file_operations evm_key_ops = { | |
89 | .read = evm_read_key, | |
90 | .write = evm_write_key, | |
91 | }; | |
92 | ||
93 | int __init evm_init_secfs(void) | |
94 | { | |
95 | int error = 0; | |
96 | ||
97 | evm_init_tpm = securityfs_create_file("evm", S_IRUSR | S_IRGRP, | |
98 | NULL, NULL, &evm_key_ops); | |
99 | if (!evm_init_tpm || IS_ERR(evm_init_tpm)) | |
100 | error = -EFAULT; | |
101 | return error; | |
102 | } | |
103 | ||
104 | void __exit evm_cleanup_secfs(void) | |
105 | { | |
106 | if (evm_init_tpm) | |
107 | securityfs_remove(evm_init_tpm); | |
108 | } |