mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
This commit is contained in:
@@ -497,7 +497,7 @@ static struct avc_node *avc_alloc_node(void)
|
||||
|
||||
node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT);
|
||||
if (!node)
|
||||
goto out;
|
||||
return NULL;
|
||||
|
||||
INIT_HLIST_NODE(&node->list);
|
||||
avc_cache_stats_incr(allocations);
|
||||
@@ -506,7 +506,6 @@ static struct avc_node *avc_alloc_node(void)
|
||||
selinux_avc.avc_cache_threshold)
|
||||
avc_reclaim_node();
|
||||
|
||||
out:
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
#include <linux/io_uring/cmd.h>
|
||||
#include <uapi/linux/lsm.h>
|
||||
#include <linux/memfd.h>
|
||||
#include <uapi/linux/inet_diag.h>
|
||||
|
||||
#include "initcalls.h"
|
||||
#include "avc.h"
|
||||
@@ -106,6 +107,7 @@
|
||||
#include "netlabel.h"
|
||||
#include "audit.h"
|
||||
#include "avc_ss.h"
|
||||
#include "ima.h"
|
||||
|
||||
#define SELINUX_INODE_INIT_XATTRS 1
|
||||
|
||||
@@ -1336,11 +1338,11 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
char *buffer, *path;
|
||||
|
||||
buffer = (char *)__get_free_page(GFP_KERNEL);
|
||||
buffer = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
|
||||
path = dentry_path_raw(dentry, buffer, PATH_MAX);
|
||||
if (IS_ERR(path))
|
||||
rc = PTR_ERR(path);
|
||||
else {
|
||||
@@ -1361,7 +1363,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
free_page((unsigned long)buffer);
|
||||
kfree(buffer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -6296,12 +6298,17 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
|
||||
return rc;
|
||||
} else if (rc == -EINVAL) {
|
||||
/* -EINVAL is a missing msg/perm mapping */
|
||||
pr_warn_ratelimited("SELinux: unrecognized netlink"
|
||||
" message: protocol=%hu nlmsg_type=%hu sclass=%s"
|
||||
" pid=%d comm=%s\n",
|
||||
sk->sk_protocol, nlh->nlmsg_type,
|
||||
secclass_map[sclass - 1].name,
|
||||
task_pid_nr(current), current->comm);
|
||||
if (sclass == SECCLASS_NETLINK_TCPDIAG_SOCKET &&
|
||||
nlh->nlmsg_type == DCCPDIAG_GETSOCK)
|
||||
pr_warn_once("SELinux: DCCP has been removed, pid=%d comm=%s\n",
|
||||
task_pid_nr(current), current->comm);
|
||||
else
|
||||
pr_warn_ratelimited("SELinux: unrecognized netlink"
|
||||
" message: protocol=%hu nlmsg_type=%hu sclass=%s"
|
||||
" pid=%d comm=%s\n",
|
||||
sk->sk_protocol, nlh->nlmsg_type,
|
||||
secclass_map[sclass - 1].name,
|
||||
task_pid_nr(current), current->comm);
|
||||
if (enforcing_enabled() &&
|
||||
!security_get_allow_unknown())
|
||||
return rc;
|
||||
@@ -7874,6 +7881,8 @@ static __init int selinux_init(void)
|
||||
|
||||
hashtab_cache_init();
|
||||
|
||||
selinux_ima_config_len_init();
|
||||
|
||||
security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks),
|
||||
&selinux_lsmid);
|
||||
|
||||
|
||||
+33
-32
@@ -9,9 +9,31 @@
|
||||
*/
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/ima.h>
|
||||
#include <linux/seq_buf.h>
|
||||
#include "security.h"
|
||||
#include "ima.h"
|
||||
|
||||
static int selinux_ima_config_len __ro_after_init;
|
||||
|
||||
/*
|
||||
* selinux_ima_config_len_init - Compute the configuration settings string length
|
||||
*
|
||||
* The string is fixed text plus one digit per setting, so its length
|
||||
* is known at boot.
|
||||
*/
|
||||
void __init selinux_ima_config_len_init(void)
|
||||
{
|
||||
int buf_len, suffix_len, i;
|
||||
|
||||
buf_len = strlen("initialized=0;enforcing=0;checkreqprot=0;") + 1;
|
||||
suffix_len = strlen("=0;");
|
||||
|
||||
for (i = 0; i < __POLICYDB_CAP_MAX; i++)
|
||||
buf_len += strlen(selinux_policycap_names[i]) + suffix_len;
|
||||
|
||||
selinux_ima_config_len = buf_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* selinux_ima_collect_state - Read selinux configuration settings
|
||||
*
|
||||
@@ -20,46 +42,25 @@
|
||||
*/
|
||||
static char *selinux_ima_collect_state(void)
|
||||
{
|
||||
const char *on = "=1;", *off = "=0;";
|
||||
struct seq_buf s;
|
||||
char *buf;
|
||||
int buf_len, len, i, rc;
|
||||
int i;
|
||||
|
||||
buf_len = strlen("initialized=0;enforcing=0;checkreqprot=0;") + 1;
|
||||
|
||||
len = strlen(on);
|
||||
for (i = 0; i < __POLICYDB_CAP_MAX; i++)
|
||||
buf_len += strlen(selinux_policycap_names[i]) + len;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
buf = kzalloc(selinux_ima_config_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
rc = strscpy(buf, "initialized", buf_len);
|
||||
WARN_ON(rc < 0);
|
||||
seq_buf_init(&s, buf, selinux_ima_config_len);
|
||||
|
||||
rc = strlcat(buf, selinux_initialized() ? on : off, buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
seq_buf_printf(&s, "initialized=%d;enforcing=%d;checkreqprot=%d;",
|
||||
selinux_initialized(), enforcing_enabled(),
|
||||
checkreqprot_get());
|
||||
|
||||
rc = strlcat(buf, "enforcing", buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
for (i = 0; i < __POLICYDB_CAP_MAX; i++)
|
||||
seq_buf_printf(&s, "%s=%d;", selinux_policycap_names[i],
|
||||
selinux_state.policycap[i]);
|
||||
|
||||
rc = strlcat(buf, enforcing_enabled() ? on : off, buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, "checkreqprot", buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, checkreqprot_get() ? on : off, buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
for (i = 0; i < __POLICYDB_CAP_MAX; i++) {
|
||||
rc = strlcat(buf, selinux_policycap_names[i], buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
|
||||
rc = strlcat(buf, selinux_state.policycap[i] ? on : off,
|
||||
buf_len);
|
||||
WARN_ON(rc >= buf_len);
|
||||
}
|
||||
WARN_ON(seq_buf_has_overflowed(&s));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -14,9 +14,13 @@
|
||||
#include "security.h"
|
||||
|
||||
#ifdef CONFIG_IMA
|
||||
void __init selinux_ima_config_len_init(void);
|
||||
extern void selinux_ima_measure_state(void);
|
||||
extern void selinux_ima_measure_state_locked(void);
|
||||
#else
|
||||
static inline void selinux_ima_config_len_init(void)
|
||||
{
|
||||
}
|
||||
static inline void selinux_ima_measure_state(void)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1984,17 +1984,15 @@ int __init init_sel_fs(void)
|
||||
return err;
|
||||
|
||||
err = register_filesystem(&sel_fs_type);
|
||||
if (err) {
|
||||
sysfs_remove_mount_point(fs_kobj, "selinux");
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto err_remove_mount_point;
|
||||
|
||||
selinux_null.mnt = kern_mount(&sel_fs_type);
|
||||
if (IS_ERR(selinux_null.mnt)) {
|
||||
pr_err("selinuxfs: could not mount!\n");
|
||||
err = PTR_ERR(selinux_null.mnt);
|
||||
selinux_null.mnt = NULL;
|
||||
return err;
|
||||
goto err_unregister_fs;
|
||||
}
|
||||
|
||||
selinux_null.dentry = try_lookup_noperm(&null_name,
|
||||
@@ -2003,7 +2001,7 @@ int __init init_sel_fs(void)
|
||||
pr_err("selinuxfs: could not lookup null!\n");
|
||||
err = PTR_ERR(selinux_null.dentry);
|
||||
selinux_null.dentry = NULL;
|
||||
return err;
|
||||
goto err_unmount;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2012,5 +2010,14 @@ int __init init_sel_fs(void)
|
||||
*/
|
||||
(void) selinux_kernel_status_page();
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmount:
|
||||
kern_unmount(selinux_null.mnt);
|
||||
selinux_null.mnt = NULL;
|
||||
err_unregister_fs:
|
||||
unregister_filesystem(&sel_fs_type);
|
||||
err_remove_mount_point:
|
||||
sysfs_remove_mount_point(fs_kobj, "selinux");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -604,10 +604,15 @@ static int type_index(void *key, void *datum, void *datap)
|
||||
typdatum = datum;
|
||||
p = datap;
|
||||
|
||||
if (!typdatum->value || typdatum->value > p->p_types.nprim ||
|
||||
typdatum->bounds > p->p_types.nprim) {
|
||||
pr_err("SELinux: type %s had value %u bounds %u nprim %u\n",
|
||||
(char *)key, typdatum->value, typdatum->bounds,
|
||||
p->p_types.nprim);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (typdatum->primary) {
|
||||
if (!typdatum->value || typdatum->value > p->p_types.nprim ||
|
||||
typdatum->bounds > p->p_types.nprim)
|
||||
return -EINVAL;
|
||||
p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key;
|
||||
p->type_val_to_struct[typdatum->value - 1] = typdatum;
|
||||
}
|
||||
@@ -1175,6 +1180,9 @@ static int perm_read(struct policydb *p, struct symtab *s, struct policy_file *f
|
||||
rc = -EINVAL;
|
||||
if (perdatum->value < 1 || perdatum->value > SEL_VEC_MAX)
|
||||
goto bad;
|
||||
/* indexes an nprim-sized array in security_get_permissions() */
|
||||
if (perdatum->value > s->nprim)
|
||||
goto bad;
|
||||
|
||||
rc = str_read(&key, GFP_KERNEL, fp, len);
|
||||
if (rc)
|
||||
@@ -1327,6 +1335,27 @@ static int read_cons_helper(struct policydb *p, struct constraint_node **nodep,
|
||||
if (depth == (CEXPR_MAXDEPTH - 1))
|
||||
return -EINVAL;
|
||||
depth++;
|
||||
switch (e->attr) {
|
||||
case CEXPR_USER:
|
||||
case CEXPR_TYPE:
|
||||
if (e->op != CEXPR_EQ &&
|
||||
e->op != CEXPR_NEQ)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case CEXPR_ROLE:
|
||||
case CEXPR_L1L2:
|
||||
case CEXPR_L1H2:
|
||||
case CEXPR_H1L2:
|
||||
case CEXPR_H1H2:
|
||||
case CEXPR_L1H1:
|
||||
case CEXPR_L2H2:
|
||||
if (e->op < CEXPR_EQ ||
|
||||
e->op > CEXPR_INCOMP)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case CEXPR_NAMES:
|
||||
if (!allowxtarget && (e->attr & CEXPR_XTARGET))
|
||||
@@ -1334,6 +1363,20 @@ static int read_cons_helper(struct policydb *p, struct constraint_node **nodep,
|
||||
if (depth == (CEXPR_MAXDEPTH - 1))
|
||||
return -EINVAL;
|
||||
depth++;
|
||||
switch (e->attr &
|
||||
~(CEXPR_TARGET|CEXPR_XTARGET)) {
|
||||
case CEXPR_USER:
|
||||
case CEXPR_ROLE:
|
||||
case CEXPR_TYPE:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((e->attr & (CEXPR_TARGET|CEXPR_XTARGET)) ==
|
||||
(CEXPR_TARGET|CEXPR_XTARGET))
|
||||
return -EINVAL;
|
||||
if (e->op != CEXPR_EQ && e->op != CEXPR_NEQ)
|
||||
return -EINVAL;
|
||||
rc = ebitmap_read(&e->names, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -1419,6 +1462,18 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
|
||||
cladatum->comkey);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* security_get_permissions() maps the common's permissions
|
||||
* into an array sized by this class's nprim, so a class must
|
||||
* declare at least as many as the common it inherits.
|
||||
*/
|
||||
if (cladatum->permissions.nprim <
|
||||
cladatum->comdatum->permissions.nprim) {
|
||||
pr_err("SELinux: class %s has fewer permissions than common %s\n",
|
||||
key, cladatum->comkey);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < nel; i++) {
|
||||
rc = perm_read(p, &cladatum->permissions, fp);
|
||||
|
||||
@@ -1355,8 +1355,8 @@ const char *security_get_initial_sid_context(u32 sid)
|
||||
}
|
||||
|
||||
static int security_sid_to_context_core(u32 sid, char **scontext,
|
||||
u32 *scontext_len, int force,
|
||||
int only_invalid)
|
||||
u32 *scontext_len, bool force,
|
||||
bool only_invalid)
|
||||
{
|
||||
struct selinux_policy *policy;
|
||||
struct policydb *policydb;
|
||||
@@ -1439,14 +1439,14 @@ out_unlock:
|
||||
int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
|
||||
{
|
||||
return security_sid_to_context_core(sid, scontext,
|
||||
scontext_len, 0, 0);
|
||||
scontext_len, false, false);
|
||||
}
|
||||
|
||||
int security_sid_to_context_force(u32 sid,
|
||||
char **scontext, u32 *scontext_len)
|
||||
{
|
||||
return security_sid_to_context_core(sid, scontext,
|
||||
scontext_len, 1, 0);
|
||||
scontext_len, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1466,7 +1466,7 @@ int security_sid_to_context_inval(u32 sid,
|
||||
char **scontext, u32 *scontext_len)
|
||||
{
|
||||
return security_sid_to_context_core(sid, scontext,
|
||||
scontext_len, 1, 1);
|
||||
scontext_len, true, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1552,7 +1552,7 @@ out:
|
||||
|
||||
static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
|
||||
u32 *sid, u32 def_sid, gfp_t gfp_flags,
|
||||
int force)
|
||||
bool force)
|
||||
{
|
||||
struct selinux_policy *policy;
|
||||
struct policydb *policydb;
|
||||
@@ -1641,7 +1641,7 @@ int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid,
|
||||
gfp_t gfp)
|
||||
{
|
||||
return security_context_to_sid_core(scontext, scontext_len,
|
||||
sid, SECSID_NULL, gfp, 0);
|
||||
sid, SECSID_NULL, gfp, false);
|
||||
}
|
||||
|
||||
int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp)
|
||||
@@ -1673,14 +1673,14 @@ int security_context_to_sid_default(const char *scontext, u32 scontext_len,
|
||||
u32 *sid, u32 def_sid, gfp_t gfp_flags)
|
||||
{
|
||||
return security_context_to_sid_core(scontext, scontext_len,
|
||||
sid, def_sid, gfp_flags, 1);
|
||||
sid, def_sid, gfp_flags, true);
|
||||
}
|
||||
|
||||
int security_context_to_sid_force(const char *scontext, u32 scontext_len,
|
||||
u32 *sid)
|
||||
{
|
||||
return security_context_to_sid_core(scontext, scontext_len,
|
||||
sid, SECSID_NULL, GFP_KERNEL, 1);
|
||||
sid, SECSID_NULL, GFP_KERNEL, true);
|
||||
}
|
||||
|
||||
static int compute_sid_handle_invalid_context(
|
||||
|
||||
Reference in New Issue
Block a user