aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ima.h17
-rw-r--r--security/integrity/ima/ima_appraise.c57
-rw-r--r--security/security.c6
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
46extern void ima_inode_post_setattr(struct dentry *dentry); 46extern void ima_inode_post_setattr(struct dentry *dentry);
47extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
48 const void *xattr_value, size_t xattr_value_len);
49extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name);
47#else 50#else
48static inline void ima_inode_post_setattr(struct dentry *dentry) 51static inline void ima_inode_post_setattr(struct dentry *dentry)
49{ 52{
50 return; 53 return;
51} 54}
55
56static 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
64static 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 */
178static 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
189static 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
204int 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
218int 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