.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2008 IBM Corporation |
---|
3 | 4 | * |
---|
4 | 5 | * Authors: |
---|
5 | 6 | * Mimi Zohar <zohar@us.ibm.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License as |
---|
9 | | - * published by the Free Software Foundation, version 2 of the |
---|
10 | | - * License. |
---|
11 | 7 | * |
---|
12 | 8 | * File: integrity_iint.c |
---|
13 | 9 | * - implements the integrity hooks: integrity_inode_alloc, |
---|
.. | .. |
---|
16 | 12 | * using a rbtree tree. |
---|
17 | 13 | */ |
---|
18 | 14 | #include <linux/slab.h> |
---|
19 | | -#include <linux/module.h> |
---|
| 15 | +#include <linux/init.h> |
---|
20 | 16 | #include <linux/spinlock.h> |
---|
21 | 17 | #include <linux/rbtree.h> |
---|
22 | 18 | #include <linux/file.h> |
---|
23 | 19 | #include <linux/uaccess.h> |
---|
24 | 20 | #include <linux/security.h> |
---|
| 21 | +#include <linux/lsm_hooks.h> |
---|
25 | 22 | #include "integrity.h" |
---|
26 | 23 | |
---|
27 | 24 | static struct rb_root integrity_iint_tree = RB_ROOT; |
---|
.. | .. |
---|
46 | 43 | else if (inode > iint->inode) |
---|
47 | 44 | n = n->rb_right; |
---|
48 | 45 | else |
---|
49 | | - break; |
---|
| 46 | + return iint; |
---|
50 | 47 | } |
---|
51 | | - if (!n) |
---|
52 | | - return NULL; |
---|
53 | 48 | |
---|
54 | | - return iint; |
---|
| 49 | + return NULL; |
---|
55 | 50 | } |
---|
56 | 51 | |
---|
57 | 52 | /* |
---|
.. | .. |
---|
101 | 96 | struct rb_node *node, *parent = NULL; |
---|
102 | 97 | struct integrity_iint_cache *iint, *test_iint; |
---|
103 | 98 | |
---|
| 99 | + /* |
---|
| 100 | + * The integrity's "iint_cache" is initialized at security_init(), |
---|
| 101 | + * unless it is not included in the ordered list of LSMs enabled |
---|
| 102 | + * on the boot command line. |
---|
| 103 | + */ |
---|
| 104 | + if (!iint_cache) |
---|
| 105 | + panic("%s: lsm=integrity required.\n", __func__); |
---|
| 106 | + |
---|
104 | 107 | iint = integrity_iint_find(inode); |
---|
105 | 108 | if (iint) |
---|
106 | 109 | return iint; |
---|
.. | .. |
---|
116 | 119 | parent = *p; |
---|
117 | 120 | test_iint = rb_entry(parent, struct integrity_iint_cache, |
---|
118 | 121 | rb_node); |
---|
119 | | - if (inode < test_iint->inode) |
---|
| 122 | + if (inode < test_iint->inode) { |
---|
120 | 123 | p = &(*p)->rb_left; |
---|
121 | | - else |
---|
| 124 | + } else if (inode > test_iint->inode) { |
---|
122 | 125 | p = &(*p)->rb_right; |
---|
| 126 | + } else { |
---|
| 127 | + write_unlock(&integrity_iint_lock); |
---|
| 128 | + kmem_cache_free(iint_cache, iint); |
---|
| 129 | + return test_iint; |
---|
| 130 | + } |
---|
123 | 131 | } |
---|
124 | 132 | |
---|
125 | 133 | iint->inode = inode; |
---|
.. | .. |
---|
174 | 182 | 0, SLAB_PANIC, init_once); |
---|
175 | 183 | return 0; |
---|
176 | 184 | } |
---|
177 | | -security_initcall(integrity_iintcache_init); |
---|
| 185 | +DEFINE_LSM(integrity) = { |
---|
| 186 | + .name = "integrity", |
---|
| 187 | + .init = integrity_iintcache_init, |
---|
| 188 | +}; |
---|
178 | 189 | |
---|
179 | 190 | |
---|
180 | 191 | /* |
---|
.. | .. |
---|
188 | 199 | int integrity_kernel_read(struct file *file, loff_t offset, |
---|
189 | 200 | void *addr, unsigned long count) |
---|
190 | 201 | { |
---|
191 | | - mm_segment_t old_fs; |
---|
192 | | - char __user *buf = (char __user *)addr; |
---|
193 | | - ssize_t ret; |
---|
194 | | - |
---|
195 | | - if (!(file->f_mode & FMODE_READ)) |
---|
196 | | - return -EBADF; |
---|
197 | | - |
---|
198 | | - old_fs = get_fs(); |
---|
199 | | - set_fs(get_ds()); |
---|
200 | | - ret = __vfs_read(file, buf, count, &offset); |
---|
201 | | - set_fs(old_fs); |
---|
202 | | - |
---|
203 | | - return ret; |
---|
| 202 | + return __kernel_read(file, addr, count, &offset); |
---|
204 | 203 | } |
---|
205 | 204 | |
---|
206 | 205 | /* |
---|