aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/security.h25
-rw-r--r--net/socket.c13
-rw-r--r--security/dummy.c6
-rw-r--r--security/selinux/hooks.c56
-rw-r--r--security/selinux/include/objsec.h8
-rw-r--r--security/selinux/include/selinux_netlabel.h125
-rw-r--r--security/selinux/ss/ebitmap.c144
-rw-r--r--security/selinux/ss/ebitmap.h6
-rw-r--r--security/selinux/ss/mls.c156
-rw-r--r--security/selinux/ss/mls.h21
-rw-r--r--security/selinux/ss/services.c488
11 files changed, 1020 insertions, 28 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index bb4c80fdfe7a..9f56fb8a4a6c 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1341,8 +1341,8 @@ struct security_operations {
1341 int (*unix_may_send) (struct socket * sock, struct socket * other); 1341 int (*unix_may_send) (struct socket * sock, struct socket * other);
1342 1342
1343 int (*socket_create) (int family, int type, int protocol, int kern); 1343 int (*socket_create) (int family, int type, int protocol, int kern);
1344 void (*socket_post_create) (struct socket * sock, int family, 1344 int (*socket_post_create) (struct socket * sock, int family,
1345 int type, int protocol, int kern); 1345 int type, int protocol, int kern);
1346 int (*socket_bind) (struct socket * sock, 1346 int (*socket_bind) (struct socket * sock,
1347 struct sockaddr * address, int addrlen); 1347 struct sockaddr * address, int addrlen);
1348 int (*socket_connect) (struct socket * sock, 1348 int (*socket_connect) (struct socket * sock,
@@ -2824,13 +2824,13 @@ static inline int security_socket_create (int family, int type,
2824 return security_ops->socket_create(family, type, protocol, kern); 2824 return security_ops->socket_create(family, type, protocol, kern);
2825} 2825}
2826 2826
2827static inline void security_socket_post_create(struct socket * sock, 2827static inline int security_socket_post_create(struct socket * sock,
2828 int family, 2828 int family,
2829 int type, 2829 int type,
2830 int protocol, int kern) 2830 int protocol, int kern)
2831{ 2831{
2832 security_ops->socket_post_create(sock, family, type, 2832 return security_ops->socket_post_create(sock, family, type,
2833 protocol, kern); 2833 protocol, kern);
2834} 2834}
2835 2835
2836static inline int security_socket_bind(struct socket * sock, 2836static inline int security_socket_bind(struct socket * sock,
@@ -2982,11 +2982,12 @@ static inline int security_socket_create (int family, int type,
2982 return 0; 2982 return 0;
2983} 2983}
2984 2984
2985static inline void security_socket_post_create(struct socket * sock, 2985static inline int security_socket_post_create(struct socket * sock,
2986 int family, 2986 int family,
2987 int type, 2987 int type,
2988 int protocol, int kern) 2988 int protocol, int kern)
2989{ 2989{
2990 return 0;
2990} 2991}
2991 2992
2992static inline int security_socket_bind(struct socket * sock, 2993static inline int security_socket_bind(struct socket * sock,
diff --git a/net/socket.c b/net/socket.c
index 6d261bf206fc..6756e57e1ff0 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -973,11 +973,18 @@ int sock_create_lite(int family, int type, int protocol, struct socket **res)
973 goto out; 973 goto out;
974 } 974 }
975 975
976 security_socket_post_create(sock, family, type, protocol, 1);
977 sock->type = type; 976 sock->type = type;
977 err = security_socket_post_create(sock, family, type, protocol, 1);
978 if (err)
979 goto out_release;
980
978out: 981out:
979 *res = sock; 982 *res = sock;
980 return err; 983 return err;
984out_release:
985 sock_release(sock);
986 sock = NULL;
987 goto out;
981} 988}
982 989
983/* No kernel lock held - perfect */ 990/* No kernel lock held - perfect */
@@ -1214,7 +1221,9 @@ static int __sock_create(int family, int type, int protocol, struct socket **res
1214 */ 1221 */
1215 module_put(net_families[family]->owner); 1222 module_put(net_families[family]->owner);
1216 *res = sock; 1223 *res = sock;
1217 security_socket_post_create(sock, family, type, protocol, kern); 1224 err = security_socket_post_create(sock, family, type, protocol, kern);
1225 if (err)
1226 goto out_release;
1218 1227
1219out: 1228out:
1220 net_family_read_unlock(); 1229 net_family_read_unlock();
diff --git a/security/dummy.c b/security/dummy.c
index 1c45f8e4aad1..aeee70565509 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -709,10 +709,10 @@ static int dummy_socket_create (int family, int type,
709 return 0; 709 return 0;
710} 710}
711 711
712static void dummy_socket_post_create (struct socket *sock, int family, int type, 712static int dummy_socket_post_create (struct socket *sock, int family, int type,
713 int protocol, int kern) 713 int protocol, int kern)
714{ 714{
715 return; 715 return 0;
716} 716}
717 717
718static int dummy_socket_bind (struct socket *sock, struct sockaddr *address, 718static int dummy_socket_bind (struct socket *sock, struct sockaddr *address,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 33028b3b19ce..2a6bbb921e1e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -12,6 +12,8 @@
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com> 14 * <dgoeddel@trustedcs.com>
15 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
16 * Paul Moore, <paul.moore@hp.com>
15 * 17 *
16 * This program is free software; you can redistribute it and/or modify 18 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2, 19 * it under the terms of the GNU General Public License version 2,
@@ -74,6 +76,7 @@
74#include "objsec.h" 76#include "objsec.h"
75#include "netif.h" 77#include "netif.h"
76#include "xfrm.h" 78#include "xfrm.h"
79#include "selinux_netlabel.h"
77 80
78#define XATTR_SELINUX_SUFFIX "selinux" 81#define XATTR_SELINUX_SUFFIX "selinux"
79#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX 82#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
@@ -2395,6 +2398,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
2395 2398
2396static int selinux_file_permission(struct file *file, int mask) 2399static int selinux_file_permission(struct file *file, int mask)
2397{ 2400{
2401 int rc;
2398 struct inode *inode = file->f_dentry->d_inode; 2402 struct inode *inode = file->f_dentry->d_inode;
2399 2403
2400 if (!mask) { 2404 if (!mask) {
@@ -2406,8 +2410,12 @@ static int selinux_file_permission(struct file *file, int mask)
2406 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) 2410 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2407 mask |= MAY_APPEND; 2411 mask |= MAY_APPEND;
2408 2412
2409 return file_has_perm(current, file, 2413 rc = file_has_perm(current, file,
2410 file_mask_to_av(inode->i_mode, mask)); 2414 file_mask_to_av(inode->i_mode, mask));
2415 if (rc)
2416 return rc;
2417
2418 return selinux_netlbl_inode_permission(inode, mask);
2411} 2419}
2412 2420
2413static int selinux_file_alloc_security(struct file *file) 2421static int selinux_file_alloc_security(struct file *file)
@@ -3058,9 +3066,10 @@ out:
3058 return err; 3066 return err;
3059} 3067}
3060 3068
3061static void selinux_socket_post_create(struct socket *sock, int family, 3069static int selinux_socket_post_create(struct socket *sock, int family,
3062 int type, int protocol, int kern) 3070 int type, int protocol, int kern)
3063{ 3071{
3072 int err = 0;
3064 struct inode_security_struct *isec; 3073 struct inode_security_struct *isec;
3065 struct task_security_struct *tsec; 3074 struct task_security_struct *tsec;
3066 struct sk_security_struct *sksec; 3075 struct sk_security_struct *sksec;
@@ -3077,9 +3086,12 @@ static void selinux_socket_post_create(struct socket *sock, int family,
3077 if (sock->sk) { 3086 if (sock->sk) {
3078 sksec = sock->sk->sk_security; 3087 sksec = sock->sk->sk_security;
3079 sksec->sid = isec->sid; 3088 sksec->sid = isec->sid;
3089 err = selinux_netlbl_socket_post_create(sock,
3090 family,
3091 isec->sid);
3080 } 3092 }
3081 3093
3082 return; 3094 return err;
3083} 3095}
3084 3096
3085/* Range of port numbers used to automatically bind. 3097/* Range of port numbers used to automatically bind.
@@ -3260,7 +3272,13 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3260static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3272static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3261 int size) 3273 int size)
3262{ 3274{
3263 return socket_has_perm(current, sock, SOCKET__WRITE); 3275 int rc;
3276
3277 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3278 if (rc)
3279 return rc;
3280
3281 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
3264} 3282}
3265 3283
3266static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3284static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -3468,6 +3486,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3468 if (err) 3486 if (err)
3469 goto out; 3487 goto out;
3470 3488
3489 err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad);
3490 if (err)
3491 goto out;
3492
3471 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); 3493 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
3472out: 3494out:
3473 return err; 3495 return err;
@@ -3491,8 +3513,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
3491 peer_sid = ssec->peer_sid; 3513 peer_sid = ssec->peer_sid;
3492 } 3514 }
3493 else if (isec->sclass == SECCLASS_TCP_SOCKET) { 3515 else if (isec->sclass == SECCLASS_TCP_SOCKET) {
3494 peer_sid = selinux_socket_getpeer_stream(sock->sk); 3516 peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
3495 3517 if (peer_sid == SECSID_NULL)
3518 peer_sid = selinux_socket_getpeer_stream(sock->sk);
3496 if (peer_sid == SECSID_NULL) { 3519 if (peer_sid == SECSID_NULL) {
3497 err = -ENOPROTOOPT; 3520 err = -ENOPROTOOPT;
3498 goto out; 3521 goto out;
@@ -3532,8 +3555,11 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
3532 3555
3533 if (sock && (sock->sk->sk_family == PF_UNIX)) 3556 if (sock && (sock->sk->sk_family == PF_UNIX))
3534 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3557 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
3535 else if (skb) 3558 else if (skb) {
3536 peer_secid = selinux_socket_getpeer_dgram(skb); 3559 peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb);
3560 if (peer_secid == SECSID_NULL)
3561 peer_secid = selinux_socket_getpeer_dgram(skb);
3562 }
3537 3563
3538 if (peer_secid == SECSID_NULL) 3564 if (peer_secid == SECSID_NULL)
3539 err = -EINVAL; 3565 err = -EINVAL;
@@ -3578,6 +3604,8 @@ void selinux_sock_graft(struct sock* sk, struct socket *parent)
3578 struct sk_security_struct *sksec = sk->sk_security; 3604 struct sk_security_struct *sksec = sk->sk_security;
3579 3605
3580 isec->sid = sksec->sid; 3606 isec->sid = sksec->sid;
3607
3608 selinux_netlbl_sock_graft(sk, parent);
3581} 3609}
3582 3610
3583int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, 3611int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
@@ -3585,9 +3613,15 @@ int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3585{ 3613{
3586 struct sk_security_struct *sksec = sk->sk_security; 3614 struct sk_security_struct *sksec = sk->sk_security;
3587 int err; 3615 int err;
3588 u32 newsid = 0; 3616 u32 newsid;
3589 u32 peersid; 3617 u32 peersid;
3590 3618
3619 newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid);
3620 if (newsid != SECSID_NULL) {
3621 req->secid = newsid;
3622 return 0;
3623 }
3624
3591 err = selinux_xfrm_decode_session(skb, &peersid, 0); 3625 err = selinux_xfrm_decode_session(skb, &peersid, 0);
3592 BUG_ON(err); 3626 BUG_ON(err);
3593 3627
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 79b9e0af19a0..0a39bfd1319f 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -101,6 +101,14 @@ struct sk_security_struct {
101 struct sock *sk; /* back pointer to sk object */ 101 struct sock *sk; /* back pointer to sk object */
102 u32 sid; /* SID of this object */ 102 u32 sid; /* SID of this object */
103 u32 peer_sid; /* SID of peer */ 103 u32 peer_sid; /* SID of peer */
104#ifdef CONFIG_NETLABEL
105 u16 sclass; /* sock security class */
106 enum { /* NetLabel state */
107 NLBL_UNSET = 0,
108 NLBL_REQUIRE,
109 NLBL_LABELED,
110 } nlbl_state;
111#endif
104}; 112};
105 113
106struct key_security_struct { 114struct key_security_struct {
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h
new file mode 100644
index 000000000000..88c463eef1e1
--- /dev/null
+++ b/security/selinux/include/selinux_netlabel.h
@@ -0,0 +1,125 @@
1/*
2 * SELinux interface to the NetLabel subsystem
3 *
4 * Author : Paul Moore <paul.moore@hp.com>
5 *
6 */
7
8/*
9 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27#ifndef _SELINUX_NETLABEL_H_
28#define _SELINUX_NETLABEL_H_
29
30#ifdef CONFIG_NETLABEL
31void selinux_netlbl_cache_invalidate(void);
32int selinux_netlbl_socket_post_create(struct socket *sock,
33 int sock_family,
34 u32 sid);
35void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
36u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid);
37int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
38 struct sk_buff *skb,
39 struct avc_audit_data *ad);
40u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock);
41u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb);
42
43int __selinux_netlbl_inode_permission(struct inode *inode, int mask);
44/**
45 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
46 * @inode: the file descriptor's inode
47 * @mask: the permission mask
48 *
49 * Description:
50 * Looks at a file's inode and if it is marked as a socket protected by
51 * NetLabel then verify that the socket has been labeled, if not try to label
52 * the socket now with the inode's SID. Returns zero on success, negative
53 * values on failure.
54 *
55 */
56static inline int selinux_netlbl_inode_permission(struct inode *inode,
57 int mask)
58{
59 int rc = 0;
60 struct inode_security_struct *isec;
61 struct sk_security_struct *sksec;
62
63 if (!S_ISSOCK(inode->i_mode))
64 return 0;
65
66 isec = inode->i_security;
67 sksec = SOCKET_I(inode)->sk->sk_security;
68 down(&isec->sem);
69 if (unlikely(sksec->nlbl_state == NLBL_REQUIRE &&
70 (mask & (MAY_WRITE | MAY_APPEND))))
71 rc = __selinux_netlbl_inode_permission(inode, mask);
72 up(&isec->sem);
73
74 return rc;
75}
76#else
77static inline void selinux_netlbl_cache_invalidate(void)
78{
79 return;
80}
81
82static inline int selinux_netlbl_socket_post_create(struct socket *sock,
83 int sock_family,
84 u32 sid)
85{
86 return 0;
87}
88
89static inline void selinux_netlbl_sock_graft(struct sock *sk,
90 struct socket *sock)
91{
92 return;
93}
94
95static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb,
96 u32 sock_sid)
97{
98 return SECSID_NULL;
99}
100
101static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
102 struct sk_buff *skb,
103 struct avc_audit_data *ad)
104{
105 return 0;
106}
107
108static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
109{
110 return SECSID_NULL;
111}
112
113static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
114{
115 return SECSID_NULL;
116}
117
118static inline int selinux_netlbl_inode_permission(struct inode *inode,
119 int mask)
120{
121 return 0;
122}
123#endif /* CONFIG_NETLABEL */
124
125#endif
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 47024a6e1844..4b915eb60c45 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -3,6 +3,14 @@
3 * 3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil> 4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */ 5 */
6/*
7 * Updated: Hewlett-Packard <paul.moore@hp.com>
8 *
9 * Added ebitmap_export() and ebitmap_import()
10 *
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
12 */
13
6#include <linux/kernel.h> 14#include <linux/kernel.h>
7#include <linux/slab.h> 15#include <linux/slab.h>
8#include <linux/errno.h> 16#include <linux/errno.h>
@@ -59,6 +67,142 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
59 return 0; 67 return 0;
60} 68}
61 69
70/**
71 * ebitmap_export - Export an ebitmap to a unsigned char bitmap string
72 * @src: the ebitmap to export
73 * @dst: the resulting bitmap string
74 * @dst_len: length of dst in bytes
75 *
76 * Description:
77 * Allocate a buffer at least src->highbit bits long and export the extensible
78 * bitmap into the buffer. The bitmap string will be in little endian format,
79 * i.e. LSB first. The value returned in dst_len may not the true size of the
80 * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
81 * The caller must free the buffer when finished. Returns zero on success,
82 * negative values on failure.
83 *
84 */
85int ebitmap_export(const struct ebitmap *src,
86 unsigned char **dst,
87 size_t *dst_len)
88{
89 size_t bitmap_len;
90 unsigned char *bitmap;
91 struct ebitmap_node *iter_node;
92 MAPTYPE node_val;
93 size_t bitmap_byte;
94 unsigned char bitmask;
95
96 bitmap_len = src->highbit / 8;
97 if (src->highbit % 7)
98 bitmap_len += 1;
99 if (bitmap_len == 0)
100 return -EINVAL;
101
102 bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
103 sizeof(MAPTYPE),
104 GFP_ATOMIC);
105 if (bitmap == NULL)
106 return -ENOMEM;
107
108 iter_node = src->node;
109 do {
110 bitmap_byte = iter_node->startbit / 8;
111 bitmask = 0x80;
112 node_val = iter_node->map;
113 do {
114 if (bitmask == 0) {
115 bitmap_byte++;
116 bitmask = 0x80;
117 }
118 if (node_val & (MAPTYPE)0x01)
119 bitmap[bitmap_byte] |= bitmask;
120 node_val >>= 1;
121 bitmask >>= 1;
122 } while (node_val > 0);
123 iter_node = iter_node->next;
124 } while (iter_node);
125
126 *dst = bitmap;
127 *dst_len = bitmap_len;
128 return 0;
129}
130
131/**
132 * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
133 * @src: the bitmap string
134 * @src_len: the bitmap length in bytes
135 * @dst: the empty ebitmap
136 *
137 * Description:
138 * This function takes a little endian bitmap string in src and imports it into
139 * the ebitmap pointed to by dst. Returns zero on success, negative values on
140 * failure.
141 *
142 */
143int ebitmap_import(const unsigned char *src,
144 size_t src_len,
145 struct ebitmap *dst)
146{
147 size_t src_off = 0;
148 struct ebitmap_node *node_new;
149 struct ebitmap_node *node_last = NULL;
150 size_t iter;
151 size_t iter_bit;
152 size_t iter_limit;
153 unsigned char src_byte;
154
155 do {
156 iter_limit = src_len - src_off;
157 if (iter_limit >= sizeof(MAPTYPE)) {
158 if (*(MAPTYPE *)&src[src_off] == 0) {
159 src_off += sizeof(MAPTYPE);
160 continue;
161 }
162 iter_limit = sizeof(MAPTYPE);
163 } else {
164 iter = src_off;
165 src_byte = 0;
166 do {
167 src_byte |= src[iter++];
168 } while (iter < src_len && src_byte == 0);
169 if (src_byte == 0)
170 break;
171 }
172
173 node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC);
174 if (unlikely(node_new == NULL)) {
175 ebitmap_destroy(dst);
176 return -ENOMEM;
177 }
178 node_new->startbit = src_off * 8;
179 iter = 0;
180 do {
181 src_byte = src[src_off++];
182 iter_bit = iter++ * 8;
183 while (src_byte != 0) {
184 if (src_byte & 0x80)
185 node_new->map |= MAPBIT << iter_bit;
186 iter_bit++;
187 src_byte <<= 1;
188 }
189 } while (iter < iter_limit);
190
191 if (node_last != NULL)
192 node_last->next = node_new;
193 else
194 dst->node = node_new;
195 node_last = node_new;
196 } while (src_off < src_len);
197
198 if (likely(node_last != NULL))
199 dst->highbit = node_last->startbit + MAPSIZE;
200 else
201 ebitmap_init(dst);
202
203 return 0;
204}
205
62int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) 206int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
63{ 207{
64 struct ebitmap_node *n1, *n2; 208 struct ebitmap_node *n1, *n2;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 8bf41055a6cb..da2d4651b10d 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -69,6 +69,12 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
69 69
70int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); 70int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
71int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); 71int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
72int ebitmap_export(const struct ebitmap *src,
73 unsigned char **dst,
74 size_t *dst_len);
75int ebitmap_import(const unsigned char *src,
76 size_t src_len,
77 struct ebitmap *dst);
72int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); 78int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
73int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); 79int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
74int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); 80int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index e15f7e0399b8..119bd6078ba1 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -10,6 +10,13 @@
10 * 10 *
11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
12 */ 12 */
13/*
14 * Updated: Hewlett-Packard <paul.moore@hp.com>
15 *
16 * Added support to import/export the MLS label
17 *
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19 */
13 20
14#include <linux/kernel.h> 21#include <linux/kernel.h>
15#include <linux/slab.h> 22#include <linux/slab.h>
@@ -565,3 +572,152 @@ int mls_compute_sid(struct context *scontext,
565 return -EINVAL; 572 return -EINVAL;
566} 573}
567 574
575/**
576 * mls_export_lvl - Export the MLS sensitivity levels
577 * @context: the security context
578 * @low: the low sensitivity level
579 * @high: the high sensitivity level
580 *
581 * Description:
582 * Given the security context copy the low MLS sensitivity level into lvl_low
583 * and the high sensitivity level in lvl_high. The MLS levels are only
584 * exported if the pointers are not NULL, if they are NULL then that level is
585 * not exported.
586 *
587 */
588void mls_export_lvl(const struct context *context, u32 *low, u32 *high)
589{
590 if (!selinux_mls_enabled)
591 return;
592
593 if (low != NULL)
594 *low = context->range.level[0].sens - 1;
595 if (high != NULL)
596 *high = context->range.level[1].sens - 1;
597}
598
599/**
600 * mls_import_lvl - Import the MLS sensitivity levels
601 * @context: the security context
602 * @low: the low sensitivity level
603 * @high: the high sensitivity level
604 *
605 * Description:
606 * Given the security context and the two sensitivty levels, set the MLS levels
607 * in the context according the two given as parameters. Returns zero on
608 * success, negative values on failure.
609 *
610 */
611void mls_import_lvl(struct context *context, u32 low, u32 high)
612{
613 if (!selinux_mls_enabled)
614 return;
615
616 context->range.level[0].sens = low + 1;
617 context->range.level[1].sens = high + 1;
618}
619
620/**
621 * mls_export_cat - Export the MLS categories
622 * @context: the security context
623 * @low: the low category
624 * @low_len: length of the cat_low bitmap in bytes
625 * @high: the high category
626 * @high_len: length of the cat_high bitmap in bytes
627 *
628 * Description:
629 * Given the security context export the low MLS category bitmap into cat_low
630 * and the high category bitmap into cat_high. The MLS categories are only
631 * exported if the pointers are not NULL, if they are NULL then that level is
632 * not exported. The caller is responsibile for freeing the memory when
633 * finished. Returns zero on success, negative values on failure.
634 *
635 */
636int mls_export_cat(const struct context *context,
637 unsigned char **low,
638 size_t *low_len,
639 unsigned char **high,
640 size_t *high_len)
641{
642 int rc = -EPERM;
643
644 if (!selinux_mls_enabled)
645 return 0;
646
647 if (low != NULL) {
648 rc = ebitmap_export(&context->range.level[0].cat,
649 low,
650 low_len);
651 if (rc != 0)
652 goto export_cat_failure;
653 }
654 if (high != NULL) {
655 rc = ebitmap_export(&context->range.level[1].cat,
656 high,
657 high_len);
658 if (rc != 0)
659 goto export_cat_failure;
660 }
661
662 return 0;
663
664export_cat_failure:
665 if (low != NULL)
666 kfree(*low);
667 if (high != NULL)
668 kfree(*high);
669 return rc;
670}
671
672/**
673 * mls_import_cat - Import the MLS categories
674 * @context: the security context
675 * @low: the low category
676 * @low_len: length of the cat_low bitmap in bytes
677 * @high: the high category
678 * @high_len: length of the cat_high bitmap in bytes
679 *
680 * Description:
681 * Given the security context and the two category bitmap strings import the
682 * categories into the security context. The MLS categories are only imported
683 * if the pointers are not NULL, if they are NULL they are skipped. Returns
684 * zero on success, negative values on failure.
685 *
686 */
687int mls_import_cat(struct context *context,
688 const unsigned char *low,
689 size_t low_len,
690 const unsigned char *high,
691 size_t high_len)
692{
693 int rc = -EPERM;
694
695 if (!selinux_mls_enabled)
696 return 0;
697
698 if (low != NULL) {
699 rc = ebitmap_import(low,
700 low_len,
701 &context->range.level[0].cat);
702 if (rc != 0)
703 goto import_cat_failure;
704 }
705 if (high != NULL) {
706 if (high == low)
707 rc = ebitmap_cpy(&context->range.level[1].cat,
708 &context->range.level[0].cat);
709 else
710 rc = ebitmap_import(high,
711 high_len,
712 &context->range.level[1].cat);
713 if (rc != 0)
714 goto import_cat_failure;
715 }
716
717 return 0;
718
719import_cat_failure:
720 ebitmap_destroy(&context->range.level[0].cat);
721 ebitmap_destroy(&context->range.level[1].cat);
722 return rc;
723}
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 90c5e88987fa..df6032c6d492 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -10,6 +10,13 @@
10 * 10 *
11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
12 */ 12 */
13/*
14 * Updated: Hewlett-Packard <paul.moore@hp.com>
15 *
16 * Added support to import/export the MLS label
17 *
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19 */
13 20
14#ifndef _SS_MLS_H_ 21#ifndef _SS_MLS_H_
15#define _SS_MLS_H_ 22#define _SS_MLS_H_
@@ -62,5 +69,19 @@ int mls_compute_sid(struct context *scontext,
62int mls_setup_user_range(struct context *fromcon, struct user_datum *user, 69int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
63 struct context *usercon); 70 struct context *usercon);
64 71
72void mls_export_lvl(const struct context *context, u32 *low, u32 *high);
73void mls_import_lvl(struct context *context, u32 low, u32 high);
74
75int mls_export_cat(const struct context *context,
76 unsigned char **low,
77 size_t *low_len,
78 unsigned char **high,
79 size_t *high_len);
80int mls_import_cat(struct context *context,
81 const unsigned char *low,
82 size_t low_len,
83 const unsigned char *high,
84 size_t high_len);
85
65#endif /* _SS_MLS_H */ 86#endif /* _SS_MLS_H */
66 87
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b00ec69f0ffd..910afa1ffc31 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -13,6 +13,11 @@
13 * 13 *
14 * Added conditional policy language extensions 14 * Added conditional policy language extensions
15 * 15 *
16 * Updated: Hewlett-Packard <paul.moore@hp.com>
17 *
18 * Added support for NetLabel
19 *
20 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
16 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 21 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
17 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 22 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
18 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 23 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
@@ -29,6 +34,8 @@
29#include <linux/sched.h> 34#include <linux/sched.h>
30#include <linux/audit.h> 35#include <linux/audit.h>
31#include <linux/mutex.h> 36#include <linux/mutex.h>
37#include <net/sock.h>
38#include <net/netlabel.h>
32 39
33#include "flask.h" 40#include "flask.h"
34#include "avc.h" 41#include "avc.h"
@@ -40,6 +47,8 @@
40#include "services.h" 47#include "services.h"
41#include "conditional.h" 48#include "conditional.h"
42#include "mls.h" 49#include "mls.h"
50#include "objsec.h"
51#include "selinux_netlabel.h"
43 52
44extern void selnl_notify_policyload(u32 seqno); 53extern void selnl_notify_policyload(u32 seqno);
45unsigned int policydb_loaded_version; 54unsigned int policydb_loaded_version;
@@ -1241,6 +1250,7 @@ int security_load_policy(void *data, size_t len)
1241 selinux_complete_init(); 1250 selinux_complete_init();
1242 avc_ss_reset(seqno); 1251 avc_ss_reset(seqno);
1243 selnl_notify_policyload(seqno); 1252 selnl_notify_policyload(seqno);
1253 selinux_netlbl_cache_invalidate();
1244 return 0; 1254 return 0;
1245 } 1255 }
1246 1256
@@ -1295,6 +1305,7 @@ int security_load_policy(void *data, size_t len)
1295 1305
1296 avc_ss_reset(seqno); 1306 avc_ss_reset(seqno);
1297 selnl_notify_policyload(seqno); 1307 selnl_notify_policyload(seqno);
1308 selinux_netlbl_cache_invalidate();
1298 1309
1299 return 0; 1310 return 0;
1300 1311
@@ -2133,3 +2144,480 @@ void selinux_audit_set_callback(int (*callback)(void))
2133{ 2144{
2134 aurule_callback = callback; 2145 aurule_callback = callback;
2135} 2146}
2147
2148#ifdef CONFIG_NETLABEL
2149/*
2150 * This is the structure we store inside the NetLabel cache block.
2151 */
2152#define NETLBL_CACHE(x) ((struct netlbl_cache *)(x))
2153#define NETLBL_CACHE_T_NONE 0
2154#define NETLBL_CACHE_T_SID 1
2155#define NETLBL_CACHE_T_MLS 2
2156struct netlbl_cache {
2157 u32 type;
2158 union {
2159 u32 sid;
2160 struct mls_range mls_label;
2161 } data;
2162};
2163
2164/**
2165 * selinux_netlbl_cache_free - Free the NetLabel cached data
2166 * @data: the data to free
2167 *
2168 * Description:
2169 * This function is intended to be used as the free() callback inside the
2170 * netlbl_lsm_cache structure.
2171 *
2172 */
2173static void selinux_netlbl_cache_free(const void *data)
2174{
2175 struct netlbl_cache *cache = NETLBL_CACHE(data);
2176 switch (cache->type) {
2177 case NETLBL_CACHE_T_MLS:
2178 ebitmap_destroy(&cache->data.mls_label.level[0].cat);
2179 break;
2180 }
2181 kfree(data);
2182}
2183
2184/**
2185 * selinux_netlbl_cache_add - Add an entry to the NetLabel cache
2186 * @skb: the packet
2187 * @ctx: the SELinux context
2188 *
2189 * Description:
2190 * Attempt to cache the context in @ctx, which was derived from the packet in
2191 * @skb, in the NetLabel subsystem cache.
2192 *
2193 */
2194static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2195{
2196 struct netlbl_cache *cache = NULL;
2197 struct netlbl_lsm_secattr secattr;
2198
2199 netlbl_secattr_init(&secattr);
2200
2201 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2202 if (cache == NULL)
2203 goto netlbl_cache_add_failure;
2204 secattr.cache.free = selinux_netlbl_cache_free;
2205 secattr.cache.data = (void *)cache;
2206
2207 cache->type = NETLBL_CACHE_T_MLS;
2208 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
2209 &ctx->range.level[0].cat) != 0)
2210 goto netlbl_cache_add_failure;
2211 cache->data.mls_label.level[1].cat.highbit =
2212 cache->data.mls_label.level[0].cat.highbit;
2213 cache->data.mls_label.level[1].cat.node =
2214 cache->data.mls_label.level[0].cat.node;
2215 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
2216 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2217
2218 if (netlbl_cache_add(skb, &secattr) != 0)
2219 goto netlbl_cache_add_failure;
2220
2221 return;
2222
2223netlbl_cache_add_failure:
2224 netlbl_secattr_destroy(&secattr, 1);
2225}
2226
2227/**
2228 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
2229 *
2230 * Description:
2231 * Invalidate the NetLabel security attribute mapping cache.
2232 *
2233 */
2234void selinux_netlbl_cache_invalidate(void)
2235{
2236 netlbl_cache_invalidate();
2237}
2238
2239/**
2240 * selinux_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
2241 * @skb: the network packet
2242 * @secattr: the NetLabel packet security attributes
2243 * @base_sid: the SELinux SID to use as a context for MLS only attributes
2244 * @sid: the SELinux SID
2245 *
2246 * Description:
2247 * Convert the given NetLabel packet security attributes in @secattr into a
2248 * SELinux SID. If the @secattr field does not contain a full SELinux
2249 * SID/context then use the context in @base_sid as the foundation. If @skb
2250 * is not NULL attempt to cache as much data as possibile. Returns zero on
2251 * success, negative values on failure.
2252 *
2253 */
2254static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2255 struct netlbl_lsm_secattr *secattr,
2256 u32 base_sid,
2257 u32 *sid)
2258{
2259 int rc = -EIDRM;
2260 struct context *ctx;
2261 struct context ctx_new;
2262 struct netlbl_cache *cache;
2263
2264 POLICY_RDLOCK;
2265
2266 if (secattr->cache.data) {
2267 cache = NETLBL_CACHE(secattr->cache.data);
2268 switch (cache->type) {
2269 case NETLBL_CACHE_T_SID:
2270 *sid = cache->data.sid;
2271 rc = 0;
2272 break;
2273 case NETLBL_CACHE_T_MLS:
2274 ctx = sidtab_search(&sidtab, base_sid);
2275 if (ctx == NULL)
2276 goto netlbl_secattr_to_sid_return;
2277
2278 ctx_new.user = ctx->user;
2279 ctx_new.role = ctx->role;
2280 ctx_new.type = ctx->type;
2281 ctx_new.range.level[0].sens =
2282 cache->data.mls_label.level[0].sens;
2283 ctx_new.range.level[0].cat.highbit =
2284 cache->data.mls_label.level[0].cat.highbit;
2285 ctx_new.range.level[0].cat.node =
2286 cache->data.mls_label.level[0].cat.node;
2287 ctx_new.range.level[1].sens =
2288 cache->data.mls_label.level[1].sens;
2289 ctx_new.range.level[1].cat.highbit =
2290 cache->data.mls_label.level[1].cat.highbit;
2291 ctx_new.range.level[1].cat.node =
2292 cache->data.mls_label.level[1].cat.node;
2293
2294 rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
2295 break;
2296 default:
2297 goto netlbl_secattr_to_sid_return;
2298 }
2299 } else if (secattr->mls_lvl_vld) {
2300 ctx = sidtab_search(&sidtab, base_sid);
2301 if (ctx == NULL)
2302 goto netlbl_secattr_to_sid_return;
2303
2304 ctx_new.user = ctx->user;
2305 ctx_new.role = ctx->role;
2306 ctx_new.type = ctx->type;
2307 mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl);
2308 if (secattr->mls_cat) {
2309 if (mls_import_cat(&ctx_new,
2310 secattr->mls_cat,
2311 secattr->mls_cat_len,
2312 NULL,
2313 0) != 0)
2314 goto netlbl_secattr_to_sid_return;
2315 ctx_new.range.level[1].cat.highbit =
2316 ctx_new.range.level[0].cat.highbit;
2317 ctx_new.range.level[1].cat.node =
2318 ctx_new.range.level[0].cat.node;
2319 } else {
2320 ebitmap_init(&ctx_new.range.level[0].cat);
2321 ebitmap_init(&ctx_new.range.level[1].cat);
2322 }
2323 if (mls_context_isvalid(&policydb, &ctx_new) != 1)
2324 goto netlbl_secattr_to_sid_return_cleanup;
2325
2326 rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
2327 if (rc != 0)
2328 goto netlbl_secattr_to_sid_return_cleanup;
2329
2330 if (skb != NULL)
2331 selinux_netlbl_cache_add(skb, &ctx_new);
2332 ebitmap_destroy(&ctx_new.range.level[0].cat);
2333 } else {
2334 *sid = SECINITSID_UNLABELED;
2335 rc = 0;
2336 }
2337
2338netlbl_secattr_to_sid_return:
2339 POLICY_RDUNLOCK;
2340 return rc;
2341netlbl_secattr_to_sid_return_cleanup:
2342 ebitmap_destroy(&ctx_new.range.level[0].cat);
2343 goto netlbl_secattr_to_sid_return;
2344}
2345
2346/**
2347 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
2348 * @skb: the packet
2349 * @base_sid: the SELinux SID to use as a context for MLS only attributes
2350 * @sid: the SID
2351 *
2352 * Description:
2353 * Call the NetLabel mechanism to get the security attributes of the given
2354 * packet and use those attributes to determine the correct context/SID to
2355 * assign to the packet. Returns zero on success, negative values on failure.
2356 *
2357 */
2358static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
2359 u32 base_sid,
2360 u32 *sid)
2361{
2362 int rc;
2363 struct netlbl_lsm_secattr secattr;
2364
2365 netlbl_secattr_init(&secattr);
2366 rc = netlbl_skbuff_getattr(skb, &secattr);
2367 if (rc == 0)
2368 rc = selinux_netlbl_secattr_to_sid(skb,
2369 &secattr,
2370 base_sid,
2371 sid);
2372 netlbl_secattr_destroy(&secattr, 0);
2373
2374 return rc;
2375}
2376
2377/**
2378 * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
2379 * @sock: the socket to label
2380 * @sid: the SID to use
2381 *
2382 * Description:
2383 * Attempt to label a socket using the NetLabel mechanism using the given
2384 * SID. Returns zero values on success, negative values on failure.
2385 *
2386 */
2387static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
2388{
2389 int rc = -ENOENT;
2390 struct sk_security_struct *sksec = sock->sk->sk_security;
2391 struct netlbl_lsm_secattr secattr;
2392 struct context *ctx;
2393
2394 if (!ss_initialized)
2395 return 0;
2396
2397 POLICY_RDLOCK;
2398
2399 ctx = sidtab_search(&sidtab, sid);
2400 if (ctx == NULL)
2401 goto netlbl_socket_setsid_return;
2402
2403 netlbl_secattr_init(&secattr);
2404 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2405 GFP_ATOMIC);
2406 mls_export_lvl(ctx, &secattr.mls_lvl, NULL);
2407 secattr.mls_lvl_vld = 1;
2408 mls_export_cat(ctx,
2409 &secattr.mls_cat,
2410 &secattr.mls_cat_len,
2411 NULL,
2412 NULL);
2413
2414 rc = netlbl_socket_setattr(sock, &secattr);
2415 if (rc == 0)
2416 sksec->nlbl_state = NLBL_LABELED;
2417
2418 netlbl_secattr_destroy(&secattr, 0);
2419
2420netlbl_socket_setsid_return:
2421 POLICY_RDUNLOCK;
2422 return rc;
2423}
2424
2425/**
2426 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
2427 * @sock: the socket to label
2428 * @sock_family: the socket family
2429 * @sid: the SID to use
2430 *
2431 * Description:
2432 * Attempt to label a socket using the NetLabel mechanism using the given
2433 * SID. Returns zero values on success, negative values on failure.
2434 *
2435 */
2436int selinux_netlbl_socket_post_create(struct socket *sock,
2437 int sock_family,
2438 u32 sid)
2439{
2440 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2441 struct sk_security_struct *sksec = sock->sk->sk_security;
2442
2443 if (sock_family != PF_INET)
2444 return 0;
2445
2446 sksec->sclass = isec->sclass;
2447 sksec->nlbl_state = NLBL_REQUIRE;
2448 return selinux_netlbl_socket_setsid(sock, sid);
2449}
2450
2451/**
2452 * selinux_netlbl_sock_graft - Netlabel the new socket
2453 * @sk: the new connection
2454 * @sock: the new socket
2455 *
2456 * Description:
2457 * The connection represented by @sk is being grafted onto @sock so set the
2458 * socket's NetLabel to match the SID of @sk.
2459 *
2460 */
2461void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2462{
2463 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2464 struct sk_security_struct *sksec = sk->sk_security;
2465
2466 if (sk->sk_family != PF_INET)
2467 return;
2468
2469 sksec->nlbl_state = NLBL_REQUIRE;
2470 sksec->peer_sid = sksec->sid;
2471 sksec->sclass = isec->sclass;
2472
2473 /* Try to set the NetLabel on the socket to save time later, if we fail
2474 * here we will pick up the pieces in later calls to
2475 * selinux_netlbl_inode_permission(). */
2476 selinux_netlbl_socket_setsid(sock, sksec->sid);
2477}
2478
2479/**
2480 * selinux_netlbl_inet_conn_request - Handle a new connection request
2481 * @skb: the packet
2482 * @sock_sid: the SID of the parent socket
2483 *
2484 * Description:
2485 * If present, use the security attributes of the packet in @skb and the
2486 * parent sock's SID to arrive at a SID for the new child sock. Returns the
2487 * SID of the connection or SECSID_NULL on failure.
2488 *
2489 */
2490u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2491{
2492 int rc;
2493 u32 peer_sid;
2494
2495 rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
2496 if (rc != 0)
2497 return SECSID_NULL;
2498
2499 if (peer_sid == SECINITSID_UNLABELED)
2500 return SECSID_NULL;
2501
2502 return peer_sid;
2503}
2504
2505/**
2506 * __selinux_netlbl_inode_permission - Label a socket using NetLabel
2507 * @inode: the file descriptor's inode
2508 * @mask: the permission mask
2509 *
2510 * Description:
2511 * Try to label a socket with the inode's SID using NetLabel. Returns zero on
2512 * success, negative values on failure.
2513 *
2514 */
2515int __selinux_netlbl_inode_permission(struct inode *inode, int mask)
2516{
2517 int rc;
2518 struct socket *sock = SOCKET_I(inode);
2519 struct sk_security_struct *sksec = sock->sk->sk_security;
2520
2521 lock_sock(sock->sk);
2522 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2523 release_sock(sock->sk);
2524
2525 return rc;
2526}
2527
2528/**
2529 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
2530 * @sksec: the sock's sk_security_struct
2531 * @skb: the packet
2532 * @ad: the audit data
2533 *
2534 * Description:
2535 * Fetch the NetLabel security attributes from @skb and perform an access check
2536 * against the receiving socket. Returns zero on success, negative values on
2537 * error.
2538 *
2539 */
2540int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2541 struct sk_buff *skb,
2542 struct avc_audit_data *ad)
2543{
2544 int rc;
2545 u32 netlbl_sid;
2546 u32 recv_perm;
2547
2548 rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid);
2549 if (rc != 0)
2550 return rc;
2551
2552 if (netlbl_sid == SECINITSID_UNLABELED)
2553 return 0;
2554
2555 switch (sksec->sclass) {
2556 case SECCLASS_UDP_SOCKET:
2557 recv_perm = UDP_SOCKET__RECV_MSG;
2558 break;
2559 case SECCLASS_TCP_SOCKET:
2560 recv_perm = TCP_SOCKET__RECV_MSG;
2561 break;
2562 default:
2563 recv_perm = RAWIP_SOCKET__RECV_MSG;
2564 }
2565
2566 rc = avc_has_perm(sksec->sid,
2567 netlbl_sid,
2568 sksec->sclass,
2569 recv_perm,
2570 ad);
2571 if (rc == 0)
2572 return 0;
2573
2574 netlbl_skbuff_err(skb, rc);
2575 return rc;
2576}
2577
2578/**
2579 * selinux_netlbl_socket_peersid - Return the peer SID of a connected socket
2580 * @sock: the socket
2581 *
2582 * Description:
2583 * Examine @sock to find the connected peer's SID. Returns the SID on success
2584 * or SECSID_NULL on error.
2585 *
2586 */
2587u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
2588{
2589 struct sk_security_struct *sksec = sock->sk->sk_security;
2590
2591 if (sksec->peer_sid == SECINITSID_UNLABELED)
2592 return SECSID_NULL;
2593
2594 return sksec->peer_sid;
2595}
2596
2597/**
2598 * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
2599 * @skb: the packet
2600 *
2601 * Description:
2602 * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on
2603 * success, SECSID_NULL on error.
2604 *
2605 */
2606u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2607{
2608 int peer_sid;
2609 struct sock *sk = skb->sk;
2610 struct inode_security_struct *isec;
2611
2612 if (sk == NULL || sk->sk_socket == NULL)
2613 return SECSID_NULL;
2614
2615 isec = SOCK_INODE(sk->sk_socket)->i_security;
2616 if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0)
2617 return SECSID_NULL;
2618 if (peer_sid == SECINITSID_UNLABELED)
2619 return SECSID_NULL;
2620
2621 return peer_sid;
2622}
2623#endif /* CONFIG_NETLABEL */