Commit c269497d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'selinux-pr-20220321' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux

Pull selinux updates from Paul Moore:
 "We've got a number of SELinux patches queued up, the highlights are:

   - Fixup the security_fs_context_parse_param() LSM hook so it executes
     all of the LSM hook implementations unless a serious error occurs.

     We also correct the SELinux hook implementation so that it returns
     zero on success.

   - In addition to a few SELinux mount option parsing fixes, we
     simplified the parsing by moving it earlier in the process.

     The logic was that it was unlikely an admin/user would use the new
     mount API and not have the policy loaded before passing the SELinux
     options.

   - Properly fixed the LSM/SELinux/SCTP hooks with the addition of the
     security_sctp_assoc_established() hook.

     This work was done in conjunction with the netdev folks and should
     complete the move of the SCTP labeling from the endpoints to the
     associations.

   - Fixed a variety of sparse warnings caused by changes in the "__rcu"
     markings of some core kernel structures.

   - Ensure we access the superblock's LSM security blob using the
     stacking-safe accessors.

   - Added the ability for the kernel to always allow FIOCLEX and
     FIONCLEX if the "ioctl_skip_cloexec" policy capability is
     specified.

   - Various constifications improvements, type casting improvements,
     additional return value checks, and dead code/parameter removal.

   - Documentation fixes"

* tag 'selinux-pr-20220321' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: (23 commits)
  selinux: shorten the policy capability enum names
  docs: fix 'make htmldocs' warning in SCTP.rst
  selinux: allow FIOCLEX and FIONCLEX with policy capability
  selinux: use correct type for context length
  selinux: drop return statement at end of void functions
  security: implement sctp_assoc_established hook in selinux
  security: add sctp_assoc_established hook
  selinux: parse contexts for mount options early
  selinux: various sparse fixes
  selinux: try to use preparsed sid before calling parse_sid()
  selinux: Fix selinux_sb_mnt_opts_compat()
  LSM: general protection fault in legacy_parse_param
  selinux: fix a type cast problem in cred_init_security()
  selinux: drop unused macro
  selinux: simplify cred_init_security
  selinux: do not discard const qualifier in cast
  selinux: drop unused parameter of avtab_insert_node
  selinux: drop cast to same type
  selinux: enclose macro arguments in parenthesis
  selinux: declare name parameter of hash_eval const
  ...
parents 7f313ff0 cdbec3ed
......@@ -15,10 +15,7 @@ For security module support, three SCTP specific hooks have been implemented::
security_sctp_assoc_request()
security_sctp_bind_connect()
security_sctp_sk_clone()
Also the following security hook has been utilised::
security_inet_conn_established()
security_sctp_assoc_established()
The usage of these hooks are described below with the SELinux implementation
described in the `SCTP SELinux Support`_ chapter.
......@@ -122,11 +119,12 @@ calls **sctp_peeloff**\(3).
@newsk - pointer to new sock structure.
security_inet_conn_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when a COOKIE ACK is received::
security_sctp_assoc_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when a COOKIE ACK is received, and the peer secid will be
saved into ``@asoc->peer_secid`` for client::
@sk - pointer to sock structure.
@asoc - pointer to sctp association structure.
@skb - pointer to skbuff of the COOKIE ACK packet.
......@@ -134,7 +132,7 @@ Security Hooks used for Association Establishment
-------------------------------------------------
The following diagram shows the use of ``security_sctp_bind_connect()``,
``security_sctp_assoc_request()``, ``security_inet_conn_established()`` when
``security_sctp_assoc_request()``, ``security_sctp_assoc_established()`` when
establishing an association.
::
......@@ -172,7 +170,7 @@ establishing an association.
<------------------------------------------- COOKIE ACK
| |
sctp_sf_do_5_1E_ca |
Call security_inet_conn_established() |
Call security_sctp_assoc_established() |
to set the peer label. |
| |
| If SCTP_SOCKET_TCP or peeled off
......@@ -198,7 +196,7 @@ hooks with the SELinux specifics expanded below::
security_sctp_assoc_request()
security_sctp_bind_connect()
security_sctp_sk_clone()
security_inet_conn_established()
security_sctp_assoc_established()
security_sctp_assoc_request()
......@@ -271,12 +269,12 @@ sockets sid and peer sid to that contained in the ``@asoc sid`` and
@newsk - pointer to new sock structure.
security_inet_conn_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
security_sctp_assoc_established()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when a COOKIE ACK is received where it sets the connection's peer sid
to that in ``@skb``::
@sk - pointer to sock structure.
@asoc - pointer to sctp association structure.
@skb - pointer to skbuff of the COOKIE ACK packet.
......
......@@ -332,6 +332,8 @@ LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname,
struct sockaddr *address, int addrlen)
LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc,
struct sock *sk, struct sock *newsk)
LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc,
struct sk_buff *skb)
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
......
......@@ -1046,6 +1046,11 @@
* @asoc pointer to current sctp association structure.
* @sk pointer to current sock structure.
* @newsk pointer to new sock structure.
* @sctp_assoc_established:
* Passes the @asoc and @chunk->skb of the association COOKIE_ACK packet
* to the security module.
* @asoc pointer to sctp association structure.
* @skb pointer to skbuff of association packet.
*
* Security hooks for Infiniband
*
......
......@@ -1422,6 +1422,8 @@ int security_sctp_bind_connect(struct sock *sk, int optname,
struct sockaddr *address, int addrlen);
void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
struct sock *newsk);
int security_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb);
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct sock *sock,
......@@ -1641,6 +1643,12 @@ static inline void security_sctp_sk_clone(struct sctp_association *asoc,
struct sock *newsk)
{
}
static inline int security_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb)
{
return 0;
}
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
......
......@@ -930,6 +930,11 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Set peer label for connection. */
if (security_sctp_assoc_established((struct sctp_association *)asoc,
chunk->skb))
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
/* Verify that the chunk length for the COOKIE-ACK is OK.
* If we don't do this, any bundled chunks may be junked.
*/
......@@ -945,9 +950,6 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net,
*/
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
/* Set peer label for connection. */
security_inet_conn_established(ep->base.sk, chunk->skb);
/* RFC 2960 5.1 Normal Establishment of an Association
*
* E) Upon reception of the COOKIE ACK, endpoint "A" will move
......
......@@ -884,9 +884,22 @@ int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
return call_int_hook(fs_context_dup, 0, fc, src_fc);
}
int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param)
int security_fs_context_parse_param(struct fs_context *fc,
struct fs_parameter *param)
{
return call_int_hook(fs_context_parse_param, -ENOPARAM, fc, param);
struct security_hook_list *hp;
int trc;
int rc = -ENOPARAM;
hlist_for_each_entry(hp, &security_hook_heads.fs_context_parse_param,
list) {
trc = hp->hook.fs_context_parse_param(fc, param);
if (trc == 0)
rc = 0;
else if (trc != -ENOPARAM)
return trc;
}
return rc;
}
int security_sb_alloc(struct super_block *sb)
......@@ -2391,6 +2404,13 @@ void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
}
EXPORT_SYMBOL(security_sctp_sk_clone);
int security_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb)
{
return call_int_hook(sctp_assoc_established, 0, asoc, skb);
}
EXPORT_SYMBOL(security_sctp_assoc_established);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_INFINIBAND
......
......@@ -211,10 +211,9 @@ static int selinux_lsm_notifier_avc_callback(u32 event)
*/
static void cred_init_security(void)
{
struct cred *cred = (struct cred *) current->real_cred;
struct task_security_struct *tsec;
tsec = selinux_cred(cred);
tsec = selinux_cred(unrcu_pointer(current->real_cred));
tsec->osid = tsec->sid = SECINITSID_KERNEL;
}
......@@ -341,17 +340,15 @@ static void inode_free_security(struct inode *inode)
}
struct selinux_mnt_opts {
const char *fscontext, *context, *rootcontext, *defcontext;
u32 fscontext_sid;
u32 context_sid;
u32 rootcontext_sid;
u32 defcontext_sid;
};
static void selinux_free_mnt_opts(void *mnt_opts)
{
struct selinux_mnt_opts *opts = mnt_opts;
kfree(opts->fscontext);
kfree(opts->context);
kfree(opts->rootcontext);
kfree(opts->defcontext);
kfree(opts);
kfree(mnt_opts);
}
enum {
......@@ -479,7 +476,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
static int sb_check_xattr_support(struct super_block *sb)
{
struct superblock_security_struct *sbsec = sb->s_security;
struct superblock_security_struct *sbsec = selinux_superblock(sb);
struct dentry *root = sb->s_root;
struct inode *root_inode = d_backing_inode(root);
u32 sid;
......@@ -598,18 +595,6 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
return 0;
}
static int parse_sid(struct super_block *sb, const char *s, u32 *sid,
gfp_t gfp)
{
int rc = security_context_str_to_sid(&selinux_state, s,
sid, gfp);
if (rc)
pr_warn("SELinux: security_context_str_to_sid"
"(%s) failed for (dev %s, type %s) errno=%d\n",
s, sb->s_id, sb->s_type->name, rc);
return rc;
}
/*
* Allow filesystems with binary mount data to explicitly set mount point
* labeling information.
......@@ -672,41 +657,29 @@ static int selinux_set_mnt_opts(struct super_block *sb,
* than once with different security options.
*/
if (opts) {
if (opts->fscontext) {
rc = parse_sid(sb, opts->fscontext, &fscontext_sid,
GFP_KERNEL);
if (rc)
goto out;
if (opts->fscontext_sid) {
fscontext_sid = opts->fscontext_sid;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
fscontext_sid))
goto out_double_mount;
sbsec->flags |= FSCONTEXT_MNT;
}
if (opts->context) {
rc = parse_sid(sb, opts->context, &context_sid,
GFP_KERNEL);
if (rc)
goto out;
if (opts->context_sid) {
context_sid = opts->context_sid;
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
context_sid))
goto out_double_mount;
sbsec->flags |= CONTEXT_MNT;
}
if (opts->rootcontext) {
rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid,
GFP_KERNEL);
if (rc)
goto out;
if (opts->rootcontext_sid) {
rootcontext_sid = opts->rootcontext_sid;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
rootcontext_sid))
goto out_double_mount;
sbsec->flags |= ROOTCONTEXT_MNT;
}
if (opts->defcontext) {
rc = parse_sid(sb, opts->defcontext, &defcontext_sid,
GFP_KERNEL);
if (rc)
goto out;
if (opts->defcontext_sid) {
defcontext_sid = opts->defcontext_sid;
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
defcontext_sid))
goto out_double_mount;
......@@ -976,6 +949,8 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
{
struct selinux_mnt_opts *opts = *mnt_opts;
bool is_alloc_opts = false;
u32 *dst_sid;
int rc;
if (token == Opt_seclabel)
/* eaten and completely ignored */
......@@ -983,6 +958,11 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
if (!s)
return -ENOMEM;
if (!selinux_initialized(&selinux_state)) {
pr_warn("SELinux: Unable to set superblock options before the security server is initialized\n");
return -EINVAL;
}
if (!opts) {
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
......@@ -993,28 +973,34 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
switch (token) {
case Opt_context:
if (opts->context || opts->defcontext)
if (opts->context_sid || opts->defcontext_sid)
goto err;
opts->context = s;
dst_sid = &opts->context_sid;
break;
case Opt_fscontext:
if (opts->fscontext)
if (opts->fscontext_sid)
goto err;
opts->fscontext = s;
dst_sid = &opts->fscontext_sid;
break;
case Opt_rootcontext:
if (opts->rootcontext)
if (opts->rootcontext_sid)
goto err;
opts->rootcontext = s;
dst_sid = &opts->rootcontext_sid;
break;
case Opt_defcontext:
if (opts->context || opts->defcontext)
if (opts->context_sid || opts->defcontext_sid)
goto err;
opts->defcontext = s;
dst_sid = &opts->defcontext_sid;
break;
default:
WARN_ON(1);
return -EINVAL;
}
return 0;
rc = security_context_str_to_sid(&selinux_state, s, dst_sid, GFP_KERNEL);
if (rc)
pr_warn("SELinux: security_context_str_to_sid (%s) failed with errno=%d\n",
s, rc);
return rc;
err:
if (is_alloc_opts) {
......@@ -2535,7 +2521,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
if (rc) {
clear_itimer();
spin_lock_irq(&current->sighand->siglock);
spin_lock_irq(&unrcu_pointer(current->sighand)->siglock);
if (!fatal_signal_pending(current)) {
flush_sigqueue(&current->pending);
flush_sigqueue(&current->signal->shared_pending);
......@@ -2543,13 +2529,13 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
sigemptyset(&current->blocked);
recalc_sigpending();
}
spin_unlock_irq(&current->sighand->siglock);
spin_unlock_irq(&unrcu_pointer(current->sighand)->siglock);
}
/* Wake up the parent if it is waiting so that it can recheck
* wait permission to the new task SID. */
read_lock(&tasklist_lock);
__wake_up_parent(current, current->real_parent);
__wake_up_parent(current, unrcu_pointer(current->real_parent));
read_unlock(&tasklist_lock);
}
......@@ -2647,9 +2633,7 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
{
struct selinux_mnt_opts *opts = mnt_opts;
struct superblock_security_struct *sbsec = sb->s_security;
u32 sid;
int rc;
struct superblock_security_struct *sbsec = selinux_superblock(sb);
/*
* Superblock not initialized (i.e. no options) - reject if any
......@@ -2665,35 +2649,27 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
if (!opts)
return (sbsec->flags & SE_MNTMASK) ? 1 : 0;
if (opts->fscontext) {
rc = parse_sid(sb, opts->fscontext, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
if (opts->fscontext_sid) {
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
opts->fscontext_sid))
return 1;
}
if (opts->context) {
rc = parse_sid(sb, opts->context, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
if (opts->context_sid) {
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
opts->context_sid))
return 1;
}
if (opts->rootcontext) {
if (opts->rootcontext_sid) {
struct inode_security_struct *root_isec;
root_isec = backing_inode_security(sb->s_root);
rc = parse_sid(sb, opts->rootcontext, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
opts->rootcontext_sid))
return 1;
}
if (opts->defcontext) {
rc = parse_sid(sb, opts->defcontext, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
if (opts->defcontext_sid) {
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
opts->defcontext_sid))
return 1;
}
return 0;
......@@ -2703,8 +2679,6 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
{
struct selinux_mnt_opts *opts = mnt_opts;
struct superblock_security_struct *sbsec = selinux_superblock(sb);
u32 sid;
int rc;
if (!(sbsec->flags & SE_SBINITIALIZED))
return 0;
......@@ -2712,34 +2686,26 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
if (!opts)
return 0;
if (opts->fscontext) {
rc = parse_sid(sb, opts->fscontext, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
if (opts->fscontext_sid) {
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
opts->fscontext_sid))
goto out_bad_option;
}
if (opts->context) {
rc = parse_sid(sb, opts->context, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
if (opts->context_sid) {
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
opts->context_sid))
goto out_bad_option;
}
if (opts->rootcontext) {
if (opts->rootcontext_sid) {
struct inode_security_struct *root_isec;
root_isec = backing_inode_security(sb->s_root);
rc = parse_sid(sb, opts->rootcontext, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
opts->rootcontext_sid))
goto out_bad_option;
}
if (opts->defcontext) {
rc = parse_sid(sb, opts->defcontext, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
if (opts->defcontext_sid) {
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
opts->defcontext_sid))
goto out_bad_option;
}
return 0;
......@@ -2806,38 +2772,12 @@ static int selinux_fs_context_dup(struct fs_context *fc,
struct fs_context *src_fc)
{
const struct selinux_mnt_opts *src = src_fc->security;
struct selinux_mnt_opts *opts;
if (!src)
return 0;
fc->security = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
if (!fc->security)
return -ENOMEM;
opts = fc->security;
if (src->fscontext) {
opts->fscontext = kstrdup(src->fscontext, GFP_KERNEL);
if (!opts->fscontext)
return -ENOMEM;
}
if (src->context) {
opts->context = kstrdup(src->context, GFP_KERNEL);
if (!opts->context)
return -ENOMEM;
}
if (src->rootcontext) {
opts->rootcontext = kstrdup(src->rootcontext, GFP_KERNEL);
if (!opts->rootcontext)
return -ENOMEM;
}
if (src->defcontext) {
opts->defcontext = kstrdup(src->defcontext, GFP_KERNEL);
if (!opts->defcontext)
return -ENOMEM;
}
return 0;
fc->security = kmemdup(src, sizeof(*src), GFP_KERNEL);
return fc->security ? 0 : -ENOMEM;
}
static const struct fs_parameter_spec selinux_fs_parameters[] = {
......@@ -2860,10 +2800,9 @@ static int selinux_fs_context_parse_param(struct fs_context *fc,
return opt;
rc = selinux_add_opt(opt, param->string, &fc->security);
if (!rc) {
if (!rc)
param->string = NULL;
rc = 1;
}
return rc;
}
......@@ -3345,8 +3284,6 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
isec->sid = newsid;
isec->initialized = LABEL_INITIALIZED;
spin_unlock(&isec->lock);
return;
}
static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
......@@ -3745,6 +3682,12 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
CAP_OPT_NONE, true);
break;
case FIOCLEX:
case FIONCLEX:
if (!selinux_policycap_ioctl_skip_cloexec())
error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
break;
/* default case assumes that the command will go
* to the file's ioctl() function.
*/
......@@ -5299,37 +5242,38 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
sksec->sclass = isec->sclass;
}
/* Called whenever SCTP receives an INIT chunk. This happens when an incoming
* connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
* already present).
/*
* Determines peer_secid for the asoc and updates socket's peer label
* if it's the first association on the socket.
*/
static int selinux_sctp_assoc_request(struct sctp_association *asoc,
struct sk_buff *skb)
static int selinux_sctp_process_new_assoc(struct sctp_association *asoc,
struct sk_buff *skb)
{
struct sk_security_struct *sksec = asoc->base.sk->sk_security;
struct sock *sk = asoc->base.sk;
u16 family = sk->sk_family;
struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
u8 peerlbl_active;
u32 peer_sid = SECINITSID_UNLABELED;
u32 conn_sid;
int err = 0;
int err;
if (!selinux_policycap_extsockclass())
return 0;
/* handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
family = PF_INET;
peerlbl_active = selinux_peerlbl_enabled();
if (selinux_peerlbl_enabled()) {
asoc->peer_secid = SECSID_NULL;
if (peerlbl_active) {
/* This will return peer_sid = SECSID_NULL if there are
* no peer labels, see security_net_peersid_resolve().
*/
err = selinux_skb_peerlbl_sid(skb, asoc->base.sk->sk_family,
&peer_sid);
err = selinux_skb_peerlbl_sid(skb, family, &asoc->peer_secid);
if (err)
return err;
if (peer_sid == SECSID_NULL)
peer_sid = SECINITSID_UNLABELED;
if (asoc->peer_secid == SECSID_NULL)
asoc->peer_secid = SECINITSID_UNLABELED;
} else {
asoc->peer_secid = SECINITSID_UNLABELED;
}
if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
......@@ -5340,8 +5284,8 @@ static int selinux_sctp_assoc_request(struct sctp_association *asoc,
* then it is approved by policy and used as the primary
* peer SID for getpeercon(3).
*/
sksec->peer_sid = peer_sid;
} else if (sksec->peer_sid != peer_sid) {
sksec->peer_sid = asoc->peer_secid;
} else if (sksec->peer_sid != asoc->peer_secid) {
/* Other association peer SIDs are checked to enforce
* consistency among the peer SIDs.
*/
......@@ -5349,11 +5293,32 @@ static int selinux_sctp_assoc_request(struct sctp_association *asoc,
ad.u.net = &net;
ad.u.net->sk = asoc->base.sk;
err = avc_has_perm(&selinux_state,
sksec->peer_sid, peer_sid, sksec->sclass,
SCTP_SOCKET__ASSOCIATION, &ad);
sksec->peer_sid, asoc->peer_secid,
sksec->sclass, SCTP_SOCKET__ASSOCIATION,
&ad);
if (err)
return err;
}
return 0;
}
/* Called whenever SCTP receives an INIT or COOKIE ECHO chunk. This
* happens on an incoming connect(2), sctp_connectx(3) or
* sctp_sendmsg(3) (with no association already present).
*/
static int selinux_sctp_assoc_request(struct sctp_association *asoc,
struct sk_buff *skb)
{
struct sk_security_struct *sksec = asoc->base.sk->sk_security;
u32 conn_sid;
int err;
if (!selinux_policycap_extsockclass())
return 0;
err = selinux_sctp_process_new_assoc(asoc, skb);
if (err)
return err;
/* Compute the MLS component for the connection and store
* the information in asoc. This will be used by SCTP TCP type
......@@ -5361,17 +5326,36 @@ static int selinux_sctp_assoc_request(struct sctp_association *asoc,
* socket to be generated. selinux_sctp_sk_clone() will then
* plug this into the new socket.
*/
err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
err = selinux_conn_sid(sksec->sid, asoc->peer_secid, &conn_sid);
if (err)
return err;
asoc->secid = conn_sid;
asoc->peer_secid = peer_sid;
/* Set any NetLabel labels including CIPSO/CALIPSO options. */
return selinux_netlbl_sctp_assoc_request(asoc, skb);
}
/* Called when SCTP receives a COOKIE ACK chunk as the final
* response to an association request (initited by us).
*/
static int selinux_sctp_assoc_established(struct sctp_association *asoc,
struct sk_buff *skb)
{
struct sk_security_struct *sksec = asoc->base.sk->sk_security;
if (!selinux_policycap_extsockclass())
return 0;
/* Inherit secid from the parent socket - this will be picked up
* by selinux_sctp_sk_clone() if the association gets peeled off
* into a new socket.
*/
asoc->secid = sksec->sid;
return selinux_sctp_process_new_assoc(asoc, skb);
}
/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
* based on their @optname.
*/
......@@ -7192,6 +7176,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
LSM_HOOK_INIT(sctp_assoc_established, selinux_sctp_assoc_established),
LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
......
......@@ -104,7 +104,7 @@ static void sel_ib_pkey_insert(struct sel_ib_pkey *pkey)
tail = list_entry(
rcu_dereference_protected(
sel_ib_pkey_hash[idx].list.prev,
list_tail_rcu(&sel_ib_pkey_hash[idx].list),
lockdep_is_held(&sel_ib_pkey_lock)),
struct sel_ib_pkey, list);
list_del_rcu(&tail->list);
......
......@@ -29,7 +29,7 @@ static char *selinux_ima_collect_state(struct selinux_state *state)
buf_len = strlen("initialized=0;enforcing=0;checkreqprot=0;") + 1;
len = strlen(on);
for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++)
for (i = 0; i < __POLICYDB_CAP_MAX; i++)
buf_len += strlen(selinux_policycap_names[i]) + len;
buf = kzalloc(buf_len, GFP_KERNEL);
......@@ -54,7 +54,7 @@ static char *selinux_ima_collect_state(struct selinux_state *state)
rc = strlcat(buf, checkreqprot_get(state) ? on : off, buf_len);
WARN_ON(rc >= buf_len);
for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) {
for (i = 0; i < __POLICYDB_CAP_MAX; i++) {
rc = strlcat(buf, selinux_policycap_names[i], buf_len);
WARN_ON(rc >= buf_len);
......
......@@ -4,17 +4,18 @@
/* Policy capabilities */
enum {
POLICYDB_CAPABILITY_NETPEER,
POLICYDB_CAPABILITY_OPENPERM,
POLICYDB_CAPABILITY_EXTSOCKCLASS,
POLICYDB_CAPABILITY_ALWAYSNETWORK,
POLICYDB_CAPABILITY_CGROUPSECLABEL,
POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION,
POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS,
__POLICYDB_CAPABILITY_MAX
POLICYDB_CAP_NETPEER,
POLICYDB_CAP_OPENPERM,
POLICYDB_CAP_EXTSOCKCLASS,
POLICYDB_CAP_ALWAYSNETWORK,
POLICYDB_CAP_CGROUPSECLABEL,
POLICYDB_CAP_NNP_NOSUID_TRANSITION,
POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS,
POLICYDB_CAP_IOCTL_SKIP_CLOEXEC,
__POLICYDB_CAP_MAX
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
#define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1)
extern const char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX];
extern const char *selinux_policycap_names[__POLICYDB_CAP_MAX];
#endif /* _SELINUX_POLICYCAP_H_ */
......@@ -5,14 +5,15 @@
#include "policycap.h"
/* Policy capability names */
const char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
const char *selinux_policycap_names[__POLICYDB_CAP_MAX] = {
"network_peer_controls",
"open_perms",
"extended_socket_class",
"always_check_network",
"cgroup_seclabel",
"nnp_nosuid_transition",
"genfs_seclabel_symlinks"
"genfs_seclabel_symlinks",
"ioctl_skip_cloexec"
};
#endif /* _SELINUX_POLICYCAP_NAMES_H_ */
......@@ -96,7 +96,7 @@ struct selinux_state {
#endif
bool checkreqprot;
bool initialized;
bool policycap[__POLICYDB_CAPABILITY_MAX];
bool policycap[__POLICYDB_CAP_MAX];
struct page *status_page;
struct mutex status_lock;
......@@ -174,49 +174,56 @@ static inline bool selinux_policycap_netpeer(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_NETPEER]);
return READ_ONCE(state->policycap[POLICYDB_CAP_NETPEER]);
}
static inline bool selinux_policycap_openperm(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_OPENPERM]);
return READ_ONCE(state->policycap[POLICYDB_CAP_OPENPERM]);
}
static inline bool selinux_policycap_extsockclass(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_EXTSOCKCLASS]);
return READ_ONCE(state->policycap[POLICYDB_CAP_EXTSOCKCLASS]);
}
static inline bool selinux_policycap_alwaysnetwork(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_ALWAYSNETWORK]);
return READ_ONCE(state->policycap[POLICYDB_CAP_ALWAYSNETWORK]);
}
static inline bool selinux_policycap_cgroupseclabel(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_CGROUPSECLABEL]);
return READ_ONCE(state->policycap[POLICYDB_CAP_CGROUPSECLABEL]);
}
static inline bool selinux_policycap_nnp_nosuid_transition(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION]);
return READ_ONCE(state->policycap[POLICYDB_CAP_NNP_NOSUID_TRANSITION]);
}
static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS]);
return READ_ONCE(state->policycap[POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS]);
}
static inline bool selinux_policycap_ioctl_skip_cloexec(void)
{
struct selinux_state *state = &selinux_state;
return READ_ONCE(state->policycap[POLICYDB_CAP_IOCTL_SKIP_CLOEXEC]);
}
struct selinux_policy_convert_data;
......@@ -254,8 +261,8 @@ struct av_decision {
#define XPERMS_AUDITALLOW 2
#define XPERMS_DONTAUDIT 4
#define security_xperm_set(perms, x) (perms[x >> 5] |= 1 << (x & 0x1f))
#define security_xperm_test(perms, x) (1 & (perms[x >> 5] >> (x & 0x1f)))
#define security_xperm_set(perms, x) ((perms)[(x) >> 5] |= 1 << ((x) & 0x1f))
#define security_xperm_test(perms, x) (1 & ((perms)[(x) >> 5] >> ((x) & 0x1f)))
struct extended_perms_data {
u32 p[8];
};
......@@ -386,11 +393,11 @@ int security_get_allow_unknown(struct selinux_state *state);
int security_fs_use(struct selinux_state *state, struct super_block *sb);
int security_genfs_sid(struct selinux_state *state,
const char *fstype, char *name, u16 sclass,
const char *fstype, const char *path, u16 sclass,
u32 *sid);
int selinux_policy_genfs_sid(struct selinux_policy *policy,
const char *fstype, char *name, u16 sclass,
const char *fstype, const char *path, u16 sclass,
u32 *sid);
#ifdef CONFIG_NETLABEL
......
......@@ -107,7 +107,7 @@ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
switch (family) {
case PF_INET:
idx = sel_netnode_hashfn_ipv4(*(__be32 *)addr);
idx = sel_netnode_hashfn_ipv4(*(const __be32 *)addr);
break;
case PF_INET6:
idx = sel_netnode_hashfn_ipv6(addr);
......@@ -121,7 +121,7 @@ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
if (node->nsec.family == family)
switch (family) {
case PF_INET:
if (node->nsec.addr.ipv4 == *(__be32 *)addr)
if (node->nsec.addr.ipv4 == *(const __be32 *)addr)
return node;
break;
case PF_INET6:
......@@ -164,8 +164,9 @@ static void sel_netnode_insert(struct sel_netnode *node)
if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
struct sel_netnode *tail;
tail = list_entry(
rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
lockdep_is_held(&sel_netnode_lock)),
rcu_dereference_protected(
list_tail_rcu(&sel_netnode_hash[idx].list),
lockdep_is_held(&sel_netnode_lock)),
struct sel_netnode, list);
list_del_rcu(&tail->list);
kfree_rcu(tail, rcu);
......
......@@ -113,7 +113,7 @@ static void sel_netport_insert(struct sel_netport *port)
struct sel_netport *tail;
tail = list_entry(
rcu_dereference_protected(
sel_netport_hash[idx].list.prev,
list_tail_rcu(&sel_netport_hash[idx].list),
lockdep_is_held(&sel_netport_lock)),
struct sel_netport, list);
list_del_rcu(&tail->list);
......
......@@ -1983,7 +1983,7 @@ static int sel_make_policycap(struct selinux_fs_info *fsi)
struct dentry *dentry = NULL;
struct inode *inode = NULL;
for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) {
for (iter = 0; iter <= POLICYDB_CAP_MAX; iter++) {
if (iter < ARRAY_SIZE(selinux_policycap_names))
dentry = d_alloc_name(fsi->policycap_dir,
selinux_policycap_names[iter]);
......@@ -2127,6 +2127,8 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc)
}
ret = sel_make_avc_files(dentry);
if (ret)
goto err;
dentry = sel_make_dir(sb->s_root, "ss", &fsi->last_ino);
if (IS_ERR(dentry)) {
......
......@@ -67,7 +67,7 @@ static inline int avtab_hash(const struct avtab_key *keyp, u32 mask)
static struct avtab_node*
avtab_insert_node(struct avtab *h, int hvalue,
struct avtab_node *prev, struct avtab_node *cur,
struct avtab_node *prev,
const struct avtab_key *key, const struct avtab_datum *datum)
{
struct avtab_node *newnode;
......@@ -137,7 +137,7 @@ static int avtab_insert(struct avtab *h, const struct avtab_key *key,
break;
}
newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
newnode = avtab_insert_node(h, hvalue, prev, key, datum);
if (!newnode)
return -ENOMEM;
......@@ -177,7 +177,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h,
key->target_class < cur->key.target_class)
break;
}
return avtab_insert_node(h, hvalue, prev, cur, key, datum);
return avtab_insert_node(h, hvalue, prev, key, datum);
}
struct avtab_datum *avtab_search(struct avtab *h, const struct avtab_key *key)
......
......@@ -567,8 +567,6 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
if (node->key.specified & AVTAB_ENABLED)
services_compute_xperms_decision(xpermd, node);
}
return;
}
/* Determine whether additional permissions are granted by the conditional
* av table, and if so, add them to the result
......
......@@ -359,7 +359,6 @@ void ebitmap_destroy(struct ebitmap *e)
e->highbit = 0;
e->node = NULL;
return;
}
int ebitmap_read(struct ebitmap *e, void *fp)
......
......@@ -118,9 +118,9 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
}
#define ebitmap_for_each_positive_bit(e, n, bit) \
for (bit = ebitmap_start_positive(e, &n); \
bit < ebitmap_length(e); \
bit = ebitmap_next_positive(e, &n, bit)) \
for ((bit) = ebitmap_start_positive(e, &(n)); \
(bit) < ebitmap_length(e); \
(bit) = ebitmap_next_positive(e, &(n), bit)) \
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
......
......@@ -156,7 +156,6 @@ void mls_sid_to_context(struct policydb *p,
}
*scontext = scontextp;
return;
}
int mls_level_isvalid(struct policydb *p, struct mls_level *l)
......
......@@ -41,8 +41,6 @@
#include "mls.h"
#include "services.h"
#define _DEBUG_HASHES
#ifdef DEBUG_HASHES
static const char *symtab_name[SYM_NUM] = {
"common prefixes",
......@@ -704,7 +702,7 @@ static void symtab_hash_eval(struct symtab *s)
}
#else
static inline void hash_eval(struct hashtab *h, char *hash_name)
static inline void hash_eval(struct hashtab *h, const char *hash_name)
{
}
#endif
......
......@@ -529,8 +529,6 @@ static void security_dump_masked_av(struct policydb *policydb,
/* release scontext/tcontext */
kfree(tcontext_name);
kfree(scontext_name);
return;
}
/*
......@@ -1452,7 +1450,7 @@ static int string_to_context_struct(struct policydb *pol,
/* Parse the security context. */
rc = -EINVAL;
scontextp = (char *) scontext;
scontextp = scontext;
/* Extract the user. */
p = scontextp;
......@@ -2875,7 +2873,7 @@ int security_get_user_sids(struct selinux_state *state,
*/
static inline int __security_genfs_sid(struct selinux_policy *policy,
const char *fstype,
char *path,
const char *path,
u16 orig_sclass,
u32 *sid)
{
......@@ -2928,7 +2926,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
*/
int security_genfs_sid(struct selinux_state *state,
const char *fstype,
char *path,
const char *path,
u16 orig_sclass,
u32 *sid)
{
......@@ -2952,7 +2950,7 @@ int security_genfs_sid(struct selinux_state *state,
int selinux_policy_genfs_sid(struct selinux_policy *policy,
const char *fstype,
char *path,
const char *path,
u16 orig_sclass,
u32 *sid)
{
......
......@@ -27,8 +27,8 @@ struct sidtab_str_cache {
char str[];
};
#define index_to_sid(index) (index + SECINITSID_NUM + 1)
#define sid_to_index(sid) (sid - (SECINITSID_NUM + 1))
#define index_to_sid(index) ((index) + SECINITSID_NUM + 1)
#define sid_to_index(sid) ((sid) - (SECINITSID_NUM + 1))
int sidtab_init(struct sidtab *s)
{
......
......@@ -347,7 +347,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
int rc;
struct xfrm_sec_ctx *ctx;
char *ctx_str = NULL;
int str_len;
u32 str_len;
if (!polsec)
return 0;
......
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