Commit 6f3be9f5 authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Paul Moore

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: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: default avatarJames Morris <james.l.morris@oracle.com>
Acked-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: default avatarPaul Moore <pmoore@redhat.com>
parent 83da53c5
...@@ -1261,6 +1261,10 @@ ...@@ -1261,6 +1261,10 @@
* audit_rule_init. * audit_rule_init.
* @rule contains the allocated rule * @rule contains the allocated rule
* *
* @inode_invalidate_secctx:
* Notify the security module that it must revalidate the security context
* of an inode.
*
* @inode_notifysecctx: * @inode_notifysecctx:
* Notify the security module of what the security context of an inode * Notify the security module of what the security context of an inode
* should be. Initializes the incore security context managed by the * should be. Initializes the incore security context managed by the
...@@ -1516,6 +1520,7 @@ union security_list_options { ...@@ -1516,6 +1520,7 @@ union security_list_options {
int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid); int (*secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid);
void (*release_secctx)(char *secdata, u32 seclen); void (*release_secctx)(char *secdata, u32 seclen);
void (*inode_invalidate_secctx)(struct inode *inode);
int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen); int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen); int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen);
...@@ -1757,6 +1762,7 @@ struct security_hook_heads { ...@@ -1757,6 +1762,7 @@ struct security_hook_heads {
struct list_head secid_to_secctx; struct list_head secid_to_secctx;
struct list_head secctx_to_secid; struct list_head secctx_to_secid;
struct list_head release_secctx; struct list_head release_secctx;
struct list_head inode_invalidate_secctx;
struct list_head inode_notifysecctx; struct list_head inode_notifysecctx;
struct list_head inode_setsecctx; struct list_head inode_setsecctx;
struct list_head inode_getsecctx; struct list_head inode_getsecctx;
......
...@@ -353,6 +353,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); ...@@ -353,6 +353,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
void security_release_secctx(char *secdata, u32 seclen); void security_release_secctx(char *secdata, u32 seclen);
void security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
...@@ -1093,6 +1094,10 @@ static inline void security_release_secctx(char *secdata, u32 seclen) ...@@ -1093,6 +1094,10 @@ static inline void security_release_secctx(char *secdata, u32 seclen)
{ {
} }
static inline void security_inode_invalidate_secctx(struct inode *inode)
{
}
static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -1161,6 +1161,12 @@ void security_release_secctx(char *secdata, u32 seclen) ...@@ -1161,6 +1161,12 @@ void security_release_secctx(char *secdata, u32 seclen)
} }
EXPORT_SYMBOL(security_release_secctx); EXPORT_SYMBOL(security_release_secctx);
void security_inode_invalidate_secctx(struct inode *inode)
{
call_void_hook(inode_invalidate_secctx, inode);
}
EXPORT_SYMBOL(security_inode_invalidate_secctx);
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{ {
return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen); return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen);
...@@ -1763,6 +1769,8 @@ struct security_hook_heads security_hook_heads = { ...@@ -1763,6 +1769,8 @@ struct security_hook_heads security_hook_heads = {
LIST_HEAD_INIT(security_hook_heads.secctx_to_secid), LIST_HEAD_INIT(security_hook_heads.secctx_to_secid),
.release_secctx = .release_secctx =
LIST_HEAD_INIT(security_hook_heads.release_secctx), LIST_HEAD_INIT(security_hook_heads.release_secctx),
.inode_invalidate_secctx =
LIST_HEAD_INIT(security_hook_heads.inode_invalidate_secctx),
.inode_notifysecctx = .inode_notifysecctx =
LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx), LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx),
.inode_setsecctx = .inode_setsecctx =
......
...@@ -820,7 +820,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, ...@@ -820,7 +820,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
goto out; goto out;
root_isec->sid = rootcontext_sid; root_isec->sid = rootcontext_sid;
root_isec->initialized = 1; root_isec->initialized = LABEL_INITIALIZED;
} }
if (defcontext_sid) { if (defcontext_sid) {
...@@ -1308,11 +1308,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent ...@@ -1308,11 +1308,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
unsigned len = 0; unsigned len = 0;
int rc = 0; int rc = 0;
if (isec->initialized) if (isec->initialized == LABEL_INITIALIZED)
goto out; goto out;
mutex_lock(&isec->lock); mutex_lock(&isec->lock);
if (isec->initialized) if (isec->initialized == LABEL_INITIALIZED)
goto out_unlock; goto out_unlock;
sbsec = inode->i_sb->s_security; sbsec = inode->i_sb->s_security;
...@@ -1484,7 +1484,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent ...@@ -1484,7 +1484,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
break; break;
} }
isec->initialized = 1; isec->initialized = LABEL_INITIALIZED;
out_unlock: out_unlock:
mutex_unlock(&isec->lock); mutex_unlock(&isec->lock);
...@@ -2790,7 +2790,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, ...@@ -2790,7 +2790,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
struct inode_security_struct *isec = inode->i_security; struct inode_security_struct *isec = inode->i_security;
isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid; isec->sid = newsid;
isec->initialized = 1; isec->initialized = LABEL_INITIALIZED;
} }
if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT)) if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
...@@ -3089,7 +3089,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, ...@@ -3089,7 +3089,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid; isec->sid = newsid;
isec->initialized = 1; isec->initialized = LABEL_INITIALIZED;
return; return;
} }
...@@ -3183,7 +3183,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, ...@@ -3183,7 +3183,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid; isec->sid = newsid;
isec->initialized = 1; isec->initialized = LABEL_INITIALIZED;
return 0; return 0;
} }
...@@ -3761,7 +3761,7 @@ static void selinux_task_to_inode(struct task_struct *p, ...@@ -3761,7 +3761,7 @@ static void selinux_task_to_inode(struct task_struct *p,
u32 sid = task_sid(p); u32 sid = task_sid(p);
isec->sid = sid; isec->sid = sid;
isec->initialized = 1; isec->initialized = LABEL_INITIALIZED;
} }
/* Returns error only if unable to parse addresses */ /* Returns error only if unable to parse addresses */
...@@ -4092,7 +4092,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, ...@@ -4092,7 +4092,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
return err; return err;
} }
isec->initialized = 1; isec->initialized = LABEL_INITIALIZED;
if (sock->sk) { if (sock->sk) {
sksec = sock->sk->sk_security; sksec = sock->sk->sk_security;
...@@ -4283,7 +4283,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) ...@@ -4283,7 +4283,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
isec = inode_security(SOCK_INODE(sock)); isec = inode_security(SOCK_INODE(sock));
newisec->sclass = isec->sclass; newisec->sclass = isec->sclass;
newisec->sid = isec->sid; newisec->sid = isec->sid;
newisec->initialized = 1; newisec->initialized = LABEL_INITIALIZED;
return 0; return 0;
} }
...@@ -5775,6 +5775,15 @@ static void selinux_release_secctx(char *secdata, u32 seclen) ...@@ -5775,6 +5775,15 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
kfree(secdata); kfree(secdata);
} }
static void selinux_inode_invalidate_secctx(struct inode *inode)
{
struct inode_security_struct *isec = inode->i_security;
mutex_lock(&isec->lock);
isec->initialized = LABEL_INVALID;
mutex_unlock(&isec->lock);
}
/* /*
* called with inode->i_mutex locked * called with inode->i_mutex locked
*/ */
...@@ -6006,6 +6015,7 @@ static struct security_hook_list selinux_hooks[] = { ...@@ -6006,6 +6015,7 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx), LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid), LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
LSM_HOOK_INIT(release_secctx, selinux_release_secctx), LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx), LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx), LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx), LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
......
...@@ -37,6 +37,12 @@ struct task_security_struct { ...@@ -37,6 +37,12 @@ struct task_security_struct {
u32 sockcreate_sid; /* fscreate SID */ u32 sockcreate_sid; /* fscreate SID */
}; };
enum label_initialized {
LABEL_MISSING, /* not initialized */
LABEL_INITIALIZED, /* inizialized */
LABEL_INVALID /* invalid */
};
struct inode_security_struct { struct inode_security_struct {
struct inode *inode; /* back pointer to inode object */ struct inode *inode; /* back pointer to inode object */
union { union {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment