selinux/stable-6.5 PR 20230626
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmSZucUUHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXMoew/+IpRuIKwouAvTINC2IEuacNlCghSs berPaYSLF89WTgbJN6hPm9NtaPU+epm5hikYp9/Ebm1Hi/91zgZZfUAN64c4e9Mx 0GgO4VwuEbx6pOK0CF9EEQTlOWnOOiP24pQlYtQGUcYOTY3OaxFkLjYx9BMw05Rd Km93eVRgJolap62ChCxdULPQQIEW0DDNGAI9TPRrPbtYRT0oSmfsMGL8Ndkui8K8 LlUVpOO5MM5/gCJjP+5PSVoyui6++ao2AwjsFk7I3hJqm3NN5fWFzWH9axLqZEqd ZfGdiah48ga+eNqi6pi79pBetlvpfHshELVwKxN9ck2UjzWQe8dqfy1p/0ikHO29 OuD+urnGTPF668GszGZgC59LoaKrHFUBjfxj3g56/BOk2aqxXKY7qeZClJ/AUEZv +VEa/foB0OCVxCBOcTvXB7Zgiz5isoR3hAQu2MmWzny9tCgHFYXJ1u0UhQaFjx57 ScPxlnjvzD5pA4ts+P2ggRojQ3Xo35dUoC353kuaaCrSg9v8yfz0ex3KeS/m9uJG MbeOtl44Xmqzzy0EB7ycNeF96kdbvKSc5XLBZyuT5CmAMUXlL3s6OOa26aevVifj LwNHAc1D7oe773Ty2WpW2s82Nh4hUyYVdIKg+9RDm74mS2ftZFeeGgFVumNQ80ZH DGhjW2iZY+0a0EU= =xzMY -----END PGP SIGNATURE----- Merge tag 'selinux-pr-20230626' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux Pull selinux updates from Paul Moore: - Thanks to help from the MPTCP folks, it looks like we have finally sorted out a proper solution to the MPTCP socket labeling issue, see the new security_mptcp_add_subflow() LSM hook. - Fix the labeled NFS handling such that a labeled NFS share mounted prior to the initial SELinux policy load is properly labeled once a policy is loaded; more information in the commit description. - Two patches to security/selinux/Makefile, the first took the cleanups in v6.4 a bit further and the second removed the grouped targets support as that functionality doesn't appear to be properly supported prior to make v4.3. - Deprecate the "fs" object context type in SELinux policies. The fs object context type was an old vestige that was introduced back in v2.6.12-rc2 but never really used. - A number of small changes that remove dead code, clean up some awkward bits, and generally improve the quality of the code. See the individual commit descriptions for more information. * tag 'selinux-pr-20230626' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: avoid bool as identifier name selinux: fix Makefile for versions of make < v4.3 selinux: make labeled NFS work when mounted before policy load selinux: cleanup exit_sel_fs() declaration selinux: deprecated fs ocon selinux: make header files self-including selinux: keep context struct members in sync selinux: Implement mptcp_add_subflow hook security, lsm: Introduce security_mptcp_add_subflow() selinux: small cleanups in selinux_audit_rule_init() selinux: declare read-only data arrays const selinux: retain const qualifier on string literal in avtab_hash_eval() selinux: drop return at end of void function avc_insert() selinux: avc: drop unused function avc_disable() selinux: adjust typos in comments selinux: do not leave dangling pointer behind selinux: more Makefile tweaks
This commit is contained in:
commit
729b39ec1b
@ -343,6 +343,7 @@ LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc,
|
|||||||
struct sock *sk, struct sock *newsk)
|
struct sock *sk, struct sock *newsk)
|
||||||
LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc,
|
LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
|
LSM_HOOK(int, 0, mptcp_add_subflow, struct sock *sk, struct sock *ssk)
|
||||||
#endif /* CONFIG_SECURITY_NETWORK */
|
#endif /* CONFIG_SECURITY_NETWORK */
|
||||||
|
|
||||||
#ifdef CONFIG_SECURITY_INFINIBAND
|
#ifdef CONFIG_SECURITY_INFINIBAND
|
||||||
|
@ -1465,6 +1465,7 @@ void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
|
|||||||
struct sock *newsk);
|
struct sock *newsk);
|
||||||
int security_sctp_assoc_established(struct sctp_association *asoc,
|
int security_sctp_assoc_established(struct sctp_association *asoc,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
|
int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk);
|
||||||
|
|
||||||
#else /* CONFIG_SECURITY_NETWORK */
|
#else /* CONFIG_SECURITY_NETWORK */
|
||||||
static inline int security_unix_stream_connect(struct sock *sock,
|
static inline int security_unix_stream_connect(struct sock *sock,
|
||||||
@ -1692,6 +1693,11 @@ static inline int security_sctp_assoc_established(struct sctp_association *asoc,
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_SECURITY_NETWORK */
|
#endif /* CONFIG_SECURITY_NETWORK */
|
||||||
|
|
||||||
#ifdef CONFIG_SECURITY_INFINIBAND
|
#ifdef CONFIG_SECURITY_INFINIBAND
|
||||||
|
@ -1668,6 +1668,10 @@ int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
|
|||||||
|
|
||||||
lock_sock_nested(sf->sk, SINGLE_DEPTH_NESTING);
|
lock_sock_nested(sf->sk, SINGLE_DEPTH_NESTING);
|
||||||
|
|
||||||
|
err = security_mptcp_add_subflow(sk, sf->sk);
|
||||||
|
if (err)
|
||||||
|
goto release_ssk;
|
||||||
|
|
||||||
/* the newly created socket has to be in the same cgroup as its parent */
|
/* the newly created socket has to be in the same cgroup as its parent */
|
||||||
mptcp_attach_cgroup(sk, sf->sk);
|
mptcp_attach_cgroup(sk, sf->sk);
|
||||||
|
|
||||||
@ -1680,6 +1684,8 @@ int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
|
|||||||
get_net_track(net, &sf->sk->ns_tracker, GFP_KERNEL);
|
get_net_track(net, &sf->sk->ns_tracker, GFP_KERNEL);
|
||||||
sock_inuse_add(net, 1);
|
sock_inuse_add(net, 1);
|
||||||
err = tcp_set_ulp(sf->sk, "mptcp");
|
err = tcp_set_ulp(sf->sk, "mptcp");
|
||||||
|
|
||||||
|
release_ssk:
|
||||||
release_sock(sf->sk);
|
release_sock(sf->sk);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -4667,6 +4667,23 @@ int security_sctp_assoc_established(struct sctp_association *asoc,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(security_sctp_assoc_established);
|
EXPORT_SYMBOL(security_sctp_assoc_established);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* security_mptcp_add_subflow() - Inherit the LSM label from the MPTCP socket
|
||||||
|
* @sk: the owning MPTCP socket
|
||||||
|
* @ssk: the new subflow
|
||||||
|
*
|
||||||
|
* Update the labeling for the given MPTCP subflow, to match the one of the
|
||||||
|
* owning MPTCP socket. This hook has to be called after the socket creation and
|
||||||
|
* initialization via the security_socket_create() and
|
||||||
|
* security_socket_post_create() LSM hooks.
|
||||||
|
*
|
||||||
|
* Return: Returns 0 on success or a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
|
||||||
|
{
|
||||||
|
return call_int_hook(mptcp_add_subflow, 0, sk, ssk);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_SECURITY_NETWORK */
|
#endif /* CONFIG_SECURITY_NETWORK */
|
||||||
|
|
||||||
#ifdef CONFIG_SECURITY_INFINIBAND
|
#ifdef CONFIG_SECURITY_INFINIBAND
|
||||||
|
@ -3,32 +3,38 @@
|
|||||||
# Makefile for building the SELinux module as part of the kernel tree.
|
# Makefile for building the SELinux module as part of the kernel tree.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# NOTE: There are a number of improvements that can be made to this Makefile
|
||||||
|
# once the kernel requires make v4.3 or greater; the most important feature
|
||||||
|
# lacking in older versions of make is support for grouped targets. These
|
||||||
|
# improvements are noted inline in the Makefile below ...
|
||||||
|
|
||||||
obj-$(CONFIG_SECURITY_SELINUX) := selinux.o
|
obj-$(CONFIG_SECURITY_SELINUX) := selinux.o
|
||||||
|
|
||||||
|
ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
|
||||||
|
|
||||||
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
|
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
|
||||||
netnode.o netport.o status.o \
|
netnode.o netport.o status.o \
|
||||||
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
|
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
|
||||||
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o
|
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/context.o
|
||||||
|
|
||||||
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
|
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
|
||||||
|
|
||||||
selinux-$(CONFIG_NETLABEL) += netlabel.o
|
selinux-$(CONFIG_NETLABEL) += netlabel.o
|
||||||
|
|
||||||
selinux-$(CONFIG_SECURITY_INFINIBAND) += ibpkey.o
|
selinux-$(CONFIG_SECURITY_INFINIBAND) += ibpkey.o
|
||||||
|
|
||||||
selinux-$(CONFIG_IMA) += ima.o
|
selinux-$(CONFIG_IMA) += ima.o
|
||||||
|
|
||||||
ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
|
genhdrs := flask.h av_permissions.h
|
||||||
|
|
||||||
|
# see the note above, replace the dependency rule with the one below:
|
||||||
|
# $(addprefix $(obj)/,$(selinux-y)): $(addprefix $(obj)/,$(genhdrs))
|
||||||
$(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
|
$(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
|
||||||
|
|
||||||
quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h
|
quiet_cmd_genhdrs = GEN $(addprefix $(obj)/,$(genhdrs))
|
||||||
cmd_flask = $< $(obj)/flask.h $(obj)/av_permissions.h
|
cmd_genhdrs = $< $(addprefix $(obj)/,$(genhdrs))
|
||||||
|
|
||||||
targets += flask.h av_permissions.h
|
# see the note above, replace the $targets and 'flask.h' rule with the lines
|
||||||
# once make >= 4.3 is required, we can use grouped targets in the rule below,
|
# below:
|
||||||
# which basically involves adding both headers and a '&' before the colon, see
|
# targets += $(genhdrs)
|
||||||
# the example below:
|
# $(addprefix $(obj)/,$(genhdrs)) &: scripts/selinux/...
|
||||||
# $(obj)/flask.h $(obj)/av_permissions.h &: scripts/selinux/...
|
targets += flask.h
|
||||||
$(obj)/flask.h: scripts/selinux/genheaders/genheaders FORCE
|
$(obj)/flask.h: scripts/selinux/genheaders/genheaders FORCE
|
||||||
$(call if_changed,flask)
|
$(call if_changed,genhdrs)
|
||||||
|
@ -642,7 +642,6 @@ static void avc_insert(u32 ssid, u32 tsid, u16 tclass,
|
|||||||
hlist_add_head_rcu(&node->list, head);
|
hlist_add_head_rcu(&node->list, head);
|
||||||
found:
|
found:
|
||||||
spin_unlock_irqrestore(lock, flag);
|
spin_unlock_irqrestore(lock, flag);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1203,22 +1202,3 @@ u32 avc_policy_seqno(void)
|
|||||||
{
|
{
|
||||||
return selinux_avc.avc_cache.latest_notif;
|
return selinux_avc.avc_cache.latest_notif;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avc_disable(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If you are looking at this because you have realized that we are
|
|
||||||
* not destroying the avc_node_cachep it might be easy to fix, but
|
|
||||||
* I don't know the memory barrier semantics well enough to know. It's
|
|
||||||
* possible that some other task dereferenced security_ops when
|
|
||||||
* it still pointed to selinux operations. If that is the case it's
|
|
||||||
* possible that it is about to use the avc and is about to need the
|
|
||||||
* avc_node_cachep. I know I could wrap the security.c security_ops call
|
|
||||||
* in an rcu_lock, but seriously, it's not worth it. Instead I just flush
|
|
||||||
* the cache and get that memory back.
|
|
||||||
*/
|
|
||||||
if (avc_node_cachep) {
|
|
||||||
avc_flush();
|
|
||||||
/* kmem_cache_destroy(avc_node_cachep); */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -357,7 +357,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
|
#define A(s, has_arg) {#s, sizeof(#s) - 1, Opt_##s, has_arg}
|
||||||
static struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
int len;
|
int len;
|
||||||
int opt;
|
int opt;
|
||||||
@ -605,6 +605,13 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
|||||||
u32 defcontext_sid = 0;
|
u32 defcontext_sid = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specifying internal flags without providing a place to
|
||||||
|
* place the results is not allowed
|
||||||
|
*/
|
||||||
|
if (kern_flags && !set_kern_flags)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&sbsec->lock);
|
mutex_lock(&sbsec->lock);
|
||||||
|
|
||||||
if (!selinux_initialized()) {
|
if (!selinux_initialized()) {
|
||||||
@ -612,6 +619,10 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
|||||||
/* Defer initialization until selinux_complete_init,
|
/* Defer initialization until selinux_complete_init,
|
||||||
after the initial policy is loaded and the security
|
after the initial policy is loaded and the security
|
||||||
server is ready to handle calls. */
|
server is ready to handle calls. */
|
||||||
|
if (kern_flags & SECURITY_LSM_NATIVE_LABELS) {
|
||||||
|
sbsec->flags |= SE_SBNATIVE;
|
||||||
|
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
@ -619,12 +630,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
|||||||
"before the security server is initialized\n");
|
"before the security server is initialized\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (kern_flags && !set_kern_flags) {
|
|
||||||
/* Specifying internal flags without providing a place to
|
|
||||||
* place the results is not allowed */
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Binary mount data FS will come through this function twice. Once
|
* Binary mount data FS will come through this function twice. Once
|
||||||
@ -757,7 +762,17 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
|||||||
* sets the label used on all file below the mountpoint, and will set
|
* sets the label used on all file below the mountpoint, and will set
|
||||||
* the superblock context if not already set.
|
* the superblock context if not already set.
|
||||||
*/
|
*/
|
||||||
if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
|
if (sbsec->flags & SE_SBNATIVE) {
|
||||||
|
/*
|
||||||
|
* This means we are initializing a superblock that has been
|
||||||
|
* mounted before the SELinux was initialized and the
|
||||||
|
* filesystem requested native labeling. We had already
|
||||||
|
* returned SECURITY_LSM_NATIVE_LABELS in *set_kern_flags
|
||||||
|
* in the original mount attempt, so now we just need to set
|
||||||
|
* the SECURITY_FS_USE_NATIVE behavior.
|
||||||
|
*/
|
||||||
|
sbsec->behavior = SECURITY_FS_USE_NATIVE;
|
||||||
|
} else if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
|
||||||
sbsec->behavior = SECURITY_FS_USE_NATIVE;
|
sbsec->behavior = SECURITY_FS_USE_NATIVE;
|
||||||
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
||||||
}
|
}
|
||||||
@ -868,13 +883,6 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|||||||
int set_context = (oldsbsec->flags & CONTEXT_MNT);
|
int set_context = (oldsbsec->flags & CONTEXT_MNT);
|
||||||
int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
|
int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
|
||||||
|
|
||||||
/*
|
|
||||||
* if the parent was able to be mounted it clearly had no special lsm
|
|
||||||
* mount options. thus we can safely deal with this superblock later
|
|
||||||
*/
|
|
||||||
if (!selinux_initialized())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Specifying internal flags without providing a place to
|
* Specifying internal flags without providing a place to
|
||||||
* place the results is not allowed.
|
* place the results is not allowed.
|
||||||
@ -882,18 +890,31 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|||||||
if (kern_flags && !set_kern_flags)
|
if (kern_flags && !set_kern_flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&newsbsec->lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if the parent was able to be mounted it clearly had no special lsm
|
||||||
|
* mount options. thus we can safely deal with this superblock later
|
||||||
|
*/
|
||||||
|
if (!selinux_initialized()) {
|
||||||
|
if (kern_flags & SECURITY_LSM_NATIVE_LABELS) {
|
||||||
|
newsbsec->flags |= SE_SBNATIVE;
|
||||||
|
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* how can we clone if the old one wasn't set up?? */
|
/* how can we clone if the old one wasn't set up?? */
|
||||||
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
|
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
|
||||||
|
|
||||||
/* if fs is reusing a sb, make sure that the contexts match */
|
/* if fs is reusing a sb, make sure that the contexts match */
|
||||||
if (newsbsec->flags & SE_SBINITIALIZED) {
|
if (newsbsec->flags & SE_SBINITIALIZED) {
|
||||||
|
mutex_unlock(&newsbsec->lock);
|
||||||
if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
|
if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
|
||||||
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
||||||
return selinux_cmp_sb_context(oldsb, newsb);
|
return selinux_cmp_sb_context(oldsb, newsb);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&newsbsec->lock);
|
|
||||||
|
|
||||||
newsbsec->flags = oldsbsec->flags;
|
newsbsec->flags = oldsbsec->flags;
|
||||||
|
|
||||||
newsbsec->sid = oldsbsec->sid;
|
newsbsec->sid = oldsbsec->sid;
|
||||||
@ -937,7 +958,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: the caller is resposible for freeing the memory even if on error.
|
* NOTE: the caller is responsible for freeing the memory even if on error.
|
||||||
*/
|
*/
|
||||||
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
|
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
|
||||||
{
|
{
|
||||||
@ -1394,8 +1415,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
|||||||
spin_unlock(&isec->lock);
|
spin_unlock(&isec->lock);
|
||||||
|
|
||||||
switch (sbsec->behavior) {
|
switch (sbsec->behavior) {
|
||||||
|
/*
|
||||||
|
* In case of SECURITY_FS_USE_NATIVE we need to re-fetch the labels
|
||||||
|
* via xattr when called from delayed_superblock_init().
|
||||||
|
*/
|
||||||
case SECURITY_FS_USE_NATIVE:
|
case SECURITY_FS_USE_NATIVE:
|
||||||
break;
|
|
||||||
case SECURITY_FS_USE_XATTR:
|
case SECURITY_FS_USE_XATTR:
|
||||||
if (!(inode->i_opflags & IOP_XATTR)) {
|
if (!(inode->i_opflags & IOP_XATTR)) {
|
||||||
sid = sbsec->def_sid;
|
sid = sbsec->def_sid;
|
||||||
@ -5379,6 +5403,21 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk
|
|||||||
selinux_netlbl_sctp_sk_clone(sk, newsk);
|
selinux_netlbl_sctp_sk_clone(sk, newsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
|
||||||
|
{
|
||||||
|
struct sk_security_struct *ssksec = ssk->sk_security;
|
||||||
|
struct sk_security_struct *sksec = sk->sk_security;
|
||||||
|
|
||||||
|
ssksec->sclass = sksec->sclass;
|
||||||
|
ssksec->sid = sksec->sid;
|
||||||
|
|
||||||
|
/* replace the existing subflow label deleting the existing one
|
||||||
|
* and re-recreating a new label using the updated context
|
||||||
|
*/
|
||||||
|
selinux_netlbl_sk_security_free(ssksec);
|
||||||
|
return selinux_netlbl_socket_post_create(ssk, ssk->sk_family);
|
||||||
|
}
|
||||||
|
|
||||||
static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
|
static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
|
||||||
struct request_sock *req)
|
struct request_sock *req)
|
||||||
{
|
{
|
||||||
@ -7074,6 +7113,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
|
|||||||
LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
|
LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
|
||||||
LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
|
LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
|
||||||
LSM_HOOK_INIT(sctp_assoc_established, selinux_sctp_assoc_established),
|
LSM_HOOK_INIT(sctp_assoc_established, selinux_sctp_assoc_established),
|
||||||
|
LSM_HOOK_INIT(mptcp_add_subflow, selinux_mptcp_add_subflow),
|
||||||
LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
|
LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
|
||||||
LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
|
LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
|
||||||
LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
|
LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
|
* Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
|
||||||
*
|
*
|
||||||
* Measure critical data structures maintainted by SELinux
|
* Measure critical data structures maintained by SELinux
|
||||||
* using IMA subsystem.
|
* using IMA subsystem.
|
||||||
*/
|
*/
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
|
@ -41,7 +41,7 @@ void selinux_audit_rule_free(void *rule);
|
|||||||
* selinux_audit_rule_match - determine if a context ID matches a rule.
|
* selinux_audit_rule_match - determine if a context ID matches a rule.
|
||||||
* @sid: the context ID to check
|
* @sid: the context ID to check
|
||||||
* @field: the field this rule refers to
|
* @field: the field this rule refers to
|
||||||
* @op: the operater the rule uses
|
* @op: the operator the rule uses
|
||||||
* @rule: pointer to the audit rule to check against
|
* @rule: pointer to the audit rule to check against
|
||||||
*
|
*
|
||||||
* Returns 1 if the context id matches the rule, 0 if it does not, and
|
* Returns 1 if the context id matches the rule, 0 if it does not, and
|
||||||
|
@ -168,9 +168,6 @@ int avc_get_hash_stats(char *page);
|
|||||||
unsigned int avc_get_cache_threshold(void);
|
unsigned int avc_get_cache_threshold(void);
|
||||||
void avc_set_cache_threshold(unsigned int cache_threshold);
|
void avc_set_cache_threshold(unsigned int cache_threshold);
|
||||||
|
|
||||||
/* Attempt to free avc node cache */
|
|
||||||
void avc_disable(void);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
|
#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
|
||||||
DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats);
|
DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats);
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#define _SELINUX_IB_PKEY_H
|
#define _SELINUX_IB_PKEY_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include "flask.h"
|
||||||
|
|
||||||
#ifdef CONFIG_SECURITY_INFINIBAND
|
#ifdef CONFIG_SECURITY_INFINIBAND
|
||||||
void sel_ib_pkey_flush(void);
|
void sel_ib_pkey_flush(void);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
|
* Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
|
||||||
*
|
*
|
||||||
* Measure critical data structures maintainted by SELinux
|
* Measure critical data structures maintained by SELinux
|
||||||
* using IMA subsystem.
|
* using IMA subsystem.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
|
||||||
static const char *const initial_sid_to_string[] = {
|
static const char *const initial_sid_to_string[] = {
|
||||||
NULL,
|
NULL,
|
||||||
"kernel",
|
"kernel",
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#define SE_SBPROC 0x0200
|
#define SE_SBPROC 0x0200
|
||||||
#define SE_SBGENFS 0x0400
|
#define SE_SBGENFS 0x0400
|
||||||
#define SE_SBGENFS_XATTR 0x0800
|
#define SE_SBGENFS_XATTR 0x0800
|
||||||
|
#define SE_SBNATIVE 0x1000
|
||||||
|
|
||||||
#define CONTEXT_STR "context"
|
#define CONTEXT_STR "context"
|
||||||
#define FSCONTEXT_STR "fscontext"
|
#define FSCONTEXT_STR "fscontext"
|
||||||
@ -384,7 +385,6 @@ struct selinux_kernel_status {
|
|||||||
extern void selinux_status_update_setenforce(int enforcing);
|
extern void selinux_status_update_setenforce(int enforcing);
|
||||||
extern void selinux_status_update_policyload(int seqno);
|
extern void selinux_status_update_policyload(int seqno);
|
||||||
extern void selinux_complete_init(void);
|
extern void selinux_complete_init(void);
|
||||||
extern void exit_sel_fs(void);
|
|
||||||
extern struct path selinux_null;
|
extern struct path selinux_null;
|
||||||
extern void selnl_notify_setenforce(int val);
|
extern void selnl_notify_setenforce(int val);
|
||||||
extern void selnl_notify_policyload(u32 seqno);
|
extern void selnl_notify_policyload(u32 seqno);
|
||||||
|
@ -154,8 +154,12 @@ void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
|
|||||||
*/
|
*/
|
||||||
void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
|
void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
|
||||||
{
|
{
|
||||||
if (sksec->nlbl_secattr != NULL)
|
if (!sksec->nlbl_secattr)
|
||||||
|
return;
|
||||||
|
|
||||||
netlbl_secattr_free(sksec->nlbl_secattr);
|
netlbl_secattr_free(sksec->nlbl_secattr);
|
||||||
|
sksec->nlbl_secattr = NULL;
|
||||||
|
sksec->nlbl_state = NLBL_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -951,7 +951,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
|
|||||||
* either whitespace or multibyte characters, they shall be
|
* either whitespace or multibyte characters, they shall be
|
||||||
* encoded based on the percentage-encoding rule.
|
* encoded based on the percentage-encoding rule.
|
||||||
* If not encoded, the sscanf logic picks up only left-half
|
* If not encoded, the sscanf logic picks up only left-half
|
||||||
* of the supplied name; splitted by a whitespace unexpectedly.
|
* of the supplied name; split by a whitespace unexpectedly.
|
||||||
*/
|
*/
|
||||||
char *r, *w;
|
char *r, *w;
|
||||||
int c1, c2;
|
int c1, c2;
|
||||||
@ -1649,7 +1649,7 @@ static int sel_make_ss_files(struct dentry *dir)
|
|||||||
struct super_block *sb = dir->d_sb;
|
struct super_block *sb = dir->d_sb;
|
||||||
struct selinux_fs_info *fsi = sb->s_fs_info;
|
struct selinux_fs_info *fsi = sb->s_fs_info;
|
||||||
int i;
|
int i;
|
||||||
static struct tree_descr files[] = {
|
static const struct tree_descr files[] = {
|
||||||
{ "sidtab_hash_stats", &sel_sidtab_hash_stats_ops, S_IRUGO },
|
{ "sidtab_hash_stats", &sel_sidtab_hash_stats_ops, S_IRUGO },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ int avtab_alloc_dup(struct avtab *new, const struct avtab *orig)
|
|||||||
return avtab_alloc_common(new, orig->nslot);
|
return avtab_alloc_common(new, orig->nslot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void avtab_hash_eval(struct avtab *h, char *tag)
|
void avtab_hash_eval(struct avtab *h, const char *tag)
|
||||||
{
|
{
|
||||||
int i, chain_len, slots_used, max_chain_len;
|
int i, chain_len, slots_used, max_chain_len;
|
||||||
unsigned long long chain2_len_sum;
|
unsigned long long chain2_len_sum;
|
||||||
|
@ -92,7 +92,7 @@ int avtab_alloc(struct avtab *, u32);
|
|||||||
int avtab_alloc_dup(struct avtab *new, const struct avtab *orig);
|
int avtab_alloc_dup(struct avtab *new, const struct avtab *orig);
|
||||||
struct avtab_datum *avtab_search(struct avtab *h, const struct avtab_key *k);
|
struct avtab_datum *avtab_search(struct avtab *h, const struct avtab_key *k);
|
||||||
void avtab_destroy(struct avtab *h);
|
void avtab_destroy(struct avtab *h);
|
||||||
void avtab_hash_eval(struct avtab *h, char *tag);
|
void avtab_hash_eval(struct avtab *h, const char *tag);
|
||||||
|
|
||||||
struct policydb;
|
struct policydb;
|
||||||
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
||||||
|
@ -38,7 +38,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
|
|||||||
if (sp == (COND_EXPR_MAXDEPTH - 1))
|
if (sp == (COND_EXPR_MAXDEPTH - 1))
|
||||||
return -1;
|
return -1;
|
||||||
sp++;
|
sp++;
|
||||||
s[sp] = p->bool_val_to_struct[node->bool - 1]->state;
|
s[sp] = p->bool_val_to_struct[node->boolean - 1]->state;
|
||||||
break;
|
break;
|
||||||
case COND_NOT:
|
case COND_NOT:
|
||||||
if (sp < 0)
|
if (sp < 0)
|
||||||
@ -366,7 +366,7 @@ static int expr_node_isvalid(struct policydb *p, struct cond_expr_node *expr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr->bool > p->p_bools.nprim) {
|
if (expr->boolean > p->p_bools.nprim) {
|
||||||
pr_err("SELinux: conditional expressions uses unknown bool.\n");
|
pr_err("SELinux: conditional expressions uses unknown bool.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -401,7 +401,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
expr->expr_type = le32_to_cpu(buf[0]);
|
expr->expr_type = le32_to_cpu(buf[0]);
|
||||||
expr->bool = le32_to_cpu(buf[1]);
|
expr->boolean = le32_to_cpu(buf[1]);
|
||||||
|
|
||||||
if (!expr_node_isvalid(p, expr))
|
if (!expr_node_isvalid(p, expr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -518,7 +518,7 @@ static int cond_write_node(struct policydb *p, struct cond_node *node,
|
|||||||
|
|
||||||
for (i = 0; i < node->expr.len; i++) {
|
for (i = 0; i < node->expr.len; i++) {
|
||||||
buf[0] = cpu_to_le32(node->expr.nodes[i].expr_type);
|
buf[0] = cpu_to_le32(node->expr.nodes[i].expr_type);
|
||||||
buf[1] = cpu_to_le32(node->expr.nodes[i].bool);
|
buf[1] = cpu_to_le32(node->expr.nodes[i].boolean);
|
||||||
rc = put_entry(buf, sizeof(u32), 2, fp);
|
rc = put_entry(buf, sizeof(u32), 2, fp);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -29,7 +29,7 @@ struct cond_expr_node {
|
|||||||
#define COND_NEQ 7 /* bool != bool */
|
#define COND_NEQ 7 /* bool != bool */
|
||||||
#define COND_LAST COND_NEQ
|
#define COND_LAST COND_NEQ
|
||||||
u32 expr_type;
|
u32 expr_type;
|
||||||
u32 bool;
|
u32 boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cond_expr {
|
struct cond_expr {
|
||||||
|
@ -167,6 +167,8 @@ static inline int context_cpy(struct context *dst, const struct context *src)
|
|||||||
rc = mls_context_cpy(dst, src);
|
rc = mls_context_cpy(dst, src);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
kfree(dst->str);
|
kfree(dst->str);
|
||||||
|
dst->str = NULL;
|
||||||
|
dst->len = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#include "services.h"
|
#include "services.h"
|
||||||
|
|
||||||
#ifdef DEBUG_HASHES
|
#ifdef DEBUG_HASHES
|
||||||
static const char *symtab_name[SYM_NUM] = {
|
static const char *const symtab_name[SYM_NUM] = {
|
||||||
"common prefixes",
|
"common prefixes",
|
||||||
"classes",
|
"classes",
|
||||||
"roles",
|
"roles",
|
||||||
@ -2257,6 +2257,10 @@ static int ocontext_read(struct policydb *p, const struct policydb_compat_info *
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (i == OCON_FS)
|
||||||
|
pr_warn("SELinux: void and deprecated fs ocon %s\n",
|
||||||
|
c->u.name);
|
||||||
|
|
||||||
rc = context_read_and_validate(&c->context[0], p, fp);
|
rc = context_read_and_validate(&c->context[0], p, fp);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -225,7 +225,7 @@ struct genfs {
|
|||||||
|
|
||||||
/* object context array indices */
|
/* object context array indices */
|
||||||
#define OCON_ISID 0 /* initial SIDs */
|
#define OCON_ISID 0 /* initial SIDs */
|
||||||
#define OCON_FS 1 /* unlabeled file systems */
|
#define OCON_FS 1 /* unlabeled file systems (deprecated) */
|
||||||
#define OCON_PORT 2 /* TCP and UDP port numbers */
|
#define OCON_PORT 2 /* TCP and UDP port numbers */
|
||||||
#define OCON_NETIF 3 /* network interfaces */
|
#define OCON_NETIF 3 /* network interfaces */
|
||||||
#define OCON_NODE 4 /* nodes */
|
#define OCON_NODE 4 /* nodes */
|
||||||
|
@ -583,7 +583,7 @@ static void type_attribute_bounds_av(struct policydb *policydb,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* flag which drivers have permissions
|
* flag which drivers have permissions
|
||||||
* only looking for ioctl based extended permssions
|
* only looking for ioctl based extended permissions
|
||||||
*/
|
*/
|
||||||
void services_compute_xperms_drivers(
|
void services_compute_xperms_drivers(
|
||||||
struct extended_perms *xperms,
|
struct extended_perms *xperms,
|
||||||
@ -3541,38 +3541,38 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
|
|||||||
tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL);
|
tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL);
|
||||||
if (!tmprule)
|
if (!tmprule)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
context_init(&tmprule->au_ctxt);
|
context_init(&tmprule->au_ctxt);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
policy = rcu_dereference(state->policy);
|
policy = rcu_dereference(state->policy);
|
||||||
policydb = &policy->policydb;
|
policydb = &policy->policydb;
|
||||||
|
|
||||||
tmprule->au_seqno = policy->latest_granting;
|
tmprule->au_seqno = policy->latest_granting;
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case AUDIT_SUBJ_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_OBJ_USER:
|
case AUDIT_OBJ_USER:
|
||||||
rc = -EINVAL;
|
|
||||||
userdatum = symtab_search(&policydb->p_users, rulestr);
|
userdatum = symtab_search(&policydb->p_users, rulestr);
|
||||||
if (!userdatum)
|
if (!userdatum) {
|
||||||
goto out;
|
rc = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
tmprule->au_ctxt.user = userdatum->value;
|
tmprule->au_ctxt.user = userdatum->value;
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUBJ_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_OBJ_ROLE:
|
case AUDIT_OBJ_ROLE:
|
||||||
rc = -EINVAL;
|
|
||||||
roledatum = symtab_search(&policydb->p_roles, rulestr);
|
roledatum = symtab_search(&policydb->p_roles, rulestr);
|
||||||
if (!roledatum)
|
if (!roledatum) {
|
||||||
goto out;
|
rc = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
tmprule->au_ctxt.role = roledatum->value;
|
tmprule->au_ctxt.role = roledatum->value;
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUBJ_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_OBJ_TYPE:
|
case AUDIT_OBJ_TYPE:
|
||||||
rc = -EINVAL;
|
|
||||||
typedatum = symtab_search(&policydb->p_types, rulestr);
|
typedatum = symtab_search(&policydb->p_types, rulestr);
|
||||||
if (!typedatum)
|
if (!typedatum) {
|
||||||
goto out;
|
rc = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
tmprule->au_ctxt.type = typedatum->value;
|
tmprule->au_ctxt.type = typedatum->value;
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUBJ_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
@ -3582,20 +3582,18 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
|
|||||||
rc = mls_from_string(policydb, rulestr, &tmprule->au_ctxt,
|
rc = mls_from_string(policydb, rulestr, &tmprule->au_ctxt,
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto err;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = 0;
|
|
||||||
out:
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
selinux_audit_rule_free(tmprule);
|
|
||||||
tmprule = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*rule = tmprule;
|
*rule = tmprule;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
rcu_read_unlock();
|
||||||
|
selinux_audit_rule_free(tmprule);
|
||||||
|
*rule = NULL;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user