aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2013-05-22 21:42:56 -0400
committerCasey Schaufler <casey@schaufler-ca.com>2013-05-28 13:08:26 -0400
commitc673944347edfd4362b10eea11ac384a582b1cf5 (patch)
treeb1495c8af7910a697e4b6c6e13790911f02b8291 /security
parent4726e8fa1dcad533362475ebf91f70d5b6b6292f (diff)
Smack: Local IPv6 port based controls
Smack does not provide access controls on IPv6 communications. This patch introduces a mechanism for maintaining Smack lables for local IPv6 communications. It is based on labeling local ports. The behavior should be compatible with any future "real" IPv6 support as it provides no interfaces for users to manipulate the labeling. Remote IPv6 connections use the ambient label the same way that unlabeled IPv4 packets are treated. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security')
-rw-r--r--security/smack/smack.h11
-rw-r--r--security/smack/smack_lsm.c348
2 files changed, 319 insertions, 40 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 8ad30955e15d..bb28e099abfe 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -94,6 +94,17 @@ struct smk_netlbladdr {
94}; 94};
95 95
96/* 96/*
97 * An entry in the table identifying ports.
98 */
99struct smk_port_label {
100 struct list_head list;
101 struct sock *smk_sock; /* socket initialized on */
102 unsigned short smk_port; /* the port number */
103 char *smk_in; /* incoming label */
104 char *smk_out; /* outgoing label */
105};
106
107/*
97 * This is the repository for labels seen so that it is 108 * This is the repository for labels seen so that it is
98 * not necessary to keep allocating tiny chuncks of memory 109 * not necessary to keep allocating tiny chuncks of memory
99 * and so that they can be shared. 110 * and so that they can be shared.
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d52c780bdb78..609e89de3c24 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -27,10 +27,13 @@
27#include <linux/ip.h> 27#include <linux/ip.h>
28#include <linux/tcp.h> 28#include <linux/tcp.h>
29#include <linux/udp.h> 29#include <linux/udp.h>
30#include <linux/dccp.h>
30#include <linux/slab.h> 31#include <linux/slab.h>
31#include <linux/mutex.h> 32#include <linux/mutex.h>
32#include <linux/pipe_fs_i.h> 33#include <linux/pipe_fs_i.h>
33#include <net/cipso_ipv4.h> 34#include <net/cipso_ipv4.h>
35#include <net/ip.h>
36#include <net/ipv6.h>
34#include <linux/audit.h> 37#include <linux/audit.h>
35#include <linux/magic.h> 38#include <linux/magic.h>
36#include <linux/dcache.h> 39#include <linux/dcache.h>
@@ -45,6 +48,12 @@
45#define TRANS_TRUE "TRUE" 48#define TRANS_TRUE "TRUE"
46#define TRANS_TRUE_SIZE 4 49#define TRANS_TRUE_SIZE 4
47 50
51#define SMK_CONNECTING 0
52#define SMK_RECEIVING 1
53#define SMK_SENDING 2
54
55LIST_HEAD(smk_ipv6_port_list);
56
48/** 57/**
49 * smk_fetch - Fetch the smack label from a file. 58 * smk_fetch - Fetch the smack label from a file.
50 * @ip: a pointer to the inode 59 * @ip: a pointer to the inode
@@ -1878,6 +1887,155 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
1878} 1887}
1879 1888
1880/** 1889/**
1890 * smk_ipv6_port_label - Smack port access table management
1891 * @sock: socket
1892 * @address: address
1893 *
1894 * Create or update the port list entry
1895 */
1896static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
1897{
1898 struct sock *sk = sock->sk;
1899 struct sockaddr_in6 *addr6;
1900 struct socket_smack *ssp = sock->sk->sk_security;
1901 struct smk_port_label *spp;
1902 unsigned short port = 0;
1903
1904 if (address == NULL) {
1905 /*
1906 * This operation is changing the Smack information
1907 * on the bound socket. Take the changes to the port
1908 * as well.
1909 */
1910 list_for_each_entry(spp, &smk_ipv6_port_list, list) {
1911 if (sk != spp->smk_sock)
1912 continue;
1913 spp->smk_in = ssp->smk_in;
1914 spp->smk_out = ssp->smk_out;
1915 return;
1916 }
1917 /*
1918 * A NULL address is only used for updating existing
1919 * bound entries. If there isn't one, it's OK.
1920 */
1921 return;
1922 }
1923
1924 addr6 = (struct sockaddr_in6 *)address;
1925 port = ntohs(addr6->sin6_port);
1926 /*
1927 * This is a special case that is safely ignored.
1928 */
1929 if (port == 0)
1930 return;
1931
1932 /*
1933 * Look for an existing port list entry.
1934 * This is an indication that a port is getting reused.
1935 */
1936 list_for_each_entry(spp, &smk_ipv6_port_list, list) {
1937 if (spp->smk_port != port)
1938 continue;
1939 spp->smk_port = port;
1940 spp->smk_sock = sk;
1941 spp->smk_in = ssp->smk_in;
1942 spp->smk_out = ssp->smk_out;
1943 return;
1944 }
1945
1946 /*
1947 * A new port entry is required.
1948 */
1949 spp = kzalloc(sizeof(*spp), GFP_KERNEL);
1950 if (spp == NULL)
1951 return;
1952
1953 spp->smk_port = port;
1954 spp->smk_sock = sk;
1955 spp->smk_in = ssp->smk_in;
1956 spp->smk_out = ssp->smk_out;
1957
1958 list_add(&spp->list, &smk_ipv6_port_list);
1959 return;
1960}
1961
1962/**
1963 * smk_ipv6_port_check - check Smack port access
1964 * @sock: socket
1965 * @address: address
1966 *
1967 * Create or update the port list entry
1968 */
1969static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address,
1970 int act)
1971{
1972 __be16 *bep;
1973 __be32 *be32p;
1974 struct sockaddr_in6 *addr6;
1975 struct smk_port_label *spp;
1976 struct socket_smack *ssp = sk->sk_security;
1977 unsigned short port = 0;
1978 char *subject;
1979 char *object;
1980 struct smk_audit_info ad;
1981#ifdef CONFIG_AUDIT
1982 struct lsm_network_audit net;
1983#endif
1984
1985 if (act == SMK_RECEIVING) {
1986 subject = smack_net_ambient;
1987 object = ssp->smk_in;
1988 } else {
1989 subject = ssp->smk_out;
1990 object = smack_net_ambient;
1991 }
1992
1993 /*
1994 * Get the IP address and port from the address.
1995 */
1996 addr6 = (struct sockaddr_in6 *)address;
1997 port = ntohs(addr6->sin6_port);
1998 bep = (__be16 *)(&addr6->sin6_addr);
1999 be32p = (__be32 *)(&addr6->sin6_addr);
2000
2001 /*
2002 * It's remote, so port lookup does no good.
2003 */
2004 if (be32p[0] || be32p[1] || be32p[2] || bep[6] || ntohs(bep[7]) != 1)
2005 goto auditout;
2006
2007 /*
2008 * It's local so the send check has to have passed.
2009 */
2010 if (act == SMK_RECEIVING) {
2011 subject = smack_known_web.smk_known;
2012 goto auditout;
2013 }
2014
2015 list_for_each_entry(spp, &smk_ipv6_port_list, list) {
2016 if (spp->smk_port != port)
2017 continue;
2018 object = spp->smk_in;
2019 if (act == SMK_CONNECTING)
2020 ssp->smk_packet = spp->smk_out;
2021 break;
2022 }
2023
2024auditout:
2025
2026#ifdef CONFIG_AUDIT
2027 smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
2028 ad.a.u.net->family = sk->sk_family;
2029 ad.a.u.net->dport = port;
2030 if (act == SMK_RECEIVING)
2031 ad.a.u.net->v6info.saddr = addr6->sin6_addr;
2032 else
2033 ad.a.u.net->v6info.daddr = addr6->sin6_addr;
2034#endif
2035 return smk_access(subject, object, MAY_WRITE, &ad);
2036}
2037
2038/**
1881 * smack_inode_setsecurity - set smack xattrs 2039 * smack_inode_setsecurity - set smack xattrs
1882 * @inode: the object 2040 * @inode: the object
1883 * @name: attribute name 2041 * @name: attribute name
@@ -1926,7 +2084,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1926 ssp->smk_in = sp; 2084 ssp->smk_in = sp;
1927 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { 2085 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
1928 ssp->smk_out = sp; 2086 ssp->smk_out = sp;
1929 if (sock->sk->sk_family != PF_UNIX) { 2087 if (sock->sk->sk_family == PF_INET) {
1930 rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); 2088 rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1931 if (rc != 0) 2089 if (rc != 0)
1932 printk(KERN_WARNING 2090 printk(KERN_WARNING
@@ -1936,6 +2094,9 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1936 } else 2094 } else
1937 return -EOPNOTSUPP; 2095 return -EOPNOTSUPP;
1938 2096
2097 if (sock->sk->sk_family == PF_INET6)
2098 smk_ipv6_port_label(sock, NULL);
2099
1939 return 0; 2100 return 0;
1940} 2101}
1941 2102
@@ -1963,6 +2124,25 @@ static int smack_socket_post_create(struct socket *sock, int family,
1963} 2124}
1964 2125
1965/** 2126/**
2127 * smack_socket_bind - record port binding information.
2128 * @sock: the socket
2129 * @address: the port address
2130 * @addrlen: size of the address
2131 *
2132 * Records the label bound to a port.
2133 *
2134 * Returns 0
2135 */
2136static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
2137 int addrlen)
2138{
2139 if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
2140 smk_ipv6_port_label(sock, address);
2141
2142 return 0;
2143}
2144
2145/**
1966 * smack_socket_connect - connect access check 2146 * smack_socket_connect - connect access check
1967 * @sock: the socket 2147 * @sock: the socket
1968 * @sap: the other end 2148 * @sap: the other end
@@ -1975,12 +2155,24 @@ static int smack_socket_post_create(struct socket *sock, int family,
1975static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, 2155static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
1976 int addrlen) 2156 int addrlen)
1977{ 2157{
1978 if (sock->sk == NULL || sock->sk->sk_family != PF_INET) 2158 int rc = 0;
2159
2160 if (sock->sk == NULL)
1979 return 0; 2161 return 0;
1980 if (addrlen < sizeof(struct sockaddr_in))
1981 return -EINVAL;
1982 2162
1983 return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap); 2163 switch (sock->sk->sk_family) {
2164 case PF_INET:
2165 if (addrlen < sizeof(struct sockaddr_in))
2166 return -EINVAL;
2167 rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
2168 break;
2169 case PF_INET6:
2170 if (addrlen < sizeof(struct sockaddr_in6))
2171 return -EINVAL;
2172 rc = smk_ipv6_port_check(sock->sk, sap, SMK_CONNECTING);
2173 break;
2174 }
2175 return rc;
1984} 2176}
1985 2177
1986/** 2178/**
@@ -2792,22 +2984,32 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
2792 * @msg: the message 2984 * @msg: the message
2793 * @size: the size of the message 2985 * @size: the size of the message
2794 * 2986 *
2795 * Return 0 if the current subject can write to the destination 2987 * Return 0 if the current subject can write to the destination host.
2796 * host. This is only a question if the destination is a single 2988 * For IPv4 this is only a question if the destination is a single label host.
2797 * label host. 2989 * For IPv6 this is a check against the label of the port.
2798 */ 2990 */
2799static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, 2991static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2800 int size) 2992 int size)
2801{ 2993{
2802 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; 2994 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
2995 struct sockaddr *sap = (struct sockaddr *) msg->msg_name;
2996 int rc = 0;
2803 2997
2804 /* 2998 /*
2805 * Perfectly reasonable for this to be NULL 2999 * Perfectly reasonable for this to be NULL
2806 */ 3000 */
2807 if (sip == NULL || sip->sin_family != AF_INET) 3001 if (sip == NULL)
2808 return 0; 3002 return 0;
2809 3003
2810 return smack_netlabel_send(sock->sk, sip); 3004 switch (sip->sin_family) {
3005 case AF_INET:
3006 rc = smack_netlabel_send(sock->sk, sip);
3007 break;
3008 case AF_INET6:
3009 rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
3010 break;
3011 }
3012 return rc;
2811} 3013}
2812 3014
2813/** 3015/**
@@ -2878,6 +3080,54 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2878 return smack_net_ambient; 3080 return smack_net_ambient;
2879} 3081}
2880 3082
3083static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr *sap)
3084{
3085 struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;
3086 u8 nexthdr;
3087 int offset;
3088 int proto = -EINVAL;
3089 struct ipv6hdr _ipv6h;
3090 struct ipv6hdr *ip6;
3091 __be16 frag_off;
3092 struct tcphdr _tcph, *th;
3093 struct udphdr _udph, *uh;
3094 struct dccp_hdr _dccph, *dh;
3095
3096 sip->sin6_port = 0;
3097
3098 offset = skb_network_offset(skb);
3099 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3100 if (ip6 == NULL)
3101 return -EINVAL;
3102 sip->sin6_addr = ip6->saddr;
3103
3104 nexthdr = ip6->nexthdr;
3105 offset += sizeof(_ipv6h);
3106 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
3107 if (offset < 0)
3108 return -EINVAL;
3109
3110 proto = nexthdr;
3111 switch (proto) {
3112 case IPPROTO_TCP:
3113 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3114 if (th != NULL)
3115 sip->sin6_port = th->source;
3116 break;
3117 case IPPROTO_UDP:
3118 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3119 if (uh != NULL)
3120 sip->sin6_port = uh->source;
3121 break;
3122 case IPPROTO_DCCP:
3123 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3124 if (dh != NULL)
3125 sip->sin6_port = dh->dccph_sport;
3126 break;
3127 }
3128 return proto;
3129}
3130
2881/** 3131/**
2882 * smack_socket_sock_rcv_skb - Smack packet delivery access check 3132 * smack_socket_sock_rcv_skb - Smack packet delivery access check
2883 * @sk: socket 3133 * @sk: socket
@@ -2889,43 +3139,52 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2889{ 3139{
2890 struct netlbl_lsm_secattr secattr; 3140 struct netlbl_lsm_secattr secattr;
2891 struct socket_smack *ssp = sk->sk_security; 3141 struct socket_smack *ssp = sk->sk_security;
3142 struct sockaddr sadd;
2892 char *csp; 3143 char *csp;
2893 int rc; 3144 int rc = 0;
2894 struct smk_audit_info ad; 3145 struct smk_audit_info ad;
2895#ifdef CONFIG_AUDIT 3146#ifdef CONFIG_AUDIT
2896 struct lsm_network_audit net; 3147 struct lsm_network_audit net;
2897#endif 3148#endif
2898 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) 3149 switch (sk->sk_family) {
2899 return 0; 3150 case PF_INET:
2900 3151 /*
2901 /* 3152 * Translate what netlabel gave us.
2902 * Translate what netlabel gave us. 3153 */
2903 */ 3154 netlbl_secattr_init(&secattr);
2904 netlbl_secattr_init(&secattr);
2905 3155
2906 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); 3156 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
2907 if (rc == 0) 3157 if (rc == 0)
2908 csp = smack_from_secattr(&secattr, ssp); 3158 csp = smack_from_secattr(&secattr, ssp);
2909 else 3159 else
2910 csp = smack_net_ambient; 3160 csp = smack_net_ambient;
2911 3161
2912 netlbl_secattr_destroy(&secattr); 3162 netlbl_secattr_destroy(&secattr);
2913 3163
2914#ifdef CONFIG_AUDIT 3164#ifdef CONFIG_AUDIT
2915 smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); 3165 smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
2916 ad.a.u.net->family = sk->sk_family; 3166 ad.a.u.net->family = sk->sk_family;
2917 ad.a.u.net->netif = skb->skb_iif; 3167 ad.a.u.net->netif = skb->skb_iif;
2918 ipv4_skb_to_auditdata(skb, &ad.a, NULL); 3168 ipv4_skb_to_auditdata(skb, &ad.a, NULL);
2919#endif 3169#endif
2920 /* 3170 /*
2921 * Receiving a packet requires that the other end 3171 * Receiving a packet requires that the other end
2922 * be able to write here. Read access is not required. 3172 * be able to write here. Read access is not required.
2923 * This is the simplist possible security model 3173 * This is the simplist possible security model
2924 * for networking. 3174 * for networking.
2925 */ 3175 */
2926 rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad); 3176 rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad);
2927 if (rc != 0) 3177 if (rc != 0)
2928 netlbl_skbuff_err(skb, rc, 0); 3178 netlbl_skbuff_err(skb, rc, 0);
3179 break;
3180 case PF_INET6:
3181 rc = smk_skb_to_addr_ipv6(skb, &sadd);
3182 if (rc == IPPROTO_UDP || rc == IPPROTO_TCP)
3183 rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
3184 else
3185 rc = 0;
3186 break;
3187 }
2929 return rc; 3188 return rc;
2930} 3189}
2931 3190
@@ -3063,9 +3322,17 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3063 struct lsm_network_audit net; 3322 struct lsm_network_audit net;
3064#endif 3323#endif
3065 3324
3066 /* handle mapped IPv4 packets arriving via IPv6 sockets */ 3325 if (family == PF_INET6) {
3067 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) 3326 /*
3068 family = PF_INET; 3327 * Handle mapped IPv4 packets arriving
3328 * via IPv6 sockets. Don't set up netlabel
3329 * processing on IPv6.
3330 */
3331 if (skb->protocol == htons(ETH_P_IP))
3332 family = PF_INET;
3333 else
3334 return 0;
3335 }
3069 3336
3070 netlbl_secattr_init(&secattr); 3337 netlbl_secattr_init(&secattr);
3071 rc = netlbl_skbuff_getattr(skb, family, &secattr); 3338 rc = netlbl_skbuff_getattr(skb, family, &secattr);
@@ -3498,6 +3765,7 @@ struct security_operations smack_ops = {
3498 .unix_may_send = smack_unix_may_send, 3765 .unix_may_send = smack_unix_may_send,
3499 3766
3500 .socket_post_create = smack_socket_post_create, 3767 .socket_post_create = smack_socket_post_create,
3768 .socket_bind = smack_socket_bind,
3501 .socket_connect = smack_socket_connect, 3769 .socket_connect = smack_socket_connect,
3502 .socket_sendmsg = smack_socket_sendmsg, 3770 .socket_sendmsg = smack_socket_sendmsg,
3503 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, 3771 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb,