aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c17
-rw-r--r--security/keys/key.c14
-rw-r--r--security/keys/keyring.c4
-rw-r--r--security/keys/process_keys.c2
-rw-r--r--security/selinux/avc.c29
-rw-r--r--security/selinux/hooks.c202
-rw-r--r--security/selinux/include/av_inherit.h1
-rw-r--r--security/selinux/include/av_perm_to_string.h8
-rw-r--r--security/selinux/include/av_permissions.h32
-rw-r--r--security/selinux/include/avc.h8
-rw-r--r--security/selinux/include/avc_ss.h24
-rw-r--r--security/selinux/include/class_to_string.h2
-rw-r--r--security/selinux/include/flask.h2
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h4
-rw-r--r--security/selinux/include/selinux_netlabel.h53
-rw-r--r--security/selinux/include/xfrm.h28
-rw-r--r--security/selinux/nlmsgtab.c1
-rw-r--r--security/selinux/selinuxfs.c8
-rw-r--r--security/selinux/ss/avtab.c4
-rw-r--r--security/selinux/ss/ebitmap.c200
-rw-r--r--security/selinux/ss/ebitmap.h26
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/hashtab.h10
-rw-r--r--security/selinux/ss/mls.c143
-rw-r--r--security/selinux/ss/mls.h46
-rw-r--r--security/selinux/ss/policydb.c6
-rw-r--r--security/selinux/ss/services.c448
-rw-r--r--security/selinux/ss/symtab.c8
-rw-r--r--security/selinux/xfrm.c207
30 files changed, 816 insertions, 729 deletions
diff --git a/security/dummy.c b/security/dummy.c
index 43874c1e6e2..558795b237d 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(struct sock *newsk,
{
}
+static inline void dummy_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb)
+{
+}
+
static inline void dummy_req_classify_flow(const struct request_sock *req,
struct flowi *fl)
{
@@ -836,7 +841,7 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk)
+ struct xfrm_user_sec_ctx *sec_ctx)
{
return 0;
}
@@ -856,7 +861,7 @@ static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
}
static int dummy_xfrm_state_alloc_security(struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid)
+ struct xfrm_user_sec_ctx *sec_ctx, u32 secid)
{
return 0;
}
@@ -881,12 +886,6 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
return 1;
}
-static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
- struct xfrm_policy *xp)
-{
- return 1;
-}
-
static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
{
return 0;
@@ -1108,6 +1107,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, sock_graft);
set_to_dummy_if_null(ops, inet_conn_request);
set_to_dummy_if_null(ops, inet_csk_clone);
+ set_to_dummy_if_null(ops, inet_conn_established);
set_to_dummy_if_null(ops, req_classify_flow);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1120,7 +1120,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, xfrm_state_delete_security);
set_to_dummy_if_null(ops, xfrm_policy_lookup);
set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
- set_to_dummy_if_null(ops, xfrm_flow_state_match);
set_to_dummy_if_null(ops, xfrm_decode_session);
#endif /* CONFIG_SECURITY_NETWORK_XFRM */
#ifdef CONFIG_KEYS
diff --git a/security/keys/key.c b/security/keys/key.c
index 80de8c3e9cc..ac9326c5f1d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -20,7 +20,7 @@
#include <linux/err.h>
#include "internal.h"
-static kmem_cache_t *key_jar;
+static struct kmem_cache *key_jar;
struct rb_root key_serial_tree; /* tree of keys indexed by serial */
DEFINE_SPINLOCK(key_serial_lock);
@@ -30,8 +30,8 @@ DEFINE_SPINLOCK(key_user_lock);
static LIST_HEAD(key_types_list);
static DECLARE_RWSEM(key_types_sem);
-static void key_cleanup(void *data);
-static DECLARE_WORK(key_cleanup_task, key_cleanup, NULL);
+static void key_cleanup(struct work_struct *work);
+static DECLARE_WORK(key_cleanup_task, key_cleanup);
/* we serialise key instantiation and link */
DECLARE_RWSEM(key_construction_sem);
@@ -285,16 +285,14 @@ struct key *key_alloc(struct key_type *type, const char *desc,
}
/* allocate and initialise the key and its description */
- key = kmem_cache_alloc(key_jar, SLAB_KERNEL);
+ key = kmem_cache_alloc(key_jar, GFP_KERNEL);
if (!key)
goto no_memory_2;
if (desc) {
- key->description = kmalloc(desclen, GFP_KERNEL);
+ key->description = kmemdup(desc, desclen, GFP_KERNEL);
if (!key->description)
goto no_memory_3;
-
- memcpy(key->description, desc, desclen);
}
atomic_set(&key->usage, 1);
@@ -552,7 +550,7 @@ EXPORT_SYMBOL(key_negate_and_link);
* do cleaning up in process context so that we don't have to disable
* interrupts all over the place
*/
-static void key_cleanup(void *data)
+static void key_cleanup(struct work_struct *work)
{
struct rb_node *_n;
struct key *key;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e8d02acc51e..ad45ce73964 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -706,12 +706,10 @@ int __key_link(struct key *keyring, struct key *key)
BUG_ON(size > PAGE_SIZE);
ret = -ENOMEM;
- nklist = kmalloc(size, GFP_KERNEL);
+ nklist = kmemdup(klist, size, GFP_KERNEL);
if (!nklist)
goto error2;
- memcpy(nklist, klist, size);
-
/* replace matched key */
atomic_inc(&key->usage);
nklist->keys[loop] = key;
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 32150cf7c37..b6f86808475 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -27,7 +27,7 @@ static DEFINE_MUTEX(key_session_mutex);
struct key_user root_key_user = {
.usage = ATOMIC_INIT(3),
.consq = LIST_HEAD_INIT(root_key_user.consq),
- .lock = SPIN_LOCK_UNLOCKED,
+ .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
.nkeys = ATOMIC_INIT(2),
.nikeys = ATOMIC_INIT(2),
.uid = 0,
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index a300702da52..e7c0b5e2066 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -32,12 +32,7 @@
#include "avc.h"
#include "avc_ss.h"
-static const struct av_perm_to_string
-{
- u16 tclass;
- u32 value;
- const char *name;
-} av_perm_to_string[] = {
+static const struct av_perm_to_string av_perm_to_string[] = {
#define S_(c, v, s) { c, v, s },
#include "av_perm_to_string.h"
#undef S_
@@ -57,17 +52,21 @@ static const char *class_to_string[] = {
#undef TE_
#undef S_
-static const struct av_inherit
-{
- u16 tclass;
- const char **common_pts;
- u32 common_base;
-} av_inherit[] = {
+static const struct av_inherit av_inherit[] = {
#define S_(c, i, b) { c, common_##i##_perm_to_string, b },
#include "av_inherit.h"
#undef S_
};
+const struct selinux_class_perm selinux_class_perm = {
+ av_perm_to_string,
+ ARRAY_SIZE(av_perm_to_string),
+ class_to_string,
+ ARRAY_SIZE(class_to_string),
+ av_inherit,
+ ARRAY_SIZE(av_inherit)
+};
+
#define AVC_CACHE_SLOTS 512
#define AVC_DEF_CACHE_THRESHOLD 512
#define AVC_CACHE_RECLAIM 16
@@ -125,7 +124,7 @@ DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 };
static struct avc_cache avc_cache;
static struct avc_callback_node *avc_callbacks;
-static kmem_cache_t *avc_node_cachep;
+static struct kmem_cache *avc_node_cachep;
static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
{
@@ -333,7 +332,7 @@ static struct avc_node *avc_alloc_node(void)
{
struct avc_node *node;
- node = kmem_cache_alloc(avc_node_cachep, SLAB_ATOMIC);
+ node = kmem_cache_alloc(avc_node_cachep, GFP_ATOMIC);
if (!node)
goto out;
@@ -497,7 +496,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
audit_log_format(ab, " %s=%d", name2, ntohs(port));
}
-static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr,
+static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
__be16 port, char *name1, char *name2)
{
if (addr)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e9969a2fc84..65fb5e8ea94 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -58,6 +58,7 @@
#include <linux/netlink.h>
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <linux/dccp.h>
#include <linux/quota.h>
#include <linux/un.h> /* for Unix socket types */
#include <net/af_unix.h> /* for Unix socket types */
@@ -123,7 +124,7 @@ static struct security_operations *secondary_ops = NULL;
static LIST_HEAD(superblock_security_head);
static DEFINE_SPINLOCK(sb_security_lock);
-static kmem_cache_t *sel_inode_cache;
+static struct kmem_cache *sel_inode_cache;
/* Return security context for a given sid or just the context
length if the buffer is null or length is 0 */
@@ -180,7 +181,7 @@ static int inode_alloc_security(struct inode *inode)
struct task_security_struct *tsec = current->security;
struct inode_security_struct *isec;
- isec = kmem_cache_alloc(sel_inode_cache, SLAB_KERNEL);
+ isec = kmem_cache_alloc(sel_inode_cache, GFP_KERNEL);
if (!isec)
return -ENOMEM;
@@ -751,6 +752,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
return SECCLASS_UDP_SOCKET;
else
return SECCLASS_RAWIP_SOCKET;
+ case SOCK_DCCP:
+ return SECCLASS_DCCP_SOCKET;
default:
return SECCLASS_RAWIP_SOCKET;
}
@@ -1117,8 +1120,8 @@ static int file_has_perm(struct task_struct *tsk,
{
struct task_security_struct *tsec = tsk->security;
struct file_security_struct *fsec = file->f_security;
- struct vfsmount *mnt = file->f_vfsmnt;
- struct dentry *dentry = file->f_dentry;
+ struct vfsmount *mnt = file->f_path.mnt;
+ struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct avc_audit_data ad;
int rc;
@@ -1578,7 +1581,7 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
static int selinux_bprm_set_security(struct linux_binprm *bprm)
{
struct task_security_struct *tsec;
- struct inode *inode = bprm->file->f_dentry->d_inode;
+ struct inode *inode = bprm->file->f_path.dentry->d_inode;
struct inode_security_struct *isec;
struct bprm_security_struct *bsec;
u32 newsid;
@@ -1618,10 +1621,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
}
AVC_AUDIT_DATA_INIT(&ad, FS);
- ad.u.fs.mnt = bprm->file->f_vfsmnt;
- ad.u.fs.dentry = bprm->file->f_dentry;
+ ad.u.fs.mnt = bprm->file->f_path.mnt;
+ ad.u.fs.dentry = bprm->file->f_path.dentry;
- if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)
+ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
newsid = tsec->sid;
if (tsec->sid == newsid) {
@@ -1692,9 +1695,10 @@ static inline void flush_unauthorized_files(struct files_struct * files)
struct tty_struct *tty;
struct fdtable *fdt;
long j = -1;
+ int drop_tty = 0;
mutex_lock(&tty_mutex);
- tty = current->signal->tty;
+ tty = get_current_tty();
if (tty) {
file_list_lock();
file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
@@ -1704,15 +1708,17 @@ static inline void flush_unauthorized_files(struct files_struct * files)
than using file_has_perm, as this particular open
file may belong to another process and we are only
interested in the inode-based check here. */
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
if (inode_has_perm(current, inode,
FILE__READ | FILE__WRITE, NULL)) {
- /* Reset controlling tty. */
- current->signal->tty = NULL;
- current->signal->tty_old_pgrp = 0;
+ drop_tty = 1;
}
}
file_list_unlock();
+
+ /* Reset controlling tty. */
+ if (drop_tty)
+ proc_set_tty(current, NULL);
}
mutex_unlock(&tty_mutex);
@@ -1728,7 +1734,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
j++;
i = j * __NFDBITS;
fdt = files_fdtable(files);
- if (i >= fdt->max_fds || i >= fdt->max_fdset)
+ if (i >= fdt->max_fds)
break;
set = fdt->open_fds->fds_bits[j];
if (!set)
@@ -1754,7 +1760,8 @@ static inline void flush_unauthorized_files(struct files_struct * files)
get_file(devnull);
} else {
devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
- if (!devnull) {
+ if (IS_ERR(devnull)) {
+ devnull = NULL;
put_unused_fd(fd);
fput(file);
continue;
@@ -2413,7 +2420,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
static int selinux_file_permission(struct file *file, int mask)
{
int rc;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
if (!mask) {
/* No permission to check. Existence test. */
@@ -2590,7 +2597,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
switch (cmd) {
case F_SETFL:
- if (!file->f_dentry || !file->f_dentry->d_inode) {
+ if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
err = -EINVAL;
break;
}
@@ -2616,7 +2623,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
case F_SETLK64:
case F_SETLKW64:
#endif
- if (!file->f_dentry || !file->f_dentry->d_inode) {
+ if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
err = -EINVAL;
break;
}
@@ -2888,7 +2895,8 @@ static void selinux_task_to_inode(struct task_struct *p,
}
/* Returns error only if unable to parse addresses */
-static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
+static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ struct avc_audit_data *ad, u8 *proto)
{
int offset, ihlen, ret = -EINVAL;
struct iphdr _iph, *ih;
@@ -2906,6 +2914,9 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
ad->u.net.v4info.daddr = ih->daddr;
ret = 0;
+ if (proto)
+ *proto = ih->protocol;
+
switch (ih->protocol) {
case IPPROTO_TCP: {
struct tcphdr _tcph, *th;
@@ -2939,6 +2950,22 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
break;
}
+ case IPPROTO_DCCP: {
+ struct dccp_hdr _dccph, *dh;
+
+ if (ntohs(ih->frag_off) & IP_OFFSET)
+ break;
+
+ offset += ihlen;
+ dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
+ if (dh == NULL)
+ break;
+
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+ }
+
default:
break;
}
@@ -2949,7 +2976,8 @@ out:
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
/* Returns error only if unable to parse addresses */
-static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad)
+static int selinux_parse_skb_ipv6(struct sk_buff *skb,
+ struct avc_audit_data *ad, u8 *proto)
{
u8 nexthdr;
int ret = -EINVAL, offset;
@@ -2970,6 +2998,9 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
if (offset < 0)
goto out;
+ if (proto)
+ *proto = nexthdr;
+
switch (nexthdr) {
case IPPROTO_TCP: {
struct tcphdr _tcph, *th;
@@ -2995,6 +3026,18 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
break;
}
+ case IPPROTO_DCCP: {
+ struct dccp_hdr _dccph, *dh;
+
+ dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
+ if (dh == NULL)
+ break;
+
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+ }
+
/* includes fragments */
default:
break;
@@ -3006,13 +3049,13 @@ out:
#endif /* IPV6 */
static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
- char **addrp, int *len, int src)
+ char **addrp, int *len, int src, u8 *proto)
{
int ret = 0;
switch (ad->u.net.family) {
case PF_INET:
- ret = selinux_parse_skb_ipv4(skb, ad);
+ ret = selinux_parse_skb_ipv4(skb, ad, proto);
if (ret || !addrp)
break;
*len = 4;
@@ -3022,7 +3065,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case PF_INET6:
- ret = selinux_parse_skb_ipv6(skb, ad);
+ ret = selinux_parse_skb_ipv6(skb, ad, proto);
if (ret || !addrp)
break;
*len = 16;
@@ -3100,9 +3143,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
if (sock->sk) {
sksec = sock->sk->sk_security;
sksec->sid = isec->sid;
- err = selinux_netlbl_socket_post_create(sock,
- family,
- isec->sid);
+ err = selinux_netlbl_socket_post_create(sock);
}
return err;
@@ -3179,7 +3220,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
case SECCLASS_UDP_SOCKET:
node_perm = UDP_SOCKET__NODE_BIND;
break;
-
+
+ case SECCLASS_DCCP_SOCKET:
+ node_perm = DCCP_SOCKET__NODE_BIND;
+ break;
+
default:
node_perm = RAWIP_SOCKET__NODE_BIND;
break;
@@ -3217,16 +3262,17 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
return err;
/*
- * If a TCP socket, check name_connect permission for the port.
+ * If a TCP or DCCP socket, check name_connect permission for the port.
*/
isec = SOCK_INODE(sock)->i_security;
- if (isec->sclass == SECCLASS_TCP_SOCKET) {
+ if (isec->sclass == SECCLASS_TCP_SOCKET ||
+ isec->sclass == SECCLASS_DCCP_SOCKET) {
struct sock *sk = sock->sk;
struct avc_audit_data ad;
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
unsigned short snum;
- u32 sid;
+ u32 sid, perm;
if (sk->sk_family == PF_INET) {
addr4 = (struct sockaddr_in *)address;
@@ -3245,11 +3291,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
if (err)
goto out;
+ perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
+ TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
+
AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.dport = htons(snum);
ad.u.net.family = sk->sk_family;
- err = avc_has_perm(isec->sid, sid, isec->sclass,
- TCP_SOCKET__NAME_CONNECT, &ad);
+ err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
if (err)
goto out;
}
@@ -3313,7 +3361,13 @@ static int selinux_socket_getpeername(struct socket *sock)
static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
{
- return socket_has_perm(current, sock, SOCKET__SETOPT);
+ int err;
+
+ err = socket_has_perm(current, sock, SOCKET__SETOPT);
+ if (err)
+ return err;
+
+ return selinux_netlbl_socket_setsockopt(sock, level, optname);
}
static int selinux_socket_getsockopt(struct socket *sock, int level,
@@ -3431,7 +3485,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
node_perm = NODE__TCP_RECV;
recv_perm = TCP_SOCKET__RECV_MSG;
break;
-
+
+ case SECCLASS_DCCP_SOCKET:
+ netif_perm = NETIF__DCCP_RECV;
+ node_perm = NODE__DCCP_RECV;
+ recv_perm = DCCP_SOCKET__RECV_MSG;
+ break;
+
default:
netif_perm = NETIF__RAWIP_RECV;
node_perm = NODE__RAWIP_RECV;
@@ -3480,14 +3540,14 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
goto out;
/* Handle mapped IPv4 packets arriving via IPv6 sockets */
- if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
+ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
family = PF_INET;
AVC_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
ad.u.net.family = family;
- err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
if (err)
goto out;
@@ -3517,25 +3577,16 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
u32 scontext_len;
struct sk_security_struct *ssec;
struct inode_security_struct *isec;
- u32 peer_sid = 0;
+ u32 peer_sid = SECSID_NULL;
isec = SOCK_INODE(sock)->i_security;
- /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */
- if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) {
+ if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
+ isec->sclass == SECCLASS_TCP_SOCKET) {
ssec = sock->sk->sk_security;
peer_sid = ssec->peer_sid;
}
- else if (isec->sclass == SECCLASS_TCP_SOCKET) {
- peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
- if (peer_sid == SECSID_NULL)
- peer_sid = selinux_socket_getpeer_stream(sock->sk);
- if (peer_sid == SECSID_NULL) {
- err = -ENOPROTOOPT;
- goto out;
- }
- }
- else {
+ if (peer_sid == SECSID_NULL) {
err = -ENOPROTOOPT;
goto out;
}
@@ -3567,13 +3618,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
u32 peer_secid = SECSID_NULL;
int err = 0;
- if (sock && (sock->sk->sk_family == PF_UNIX))
+ if (sock && sock->sk->sk_family == PF_UNIX)
selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
- else if (skb) {
- peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb);
- if (peer_secid == SECSID_NULL)
- peer_secid = selinux_socket_getpeer_dgram(skb);
- }
+ else if (skb)
+ security_skb_extlbl_sid(skb,
+ SECINITSID_UNLABELED,
+ &peer_secid);
if (peer_secid == SECSID_NULL)
err = -EINVAL;
@@ -3600,7 +3650,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
newssec->sid = ssec->sid;
newssec->peer_sid = ssec->peer_sid;
- selinux_netlbl_sk_clone_security(ssec, newssec);
+ selinux_netlbl_sk_security_clone(ssec, newssec);
}
static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -3634,17 +3684,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
u32 newsid;
u32 peersid;
- newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid);
- if (newsid != SECSID_NULL) {
- req->secid = newsid;
- return 0;
- }
-
- err = selinux_xfrm_decode_session(skb, &peersid, 0);
- BUG_ON(err);
-
+ security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid);
if (peersid == SECSID_NULL) {
req->secid = sksec->sid;
+ req->peer_secid = SECSID_NULL;
return 0;
}
@@ -3653,6 +3696,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
return err;
req->secid = newsid;
+ req->peer_secid = peersid;
return 0;
}
@@ -3662,12 +3706,23 @@ static void selinux_inet_csk_clone(struct sock *newsk,
struct sk_security_struct *newsksec = newsk->sk_security;
newsksec->sid = req->secid;
+ newsksec->peer_sid = req->peer_secid;
/* NOTE: Ideally, we should also get the isec->sid for the
new socket in sync, but we don't have the isec available yet.
So we will wait until sock_graft to do it, by which
time it will have been created and available. */
- selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family);
+ /* We don't need to take any sort of lock here as we are the only
+ * thread with access to newsksec */
+ selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
+}
+
+static void selinux_inet_conn_established(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct sk_security_struct *sksec = sk->sk_security;
+
+ security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid);
}
static void selinux_req_classify_flow(const struct request_sock *req,
@@ -3750,7 +3805,13 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *
node_perm = NODE__TCP_SEND;
send_perm = TCP_SOCKET__SEND_MSG;
break;
-
+
+ case SECCLASS_DCCP_SOCKET:
+ netif_perm = NETIF__DCCP_SEND;
+ node_perm = NODE__DCCP_SEND;
+ send_perm = DCCP_SOCKET__SEND_MSG;
+ break;
+
default:
netif_perm = NETIF__RAWIP_SEND;
node_perm = NODE__RAWIP_SEND;
@@ -3801,6 +3862,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
struct avc_audit_data ad;
struct net_device *dev = (struct net_device *)out;
struct sk_security_struct *sksec;
+ u8 proto;
sk = skb->sk;
if (!sk)
@@ -3812,7 +3874,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
ad.u.net.netif = dev->name;
ad.u.net.family = family;
- err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+ err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto);
if (err)
goto out;
@@ -3826,7 +3888,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
if (err)
goto out;
- err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad);
+ err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto);
out:
return err ? NF_DROP : NF_ACCEPT;
}
@@ -4732,6 +4794,7 @@ static struct security_operations selinux_ops = {
.sock_graft = selinux_sock_graft,
.inet_conn_request = selinux_inet_conn_request,
.inet_csk_clone = selinux_inet_csk_clone,
+ .inet_conn_established = selinux_inet_conn_established,
.req_classify_flow = selinux_req_classify_flow,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -4744,7 +4807,6 @@ static struct security_operations selinux_ops = {
.xfrm_state_delete_security = selinux_xfrm_state_delete,
.xfrm_policy_lookup = selinux_xfrm_policy_lookup,
.xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
- .xfrm_flow_state_match = selinux_xfrm_flow_state_match,
.xfrm_decode_session = selinux_xfrm_decode_session,
#endif
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h
index a68fdd55597..8377a4ba3b9 100644
--- a/security/selinux/include/av_inherit.h
+++ b/security/selinux/include/av_inherit.h
@@ -30,3 +30,4 @@
S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
+ S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL)
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 09fc8a2345e..ad9fb2d69b5 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -35,12 +35,16 @@
S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv")
S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send")
S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest")
+ S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv")
+ S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send")
S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv")
S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")
S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv")
S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send")
S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv")
S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send")
+ S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv")
+ S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom")
@@ -252,3 +256,7 @@
S_(SECCLASS_KEY, KEY__LINK, "link")
S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
S_(SECCLASS_KEY, KEY__CREATE, "create")
+ S_(SECCLASS_CONTEXT, CONTEXT__TRANSLATE, "translate")
+ S_(SECCLASS_CONTEXT, CONTEXT__CONTAINS, "contains")
+ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
+ S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 81f4f526c8b..2de4b5fe3aa 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -312,6 +312,8 @@
#define NODE__RAWIP_RECV 0x00000010UL
#define NODE__RAWIP_SEND 0x00000020UL
#define NODE__ENFORCE_DEST 0x00000040UL
+#define NODE__DCCP_RECV 0x00000080UL
+#define NODE__DCCP_SEND 0x00000100UL
#define NETIF__TCP_RECV 0x00000001UL
#define NETIF__TCP_SEND 0x00000002UL
@@ -319,6 +321,8 @@
#define NETIF__UDP_SEND 0x00000008UL
#define NETIF__RAWIP_RECV 0x00000010UL
#define NETIF__RAWIP_SEND 0x00000020UL
+#define NETIF__DCCP_RECV 0x00000040UL
+#define NETIF__DCCP_SEND 0x00000080UL
#define NETLINK_SOCKET__IOCTL 0x00000001UL
#define NETLINK_SOCKET__READ 0x00000002UL
@@ -970,3 +974,31 @@
#define KEY__LINK 0x00000010UL
#define KEY__SETATTR 0x00000020UL
#define KEY__CREATE 0x00000040UL
+
+#define CONTEXT__TRANSLATE 0x00000001UL
+#define CONTEXT__CONTAINS 0x00000002UL
+
+#define DCCP_SOCKET_