Commit a178d2027d3198b0a04517d764326ab71cd73da2

Authored by Eric Paris
Committed by Linus Torvalds
1 parent b9593d309d

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>

Showing 6 changed files with 22 additions and 34 deletions Side-by-side Diff

... ... @@ -24,6 +24,7 @@
24 24 #include <linux/mount.h>
25 25 #include <linux/async.h>
26 26 #include <linux/posix_acl.h>
  27 +#include <linux/ima.h>
27 28  
28 29 /*
29 30 * This is needed for the following functions:
... ... @@ -776,6 +776,10 @@
776 776  
777 777 unsigned int i_flags;
778 778  
  779 +#ifdef CONFIG_IMA
  780 + /* protected by i_lock */
  781 + unsigned int i_readcount; /* struct files open RO */
  782 +#endif
779 783 atomic_t i_writecount;
780 784 #ifdef CONFIG_SECURITY
781 785 void *i_security;
security/integrity/ima/ima.h
... ... @@ -70,6 +70,7 @@
70 70 void ima_cleanup(void);
71 71 int ima_fs_init(void);
72 72 void ima_fs_cleanup(void);
  73 +int ima_inode_alloc(struct inode *inode);
73 74 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
74 75 const char *op, struct inode *inode);
75 76 int ima_calc_hash(struct file *file, char *digest);
... ... @@ -106,8 +107,6 @@
106 107 unsigned char flags;
107 108 u8 digest[IMA_DIGEST_SIZE];
108 109 struct mutex mutex; /* protects: version, flags, digest */
109   - /* protected by inode->i_lock */
110   - unsigned int readcount; /* measured files readcount */
111 110 struct kref refcount; /* ima_iint_cache reference count */
112 111 };
113 112  
security/integrity/ima/ima_api.c
... ... @@ -116,7 +116,7 @@
116 116 {
117 117 int must_measure;
118 118  
119   - if (iint->flags & IMA_MEASURED)
  119 + if (iint && iint->flags & IMA_MEASURED)
120 120 return 1;
121 121  
122 122 must_measure = ima_match_policy(inode, function, mask);
security/integrity/ima/ima_iint.c
... ... @@ -124,11 +124,6 @@
124 124 refcount);
125 125 iint->version = 0;
126 126 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   - }
132 127 kref_init(&iint->refcount);
133 128 kmem_cache_free(iint_cache, iint);
134 129 }
... ... @@ -143,6 +138,11 @@
143 138 {
144 139 struct ima_iint_cache *iint;
145 140  
  141 + if (inode->i_readcount)
  142 + printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount);
  143 +
  144 + inode->i_readcount = 0;
  145 +
146 146 spin_lock(&ima_iint_lock);
147 147 iint = __ima_iint_find(inode);
148 148 if (iint)
... ... @@ -160,7 +160,6 @@
160 160 iint->version = 0;
161 161 iint->flags = 0UL;
162 162 mutex_init(&iint->mutex);
163   - iint->readcount = 0;
164 163 kref_init(&iint->refcount);
165 164 }
166 165  
security/integrity/ima/ima_main.c
... ... @@ -86,17 +86,6 @@
86 86 }
87 87  
88 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   -
99   -/*
100 89 * ima_counts_get - increment file counts
101 90 *
102 91 * Maintain read/write counters for all files, but only
103 92  
104 93  
105 94  
106 95  
... ... @@ -112,27 +101,23 @@
112 101 struct dentry *dentry = file->f_path.dentry;
113 102 struct inode *inode = dentry->d_inode;
114 103 fmode_t mode = file->f_mode;
115   - struct ima_iint_cache *iint;
116 104 int rc;
117 105 bool send_tomtou = false, send_writers = false;
118 106  
119   - if (!iint_initialized || !S_ISREG(inode->i_mode))
  107 + if (!S_ISREG(inode->i_mode))
120 108 return;
121   - iint = ima_iint_find_get(inode);
122   - if (!iint)
123   - return;
124   - mutex_lock(&iint->mutex);
  109 +
125 110 spin_lock(&inode->i_lock);
126 111  
127 112 if (!ima_initialized)
128 113 goto out;
129 114  
130   - rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
  115 + rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK);
131 116 if (rc < 0)
132 117 goto out;
133 118  
134 119 if (mode & FMODE_WRITE) {
135   - if (iint->readcount)
  120 + if (inode->i_readcount)
136 121 send_tomtou = true;
137 122 goto out;
138 123 }
139 124  
... ... @@ -140,10 +125,10 @@
140 125 if (atomic_read(&inode->i_writecount) > 0)
141 126 send_writers = true;
142 127 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++;
144 131 spin_unlock(&inode->i_lock);
145   - mutex_unlock(&iint->mutex);
146   - kref_put(&iint->refcount, iint_free);
147 132  
148 133 if (send_tomtou)
149 134 ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
150 135  
... ... @@ -166,9 +151,9 @@
166 151 assert_spin_locked(&inode->i_lock);
167 152  
168 153 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
169   - if (unlikely(iint->readcount == 0))
  154 + if (unlikely(inode->i_readcount == 0))
170 155 dump = true;
171   - iint->readcount--;
  156 + inode->i_readcount--;
172 157 }
173 158 if (mode & FMODE_WRITE) {
174 159 if (atomic_read(&inode->i_writecount) <= 0)
... ... @@ -180,7 +165,7 @@
180 165  
181 166 if (dump && !ima_limit_imbalance(file)) {
182 167 printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
183   - __func__, iint->readcount);
  168 + __func__, inode->i_readcount);
184 169 dump_stack();
185 170 }
186 171 }