Skip to content

Commit 4de2f08

Browse files
robertosassupcmoore
authored andcommitted
ima: Make it independent from 'integrity' LSM
Make the 'ima' LSM independent from the 'integrity' LSM by introducing IMA own integrity metadata (ima_iint_cache structure, with IMA-specific fields from the integrity_iint_cache structure), and by managing it directly from the 'ima' LSM. Create ima_iint.c and introduce the same integrity metadata management functions found in iint.c (renamed with ima_). However, instead of putting metadata in an rbtree, reserve space from IMA in the inode security blob for a pointer, and introduce the ima_inode_set_iint()/ima_inode_get_iint() primitives to store/retrieve that pointer. This improves search time from logarithmic to constant. Consequently, don't include the inode pointer as field in the ima_iint_cache structure, since the association with the inode is clear. Since the inode field is missing in ima_iint_cache, pass the extra inode parameter to ima_get_verity_digest(). Prefer storing the pointer instead of the entire ima_iint_cache structure, to avoid too much memory pressure. Use the same mechanism as before, a cache named ima_iint_cache (renamed from iint_cache), to quickly allocate a new ima_iint_cache structure when requested by the IMA policy. Create the new ima_iint_cache in ima_iintcache_init(), called by init_ima_lsm(), during the initialization of the 'ima' LSM. And, register ima_inode_free_security() to free the ima_iint_cache structure, if exists. Replace integrity_iint_cache with ima_iint_cache in various places of the IMA code. Also, replace integrity_inode_get() and integrity_iint_find(), respectively with ima_inode_get() and ima_iint_find(). Finally, move the remaining IMA-specific flags to security/integrity/ima/ima.h, since they are now unnecessary in the common integrity layer. Signed-off-by: Roberto Sassu <[email protected]> Reviewed-by: Casey Schaufler <[email protected]> Reviewed-by: Stefan Berger <[email protected]> Reviewed-by: Mimi Zohar <[email protected]> Acked-by: Mimi Zohar <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent 75a323e commit 4de2f08

File tree

9 files changed

+308
-116
lines changed

9 files changed

+308
-116
lines changed

security/integrity/ima/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Measurement Architecture(IMA).
55
#
66

7-
obj-$(CONFIG_IMA) += ima.o
7+
obj-$(CONFIG_IMA) += ima.o ima_iint.o
88

99
ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
1010
ima_policy.o ima_template.o ima_template_lib.o

security/integrity/ima/ima.h

Lines changed: 118 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ extern const char boot_aggregate_name[];
6060

6161
/* IMA event related data */
6262
struct ima_event_data {
63-
struct integrity_iint_cache *iint;
63+
struct ima_iint_cache *iint;
6464
struct file *file;
6565
const unsigned char *filename;
6666
struct evm_ima_xattr_data *xattr_value;
@@ -119,6 +119,107 @@ struct ima_kexec_hdr {
119119
u64 count;
120120
};
121121

122+
/* IMA iint action cache flags */
123+
#define IMA_MEASURE 0x00000001
124+
#define IMA_MEASURED 0x00000002
125+
#define IMA_APPRAISE 0x00000004
126+
#define IMA_APPRAISED 0x00000008
127+
/*#define IMA_COLLECT 0x00000010 do not use this flag */
128+
#define IMA_COLLECTED 0x00000020
129+
#define IMA_AUDIT 0x00000040
130+
#define IMA_AUDITED 0x00000080
131+
#define IMA_HASH 0x00000100
132+
#define IMA_HASHED 0x00000200
133+
134+
/* IMA iint policy rule cache flags */
135+
#define IMA_NONACTION_FLAGS 0xff000000
136+
#define IMA_DIGSIG_REQUIRED 0x01000000
137+
#define IMA_PERMIT_DIRECTIO 0x02000000
138+
#define IMA_NEW_FILE 0x04000000
139+
#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000
140+
#define IMA_MODSIG_ALLOWED 0x20000000
141+
#define IMA_CHECK_BLACKLIST 0x40000000
142+
#define IMA_VERITY_REQUIRED 0x80000000
143+
144+
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
145+
IMA_HASH | IMA_APPRAISE_SUBMASK)
146+
#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED | \
147+
IMA_HASHED | IMA_COLLECTED | \
148+
IMA_APPRAISED_SUBMASK)
149+
150+
/* IMA iint subaction appraise cache flags */
151+
#define IMA_FILE_APPRAISE 0x00001000
152+
#define IMA_FILE_APPRAISED 0x00002000
153+
#define IMA_MMAP_APPRAISE 0x00004000
154+
#define IMA_MMAP_APPRAISED 0x00008000
155+
#define IMA_BPRM_APPRAISE 0x00010000
156+
#define IMA_BPRM_APPRAISED 0x00020000
157+
#define IMA_READ_APPRAISE 0x00040000
158+
#define IMA_READ_APPRAISED 0x00080000
159+
#define IMA_CREDS_APPRAISE 0x00100000
160+
#define IMA_CREDS_APPRAISED 0x00200000
161+
#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \
162+
IMA_BPRM_APPRAISE | IMA_READ_APPRAISE | \
163+
IMA_CREDS_APPRAISE)
164+
#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \
165+
IMA_BPRM_APPRAISED | IMA_READ_APPRAISED | \
166+
IMA_CREDS_APPRAISED)
167+
168+
/* IMA iint cache atomic_flags */
169+
#define IMA_CHANGE_XATTR 0
170+
#define IMA_UPDATE_XATTR 1
171+
#define IMA_CHANGE_ATTR 2
172+
#define IMA_DIGSIG 3
173+
#define IMA_MUST_MEASURE 4
174+
175+
/* IMA integrity metadata associated with an inode */
176+
struct ima_iint_cache {
177+
struct mutex mutex; /* protects: version, flags, digest */
178+
u64 version; /* track inode changes */
179+
unsigned long flags;
180+
unsigned long measured_pcrs;
181+
unsigned long atomic_flags;
182+
unsigned long real_ino;
183+
dev_t real_dev;
184+
enum integrity_status ima_file_status:4;
185+
enum integrity_status ima_mmap_status:4;
186+
enum integrity_status ima_bprm_status:4;
187+
enum integrity_status ima_read_status:4;
188+
enum integrity_status ima_creds_status:4;
189+
struct ima_digest_data *ima_hash;
190+
};
191+
192+
extern struct lsm_blob_sizes ima_blob_sizes;
193+
194+
static inline struct ima_iint_cache *
195+
ima_inode_get_iint(const struct inode *inode)
196+
{
197+
struct ima_iint_cache **iint_sec;
198+
199+
if (unlikely(!inode->i_security))
200+
return NULL;
201+
202+
iint_sec = inode->i_security + ima_blob_sizes.lbs_inode;
203+
return *iint_sec;
204+
}
205+
206+
static inline void ima_inode_set_iint(const struct inode *inode,
207+
struct ima_iint_cache *iint)
208+
{
209+
struct ima_iint_cache **iint_sec;
210+
211+
if (unlikely(!inode->i_security))
212+
return;
213+
214+
iint_sec = inode->i_security + ima_blob_sizes.lbs_inode;
215+
*iint_sec = iint;
216+
}
217+
218+
struct ima_iint_cache *ima_iint_find(struct inode *inode);
219+
struct ima_iint_cache *ima_inode_get(struct inode *inode);
220+
void ima_inode_free(struct inode *inode);
221+
void __init ima_iintcache_init(void);
222+
122223
extern const int read_idmap[];
123224

124225
#ifdef CONFIG_HAVE_IMA_KEXEC
@@ -152,8 +253,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
152253
struct ima_template_entry *entry);
153254
int ima_calc_boot_aggregate(struct ima_digest_data *hash);
154255
void ima_add_violation(struct file *file, const unsigned char *filename,
155-
struct integrity_iint_cache *iint,
156-
const char *op, const char *cause);
256+
struct ima_iint_cache *iint, const char *op,
257+
const char *cause);
157258
int ima_init_crypto(void);
158259
void ima_putc(struct seq_file *m, void *data, int datalen);
159260
void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
@@ -267,10 +368,10 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode,
267368
struct ima_template_desc **template_desc,
268369
const char *func_data, unsigned int *allowed_algos);
269370
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
270-
int ima_collect_measurement(struct integrity_iint_cache *iint,
271-
struct file *file, void *buf, loff_t size,
272-
enum hash_algo algo, struct modsig *modsig);
273-
void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
371+
int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
372+
void *buf, loff_t size, enum hash_algo algo,
373+
struct modsig *modsig);
374+
void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
274375
const unsigned char *filename,
275376
struct evm_ima_xattr_data *xattr_value,
276377
int xattr_len, const struct modsig *modsig, int pcr,
@@ -280,7 +381,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap,
280381
const char *eventname, enum ima_hooks func,
281382
int pcr, const char *func_data,
282383
bool buf_hash, u8 *digest, size_t digest_len);
283-
void ima_audit_measurement(struct integrity_iint_cache *iint,
384+
void ima_audit_measurement(struct ima_iint_cache *iint,
284385
const unsigned char *filename);
285386
int ima_alloc_init_template(struct ima_event_data *event_data,
286387
struct ima_template_entry **entry,
@@ -318,17 +419,16 @@ int ima_policy_show(struct seq_file *m, void *v);
318419
#define IMA_APPRAISE_KEXEC 0x40
319420

320421
#ifdef CONFIG_IMA_APPRAISE
321-
int ima_check_blacklist(struct integrity_iint_cache *iint,
422+
int ima_check_blacklist(struct ima_iint_cache *iint,
322423
const struct modsig *modsig, int pcr);
323-
int ima_appraise_measurement(enum ima_hooks func,
324-
struct integrity_iint_cache *iint,
424+
int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
325425
struct file *file, const unsigned char *filename,
326426
struct evm_ima_xattr_data *xattr_value,
327427
int xattr_len, const struct modsig *modsig);
328428
int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
329429
int mask, enum ima_hooks func);
330-
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
331-
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
430+
void ima_update_xattr(struct ima_iint_cache *iint, struct file *file);
431+
enum integrity_status ima_get_cache_status(struct ima_iint_cache *iint,
332432
enum ima_hooks func);
333433
enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
334434
int xattr_len);
@@ -337,14 +437,14 @@ int ima_read_xattr(struct dentry *dentry,
337437
void __init init_ima_appraise_lsm(const struct lsm_id *lsmid);
338438

339439
#else
340-
static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
440+
static inline int ima_check_blacklist(struct ima_iint_cache *iint,
341441
const struct modsig *modsig, int pcr)
342442
{
343443
return 0;
344444
}
345445

346446
static inline int ima_appraise_measurement(enum ima_hooks func,
347-
struct integrity_iint_cache *iint,
447+
struct ima_iint_cache *iint,
348448
struct file *file,
349449
const unsigned char *filename,
350450
struct evm_ima_xattr_data *xattr_value,
@@ -361,14 +461,13 @@ static inline int ima_must_appraise(struct mnt_idmap *idmap,
361461
return 0;
362462
}
363463

364-
static inline void ima_update_xattr(struct integrity_iint_cache *iint,
464+
static inline void ima_update_xattr(struct ima_iint_cache *iint,
365465
struct file *file)
366466
{
367467
}
368468

369-
static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache
370-
*iint,
371-
enum ima_hooks func)
469+
static inline enum integrity_status
470+
ima_get_cache_status(struct ima_iint_cache *iint, enum ima_hooks func)
372471
{
373472
return INTEGRITY_UNKNOWN;
374473
}

security/integrity/ima/ima_api.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ int ima_store_template(struct ima_template_entry *entry,
131131
* value is invalidated.
132132
*/
133133
void ima_add_violation(struct file *file, const unsigned char *filename,
134-
struct integrity_iint_cache *iint,
135-
const char *op, const char *cause)
134+
struct ima_iint_cache *iint, const char *op,
135+
const char *cause)
136136
{
137137
struct ima_template_entry *entry;
138138
struct inode *inode = file_inode(file);
@@ -201,7 +201,8 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode,
201201
allowed_algos);
202202
}
203203

204-
static bool ima_get_verity_digest(struct integrity_iint_cache *iint,
204+
static bool ima_get_verity_digest(struct ima_iint_cache *iint,
205+
struct inode *inode,
205206
struct ima_max_digest_data *hash)
206207
{
207208
enum hash_algo alg;
@@ -211,7 +212,7 @@ static bool ima_get_verity_digest(struct integrity_iint_cache *iint,
211212
* On failure, 'measure' policy rules will result in a file data
212213
* hash containing 0's.
213214
*/
214-
digest_len = fsverity_get_digest(iint->inode, hash->digest, NULL, &alg);
215+
digest_len = fsverity_get_digest(inode, hash->digest, NULL, &alg);
215216
if (digest_len == 0)
216217
return false;
217218

@@ -237,9 +238,9 @@ static bool ima_get_verity_digest(struct integrity_iint_cache *iint,
237238
*
238239
* Return 0 on success, error code otherwise
239240
*/
240-
int ima_collect_measurement(struct integrity_iint_cache *iint,
241-
struct file *file, void *buf, loff_t size,
242-
enum hash_algo algo, struct modsig *modsig)
241+
int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
242+
void *buf, loff_t size, enum hash_algo algo,
243+
struct modsig *modsig)
243244
{
244245
const char *audit_cause = "failed";
245246
struct inode *inode = file_inode(file);
@@ -280,7 +281,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
280281
memset(&hash.digest, 0, sizeof(hash.digest));
281282

282283
if (iint->flags & IMA_VERITY_REQUIRED) {
283-
if (!ima_get_verity_digest(iint, &hash)) {
284+
if (!ima_get_verity_digest(iint, inode, &hash)) {
284285
audit_cause = "no-verity-digest";
285286
result = -ENODATA;
286287
}
@@ -338,8 +339,8 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
338339
*
339340
* Must be called with iint->mutex held.
340341
*/
341-
void ima_store_measurement(struct integrity_iint_cache *iint,
342-
struct file *file, const unsigned char *filename,
342+
void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
343+
const unsigned char *filename,
343344
struct evm_ima_xattr_data *xattr_value,
344345
int xattr_len, const struct modsig *modsig, int pcr,
345346
struct ima_template_desc *template_desc)
@@ -382,7 +383,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
382383
ima_free_template_entry(entry);
383384
}
384385

385-
void ima_audit_measurement(struct integrity_iint_cache *iint,
386+
void ima_audit_measurement(struct ima_iint_cache *iint,
386387
const unsigned char *filename)
387388
{
388389
struct audit_buffer *ab;

security/integrity/ima/ima_appraise.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
8484
NULL, NULL, NULL);
8585
}
8686

87-
static int ima_fix_xattr(struct dentry *dentry,
88-
struct integrity_iint_cache *iint)
87+
static int ima_fix_xattr(struct dentry *dentry, struct ima_iint_cache *iint)
8988
{
9089
int rc, offset;
9190
u8 algo = iint->ima_hash->algo;
@@ -106,7 +105,7 @@ static int ima_fix_xattr(struct dentry *dentry,
106105
}
107106

108107
/* Return specific func appraised cached result */
109-
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
108+
enum integrity_status ima_get_cache_status(struct ima_iint_cache *iint,
110109
enum ima_hooks func)
111110
{
112111
switch (func) {
@@ -126,7 +125,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
126125
}
127126
}
128127

129-
static void ima_set_cache_status(struct integrity_iint_cache *iint,
128+
static void ima_set_cache_status(struct ima_iint_cache *iint,
130129
enum ima_hooks func,
131130
enum integrity_status status)
132131
{
@@ -152,8 +151,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint,
152151
}
153152
}
154153

155-
static void ima_cache_flags(struct integrity_iint_cache *iint,
156-
enum ima_hooks func)
154+
static void ima_cache_flags(struct ima_iint_cache *iint, enum ima_hooks func)
157155
{
158156
switch (func) {
159157
case MMAP_CHECK:
@@ -276,7 +274,7 @@ static int calc_file_id_hash(enum evm_ima_xattr_type type,
276274
*
277275
* Return 0 on success, error code otherwise.
278276
*/
279-
static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
277+
static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint,
280278
struct evm_ima_xattr_data *xattr_value, int xattr_len,
281279
enum integrity_status *status, const char **cause)
282280
{
@@ -443,7 +441,7 @@ static int modsig_verify(enum ima_hooks func, const struct modsig *modsig,
443441
*
444442
* Returns -EPERM if the hash is blacklisted.
445443
*/
446-
int ima_check_blacklist(struct integrity_iint_cache *iint,
444+
int ima_check_blacklist(struct ima_iint_cache *iint,
447445
const struct modsig *modsig, int pcr)
448446
{
449447
enum hash_algo hash_algo;
@@ -477,8 +475,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
477475
*
478476
* Return 0 on success, error code otherwise
479477
*/
480-
int ima_appraise_measurement(enum ima_hooks func,
481-
struct integrity_iint_cache *iint,
478+
int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
482479
struct file *file, const unsigned char *filename,
483480
struct evm_ima_xattr_data *xattr_value,
484481
int xattr_len, const struct modsig *modsig)
@@ -603,7 +600,7 @@ int ima_appraise_measurement(enum ima_hooks func,
603600
/*
604601
* ima_update_xattr - update 'security.ima' hash value
605602
*/
606-
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
603+
void ima_update_xattr(struct ima_iint_cache *iint, struct file *file)
607604
{
608605
struct dentry *dentry = file_dentry(file);
609606
int rc = 0;
@@ -640,15 +637,15 @@ static void ima_inode_post_setattr(struct mnt_idmap *idmap,
640637
struct dentry *dentry, int ia_valid)
641638
{
642639
struct inode *inode = d_backing_inode(dentry);
643-
struct integrity_iint_cache *iint;
640+
struct ima_iint_cache *iint;
644641
int action;
645642

646643
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
647644
|| !(inode->i_opflags & IOP_XATTR))
648645
return;
649646

650647
action = ima_must_appraise(idmap, inode, MAY_ACCESS, POST_SETATTR);
651-
iint = integrity_iint_find(inode);
648+
iint = ima_iint_find(inode);
652649
if (iint) {
653650
set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags);
654651
if (!action)
@@ -674,12 +671,12 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
674671

675672
static void ima_reset_appraise_flags(struct inode *inode, int digsig)
676673
{
677-
struct integrity_iint_cache *iint;
674+
struct ima_iint_cache *iint;
678675

679676
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
680677
return;
681678

682-
iint = integrity_iint_find(inode);
679+
iint = ima_iint_find(inode);
683680
if (!iint)
684681
return;
685682
iint->measured_pcrs = 0;

0 commit comments

Comments
 (0)