Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -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 {
	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 {
	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;
+5 −0
Original line number Original line Diff line number Diff line
@@ -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)
{
{
}
}


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;
+8 −0
Original line number Original line Diff line number Diff line
@@ -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 = {
		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 =
+20 −10
Original line number Original line Diff line number Diff line
@@ -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
	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
		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,
		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,


	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,


	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,
	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,
			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)
	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)
	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[] = {
	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),
+6 −0
Original line number Original line Diff line number Diff line
@@ -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 {