Merge git://git.infradead.org/users/eparis/selinux
Conflicts: security/selinux/hooks.c Pull Eric's existing SELinux tree as there are a number of patches in there that are not yet upstream. There was some minor fixup needed to resolve a conflict in security/selinux/hooks.c:selinux_set_mnt_opts() between the labeled NFS patches and Eric's security_fs_use() simplification patch.
This commit is contained in:
@@ -95,7 +95,9 @@
|
||||
#include "audit.h"
|
||||
#include "avc_ss.h"
|
||||
|
||||
#define NUM_SEL_MNT_OPTS 5
|
||||
#define SB_TYPE_FMT "%s%s%s"
|
||||
#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
|
||||
#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
|
||||
|
||||
extern struct security_operations *security_ops;
|
||||
|
||||
@@ -139,12 +141,28 @@ static struct kmem_cache *sel_inode_cache;
|
||||
* This function checks the SECMARK reference counter to see if any SECMARK
|
||||
* targets are currently configured, if the reference counter is greater than
|
||||
* zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
|
||||
* enabled, false (0) if SECMARK is disabled.
|
||||
* enabled, false (0) if SECMARK is disabled. If the always_check_network
|
||||
* policy capability is enabled, SECMARK is always considered enabled.
|
||||
*
|
||||
*/
|
||||
static int selinux_secmark_enabled(void)
|
||||
{
|
||||
return (atomic_read(&selinux_secmark_refcount) > 0);
|
||||
return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
|
||||
}
|
||||
|
||||
/**
|
||||
* selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
|
||||
*
|
||||
* Description:
|
||||
* This function checks if NetLabel or labeled IPSEC is enabled. Returns true
|
||||
* (1) if any are enabled or false (0) if neither are enabled. If the
|
||||
* always_check_network policy capability is enabled, peer labeling
|
||||
* is always considered enabled.
|
||||
*
|
||||
*/
|
||||
static int selinux_peerlbl_enabled(void)
|
||||
{
|
||||
return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -309,8 +327,11 @@ enum {
|
||||
Opt_defcontext = 3,
|
||||
Opt_rootcontext = 4,
|
||||
Opt_labelsupport = 5,
|
||||
Opt_nextmntopt = 6,
|
||||
};
|
||||
|
||||
#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
|
||||
|
||||
static const match_table_t tokens = {
|
||||
{Opt_context, CONTEXT_STR "%s"},
|
||||
{Opt_fscontext, FSCONTEXT_STR "%s"},
|
||||
@@ -355,6 +376,29 @@ static int may_context_mount_inode_relabel(u32 sid,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int selinux_is_sblabel_mnt(struct super_block *sb)
|
||||
{
|
||||
struct superblock_security_struct *sbsec = sb->s_security;
|
||||
|
||||
if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
|
||||
sbsec->behavior == SECURITY_FS_USE_TRANS ||
|
||||
sbsec->behavior == SECURITY_FS_USE_TASK)
|
||||
return 1;
|
||||
|
||||
/* Special handling for sysfs. Is genfs but also has setxattr handler*/
|
||||
if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Special handling for rootfs. Is genfs but supports
|
||||
* setting SELinux context on in-core inodes.
|
||||
*/
|
||||
if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sb_finish_set_opts(struct super_block *sb)
|
||||
{
|
||||
struct superblock_security_struct *sbsec = sb->s_security;
|
||||
@@ -369,8 +413,8 @@ static int sb_finish_set_opts(struct super_block *sb)
|
||||
the first boot of the SELinux kernel before we have
|
||||
assigned xattr values to the filesystem. */
|
||||
if (!root_inode->i_op->getxattr) {
|
||||
printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
|
||||
"xattr support\n", sb->s_id, sb->s_type->name);
|
||||
printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
|
||||
"xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
@@ -378,35 +422,27 @@ static int sb_finish_set_opts(struct super_block *sb)
|
||||
if (rc < 0 && rc != -ENODATA) {
|
||||
if (rc == -EOPNOTSUPP)
|
||||
printk(KERN_WARNING "SELinux: (dev %s, type "
|
||||
"%s) has no security xattr handler\n",
|
||||
sb->s_id, sb->s_type->name);
|
||||
SB_TYPE_FMT") has no security xattr handler\n",
|
||||
sb->s_id, SB_TYPE_ARGS(sb));
|
||||
else
|
||||
printk(KERN_WARNING "SELinux: (dev %s, type "
|
||||
"%s) getxattr errno %d\n", sb->s_id,
|
||||
sb->s_type->name, -rc);
|
||||
SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
|
||||
SB_TYPE_ARGS(sb), -rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
|
||||
|
||||
if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
|
||||
printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
|
||||
sb->s_id, sb->s_type->name);
|
||||
printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
|
||||
sb->s_id, SB_TYPE_ARGS(sb));
|
||||
else
|
||||
printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
|
||||
sb->s_id, sb->s_type->name,
|
||||
printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
|
||||
sb->s_id, SB_TYPE_ARGS(sb),
|
||||
labeling_behaviors[sbsec->behavior-1]);
|
||||
|
||||
if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
|
||||
sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
|
||||
sbsec->behavior == SECURITY_FS_USE_NONE ||
|
||||
sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
|
||||
sbsec->flags &= ~SE_SBLABELSUPP;
|
||||
|
||||
/* Special handling for sysfs. Is genfs but also has setxattr handler*/
|
||||
if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
|
||||
sbsec->flags |= SE_SBLABELSUPP;
|
||||
sbsec->flags |= SE_SBINITIALIZED;
|
||||
if (selinux_is_sblabel_mnt(sb))
|
||||
sbsec->flags |= SBLABEL_MNT;
|
||||
|
||||
/* Initialize the root inode. */
|
||||
rc = inode_doinit_with_dentry(root_inode, root);
|
||||
@@ -460,15 +496,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
|
||||
if (!ss_initialized)
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure we always check enough bits to cover the mask */
|
||||
BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
|
||||
|
||||
tmp = sbsec->flags & SE_MNTMASK;
|
||||
/* count the number of mount options for this sb */
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
|
||||
if (tmp & 0x01)
|
||||
opts->num_mnt_opts++;
|
||||
tmp >>= 1;
|
||||
}
|
||||
/* Check if the Label support flag is set */
|
||||
if (sbsec->flags & SE_SBLABELSUPP)
|
||||
if (sbsec->flags & SBLABEL_MNT)
|
||||
opts->num_mnt_opts++;
|
||||
|
||||
opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
|
||||
@@ -515,9 +554,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
|
||||
opts->mnt_opts[i] = context;
|
||||
opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
|
||||
}
|
||||
if (sbsec->flags & SE_SBLABELSUPP) {
|
||||
if (sbsec->flags & SBLABEL_MNT) {
|
||||
opts->mnt_opts[i] = NULL;
|
||||
opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
|
||||
opts->mnt_opts_flags[i++] = SBLABEL_MNT;
|
||||
}
|
||||
|
||||
BUG_ON(i != opts->num_mnt_opts);
|
||||
@@ -561,7 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
||||
const struct cred *cred = current_cred();
|
||||
int rc = 0, i;
|
||||
struct superblock_security_struct *sbsec = sb->s_security;
|
||||
const char *name = sb->s_type->name;
|
||||
struct inode *inode = sbsec->sb->s_root->d_inode;
|
||||
struct inode_security_struct *root_isec = inode->i_security;
|
||||
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
|
||||
@@ -614,14 +652,14 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
||||
for (i = 0; i < num_opts; i++) {
|
||||
u32 sid;
|
||||
|
||||
if (flags[i] == SE_SBLABELSUPP)
|
||||
if (flags[i] == SBLABEL_MNT)
|
||||
continue;
|
||||
rc = security_context_to_sid(mount_options[i],
|
||||
strlen(mount_options[i]), &sid);
|
||||
if (rc) {
|
||||
printk(KERN_WARNING "SELinux: security_context_to_sid"
|
||||
"(%s) failed for (dev %s, type %s) errno=%d\n",
|
||||
mount_options[i], sb->s_id, name, rc);
|
||||
"(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
|
||||
mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
|
||||
goto out;
|
||||
}
|
||||
switch (flags[i]) {
|
||||
@@ -685,9 +723,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
||||
* Determine the labeling behavior to use for this
|
||||
* filesystem type.
|
||||
*/
|
||||
rc = security_fs_use((sbsec->flags & SE_SBPROC) ?
|
||||
"proc" : sb->s_type->name,
|
||||
&sbsec->behavior, &sbsec->sid);
|
||||
rc = security_fs_use(sb);
|
||||
if (rc) {
|
||||
printk(KERN_WARNING
|
||||
"%s: security_fs_use(%s) returned %d\n",
|
||||
@@ -770,7 +806,8 @@ out:
|
||||
out_double_mount:
|
||||
rc = -EINVAL;
|
||||
printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
|
||||
"security settings for (dev %s, type %s)\n", sb->s_id, name);
|
||||
"security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
|
||||
SB_TYPE_ARGS(sb));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1037,7 +1074,7 @@ static void selinux_write_opts(struct seq_file *m,
|
||||
case DEFCONTEXT_MNT:
|
||||
prefix = DEFCONTEXT_STR;
|
||||
break;
|
||||
case SE_SBLABELSUPP:
|
||||
case SBLABEL_MNT:
|
||||
seq_putc(m, ',');
|
||||
seq_puts(m, LABELSUPP_STR);
|
||||
continue;
|
||||
@@ -1650,7 +1687,7 @@ static int may_create(struct inode *dir,
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
|
||||
if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
|
||||
rc = security_transition_sid(sid, dsec->sid, tclass,
|
||||
&dentry->d_name, &newsid);
|
||||
if (rc)
|
||||
@@ -2438,14 +2475,14 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
|
||||
u32 sid;
|
||||
size_t len;
|
||||
|
||||
if (flags[i] == SE_SBLABELSUPP)
|
||||
if (flags[i] == SBLABEL_MNT)
|
||||
continue;
|
||||
len = strlen(mount_options[i]);
|
||||
rc = security_context_to_sid(mount_options[i], len, &sid);
|
||||
if (rc) {
|
||||
printk(KERN_WARNING "SELinux: security_context_to_sid"
|
||||
"(%s) failed for (dev %s, type %s) errno=%d\n",
|
||||
mount_options[i], sb->s_id, sb->s_type->name, rc);
|
||||
"(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
|
||||
mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
|
||||
goto out_free_opts;
|
||||
}
|
||||
rc = -EINVAL;
|
||||
@@ -2483,8 +2520,8 @@ out_free_secdata:
|
||||
return rc;
|
||||
out_bad_option:
|
||||
printk(KERN_WARNING "SELinux: unable to change security options "
|
||||
"during remount (dev %s, type=%s)\n", sb->s_id,
|
||||
sb->s_type->name);
|
||||
"during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
|
||||
SB_TYPE_ARGS(sb));
|
||||
goto out_free_opts;
|
||||
}
|
||||
|
||||
@@ -2606,7 +2643,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
|
||||
if ((sbsec->flags & SE_SBINITIALIZED) &&
|
||||
(sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
|
||||
newsid = sbsec->mntpoint_sid;
|
||||
else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
|
||||
else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
|
||||
rc = security_transition_sid(sid, dsec->sid,
|
||||
inode_mode_to_security_class(inode->i_mode),
|
||||
qstr, &newsid);
|
||||
@@ -2628,7 +2665,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
|
||||
isec->initialized = 1;
|
||||
}
|
||||
|
||||
if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
|
||||
if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (name) {
|
||||
@@ -2836,7 +2873,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
return selinux_inode_setotherxattr(dentry, name);
|
||||
|
||||
sbsec = inode->i_sb->s_security;
|
||||
if (!(sbsec->flags & SE_SBLABELSUPP))
|
||||
if (!(sbsec->flags & SBLABEL_MNT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!inode_owner_or_capable(inode))
|
||||
@@ -3797,8 +3834,12 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
|
||||
u32 nlbl_sid;
|
||||
u32 nlbl_type;
|
||||
|
||||
selinux_skb_xfrm_sid(skb, &xfrm_sid);
|
||||
selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
|
||||
err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
|
||||
if (unlikely(err))
|
||||
return -EACCES;
|
||||
err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
|
||||
if (unlikely(err))
|
||||
return -EACCES;
|
||||
|
||||
err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
|
||||
if (unlikely(err)) {
|
||||
@@ -4252,7 +4293,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
||||
return selinux_sock_rcv_skb_compat(sk, skb, family);
|
||||
|
||||
secmark_active = selinux_secmark_enabled();
|
||||
peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
|
||||
peerlbl_active = selinux_peerlbl_enabled();
|
||||
if (!secmark_active && !peerlbl_active)
|
||||
return 0;
|
||||
|
||||
@@ -4634,7 +4675,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
|
||||
|
||||
secmark_active = selinux_secmark_enabled();
|
||||
netlbl_active = netlbl_enabled();
|
||||
peerlbl_active = netlbl_active || selinux_xfrm_enabled();
|
||||
peerlbl_active = selinux_peerlbl_enabled();
|
||||
if (!secmark_active && !peerlbl_active)
|
||||
return NF_ACCEPT;
|
||||
|
||||
@@ -4786,7 +4827,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
|
||||
return NF_ACCEPT;
|
||||
#endif
|
||||
secmark_active = selinux_secmark_enabled();
|
||||
peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
|
||||
peerlbl_active = selinux_peerlbl_enabled();
|
||||
if (!secmark_active && !peerlbl_active)
|
||||
return NF_ACCEPT;
|
||||
|
||||
@@ -5790,7 +5831,8 @@ static struct security_operations selinux_ops = {
|
||||
.xfrm_policy_clone_security = selinux_xfrm_policy_clone,
|
||||
.xfrm_policy_free_security = selinux_xfrm_policy_free,
|
||||
.xfrm_policy_delete_security = selinux_xfrm_policy_delete,
|
||||
.xfrm_state_alloc_security = selinux_xfrm_state_alloc,
|
||||
.xfrm_state_alloc = selinux_xfrm_state_alloc,
|
||||
.xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
|
||||
.xfrm_state_free_security = selinux_xfrm_state_free,
|
||||
.xfrm_state_delete_security = selinux_xfrm_state_delete,
|
||||
.xfrm_policy_lookup = selinux_xfrm_policy_lookup,
|
||||
|
Reference in New Issue
Block a user