提交 a205752d 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
  selinux: preserve boolean values across policy reloads
  selinux: change numbering of boolean directory inodes in selinuxfs
  selinux: remove unused enumeration constant from selinuxfs
  selinux: explicitly number all selinuxfs inodes
  selinux: export initial SID contexts via selinuxfs
  selinux: remove userland security class and permission definitions
  SELinux: move security_skb_extlbl_sid() out of the security server
  MAINTAINERS: update selinux entry
  SELinux: rename selinux_netlabel.h to netlabel.h
  SELinux: extract the NetLabel SELinux support from the security server
  NetLabel: convert a BUG_ON in the CIPSO code to a runtime check
  NetLabel: cleanup and document CIPSO constants
...@@ -2980,8 +2980,10 @@ P: Stephen Smalley ...@@ -2980,8 +2980,10 @@ P: Stephen Smalley
M: sds@tycho.nsa.gov M: sds@tycho.nsa.gov
P: James Morris P: James Morris
M: jmorris@namei.org M: jmorris@namei.org
P: Eric Paris
M: eparis@parisplace.org
L: linux-kernel@vger.kernel.org (kernel issues) L: linux-kernel@vger.kernel.org (kernel issues)
L: selinux@tycho.nsa.gov (general discussion) L: selinux@tycho.nsa.gov (subscribers-only, general discussion)
W: http://www.nsa.gov/selinux W: http://www.nsa.gov/selinux
S: Supported S: Supported
......
...@@ -91,6 +91,33 @@ static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL; ...@@ -91,6 +91,33 @@ static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL;
int cipso_v4_rbm_optfmt = 0; int cipso_v4_rbm_optfmt = 0;
int cipso_v4_rbm_strictvalid = 1; int cipso_v4_rbm_strictvalid = 1;
/*
* Protocol Constants
*/
/* Maximum size of the CIPSO IP option, derived from the fact that the maximum
* IPv4 header size is 60 bytes and the base IPv4 header is 20 bytes long. */
#define CIPSO_V4_OPT_LEN_MAX 40
/* Length of the base CIPSO option, this includes the option type (1 byte), the
* option length (1 byte), and the DOI (4 bytes). */
#define CIPSO_V4_HDR_LEN 6
/* Base length of the restrictive category bitmap tag (tag #1). */
#define CIPSO_V4_TAG_RBM_BLEN 4
/* Base length of the enumerated category tag (tag #2). */
#define CIPSO_V4_TAG_ENUM_BLEN 4
/* Base length of the ranged categories bitmap tag (tag #5). */
#define CIPSO_V4_TAG_RNG_BLEN 4
/* The maximum number of category ranges permitted in the ranged category tag
* (tag #5). You may note that the IETF draft states that the maximum number
* of category ranges is 7, but if the low end of the last category range is
* zero then it is possibile to fit 8 category ranges because the zero should
* be omitted. */
#define CIPSO_V4_TAG_RNG_CAT_MAX 8
/* /*
* Helper Functions * Helper Functions
*/ */
...@@ -1109,16 +1136,15 @@ static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def, ...@@ -1109,16 +1136,15 @@ static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
unsigned char *net_cat, unsigned char *net_cat,
u32 net_cat_len) u32 net_cat_len)
{ {
/* The constant '16' is not random, it is the maximum number of
* high/low category range pairs as permitted by the CIPSO draft based
* on a maximum IPv4 header length of 60 bytes - the BUG_ON() assertion
* does a sanity check to make sure we don't overflow the array. */
int iter = -1; int iter = -1;
u16 array[16]; u16 array[CIPSO_V4_TAG_RNG_CAT_MAX * 2];
u32 array_cnt = 0; u32 array_cnt = 0;
u32 cat_size = 0; u32 cat_size = 0;
BUG_ON(net_cat_len > 30); /* make sure we don't overflow the 'array[]' variable */
if (net_cat_len >
(CIPSO_V4_OPT_LEN_MAX - CIPSO_V4_HDR_LEN - CIPSO_V4_TAG_RNG_BLEN))
return -ENOSPC;
for (;;) { for (;;) {
iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1); iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1);
...@@ -1196,9 +1222,6 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def, ...@@ -1196,9 +1222,6 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
* Protocol Handling Functions * Protocol Handling Functions
*/ */
#define CIPSO_V4_OPT_LEN_MAX 40
#define CIPSO_V4_HDR_LEN 6
/** /**
* cipso_v4_gentag_hdr - Generate a CIPSO option header * cipso_v4_gentag_hdr - Generate a CIPSO option header
* @doi_def: the DOI definition * @doi_def: the DOI definition
......
...@@ -263,9 +263,6 @@ int netlbl_socket_setattr(const struct socket *sock, ...@@ -263,9 +263,6 @@ int netlbl_socket_setattr(const struct socket *sock,
int ret_val = -ENOENT; int ret_val = -ENOENT;
struct netlbl_dom_map *dom_entry; struct netlbl_dom_map *dom_entry;
if ((secattr->flags & NETLBL_SECATTR_DOMAIN) == 0)
return -ENOENT;
rcu_read_lock(); rcu_read_lock();
dom_entry = netlbl_domhsh_getentry(secattr->domain); dom_entry = netlbl_domhsh_getentry(secattr->domain);
if (dom_entry == NULL) if (dom_entry == NULL)
......
...@@ -8,5 +8,7 @@ selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o ...@@ -8,5 +8,7 @@ selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
selinux-$(CONFIG_NETLABEL) += netlabel.o
EXTRA_CFLAGS += -Isecurity/selinux/include EXTRA_CFLAGS += -Isecurity/selinux/include
...@@ -217,6 +217,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla ...@@ -217,6 +217,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
audit_log_format(ab, " tcontext=%s", scontext); audit_log_format(ab, " tcontext=%s", scontext);
kfree(scontext); kfree(scontext);
} }
BUG_ON(tclass >= ARRAY_SIZE(class_to_string) || !class_to_string[tclass]);
audit_log_format(ab, " tclass=%s", class_to_string[tclass]); audit_log_format(ab, " tclass=%s", class_to_string[tclass]);
} }
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
#include "objsec.h" #include "objsec.h"
#include "netif.h" #include "netif.h"
#include "xfrm.h" #include "xfrm.h"
#include "selinux_netlabel.h" #include "netlabel.h"
#define XATTR_SELINUX_SUFFIX "selinux" #define XATTR_SELINUX_SUFFIX "selinux"
#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
...@@ -3123,6 +3123,34 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, ...@@ -3123,6 +3123,34 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
return ret; return ret;
} }
/**
* selinux_skb_extlbl_sid - Determine the external label of a packet
* @skb: the packet
* @base_sid: the SELinux SID to use as a context for MLS only external labels
* @sid: the packet's SID
*
* Description:
* Check the various different forms of external packet labeling and determine
* the external SID for the packet.
*
*/
static void selinux_skb_extlbl_sid(struct sk_buff *skb,
u32 base_sid,
u32 *sid)
{
u32 xfrm_sid;
u32 nlbl_sid;
selinux_skb_xfrm_sid(skb, &xfrm_sid);
if (selinux_netlbl_skbuff_getsid(skb,
(xfrm_sid == SECSID_NULL ?
base_sid : xfrm_sid),
&nlbl_sid) != 0)
nlbl_sid = SECSID_NULL;
*sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
}
/* socket security operations */ /* socket security operations */
static int socket_has_perm(struct task_struct *task, struct socket *sock, static int socket_has_perm(struct task_struct *task, struct socket *sock,
u32 perms) u32 perms)
...@@ -3664,9 +3692,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * ...@@ -3664,9 +3692,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
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); selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
else if (skb) else if (skb)
security_skb_extlbl_sid(skb, selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peer_secid);
SECINITSID_UNLABELED,
&peer_secid);
if (peer_secid == SECSID_NULL) if (peer_secid == SECSID_NULL)
err = -EINVAL; err = -EINVAL;
...@@ -3727,7 +3753,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, ...@@ -3727,7 +3753,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
u32 newsid; u32 newsid;
u32 peersid; u32 peersid;
security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid); selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid);
if (peersid == SECSID_NULL) { if (peersid == SECSID_NULL) {
req->secid = sksec->sid; req->secid = sksec->sid;
req->peer_secid = SECSID_NULL; req->peer_secid = SECSID_NULL;
...@@ -3765,7 +3791,7 @@ static void selinux_inet_conn_established(struct sock *sk, ...@@ -3765,7 +3791,7 @@ static void selinux_inet_conn_established(struct sock *sk,
{ {
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid); selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid);
} }
static void selinux_req_classify_flow(const struct request_sock *req, static void selinux_req_classify_flow(const struct request_sock *req,
......
...@@ -128,96 +128,6 @@ ...@@ -128,96 +128,6 @@
S_(SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease") S_(SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease")
S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_WRITE, "audit_write") S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_WRITE, "audit_write")
S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_CONTROL, "audit_control") S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_CONTROL, "audit_control")
S_(SECCLASS_PASSWD, PASSWD__PASSWD, "passwd")
S_(SECCLASS_PASSWD, PASSWD__CHFN, "chfn")
S_(SECCLASS_PASSWD, PASSWD__CHSH, "chsh")
S_(SECCLASS_PASSWD, PASSWD__ROOTOK, "rootok")
S_(SECCLASS_PASSWD, PASSWD__CRONTAB, "crontab")
S_(SECCLASS_DRAWABLE, DRAWABLE__CREATE, "create")
S_(SECCLASS_DRAWABLE, DRAWABLE__DESTROY, "destroy")
S_(SECCLASS_DRAWABLE, DRAWABLE__DRAW, "draw")
S_(SECCLASS_DRAWABLE, DRAWABLE__COPY, "copy")
S_(SECCLASS_DRAWABLE, DRAWABLE__GETATTR, "getattr")
S_(SECCLASS_GC, GC__CREATE, "create")
S_(SECCLASS_GC, GC__FREE, "free")
S_(SECCLASS_GC, GC__GETATTR, "getattr")
S_(SECCLASS_GC, GC__SETATTR, "setattr")
S_(SECCLASS_WINDOW, WINDOW__ADDCHILD, "addchild")
S_(SECCLASS_WINDOW, WINDOW__CREATE, "create")
S_(SECCLASS_WINDOW, WINDOW__DESTROY, "destroy")
S_(SECCLASS_WINDOW, WINDOW__MAP, "map")
S_(SECCLASS_WINDOW, WINDOW__UNMAP, "unmap")
S_(SECCLASS_WINDOW, WINDOW__CHSTACK, "chstack")
S_(SECCLASS_WINDOW, WINDOW__CHPROPLIST, "chproplist")
S_(SECCLASS_WINDOW, WINDOW__CHPROP, "chprop")
S_(SECCLASS_WINDOW, WINDOW__LISTPROP, "listprop")
S_(SECCLASS_WINDOW, WINDOW__GETATTR, "getattr")
S_(SECCLASS_WINDOW, WINDOW__SETATTR, "setattr")
S_(SECCLASS_WINDOW, WINDOW__SETFOCUS, "setfocus")
S_(SECCLASS_WINDOW, WINDOW__MOVE, "move")
S_(SECCLASS_WINDOW, WINDOW__CHSELECTION, "chselection")
S_(SECCLASS_WINDOW, WINDOW__CHPARENT, "chparent")
S_(SECCLASS_WINDOW, WINDOW__CTRLLIFE, "ctrllife")
S_(SECCLASS_WINDOW, WINDOW__ENUMERATE, "enumerate")
S_(SECCLASS_WINDOW, WINDOW__TRANSPARENT, "transparent")
S_(SECCLASS_WINDOW, WINDOW__MOUSEMOTION, "mousemotion")
S_(SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT, "clientcomevent")
S_(SECCLASS_WINDOW, WINDOW__INPUTEVENT, "inputevent")
S_(SECCLASS_WINDOW, WINDOW__DRAWEVENT, "drawevent")
S_(SECCLASS_WINDOW, WINDOW__WINDOWCHANGEEVENT, "windowchangeevent")
S_(SECCLASS_WINDOW, WINDOW__WINDOWCHANGEREQUEST, "windowchangerequest")
S_(SECCLASS_WINDOW, WINDOW__SERVERCHANGEEVENT, "serverchangeevent")
S_(SECCLASS_WINDOW, WINDOW__EXTENSIONEVENT, "extensionevent")
S_(SECCLASS_FONT, FONT__LOAD, "load")
S_(SECCLASS_FONT, FONT__FREE, "free")
S_(SECCLASS_FONT, FONT__GETATTR, "getattr")
S_(SECCLASS_FONT, FONT__USE, "use")
S_(SECCLASS_COLORMAP, COLORMAP__CREATE, "create")
S_(SECCLASS_COLORMAP, COLORMAP__FREE, "free")
S_(SECCLASS_COLORMAP, COLORMAP__INSTALL, "install")
S_(SECCLASS_COLORMAP, COLORMAP__UNINSTALL, "uninstall")
S_(SECCLASS_COLORMAP, COLORMAP__LIST, "list")
S_(SECCLASS_COLORMAP, COLORMAP__READ, "read")
S_(SECCLASS_COLORMAP, COLORMAP__STORE, "store")
S_(SECCLASS_COLORMAP, COLORMAP__GETATTR, "getattr")
S_(SECCLASS_COLORMAP, COLORMAP__SETATTR, "setattr")
S_(SECCLASS_PROPERTY, PROPERTY__CREATE, "create")
S_(SECCLASS_PROPERTY, PROPERTY__FREE, "free")
S_(SECCLASS_PROPERTY, PROPERTY__READ, "read")
S_(SECCLASS_PROPERTY, PROPERTY__WRITE, "write")
S_(SECCLASS_CURSOR, CURSOR__CREATE, "create")
S_(SECCLASS_CURSOR, CURSOR__CREATEGLYPH, "createglyph")
S_(SECCLASS_CURSOR, CURSOR__FREE, "free")
S_(SECCLASS_CURSOR, CURSOR__ASSIGN, "assign")
S_(SECCLASS_CURSOR, CURSOR__SETATTR, "setattr")
S_(SECCLASS_XCLIENT, XCLIENT__KILL, "kill")
S_(SECCLASS_XINPUT, XINPUT__LOOKUP, "lookup")
S_(SECCLASS_XINPUT, XINPUT__GETATTR, "getattr")
S_(SECCLASS_XINPUT, XINPUT__SETATTR, "setattr")
S_(SECCLASS_XINPUT, XINPUT__SETFOCUS, "setfocus")
S_(SECCLASS_XINPUT, XINPUT__WARPPOINTER, "warppointer")
S_(SECCLASS_XINPUT, XINPUT__ACTIVEGRAB, "activegrab")
S_(SECCLASS_XINPUT, XINPUT__PASSIVEGRAB, "passivegrab")
S_(SECCLASS_XINPUT, XINPUT__UNGRAB, "ungrab")
S_(SECCLASS_XINPUT, XINPUT__BELL, "bell")
S_(SECCLASS_XINPUT, XINPUT__MOUSEMOTION, "mousemotion")
S_(SECCLASS_XINPUT, XINPUT__RELABELINPUT, "relabelinput")
S_(SECCLASS_XSERVER, XSERVER__SCREENSAVER, "screensaver")
S_(SECCLASS_XSERVER, XSERVER__GETHOSTLIST, "gethostlist")
S_(SECCLASS_XSERVER, XSERVER__SETHOSTLIST, "sethostlist")
S_(SECCLASS_XSERVER, XSERVER__GETFONTPATH, "getfontpath")
S_(SECCLASS_XSERVER, XSERVER__SETFONTPATH, "setfontpath")
S_(SECCLASS_XSERVER, XSERVER__GETATTR, "getattr")
S_(SECCLASS_XSERVER, XSERVER__GRAB, "grab")
S_(SECCLASS_XSERVER, XSERVER__UNGRAB, "ungrab")
S_(SECCLASS_XEXTENSION, XEXTENSION__QUERY, "query")
S_(SECCLASS_XEXTENSION, XEXTENSION__USE, "use")
S_(SECCLASS_PAX, PAX__PAGEEXEC, "pageexec")
S_(SECCLASS_PAX, PAX__EMUTRAMP, "emutramp")
S_(SECCLASS_PAX, PAX__MPROTECT, "mprotect")
S_(SECCLASS_PAX, PAX__RANDMMAP, "randmmap")
S_(SECCLASS_PAX, PAX__RANDEXEC, "randexec")
S_(SECCLASS_PAX, PAX__SEGMEXEC, "segmexec")
S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read") S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read")
S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write") S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write")
S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read") S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read")
...@@ -232,16 +142,6 @@ ...@@ -232,16 +142,6 @@
S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv") S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv")
S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read") S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read")
S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write") S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write")
S_(SECCLASS_DBUS, DBUS__ACQUIRE_SVC, "acquire_svc")
S_(SECCLASS_DBUS, DBUS__SEND_MSG, "send_msg")
S_(SECCLASS_NSCD, NSCD__GETPWD, "getpwd")
S_(SECCLASS_NSCD, NSCD__GETGRP, "getgrp")
S_(SECCLASS_NSCD, NSCD__GETHOST, "gethost")
S_(SECCLASS_NSCD, NSCD__GETSTAT, "getstat")
S_(SECCLASS_NSCD, NSCD__ADMIN, "admin")
S_(SECCLASS_NSCD, NSCD__SHMEMPWD, "shmempwd")
S_(SECCLASS_NSCD, NSCD__SHMEMGRP, "shmemgrp")
S_(SECCLASS_NSCD, NSCD__SHMEMHOST, "shmemhost")
S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
...@@ -256,7 +156,5 @@ ...@@ -256,7 +156,5 @@
S_(SECCLASS_KEY, KEY__LINK, "link") S_(SECCLASS_KEY, KEY__LINK, "link")
S_(SECCLASS_KEY, KEY__SETATTR, "setattr") S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
S_(SECCLASS_KEY, KEY__CREATE, "create") 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__NODE_BIND, "node_bind")
S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* /*
* Security object class definitions * Security object class definitions
*/ */
S_("null") S_(NULL)
S_("security") S_("security")
S_("process") S_("process")
S_("system") S_("system")
...@@ -32,19 +32,19 @@ ...@@ -32,19 +32,19 @@
S_("msgq") S_("msgq")
S_("shm") S_("shm")
S_("ipc") S_("ipc")
S_("passwd") S_(NULL)
S_("drawable") S_(NULL)
S_("window") S_(NULL)
S_("gc") S_(NULL)
S_("font") S_(NULL)
S_("colormap") S_(NULL)
S_("property") S_(NULL)
S_("cursor") S_(NULL)
S_("xclient") S_(NULL)
S_("xinput") S_(NULL)
S_("xserver") S_(NULL)
S_("xextension") S_(NULL)
S_("pax") S_(NULL)
S_("netlink_route_socket") S_("netlink_route_socket")
S_("netlink_firewall_socket") S_("netlink_firewall_socket")
S_("netlink_tcpdiag_socket") S_("netlink_tcpdiag_socket")
...@@ -54,12 +54,12 @@ ...@@ -54,12 +54,12 @@
S_("netlink_audit_socket") S_("netlink_audit_socket")
S_("netlink_ip6fw_socket") S_("netlink_ip6fw_socket")
S_("netlink_dnrt_socket") S_("netlink_dnrt_socket")
S_("dbus") S_(NULL)
S_("nscd") S_(NULL)
S_("association") S_("association")
S_("netlink_kobject_uevent_socket") S_("netlink_kobject_uevent_socket")
S_("appletalk_socket") S_("appletalk_socket")
S_("packet") S_("packet")
S_("key") S_("key")
S_("context") S_(NULL)
S_("dccp_socket") S_("dccp_socket")
...@@ -34,19 +34,6 @@ ...@@ -34,19 +34,6 @@
#define SECCLASS_MSGQ 27 #define SECCLASS_MSGQ 27
#define SECCLASS_SHM 28 #define SECCLASS_SHM 28
#define SECCLASS_IPC 29 #define SECCLASS_IPC 29
#define SECCLASS_PASSWD 30
#define SECCLASS_DRAWABLE 31
#define SECCLASS_WINDOW 32
#define SECCLASS_GC 33
#define SECCLASS_FONT 34
#define SECCLASS_COLORMAP 35
#define SECCLASS_PROPERTY 36
#define SECCLASS_CURSOR 37
#define SECCLASS_XCLIENT 38
#define SECCLASS_XINPUT 39
#define SECCLASS_XSERVER 40
#define SECCLASS_XEXTENSION 41
#define SECCLASS_PAX 42
#define SECCLASS_NETLINK_ROUTE_SOCKET 43 #define SECCLASS_NETLINK_ROUTE_SOCKET 43
#define SECCLASS_NETLINK_FIREWALL_SOCKET 44 #define SECCLASS_NETLINK_FIREWALL_SOCKET 44
#define SECCLASS_NETLINK_TCPDIAG_SOCKET 45 #define SECCLASS_NETLINK_TCPDIAG_SOCKET 45
...@@ -56,14 +43,11 @@ ...@@ -56,14 +43,11 @@
#define SECCLASS_NETLINK_AUDIT_SOCKET 49 #define SECCLASS_NETLINK_AUDIT_SOCKET 49
#define SECCLASS_NETLINK_IP6FW_SOCKET 50 #define SECCLASS_NETLINK_IP6FW_SOCKET 50
#define SECCLASS_NETLINK_DNRT_SOCKET 51 #define SECCLASS_NETLINK_DNRT_SOCKET 51
#define SECCLASS_DBUS 52
#define SECCLASS_NSCD 53
#define SECCLASS_ASSOCIATION 54 #define SECCLASS_ASSOCIATION 54
#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55
#define SECCLASS_APPLETALK_SOCKET 56 #define SECCLASS_APPLETALK_SOCKET 56
#define SECCLASS_PACKET 57 #define SECCLASS_PACKET 57
#define SECCLASS_KEY 58 #define SECCLASS_KEY 58
#define SECCLASS_CONTEXT 59
#define SECCLASS_DCCP_SOCKET 60 #define SECCLASS_DCCP_SOCKET 60
/* /*
......
...@@ -38,19 +38,22 @@ ...@@ -38,19 +38,22 @@
#ifdef CONFIG_NETLABEL #ifdef CONFIG_NETLABEL
void selinux_netlbl_cache_invalidate(void); void selinux_netlbl_cache_invalidate(void);
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid);
int selinux_netlbl_socket_post_create(struct socket *sock);
void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
struct avc_audit_data *ad);
void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
int family); int family);
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
int family); int family);
void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
struct sk_security_struct *newssec); struct sk_security_struct *newssec);
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid);
void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
int selinux_netlbl_socket_post_create(struct socket *sock);
int selinux_netlbl_inode_permission(struct inode *inode, int mask); int selinux_netlbl_inode_permission(struct inode *inode, int mask);
int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
struct avc_audit_data *ad);
int selinux_netlbl_socket_setsockopt(struct socket *sock, int selinux_netlbl_socket_setsockopt(struct socket *sock,
int level, int level,
int optname); int optname);
...@@ -60,59 +63,53 @@ static inline void selinux_netlbl_cache_invalidate(void) ...@@ -60,59 +63,53 @@ static inline void selinux_netlbl_cache_invalidate(void)
return; return;
} }
static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, static inline void selinux_netlbl_sk_security_reset(
u32 base_sid, struct sk_security_struct *ssec,
u32 *sid) int family)
{ {
*sid = SECSID_NULL; return;
return 0;
} }
static inline void selinux_netlbl_sk_security_init(
static inline int selinux_netlbl_socket_post_create(struct socket *sock) struct sk_security_struct *ssec,
int family)
{ {
return 0; return;
} }
static inline void selinux_netlbl_sk_security_clone(
static inline void selinux_netlbl_sock_graft(struct sock *sk, struct sk_security_struct *ssec,
struct socket *sock) struct sk_security_struct *newssec)
{ {
return; return;
} }
static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
struct sk_buff *skb, u32 base_sid,
struct avc_audit_data *ad) u32 *sid)
{ {
*sid = SECSID_NULL;
return 0; return 0;
} }
static inline void selinux_netlbl_sk_security_reset( static inline void selinux_netlbl_sock_graft(struct sock *sk,
struct sk_security_struct *ssec, struct socket *sock)
int family)
{
return;
}
static inline void selinux_netlbl_sk_security_init(
struct sk_security_struct *ssec,
int family)
{ {
return; return;
} }
static inline int selinux_netlbl_socket_post_create(struct socket *sock)
static inline void selinux_netlbl_sk_security_clone(
struct sk_security_struct *ssec,
struct sk_security_struct *newssec)
{ {
return; return 0;
} }
static inline int selinux_netlbl_inode_permission(struct inode *inode, static inline int selinux_netlbl_inode_permission(struct inode *inode,
int mask) int mask)
{ {
return 0; return 0;
} }
static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
struct avc_audit_data *ad)
{
return 0;
}
static inline int selinux_netlbl_socket_setsockopt(struct socket *sock, static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
int level, int level,
int optname) int optname)
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS #define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS
#endif #endif
struct sk_buff; struct netlbl_lsm_secattr;
extern int selinux_enabled; extern int selinux_enabled;
extern int selinux_mls_enabled; extern int selinux_mls_enabled;
...@@ -82,8 +82,6 @@ int security_netif_sid(char *name, u32 *if_sid, ...@@ -82,8 +82,6 @@ int security_netif_sid(char *name, u32 *if_sid,
int security_node_sid(u16 domain, void *addr, u32 addrlen, int security_node_sid(u16 domain, void *addr, u32 addrlen,
u32 *out_sid); u32 *out_sid);
void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid);
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass); u16 tclass);
...@@ -102,5 +100,30 @@ int security_fs_use(const char *fstype, unsigned int *behavior, ...@@ -102,5 +100,30 @@ int security_fs_use(const char *fstype, unsigned int *behavior,
int security_genfs_sid(const char *fstype, char *name, u16 sclass, int security_genfs_sid(const char *fstype, char *name, u16 sclass,
u32 *sid); u32 *sid);
#ifdef CONFIG_NETLABEL
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
u32 base_sid,
u32 *sid);
int security_netlbl_sid_to_secattr(u32 sid,
struct netlbl_lsm_secattr *secattr);
#else
static inline int security_netlbl_secattr_to_sid(
struct netlbl_lsm_secattr *secattr,
u32 base_sid,
u32 *sid)
{
return -EIDRM;
}
static inline int security_netlbl_sid_to_secattr(u32 sid,
struct netlbl_lsm_secattr *secattr)
{
return -ENOENT;
}
#endif /* CONFIG_NETLABEL */
const char *security_get_initial_sid_context(u32 sid);
#endif /* _SELINUX_SECURITY_H_ */ #endif /* _SELINUX_SECURITY_H_ */
/*
* SELinux NetLabel Support
*
* This file provides the necessary glue to tie NetLabel into the SELinux
* subsystem.
*
* Author: Paul Moore <paul.moore@hp.com>
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2007
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <net/sock.h>
#include <net/netlabel.h>
#include "objsec.h"
#include "security.h"
/**
* selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
* @sock: the socket to label
* @sid: the SID to use
*
* Description:
* Attempt to label a socket using the NetLabel mechanism using the given
* SID. Returns zero values on success, negative values on failure. The
* caller is responsibile for calling rcu_read_lock() before calling this
* this function and rcu_read_unlock() after this function returns.
*
*/
static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
{
int rc;
struct sk_security_struct *sksec = sock->sk->sk_security;
struct netlbl_lsm_secattr secattr;
rc = security_netlbl_sid_to_secattr(sid, &secattr);
if (rc != 0)
return rc;
rc = netlbl_socket_setattr(sock, &secattr);
if (rc == 0) {
spin_lock_bh(&sksec->nlbl_lock);
sksec->nlbl_state = NLBL_LABELED;
spin_unlock_bh(&sksec->nlbl_lock);
}
return rc;
}
/**
* selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
*
* Description:
* Invalidate the NetLabel security attribute mapping cache.
*
*/
void selinux_netlbl_cache_invalidate(void)
{
netlbl_cache_invalidate();
}
/**
* selinux_netlbl_sk_security_reset - Reset the NetLabel fields
* @ssec: the sk_security_struct
* @family: the socket family
*
* Description:
* Called when the NetLabel state of a sk_security_struct needs to be reset.
* The caller is responsibile for all the NetLabel sk_security_struct locking.
*
*/
void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
int family)
{
if (family == PF_INET)
ssec->nlbl_state = NLBL_REQUIRE;
else
ssec->nlbl_state = NLBL_UNSET;
}
/**
* selinux_netlbl_sk_security_init - Setup the NetLabel fields
* @ssec: the sk_security_struct
* @family: the socket family
*
* Description:
* Called when a new sk_security_struct is allocated to initialize the NetLabel
* fields.
*
*/
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
int family)
{
/* No locking needed, we are the only one who has access to ssec */
selinux_netlbl_sk_security_reset(ssec, family);
spin_lock_init(&ssec->nlbl_lock);
}
/**
* selinux_netlbl_sk_security_clone - Copy the NetLabel fields
* @ssec: the original sk_security_struct
* @newssec: the cloned sk_security_struct
*
* Description:
* Clone the NetLabel specific sk_security_struct fields from @ssec to
* @newssec.
*
*/
void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
struct sk_security_struct *newssec)
{
/* We don't need to take newssec->nlbl_lock because we are the only
* thread with access to newssec, but we do need to take the RCU read
* lock as other threads could have access to ssec */
rcu_read_lock();
selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
newssec->sclass = ssec->sclass;
rcu_read_unlock();
}
/**
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
* @skb: the packet
* @base_sid: the SELinux SID to use as a context for MLS only attributes
* @sid: the SID
*
* Description:
* Call the NetLabel mechanism to get the security attributes of the given
* packet and use those attributes to determine the correct context/SID to
* assign to the packet. Returns zero on success, negative values on failure.
*
*/
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
{
int rc;
struct netlbl_lsm_secattr secattr;
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = security_netlbl_secattr_to_sid(&secattr,
base_sid,
sid);
else
*sid = SECSID_NULL;
netlbl_secattr_destroy(&secattr);
return rc;
}
/**
* selinux_netlbl_sock_graft - Netlabel the new socket
* @sk: the new connection
* @sock: the new socket
*
* Description:
* The connection represented by @sk is being grafted onto @sock so set the
* socket's NetLabel to match the SID of @sk.
*
*/
void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
{
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
u32 nlbl_peer_sid;
sksec->sclass = isec->sclass;
rcu_read_lock();
if (sksec->nlbl_state != NLBL_REQUIRE) {
rcu_read_unlock();
return;
}
netlbl_secattr_init(&secattr);
if (netlbl_sock_getattr(sk, &secattr) == 0 &&
secattr.flags != NETLBL_SECATTR_NONE &&
security_netlbl_secattr_to_sid(&secattr,
SECINITSID_UNLABELED,
&nlbl_peer_sid) == 0)
sksec->peer_sid = nlbl_peer_sid;
netlbl_secattr_destroy(&secattr);
/* Try to set the NetLabel on the socket to save time later, if we fail
* here we will pick up the pieces in later calls to
* selinux_netlbl_inode_permission(). */
selinux_netlbl_socket_setsid(sock, sksec->sid);
rcu_read_unlock();
}
/**
* selinux_netlbl_socket_post_create - Label a socket using NetLabel
* @sock: the socket to label
*
* Description:
* Attempt to label a socket using the NetLabel mechanism using the given
* SID. Returns zero values on success, negative values on failure.
*
*/
int selinux_netlbl_socket_post_create(struct socket *sock)
{
int rc = 0;
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
struct sk_security_struct *sksec = sock->sk->sk_security;
sksec->sclass = isec->sclass;
rcu_read_lock();
if (sksec->nlbl_state == NLBL_REQUIRE)
rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
rcu_read_unlock();
return rc;
}
/**
* selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
* @inode: the file descriptor's inode
* @mask: the permission mask
*
* Description:
* Looks at a file's inode and if it is marked as a socket protected by
* NetLabel then verify that the socket has been labeled, if not try to label
* the socket now with the inode's SID. Returns zero on success, negative
* values on failure.
*
*/
int selinux_netlbl_inode_permission(struct inode *inode, int mask)
{
int rc;
struct sk_security_struct *sksec;
struct socket *sock;
if (!S_ISSOCK(inode->i_mode) ||
((mask & (MAY_WRITE | MAY_APPEND)) == 0))
return 0;
sock = SOCKET_I(inode);
sksec = sock->sk->sk_security;
rcu_read_lock();
if (sksec->nlbl_state != NLBL_REQUIRE) {
rcu_read_unlock();
return 0;
}
local_bh_disable();
bh_lock_sock_nested(sock->sk);
rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
bh_unlock_sock(sock->sk);
local_bh_enable();
rcu_read_unlock();
return rc;
}
/**
* selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
* @sksec: the sock's sk_security_struct
* @skb: the packet
* @ad: the audit data
*
* Description:
* Fetch the NetLabel security attributes from @skb and perform an access check
* against the receiving socket. Returns zero on success, negative values on
* error.
*
*/
int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
struct avc_audit_data *ad)
{
int rc;
u32 netlbl_sid;
u32 recv_perm;
rc = selinux_netlbl_skbuff_getsid(skb,
SECINITSID_UNLABELED,
&netlbl_sid);
if (rc != 0)
return rc;
if (netlbl_sid == SECSID_NULL)
return 0;
switch (sksec->sclass) {
case SECCLASS_UDP_SOCKET:
recv_perm = UDP_SOCKET__RECVFROM;
break;
case SECCLASS_TCP_SOCKET:
recv_perm = TCP_SOCKET__RECVFROM;
break;
default:
recv_perm = RAWIP_SOCKET__RECVFROM;
}
rc = avc_has_perm(sksec->sid,
netlbl_sid,
sksec->sclass,
recv_perm,
ad);
if (rc == 0)
return 0;
netlbl_skbuff_err(skb, rc);
return rc;
}
/**
* selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
* @sock: the socket
* @level: the socket level or protocol
* @optname: the socket option name
*
* Description:
* Check the setsockopt() call and if the user is trying to replace the IP
* options on a socket and a NetLabel is in place for the socket deny the
* access; otherwise allow the access. Returns zero when the access is
* allowed, -EACCES when denied, and other negative values on error.
*
*/
int selinux_netlbl_socket_setsockopt(struct socket *sock,
int level,
int optname)
{
int rc = 0;
struct sk_security_struct *sksec = sock->sk->sk_security;
struct netlbl_lsm_secattr secattr;
rcu_read_lock();
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
sksec->nlbl_state == NLBL_LABELED) {
netlbl_secattr_init(&secattr);
rc = netlbl_socket_getattr(sock, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = -EACCES;
netlbl_secattr_destroy(&secattr);
}
rcu_read_unlock();
return rc;
}
...@@ -96,12 +96,18 @@ enum sel_inos { ...@@ -96,12 +96,18 @@ enum sel_inos {
SEL_COMMIT_BOOLS, /* commit new boolean values */ SEL_COMMIT_BOOLS, /* commit new boolean values */
SEL_MLS, /* return if MLS policy is enabled */ SEL_MLS, /* return if MLS policy is enabled */
SEL_DISABLE, /* disable SELinux until next reboot */ SEL_DISABLE, /* disable SELinux until next reboot */
SEL_AVC, /* AVC management directory */
SEL_MEMBER, /* compute polyinstantiation membership decision */ SEL_MEMBER, /* compute polyinstantiation membership decision */
SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */ SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
SEL_COMPAT_NET, /* whether to use old compat network packet controls */ SEL_COMPAT_NET, /* whether to use old compat network packet controls */
SEL_INO_NEXT, /* The next inode number to use */
}; };
static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
#define SEL_INITCON_INO_OFFSET 0x01000000
#define SEL_BOOL_INO_OFFSET 0x02000000
#define SEL_INO_MASK 0x00ffffff
#define TMPBUFLEN 12 #define TMPBUFLEN 12
static ssize_t sel_read_enforce(struct file *filp, char __user *buf, static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
...@@ -777,8 +783,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode) ...@@ -777,8 +783,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode)
return ret; return ret;
} }
#define BOOL_INO_OFFSET 30
static ssize_t sel_read_bool(struct file *filep, char __user *buf, static ssize_t sel_read_bool(struct file *filep, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
...@@ -806,14 +810,14 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, ...@@ -806,14 +810,14 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
} }
inode = filep->f_path.dentry->d_inode; inode = filep->f_path.dentry->d_inode;
cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET); cur_enforcing = security_get_bool_value(inode->i_ino&SEL_INO_MASK);
if (cur_enforcing < 0) { if (cur_enforcing < 0) {
ret = cur_enforcing; ret = cur_enforcing;
goto out; goto out;
} }
length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]); bool_pending_values[inode->i_ino&SEL_INO_MASK]);
ret = simple_read_from_buffer(buf, count, ppos, page, length); ret = simple_read_from_buffer(buf, count, ppos, page, length);
out: out:
mutex_unlock(&sel_mutex); mutex_unlock(&sel_mutex);
...@@ -865,7 +869,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, ...@@ -865,7 +869,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
new_value = 1; new_value = 1;
inode = filep->f_path.dentry->d_inode; inode = filep->f_path.dentry->d_inode;
bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value; bool_pending_values[inode->i_ino&SEL_INO_MASK] = new_value;
length = count; length = count;
out: out:
...@@ -1029,7 +1033,7 @@ static int sel_make_bools(void) ...@@ -1029,7 +1033,7 @@ static int sel_make_bools(void)
isec->sid = sid; isec->sid = sid;
isec->initialized = 1; isec->initialized = 1;
inode->i_fop = &sel_bool_ops; inode->i_fop = &sel_bool_ops;
inode->i_ino = i + BOOL_INO_OFFSET; inode->i_ino = i|SEL_BOOL_INO_OFFSET;
d_add(dentry, inode); d_add(dentry, inode);
} }
bool_num = num; bool_num = num;
...@@ -1234,6 +1238,56 @@ static int sel_make_avc_files(struct dentry *dir) ...@@ -1234,6 +1238,56 @@ static int sel_make_avc_files(struct dentry *dir)
goto out; goto out;
} }
inode->i_fop = files[i].ops; inode->i_fop = files[i].ops;
inode->i_ino = ++sel_last_ino;
d_add(dentry, inode);
}
out:
return ret;
}
static ssize_t sel_read_initcon(struct file * file, char __user *buf,
size_t count, loff_t *ppos)
{
struct inode *inode;
char *con;
u32 sid, len;
ssize_t ret;
inode = file->f_path.dentry->d_inode;
sid = inode->i_ino&SEL_INO_MASK;
ret = security_sid_to_context(sid, &con, &len);
if (ret < 0)
return ret;
ret = simple_read_from_buffer(buf, count, ppos, con, len);
kfree(con);
return ret;
}
static const struct file_operations sel_initcon_ops = {
.read = sel_read_initcon,
};
static int sel_make_initcon_files(struct dentry *dir)
{
int i, ret = 0;
for (i = 1; i <= SECINITSID_NUM; i++) {
struct inode *inode;
struct dentry *dentry;
dentry = d_alloc_name(dir, security_get_initial_sid_context(i));
if (!dentry) {
ret = -ENOMEM;
goto out;
}
inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
if (!inode) {
ret = -ENOMEM;
goto out;
}
inode->i_fop = &sel_initcon_ops;
inode->i_ino = i|SEL_INITCON_INO_OFFSET;
d_add(dentry, inode); d_add(dentry, inode);
} }
out: out:
...@@ -1252,6 +1306,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry) ...@@ -1252,6 +1306,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry)
} }
inode->i_op = &simple_dir_inode_operations; inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
inode->i_ino = ++sel_last_ino;
/* directory inodes start off with i_nlink == 2 (for "." entry) */ /* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode); inc_nlink(inode);
d_add(dentry, inode); d_add(dentry, inode);
...@@ -1314,6 +1369,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) ...@@ -1314,6 +1369,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
inode->i_ino = ++sel_last_ino;
isec = (struct inode_security_struct*)inode->i_security; isec = (struct inode_security_struct*)inode->i_security;
isec->sid = SECINITSID_DEVNULL; isec->sid = SECINITSID_DEVNULL;
isec->sclass = SECCLASS_CHR_FILE; isec->sclass = SECCLASS_CHR_FILE;
...@@ -1336,6 +1392,21 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) ...@@ -1336,6 +1392,21 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
ret = sel_make_avc_files(dentry); ret = sel_make_avc_files(dentry);
if (ret) if (ret)
goto err; goto err;
dentry = d_alloc_name(sb->s_root, "initial_contexts");
if (!dentry) {
ret = -ENOMEM;
goto err;
}
ret = sel_make_dir(root_inode, dentry);
if (ret)
goto err;
ret = sel_make_initcon_files(dentry);
if (ret)
goto err;
out: out:
return ret; return ret;
err: err:
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <net/sock.h>
#include <net/netlabel.h> #include <net/netlabel.h>
#include "flask.h" #include "flask.h"
...@@ -53,7 +52,7 @@ ...@@ -53,7 +52,7 @@
#include "conditional.h" #include "conditional.h"
#include "mls.h" #include "mls.h"
#include "objsec.h" #include "objsec.h"
#include "selinux_netlabel.h" #include "netlabel.h"
#include "xfrm.h" #include "xfrm.h"
#include "ebitmap.h" #include "ebitmap.h"
...@@ -594,6 +593,13 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 ...@@ -594,6 +593,13 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
#include "initial_sid_to_string.h" #include "initial_sid_to_string.h"
const char *security_get_initial_sid_context(u32 sid)
{
if (unlikely(sid > SECINITSID_NUM))
return NULL;
return initial_sid_to_string[sid];
}
/** /**
* security_sid_to_context - Obtain a context for a given SID. * security_sid_to_context - Obtain a context for a given SID.
* @sid: security identifier, SID * @sid: security identifier, SID
...@@ -1050,6 +1056,8 @@ static int validate_classes(struct policydb *p) ...@@ -1050,6 +1056,8 @@ static int validate_classes(struct policydb *p)
for (i = 1; i < kdefs->cts_len; i++) { for (i = 1; i < kdefs->cts_len; i++) {
def_class = kdefs->class_to_string[i]; def_class = kdefs->class_to_string[i];
if (!def_class)
continue;
if (i > p->p_classes.nprim) { if (i > p->p_classes.nprim) {
printk(KERN_INFO printk(KERN_INFO
"security: class %s not defined in policy\n", "security: class %s not defined in policy\n",
...@@ -1249,6 +1257,7 @@ static int convert_context(u32 key, ...@@ -1249,6 +1257,7 @@ static int convert_context(u32 key,
} }
extern void selinux_complete_init(void); extern void selinux_complete_init(void);
static int security_preserve_bools(struct policydb *p);
/** /**
* security_load_policy - Load a security policy configuration. * security_load_policy - Load a security policy configuration.
...@@ -1325,6 +1334,12 @@ int security_load_policy(void *data, size_t len) ...@@ -1325,6 +1334,12 @@ int security_load_policy(void *data, size_t len)
goto err; goto err;
} }
rc = security_preserve_bools(&newpolicydb);
if (rc) {
printk(KERN_ERR "security: unable to preserve booleans\n");
goto err;
}
/* Clone the SID table. */ /* Clone the SID table. */
sidtab_shutdown(&sidtab); sidtab_shutdown(&sidtab);
if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { if (sidtab_map(&sidtab, clone_sid, &newsidtab)) {
...@@ -1882,6 +1897,37 @@ int security_get_bool_value(int bool) ...@@ -1882,6 +1897,37 @@ int security_get_bool_value(int bool)
return rc; return rc;
} }
static int security_preserve_bools(struct policydb *p)
{
int rc, nbools = 0, *bvalues = NULL, i;
char **bnames = NULL;
struct cond_bool_datum *booldatum;
struct cond_node *cur;
rc = security_get_bools(&nbools, &bnames, &bvalues);
if (rc)
goto out;
for (i = 0; i < nbools; i++) {
booldatum = hashtab_search(p->p_bools.table, bnames[i]);
if (booldatum)
booldatum->state = bvalues[i];
}
for (cur = p->cond_list; cur != NULL; cur = cur->next) {
rc = evaluate_cond_node(p, cur);
if (rc)
goto out;
}
out:
if (bnames) {
for (i = 0; i < nbools; i++)
kfree(bnames[i]);
}
kfree(bnames);
kfree(bvalues);
return rc;
}
/* /*
* security_sid_mls_copy() - computes a new sid based on the given * security_sid_mls_copy() - computes a new sid based on the given
* sid and the mls portion of mls_sid. * sid and the mls portion of mls_sid.
...@@ -2198,41 +2244,15 @@ void selinux_audit_set_callback(int (*callback)(void)) ...@@ -2198,41 +2244,15 @@ void selinux_audit_set_callback(int (*callback)(void))
aurule_callback = callback; aurule_callback = callback;
} }
/**
* security_skb_extlbl_sid - Determine the external label of a packet
* @skb: the packet
* @base_sid: the SELinux SID to use as a context for MLS only external labels
* @sid: the packet's SID
*
* Description:
* Check the various different forms of external packet labeling and determine
* the external SID for the packet.
*
*/
void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
{
u32 xfrm_sid;
u32 nlbl_sid;
selinux_skb_xfrm_sid(skb, &xfrm_sid);
if (selinux_netlbl_skbuff_getsid(skb,
(xfrm_sid == SECSID_NULL ?
base_sid : xfrm_sid),
&nlbl_sid) != 0)
nlbl_sid = SECSID_NULL;
*sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
}
#ifdef CONFIG_NETLABEL #ifdef CONFIG_NETLABEL
/* /*
* This is the structure we store inside the NetLabel cache block. * NetLabel cache structure
*/ */
#define NETLBL_CACHE(x) ((struct netlbl_cache *)(x)) #define NETLBL_CACHE(x) ((struct selinux_netlbl_cache *)(x))
#define NETLBL_CACHE_T_NONE 0 #define NETLBL_CACHE_T_NONE 0
#define NETLBL_CACHE_T_SID 1 #define NETLBL_CACHE_T_SID 1
#define NETLBL_CACHE_T_MLS 2 #define NETLBL_CACHE_T_MLS 2
struct netlbl_cache { struct selinux_netlbl_cache {
u32 type; u32 type;
union { union {
u32 sid; u32 sid;
...@@ -2241,7 +2261,7 @@ struct netlbl_cache { ...@@ -2241,7 +2261,7 @@ struct netlbl_cache {
}; };
/** /**
* selinux_netlbl_cache_free - Free the NetLabel cached data * security_netlbl_cache_free - Free the NetLabel cached data
* @data: the data to free * @data: the data to free
* *
* Description: * Description:
...@@ -2249,9 +2269,9 @@ struct netlbl_cache { ...@@ -2249,9 +2269,9 @@ struct netlbl_cache {
* netlbl_lsm_cache structure. * netlbl_lsm_cache structure.
* *
*/ */
static void selinux_netlbl_cache_free(const void *data) static void security_netlbl_cache_free(const void *data)
{ {
struct netlbl_cache *cache; struct selinux_netlbl_cache *cache;
if (data == NULL) if (data == NULL)
return; return;
...@@ -2266,33 +2286,33 @@ static void selinux_netlbl_cache_free(const void *data) ...@@ -2266,33 +2286,33 @@ static void selinux_netlbl_cache_free(const void *data)
} }
/** /**
* selinux_netlbl_cache_add - Add an entry to the NetLabel cache * security_netlbl_cache_add - Add an entry to the NetLabel cache
* @skb: the packet * @secattr: the NetLabel packet security attributes
* @ctx: the SELinux context * @ctx: the SELinux context
* *
* Description: * Description:
* Attempt to cache the context in @ctx, which was derived from the packet in * Attempt to cache the context in @ctx, which was derived from the packet in
* @skb, in the NetLabel subsystem cache. * @skb, in the NetLabel subsystem cache. This function assumes @secattr has
* already been initialized.
* *
*/ */
static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
struct context *ctx)
{ {
struct netlbl_cache *cache = NULL; struct selinux_netlbl_cache *cache = NULL;
struct netlbl_lsm_secattr secattr;
netlbl_secattr_init(&secattr); secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); if (secattr->cache == NULL)
if (secattr.cache == NULL) return;
goto netlbl_cache_add_return;
cache = kzalloc(sizeof(*cache), GFP_ATOMIC); cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
if (cache == NULL) if (cache == NULL)
goto netlbl_cache_add_return; return;
cache->type = NETLBL_CACHE_T_MLS; cache->type = NETLBL_CACHE_T_MLS;
if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
&ctx->range.level[0].cat) != 0) &ctx->range.level[0].cat) != 0)
goto netlbl_cache_add_return; return;
cache->data.mls_label.level[1].cat.highbit = cache->data.mls_label.level[1].cat.highbit =
cache->data.mls_label.level[0].cat.highbit; cache->data.mls_label.level[0].cat.highbit;
cache->data.mls_label.level[1].cat.node = cache->data.mls_label.level[1].cat.node =
...@@ -2300,52 +2320,40 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) ...@@ -2300,52 +2320,40 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
secattr.cache->free = selinux_netlbl_cache_free; secattr->cache->free = security_netlbl_cache_free;
secattr.cache->data = (void *)cache; secattr->cache->data = (void *)cache;
secattr.flags = NETLBL_SECATTR_CACHE; secattr->flags |= NETLBL_SECATTR_CACHE;
netlbl_cache_add(skb, &secattr);
netlbl_cache_add_return:
netlbl_secattr_destroy(&secattr);
} }
/** /**
* selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
*
* Description:
* Invalidate the NetLabel security attribute mapping cache.
*
*/
void selinux_netlbl_cache_invalidate(void)
{
netlbl_cache_invalidate();
}
/**
* selinux_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
* @skb: the network packet
* @secattr: the NetLabel packet security attributes * @secattr: the NetLabel packet security attributes
* @base_sid: the SELinux SID to use as a context for MLS only attributes * @base_sid: the SELinux SID to use as a context for MLS only attributes
* @sid: the SELinux SID * @sid: the SELinux SID
* *
* Description: * Description:
* Convert the given NetLabel packet security attributes in @secattr into a * Convert the given NetLabel security attributes in @secattr into a
* SELinux SID. If the @secattr field does not contain a full SELinux * SELinux SID. If the @secattr field does not contain a full SELinux
* SID/context then use the context in @base_sid as the foundation. If @skb * SID/context then use the context in @base_sid as the foundation. If
* is not NULL attempt to cache as much data as possibile. Returns zero on * possibile the 'cache' field of @secattr is set and the CACHE flag is set;
* success, negative values on failure. * this is to allow the @secattr to be used by NetLabel to cache the secattr to
* SID conversion for future lookups. Returns zero on success, negative
* values on failure.
* *
*/ */
static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
struct netlbl_lsm_secattr *secattr, u32 base_sid,
u32 base_sid, u32 *sid)
u32 *sid)
{ {
int rc = -EIDRM; int rc = -EIDRM;
struct context *ctx; struct context *ctx;
struct context ctx_new; struct context ctx_new;
struct netlbl_cache *cache; struct selinux_netlbl_cache *cache;
if (!ss_initialized) {
*sid = SECSID_NULL;
return 0;
}
POLICY_RDLOCK; POLICY_RDLOCK;
...@@ -2410,8 +2418,8 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ...@@ -2410,8 +2418,8 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
if (rc != 0) if (rc != 0)
goto netlbl_secattr_to_sid_return_cleanup; goto netlbl_secattr_to_sid_return_cleanup;
if (skb != NULL) security_netlbl_cache_add(secattr, &ctx_new);
selinux_netlbl_cache_add(skb, &ctx_new);
ebitmap_destroy(&ctx_new.range.level[0].cat); ebitmap_destroy(&ctx_new.range.level[0].cat);
} else { } else {
*sid = SECSID_NULL; *sid = SECSID_NULL;
...@@ -2427,338 +2435,43 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, ...@@ -2427,338 +2435,43 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
} }
/** /**
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * security_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr
* @skb: the packet * @sid: the SELinux SID
* @base_sid: the SELinux SID to use as a context for MLS only attributes * @secattr: the NetLabel packet security attributes
* @sid: the SID
*
* Description:
* Call the NetLabel mechanism to get the security attributes of the given
* packet and use those attributes to determine the correct context/SID to
* assign to the packet. Returns zero on success, negative values on failure.
*
*/
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
{
int rc;
struct netlbl_lsm_secattr secattr;
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = selinux_netlbl_secattr_to_sid(skb,
&secattr,
base_sid,
sid);
else
*sid = SECSID_NULL;
netlbl_secattr_destroy(&secattr);
return rc;
}
/**
* selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
* @sock: the socket to label
* @sid: the SID to use
* *
* Description: * Description:
* Attempt to label a socket using the NetLabel mechanism using the given * Convert the given SELinux SID in @sid into a NetLabel security attribute.
* SID. Returns zero values on success, negative values on failure. The * Returns zero on success, negative values on failure.
* caller is responsibile for calling rcu_read_lock() before calling this
* this function and rcu_read_unlock() after this function returns.
* *
*/ */
static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
{ {
int rc = -ENOENT; int rc = -ENOENT;
struct sk_security_struct *sksec = sock->sk->sk_security;
struct netlbl_lsm_secattr secattr;
struct context *ctx; struct context *ctx;
netlbl_secattr_init(secattr);
if (!ss_initialized) if (!ss_initialized)
return 0; return 0;
netlbl_secattr_init(&secattr);
POLICY_RDLOCK; POLICY_RDLOCK;
ctx = sidtab_search(&sidtab, sid); ctx = sidtab_search(&sidtab, sid);
if (ctx == NULL) if (ctx == NULL)
goto netlbl_socket_setsid_return; goto netlbl_sid_to_secattr_failure;
secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], GFP_ATOMIC);
GFP_ATOMIC); secattr->flags |= NETLBL_SECATTR_DOMAIN;
secattr.flags |= NETLBL_SECATTR_DOMAIN; mls_export_netlbl_lvl(ctx, secattr);
mls_export_netlbl_lvl(ctx, &secattr); rc = mls_export_netlbl_cat(ctx, secattr);
rc = mls_export_netlbl_cat(ctx, &secattr);
if (rc != 0) if (rc != 0)
goto netlbl_socket_setsid_return; goto netlbl_sid_to_secattr_failure;
rc = netlbl_socket_setattr(sock, &secattr);
if (rc == 0) {
spin_lock_bh(&sksec->nlbl_lock);
sksec->nlbl_state = NLBL_LABELED;
spin_unlock_bh(&sksec->nlbl_lock);
}
netlbl_socket_setsid_return:
POLICY_RDUNLOCK; POLICY_RDUNLOCK;
netlbl_secattr_destroy(&secattr);
return rc;
}
/**
* selinux_netlbl_sk_security_reset - Reset the NetLabel fields
* @ssec: the sk_security_struct
* @family: the socket family
*
* Description:
* Called when the NetLabel state of a sk_security_struct needs to be reset.
* The caller is responsibile for all the NetLabel sk_security_struct locking.
*
*/
void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
int family)
{
if (family == PF_INET)
ssec->nlbl_state = NLBL_REQUIRE;
else
ssec->nlbl_state = NLBL_UNSET;
}
/** return 0;
* selinux_netlbl_sk_security_init - Setup the NetLabel fields
* @ssec: the sk_security_struct
* @family: the socket family
*
* Description:
* Called when a new sk_security_struct is allocated to initialize the NetLabel
* fields.
*
*/
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
int family)
{
/* No locking needed, we are the only one who has access to ssec */
selinux_netlbl_sk_security_reset(ssec, family);
spin_lock_init(&ssec->nlbl_lock);
}
/**
* selinux_netlbl_sk_security_clone - Copy the NetLabel fields
* @ssec: the original sk_security_struct
* @newssec: the cloned sk_security_struct
*
* Description:
* Clone the NetLabel specific sk_security_struct fields from @ssec to
* @newssec.
*
*/
void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
struct sk_security_struct *newssec)
{
/* We don't need to take newssec->nlbl_lock because we are the only
* thread with access to newssec, but we do need to take the RCU read
* lock as other threads could have access to ssec */
rcu_read_lock();
selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
newssec->sclass = ssec->sclass;
rcu_read_unlock();
}
/**
* selinux_netlbl_socket_post_create - Label a socket using NetLabel
* @sock: the socket to label
*
* Description:
* Attempt to label a socket using the NetLabel mechanism using the given
* SID. Returns zero values on success, negative values on failure.
*
*/
int selinux_netlbl_socket_post_create(struct socket *sock)
{
int rc = 0;
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
struct sk_security_struct *sksec = sock->sk->sk_security;
sksec->sclass = isec->sclass;
rcu_read_lock();
if (sksec->nlbl_state == NLBL_REQUIRE)
rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
rcu_read_unlock();
return rc;
}
/**
* selinux_netlbl_sock_graft - Netlabel the new socket
* @sk: the new connection
* @sock: the new socket
*
* Description:
* The connection represented by @sk is being grafted onto @sock so set the
* socket's NetLabel to match the SID of @sk.
*
*/
void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
{
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
u32 nlbl_peer_sid;
sksec->sclass = isec->sclass;
rcu_read_lock();
if (sksec->nlbl_state != NLBL_REQUIRE) {
rcu_read_unlock();
return;
}
netlbl_secattr_init(&secattr);
if (netlbl_sock_getattr(sk, &secattr) == 0 &&
secattr.flags != NETLBL_SECATTR_NONE &&
selinux_netlbl_secattr_to_sid(NULL,
&secattr,
SECINITSID_UNLABELED,
&nlbl_peer_sid) == 0)
sksec->peer_sid = nlbl_peer_sid;
netlbl_secattr_destroy(&secattr);
/* Try to set the NetLabel on the socket to save time later, if we fail
* here we will pick up the pieces in later calls to
* selinux_netlbl_inode_permission(). */
selinux_netlbl_socket_setsid(sock, sksec->sid);
rcu_read_unlock();
}
/**
* selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
* @inode: the file descriptor's inode
* @mask: the permission mask
*
* Description:
* Looks at a file's inode and if it is marked as a socket protected by
* NetLabel then verify that the socket has been labeled, if not try to label
* the socket now with the inode's SID. Returns zero on success, negative
* values on failure.
*
*/
int selinux_netlbl_inode_permission(struct inode *inode, int mask)
{
int rc;
struct sk_security_struct *sksec;
struct socket *sock;
if (!S_ISSOCK(inode->i_mode) ||
((mask & (MAY_WRITE | MAY_APPEND)) == 0))
return 0;
sock = SOCKET_I(inode);
sksec = sock->sk->sk_security;
rcu_read_lock();
if (sksec->nlbl_state != NLBL_REQUIRE) {
rcu_read_unlock();
return 0;
}
local_bh_disable();
bh_lock_sock_nested(sock->sk);
rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
bh_unlock_sock(sock->sk);
local_bh_enable();
rcu_read_unlock();
return rc;
}
/**
* selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
* @sksec: the sock's sk_security_struct
* @skb: the packet
* @ad: the audit data
*
* Description:
* Fetch the NetLabel security attributes from @skb and perform an access check
* against the receiving socket. Returns zero on success, negative values on
* error.
*
*/
int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
struct sk_buff *skb,
struct avc_audit_data *ad)
{
int rc;
u32 netlbl_sid;
u32 recv_perm;
rc = selinux_netlbl_skbuff_getsid(skb,
SECINITSID_UNLABELED,
&netlbl_sid);
if (rc != 0)
return rc;
if (netlbl_sid == SECSID_NULL)
return 0;
switch (sksec->sclass) {
case SECCLASS_UDP_SOCKET:
recv_perm = UDP_SOCKET__RECVFROM;
break;
case SECCLASS_TCP_SOCKET:
recv_perm = TCP_SOCKET__RECVFROM;
break;
default:
recv_perm = RAWIP_SOCKET__RECVFROM;
}
rc = avc_has_perm(sksec->sid,
netlbl_sid,
sksec->sclass,
recv_perm,
ad);
if (rc == 0)
return 0;
netlbl_skbuff_err(skb, rc);
return rc;
}
/**
* selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
* @sock: the socket
* @level: the socket level or protocol
* @optname: the socket option name
*
* Description:
* Check the setsockopt() call and if the user is trying to replace the IP
* options on a socket and a NetLabel is in place for the socket deny the
* access; otherwise allow the access. Returns zero when the access is
* allowed, -EACCES when denied, and other negative values on error.
*
*/
int selinux_netlbl_socket_setsockopt(struct socket *sock,
int level,
int optname)
{
int rc = 0;
struct sk_security_struct *sksec = sock->sk->sk_security;
struct netlbl_lsm_secattr secattr;
rcu_read_lock();
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
sksec->nlbl_state == NLBL_LABELED) {
netlbl_secattr_init(&secattr);
rc = netlbl_socket_getattr(sock, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = -EACCES;
netlbl_secattr_destroy(&secattr);
}
rcu_read_unlock();
netlbl_sid_to_secattr_failure:
POLICY_RDUNLOCK;
netlbl_secattr_destroy(secattr);
return rc; return rc;
} }
#endif /* CONFIG_NETLABEL */ #endif /* CONFIG_NETLABEL */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册