NetLabel: check for a CIPSOv4 option before we do call into the CIPSOv4 layer
[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         if ((secattr->flags & NETLBL_SECATTR_DOMAIN) == 0)
66                 return -ENOENT;
67
68         rcu_read_lock();
69         dom_entry = netlbl_domhsh_getentry(secattr->domain);
70         if (dom_entry == NULL)
71                 goto socket_setattr_return;
72         switch (dom_entry->type) {
73         case NETLBL_NLTYPE_CIPSOV4:
74                 ret_val = cipso_v4_socket_setattr(sock,
75                                                   dom_entry->type_def.cipsov4,
76                                                   secattr);
77                 break;
78         case NETLBL_NLTYPE_UNLABELED:
79                 ret_val = 0;
80                 break;
81         default:
82                 ret_val = -ENOENT;
83         }
84
85 socket_setattr_return:
86         rcu_read_unlock();
87         return ret_val;
88 }
89
90 /**
91  * netlbl_sock_getattr - Determine the security attributes of a sock
92  * @sk: the sock
93  * @secattr: the security attributes
94  *
95  * Description:
96  * Examines the given sock to see any NetLabel style labeling has been
97  * applied to the sock, if so it parses the socket label and returns the
98  * security attributes in @secattr.  Returns zero on success, negative values
99  * on failure.
100  *
101  */
102 int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
103 {
104         int ret_val;
105
106         ret_val = cipso_v4_sock_getattr(sk, secattr);
107         if (ret_val == 0)
108                 return 0;
109
110         return netlbl_unlabel_getattr(secattr);
111 }
112
113 /**
114  * netlbl_socket_getattr - Determine the security attributes of a socket
115  * @sock: the socket
116  * @secattr: the security attributes
117  *
118  * Description:
119  * Examines the given socket to see any NetLabel style labeling has been
120  * applied to the socket, if so it parses the socket label and returns the
121  * security attributes in @secattr.  Returns zero on success, negative values
122  * on failure.
123  *
124  */
125 int netlbl_socket_getattr(const struct socket *sock,
126                           struct netlbl_lsm_secattr *secattr)
127 {
128         int ret_val;
129
130         ret_val = cipso_v4_socket_getattr(sock, secattr);
131         if (ret_val == 0)
132                 return 0;
133
134         return netlbl_unlabel_getattr(secattr);
135 }
136
137 /**
138  * netlbl_skbuff_getattr - Determine the security attributes of a packet
139  * @skb: the packet
140  * @secattr: the security attributes
141  *
142  * Description:
143  * Examines the given packet to see if a recognized form of packet labeling
144  * is present, if so it parses the packet label and returns the security
145  * attributes in @secattr.  Returns zero on success, negative values on
146  * failure.
147  *
148  */
149 int netlbl_skbuff_getattr(const struct sk_buff *skb,
150                           struct netlbl_lsm_secattr *secattr)
151 {
152         if (CIPSO_V4_OPTEXIST(skb) &&
153             cipso_v4_skbuff_getattr(skb, secattr) == 0)
154                 return 0;
155
156         return netlbl_unlabel_getattr(secattr);
157 }
158
159 /**
160  * netlbl_skbuff_err - Handle a LSM error on a sk_buff
161  * @skb: the packet
162  * @error: the error code
163  *
164  * Description:
165  * Deal with a LSM problem when handling the packet in @skb, typically this is
166  * a permission denied problem (-EACCES).  The correct action is determined
167  * according to the packet's labeling protocol.
168  *
169  */
170 void netlbl_skbuff_err(struct sk_buff *skb, int error)
171 {
172         if (CIPSO_V4_OPTEXIST(skb))
173                 cipso_v4_error(skb, error, 0);
174 }
175
176 /**
177  * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
178  *
179  * Description:
180  * For all of the NetLabel protocols that support some form of label mapping
181  * cache, invalidate the cache.  Returns zero on success, negative values on
182  * error.
183  *
184  */
185 void netlbl_cache_invalidate(void)
186 {
187         cipso_v4_cache_invalidate();
188 }
189
190 /**
191  * netlbl_cache_add - Add an entry to a NetLabel protocol cache
192  * @skb: the packet
193  * @secattr: the packet's security attributes
194  *
195  * Description:
196  * Add the LSM security attributes for the given packet to the underlying
197  * NetLabel protocol's label mapping cache.  Returns zero on success, negative
198  * values on error.
199  *
200  */
201 int netlbl_cache_add(const struct sk_buff *skb,
202                      const struct netlbl_lsm_secattr *secattr)
203 {
204         if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
205                 return -ENOMSG;
206
207         if (CIPSO_V4_OPTEXIST(skb))
208                 return cipso_v4_cache_add(skb, secattr);
209
210         return -ENOMSG;
211 }
212
213 /*
214  * Setup Functions
215  */
216
217 /**
218  * netlbl_init - Initialize NetLabel
219  *
220  * Description:
221  * Perform the required NetLabel initialization before first use.
222  *
223  */
224 static int __init netlbl_init(void)
225 {
226         int ret_val;
227
228         printk(KERN_INFO "NetLabel: Initializing\n");
229         printk(KERN_INFO "NetLabel:  domain hash size = %u\n",
230                (1 << NETLBL_DOMHSH_BITSIZE));
231         printk(KERN_INFO "NetLabel:  protocols ="
232                " UNLABELED"
233                " CIPSOv4"
234                "\n");
235
236         ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
237         if (ret_val != 0)
238                 goto init_failure;
239
240         ret_val = netlbl_netlink_init();
241         if (ret_val != 0)
242                 goto init_failure;
243
244         ret_val = netlbl_unlabel_defconf();
245         if (ret_val != 0)
246                 goto init_failure;
247         printk(KERN_INFO "NetLabel:  unlabeled traffic allowed by default\n");
248
249         return 0;
250
251 init_failure:
252         panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
253 }
254
255 subsys_initcall(netlbl_init);