aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima_appraise.c70
-rw-r--r--security/integrity/integrity.h1
2 files changed, 52 insertions, 19 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index f9979976aa5d..4cdf36ad884a 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -63,7 +63,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
63{ 63{
64 struct dentry *dentry = file->f_dentry; 64 struct dentry *dentry = file->f_dentry;
65 struct inode *inode = dentry->d_inode; 65 struct inode *inode = dentry->d_inode;
66 struct evm_ima_xattr_data xattr_value; 66 struct evm_ima_xattr_data *xattr_value = NULL;
67 enum integrity_status status = INTEGRITY_UNKNOWN; 67 enum integrity_status status = INTEGRITY_UNKNOWN;
68 const char *op = "appraise_data"; 68 const char *op = "appraise_data";
69 char *cause = "unknown"; 69 char *cause = "unknown";
@@ -77,8 +77,8 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
77 if (iint->flags & IMA_APPRAISED) 77 if (iint->flags & IMA_APPRAISED)
78 return iint->ima_status; 78 return iint->ima_status;
79 79
80 rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value, 80 rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value,
81 sizeof xattr_value); 81 0, GFP_NOFS);
82 if (rc <= 0) { 82 if (rc <= 0) {
83 if (rc && rc != -ENODATA) 83 if (rc && rc != -ENODATA)
84 goto out; 84 goto out;
@@ -89,8 +89,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
89 goto out; 89 goto out;
90 } 90 }
91 91
92 status = evm_verifyxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value, 92 status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
93 rc, iint);
94 if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) { 93 if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
95 if ((status == INTEGRITY_NOLABEL) 94 if ((status == INTEGRITY_NOLABEL)
96 || (status == INTEGRITY_NOXATTRS)) 95 || (status == INTEGRITY_NOXATTRS))
@@ -100,30 +99,58 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
100 goto out; 99 goto out;
101 } 100 }
102 101
103 rc = memcmp(xattr_value.digest, iint->ima_xattr.digest, 102 switch (xattr_value->type) {
104 IMA_DIGEST_SIZE); 103 case IMA_XATTR_DIGEST:
105 if (rc) { 104 rc = memcmp(xattr_value->digest, iint->ima_xattr.digest,
106 status = INTEGRITY_FAIL; 105 IMA_DIGEST_SIZE);
107 cause = "invalid-hash"; 106 if (rc) {
108 print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE, 107 cause = "invalid-hash";
109 &xattr_value, sizeof xattr_value); 108 status = INTEGRITY_FAIL;
110 print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE, 109 print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
111 (u8 *)&iint->ima_xattr, 110 xattr_value, sizeof(*xattr_value));
112 sizeof iint->ima_xattr); 111 print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
113 goto out; 112 (u8 *)&iint->ima_xattr,
113 sizeof iint->ima_xattr);
114 break;
115 }
116 status = INTEGRITY_PASS;
117 break;
118 case EVM_IMA_XATTR_DIGSIG:
119 iint->flags |= IMA_DIGSIG;
120 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
121 xattr_value->digest, rc - 1,
122 iint->ima_xattr.digest,
123 IMA_DIGEST_SIZE);
124 if (rc == -EOPNOTSUPP) {
125 status = INTEGRITY_UNKNOWN;
126 } else if (rc) {
127 cause = "invalid-signature";
128 status = INTEGRITY_FAIL;
129 } else {
130 status = INTEGRITY_PASS;
131 }
132 break;
133 default:
134 status = INTEGRITY_UNKNOWN;
135 cause = "unknown-ima-data";
136 break;
114 } 137 }
115 status = INTEGRITY_PASS; 138
116 iint->flags |= IMA_APPRAISED;
117out: 139out:
118 if (status != INTEGRITY_PASS) { 140 if (status != INTEGRITY_PASS) {
119 if (ima_appraise & IMA_APPRAISE_FIX) { 141 if ((ima_appraise & IMA_APPRAISE_FIX) &&
142 (!xattr_value ||
143 xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
120 ima_fix_xattr(dentry, iint); 144 ima_fix_xattr(dentry, iint);
121 status = INTEGRITY_PASS; 145 status = INTEGRITY_PASS;
122 } 146 }
123 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, 147 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
124 op, cause, rc, 0); 148 op, cause, rc, 0);
149 } else {
150 iint->flags |= IMA_APPRAISED;
125 } 151 }
126 iint->ima_status = status; 152 iint->ima_status = status;
153 kfree(xattr_value);
127 return status; 154 return status;
128} 155}
129 156
@@ -135,9 +162,14 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
135 struct dentry *dentry = file->f_dentry; 162 struct dentry *dentry = file->f_dentry;
136 int rc = 0; 163 int rc = 0;
137 164
165 /* do not collect and update hash for digital signatures */
166 if (iint->flags & IMA_DIGSIG)
167 return;
168
138 rc = ima_collect_measurement(iint, file); 169 rc = ima_collect_measurement(iint, file);
139 if (rc < 0) 170 if (rc < 0)
140 return; 171 return;
172
141 ima_fix_xattr(dentry, iint); 173 ima_fix_xattr(dentry, iint);
142} 174}
143 175
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 91ccef1c704b..4eec1b14193e 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -21,6 +21,7 @@
21#define IMA_APPRAISE 0x04 21#define IMA_APPRAISE 0x04
22#define IMA_APPRAISED 0x08 22#define IMA_APPRAISED 0x08
23#define IMA_COLLECTED 0x10 23#define IMA_COLLECTED 0x10
24#define IMA_DIGSIG 0x20
24 25
25enum evm_ima_xattr_type { 26enum evm_ima_xattr_type {
26 IMA_XATTR_DIGEST = 0x01, 27 IMA_XATTR_DIGEST = 0x01,