| .. | .. |
|---|
| 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 | /* |
|---|