Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / net / netlabel / netlabel_kapi.c
1 /*
2  * NetLabel Kernel API
3  *
4  * This file defines the kernel API for the NetLabel system.  The NetLabel
5  * system manages static and dynamic label mappings for network protocols such
6  * as CIPSO and RIPSO.
7  *
8  * Author: Paul Moore <paul.moore@hp.com>
9  *
10  */
11
12 /*
13  * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
14  *
15  * This program is free software;  you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
23  * the GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program;  if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28  *
29  */
30
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <net/ip.h>
34 #include <net/netlabel.h>
35 #include <net/cipso_ipv4.h>
36 #include <asm/bug.h>
37
38 #include "netlabel_domainhash.h"
39 #include "netlabel_unlabeled.h"
40 #include "netlabel_user.h"
41
42 /*
43  * LSM Functions
44  */
45
46 /**
47  * netlbl_socket_setattr - Label a socket using the correct protocol
48  * @sock: the socket to label
49  * @secattr: the security attributes
50  *
51  * Description:
52  * Attach the correct label to the given socket using the security attributes
53  * specified in @secattr.  This function requires exclusive access to
54  * @sock->sk, which means it either needs to be in the process of being
55  * created or locked via lock_sock(sock->sk).  Returns zero on success,
56  * negative values on failure.
57  *
58  */
59 int netlbl_socket_setattr(const struct socket *sock,
60                           const struct netlbl_lsm_secattr *secattr)
61 {
62         int ret_val = -ENOENT;
63         struct netlbl_dom_map *dom_entry;
64
65         rcu_read_lock();
66         dom_entry = netlbl_domhsh_getentry(secattr->domain);
67         if (dom_entry == NULL)
68                 goto socket_setattr_return;
69         switch (dom_entry->type) {
70         case NETLBL_NLTYPE_CIPSOV4:
71                 ret_val = cipso_v4_socket_setattr(sock,
72                                                   dom_entry->type_def.cipsov4,
73                                                   secattr);
74                 break;
75         case NETLBL_NLTYPE_UNLABELED:
76                 ret_val = 0;
77                 break;
78         default:
79                 ret_val = -ENOENT;
80         }
81
82 socket_setattr_return:
83         rcu_read_unlock();
84         return ret_val;
85 }
86
87 /**
88  * netlbl_sock_getattr - Determine the security attributes of a sock
89  * @sk: the sock
90  * @secattr: the security attributes
91  *
92  * Description:
93  * Examines the given sock to see any NetLabel style labeling has been
94  * applied to the sock, if so it parses the socket label and returns the
95  * security attributes in @secattr.  Returns zero on success, negative values
96  * on failure.
97  *
98  */
99 int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
100 {
101         int ret_val;
102
103         ret_val = cipso_v4_sock_getattr(sk, secattr);
104         if (ret_val == 0)
105                 return 0;
106
107         return netlbl_unlabel_getattr(secattr);
108 }
109
110 /**
111  * netlbl_socket_getattr - Determine the security attributes of a socket
112  * @sock: the socket
113  * @secattr: the security attributes
114  *
115  * Description:
116  * Examines the given socket to see any NetLabel style labeling has been
117  * applied to the socket, if so it parses the socket label and returns the
118  * security attributes in @secattr.  Returns zero on success, negative values
119  * on failure.
120  *
121  */
122 int netlbl_socket_getattr(const struct socket *sock,
123                           struct netlbl_lsm_secattr *secattr)
124 {
125         int ret_val;
126
127         ret_val = cipso_v4_socket_getattr(sock, secattr);
128         if (ret_val == 0)
129                 return 0;
130
131         return netlbl_unlabel_getattr(secattr);
132 }
133
134 /**
135  * netlbl_skbuff_getattr - Determine the security attributes of a packet
136  * @skb: the packet
137  * @secattr: the security attributes
138  *
139  * Description:
140  * Examines the given packet to see if a recognized form of packet labeling
141  * is present, if so it parses the packet label and returns the security
142  * attributes in @secattr.  Returns zero on success, negative values on
143  * failure.
144  *
145  */
146 int netlbl_skbuff_getattr(const struct sk_buff *skb,
147                           struct netlbl_lsm_secattr *secattr)
148 {
149         int ret_val;
150
151         ret_val = cipso_v4_skbuff_getattr(skb, secattr);
152         if (ret_val == 0)
153                 return 0;
154
155         return netlbl_unlabel_getattr(secattr);
156 }
157
158 /**
159  * netlbl_skbuff_err - Handle a LSM error on a sk_buff
160  * @skb: the packet
161  * @error: the error code
162  *
163  * Description:
164  * Deal with a LSM problem when handling the packet in @skb, typically this is
165  * a permission denied problem (-EACCES).  The correct action is determined
166  * according to the packet's labeling protocol.
167  *
168  */
169 void netlbl_skbuff_err(struct sk_buff *skb, int error)
170 {
171         if (CIPSO_V4_OPTEXIST(skb))
172                 cipso_v4_error(skb, error, 0);
173 }
174
175 /**
176  * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
177  *
178  * Description:
179  * For all of the NetLabel protocols that support some form of label mapping
180  * cache, invalidate the cache.  Returns zero on success, negative values on
181  * error.
182  *
183  */
184 void netlbl_cache_invalidate(void)
185 {
186         cipso_v4_cache_invalidate();
187 }
188
189 /**
190  * netlbl_cache_add - Add an entry to a NetLabel protocol cache
191  * @skb: the packet
192  * @secattr: the packet's security attributes
193  *
194  * Description:
195  * Add the LSM security attributes for the given packet to the underlying
196  * NetLabel protocol's label mapping cache.  Returns zero on success, negative
197  * values on error.
198  *
199  */
200 int netlbl_cache_add(const struct sk_buff *skb,
201                      const struct netlbl_lsm_secattr *secattr)
202 {
203         if (secattr->cache.data == NULL)
204                 return -ENOMSG;
205
206         if (CIPSO_V4_OPTEXIST(skb))
207                 return cipso_v4_cache_add(skb, secattr);
208
209         return -ENOMSG;
210 }
211
212 /*
213  * Setup Functions
214  */
215
216 /**
217  * netlbl_init - Initialize NetLabel
218  *
219  * Description:
220  * Perform the required NetLabel initialization before first use.
221  *
222  */
223 static int __init netlbl_init(void)
224 {
225         int ret_val;
226
227         printk(KERN_INFO "NetLabel: Initializing\n");
228         printk(KERN_INFO "NetLabel:  domain hash size = %u\n",
229                (1 << NETLBL_DOMHSH_BITSIZE));
230         printk(KERN_INFO "NetLabel:  protocols ="
231                " UNLABELED"
232                " CIPSOv4"
233                "\n");
234
235         ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
236         if (ret_val != 0)
237                 goto init_failure;
238
239         ret_val = netlbl_netlink_init();
240         if (ret_val != 0)
241                 goto init_failure;
242
243         ret_val = netlbl_unlabel_defconf();
244         if (ret_val != 0)
245                 goto init_failure;
246         printk(KERN_INFO "NetLabel:  unlabeled traffic allowed by default\n");
247
248         return 0;
249
250 init_failure:
251         panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
252 }
253
254 subsys_initcall(netlbl_init);