Skip to content

Commit a178d20

Browse files
eparistorvalds
authored andcommitted
IMA: move read counter into struct inode
IMA currently allocated an inode integrity structure for every inode in core. This stucture is about 120 bytes long. Most files however (especially on a system which doesn't make use of IMA) will never need any of this space. The problem is that if IMA is enabled we need to know information about the number of readers and the number of writers for every inode on the box. At the moment we collect that information in the per inode iint structure and waste the rest of the space. This patch moves those counters into the struct inode so we can eventually stop allocating an IMA integrity structure except when absolutely needed. This patch does the minimum needed to move the location of the data. Further cleanups, especially the location of counter updates, may still be possible. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent b9593d3 commit a178d20

File tree

6 files changed

+22
-34
lines changed

6 files changed

+22
-34
lines changed

fs/inode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/mount.h>
2525
#include <linux/async.h>
2626
#include <linux/posix_acl.h>
27+
#include <linux/ima.h>
2728

2829
/*
2930
* This is needed for the following functions:

include/linux/fs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,10 @@ struct inode {
776776

777777
unsigned int i_flags;
778778

779+
#ifdef CONFIG_IMA
780+
/* protected by i_lock */
781+
unsigned int i_readcount; /* struct files open RO */
782+
#endif
779783
atomic_t i_writecount;
780784
#ifdef CONFIG_SECURITY
781785
void *i_security;

security/integrity/ima/ima.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ int ima_init(void);
7070
void ima_cleanup(void);
7171
int ima_fs_init(void);
7272
void ima_fs_cleanup(void);
73+
int ima_inode_alloc(struct inode *inode);
7374
int ima_add_template_entry(struct ima_template_entry *entry, int violation,
7475
const char *op, struct inode *inode);
7576
int ima_calc_hash(struct file *file, char *digest);
@@ -106,8 +107,6 @@ struct ima_iint_cache {
106107
unsigned char flags;
107108
u8 digest[IMA_DIGEST_SIZE];
108109
struct mutex mutex; /* protects: version, flags, digest */
109-
/* protected by inode->i_lock */
110-
unsigned int readcount; /* measured files readcount */
111110
struct kref refcount; /* ima_iint_cache reference count */
112111
};
113112

security/integrity/ima/ima_api.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
116116
{
117117
int must_measure;
118118

119-
if (iint->flags & IMA_MEASURED)
119+
if (iint && iint->flags & IMA_MEASURED)
120120
return 1;
121121

122122
must_measure = ima_match_policy(inode, function, mask);

security/integrity/ima/ima_iint.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,6 @@ void iint_free(struct kref *kref)
124124
refcount);
125125
iint->version = 0;
126126
iint->flags = 0UL;
127-
if (iint->readcount != 0) {
128-
printk(KERN_INFO "%s: readcount: %u\n", __func__,
129-
iint->readcount);
130-
iint->readcount = 0;
131-
}
132127
kref_init(&iint->refcount);
133128
kmem_cache_free(iint_cache, iint);
134129
}
@@ -143,6 +138,11 @@ void ima_inode_free(struct inode *inode)
143138
{
144139
struct ima_iint_cache *iint;
145140

141+
if (inode->i_readcount)
142+
printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount);
143+
144+
inode->i_readcount = 0;
145+
146146
spin_lock(&ima_iint_lock);
147147
iint = __ima_iint_find(inode);
148148
if (iint)
@@ -160,7 +160,6 @@ static void init_once(void *foo)
160160
iint->version = 0;
161161
iint->flags = 0UL;
162162
mutex_init(&iint->mutex);
163-
iint->readcount = 0;
164163
kref_init(&iint->refcount);
165164
}
166165

security/integrity/ima/ima_main.c

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,6 @@ static bool ima_limit_imbalance(struct file *file)
8585
return found;
8686
}
8787

88-
/*
89-
* Update the counts given an fmode_t
90-
*/
91-
static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
92-
{
93-
assert_spin_locked(&iint->inode->i_lock);
94-
95-
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
96-
iint->readcount++;
97-
}
98-
9988
/*
10089
* ima_counts_get - increment file counts
10190
*
@@ -112,38 +101,34 @@ void ima_counts_get(struct file *file)
112101
struct dentry *dentry = file->f_path.dentry;
113102
struct inode *inode = dentry->d_inode;
114103
fmode_t mode = file->f_mode;
115-
struct ima_iint_cache *iint;
116104
int rc;
117105
bool send_tomtou = false, send_writers = false;
118106

119-
if (!iint_initialized || !S_ISREG(inode->i_mode))
107+
if (!S_ISREG(inode->i_mode))
120108
return;
121-
iint = ima_iint_find_get(inode);
122-
if (!iint)
123-
return;
124-
mutex_lock(&iint->mutex);
109+
125110
spin_lock(&inode->i_lock);
126111

127112
if (!ima_initialized)
128113
goto out;
129114

130-
rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
115+
rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK);
131116
if (rc < 0)
132117
goto out;
133118

134119
if (mode & FMODE_WRITE) {
135-
if (iint->readcount)
120+
if (inode->i_readcount)
136121
send_tomtou = true;
137122
goto out;
138123
}
139124

140125
if (atomic_read(&inode->i_writecount) > 0)
141126
send_writers = true;
142127
out:
143-
ima_inc_counts(iint, file->f_mode);
128+
/* remember the vfs deals with i_writecount */
129+
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
130+
inode->i_readcount++;
144131
spin_unlock(&inode->i_lock);
145-
mutex_unlock(&iint->mutex);
146-
kref_put(&iint->refcount, iint_free);
147132

148133
if (send_tomtou)
149134
ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
@@ -166,9 +151,9 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
166151
assert_spin_locked(&inode->i_lock);
167152

168153
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
169-
if (unlikely(iint->readcount == 0))
154+
if (unlikely(inode->i_readcount == 0))
170155
dump = true;
171-
iint->readcount--;
156+
inode->i_readcount--;
172157
}
173158
if (mode & FMODE_WRITE) {
174159
if (atomic_read(&inode->i_writecount) <= 0)
@@ -180,7 +165,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
180165

181166
if (dump && !ima_limit_imbalance(file)) {
182167
printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
183-
__func__, iint->readcount);
168+
__func__, inode->i_readcount);
184169
dump_stack();
185170
}
186171
}

0 commit comments

Comments
 (0)