Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

security: Add hook to invalidate inode security labels

Add a hook to invalidate an inode's security label when the cached
information becomes invalid.

Add the new hook in selinux: set a flag when a security label becomes
invalid.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: James Morris <james.l.morris@oracle.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <pmoore@redhat.com>

authored by

Andreas Gruenbacher and committed by
Paul Moore
6f3be9f5 83da53c5

+45 -10
+6
include/linux/lsm_hooks.h
··· 1261 1261 * audit_rule_init. 1262 1262 * @rule contains the allocated rule 1263 1263 * 1264 + * @inode_invalidate_secctx: 1265 + * Notify the security module that it must revalidate the security context 1266 + * of an inode. 1267 + * 1264 1268 * @inode_notifysecctx: 1265 1269 * Notify the security module of what the security context of an inode 1266 1270 * should be. Initializes the incore security context managed by the ··· 1520 1516 int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid); 1521 1517 void (*release_secctx)(char *secdata, u32 seclen); 1522 1518 1519 + void (*inode_invalidate_secctx)(struct inode *inode); 1523 1520 int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen); 1524 1521 int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen); 1525 1522 int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); ··· 1762 1757 struct list_head secid_to_secctx; 1763 1758 struct list_head secctx_to_secid; 1764 1759 struct list_head release_secctx; 1760 + struct list_head inode_invalidate_secctx; 1765 1761 struct list_head inode_notifysecctx; 1766 1762 struct list_head inode_setsecctx; 1767 1763 struct list_head inode_getsecctx;
+5
include/linux/security.h
··· 353 353 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); 354 354 void security_release_secctx(char *secdata, u32 seclen); 355 355 356 + void security_inode_invalidate_secctx(struct inode *inode); 356 357 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); 357 358 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); 358 359 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); ··· 1091 1090 } 1092 1091 1093 1092 static inline void security_release_secctx(char *secdata, u32 seclen) 1093 + { 1094 + } 1095 + 1096 + static inline void security_inode_invalidate_secctx(struct inode *inode) 1094 1097 { 1095 1098 } 1096 1099
+8
security/security.c
··· 1161 1161 } 1162 1162 EXPORT_SYMBOL(security_release_secctx); 1163 1163 1164 + void security_inode_invalidate_secctx(struct inode *inode) 1165 + { 1166 + call_void_hook(inode_invalidate_secctx, inode); 1167 + } 1168 + EXPORT_SYMBOL(security_inode_invalidate_secctx); 1169 + 1164 1170 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) 1165 1171 { 1166 1172 return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen); ··· 1769 1763 LIST_HEAD_INIT(security_hook_heads.secctx_to_secid), 1770 1764 .release_secctx = 1771 1765 LIST_HEAD_INIT(security_hook_heads.release_secctx), 1766 + .inode_invalidate_secctx = 1767 + LIST_HEAD_INIT(security_hook_heads.inode_invalidate_secctx), 1772 1768 .inode_notifysecctx = 1773 1769 LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx), 1774 1770 .inode_setsecctx =
+20 -10
security/selinux/hooks.c
··· 820 820 goto out; 821 821 822 822 root_isec->sid = rootcontext_sid; 823 - root_isec->initialized = 1; 823 + root_isec->initialized = LABEL_INITIALIZED; 824 824 } 825 825 826 826 if (defcontext_sid) { ··· 1308 1308 unsigned len = 0; 1309 1309 int rc = 0; 1310 1310 1311 - if (isec->initialized) 1311 + if (isec->initialized == LABEL_INITIALIZED) 1312 1312 goto out; 1313 1313 1314 1314 mutex_lock(&isec->lock); 1315 - if (isec->initialized) 1315 + if (isec->initialized == LABEL_INITIALIZED) 1316 1316 goto out_unlock; 1317 1317 1318 1318 sbsec = inode->i_sb->s_security; ··· 1484 1484 break; 1485 1485 } 1486 1486 1487 - isec->initialized = 1; 1487 + isec->initialized = LABEL_INITIALIZED; 1488 1488 1489 1489 out_unlock: 1490 1490 mutex_unlock(&isec->lock); ··· 2790 2790 struct inode_security_struct *isec = inode->i_security; 2791 2791 isec->sclass = inode_mode_to_security_class(inode->i_mode); 2792 2792 isec->sid = newsid; 2793 - isec->initialized = 1; 2793 + isec->initialized = LABEL_INITIALIZED; 2794 2794 } 2795 2795 2796 2796 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT)) ··· 3089 3089 3090 3090 isec->sclass = inode_mode_to_security_class(inode->i_mode); 3091 3091 isec->sid = newsid; 3092 - isec->initialized = 1; 3092 + isec->initialized = LABEL_INITIALIZED; 3093 3093 3094 3094 return; 3095 3095 } ··· 3183 3183 3184 3184 isec->sclass = inode_mode_to_security_class(inode->i_mode); 3185 3185 isec->sid = newsid; 3186 - isec->initialized = 1; 3186 + isec->initialized = LABEL_INITIALIZED; 3187 3187 return 0; 3188 3188 } 3189 3189 ··· 3761 3761 u32 sid = task_sid(p); 3762 3762 3763 3763 isec->sid = sid; 3764 - isec->initialized = 1; 3764 + isec->initialized = LABEL_INITIALIZED; 3765 3765 } 3766 3766 3767 3767 /* Returns error only if unable to parse addresses */ ··· 4092 4092 return err; 4093 4093 } 4094 4094 4095 - isec->initialized = 1; 4095 + isec->initialized = LABEL_INITIALIZED; 4096 4096 4097 4097 if (sock->sk) { 4098 4098 sksec = sock->sk->sk_security; ··· 4283 4283 isec = inode_security(SOCK_INODE(sock)); 4284 4284 newisec->sclass = isec->sclass; 4285 4285 newisec->sid = isec->sid; 4286 - newisec->initialized = 1; 4286 + newisec->initialized = LABEL_INITIALIZED; 4287 4287 4288 4288 return 0; 4289 4289 } ··· 5775 5775 kfree(secdata); 5776 5776 } 5777 5777 5778 + static void selinux_inode_invalidate_secctx(struct inode *inode) 5779 + { 5780 + struct inode_security_struct *isec = inode->i_security; 5781 + 5782 + mutex_lock(&isec->lock); 5783 + isec->initialized = LABEL_INVALID; 5784 + mutex_unlock(&isec->lock); 5785 + } 5786 + 5778 5787 /* 5779 5788 * called with inode->i_mutex locked 5780 5789 */ ··· 6015 6006 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx), 6016 6007 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid), 6017 6008 LSM_HOOK_INIT(release_secctx, selinux_release_secctx), 6009 + LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx), 6018 6010 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx), 6019 6011 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx), 6020 6012 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
+6
security/selinux/include/objsec.h
··· 37 37 u32 sockcreate_sid; /* fscreate SID */ 38 38 }; 39 39 40 + enum label_initialized { 41 + LABEL_MISSING, /* not initialized */ 42 + LABEL_INITIALIZED, /* inizialized */ 43 + LABEL_INVALID /* invalid */ 44 + }; 45 + 40 46 struct inode_security_struct { 41 47 struct inode *inode; /* back pointer to inode object */ 42 48 union {