Merge branch 'master' of git://git.infradead.org/users/pcmoore/selinux into next
Conflicts: security/selinux/hooks.c Resolved using request struct. Signed-off-by: James Morris <james.l.morris@oracle.com>
This commit is contained in:
commit
d4a82a4a03
7 changed files with 164 additions and 39 deletions
|
@ -82,7 +82,6 @@
|
|||
#include <linux/syslog.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/msg.h>
|
||||
#include <linux/shm.h>
|
||||
|
||||
|
@ -4474,14 +4473,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|||
{
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
int err;
|
||||
u16 family = sk->sk_family;
|
||||
u16 family = req->rsk_ops->family;
|
||||
u32 connsid;
|
||||
u32 peersid;
|
||||
|
||||
/* handle mapped IPv4 packets arriving via IPv6 sockets */
|
||||
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
|
||||
family = PF_INET;
|
||||
|
||||
err = selinux_skb_peerlbl_sid(skb, family, &peersid);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -33,13 +33,14 @@
|
|||
#define POLICYDB_VERSION_ROLETRANS 26
|
||||
#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
|
||||
#define POLICYDB_VERSION_DEFAULT_TYPE 28
|
||||
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
|
||||
|
||||
/* Range of policy versions we understand*/
|
||||
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
|
||||
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
||||
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
|
||||
#else
|
||||
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_DEFAULT_TYPE
|
||||
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_CONSTRAINT_NAMES
|
||||
#endif
|
||||
|
||||
/* Mask for just the mount related flags */
|
||||
|
|
|
@ -100,6 +100,32 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
|
|||
return secattr;
|
||||
}
|
||||
|
||||
/**
|
||||
* selinux_netlbl_sock_getattr - Get the cached NetLabel secattr
|
||||
* @sk: the socket
|
||||
* @sid: the SID
|
||||
*
|
||||
* Query the socket's cached secattr and if the SID matches the cached value
|
||||
* return the cache, otherwise return NULL.
|
||||
*
|
||||
*/
|
||||
static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
|
||||
const struct sock *sk,
|
||||
u32 sid)
|
||||
{
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
|
||||
|
||||
if (secattr == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((secattr->flags & NETLBL_SECATTR_SECID) &&
|
||||
(secattr->attr.secid == sid))
|
||||
return secattr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
|
||||
*
|
||||
|
@ -224,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
|
|||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
if (sksec->nlbl_state != NLBL_REQSKB)
|
||||
return 0;
|
||||
secattr = sksec->nlbl_secattr;
|
||||
secattr = selinux_netlbl_sock_getattr(sk, sid);
|
||||
}
|
||||
if (secattr == NULL) {
|
||||
secattr = &secattr_storage;
|
||||
|
@ -410,6 +436,9 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
|
|||
sksec->nlbl_state == NLBL_CONNLABELED)) {
|
||||
netlbl_secattr_init(&secattr);
|
||||
lock_sock(sk);
|
||||
/* call the netlabel function directly as we want to see the
|
||||
* on-the-wire label that is assigned via the socket's options
|
||||
* and not the cached netlabel/lsm attributes */
|
||||
rc = netlbl_sock_getattr(sk, &secattr);
|
||||
release_sock(sk);
|
||||
if (rc == 0)
|
||||
|
|
|
@ -48,6 +48,7 @@ struct constraint_expr {
|
|||
u32 op; /* operator */
|
||||
|
||||
struct ebitmap names; /* names */
|
||||
struct type_set *type_names;
|
||||
|
||||
struct constraint_expr *next; /* next expression */
|
||||
};
|
||||
|
|
|
@ -143,6 +143,11 @@ static struct policydb_compat_info policydb_compat[] = {
|
|||
.sym_num = SYM_NUM,
|
||||
.ocon_num = OCON_NUM,
|
||||
},
|
||||
{
|
||||
.version = POLICYDB_VERSION_CONSTRAINT_NAMES,
|
||||
.sym_num = SYM_NUM,
|
||||
.ocon_num = OCON_NUM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct policydb_compat_info *policydb_lookup_compat(int version)
|
||||
|
@ -613,6 +618,19 @@ static int common_destroy(void *key, void *datum, void *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void constraint_expr_destroy(struct constraint_expr *expr)
|
||||
{
|
||||
if (expr) {
|
||||
ebitmap_destroy(&expr->names);
|
||||
if (expr->type_names) {
|
||||
ebitmap_destroy(&expr->type_names->types);
|
||||
ebitmap_destroy(&expr->type_names->negset);
|
||||
kfree(expr->type_names);
|
||||
}
|
||||
kfree(expr);
|
||||
}
|
||||
}
|
||||
|
||||
static int cls_destroy(void *key, void *datum, void *p)
|
||||
{
|
||||
struct class_datum *cladatum;
|
||||
|
@ -628,10 +646,9 @@ static int cls_destroy(void *key, void *datum, void *p)
|
|||
while (constraint) {
|
||||
e = constraint->expr;
|
||||
while (e) {
|
||||
ebitmap_destroy(&e->names);
|
||||
etmp = e;
|
||||
e = e->next;
|
||||
kfree(etmp);
|
||||
constraint_expr_destroy(etmp);
|
||||
}
|
||||
ctemp = constraint;
|
||||
constraint = constraint->next;
|
||||
|
@ -642,16 +659,14 @@ static int cls_destroy(void *key, void *datum, void *p)
|
|||
while (constraint) {
|
||||
e = constraint->expr;
|
||||
while (e) {
|
||||
ebitmap_destroy(&e->names);
|
||||
etmp = e;
|
||||
e = e->next;
|
||||
kfree(etmp);
|
||||
constraint_expr_destroy(etmp);
|
||||
}
|
||||
ctemp = constraint;
|
||||
constraint = constraint->next;
|
||||
kfree(ctemp);
|
||||
}
|
||||
|
||||
kfree(cladatum->comkey);
|
||||
}
|
||||
kfree(datum);
|
||||
|
@ -1156,8 +1171,34 @@ bad:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int read_cons_helper(struct constraint_node **nodep, int ncons,
|
||||
int allowxtarget, void *fp)
|
||||
static void type_set_init(struct type_set *t)
|
||||
{
|
||||
ebitmap_init(&t->types);
|
||||
ebitmap_init(&t->negset);
|
||||
}
|
||||
|
||||
static int type_set_read(struct type_set *t, void *fp)
|
||||
{
|
||||
__le32 buf[1];
|
||||
int rc;
|
||||
|
||||
if (ebitmap_read(&t->types, fp))
|
||||
return -EINVAL;
|
||||
if (ebitmap_read(&t->negset, fp))
|
||||
return -EINVAL;
|
||||
|
||||
rc = next_entry(buf, fp, sizeof(u32));
|
||||
if (rc < 0)
|
||||
return -EINVAL;
|
||||
t->flags = le32_to_cpu(buf[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int read_cons_helper(struct policydb *p,
|
||||
struct constraint_node **nodep,
|
||||
int ncons, int allowxtarget, void *fp)
|
||||
{
|
||||
struct constraint_node *c, *lc;
|
||||
struct constraint_expr *e, *le;
|
||||
|
@ -1225,6 +1266,18 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
|
|||
rc = ebitmap_read(&e->names, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (p->policyvers >=
|
||||
POLICYDB_VERSION_CONSTRAINT_NAMES) {
|
||||
e->type_names = kzalloc(sizeof
|
||||
(*e->type_names),
|
||||
GFP_KERNEL);
|
||||
if (!e->type_names)
|
||||
return -ENOMEM;
|
||||
type_set_init(e->type_names);
|
||||
rc = type_set_read(e->type_names, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -1301,7 +1354,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
|
|||
goto bad;
|
||||
}
|
||||
|
||||
rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
|
||||
rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);
|
||||
if (rc)
|
||||
goto bad;
|
||||
|
||||
|
@ -1311,7 +1364,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
|
|||
if (rc)
|
||||
goto bad;
|
||||
ncons = le32_to_cpu(buf[0]);
|
||||
rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
|
||||
rc = read_cons_helper(p, &cladatum->validatetrans,
|
||||
ncons, 1, fp);
|
||||
if (rc)
|
||||
goto bad;
|
||||
}
|
||||
|
@ -2753,6 +2807,24 @@ static int common_write(void *vkey, void *datum, void *ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int type_set_write(struct type_set *t, void *fp)
|
||||
{
|
||||
int rc;
|
||||
__le32 buf[1];
|
||||
|
||||
if (ebitmap_write(&t->types, fp))
|
||||
return -EINVAL;
|
||||
if (ebitmap_write(&t->negset, fp))
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = cpu_to_le32(t->flags);
|
||||
rc = put_entry(buf, sizeof(u32), 1, fp);
|
||||
if (rc)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_cons_helper(struct policydb *p, struct constraint_node *node,
|
||||
void *fp)
|
||||
{
|
||||
|
@ -2784,6 +2856,12 @@ static int write_cons_helper(struct policydb *p, struct constraint_node *node,
|
|||
rc = ebitmap_write(&e->names, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (p->policyvers >=
|
||||
POLICYDB_VERSION_CONSTRAINT_NAMES) {
|
||||
rc = type_set_write(e->type_names, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -153,6 +153,17 @@ struct cond_bool_datum {
|
|||
|
||||
struct cond_node;
|
||||
|
||||
/*
|
||||
* type set preserves data needed to determine constraint info from
|
||||
* policy source. This is not used by the kernel policy but allows
|
||||
* utilities such as audit2allow to determine constraint denials.
|
||||
*/
|
||||
struct type_set {
|
||||
struct ebitmap types;
|
||||
struct ebitmap negset;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* The configuration data includes security contexts for
|
||||
* initial SIDs, unlabeled file systems, TCP and UDP port numbers,
|
||||
|
|
|
@ -1831,7 +1831,7 @@ static int security_preserve_bools(struct policydb *p);
|
|||
*/
|
||||
int security_load_policy(void *data, size_t len)
|
||||
{
|
||||
struct policydb oldpolicydb, newpolicydb;
|
||||
struct policydb *oldpolicydb, *newpolicydb;
|
||||
struct sidtab oldsidtab, newsidtab;
|
||||
struct selinux_mapping *oldmap, *map = NULL;
|
||||
struct convert_context_args args;
|
||||
|
@ -1840,12 +1840,19 @@ int security_load_policy(void *data, size_t len)
|
|||
int rc = 0;
|
||||
struct policy_file file = { data, len }, *fp = &file;
|
||||
|
||||
oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
|
||||
if (!oldpolicydb) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
newpolicydb = oldpolicydb + 1;
|
||||
|
||||
if (!ss_initialized) {
|
||||
avtab_cache_init();
|
||||
rc = policydb_read(&policydb, fp);
|
||||
if (rc) {
|
||||
avtab_cache_destroy();
|
||||
return rc;
|
||||
goto out;
|
||||
}
|
||||
|
||||
policydb.len = len;
|
||||
|
@ -1855,14 +1862,14 @@ int security_load_policy(void *data, size_t len)
|
|||
if (rc) {
|
||||
policydb_destroy(&policydb);
|
||||
avtab_cache_destroy();
|
||||
return rc;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = policydb_load_isids(&policydb, &sidtab);
|
||||
if (rc) {
|
||||
policydb_destroy(&policydb);
|
||||
avtab_cache_destroy();
|
||||
return rc;
|
||||
goto out;
|
||||
}
|
||||
|
||||
security_load_policycaps();
|
||||
|
@ -1874,36 +1881,36 @@ int security_load_policy(void *data, size_t len)
|
|||
selinux_status_update_policyload(seqno);
|
||||
selinux_netlbl_cache_invalidate();
|
||||
selinux_xfrm_notify_policyload();
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if 0
|
||||
sidtab_hash_eval(&sidtab, "sids");
|
||||
#endif
|
||||
|
||||
rc = policydb_read(&newpolicydb, fp);
|
||||
rc = policydb_read(newpolicydb, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
newpolicydb.len = len;
|
||||
newpolicydb->len = len;
|
||||
/* If switching between different policy types, log MLS status */
|
||||
if (policydb.mls_enabled && !newpolicydb.mls_enabled)
|
||||
if (policydb.mls_enabled && !newpolicydb->mls_enabled)
|
||||
printk(KERN_INFO "SELinux: Disabling MLS support...\n");
|
||||
else if (!policydb.mls_enabled && newpolicydb.mls_enabled)
|
||||
else if (!policydb.mls_enabled && newpolicydb->mls_enabled)
|
||||
printk(KERN_INFO "SELinux: Enabling MLS support...\n");
|
||||
|
||||
rc = policydb_load_isids(&newpolicydb, &newsidtab);
|
||||
rc = policydb_load_isids(newpolicydb, &newsidtab);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "SELinux: unable to load the initial SIDs\n");
|
||||
policydb_destroy(&newpolicydb);
|
||||
return rc;
|
||||
policydb_destroy(newpolicydb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size);
|
||||
rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
rc = security_preserve_bools(&newpolicydb);
|
||||
rc = security_preserve_bools(newpolicydb);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "SELinux: unable to preserve booleans\n");
|
||||
goto err;
|
||||
|
@ -1921,7 +1928,7 @@ int security_load_policy(void *data, size_t len)
|
|||
* in the new SID table.
|
||||
*/
|
||||
args.oldp = &policydb;
|
||||
args.newp = &newpolicydb;
|
||||
args.newp = newpolicydb;
|
||||
rc = sidtab_map(&newsidtab, convert_context, &args);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "SELinux: unable to convert the internal"
|
||||
|
@ -1931,12 +1938,12 @@ int security_load_policy(void *data, size_t len)
|
|||
}
|
||||
|
||||
/* Save the old policydb and SID table to free later. */
|
||||
memcpy(&oldpolicydb, &policydb, sizeof policydb);
|
||||
memcpy(oldpolicydb, &policydb, sizeof(policydb));
|
||||
sidtab_set(&oldsidtab, &sidtab);
|
||||
|
||||
/* Install the new policydb and SID table. */
|
||||
write_lock_irq(&policy_rwlock);
|
||||
memcpy(&policydb, &newpolicydb, sizeof policydb);
|
||||
memcpy(&policydb, newpolicydb, sizeof(policydb));
|
||||
sidtab_set(&sidtab, &newsidtab);
|
||||
security_load_policycaps();
|
||||
oldmap = current_mapping;
|
||||
|
@ -1946,7 +1953,7 @@ int security_load_policy(void *data, size_t len)
|
|||
write_unlock_irq(&policy_rwlock);
|
||||
|
||||
/* Free the old policydb and SID table. */
|
||||
policydb_destroy(&oldpolicydb);
|
||||
policydb_destroy(oldpolicydb);
|
||||
sidtab_destroy(&oldsidtab);
|
||||
kfree(oldmap);
|
||||
|
||||
|
@ -1956,14 +1963,17 @@ int security_load_policy(void *data, size_t len)
|
|||
selinux_netlbl_cache_invalidate();
|
||||
selinux_xfrm_notify_policyload();
|
||||
|
||||
return 0;
|
||||
rc = 0;
|
||||
goto out;
|
||||
|
||||
err:
|
||||
kfree(map);
|
||||
sidtab_destroy(&newsidtab);
|
||||
policydb_destroy(&newpolicydb);
|
||||
return rc;
|
||||
policydb_destroy(newpolicydb);
|
||||
|
||||
out:
|
||||
kfree(oldpolicydb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
size_t security_policydb_len(void)
|
||||
|
|
Loading…
Reference in a new issue