aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/Smack.txt42
-rw-r--r--Documentation/feature-removal-schedule.txt11
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--include/linux/security.h13
-rw-r--r--include/net/cipso_ipv4.h17
-rw-r--r--include/net/netlabel.h17
-rw-r--r--net/ipv4/cipso_ipv4.c130
-rw-r--r--net/ipv4/syncookies.c9
-rw-r--r--net/ipv4/tcp_ipv4.c7
-rw-r--r--net/netlabel/netlabel_kapi.c165
-rw-r--r--net/socket.c2
-rw-r--r--security/capability.c5
-rw-r--r--security/security.c5
-rw-r--r--security/selinux/hooks.c207
-rw-r--r--security/selinux/include/netlabel.h27
-rw-r--r--security/selinux/netlabel.c186
-rw-r--r--security/selinux/selinuxfs.c68
-rw-r--r--security/smack/smack.h32
-rw-r--r--security/smack/smack_access.c66
-rw-r--r--security/smack/smack_lsm.c282
-rw-r--r--security/smack/smackfs.c218
-rw-r--r--security/tomoyo/common.h2
22 files changed, 783 insertions, 737 deletions
diff --git a/Documentation/Smack.txt b/Documentation/Smack.txt
index 989c2fcd8111..629c92e99783 100644
--- a/Documentation/Smack.txt
+++ b/Documentation/Smack.txt
@@ -184,14 +184,16 @@ length. Single character labels using special characters, that being anything
184other than a letter or digit, are reserved for use by the Smack development 184other than a letter or digit, are reserved for use by the Smack development
185team. Smack labels are unstructured, case sensitive, and the only operation 185team. Smack labels are unstructured, case sensitive, and the only operation
186ever performed on them is comparison for equality. Smack labels cannot 186ever performed on them is comparison for equality. Smack labels cannot
187contain unprintable characters or the "/" (slash) character. 187contain unprintable characters or the "/" (slash) character. Smack labels
188cannot begin with a '-', which is reserved for special options.
188 189
189There are some predefined labels: 190There are some predefined labels:
190 191
191 _ Pronounced "floor", a single underscore character. 192 _ Pronounced "floor", a single underscore character.
192 ^ Pronounced "hat", a single circumflex character. 193 ^ Pronounced "hat", a single circumflex character.
193 * Pronounced "star", a single asterisk character. 194 * Pronounced "star", a single asterisk character.
194 ? Pronounced "huh", a single question mark character. 195 ? Pronounced "huh", a single question mark character.
196 @ Pronounced "Internet", a single at sign character.
195 197
196Every task on a Smack system is assigned a label. System tasks, such as 198Every task on a Smack system is assigned a label. System tasks, such as
197init(8) and systems daemons, are run with the floor ("_") label. User tasks 199init(8) and systems daemons, are run with the floor ("_") label. User tasks
@@ -412,6 +414,36 @@ sockets.
412 A privileged program may set this to match the label of another 414 A privileged program may set this to match the label of another
413 task with which it hopes to communicate. 415 task with which it hopes to communicate.
414 416
417Smack Netlabel Exceptions
418
419You will often find that your labeled application has to talk to the outside,
420unlabeled world. To do this there's a special file /smack/netlabel where you can
421add some exceptions in the form of :
422@IP1 LABEL1 or
423@IP2/MASK LABEL2
424
425It means that your application will have unlabeled access to @IP1 if it has
426write access on LABEL1, and access to the subnet @IP2/MASK if it has write
427access on LABEL2.
428
429Entries in the /smack/netlabel file are matched by longest mask first, like in
430classless IPv4 routing.
431
432A special label '@' and an option '-CIPSO' can be used there :
433@ means Internet, any application with any label has access to it
434-CIPSO means standard CIPSO networking
435
436If you don't know what CIPSO is and don't plan to use it, you can just do :
437echo 127.0.0.1 -CIPSO > /smack/netlabel
438echo 0.0.0.0/0 @ > /smack/netlabel
439
440If you use CIPSO on your 192.168.0.0/16 local network and need also unlabeled
441Internet access, you can have :
442echo 127.0.0.1 -CIPSO > /smack/netlabel
443echo 192.168.0.0/16 -CIPSO > /smack/netlabel
444echo 0.0.0.0/0 @ > /smack/netlabel
445
446
415Writing Applications for Smack 447Writing Applications for Smack
416 448
417There are three sorts of applications that will run on a Smack system. How an 449There are three sorts of applications that will run on a Smack system. How an
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 7907586c6e08..1135996bec8b 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -356,17 +356,6 @@ Who: Hans de Goede <hdegoede@redhat.com>
356 356
357--------------------------- 357---------------------------
358 358
359What: SELinux "compat_net" functionality
360When: 2.6.30 at the earliest
361Why: In 2.6.18 the Secmark concept was introduced to replace the "compat_net"
362 network access control functionality of SELinux. Secmark offers both
363 better performance and greater flexibility than the "compat_net"
364 mechanism. Now that the major Linux distributions have moved to
365 Secmark, it is time to deprecate the older mechanism and start the
366 process of removing the old code.
367Who: Paul Moore <paul.moore@hp.com>
368---------------------------
369
370What: sysfs ui for changing p4-clockmod parameters 359What: sysfs ui for changing p4-clockmod parameters
371When: September 2009 360When: September 2009
372Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and 361Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d1e2fcb6298b..be3bde51b564 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2030,15 +2030,6 @@ and is between 256 and 4096 characters. It is defined in the file
2030 If enabled at boot time, /selinux/disable can be used 2030 If enabled at boot time, /selinux/disable can be used
2031 later to disable prior to initial policy load. 2031 later to disable prior to initial policy load.
2032 2032
2033 selinux_compat_net =
2034 [SELINUX] Set initial selinux_compat_net flag value.
2035 Format: { "0" | "1" }
2036 0 -- use new secmark-based packet controls
2037 1 -- use legacy packet controls
2038 Default value is 0 (preferred).
2039 Value can be changed at runtime via
2040 /selinux/compat_net.
2041
2042 serialnumber [BUGS=X86-32] 2033 serialnumber [BUGS=X86-32]
2043 2034
2044 shapers= [NET] 2035 shapers= [NET]
diff --git a/include/linux/security.h b/include/linux/security.h
index 1f2ab6353c00..54ed15799a83 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -880,11 +880,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
880 * @sock contains the listening socket structure. 880 * @sock contains the listening socket structure.
881 * @newsock contains the newly created server socket for connection. 881 * @newsock contains the newly created server socket for connection.
882 * Return 0 if permission is granted. 882 * Return 0 if permission is granted.
883 * @socket_post_accept:
884 * This hook allows a security module to copy security
885 * information into the newly created socket's inode.
886 * @sock contains the listening socket structure.
887 * @newsock contains the newly created server socket for connection.
888 * @socket_sendmsg: 883 * @socket_sendmsg:
889 * Check permission before transmitting a message to another socket. 884 * Check permission before transmitting a message to another socket.
890 * @sock contains the socket structure. 885 * @sock contains the socket structure.
@@ -1554,8 +1549,6 @@ struct security_operations {
1554 struct sockaddr *address, int addrlen); 1549 struct sockaddr *address, int addrlen);
1555 int (*socket_listen) (struct socket *sock, int backlog); 1550 int (*socket_listen) (struct socket *sock, int backlog);
1556 int (*socket_accept) (struct socket *sock, struct socket *newsock); 1551 int (*socket_accept) (struct socket *sock, struct socket *newsock);
1557 void (*socket_post_accept) (struct socket *sock,
1558 struct socket *newsock);
1559 int (*socket_sendmsg) (struct socket *sock, 1552 int (*socket_sendmsg) (struct socket *sock,
1560 struct msghdr *msg, int size); 1553 struct msghdr *msg, int size);
1561 int (*socket_recvmsg) (struct socket *sock, 1554 int (*socket_recvmsg) (struct socket *sock,
@@ -2537,7 +2530,6 @@ int security_socket_bind(struct socket *sock, struct sockaddr *address, int addr
2537int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen); 2530int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen);
2538int security_socket_listen(struct socket *sock, int backlog); 2531int security_socket_listen(struct socket *sock, int backlog);
2539int security_socket_accept(struct socket *sock, struct socket *newsock); 2532int security_socket_accept(struct socket *sock, struct socket *newsock);
2540void security_socket_post_accept(struct socket *sock, struct socket *newsock);
2541int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size); 2533int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size);
2542int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, 2534int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
2543 int size, int flags); 2535 int size, int flags);
@@ -2616,11 +2608,6 @@ static inline int security_socket_accept(struct socket *sock,
2616 return 0; 2608 return 0;
2617} 2609}
2618 2610
2619static inline void security_socket_post_accept(struct socket *sock,
2620 struct socket *newsock)
2621{
2622}
2623
2624static inline int security_socket_sendmsg(struct socket *sock, 2611static inline int security_socket_sendmsg(struct socket *sock,
2625 struct msghdr *msg, int size) 2612 struct msghdr *msg, int size)
2626{ 2613{
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index bedc7f62e35d..abd443604c9f 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -40,6 +40,7 @@
40#include <linux/net.h> 40#include <linux/net.h>
41#include <linux/skbuff.h> 41#include <linux/skbuff.h>
42#include <net/netlabel.h> 42#include <net/netlabel.h>
43#include <net/request_sock.h>
43#include <asm/atomic.h> 44#include <asm/atomic.h>
44 45
45/* known doi values */ 46/* known doi values */
@@ -215,6 +216,10 @@ int cipso_v4_sock_setattr(struct sock *sk,
215 const struct netlbl_lsm_secattr *secattr); 216 const struct netlbl_lsm_secattr *secattr);
216void cipso_v4_sock_delattr(struct sock *sk); 217void cipso_v4_sock_delattr(struct sock *sk);
217int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); 218int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
219int cipso_v4_req_setattr(struct request_sock *req,
220 const struct cipso_v4_doi *doi_def,
221 const struct netlbl_lsm_secattr *secattr);
222void cipso_v4_req_delattr(struct request_sock *req);
218int cipso_v4_skbuff_setattr(struct sk_buff *skb, 223int cipso_v4_skbuff_setattr(struct sk_buff *skb,
219 const struct cipso_v4_doi *doi_def, 224 const struct cipso_v4_doi *doi_def,
220 const struct netlbl_lsm_secattr *secattr); 225 const struct netlbl_lsm_secattr *secattr);
@@ -247,6 +252,18 @@ static inline int cipso_v4_sock_getattr(struct sock *sk,
247 return -ENOSYS; 252 return -ENOSYS;
248} 253}
249 254
255static inline int cipso_v4_req_setattr(struct request_sock *req,
256 const struct cipso_v4_doi *doi_def,
257 const struct netlbl_lsm_secattr *secattr)
258{
259 return -ENOSYS;
260}
261
262static inline void cipso_v4_req_delattr(struct request_sock *req)
263{
264 return;
265}
266
250static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb, 267static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
251 const struct cipso_v4_doi *doi_def, 268 const struct cipso_v4_doi *doi_def,
252 const struct netlbl_lsm_secattr *secattr) 269 const struct netlbl_lsm_secattr *secattr)
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 749011eedc0b..60ebbc1fef46 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -36,6 +36,7 @@
36#include <linux/in.h> 36#include <linux/in.h>
37#include <linux/in6.h> 37#include <linux/in6.h>
38#include <net/netlink.h> 38#include <net/netlink.h>
39#include <net/request_sock.h>
39#include <asm/atomic.h> 40#include <asm/atomic.h>
40 41
41struct cipso_v4_doi; 42struct cipso_v4_doi;
@@ -406,6 +407,7 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
406 */ 407 */
407int netlbl_enabled(void); 408int netlbl_enabled(void);
408int netlbl_sock_setattr(struct sock *sk, 409int netlbl_sock_setattr(struct sock *sk,
410 u16 family,
409 const struct netlbl_lsm_secattr *secattr); 411 const struct netlbl_lsm_secattr *secattr);
410void netlbl_sock_delattr(struct sock *sk); 412void netlbl_sock_delattr(struct sock *sk);
411int netlbl_sock_getattr(struct sock *sk, 413int netlbl_sock_getattr(struct sock *sk,
@@ -413,6 +415,9 @@ int netlbl_sock_getattr(struct sock *sk,
413int netlbl_conn_setattr(struct sock *sk, 415int netlbl_conn_setattr(struct sock *sk,
414 struct sockaddr *addr, 416 struct sockaddr *addr,
415 const struct netlbl_lsm_secattr *secattr); 417 const struct netlbl_lsm_secattr *secattr);
418int netlbl_req_setattr(struct request_sock *req,
419 const struct netlbl_lsm_secattr *secattr);
420void netlbl_req_delattr(struct request_sock *req);
416int netlbl_skbuff_setattr(struct sk_buff *skb, 421int netlbl_skbuff_setattr(struct sk_buff *skb,
417 u16 family, 422 u16 family,
418 const struct netlbl_lsm_secattr *secattr); 423 const struct netlbl_lsm_secattr *secattr);
@@ -519,7 +524,8 @@ static inline int netlbl_enabled(void)
519 return 0; 524 return 0;
520} 525}
521static inline int netlbl_sock_setattr(struct sock *sk, 526static inline int netlbl_sock_setattr(struct sock *sk,
522 const struct netlbl_lsm_secattr *secattr) 527 u16 family,
528 const struct netlbl_lsm_secattr *secattr)
523{ 529{
524 return -ENOSYS; 530 return -ENOSYS;
525} 531}
@@ -537,6 +543,15 @@ static inline int netlbl_conn_setattr(struct sock *sk,
537{ 543{
538 return -ENOSYS; 544 return -ENOSYS;
539} 545}
546static inline int netlbl_req_setattr(struct request_sock *req,
547 const struct netlbl_lsm_secattr *secattr)
548{
549 return -ENOSYS;
550}
551static inline void netlbl_req_delattr(struct request_sock *req)
552{
553 return;
554}
540static inline int netlbl_skbuff_setattr(struct sk_buff *skb, 555static inline int netlbl_skbuff_setattr(struct sk_buff *skb,
541 u16 family, 556 u16 family,
542 const struct netlbl_lsm_secattr *secattr) 557 const struct netlbl_lsm_secattr *secattr)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 7bc992976d29..039cc1ffe977 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1942,23 +1942,85 @@ socket_setattr_failure:
1942} 1942}
1943 1943
1944/** 1944/**
1945 * cipso_v4_sock_delattr - Delete the CIPSO option from a socket 1945 * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
1946 * @sk: the socket 1946 * @req: the connection request socket
1947 * @doi_def: the CIPSO DOI to use
1948 * @secattr: the specific security attributes of the socket
1947 * 1949 *
1948 * Description: 1950 * Description:
1949 * Removes the CIPSO option from a socket, if present. 1951 * Set the CIPSO option on the given socket using the DOI definition and
1952 * security attributes passed to the function. Returns zero on success and
1953 * negative values on failure.
1950 * 1954 *
1951 */ 1955 */
1952void cipso_v4_sock_delattr(struct sock *sk) 1956int cipso_v4_req_setattr(struct request_sock *req,
1957 const struct cipso_v4_doi *doi_def,
1958 const struct netlbl_lsm_secattr *secattr)
1953{ 1959{
1954 u8 hdr_delta; 1960 int ret_val = -EPERM;
1955 struct ip_options *opt; 1961 unsigned char *buf = NULL;
1956 struct inet_sock *sk_inet; 1962 u32 buf_len;
1963 u32 opt_len;
1964 struct ip_options *opt = NULL;
1965 struct inet_request_sock *req_inet;
1957 1966
1958 sk_inet = inet_sk(sk); 1967 /* We allocate the maximum CIPSO option size here so we are probably
1959 opt = sk_inet->opt; 1968 * being a little wasteful, but it makes our life _much_ easier later
1960 if (opt == NULL || opt->cipso == 0) 1969 * on and after all we are only talking about 40 bytes. */
1961 return; 1970 buf_len = CIPSO_V4_OPT_LEN_MAX;
1971 buf = kmalloc(buf_len, GFP_ATOMIC);
1972 if (buf == NULL) {
1973 ret_val = -ENOMEM;
1974 goto req_setattr_failure;
1975 }
1976
1977 ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
1978 if (ret_val < 0)
1979 goto req_setattr_failure;
1980 buf_len = ret_val;
1981
1982 /* We can't use ip_options_get() directly because it makes a call to
1983 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
1984 * we won't always have CAP_NET_RAW even though we _always_ want to
1985 * set the IPOPT_CIPSO option. */
1986 opt_len = (buf_len + 3) & ~3;
1987 opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
1988 if (opt == NULL) {
1989 ret_val = -ENOMEM;
1990 goto req_setattr_failure;
1991 }
1992 memcpy(opt->__data, buf, buf_len);
1993 opt->optlen = opt_len;
1994 opt->cipso = sizeof(struct iphdr);
1995 kfree(buf);
1996 buf = NULL;
1997
1998 req_inet = inet_rsk(req);
1999 opt = xchg(&req_inet->opt, opt);
2000 kfree(opt);
2001
2002 return 0;
2003
2004req_setattr_failure:
2005 kfree(buf);
2006 kfree(opt);
2007 return ret_val;
2008}
2009
2010/**
2011 * cipso_v4_delopt - Delete the CIPSO option from a set of IP options
2012 * @opt_ptr: IP option pointer
2013 *
2014 * Description:
2015 * Deletes the CIPSO IP option from a set of IP options and makes the necessary
2016 * adjustments to the IP option structure. Returns zero on success, negative
2017 * values on failure.
2018 *
2019 */
2020int cipso_v4_delopt(struct ip_options **opt_ptr)
2021{
2022 int hdr_delta = 0;
2023 struct ip_options *opt = *opt_ptr;
1962 2024
1963 if (opt->srr || opt->rr || opt->ts || opt->router_alert) { 2025 if (opt->srr || opt->rr || opt->ts || opt->router_alert) {
1964 u8 cipso_len; 2026 u8 cipso_len;
@@ -2003,11 +2065,34 @@ void cipso_v4_sock_delattr(struct sock *sk)
2003 } else { 2065 } else {
2004 /* only the cipso option was present on the socket so we can 2066 /* only the cipso option was present on the socket so we can
2005 * remove the entire option struct */ 2067 * remove the entire option struct */
2006 sk_inet->opt = NULL; 2068 *opt_ptr = NULL;
2007 hdr_delta = opt->optlen; 2069 hdr_delta = opt->optlen;
2008 kfree(opt); 2070 kfree(opt);
2009 } 2071 }
2010 2072
2073 return hdr_delta;
2074}
2075
2076/**
2077 * cipso_v4_sock_delattr - Delete the CIPSO option from a socket
2078 * @sk: the socket
2079 *
2080 * Description:
2081 * Removes the CIPSO option from a socket, if present.
2082 *
2083 */
2084void cipso_v4_sock_delattr(struct sock *sk)
2085{
2086 int hdr_delta;
2087 struct ip_options *opt;
2088 struct inet_sock *sk_inet;
2089
2090 sk_inet = inet_sk(sk);
2091 opt = sk_inet->opt;
2092 if (opt == NULL || opt->cipso == 0)
2093 return;
2094
2095 hdr_delta = cipso_v4_delopt(&sk_inet->opt);
2011 if (sk_inet->is_icsk && hdr_delta > 0) { 2096 if (sk_inet->is_icsk && hdr_delta > 0) {
2012 struct inet_connection_sock *sk_conn = inet_csk(sk); 2097 struct inet_connection_sock *sk_conn = inet_csk(sk);
2013 sk_conn->icsk_ext_hdr_len -= hdr_delta; 2098 sk_conn->icsk_ext_hdr_len -= hdr_delta;
@@ -2016,6 +2101,27 @@ void cipso_v4_sock_delattr(struct sock *sk)
2016} 2101}
2017 2102
2018/** 2103/**
2104 * cipso_v4_req_delattr - Delete the CIPSO option from a request socket
2105 * @reg: the request socket
2106 *
2107 * Description:
2108 * Removes the CIPSO option from a request socket, if present.
2109 *
2110 */
2111void cipso_v4_req_delattr(struct request_sock *req)
2112{
2113 struct ip_options *opt;
2114 struct inet_request_sock *req_inet;
2115
2116 req_inet = inet_rsk(req);
2117 opt = req_inet->opt;
2118 if (opt == NULL || opt->cipso == 0)
2119 return;
2120
2121 cipso_v4_delopt(&req_inet->opt);
2122}
2123
2124/**
2019 * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions 2125 * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
2020 * @cipso: the CIPSO v4 option 2126 * @cipso: the CIPSO v4 option
2021 * @secattr: the security attributes 2127 * @secattr: the security attributes
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index d346c22aa6ae..b35a950d2e06 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -288,10 +288,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
288 if (!req) 288 if (!req)
289 goto out; 289 goto out;
290 290
291 if (security_inet_conn_request(sk, skb, req)) {
292 reqsk_free(req);
293 goto out;
294 }
295 ireq = inet_rsk(req); 291 ireq = inet_rsk(req);
296 treq = tcp_rsk(req); 292 treq = tcp_rsk(req);
297 treq->rcv_isn = ntohl(th->seq) - 1; 293 treq->rcv_isn = ntohl(th->seq) - 1;
@@ -322,6 +318,11 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
322 } 318 }
323 } 319 }
324 320
321 if (security_inet_conn_request(sk, skb, req)) {
322 reqsk_free(req);
323 goto out;
324 }
325
325 req->expires = 0UL; 326 req->expires = 0UL;
326 req->retrans = 0; 327 req->retrans = 0;
327 328
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index d0a314879d81..5d427f86b414 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1230,14 +1230,15 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
1230 1230
1231 tcp_openreq_init(req, &tmp_opt, skb); 1231 tcp_openreq_init(req, &tmp_opt, skb);
1232 1232
1233 if (security_inet_conn_request(sk, skb, req))
1234 goto drop_and_free;
1235
1236 ireq = inet_rsk(req); 1233 ireq = inet_rsk(req);
1237 ireq->loc_addr = daddr; 1234 ireq->loc_addr = daddr;
1238 ireq->rmt_addr = saddr; 1235 ireq->rmt_addr = saddr;
1239 ireq->no_srccheck = inet_sk(sk)->transparent; 1236 ireq->no_srccheck = inet_sk(sk)->transparent;
1240 ireq->opt = tcp_v4_save_options(sk, skb); 1237 ireq->opt = tcp_v4_save_options(sk, skb);
1238
1239 if (security_inet_conn_request(sk, skb, req))
1240 goto drop_and_free;
1241
1241 if (!want_cookie) 1242 if (!want_cookie)
1242 TCP_ECN_create_request(req, tcp_hdr(skb)); 1243 TCP_ECN_create_request(req, tcp_hdr(skb));
1243 1244
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index fd9229db075c..b0e582f2d37a 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -619,8 +619,9 @@ int netlbl_enabled(void)
619} 619}
620 620
621/** 621/**
622 * netlbl_socket_setattr - Label a socket using the correct protocol 622 * netlbl_sock_setattr - Label a socket using the correct protocol
623 * @sk: the socket to label 623 * @sk: the socket to label
624 * @family: protocol family
624 * @secattr: the security attributes 625 * @secattr: the security attributes
625 * 626 *
626 * Description: 627 * Description:
@@ -633,29 +634,45 @@ int netlbl_enabled(void)
633 * 634 *
634 */ 635 */
635int netlbl_sock_setattr(struct sock *sk, 636int netlbl_sock_setattr(struct sock *sk,
637 u16 family,
636 const struct netlbl_lsm_secattr *secattr) 638 const struct netlbl_lsm_secattr *secattr)
637{ 639{
638 int ret_val = -ENOENT; 640 int ret_val;
639 struct netlbl_dom_map *dom_entry; 641 struct netlbl_dom_map *dom_entry;
640 642
641 rcu_read_lock(); 643 rcu_read_lock();
642 dom_entry = netlbl_domhsh_getentry(secattr->domain); 644 dom_entry = netlbl_domhsh_getentry(secattr->domain);
643 if (dom_entry == NULL) 645 if (dom_entry == NULL) {
646 ret_val = -ENOENT;
644 goto socket_setattr_return; 647 goto socket_setattr_return;
645 switch (dom_entry->type) { 648 }
646 case NETLBL_NLTYPE_ADDRSELECT: 649 switch (family) {
647 ret_val = -EDESTADDRREQ; 650 case AF_INET:
648 break; 651 switch (dom_entry->type) {
649 case NETLBL_NLTYPE_CIPSOV4: 652 case NETLBL_NLTYPE_ADDRSELECT:
650 ret_val = cipso_v4_sock_setattr(sk, 653 ret_val = -EDESTADDRREQ;
651 dom_entry->type_def.cipsov4, 654 break;
652 secattr); 655 case NETLBL_NLTYPE_CIPSOV4:
656 ret_val = cipso_v4_sock_setattr(sk,
657 dom_entry->type_def.cipsov4,
658 secattr);
659 break;
660 case NETLBL_NLTYPE_UNLABELED:
661 ret_val = 0;
662 break;
663 default:
664 ret_val = -ENOENT;
665 }
653 break; 666 break;
654 case NETLBL_NLTYPE_UNLABELED: 667#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
668 case AF_INET6:
669 /* since we don't support any IPv6 labeling protocols right
670 * now we can optimize everything away until we do */
655 ret_val = 0; 671 ret_val = 0;
656 break; 672 break;
673#endif /* IPv6 */
657 default: 674 default:
658 ret_val = -ENOENT; 675 ret_val = -EPROTONOSUPPORT;
659 } 676 }
660 677
661socket_setattr_return: 678socket_setattr_return:
@@ -689,9 +706,25 @@ void netlbl_sock_delattr(struct sock *sk)
689 * on failure. 706 * on failure.
690 * 707 *
691 */ 708 */
692int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) 709int netlbl_sock_getattr(struct sock *sk,
710 struct netlbl_lsm_secattr *secattr)
693{ 711{
694 return cipso_v4_sock_getattr(sk, secattr); 712 int ret_val;
713
714 switch (sk->sk_family) {
715 case AF_INET:
716 ret_val = cipso_v4_sock_getattr(sk, secattr);
717 break;
718#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
719 case AF_INET6:
720 ret_val = -ENOMSG;
721 break;
722#endif /* IPv6 */
723 default:
724 ret_val = -EPROTONOSUPPORT;
725 }
726
727 return ret_val;
695} 728}
696 729
697/** 730/**
@@ -748,7 +781,7 @@ int netlbl_conn_setattr(struct sock *sk,
748 break; 781 break;
749#endif /* IPv6 */ 782#endif /* IPv6 */
750 default: 783 default:
751 ret_val = 0; 784 ret_val = -EPROTONOSUPPORT;
752 } 785 }
753 786
754conn_setattr_return: 787conn_setattr_return:
@@ -757,6 +790,90 @@ conn_setattr_return:
757} 790}
758 791
759/** 792/**
793 * netlbl_req_setattr - Label a request socket using the correct protocol
794 * @req: the request socket to label
795 * @secattr: the security attributes
796 *
797 * Description:
798 * Attach the correct label to the given socket using the security attributes
799 * specified in @secattr. Returns zero on success, negative values on failure.
800 *
801 */
802int netlbl_req_setattr(struct request_sock *req,
803 const struct netlbl_lsm_secattr *secattr)
804{
805 int ret_val;
806 struct netlbl_dom_map *dom_entry;
807 struct netlbl_domaddr4_map *af4_entry;
808 u32 proto_type;
809 struct cipso_v4_doi *proto_cv4;
810
811 rcu_read_lock();
812 dom_entry = netlbl_domhsh_getentry(secattr->domain);
813 if (dom_entry == NULL) {
814 ret_val = -ENOENT;
815 goto req_setattr_return;
816 }
817 switch (req->rsk_ops->family) {
818 case AF_INET:
819 if (dom_entry->type == NETLBL_NLTYPE_ADDRSELECT) {
820 struct inet_request_sock *req_inet = inet_rsk(req);
821 af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
822 req_inet->rmt_addr);
823 if (af4_entry == NULL) {
824 ret_val = -ENOENT;
825 goto req_setattr_return;
826 }
827 proto_type = af4_entry->type;
828 proto_cv4 = af4_entry->type_def.cipsov4;
829 } else {
830 proto_type = dom_entry->type;
831 proto_cv4 = dom_entry->type_def.cipsov4;
832 }
833 switch (proto_type) {
834 case NETLBL_NLTYPE_CIPSOV4:
835 ret_val = cipso_v4_req_setattr(req, proto_cv4, secattr);
836 break;
837 case NETLBL_NLTYPE_UNLABELED:
838 /* just delete the protocols we support for right now
839 * but we could remove other protocols if needed */
840 cipso_v4_req_delattr(req);
841 ret_val = 0;
842 break;
843 default:
844 ret_val = -ENOENT;
845 }
846 break;
847#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
848 case AF_INET6:
849 /* since we don't support any IPv6 labeling protocols right
850 * now we can optimize everything away until we do */
851 ret_val = 0;
852 break;
853#endif /* IPv6 */
854 default:
855 ret_val = -EPROTONOSUPPORT;
856 }
857
858req_setattr_return:
859 rcu_read_unlock();
860 return ret_val;
861}
862
863/**
864* netlbl_req_delattr - Delete all the NetLabel labels on a socket
865* @req: the socket
866*
867* Description:
868* Remove all the NetLabel labeling from @req.
869*
870*/
871void netlbl_req_delattr(struct request_sock *req)
872{
873 cipso_v4_req_delattr(req);
874}
875
876/**
760 * netlbl_skbuff_setattr - Label a packet using the correct protocol 877 * netlbl_skbuff_setattr - Label a packet using the correct protocol
761 * @skb: the packet 878 * @skb: the packet
762 * @family: protocol family 879 * @family: protocol family
@@ -808,7 +925,7 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
808 break; 925 break;
809#endif /* IPv6 */ 926#endif /* IPv6 */
810 default: 927 default:
811 ret_val = 0; 928 ret_val = -EPROTONOSUPPORT;
812 } 929 }
813 930
814skbuff_setattr_return: 931skbuff_setattr_return:
@@ -833,9 +950,17 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
833 u16 family, 950 u16 family,
834 struct netlbl_lsm_secattr *secattr) 951 struct netlbl_lsm_secattr *secattr)
835{ 952{
836 if (CIPSO_V4_OPTEXIST(skb) && 953 switch (family) {
837 cipso_v4_skbuff_getattr(skb, secattr) == 0) 954 case AF_INET:
838 return 0; 955 if (CIPSO_V4_OPTEXIST(skb) &&
956 cipso_v4_skbuff_getattr(skb, secattr) == 0)
957 return 0;
958 break;
959#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
960 case AF_INET6:
961 break;
962#endif /* IPv6 */
963 }
839 964
840 return netlbl_unlabel_getattr(skb, family, secattr); 965 return netlbl_unlabel_getattr(skb, family, secattr);
841} 966}
diff --git a/net/socket.c b/net/socket.c
index 0b14b79c03af..91d0c0254ffe 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1536,8 +1536,6 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
1536 fd_install(newfd, newfile); 1536 fd_install(newfd, newfile);
1537 err = newfd; 1537 err = newfd;
1538 1538
1539 security_socket_post_accept(sock, newsock);
1540
1541out_put: 1539out_put:
1542 fput_light(sock->file, fput_needed); 1540 fput_light(sock->file, fput_needed);
1543out: 1541out:
diff --git a/security/capability.c b/security/capability.c
index c545bd1300b5..21b6cead6a8e 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -620,10 +620,6 @@ static int cap_socket_accept(struct socket *sock, struct socket *newsock)
620 return 0; 620 return 0;
621} 621}
622 622
623static void cap_socket_post_accept(struct socket *sock, struct socket *newsock)
624{
625}
626
627static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) 623static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
628{ 624{
629 return 0; 625 return 0;
@@ -1014,7 +1010,6 @@ void security_fixup_ops(struct security_operations *ops)
1014 set_to_cap_if_null(ops, socket_connect); 1010 set_to_cap_if_null(ops, socket_connect);
1015 set_to_cap_if_null(ops, socket_listen); 1011 set_to_cap_if_null(ops, socket_listen);
1016 set_to_cap_if_null(ops, socket_accept); 1012 set_to_cap_if_null(ops, socket_accept);
1017 set_to_cap_if_null(ops, socket_post_accept);
1018 set_to_cap_if_null(ops, socket_sendmsg); 1013 set_to_cap_if_null(ops, socket_sendmsg);
1019 set_to_cap_if_null(ops, socket_recvmsg); 1014 set_to_cap_if_null(ops, socket_recvmsg);
1020 set_to_cap_if_null(ops, socket_getsockname); 1015 set_to_cap_if_null(ops, socket_getsockname);
diff --git a/security/security.c b/security/security.c
index c3586c0d97e2..206e53844d2f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1007,11 +1007,6 @@ int security_socket_accept(struct socket *sock, struct socket *newsock)
1007 return security_ops->socket_accept(sock, newsock); 1007 return security_ops->socket_accept(sock, newsock);
1008} 1008}
1009 1009
1010void security_socket_post_accept(struct socket *sock, struct socket *newsock)
1011{
1012 security_ops->socket_post_accept(sock, newsock);
1013}
1014
1015int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) 1010int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
1016{ 1011{
1017 return security_ops->socket_sendmsg(sock, msg, size); 1012 return security_ops->socket_sendmsg(sock, msg, size);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7c52ba243c64..ba808ef6babb 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -93,7 +93,6 @@
93 93
94extern unsigned int policydb_loaded_version; 94extern unsigned int policydb_loaded_version;
95extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); 95extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
96extern int selinux_compat_net;
97extern struct security_operations *security_ops; 96extern struct security_operations *security_ops;
98 97
99/* SECMARK reference count */ 98/* SECMARK reference count */
@@ -311,7 +310,7 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
311 ssec->sid = SECINITSID_UNLABELED; 310 ssec->sid = SECINITSID_UNLABELED;
312 sk->sk_security = ssec; 311 sk->sk_security = ssec;
313 312
314 selinux_netlbl_sk_security_reset(ssec, family); 313 selinux_netlbl_sk_security_reset(ssec);
315 314
316 return 0; 315 return 0;
317} 316}
@@ -2945,7 +2944,6 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2945static int selinux_revalidate_file_permission(struct file *file, int mask) 2944static int selinux_revalidate_file_permission(struct file *file, int mask)
2946{ 2945{
2947 const struct cred *cred = current_cred(); 2946 const struct cred *cred = current_cred();
2948 int rc;
2949 struct inode *inode = file->f_path.dentry->d_inode; 2947 struct inode *inode = file->f_path.dentry->d_inode;
2950 2948
2951 if (!mask) { 2949 if (!mask) {
@@ -2957,29 +2955,15 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
2957 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) 2955 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2958 mask |= MAY_APPEND; 2956 mask |= MAY_APPEND;
2959 2957
2960 rc = file_has_perm(cred, file, 2958 return file_has_perm(cred, file,
2961 file_mask_to_av(inode->i_mode, mask)); 2959 file_mask_to_av(inode->i_mode, mask));
2962 if (rc)
2963 return rc;
2964
2965 return selinux_netlbl_inode_permission(inode, mask);
2966} 2960}
2967 2961
2968static int selinux_file_permission(struct file *file, int mask) 2962static int selinux_file_permission(struct file *file, int mask)
2969{ 2963{
2970 struct inode *inode = file->f_path.dentry->d_inode; 2964 if (!mask)
2971 struct file_security_struct *fsec = file->f_security;
2972 struct inode_security_struct *isec = inode->i_security;
2973 u32 sid = current_sid();
2974
2975 if (!mask) {
2976 /* No permission to check. Existence test. */ 2965 /* No permission to check. Existence test. */
2977 return 0; 2966 return 0;
2978 }
2979
2980 if (sid == fsec->sid && fsec->isid == isec->sid
2981 && fsec->pseqno == avc_policy_seqno())
2982 return selinux_netlbl_inode_permission(inode, mask);
2983 2967
2984 return selinux_revalidate_file_permission(file, mask); 2968 return selinux_revalidate_file_permission(file, mask);
2985} 2969}
@@ -3723,7 +3707,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3723 sksec = sock->sk->sk_security; 3707 sksec = sock->sk->sk_security;
3724 sksec->sid = isec->sid; 3708 sksec->sid = isec->sid;
3725 sksec->sclass = isec->sclass; 3709 sksec->sclass = isec->sclass;
3726 err = selinux_netlbl_socket_post_create(sock); 3710 err = selinux_netlbl_socket_post_create(sock->sk, family);
3727 } 3711 }
3728 3712
3729 return err; 3713 return err;
@@ -3914,13 +3898,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3914static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3898static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3915 int size) 3899 int size)
3916{ 3900{
3917 int rc; 3901 return socket_has_perm(current, sock, SOCKET__WRITE);
3918
3919 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3920 if (rc)
3921 return rc;
3922
3923 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
3924} 3902}
3925 3903
3926static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3904static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -4040,72 +4018,6 @@ static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4040 SECCLASS_NODE, NODE__RECVFROM, ad); 4018 SECCLASS_NODE, NODE__RECVFROM, ad);
4041} 4019}
4042 4020
4043static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
4044 struct sk_buff *skb,
4045 struct avc_audit_data *ad,
4046 u16 family,
4047 char *addrp)
4048{
4049 int err;
4050 struct sk_security_struct *sksec = sk->sk_security;
4051 u16 sk_class;
4052 u32 netif_perm, node_perm, recv_perm;
4053 u32 port_sid, node_sid, if_sid, sk_sid;
4054
4055 sk_sid = sksec->sid;
4056 sk_class = sksec->sclass;
4057
4058 switch (sk_class) {
4059 case SECCLASS_UDP_SOCKET:
4060 netif_perm = NETIF__UDP_RECV;
4061 node_perm = NODE__UDP_RECV;
4062 recv_perm = UDP_SOCKET__RECV_MSG;
4063 break;
4064 case SECCLASS_TCP_SOCKET:
4065 netif_perm = NETIF__TCP_RECV;
4066 node_perm = NODE__TCP_RECV;
4067 recv_perm = TCP_SOCKET__RECV_MSG;
4068 break;
4069 case SECCLASS_DCCP_SOCKET:
4070 netif_perm = NETIF__DCCP_RECV;
4071 node_perm = NODE__DCCP_RECV;
4072 recv_perm = DCCP_SOCKET__RECV_MSG;
4073 break;
4074 default:
4075 netif_perm = NETIF__RAWIP_RECV;
4076 node_perm = NODE__RAWIP_RECV;
4077 recv_perm = 0;
4078 break;
4079 }
4080
4081 err = sel_netif_sid(skb->iif, &if_sid);
4082 if (err)
4083 return err;
4084 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4085 if (err)
4086 return err;
4087
4088 err = sel_netnode_sid(addrp, family, &node_sid);
4089 if (err)
4090 return err;
4091 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
4092 if (err)
4093 return err;
4094
4095 if (!recv_perm)
4096 return 0;
4097 err = sel_netport_sid(sk->sk_protocol,
4098 ntohs(ad->u.net.sport), &port_sid);
4099 if (unlikely(err)) {
4100 printk(KERN_WARNING
4101 "SELinux: failure in"
4102 " selinux_sock_rcv_skb_iptables_compat(),"
4103 " network port label not found\n");
4104 return err;
4105 }
4106 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
4107}
4108
4109static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 4021static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4110 u16 family) 4022 u16 family)
4111{ 4023{
@@ -4123,14 +4035,12 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4123 if (err) 4035 if (err)
4124 return err; 4036 return err;
4125 4037
4126 if (selinux_compat_net) 4038 if (selinux_secmark_enabled()) {
4127 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
4128 family, addrp);
4129 else if (selinux_secmark_enabled())
4130 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4039 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4131 PACKET__RECV, &ad); 4040 PACKET__RECV, &ad);
4132 if (err) 4041 if (err)
4133 return err; 4042 return err;
4043 }
4134 4044
4135 if (selinux_policycap_netpeer) { 4045 if (selinux_policycap_netpeer) {
4136 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); 4046 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4172,7 +4082,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4172 * to the selinux_sock_rcv_skb_compat() function to deal with the 4082 * to the selinux_sock_rcv_skb_compat() function to deal with the
4173 * special handling. We do this in an attempt to keep this function 4083 * special handling. We do this in an attempt to keep this function
4174 * as fast and as clean as possible. */ 4084 * as fast and as clean as possible. */
4175 if (selinux_compat_net || !selinux_policycap_netpeer) 4085 if (!selinux_policycap_netpeer)
4176 return selinux_sock_rcv_skb_compat(sk, skb, family); 4086 return selinux_sock_rcv_skb_compat(sk, skb, family);
4177 4087
4178 secmark_active = selinux_secmark_enabled(); 4088 secmark_active = selinux_secmark_enabled();
@@ -4304,7 +4214,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4304 newssec->peer_sid = ssec->peer_sid; 4214 newssec->peer_sid = ssec->peer_sid;
4305 newssec->sclass = ssec->sclass; 4215 newssec->sclass = ssec->sclass;
4306 4216
4307 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family); 4217 selinux_netlbl_sk_security_reset(newssec);
4308} 4218}
4309 4219
4310static void selinux_sk_getsecid(struct sock *sk, u32 *secid) 4220static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -4348,16 +4258,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4348 if (peersid == SECSID_NULL) { 4258 if (peersid == SECSID_NULL) {
4349 req->secid = sksec->sid; 4259 req->secid = sksec->sid;
4350 req->peer_secid = SECSID_NULL; 4260 req->peer_secid = SECSID_NULL;
4351 return 0; 4261 } else {
4262 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4263 if (err)
4264 return err;
4265 req->secid = newsid;
4266 req->peer_secid = peersid;
4352 } 4267 }
4353 4268
4354 err = security_sid_mls_copy(sksec->sid, peersid, &newsid); 4269 return selinux_netlbl_inet_conn_request(req, family);
4355 if (err)
4356 return err;
4357
4358 req->secid = newsid;
4359 req->peer_secid = peersid;
4360 return 0;
4361} 4270}
4362 4271
4363static void selinux_inet_csk_clone(struct sock *newsk, 4272static void selinux_inet_csk_clone(struct sock *newsk,
@@ -4374,7 +4283,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
4374 4283
4375 /* We don't need to take any sort of lock here as we are the only 4284 /* We don't need to take any sort of lock here as we are the only
4376 * thread with access to newsksec */ 4285 * thread with access to newsksec */
4377 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); 4286 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
4378} 4287}
4379 4288
4380static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) 4289static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
@@ -4387,8 +4296,6 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
4387 family = PF_INET; 4296 family = PF_INET;
4388 4297
4389 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); 4298 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
4390
4391 selinux_netlbl_inet_conn_established(sk, family);
4392} 4299}
4393 4300
4394static void selinux_req_classify_flow(const struct request_sock *req, 4301static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4540,71 +4447,6 @@ static unsigned int selinux_ipv4_output(unsigned int hooknum,
4540 return selinux_ip_output(skb, PF_INET); 4447 return selinux_ip_output(skb, PF_INET);
4541} 4448}
4542 4449
4543static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4544 int ifindex,
4545 struct avc_audit_data *ad,
4546 u16 family, char *addrp)
4547{
4548 int err;
4549 struct sk_security_struct *sksec = sk->sk_security;
4550 u16 sk_class;
4551 u32 netif_perm, node_perm, send_perm;
4552 u32 port_sid, node_sid, if_sid, sk_sid;
4553
4554 sk_sid = sksec->sid;
4555 sk_class = sksec->sclass;
4556
4557 switch (sk_class) {
4558 case SECCLASS_UDP_SOCKET:
4559 netif_perm = NETIF__UDP_SEND;
4560 node_perm = NODE__UDP_SEND;
4561 send_perm = UDP_SOCKET__SEND_MSG;
4562 break;
4563 case SECCLASS_TCP_SOCKET:
4564 netif_perm = NETIF__TCP_SEND;
4565 node_perm = NODE__TCP_SEND;
4566 send_perm = TCP_SOCKET__SEND_MSG;
4567 break;
4568 case SECCLASS_DCCP_SOCKET:
4569 netif_perm = NETIF__DCCP_SEND;
4570 node_perm = NODE__DCCP_SEND;
4571 send_perm = DCCP_SOCKET__SEND_MSG;
4572 break;
4573 default:
4574 netif_perm = NETIF__RAWIP_SEND;
4575 node_perm = NODE__RAWIP_SEND;
4576 send_perm = 0;
4577 break;
4578 }
4579
4580 err = sel_netif_sid(ifindex, &if_sid);
4581 if (err)
4582 return err;
4583 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4584 return err;
4585
4586 err = sel_netnode_sid(addrp, family, &node_sid);
4587 if (err)
4588 return err;
4589 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
4590 if (err)
4591 return err;
4592
4593 if (send_perm != 0)
4594 return 0;
4595
4596 err = sel_netport_sid(sk->sk_protocol,
4597 ntohs(ad->u.net.dport), &port_sid);
4598 if (unlikely(err)) {
4599 printk(KERN_WARNING
4600 "SELinux: failure in"
4601 " selinux_ip_postroute_iptables_compat(),"
4602 " network port label not found\n");
4603 return err;
4604 }
4605 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
4606}
4607
4608static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, 4450static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4609 int ifindex, 4451 int ifindex,
4610 u16 family) 4452 u16 family)
@@ -4625,15 +4467,10 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4625 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) 4467 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4626 return NF_DROP; 4468 return NF_DROP;
4627 4469
4628 if (selinux_compat_net) { 4470 if (selinux_secmark_enabled())
4629 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4630 &ad, family, addrp))
4631 return NF_DROP;
4632 } else if (selinux_secmark_enabled()) {
4633 if (avc_has_perm(sksec->sid, skb->secmark, 4471 if (avc_has_perm(sksec->sid, skb->secmark,
4634 SECCLASS_PACKET, PACKET__SEND, &ad)) 4472 SECCLASS_PACKET, PACKET__SEND, &ad))
4635 return NF_DROP; 4473 return NF_DROP;
4636 }
4637 4474
4638 if (selinux_policycap_netpeer) 4475 if (selinux_policycap_netpeer)
4639 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) 4476 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
@@ -4657,7 +4494,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4657 * to the selinux_ip_postroute_compat() function to deal with the 4494 * to the selinux_ip_postroute_compat() function to deal with the
4658 * special handling. We do this in an attempt to keep this function 4495 * special handling. We do this in an attempt to keep this function
4659 * as fast and as clean as possible. */ 4496 * as fast and as clean as possible. */
4660 if (selinux_compat_net || !selinux_policycap_netpeer) 4497 if (!selinux_policycap_netpeer)
4661 return selinux_ip_postroute_compat(skb, ifindex, family); 4498 return selinux_ip_postroute_compat(skb, ifindex, family);
4662#ifdef CONFIG_XFRM 4499#ifdef CONFIG_XFRM
4663 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4500 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index b913c8d06038..b4b5b9b2f0be 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -32,6 +32,7 @@
32#include <linux/net.h> 32#include <linux/net.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <net/sock.h> 34#include <net/sock.h>
35#include <net/request_sock.h>
35 36
36#include "avc.h" 37#include "avc.h"
37#include "objsec.h" 38#include "objsec.h"
@@ -42,8 +43,7 @@ void selinux_netlbl_cache_invalidate(void);
42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); 43void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
43 44
44void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); 45void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
45void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 46void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec);
46 int family);
47 47
48int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 48int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
49 u16 family, 49 u16 family,
@@ -53,9 +53,9 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
53 u16 family, 53 u16 family,
54 u32 sid); 54 u32 sid);
55 55
56void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family); 56int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family);
57int selinux_netlbl_socket_post_create(struct socket *sock); 57void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family);
58int selinux_netlbl_inode_permission(struct inode *inode, int mask); 58int selinux_netlbl_socket_post_create(struct sock *sk, u16 family);
59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
60 struct sk_buff *skb, 60 struct sk_buff *skb,
61 u16 family, 61 u16 family,
@@ -85,8 +85,7 @@ static inline void selinux_netlbl_sk_security_free(
85} 85}
86 86
87static inline void selinux_netlbl_sk_security_reset( 87static inline void selinux_netlbl_sk_security_reset(
88 struct sk_security_struct *ssec, 88 struct sk_security_struct *ssec)
89 int family)
90{ 89{
91 return; 90 return;
92} 91}
@@ -113,17 +112,17 @@ static inline int selinux_netlbl_conn_setsid(struct sock *sk,
113 return 0; 112 return 0;
114} 113}
115 114
116static inline void selinux_netlbl_inet_conn_established(struct sock *sk, 115static inline int selinux_netlbl_inet_conn_request(struct request_sock *req,
117 u16 family) 116 u16 family)
118{ 117{
119 return; 118 return 0;
120} 119}
121static inline int selinux_netlbl_socket_post_create(struct socket *sock) 120static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
122{ 121{
123 return 0; 122 return;
124} 123}
125static inline int selinux_netlbl_inode_permission(struct inode *inode, 124static inline int selinux_netlbl_socket_post_create(struct sock *sk,
126 int mask) 125 u16 family)
127{ 126{
128 return 0; 127 return 0;
129} 128}
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 350794ab9b42..2e984413c7b2 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -100,41 +100,6 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
100} 100}
101 101
102/** 102/**
103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
104 * @sk: the socket to label
105 *
106 * Description:
107 * Attempt to label a socket using the NetLabel mechanism. Returns zero values
108 * on success, negative values on failure.
109 *
110 */
111static int selinux_netlbl_sock_setsid(struct sock *sk)
112{
113 int rc;
114 struct sk_security_struct *sksec = sk->sk_security;
115 struct netlbl_lsm_secattr *secattr;
116
117 if (sksec->nlbl_state != NLBL_REQUIRE)
118 return 0;
119
120 secattr = selinux_netlbl_sock_genattr(sk);
121 if (secattr == NULL)
122 return -ENOMEM;
123 rc = netlbl_sock_setattr(sk, secattr);
124 switch (rc) {
125 case 0:
126 sksec->nlbl_state = NLBL_LABELED;
127 break;
128 case -EDESTADDRREQ:
129 sksec->nlbl_state = NLBL_REQSKB;
130 rc = 0;
131 break;
132 }
133
134 return rc;
135}
136
137/**
138 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 103 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
139 * 104 *
140 * Description: 105 * Description:
@@ -188,13 +153,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
188 * The caller is responsibile for all the NetLabel sk_security_struct locking. 153 * The caller is responsibile for all the NetLabel sk_security_struct locking.
189 * 154 *
190 */ 155 */
191void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 156void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec)
192 int family)
193{ 157{
194 if (family == PF_INET) 158 ssec->nlbl_state = NLBL_UNSET;
195 ssec->nlbl_state = NLBL_REQUIRE;
196 else
197 ssec->nlbl_state = NLBL_UNSET;
198} 159}
199 160
200/** 161/**
@@ -281,127 +242,86 @@ skbuff_setsid_return:
281} 242}
282 243
283/** 244/**
284 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection 245 * selinux_netlbl_inet_conn_request - Label an incoming stream connection
285 * @sk: the new connection 246 * @req: incoming connection request socket
286 * 247 *
287 * Description: 248 * Description:
288 * A new connection has been established on @sk so make sure it is labeled 249 * A new incoming connection request is represented by @req, we need to label
289 * correctly with the NetLabel susbsystem. 250 * the new request_sock here and the stack will ensure the on-the-wire label
251 * will get preserved when a full sock is created once the connection handshake
252 * is complete. Returns zero on success, negative values on failure.
290 * 253 *
291 */ 254 */
292void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) 255int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
293{ 256{
294 int rc; 257 int rc;
295 struct sk_security_struct *sksec = sk->sk_security; 258 struct netlbl_lsm_secattr secattr;
296 struct netlbl_lsm_secattr *secattr;
297 struct inet_sock *sk_inet = inet_sk(sk);
298 struct sockaddr_in addr;
299
300 if (sksec->nlbl_state != NLBL_REQUIRE)
301 return;
302 259
303 secattr = selinux_netlbl_sock_genattr(sk); 260 if (family != PF_INET)
304 if (secattr == NULL) 261 return 0;
305 return;
306 262
307 rc = netlbl_sock_setattr(sk, secattr); 263 netlbl_secattr_init(&secattr);
308 switch (rc) { 264 rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
309 case 0: 265 if (rc != 0)
310 sksec->nlbl_state = NLBL_LABELED; 266 goto inet_conn_request_return;
311 break; 267 rc = netlbl_req_setattr(req, &secattr);
312 case -EDESTADDRREQ: 268inet_conn_request_return:
313 /* no PF_INET6 support yet because we don't support any IPv6 269 netlbl_secattr_destroy(&secattr);
314 * labeling protocols */ 270 return rc;
315 if (family != PF_INET) {
316 sksec->nlbl_state = NLBL_UNSET;
317 return;
318 }
319
320 addr.sin_family = family;
321 addr.sin_addr.s_addr = sk_inet->daddr;
322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
323 secattr) != 0) {
324 /* we failed to label the connected socket (could be
325 * for a variety of reasons, the actual "why" isn't
326 * important here) so we have to go to our backup plan,
327 * labeling the packets individually in the netfilter
328 * local output hook. this is okay but we need to
329 * adjust the MSS of the connection to take into
330 * account any labeling overhead, since we don't know
331 * the exact overhead at this point we'll use the worst
332 * case value which is 40 bytes for IPv4 */
333 struct inet_connection_sock *sk_conn = inet_csk(sk);
334 sk_conn->icsk_ext_hdr_len += 40 -
335 (sk_inet->opt ? sk_inet->opt->optlen : 0);
336 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
337
338 sksec->nlbl_state = NLBL_REQSKB;
339 } else
340 sksec->nlbl_state = NLBL_CONNLABELED;
341 break;
342 default:
343 /* note that we are failing to label the socket which could be
344 * a bad thing since it means traffic could leave the system
345 * without the desired labeling, however, all is not lost as
346 * we have a check in selinux_netlbl_inode_permission() to
347 * pick up the pieces that we might drop here because we can't
348 * return an error code */
349 break;
350 }
351} 271}
352 272
353/** 273/**
354 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 274 * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
355 * @sock: the socket to label 275 * @sk: the new sock
356 * 276 *
357 * Description: 277 * Description:
358 * Attempt to label a socket using the NetLabel mechanism using the given 278 * A new connection has been established using @sk, we've already labeled the
359 * SID. Returns zero values on success, negative values on failure. 279 * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but
280 * we need to set the NetLabel state here since we now have a sock structure.
360 * 281 *
361 */ 282 */
362int selinux_netlbl_socket_post_create(struct socket *sock) 283void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
363{ 284{
364 return selinux_netlbl_sock_setsid(sock->sk); 285 struct sk_security_struct *sksec = sk->sk_security;
286
287 if (family == PF_INET)
288 sksec->nlbl_state = NLBL_LABELED;
289 else
290 sksec->nlbl_state = NLBL_UNSET;
365} 291}
366 292
367/** 293/**
368 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled 294 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
369 * @inode: the file descriptor's inode 295 * @sock: the socket to label
370 * @mask: the permission mask 296 * @family: protocol family
371 * 297 *
372 * Description: 298 * Description:
373 * Looks at a file's inode and if it is marked as a socket protected by 299 * Attempt to label a socket using the NetLabel mechanism using the given
374 * NetLabel then verify that the socket has been labeled, if not try to label 300 * SID. Returns zero values on success, negative values on failure.
375 * the socket now with the inode's SID. Returns zero on success, negative
376 * values on failure.
377 * 301 *
378 */ 302 */
379int selinux_netlbl_inode_permission(struct inode *inode, int mask) 303int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
380{ 304{
381 int rc; 305 int rc;
382 struct sock *sk; 306 struct sk_security_struct *sksec = sk->sk_security;
383 struct socket *sock; 307 struct netlbl_lsm_secattr *secattr;
384 struct sk_security_struct *sksec;
385 308
386 if (!S_ISSOCK(inode->i_mode) || 309 if (family != PF_INET)
387 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
388 return 0;
389 sock = SOCKET_I(inode);
390 sk = sock->sk;
391 if (sk == NULL)
392 return 0;
393 sksec = sk->sk_security;
394 if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE)
395 return 0; 310 return 0;
396 311
397 local_bh_disable(); 312 secattr = selinux_netlbl_sock_genattr(sk);
398 bh_lock_sock_nested(sk); 313 if (secattr == NULL)
399 if (likely(sksec->nlbl_state == NLBL_REQUIRE)) 314 return -ENOMEM;
400 rc = selinux_netlbl_sock_setsid(sk); 315 rc = netlbl_sock_setattr(sk, family, secattr);
401 else 316 switch (rc) {
317 case 0:
318 sksec->nlbl_state = NLBL_LABELED;
319 break;
320 case -EDESTADDRREQ:
321 sksec->nlbl_state = NLBL_REQSKB;
402 rc = 0; 322 rc = 0;
403 bh_unlock_sock(sk); 323 break;
404 local_bh_enable(); 324 }
405 325
406 return rc; 326 return rc;
407} 327}
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index d3c8b982cfb0..2d5136ec3d54 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -47,8 +47,6 @@ static char *policycap_names[] = {
47 47
48unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; 48unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
49 49
50int selinux_compat_net = 0;
51
52static int __init checkreqprot_setup(char *str) 50static int __init checkreqprot_setup(char *str)
53{ 51{
54 unsigned long checkreqprot; 52 unsigned long checkreqprot;
@@ -58,16 +56,6 @@ static int __init checkreqprot_setup(char *str)
58} 56}
59__setup("checkreqprot=", checkreqprot_setup); 57__setup("checkreqprot=", checkreqprot_setup);
60 58
61static int __init selinux_compat_net_setup(char *str)
62{
63 unsigned long compat_net;
64 if (!strict_strtoul(str, 0, &compat_net))
65 selinux_compat_net = compat_net ? 1 : 0;
66 return 1;
67}
68__setup("selinux_compat_net=", selinux_compat_net_setup);
69
70
71static DEFINE_MUTEX(sel_mutex); 59static DEFINE_MUTEX(sel_mutex);
72 60
73/* global data for booleans */ 61/* global data for booleans */
@@ -450,61 +438,6 @@ static const struct file_operations sel_checkreqprot_ops = {
450 .write = sel_write_checkreqprot, 438 .write = sel_write_checkreqprot,
451}; 439};
452 440
453static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
454 size_t count, loff_t *ppos)
455{
456 char tmpbuf[TMPBUFLEN];
457 ssize_t length;
458
459 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
460 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
461}
462
463static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
464 size_t count, loff_t *ppos)
465{
466 char *page;
467 ssize_t length;
468 int new_value;
469
470 length = task_has_security(current, SECURITY__LOAD_POLICY);
471 if (length)
472 return length;
473
474 if (count >= PAGE_SIZE)
475 return -ENOMEM;
476 if (*ppos != 0) {
477 /* No partial writes. */
478 return -EINVAL;
479 }
480 page = (char *)get_zeroed_page(GFP_KERNEL);
481 if (!page)
482 return -ENOMEM;
483 length = -EFAULT;
484 if (copy_from_user(page, buf, count))
485 goto out;
486
487 length = -EINVAL;
488 if (sscanf(page, "%d", &new_value) != 1)
489 goto out;
490
491 if (new_value) {
492 printk(KERN_NOTICE
493 "SELinux: compat_net is deprecated, please use secmark"
494 " instead\n");
495 selinux_compat_net = 1;
496 } else
497 selinux_compat_net = 0;
498 length = count;
499out:
500 free_page((unsigned long) page);
501 return length;
502}
503static const struct file_operations sel_compat_net_ops = {
504 .read = sel_read_compat_net,
505 .write = sel_write_compat_net,
506};
507
508/* 441/*
509 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c 442 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
510 */ 443 */
@@ -1665,7 +1598,6 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
1665 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR}, 1598 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
1666 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO}, 1599 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
1667 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR}, 1600 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
1668 [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
1669 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, 1601 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
1670 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, 1602 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
1671 /* last one */ {""} 1603 /* last one */ {""}
diff --git a/security/smack/smack.h b/security/smack/smack.h
index b79582e4fbfd..42ef313f9856 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -18,6 +18,8 @@
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/in.h> 19#include <linux/in.h>
20#include <net/netlabel.h> 20#include <net/netlabel.h>
21#include <linux/list.h>
22#include <linux/rculist.h>
21 23
22/* 24/*
23 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is 25 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -40,7 +42,6 @@ struct superblock_smack {
40struct socket_smack { 42struct socket_smack {
41 char *smk_out; /* outbound label */ 43 char *smk_out; /* outbound label */
42 char *smk_in; /* inbound label */ 44 char *smk_in; /* inbound label */
43 int smk_labeled; /* label scheme */
44 char smk_packet[SMK_LABELLEN]; /* TCP peer label */ 45 char smk_packet[SMK_LABELLEN]; /* TCP peer label */
45}; 46};
46 47
@@ -59,17 +60,10 @@ struct inode_smack {
59 * A label access rule. 60 * A label access rule.
60 */ 61 */
61struct smack_rule { 62struct smack_rule {
62 char *smk_subject; 63 struct list_head list;
63 char *smk_object; 64 char *smk_subject;
64 int smk_access; 65 char *smk_object;
65}; 66 int smk_access;
66
67/*
68 * An entry in the table of permitted label accesses.
69 */
70struct smk_list_entry {
71 struct smk_list_entry *smk_next;
72 struct smack_rule smk_rule;
73}; 67};
74 68
75/* 69/*
@@ -85,7 +79,7 @@ struct smack_cipso {
85 * An entry in the table identifying hosts. 79 * An entry in the table identifying hosts.
86 */ 80 */
87struct smk_netlbladdr { 81struct smk_netlbladdr {
88 struct smk_netlbladdr *smk_next; 82 struct list_head list;
89 struct sockaddr_in smk_host; /* network address */ 83 struct sockaddr_in smk_host; /* network address */
90 struct in_addr smk_mask; /* network mask */ 84 struct in_addr smk_mask; /* network mask */
91 char *smk_label; /* label */ 85 char *smk_label; /* label */
@@ -113,7 +107,7 @@ struct smk_netlbladdr {
113 * the cipso direct mapping in used internally. 107 * the cipso direct mapping in used internally.
114 */ 108 */
115struct smack_known { 109struct smack_known {
116 struct smack_known *smk_next; 110 struct list_head list;
117 char smk_known[SMK_LABELLEN]; 111 char smk_known[SMK_LABELLEN];
118 u32 smk_secid; 112 u32 smk_secid;
119 struct smack_cipso *smk_cipso; 113 struct smack_cipso *smk_cipso;
@@ -138,6 +132,8 @@ struct smack_known {
138#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN 132#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
139#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT 133#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
140 134
135#define SMACK_CIPSO_OPTION "-CIPSO"
136
141/* 137/*
142 * How communications on this socket are treated. 138 * How communications on this socket are treated.
143 * Usually it's determined by the underlying netlabel code 139 * Usually it's determined by the underlying netlabel code
@@ -205,8 +201,8 @@ u32 smack_to_secid(const char *);
205extern int smack_cipso_direct; 201extern int smack_cipso_direct;
206extern char *smack_net_ambient; 202extern char *smack_net_ambient;
207extern char *smack_onlycap; 203extern char *smack_onlycap;
204extern const char *smack_cipso_option;
208 205
209extern struct smack_known *smack_known;
210extern struct smack_known smack_known_floor; 206extern struct smack_known smack_known_floor;
211extern struct smack_known smack_known_hat; 207extern struct smack_known smack_known_hat;
212extern struct smack_known smack_known_huh; 208extern struct smack_known smack_known_huh;
@@ -214,8 +210,10 @@ extern struct smack_known smack_known_invalid;
214extern struct smack_known smack_known_star; 210extern struct smack_known smack_known_star;
215extern struct smack_known smack_known_web; 211extern struct smack_known smack_known_web;
216 212
217extern struct smk_list_entry *smack_list; 213extern struct list_head smack_known_list;
218extern struct smk_netlbladdr *smack_netlbladdrs; 214extern struct list_head smack_rule_list;
215extern struct list_head smk_netlbladdr_list;
216
219extern struct security_operations smack_ops; 217extern struct security_operations smack_ops;
220 218
221/* 219/*
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index cfa19ca125e3..ac0a2707f6d4 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -16,48 +16,42 @@
16#include "smack.h" 16#include "smack.h"
17 17
18struct smack_known smack_known_huh = { 18struct smack_known smack_known_huh = {
19 .smk_next = NULL,
20 .smk_known = "?", 19 .smk_known = "?",
21 .smk_secid = 2, 20 .smk_secid = 2,
22 .smk_cipso = NULL, 21 .smk_cipso = NULL,
23}; 22};
24 23
25struct smack_known smack_known_hat = { 24struct smack_known smack_known_hat = {
26 .smk_next = &smack_known_huh,
27 .smk_known = "^", 25 .smk_known = "^",
28 .smk_secid = 3, 26 .smk_secid = 3,
29 .smk_cipso = NULL, 27 .smk_cipso = NULL,
30}; 28};
31 29
32struct smack_known smack_known_star = { 30struct smack_known smack_known_star = {
33 .smk_next = &smack_known_hat,
34 .smk_known = "*", 31 .smk_known = "*",
35 .smk_secid = 4, 32 .smk_secid = 4,
36 .smk_cipso = NULL, 33 .smk_cipso = NULL,
37}; 34};
38 35
39struct smack_known smack_known_floor = { 36struct smack_known smack_known_floor = {
40 .smk_next = &smack_known_star,
41 .smk_known = "_", 37 .smk_known = "_",
42 .smk_secid = 5, 38 .smk_secid = 5,
43 .smk_cipso = NULL, 39 .smk_cipso = NULL,
44}; 40};
45 41
46struct smack_known smack_known_invalid = { 42struct smack_known smack_known_invalid = {
47 .smk_next = &smack_known_floor,
48 .smk_known = "", 43 .smk_known = "",
49 .smk_secid = 6, 44 .smk_secid = 6,
50 .smk_cipso = NULL, 45 .smk_cipso = NULL,
51}; 46};
52 47
53struct smack_known smack_known_web = { 48struct smack_known smack_known_web = {
54 .smk_next = &smack_known_invalid,
55 .smk_known = "@", 49 .smk_known = "@",
56 .smk_secid = 7, 50 .smk_secid = 7,
57 .smk_cipso = NULL, 51 .smk_cipso = NULL,
58}; 52};
59 53
60struct smack_known *smack_known = &smack_known_web; 54LIST_HEAD(smack_known_list);
61 55
62/* 56/*
63 * The initial value needs to be bigger than any of the 57 * The initial value needs to be bigger than any of the
@@ -87,7 +81,6 @@ static u32 smack_next_secid = 10;
87int smk_access(char *subject_label, char *object_label, int request) 81int smk_access(char *subject_label, char *object_label, int request)
88{ 82{
89 u32 may = MAY_NOT; 83 u32 may = MAY_NOT;
90 struct smk_list_entry *sp;
91 struct smack_rule *srp; 84 struct smack_rule *srp;
92 85
93 /* 86 /*
@@ -139,9 +132,8 @@ int smk_access(char *subject_label, char *object_label, int request)
139 * access (e.g. read is included in readwrite) it's 132 * access (e.g. read is included in readwrite) it's
140 * good. 133 * good.
141 */ 134 */
142 for (sp = smack_list; sp != NULL; sp = sp->smk_next) { 135 rcu_read_lock();
143 srp = &sp->smk_rule; 136 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
144
145 if (srp->smk_subject == subject_label || 137 if (srp->smk_subject == subject_label ||
146 strcmp(srp->smk_subject, subject_label) == 0) { 138 strcmp(srp->smk_subject, subject_label) == 0) {
147 if (srp->smk_object == object_label || 139 if (srp->smk_object == object_label ||
@@ -151,6 +143,7 @@ int smk_access(char *subject_label, char *object_label, int request)
151 } 143 }
152 } 144 }
153 } 145 }
146 rcu_read_unlock();
154 /* 147 /*
155 * This is a bit map operation. 148 * This is a bit map operation.
156 */ 149 */
@@ -228,14 +221,17 @@ struct smack_known *smk_import_entry(const char *string, int len)
228 221
229 mutex_lock(&smack_known_lock); 222 mutex_lock(&smack_known_lock);
230 223
231 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 224 found = 0;
232 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) 225 list_for_each_entry_rcu(skp, &smack_known_list, list) {
226 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
227 found = 1;
233 break; 228 break;
229 }
230 }
234 231
235 if (skp == NULL) { 232 if (found == 0) {
236 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); 233 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
237 if (skp != NULL) { 234 if (skp != NULL) {
238 skp->smk_next = smack_known;
239 strncpy(skp->smk_known, smack, SMK_MAXLEN); 235 strncpy(skp->smk_known, smack, SMK_MAXLEN);
240 skp->smk_secid = smack_next_secid++; 236 skp->smk_secid = smack_next_secid++;
241 skp->smk_cipso = NULL; 237 skp->smk_cipso = NULL;
@@ -244,8 +240,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
244 * Make sure that the entry is actually 240 * Make sure that the entry is actually
245 * filled before putting it on the list. 241 * filled before putting it on the list.
246 */ 242 */
247 smp_mb(); 243 list_add_rcu(&skp->list, &smack_known_list);
248 smack_known = skp;
249 } 244 }
250 } 245 }
251 246
@@ -266,6 +261,9 @@ char *smk_import(const char *string, int len)
266{ 261{
267 struct smack_known *skp; 262 struct smack_known *skp;
268 263
264 /* labels cannot begin with a '-' */
265 if (string[0] == '-')
266 return NULL;
269 skp = smk_import_entry(string, len); 267 skp = smk_import_entry(string, len);
270 if (skp == NULL) 268 if (skp == NULL)
271 return NULL; 269 return NULL;
@@ -283,14 +281,19 @@ char *smack_from_secid(const u32 secid)
283{ 281{
284 struct smack_known *skp; 282 struct smack_known *skp;
285 283
286 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 284 rcu_read_lock();
287 if (skp->smk_secid == secid) 285 list_for_each_entry_rcu(skp, &smack_known_list, list) {
286 if (skp->smk_secid == secid) {
287 rcu_read_unlock();
288 return skp->smk_known; 288 return skp->smk_known;
289 }
290 }
289 291
290 /* 292 /*
291 * If we got this far someone asked for the translation 293 * If we got this far someone asked for the translation
292 * of a secid that is not on the list. 294 * of a secid that is not on the list.
293 */ 295 */
296 rcu_read_unlock();
294 return smack_known_invalid.smk_known; 297 return smack_known_invalid.smk_known;
295} 298}
296 299
@@ -305,9 +308,14 @@ u32 smack_to_secid(const char *smack)
305{ 308{
306 struct smack_known *skp; 309 struct smack_known *skp;
307 310
308 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 311 rcu_read_lock();
309 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) 312 list_for_each_entry_rcu(skp, &smack_known_list, list) {
313 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
314 rcu_read_unlock();
310 return skp->smk_secid; 315 return skp->smk_secid;
316 }
317 }
318 rcu_read_unlock();
311 return 0; 319 return 0;
312} 320}
313 321
@@ -332,7 +340,8 @@ void smack_from_cipso(u32 level, char *cp, char *result)
332 struct smack_known *kp; 340 struct smack_known *kp;
333 char *final = NULL; 341 char *final = NULL;
334 342
335 for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) { 343 rcu_read_lock();
344 list_for_each_entry(kp, &smack_known_list, list) {
336 if (kp->smk_cipso == NULL) 345 if (kp->smk_cipso == NULL)
337 continue; 346 continue;
338 347
@@ -344,6 +353,7 @@ void smack_from_cipso(u32 level, char *cp, char *result)
344 353
345 spin_unlock_bh(&kp->smk_cipsolock); 354 spin_unlock_bh(&kp->smk_cipsolock);
346 } 355 }
356 rcu_read_unlock();
347 if (final == NULL) 357 if (final == NULL)
348 final = smack_known_huh.smk_known; 358 final = smack_known_huh.smk_known;
349 strncpy(result, final, SMK_MAXLEN); 359 strncpy(result, final, SMK_MAXLEN);
@@ -360,13 +370,19 @@ void smack_from_cipso(u32 level, char *cp, char *result)
360int smack_to_cipso(const char *smack, struct smack_cipso *cp) 370int smack_to_cipso(const char *smack, struct smack_cipso *cp)
361{ 371{
362 struct smack_known *kp; 372 struct smack_known *kp;
373 int found = 0;
363 374
364 for (kp = smack_known; kp != NULL; kp = kp->smk_next) 375 rcu_read_lock();
376 list_for_each_entry_rcu(kp, &smack_known_list, list) {
365 if (kp->smk_known == smack || 377 if (kp->smk_known == smack ||
366 strcmp(kp->smk_known, smack) == 0) 378 strcmp(kp->smk_known, smack) == 0) {
379 found = 1;
367 break; 380 break;
381 }
382 }
383 rcu_read_unlock();
368 384
369 if (kp == NULL || kp->smk_cipso == NULL) 385 if (found == 0 || kp->smk_cipso == NULL)
370 return -ENOENT; 386 return -ENOENT;
371 387
372 memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso)); 388 memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 84b62b5e9e2c..921514902eca 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -7,6 +7,8 @@
7 * Casey Schaufler <casey@schaufler-ca.com> 7 * Casey Schaufler <casey@schaufler-ca.com>
8 * 8 *
9 * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> 9 * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
10 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
11 * Paul Moore <paul.moore@hp.com>
10 * 12 *
11 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2, 14 * it under the terms of the GNU General Public License version 2,
@@ -20,6 +22,7 @@
20#include <linux/ext2_fs.h> 22#include <linux/ext2_fs.h>
21#include <linux/kd.h> 23#include <linux/kd.h>
22#include <asm/ioctls.h> 24#include <asm/ioctls.h>
25#include <linux/ip.h>
23#include <linux/tcp.h> 26#include <linux/tcp.h>
24#include <linux/udp.h> 27#include <linux/udp.h>
25#include <linux/mutex.h> 28#include <linux/mutex.h>
@@ -606,6 +609,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
606 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { 609 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
607 if (!capable(CAP_MAC_ADMIN)) 610 if (!capable(CAP_MAC_ADMIN))
608 rc = -EPERM; 611 rc = -EPERM;
612 /* a label cannot be void and cannot begin with '-' */
613 if (size == 0 || (size > 0 && ((char *)value)[0] == '-'))
614 rc = -EINVAL;
609 } else 615 } else
610 rc = cap_inode_setxattr(dentry, name, value, size, flags); 616 rc = cap_inode_setxattr(dentry, name, value, size, flags);
611 617
@@ -1275,7 +1281,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
1275 1281
1276 ssp->smk_in = csp; 1282 ssp->smk_in = csp;
1277 ssp->smk_out = csp; 1283 ssp->smk_out = csp;
1278 ssp->smk_labeled = SMACK_CIPSO_SOCKET;
1279 ssp->smk_packet[0] = '\0'; 1284 ssp->smk_packet[0] = '\0';
1280 1285
1281 sk->sk_security = ssp; 1286 sk->sk_security = ssp;
@@ -1295,6 +1300,43 @@ static void smack_sk_free_security(struct sock *sk)
1295} 1300}
1296 1301
1297/** 1302/**
1303* smack_host_label - check host based restrictions
1304* @sip: the object end
1305*
1306* looks for host based access restrictions
1307*
1308* This version will only be appropriate for really small sets of single label
1309* hosts. The caller is responsible for ensuring that the RCU read lock is
1310* taken before calling this function.
1311*
1312* Returns the label of the far end or NULL if it's not special.
1313*/
1314static char *smack_host_label(struct sockaddr_in *sip)
1315{
1316 struct smk_netlbladdr *snp;
1317 struct in_addr *siap = &sip->sin_addr;
1318
1319 if (siap->s_addr == 0)
1320 return NULL;
1321
1322 list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list)
1323 /*
1324 * we break after finding the first match because
1325 * the list is sorted from longest to shortest mask
1326 * so we have found the most specific match
1327 */
1328 if ((&snp->smk_host.sin_addr)->s_addr ==
1329 (siap->s_addr & (&snp->smk_mask)->s_addr)) {
1330 /* we have found the special CIPSO option */
1331 if (snp->smk_label == smack_cipso_option)
1332 return NULL;
1333 return snp->smk_label;
1334 }
1335
1336 return NULL;
1337}
1338
1339/**
1298 * smack_set_catset - convert a capset to netlabel mls categories 1340 * smack_set_catset - convert a capset to netlabel mls categories
1299 * @catset: the Smack categories 1341 * @catset: the Smack categories
1300 * @sap: where to put the netlabel categories 1342 * @sap: where to put the netlabel categories
@@ -1365,11 +1407,10 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1365 */ 1407 */
1366static int smack_netlabel(struct sock *sk, int labeled) 1408static int smack_netlabel(struct sock *sk, int labeled)
1367{ 1409{
1368 struct socket_smack *ssp; 1410 struct socket_smack *ssp = sk->sk_security;
1369 struct netlbl_lsm_secattr secattr; 1411 struct netlbl_lsm_secattr secattr;
1370 int rc = 0; 1412 int rc = 0;
1371 1413
1372 ssp = sk->sk_security;
1373 /* 1414 /*
1374 * Usually the netlabel code will handle changing the 1415 * Usually the netlabel code will handle changing the
1375 * packet labeling based on the label. 1416 * packet labeling based on the label.
@@ -1387,27 +1428,51 @@ static int smack_netlabel(struct sock *sk, int labeled)
1387 else { 1428 else {
1388 netlbl_secattr_init(&secattr); 1429 netlbl_secattr_init(&secattr);
1389 smack_to_secattr(ssp->smk_out, &secattr); 1430 smack_to_secattr(ssp->smk_out, &secattr);
1390 rc = netlbl_sock_setattr(sk, &secattr); 1431 rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
1391 netlbl_secattr_destroy(&secattr); 1432 netlbl_secattr_destroy(&secattr);
1392 } 1433 }
1393 1434
1394 bh_unlock_sock(sk); 1435 bh_unlock_sock(sk);
1395 local_bh_enable(); 1436 local_bh_enable();
1396 /*
1397 * Remember the label scheme used so that it is not
1398 * necessary to do the netlabel setting if it has not
1399 * changed the next time through.
1400 *
1401 * The -EDESTADDRREQ case is an indication that there's
1402 * a single level host involved.
1403 */
1404 if (rc == 0)
1405 ssp->smk_labeled = labeled;
1406 1437
1407 return rc; 1438 return rc;
1408} 1439}
1409 1440
1410/** 1441/**
1442 * smack_netlbel_send - Set the secattr on a socket and perform access checks
1443 * @sk: the socket
1444 * @sap: the destination address
1445 *
1446 * Set the correct secattr for the given socket based on the destination
1447 * address and perform any outbound access checks needed.
1448 *
1449 * Returns 0 on success or an error code.
1450 *
1451 */
1452static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
1453{
1454 int rc;
1455 int sk_lbl;
1456 char *hostsp;
1457 struct socket_smack *ssp = sk->sk_security;
1458
1459 rcu_read_lock();
1460 hostsp = smack_host_label(sap);
1461 if (hostsp != NULL) {
1462 sk_lbl = SMACK_UNLABELED_SOCKET;
1463 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
1464 } else {
1465 sk_lbl = SMACK_CIPSO_SOCKET;
1466 rc = 0;
1467 }
1468 rcu_read_unlock();
1469 if (rc != 0)
1470 return rc;
1471
1472 return smack_netlabel(sk, sk_lbl);
1473}
1474
1475/**
1411 * smack_inode_setsecurity - set smack xattrs 1476 * smack_inode_setsecurity - set smack xattrs
1412 * @inode: the object 1477 * @inode: the object
1413 * @name: attribute name 1478 * @name: attribute name
@@ -1428,7 +1493,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1428 struct socket *sock; 1493 struct socket *sock;
1429 int rc = 0; 1494 int rc = 0;
1430 1495
1431 if (value == NULL || size > SMK_LABELLEN) 1496 if (value == NULL || size > SMK_LABELLEN || size == 0)
1432 return -EACCES; 1497 return -EACCES;
1433 1498
1434 sp = smk_import(value, size); 1499 sp = smk_import(value, size);
@@ -1488,41 +1553,6 @@ static int smack_socket_post_create(struct socket *sock, int family,
1488 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); 1553 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1489} 1554}
1490 1555
1491
1492/**
1493 * smack_host_label - check host based restrictions
1494 * @sip: the object end
1495 *
1496 * looks for host based access restrictions
1497 *
1498 * This version will only be appropriate for really small
1499 * sets of single label hosts.
1500 *
1501 * Returns the label of the far end or NULL if it's not special.
1502 */
1503static char *smack_host_label(struct sockaddr_in *sip)
1504{
1505 struct smk_netlbladdr *snp;
1506 struct in_addr *siap = &sip->sin_addr;
1507
1508 if (siap->s_addr == 0)
1509 return NULL;
1510
1511 for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
1512 /*
1513 * we break after finding the first match because
1514 * the list is sorted from longest to shortest mask
1515 * so we have found the most specific match
1516 */
1517 if ((&snp->smk_host.sin_addr)->s_addr ==
1518 (siap->s_addr & (&snp->smk_mask)->s_addr)) {
1519 return snp->smk_label;
1520 }
1521 }
1522
1523 return NULL;
1524}
1525
1526/** 1556/**
1527 * smack_socket_connect - connect access check 1557 * smack_socket_connect - connect access check
1528 * @sock: the socket 1558 * @sock: the socket
@@ -1536,30 +1566,12 @@ static char *smack_host_label(struct sockaddr_in *sip)
1536static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, 1566static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
1537 int addrlen) 1567 int addrlen)
1538{ 1568{
1539 struct socket_smack *ssp = sock->sk->sk_security;
1540 char *hostsp;
1541 int rc;
1542
1543 if (sock->sk == NULL || sock->sk->sk_family != PF_INET) 1569 if (sock->sk == NULL || sock->sk->sk_family != PF_INET)
1544 return 0; 1570 return 0;
1545
1546 if (addrlen < sizeof(struct sockaddr_in)) 1571 if (addrlen < sizeof(struct sockaddr_in))
1547 return -EINVAL; 1572 return -EINVAL;
1548 1573
1549 hostsp = smack_host_label((struct sockaddr_in *)sap); 1574 return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
1550 if (hostsp == NULL) {
1551 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
1552 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1553 return 0;
1554 }
1555
1556 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
1557 if (rc != 0)
1558 return rc;
1559
1560 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
1561 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
1562 return 0;
1563} 1575}
1564 1576
1565/** 1577/**
@@ -2260,9 +2272,6 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2260 int size) 2272 int size)
2261{ 2273{
2262 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; 2274 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
2263 struct socket_smack *ssp = sock->sk->sk_security;
2264 char *hostsp;
2265 int rc;
2266 2275
2267 /* 2276 /*
2268 * Perfectly reasonable for this to be NULL 2277 * Perfectly reasonable for this to be NULL
@@ -2270,22 +2279,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2270 if (sip == NULL || sip->sin_family != PF_INET) 2279 if (sip == NULL || sip->sin_family != PF_INET)
2271 return 0; 2280 return 0;
2272 2281
2273 hostsp = smack_host_label(sip); 2282 return smack_netlabel_send(sock->sk, sip);
2274 if (hostsp == NULL) {
2275 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
2276 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
2277 return 0;
2278 }
2279
2280 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
2281 if (rc != 0)
2282 return rc;
2283
2284 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
2285 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
2286
2287 return 0;
2288
2289} 2283}
2290 2284
2291 2285
@@ -2490,31 +2484,24 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
2490} 2484}
2491 2485
2492/** 2486/**
2493 * smack_sock_graft - graft access state between two sockets 2487 * smack_sock_graft - Initialize a newly created socket with an existing sock
2494 * @sk: fresh sock 2488 * @sk: child sock
2495 * @parent: donor socket 2489 * @parent: parent socket
2496 * 2490 *
2497 * Sets the netlabel socket state on sk from parent 2491 * Set the smk_{in,out} state of an existing sock based on the process that
2492 * is creating the new socket.
2498 */ 2493 */
2499static void smack_sock_graft(struct sock *sk, struct socket *parent) 2494static void smack_sock_graft(struct sock *sk, struct socket *parent)
2500{ 2495{
2501 struct socket_smack *ssp; 2496 struct socket_smack *ssp;
2502 int rc;
2503 2497
2504 if (sk == NULL) 2498 if (sk == NULL ||
2505 return; 2499 (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
2506
2507 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
2508 return; 2500 return;
2509 2501
2510 ssp = sk->sk_security; 2502 ssp = sk->sk_security;
2511 ssp->smk_in = ssp->smk_out = current_security(); 2503 ssp->smk_in = ssp->smk_out = current_security();
2512 ssp->smk_packet[0] = '\0'; 2504 /* cssp->smk_packet is already set in smack_inet_csk_clone() */
2513
2514 rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET);
2515 if (rc != 0)
2516 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
2517 __func__, -rc);
2518} 2505}
2519 2506
2520/** 2507/**
@@ -2529,35 +2516,82 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
2529static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, 2516static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
2530 struct request_sock *req) 2517 struct request_sock *req)
2531{ 2518{
2532 struct netlbl_lsm_secattr skb_secattr; 2519 u16 family = sk->sk_family;
2533 struct socket_smack *ssp = sk->sk_security; 2520 struct socket_smack *ssp = sk->sk_security;
2521 struct netlbl_lsm_secattr secattr;
2522 struct sockaddr_in addr;
2523 struct iphdr *hdr;
2534 char smack[SMK_LABELLEN]; 2524 char smack[SMK_LABELLEN];
2535 int rc; 2525 int rc;
2536 2526
2537 if (skb == NULL) 2527 /* handle mapped IPv4 packets arriving via IPv6 sockets */
2538 return -EACCES; 2528 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
2529 family = PF_INET;
2539 2530
2540 netlbl_secattr_init(&skb_secattr); 2531 netlbl_secattr_init(&secattr);
2541 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr); 2532 rc = netlbl_skbuff_getattr(skb, family, &secattr);
2542 if (rc == 0) 2533 if (rc == 0)
2543 smack_from_secattr(&skb_secattr, smack); 2534 smack_from_secattr(&secattr, smack);
2544 else 2535 else
2545 strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); 2536 strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
2546 netlbl_secattr_destroy(&skb_secattr); 2537 netlbl_secattr_destroy(&secattr);
2538
2547 /* 2539 /*
2548 * Receiving a packet requires that the other end 2540 * Receiving a packet requires that the other end be able to write
2549 * be able to write here. Read access is not required. 2541 * here. Read access is not required.
2550 *
2551 * If the request is successful save the peer's label
2552 * so that SO_PEERCRED can report it.
2553 */ 2542 */
2554 rc = smk_access(smack, ssp->smk_in, MAY_WRITE); 2543 rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
2555 if (rc == 0) 2544 if (rc != 0)
2556 strncpy(ssp->smk_packet, smack, SMK_MAXLEN); 2545 return rc;
2546
2547 /*
2548 * Save the peer's label in the request_sock so we can later setup
2549 * smk_packet in the child socket so that SO_PEERCRED can report it.
2550 */
2551 req->peer_secid = smack_to_secid(smack);
2552
2553 /*
2554 * We need to decide if we want to label the incoming connection here
2555 * if we do we only need to label the request_sock and the stack will
2556 * propogate the wire-label to the sock when it is created.
2557 */
2558 hdr = ip_hdr(skb);
2559 addr.sin_addr.s_addr = hdr->saddr;
2560 rcu_read_lock();
2561 if (smack_host_label(&addr) == NULL) {
2562 rcu_read_unlock();
2563 netlbl_secattr_init(&secattr);
2564 smack_to_secattr(smack, &secattr);
2565 rc = netlbl_req_setattr(req, &secattr);
2566 netlbl_secattr_destroy(&secattr);
2567 } else {
2568 rcu_read_unlock();
2569 netlbl_req_delattr(req);
2570 }
2557 2571
2558 return rc; 2572 return rc;
2559} 2573}
2560 2574
2575/**
2576 * smack_inet_csk_clone - Copy the connection information to the new socket
2577 * @sk: the new socket
2578 * @req: the connection's request_sock
2579 *
2580 * Transfer the connection's peer label to the newly created socket.
2581 */
2582static void smack_inet_csk_clone(struct sock *sk,
2583 const struct request_sock *req)
2584{
2585 struct socket_smack *ssp = sk->sk_security;
2586 char *smack;
2587
2588 if (req->peer_secid != 0) {
2589 smack = smack_from_secid(req->peer_secid);
2590 strncpy(ssp->smk_packet, smack, SMK_MAXLEN);
2591 } else
2592 ssp->smk_packet[0] = '\0';
2593}
2594
2561/* 2595/*
2562 * Key management security hooks 2596 * Key management security hooks
2563 * 2597 *
@@ -2909,6 +2943,7 @@ struct security_operations smack_ops = {
2909 .sk_free_security = smack_sk_free_security, 2943 .sk_free_security = smack_sk_free_security,
2910 .sock_graft = smack_sock_graft, 2944 .sock_graft = smack_sock_graft,
2911 .inet_conn_request = smack_inet_conn_request, 2945 .inet_conn_request = smack_inet_conn_request,
2946 .inet_csk_clone = smack_inet_csk_clone,
2912 2947
2913 /* key management security hooks */ 2948 /* key management security hooks */
2914#ifdef CONFIG_KEYS 2949#ifdef CONFIG_KEYS
@@ -2930,6 +2965,17 @@ struct security_operations smack_ops = {
2930 .release_secctx = smack_release_secctx, 2965 .release_secctx = smack_release_secctx,
2931}; 2966};
2932 2967
2968
2969static __init void init_smack_know_list(void)
2970{
2971 list_add(&smack_known_huh.list, &smack_known_list);
2972 list_add(&smack_known_hat.list, &smack_known_list);
2973 list_add(&smack_known_star.list, &smack_known_list);
2974 list_add(&smack_known_floor.list, &smack_known_list);
2975 list_add(&smack_known_invalid.list, &smack_known_list);
2976 list_add(&smack_known_web.list, &smack_known_list);
2977}
2978
2933/** 2979/**
2934 * smack_init - initialize the smack system 2980 * smack_init - initialize the smack system
2935 * 2981 *
@@ -2950,6 +2996,8 @@ static __init int smack_init(void)
2950 cred = (struct cred *) current->cred; 2996 cred = (struct cred *) current->cred;
2951 cred->security = &smack_known_floor.smk_known; 2997 cred->security = &smack_known_floor.smk_known;
2952 2998
2999 /* initilize the smack_know_list */
3000 init_smack_know_list();
2953 /* 3001 /*
2954 * Initialize locks 3002 * Initialize locks
2955 */ 3003 */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index a1b57e4dba3e..e03a7e19c73b 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -80,10 +80,14 @@ char *smack_onlycap;
80 * Packets are sent there unlabeled, but only from tasks that 80 * Packets are sent there unlabeled, but only from tasks that
81 * can write to the specified label. 81 * can write to the specified label.
82 */ 82 */
83struct smk_netlbladdr *smack_netlbladdrs; 83
84LIST_HEAD(smk_netlbladdr_list);
85LIST_HEAD(smack_rule_list);
84 86
85static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 87static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
86struct smk_list_entry *smack_list; 88
89const char *smack_cipso_option = SMACK_CIPSO_OPTION;
90
87 91
88#define SEQ_READ_FINISHED 1 92#define SEQ_READ_FINISHED 1
89 93
@@ -134,24 +138,27 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
134{ 138{
135 if (*pos == SEQ_READ_FINISHED) 139 if (*pos == SEQ_READ_FINISHED)
136 return NULL; 140 return NULL;
137 141 if (list_empty(&smack_rule_list))
138 return smack_list; 142 return NULL;
143 return smack_rule_list.next;
139} 144}
140 145
141static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) 146static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
142{ 147{
143 struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next; 148 struct list_head *list = v;
144 149
145 if (skp == NULL) 150 if (list_is_last(list, &smack_rule_list)) {
146 *pos = SEQ_READ_FINISHED; 151 *pos = SEQ_READ_FINISHED;
147 152 return NULL;
148 return skp; 153 }
154 return list->next;
149} 155}
150 156
151static int load_seq_show(struct seq_file *s, void *v) 157static int load_seq_show(struct seq_file *s, void *v)
152{ 158{
153 struct smk_list_entry *slp = (struct smk_list_entry *) v; 159 struct list_head *list = v;
154 struct smack_rule *srp = &slp->smk_rule; 160 struct smack_rule *srp =
161 list_entry(list, struct smack_rule, list);
155 162
156 seq_printf(s, "%s %s", (char *)srp->smk_subject, 163 seq_printf(s, "%s %s", (char *)srp->smk_subject,
157 (char *)srp->smk_object); 164 (char *)srp->smk_object);
@@ -212,32 +219,23 @@ static int smk_open_load(struct inode *inode, struct file *file)
212 */ 219 */
213static int smk_set_access(struct smack_rule *srp) 220static int smk_set_access(struct smack_rule *srp)
214{ 221{
215 struct smk_list_entry *sp; 222 struct smack_rule *sp;
216 struct smk_list_entry *newp;
217 int ret = 0; 223 int ret = 0;
218 224 int found;
219 mutex_lock(&smack_list_lock); 225 mutex_lock(&smack_list_lock);
220 226
221 for (sp = smack_list; sp != NULL; sp = sp->smk_next) 227 found = 0;
222 if (sp->smk_rule.smk_subject == srp->smk_subject && 228 list_for_each_entry_rcu(sp, &smack_rule_list, list) {
223 sp->smk_rule.smk_object == srp->smk_object) { 229 if (sp->smk_subject == srp->smk_subject &&
224 sp->smk_rule.smk_access = srp->smk_access; 230 sp->smk_object == srp->smk_object) {
231 found = 1;
232 sp->smk_access = srp->smk_access;
225 break; 233 break;
226 } 234 }
227
228 if (sp == NULL) {
229 newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL);
230 if (newp == NULL) {
231 ret = -ENOMEM;
232 goto out;
233 }
234
235 newp->smk_rule = *srp;
236 newp->smk_next = smack_list;
237 smack_list = newp;
238 } 235 }
236 if (found == 0)
237 list_add_rcu(&srp->list, &smack_rule_list);
239 238
240out:
241 mutex_unlock(&smack_list_lock); 239 mutex_unlock(&smack_list_lock);
242 240
243 return ret; 241 return ret;
@@ -261,7 +259,7 @@ out:
261static ssize_t smk_write_load(struct file *file, const char __user *buf, 259static ssize_t smk_write_load(struct file *file, const char __user *buf,
262 size_t count, loff_t *ppos) 260 size_t count, loff_t *ppos)
263{ 261{
264 struct smack_rule rule; 262 struct smack_rule *rule;
265 char *data; 263 char *data;
266 int rc = -EINVAL; 264 int rc = -EINVAL;
267 265
@@ -272,9 +270,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
272 */ 270 */
273 if (!capable(CAP_MAC_ADMIN)) 271 if (!capable(CAP_MAC_ADMIN))
274 return -EPERM; 272 return -EPERM;
275 if (*ppos != 0) 273
276 return -EINVAL; 274 if (*ppos != 0 || count != SMK_LOADLEN)
277 if (count != SMK_LOADLEN)
278 return -EINVAL; 275 return -EINVAL;
279 276
280 data = kzalloc(count, GFP_KERNEL); 277 data = kzalloc(count, GFP_KERNEL);
@@ -286,25 +283,31 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
286 goto out; 283 goto out;
287 } 284 }
288 285
289 rule.smk_subject = smk_import(data, 0); 286 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
290 if (rule.smk_subject == NULL) 287 if (rule == NULL) {
288 rc = -ENOMEM;
291 goto out; 289 goto out;
290 }
292 291
293 rule.smk_object = smk_import(data + SMK_LABELLEN, 0); 292 rule->smk_subject = smk_import(data, 0);
294 if (rule.smk_object == NULL) 293 if (rule->smk_subject == NULL)
295 goto out; 294 goto out_free_rule;
296 295
297 rule.smk_access = 0; 296 rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
297 if (rule->smk_object == NULL)
298 goto out_free_rule;
299
300 rule->smk_access = 0;
298 301
299 switch (data[SMK_LABELLEN + SMK_LABELLEN]) { 302 switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
300 case '-': 303 case '-':
301 break; 304 break;
302 case 'r': 305 case 'r':
303 case 'R': 306 case 'R':
304 rule.smk_access |= MAY_READ; 307 rule->smk_access |= MAY_READ;
305 break; 308 break;
306 default: 309 default:
307 goto out; 310 goto out_free_rule;
308 } 311 }
309 312
310 switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { 313 switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
@@ -312,10 +315,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
312 break; 315 break;
313 case 'w': 316 case 'w':
314 case 'W': 317 case 'W':
315 rule.smk_access |= MAY_WRITE; 318 rule->smk_access |= MAY_WRITE;
316 break; 319 break;
317 default: 320 default:
318 goto out; 321 goto out_free_rule;
319 } 322 }
320 323
321 switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { 324 switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
@@ -323,10 +326,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
323 break; 326 break;
324 case 'x': 327 case 'x':
325 case 'X': 328 case 'X':
326 rule.smk_access |= MAY_EXEC; 329 rule->smk_access |= MAY_EXEC;
327 break; 330 break;
328 default: 331 default:
329 goto out; 332 goto out_free_rule;
330 } 333 }
331 334
332 switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { 335 switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
@@ -334,17 +337,20 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
334 break; 337 break;
335 case 'a': 338 case 'a':
336 case 'A': 339 case 'A':
337 rule.smk_access |= MAY_APPEND; 340 rule->smk_access |= MAY_APPEND;
338 break; 341 break;
339 default: 342 default:
340 goto out; 343 goto out_free_rule;
341 } 344 }
342 345
343 rc = smk_set_access(&rule); 346 rc = smk_set_access(rule);
344 347
345 if (!rc) 348 if (!rc)
346 rc = count; 349 rc = count;
350 goto out;
347 351
352out_free_rule:
353 kfree(rule);
348out: 354out:
349 kfree(data); 355 kfree(data);
350 return rc; 356 return rc;
@@ -433,24 +439,26 @@ static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
433{ 439{
434 if (*pos == SEQ_READ_FINISHED) 440 if (*pos == SEQ_READ_FINISHED)
435 return NULL; 441 return NULL;
442 if (list_empty(&smack_known_list))
443 return NULL;
436 444
437 return smack_known; 445 return smack_known_list.next;
438} 446}
439 447
440static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) 448static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
441{ 449{
442 struct smack_known *skp = ((struct smack_known *) v)->smk_next; 450 struct list_head *list = v;
443 451
444 /* 452 /*
445 * Omit labels with no associated cipso value 453 * labels with no associated cipso value wont be printed
454 * in cipso_seq_show
446 */ 455 */
447 while (skp != NULL && !skp->smk_cipso) 456 if (list_is_last(list, &smack_known_list)) {
448 skp = skp->smk_next;
449
450 if (skp == NULL)
451 *pos = SEQ_READ_FINISHED; 457 *pos = SEQ_READ_FINISHED;
458 return NULL;
459 }
452 460
453 return skp; 461 return list->next;
454} 462}
455 463
456/* 464/*
@@ -459,7 +467,9 @@ static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
459 */ 467 */
460static int cipso_seq_show(struct seq_file *s, void *v) 468static int cipso_seq_show(struct seq_file *s, void *v)
461{ 469{
462 struct smack_known *skp = (struct smack_known *) v; 470 struct list_head *list = v;
471 struct smack_known *skp =
472 list_entry(list, struct smack_known, list);
463 struct smack_cipso *scp = skp->smk_cipso; 473 struct smack_cipso *scp = skp->smk_cipso;
464 char *cbp; 474 char *cbp;
465 char sep = '/'; 475 char sep = '/';
@@ -558,6 +568,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
558 goto unlockedout; 568 goto unlockedout;
559 } 569 }
560 570
571 /* labels cannot begin with a '-' */
572 if (data[0] == '-') {
573 rc = -EINVAL;
574 goto unlockedout;
575 }
561 data[count] = '\0'; 576 data[count] = '\0';
562 rule = data; 577 rule = data;
563 /* 578 /*
@@ -638,18 +653,21 @@ static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
638{ 653{
639 if (*pos == SEQ_READ_FINISHED) 654 if (*pos == SEQ_READ_FINISHED)
640 return NULL; 655 return NULL;
641 656 if (list_empty(&smk_netlbladdr_list))
642 return smack_netlbladdrs; 657 return NULL;
658 return smk_netlbladdr_list.next;
643} 659}
644 660
645static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) 661static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
646{ 662{
647 struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next; 663 struct list_head *list = v;
648 664
649 if (skp == NULL) 665 if (list_is_last(list, &smk_netlbladdr_list)) {
650 *pos = SEQ_READ_FINISHED; 666 *pos = SEQ_READ_FINISHED;
667 return NULL;
668 }
651 669
652 return skp; 670 return list->next;
653} 671}
654#define BEBITS (sizeof(__be32) * 8) 672#define BEBITS (sizeof(__be32) * 8)
655 673
@@ -658,7 +676,9 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
658 */ 676 */
659static int netlbladdr_seq_show(struct seq_file *s, void *v) 677static int netlbladdr_seq_show(struct seq_file *s, void *v)
660{ 678{
661 struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v; 679 struct list_head *list = v;
680 struct smk_netlbladdr *skp =
681 list_entry(list, struct smk_netlbladdr, list);
662 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; 682 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
663 int maskn; 683 int maskn;
664 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr); 684 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
@@ -702,30 +722,36 @@ static int smk_open_netlbladdr(struct inode *inode, struct file *file)
702 * 722 *
703 * This helper insert netlabel in the smack_netlbladdrs list 723 * This helper insert netlabel in the smack_netlbladdrs list
704 * sorted by netmask length (longest to smallest) 724 * sorted by netmask length (longest to smallest)
725 * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
726 *
705 */ 727 */
706static void smk_netlbladdr_insert(struct smk_netlbladdr *new) 728static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
707{ 729{
708 struct smk_netlbladdr *m; 730 struct smk_netlbladdr *m, *m_next;
709 731
710 if (smack_netlbladdrs == NULL) { 732 if (list_empty(&smk_netlbladdr_list)) {
711 smack_netlbladdrs = new; 733 list_add_rcu(&new->list, &smk_netlbladdr_list);
712 return; 734 return;
713 } 735 }
714 736
737 m = list_entry(rcu_dereference(smk_netlbladdr_list.next),
738 struct smk_netlbladdr, list);
739
715 /* the comparison '>' is a bit hacky, but works */ 740 /* the comparison '>' is a bit hacky, but works */
716 if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) { 741 if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
717 new->smk_next = smack_netlbladdrs; 742 list_add_rcu(&new->list, &smk_netlbladdr_list);
718 smack_netlbladdrs = new;
719 return; 743 return;
720 } 744 }
721 for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) { 745
722 if (m->smk_next == NULL) { 746 list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
723 m->smk_next = new; 747 if (list_is_last(&m->list, &smk_netlbladdr_list)) {
748 list_add_rcu(&new->list, &m->list);
724 return; 749 return;
725 } 750 }
726 if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) { 751 m_next = list_entry(rcu_dereference(m->list.next),
727 new->smk_next = m->smk_next; 752 struct smk_netlbladdr, list);
728 m->smk_next = new; 753 if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
754 list_add_rcu(&new->list, &m->list);
729 return; 755 return;
730 } 756 }
731 } 757 }
@@ -755,6 +781,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
755 struct netlbl_audit audit_info; 781 struct netlbl_audit audit_info;
756 struct in_addr mask; 782 struct in_addr mask;
757 unsigned int m; 783 unsigned int m;
784 int found;
758 u32 mask_bits = (1<<31); 785 u32 mask_bits = (1<<31);
759 __be32 nsa; 786 __be32 nsa;
760 u32 temp_mask; 787 u32 temp_mask;
@@ -789,9 +816,18 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
789 if (m > BEBITS) 816 if (m > BEBITS)
790 return -EINVAL; 817 return -EINVAL;
791 818
792 sp = smk_import(smack, 0); 819 /* if smack begins with '-', its an option, don't import it */
793 if (sp == NULL) 820 if (smack[0] != '-') {
794 return -EINVAL; 821 sp = smk_import(smack, 0);
822 if (sp == NULL)
823 return -EINVAL;
824 } else {
825 /* check known options */
826 if (strcmp(smack, smack_cipso_option) == 0)
827 sp = (char *)smack_cipso_option;
828 else
829 return -EINVAL;
830 }
795 831
796 for (temp_mask = 0; m > 0; m--) { 832 for (temp_mask = 0; m > 0; m--) {
797 temp_mask |= mask_bits; 833 temp_mask |= mask_bits;
@@ -808,14 +844,17 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
808 844
809 nsa = newname.sin_addr.s_addr; 845 nsa = newname.sin_addr.s_addr;
810 /* try to find if the prefix is already in the list */ 846 /* try to find if the prefix is already in the list */
811 for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next) 847 found = 0;
848 list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
812 if (skp->smk_host.sin_addr.s_addr == nsa && 849 if (skp->smk_host.sin_addr.s_addr == nsa &&
813 skp->smk_mask.s_addr == mask.s_addr) 850 skp->smk_mask.s_addr == mask.s_addr) {
851 found = 1;
814 break; 852 break;
815 853 }
854 }
816 smk_netlabel_audit_set(&audit_info); 855 smk_netlabel_audit_set(&audit_info);
817 856
818 if (skp == NULL) { 857 if (found == 0) {
819 skp = kzalloc(sizeof(*skp), GFP_KERNEL); 858 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
820 if (skp == NULL) 859 if (skp == NULL)
821 rc = -ENOMEM; 860 rc = -ENOMEM;
@@ -827,18 +866,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
827 smk_netlbladdr_insert(skp); 866 smk_netlbladdr_insert(skp);
828 } 867 }
829 } else { 868 } else {
830 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, 869 /* we delete the unlabeled entry, only if the previous label
831 &skp->smk_host.sin_addr, &skp->smk_mask, 870 * wasnt the special CIPSO option */
832 PF_INET, &audit_info); 871 if (skp->smk_label != smack_cipso_option)
872 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
873 &skp->smk_host.sin_addr, &skp->smk_mask,
874 PF_INET, &audit_info);
875 else
876 rc = 0;
833 skp->smk_label = sp; 877 skp->smk_label = sp;
834 } 878 }
835 879
836 /* 880 /*
837 * Now tell netlabel about the single label nature of 881 * Now tell netlabel about the single label nature of
838 * this host so that incoming packets get labeled. 882 * this host so that incoming packets get labeled.
883 * but only if we didn't get the special CIPSO option
839 */ 884 */
840 885 if (rc == 0 && sp != smack_cipso_option)
841 if (rc == 0)
842 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, 886 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
843 &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET, 887 &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
844 smack_to_secid(skp->smk_label), &audit_info); 888 smack_to_secid(skp->smk_label), &audit_info);
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 6dcb7cc0ed1d..26a76d67aa1c 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -55,7 +55,7 @@ struct tomoyo_path_info {
55struct tomoyo_path_info_with_data { 55struct tomoyo_path_info_with_data {
56 /* Keep "head" first, for this pointer is passed to tomoyo_free(). */ 56 /* Keep "head" first, for this pointer is passed to tomoyo_free(). */
57 struct tomoyo_path_info head; 57 struct tomoyo_path_info head;
58 char bariier1[16]; /* Safeguard for overrun. */ 58 char barrier1[16]; /* Safeguard for overrun. */
59 char body[TOMOYO_MAX_PATHNAME_LEN]; 59 char body[TOMOYO_MAX_PATHNAME_LEN];
60 char barrier2[16]; /* Safeguard for overrun. */ 60 char barrier2[16]; /* Safeguard for overrun. */
61}; 61};