diff options
-rw-r--r-- | include/linux/ima.h | 17 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 57 | ||||
-rw-r--r-- | security/security.c | 6 |
3 files changed, 80 insertions, 0 deletions
diff --git a/include/linux/ima.h b/include/linux/ima.h index e2bfbb1e9af6..2c7223d7e73b 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h | |||
@@ -44,10 +44,27 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) | |||
44 | 44 | ||
45 | #ifdef CONFIG_IMA_APPRAISE | 45 | #ifdef CONFIG_IMA_APPRAISE |
46 | extern void ima_inode_post_setattr(struct dentry *dentry); | 46 | extern void ima_inode_post_setattr(struct dentry *dentry); |
47 | extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, | ||
48 | const void *xattr_value, size_t xattr_value_len); | ||
49 | extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name); | ||
47 | #else | 50 | #else |
48 | static inline void ima_inode_post_setattr(struct dentry *dentry) | 51 | static inline void ima_inode_post_setattr(struct dentry *dentry) |
49 | { | 52 | { |
50 | return; | 53 | return; |
51 | } | 54 | } |
55 | |||
56 | static inline int ima_inode_setxattr(struct dentry *dentry, | ||
57 | const char *xattr_name, | ||
58 | const void *xattr_value, | ||
59 | size_t xattr_value_len) | ||
60 | { | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static inline int ima_inode_removexattr(struct dentry *dentry, | ||
65 | const char *xattr_name) | ||
66 | { | ||
67 | return 0; | ||
68 | } | ||
52 | #endif /* CONFIG_IMA_APPRAISE_H */ | 69 | #endif /* CONFIG_IMA_APPRAISE_H */ |
53 | #endif /* _LINUX_IMA_H */ | 70 | #endif /* _LINUX_IMA_H */ |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 681cb6e72257..becc7e09116d 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
@@ -169,3 +169,60 @@ void ima_inode_post_setattr(struct dentry *dentry) | |||
169 | rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); | 169 | rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); |
170 | return; | 170 | return; |
171 | } | 171 | } |
172 | |||
173 | /* | ||
174 | * ima_protect_xattr - protect 'security.ima' | ||
175 | * | ||
176 | * Ensure that not just anyone can modify or remove 'security.ima'. | ||
177 | */ | ||
178 | static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, | ||
179 | const void *xattr_value, size_t xattr_value_len) | ||
180 | { | ||
181 | if (strcmp(xattr_name, XATTR_NAME_IMA) == 0) { | ||
182 | if (!capable(CAP_SYS_ADMIN)) | ||
183 | return -EPERM; | ||
184 | return 1; | ||
185 | } | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static void ima_reset_appraise_flags(struct inode *inode) | ||
190 | { | ||
191 | struct integrity_iint_cache *iint; | ||
192 | |||
193 | if (!ima_initialized || !ima_appraise || !S_ISREG(inode->i_mode)) | ||
194 | return; | ||
195 | |||
196 | iint = integrity_iint_find(inode); | ||
197 | if (!iint) | ||
198 | return; | ||
199 | |||
200 | iint->flags &= ~(IMA_COLLECTED | IMA_APPRAISED | IMA_MEASURED); | ||
201 | return; | ||
202 | } | ||
203 | |||
204 | int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, | ||
205 | const void *xattr_value, size_t xattr_value_len) | ||
206 | { | ||
207 | int result; | ||
208 | |||
209 | result = ima_protect_xattr(dentry, xattr_name, xattr_value, | ||
210 | xattr_value_len); | ||
211 | if (result == 1) { | ||
212 | ima_reset_appraise_flags(dentry->d_inode); | ||
213 | result = 0; | ||
214 | } | ||
215 | return result; | ||
216 | } | ||
217 | |||
218 | int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) | ||
219 | { | ||
220 | int result; | ||
221 | |||
222 | result = ima_protect_xattr(dentry, xattr_name, NULL, 0); | ||
223 | if (result == 1) { | ||
224 | ima_reset_appraise_flags(dentry->d_inode); | ||
225 | result = 0; | ||
226 | } | ||
227 | return result; | ||
228 | } | ||
diff --git a/security/security.c b/security/security.c index 68c1b9b45d93..d23b43522a5a 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -573,6 +573,9 @@ int security_inode_setxattr(struct dentry *dentry, const char *name, | |||
573 | ret = security_ops->inode_setxattr(dentry, name, value, size, flags); | 573 | ret = security_ops->inode_setxattr(dentry, name, value, size, flags); |
574 | if (ret) | 574 | if (ret) |
575 | return ret; | 575 | return ret; |
576 | ret = ima_inode_setxattr(dentry, name, value, size); | ||
577 | if (ret) | ||
578 | return ret; | ||
576 | return evm_inode_setxattr(dentry, name, value, size); | 579 | return evm_inode_setxattr(dentry, name, value, size); |
577 | } | 580 | } |
578 | 581 | ||
@@ -608,6 +611,9 @@ int security_inode_removexattr(struct dentry *dentry, const char *name) | |||
608 | ret = security_ops->inode_removexattr(dentry, name); | 611 | ret = security_ops->inode_removexattr(dentry, name); |
609 | if (ret) | 612 | if (ret) |
610 | return ret; | 613 | return ret; |
614 | ret = ima_inode_removexattr(dentry, name); | ||
615 | if (ret) | ||
616 | return ret; | ||
611 | return evm_inode_removexattr(dentry, name); | 617 | return evm_inode_removexattr(dentry, name); |
612 | } | 618 | } |
613 | 619 | ||