diff options
Diffstat (limited to 'security/integrity/ima/ima_appraise.c')
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 92 |
1 files changed, 73 insertions, 19 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index bdc8ba1d1d27..2d4becab8918 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
@@ -42,12 +42,69 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func) | |||
42 | return ima_match_policy(inode, func, mask, IMA_APPRAISE); | 42 | return ima_match_policy(inode, func, mask, IMA_APPRAISE); |
43 | } | 43 | } |
44 | 44 | ||
45 | static void ima_fix_xattr(struct dentry *dentry, | 45 | static int ima_fix_xattr(struct dentry *dentry, |
46 | struct integrity_iint_cache *iint) | 46 | struct integrity_iint_cache *iint) |
47 | { | 47 | { |
48 | iint->ima_xattr.type = IMA_XATTR_DIGEST; | 48 | iint->ima_xattr.type = IMA_XATTR_DIGEST; |
49 | __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, (u8 *)&iint->ima_xattr, | 49 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, |
50 | sizeof iint->ima_xattr, 0); | 50 | (u8 *)&iint->ima_xattr, |
51 | sizeof(iint->ima_xattr), 0); | ||
52 | } | ||
53 | |||
54 | /* Return specific func appraised cached result */ | ||
55 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, | ||
56 | int func) | ||
57 | { | ||
58 | switch(func) { | ||
59 | case MMAP_CHECK: | ||
60 | return iint->ima_mmap_status; | ||
61 | case BPRM_CHECK: | ||
62 | return iint->ima_bprm_status; | ||
63 | case MODULE_CHECK: | ||
64 | return iint->ima_module_status; | ||
65 | case FILE_CHECK: | ||
66 | default: | ||
67 | return iint->ima_file_status; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | static void ima_set_cache_status(struct integrity_iint_cache *iint, | ||
72 | int func, enum integrity_status status) | ||
73 | { | ||
74 | switch(func) { | ||
75 | case MMAP_CHECK: | ||
76 | iint->ima_mmap_status = status; | ||
77 | break; | ||
78 | case BPRM_CHECK: | ||
79 | iint->ima_bprm_status = status; | ||
80 | break; | ||
81 | case MODULE_CHECK: | ||
82 | iint->ima_module_status = status; | ||
83 | break; | ||
84 | case FILE_CHECK: | ||
85 | default: | ||
86 | iint->ima_file_status = status; | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | static void ima_cache_flags(struct integrity_iint_cache *iint, int func) | ||
92 | { | ||
93 | switch(func) { | ||
94 | case MMAP_CHECK: | ||
95 | iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED); | ||
96 | break; | ||
97 | case BPRM_CHECK: | ||
98 | iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED); | ||
99 | break; | ||
100 | case MODULE_CHECK: | ||
101 | iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); | ||
102 | break; | ||
103 | case FILE_CHECK: | ||
104 | default: | ||
105 | iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); | ||
106 | break; | ||
107 | } | ||
51 | } | 108 | } |
52 | 109 | ||
53 | /* | 110 | /* |
@@ -58,7 +115,7 @@ static void ima_fix_xattr(struct dentry *dentry, | |||
58 | * | 115 | * |
59 | * Return 0 on success, error code otherwise | 116 | * Return 0 on success, error code otherwise |
60 | */ | 117 | */ |
61 | int ima_appraise_measurement(struct integrity_iint_cache *iint, | 118 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
62 | struct file *file, const unsigned char *filename) | 119 | struct file *file, const unsigned char *filename) |
63 | { | 120 | { |
64 | struct dentry *dentry = file->f_dentry; | 121 | struct dentry *dentry = file->f_dentry; |
@@ -74,9 +131,6 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, | |||
74 | if (!inode->i_op->getxattr) | 131 | if (!inode->i_op->getxattr) |
75 | return INTEGRITY_UNKNOWN; | 132 | return INTEGRITY_UNKNOWN; |
76 | 133 | ||
77 | if (iint->flags & IMA_APPRAISED) | ||
78 | return iint->ima_status; | ||
79 | |||
80 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value, | 134 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value, |
81 | 0, GFP_NOFS); | 135 | 0, GFP_NOFS); |
82 | if (rc <= 0) { | 136 | if (rc <= 0) { |
@@ -98,19 +152,18 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, | |||
98 | cause = "invalid-HMAC"; | 152 | cause = "invalid-HMAC"; |
99 | goto out; | 153 | goto out; |
100 | } | 154 | } |
101 | |||
102 | switch (xattr_value->type) { | 155 | switch (xattr_value->type) { |
103 | case IMA_XATTR_DIGEST: | 156 | case IMA_XATTR_DIGEST: |
157 | if (iint->flags & IMA_DIGSIG_REQUIRED) { | ||
158 | cause = "IMA signature required"; | ||
159 | status = INTEGRITY_FAIL; | ||
160 | break; | ||
161 | } | ||
104 | rc = memcmp(xattr_value->digest, iint->ima_xattr.digest, | 162 | rc = memcmp(xattr_value->digest, iint->ima_xattr.digest, |
105 | IMA_DIGEST_SIZE); | 163 | IMA_DIGEST_SIZE); |
106 | if (rc) { | 164 | if (rc) { |
107 | cause = "invalid-hash"; | 165 | cause = "invalid-hash"; |
108 | status = INTEGRITY_FAIL; | 166 | status = INTEGRITY_FAIL; |
109 | print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE, | ||
110 | xattr_value, sizeof(*xattr_value)); | ||
111 | print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE, | ||
112 | (u8 *)&iint->ima_xattr, | ||
113 | sizeof iint->ima_xattr); | ||
114 | break; | 167 | break; |
115 | } | 168 | } |
116 | status = INTEGRITY_PASS; | 169 | status = INTEGRITY_PASS; |
@@ -141,15 +194,15 @@ out: | |||
141 | if ((ima_appraise & IMA_APPRAISE_FIX) && | 194 | if ((ima_appraise & IMA_APPRAISE_FIX) && |
142 | (!xattr_value || | 195 | (!xattr_value || |
143 | xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { | 196 | xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { |
144 | ima_fix_xattr(dentry, iint); | 197 | if (!ima_fix_xattr(dentry, iint)) |
145 | status = INTEGRITY_PASS; | 198 | status = INTEGRITY_PASS; |
146 | } | 199 | } |
147 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, | 200 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, |
148 | op, cause, rc, 0); | 201 | op, cause, rc, 0); |
149 | } else { | 202 | } else { |
150 | iint->flags |= IMA_APPRAISED; | 203 | ima_cache_flags(iint, func); |
151 | } | 204 | } |
152 | iint->ima_status = status; | 205 | ima_set_cache_status(iint, func, status); |
153 | kfree(xattr_value); | 206 | kfree(xattr_value); |
154 | return status; | 207 | return status; |
155 | } | 208 | } |
@@ -195,10 +248,11 @@ void ima_inode_post_setattr(struct dentry *dentry) | |||
195 | must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); | 248 | must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); |
196 | iint = integrity_iint_find(inode); | 249 | iint = integrity_iint_find(inode); |
197 | if (iint) { | 250 | if (iint) { |
251 | iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED | | ||
252 | IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | | ||
253 | IMA_ACTION_FLAGS); | ||
198 | if (must_appraise) | 254 | if (must_appraise) |
199 | iint->flags |= IMA_APPRAISE; | 255 | iint->flags |= IMA_APPRAISE; |
200 | else | ||
201 | iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED); | ||
202 | } | 256 | } |
203 | if (!must_appraise) | 257 | if (!must_appraise) |
204 | rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); | 258 | rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); |