aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2006-08-03 19:48:37 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:53:34 -0400
commitd15c345fe3b8dfda0fa5a1d2143a35fffa746a43 (patch)
tree7de6afd5f4de2fca01eaca879e342ab493dc0bba /net/netlabel
parent446fda4f26822b2d42ab3396aafcedf38a9ff2b6 (diff)
[NetLabel]: core NetLabel subsystem
Add a new kernel subsystem, NetLabel, to provide explicit packet labeling services (CIPSO, RIPSO, etc.) to LSM developers. NetLabel is designed to work in conjunction with a LSM to intercept and decode security labels on incoming network packets as well as ensure that outgoing network packets are labeled according to the security mechanism employed by the LSM. The NetLabel subsystem is configured through a Generic NETLINK interface described in the header files included in this patch. Signed-off-by: Paul Moore <paul.moore@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlabel')
-rw-r--r--net/netlabel/Kconfig14
-rw-r--r--net/netlabel/Makefile16
-rw-r--r--net/netlabel/netlabel_cipso_v4.h217
-rw-r--r--net/netlabel/netlabel_domainhash.c513
-rw-r--r--net/netlabel/netlabel_domainhash.h63
-rw-r--r--net/netlabel/netlabel_kapi.c231
-rw-r--r--net/netlabel/netlabel_mgmt.c624
-rw-r--r--net/netlabel/netlabel_mgmt.h246
-rw-r--r--net/netlabel/netlabel_unlabeled.h98
-rw-r--r--net/netlabel/netlabel_user.c158
-rw-r--r--net/netlabel/netlabel_user.h214
11 files changed, 2394 insertions, 0 deletions
diff --git a/net/netlabel/Kconfig b/net/netlabel/Kconfig
new file mode 100644
index 000000000000..fe23cb7f1e87
--- /dev/null
+++ b/net/netlabel/Kconfig
@@ -0,0 +1,14 @@
1#
2# NetLabel configuration
3#
4
5config NETLABEL
6 bool "NetLabel subsystem support"
7 depends on NET && SECURITY
8 default n
9 ---help---
10 NetLabel provides support for explicit network packet labeling
11 protocols such as CIPSO and RIPSO. For more information see
12 Documentation/netlabel.
13
14 If you are unsure, say N.
diff --git a/net/netlabel/Makefile b/net/netlabel/Makefile
new file mode 100644
index 000000000000..8af18c0a47d9
--- /dev/null
+++ b/net/netlabel/Makefile
@@ -0,0 +1,16 @@
1#
2# Makefile for the NetLabel subsystem.
3#
4# Feb 9, 2006, Paul Moore <paul.moore@hp.com>
5#
6
7# base objects
8obj-y := netlabel_user.o netlabel_kapi.o netlabel_domainhash.o
9
10# management objects
11obj-y += netlabel_mgmt.o
12
13# protocol modules
14obj-y += netlabel_unlabeled.o
15obj-y += netlabel_cipso_v4.o
16
diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h
new file mode 100644
index 000000000000..4c6ff4b93004
--- /dev/null
+++ b/net/netlabel/netlabel_cipso_v4.h
@@ -0,0 +1,217 @@
1/*
2 * NetLabel CIPSO/IPv4 Support
3 *
4 * This file defines the CIPSO/IPv4 functions for the NetLabel system. The
5 * NetLabel system manages static and dynamic label mappings for network
6 * protocols such 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#ifndef _NETLABEL_CIPSO_V4
32#define _NETLABEL_CIPSO_V4
33
34#include <net/netlabel.h>
35
36/*
37 * The following NetLabel payloads are supported by the CIPSO subsystem, all
38 * of which are preceeded by the nlmsghdr struct.
39 *
40 * o ACK:
41 * Sent by the kernel in response to an applications message, applications
42 * should never send this message.
43 *
44 * +----------------------+-----------------------+
45 * | seq number (32 bits) | return code (32 bits) |
46 * +----------------------+-----------------------+
47 *
48 * seq number: the sequence number of the original message, taken from the
49 * nlmsghdr structure
50 * return code: return value, based on errno values
51 *
52 * o ADD:
53 * Sent by an application to add a new DOI mapping table, after completion
54 * of the task the kernel should ACK this message.
55 *
56 * +---------------+--------------------+---------------------+
57 * | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ...
58 * +---------------+--------------------+---------------------+
59 *
60 * +-----------------+
61 * | tag #X (8 bits) | ... repeated
62 * +-----------------+
63 *
64 * +-------------- ---- --- -- -
65 * | mapping data
66 * +-------------- ---- --- -- -
67 *
68 * DOI: the DOI value
69 * map type: the mapping table type (defined in the cipso_ipv4.h header
70 * as CIPSO_V4_MAP_*)
71 * tag count: the number of tags, must be greater than zero
72 * tag: the CIPSO tag for the DOI, tags listed first are given
73 * higher priorirty when sending packets
74 * mapping data: specific to the map type (see below)
75 *
76 * CIPSO_V4_MAP_STD
77 *
78 * +------------------+-----------------------+----------------------+
79 * | levels (32 bits) | max l level (32 bits) | max r level (8 bits) | ...
80 * +------------------+-----------------------+----------------------+
81 *
82 * +----------------------+---------------------+---------------------+
83 * | categories (32 bits) | max l cat (32 bits) | max r cat (16 bits) | ...
84 * +----------------------+---------------------+---------------------+
85 *
86 * +--------------------------+-------------------------+
87 * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
88 * +--------------------------+-------------------------+
89 *
90 * +-----------------------------+-----------------------------+
91 * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
92 * +-----------------------------+-----------------------------+
93 *
94 * levels: the number of level mappings
95 * max l level: the highest local level
96 * max r level: the highest remote/CIPSO level
97 * categories: the number of category mappings
98 * max l cat: the highest local category
99 * max r cat: the highest remote/CIPSO category
100 * local level: the local part of a level mapping
101 * CIPSO level: the remote/CIPSO part of a level mapping
102 * local category: the local part of a category mapping
103 * CIPSO category: the remote/CIPSO part of a category mapping
104 *
105 * CIPSO_V4_MAP_PASS
106 *
107 * No mapping data is needed for this map type.
108 *
109 * o REMOVE:
110 * Sent by an application to remove a specific DOI mapping table from the
111 * CIPSO V4 system. The kernel should ACK this message.
112 *
113 * +---------------+
114 * | DOI (32 bits) |
115 * +---------------+
116 *
117 * DOI: the DOI value
118 *
119 * o LIST:
120 * Sent by an application to list the details of a DOI definition. The
121 * kernel should send an ACK on error or a response as indicated below. The
122 * application generated message format is shown below.
123 *
124 * +---------------+
125 * | DOI (32 bits) |
126 * +---------------+
127 *
128 * DOI: the DOI value
129 *
130 * The valid response message format depends on the type of the DOI mapping,
131 * the known formats are shown below.
132 *
133 * +--------------------+
134 * | map type (32 bits) | ...
135 * +--------------------+
136 *
137 * map type: the DOI mapping table type (defined in the cipso_ipv4.h
138 * header as CIPSO_V4_MAP_*)
139 *
140 * (map type == CIPSO_V4_MAP_STD)
141 *
142 * +----------------+------------------+----------------------+
143 * | tags (32 bits) | levels (32 bits) | categories (32 bits) | ...
144 * +----------------+------------------+----------------------+
145 *
146 * +-----------------+
147 * | tag #X (8 bits) | ... repeated
148 * +-----------------+
149 *
150 * +--------------------------+-------------------------+
151 * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
152 * +--------------------------+-------------------------+
153 *
154 * +-----------------------------+-----------------------------+
155 * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
156 * +-----------------------------+-----------------------------+
157 *
158 * tags: the number of CIPSO tag types
159 * levels: the number of level mappings
160 * categories: the number of category mappings
161 * tag: the tag number, tags listed first are given higher
162 * priority when sending packets
163 * local level: the local part of a level mapping
164 * CIPSO level: the remote/CIPSO part of a level mapping
165 * local category: the local part of a category mapping
166 * CIPSO category: the remote/CIPSO part of a category mapping
167 *
168 * (map type == CIPSO_V4_MAP_PASS)
169 *
170 * +----------------+
171 * | tags (32 bits) | ...
172 * +----------------+
173 *
174 * +-----------------+
175 * | tag #X (8 bits) | ... repeated
176 * +-----------------+
177 *
178 * tags: the number of CIPSO tag types
179 * tag: the tag number, tags listed first are given higher
180 * priority when sending packets
181 *
182 * o LISTALL:
183 * This message is sent by an application to list the valid DOIs on the
184 * system. There is no payload and the kernel should respond with an ACK
185 * or the following message.
186 *
187 * +---------------------+------------------+-----------------------+
188 * | DOI count (32 bits) | DOI #X (32 bits) | map type #X (32 bits) |
189 * +---------------------+------------------+-----------------------+
190 *
191 * +-----------------------+
192 * | map type #X (32 bits) | ...
193 * +-----------------------+
194 *
195 * DOI count: the number of DOIs
196 * DOI: the DOI value
197 * map type: the DOI mapping table type (defined in the cipso_ipv4.h
198 * header as CIPSO_V4_MAP_*)
199 *
200 */
201
202/* NetLabel CIPSOv4 commands */
203enum {
204 NLBL_CIPSOV4_C_UNSPEC,
205 NLBL_CIPSOV4_C_ACK,
206 NLBL_CIPSOV4_C_ADD,
207 NLBL_CIPSOV4_C_REMOVE,
208 NLBL_CIPSOV4_C_LIST,
209 NLBL_CIPSOV4_C_LISTALL,
210 __NLBL_CIPSOV4_C_MAX,
211};
212#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1)
213
214/* NetLabel protocol functions */
215int netlbl_cipsov4_genl_init(void);
216
217#endif
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
new file mode 100644
index 000000000000..5bb3fad4a115
--- /dev/null
+++ b/net/netlabel/netlabel_domainhash.c
@@ -0,0 +1,513 @@
1/*
2 * NetLabel Domain Hash Table
3 *
4 * This file manages the domain hash table that NetLabel uses to determine
5 * which network labeling protocol to use for a given domain. The NetLabel
6 * system manages static and dynamic label mappings for network protocols such
7 * as CIPSO and RIPSO.
8 *
9 * Author: Paul Moore <paul.moore@hp.com>
10 *
11 */
12
13/*
14 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24 * the GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#include <linux/types.h>
33#include <linux/rcupdate.h>
34#include <linux/list.h>
35#include <linux/skbuff.h>
36#include <linux/spinlock.h>
37#include <linux/string.h>
38#include <net/netlabel.h>
39#include <net/cipso_ipv4.h>
40#include <asm/bug.h>
41
42#include "netlabel_mgmt.h"
43#include "netlabel_domainhash.h"
44
45struct netlbl_domhsh_tbl {
46 struct list_head *tbl;
47 u32 size;
48};
49
50/* Domain hash table */
51/* XXX - updates should be so rare that having one spinlock for the entire
52 * hash table should be okay */
53DEFINE_SPINLOCK(netlbl_domhsh_lock);
54static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
55
56/* Default domain mapping */
57DEFINE_SPINLOCK(netlbl_domhsh_def_lock);
58static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
59
60/*
61 * Domain Hash Table Helper Functions
62 */
63
64/**
65 * netlbl_domhsh_free_entry - Frees a domain hash table entry
66 * @entry: the entry's RCU field
67 *
68 * Description:
69 * This function is designed to be used as a callback to the call_rcu()
70 * function so that the memory allocated to a hash table entry can be released
71 * safely.
72 *
73 */
74static void netlbl_domhsh_free_entry(struct rcu_head *entry)
75{
76 struct netlbl_dom_map *ptr;
77
78 ptr = container_of(entry, struct netlbl_dom_map, rcu);
79 kfree(ptr->domain);
80 kfree(ptr);
81}
82
83/**
84 * netlbl_domhsh_hash - Hashing function for the domain hash table
85 * @domain: the domain name to hash
86 *
87 * Description:
88 * This is the hashing function for the domain hash table, it returns the
89 * correct bucket number for the domain. The caller is responsibile for
90 * calling the rcu_read_[un]lock() functions.
91 *
92 */
93static u32 netlbl_domhsh_hash(const char *key)
94{
95 u32 iter;
96 u32 val;
97 u32 len;
98
99 /* This is taken (with slight modification) from
100 * security/selinux/ss/symtab.c:symhash() */
101
102 for (iter = 0, val = 0, len = strlen(key); iter < len; iter++)
103 val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter];
104 return val & (rcu_dereference(netlbl_domhsh)->size - 1);
105}
106
107/**
108 * netlbl_domhsh_search - Search for a domain entry
109 * @domain: the domain
110 * @def: return default if no match is found
111 *
112 * Description:
113 * Searches the domain hash table and returns a pointer to the hash table
114 * entry if found, otherwise NULL is returned. If @def is non-zero and a
115 * match is not found in the domain hash table the default mapping is returned
116 * if it exists. The caller is responsibile for the rcu hash table locks
117 * (i.e. the caller much call rcu_read_[un]lock()).
118 *
119 */
120static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def)
121{
122 u32 bkt;
123 struct netlbl_dom_map *iter;
124
125 if (domain != NULL) {
126 bkt = netlbl_domhsh_hash(domain);
127 list_for_each_entry_rcu(iter, &netlbl_domhsh->tbl[bkt], list)
128 if (iter->valid && strcmp(iter->domain, domain) == 0)
129 return iter;
130 }
131
132 if (def != 0) {
133 iter = rcu_dereference(netlbl_domhsh_def);
134 if (iter != NULL && iter->valid)
135 return iter;
136 }
137
138 return NULL;
139}
140
141/*
142 * Domain Hash Table Functions
143 */
144
145/**
146 * netlbl_domhsh_init - Init for the domain hash
147 * @size: the number of bits to use for the hash buckets
148 *
149 * Description:
150 * Initializes the domain hash table, should be called only by
151 * netlbl_user_init() during initialization. Returns zero on success, non-zero
152 * values on error.
153 *
154 */
155int netlbl_domhsh_init(u32 size)
156{
157 u32 iter;
158 struct netlbl_domhsh_tbl *hsh_tbl;
159
160 if (size == 0)
161 return -EINVAL;
162
163 hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
164 if (hsh_tbl == NULL)
165 return -ENOMEM;
166 hsh_tbl->size = 1 << size;
167 hsh_tbl->tbl = kcalloc(hsh_tbl->size,
168 sizeof(struct list_head),
169 GFP_KERNEL);
170 if (hsh_tbl->tbl == NULL) {
171 kfree(hsh_tbl);
172 return -ENOMEM;
173 }
174 for (iter = 0; iter < hsh_tbl->size; iter++)
175 INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
176
177 rcu_read_lock();
178 spin_lock(&netlbl_domhsh_lock);
179 rcu_assign_pointer(netlbl_domhsh, hsh_tbl);
180 spin_unlock(&netlbl_domhsh_lock);
181 rcu_read_unlock();
182
183 return 0;
184}
185
186/**
187 * netlbl_domhsh_add - Adds a entry to the domain hash table
188 * @entry: the entry to add
189 *
190 * Description:
191 * Adds a new entry to the domain hash table and handles any updates to the
192 * lower level protocol handler (i.e. CIPSO). Returns zero on success,
193 * negative on failure.
194 *
195 */
196int netlbl_domhsh_add(struct netlbl_dom_map *entry)
197{
198 int ret_val;
199 u32 bkt;
200
201 switch (entry->type) {
202 case NETLBL_NLTYPE_UNLABELED:
203 ret_val = 0;
204 break;
205 case NETLBL_NLTYPE_CIPSOV4:
206 ret_val = cipso_v4_doi_domhsh_add(entry->type_def.cipsov4,
207 entry->domain);
208 break;
209 default:
210 return -EINVAL;
211 }
212 if (ret_val != 0)
213 return ret_val;
214
215 entry->valid = 1;
216 INIT_RCU_HEAD(&entry->rcu);
217
218 ret_val = 0;
219 rcu_read_lock();
220 if (entry->domain != NULL) {
221 bkt = netlbl_domhsh_hash(entry->domain);
222 spin_lock(&netlbl_domhsh_lock);
223 if (netlbl_domhsh_search(entry->domain, 0) == NULL)
224 list_add_tail_rcu(&entry->list,
225 &netlbl_domhsh->tbl[bkt]);
226 else
227 ret_val = -EEXIST;
228 spin_unlock(&netlbl_domhsh_lock);
229 } else if (entry->domain == NULL) {
230 INIT_LIST_HEAD(&entry->list);
231 spin_lock(&netlbl_domhsh_def_lock);
232 if (rcu_dereference(netlbl_domhsh_def) == NULL)
233 rcu_assign_pointer(netlbl_domhsh_def, entry);
234 else
235 ret_val = -EEXIST;
236 spin_unlock(&netlbl_domhsh_def_lock);
237 } else
238 ret_val = -EINVAL;
239 rcu_read_unlock();
240
241 if (ret_val != 0) {
242 switch (entry->type) {
243 case NETLBL_NLTYPE_CIPSOV4:
244 if (cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
245 entry->domain) != 0)
246 BUG();
247 break;
248 }
249 }
250
251 return ret_val;
252}
253
254/**
255 * netlbl_domhsh_add_default - Adds the default entry to the domain hash table
256 * @entry: the entry to add
257 *
258 * Description:
259 * Adds a new default entry to the domain hash table and handles any updates
260 * to the lower level protocol handler (i.e. CIPSO). Returns zero on success,
261 * negative on failure.
262 *
263 */
264int netlbl_domhsh_add_default(struct netlbl_dom_map *entry)
265{
266 return netlbl_domhsh_add(entry);
267}
268
269/**
270 * netlbl_domhsh_remove - Removes an entry from the domain hash table
271 * @domain: the domain to remove
272 *
273 * Description:
274 * Removes an entry from the domain hash table and handles any updates to the
275 * lower level protocol handler (i.e. CIPSO). Returns zero on success,
276 * negative on failure.
277 *
278 */
279int netlbl_domhsh_remove(const char *domain)
280{
281 int ret_val = -ENOENT;
282 struct netlbl_dom_map *entry;
283
284 rcu_read_lock();
285 if (domain != NULL)
286 entry = netlbl_domhsh_search(domain, 0);
287 else
288 entry = netlbl_domhsh_search(domain, 1);
289 if (entry == NULL)
290 goto remove_return;
291 switch (entry->type) {
292 case NETLBL_NLTYPE_UNLABELED:
293 break;
294 case NETLBL_NLTYPE_CIPSOV4:
295 ret_val = cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
296 entry->domain);
297 if (ret_val != 0)
298 goto remove_return;
299 break;
300 }
301 ret_val = 0;
302 if (entry != rcu_dereference(netlbl_domhsh_def)) {
303 spin_lock(&netlbl_domhsh_lock);
304 if (entry->valid) {
305 entry->valid = 0;
306 list_del_rcu(&entry->list);
307 } else
308 ret_val = -ENOENT;
309 spin_unlock(&netlbl_domhsh_lock);
310 } else {
311 spin_lock(&netlbl_domhsh_def_lock);
312 if (entry->valid) {
313 entry->valid = 0;
314 rcu_assign_pointer(netlbl_domhsh_def, NULL);
315 } else
316 ret_val = -ENOENT;
317 spin_unlock(&netlbl_domhsh_def_lock);
318 }
319 if (ret_val == 0)
320 call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
321
322remove_return:
323 rcu_read_unlock();
324 return ret_val;
325}
326
327/**
328 * netlbl_domhsh_remove_default - Removes the default entry from the table
329 *
330 * Description:
331 * Removes/resets the default entry for the domain hash table and handles any
332 * updates to the lower level protocol handler (i.e. CIPSO). Returns zero on
333 * success, non-zero on failure.
334 *
335 */
336int netlbl_domhsh_remove_default(void)
337{
338 return netlbl_domhsh_remove(NULL);
339}
340
341/**
342 * netlbl_domhsh_getentry - Get an entry from the domain hash table
343 * @domain: the domain name to search for
344 *
345 * Description:
346 * Look through the domain hash table searching for an entry to match @domain,
347 * return a pointer to a copy of the entry or NULL. The caller is responsibile
348 * for ensuring that rcu_read_[un]lock() is called.
349 *
350 */
351struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
352{
353 return netlbl_domhsh_search(domain, 1);
354}
355
356/**
357 * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff
358 *
359 * Description:
360 * Dump the domain hash table into a buffer suitable for returning to an
361 * application in response to a NetLabel management DOMAIN message. This
362 * function may fail if another process is growing the hash table at the same
363 * time. The returned sk_buff has room at the front of the sk_buff for
364 * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a
365 * pointer to a sk_buff on success, NULL on error.
366 *
367 */
368struct sk_buff *netlbl_domhsh_dump(size_t headroom)
369{
370 struct sk_buff *skb = NULL;
371 ssize_t buf_len;
372 u32 bkt_iter;
373 u32 dom_cnt = 0;
374 struct netlbl_domhsh_tbl *hsh_tbl;
375 struct netlbl_dom_map *list_iter;
376 ssize_t tmp_len;
377
378 buf_len = NETLBL_LEN_U32;
379 rcu_read_lock();
380 hsh_tbl = rcu_dereference(netlbl_domhsh);
381 for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
382 list_for_each_entry_rcu(list_iter,
383 &hsh_tbl->tbl[bkt_iter], list) {
384 buf_len += NETLBL_LEN_U32 +
385 nla_total_size(strlen(list_iter->domain) + 1);
386 switch (list_iter->type) {
387 case NETLBL_NLTYPE_UNLABELED:
388 break;
389 case NETLBL_NLTYPE_CIPSOV4:
390 buf_len += 2 * NETLBL_LEN_U32;
391 break;
392 }
393 dom_cnt++;
394 }
395
396 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
397 if (skb == NULL)
398 goto dump_failure;
399
400 if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0)
401 goto dump_failure;
402 buf_len -= NETLBL_LEN_U32;
403 hsh_tbl = rcu_dereference(netlbl_domhsh);
404 for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
405 list_for_each_entry_rcu(list_iter,
406 &hsh_tbl->tbl[bkt_iter], list) {
407 tmp_len = nla_total_size(strlen(list_iter->domain) +
408 1);
409 if (buf_len < NETLBL_LEN_U32 + tmp_len)
410 goto dump_failure;
411 if (nla_put_string(skb,
412 NLA_STRING,
413 list_iter->domain) != 0)
414 goto dump_failure;
415 if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0)
416 goto dump_failure;
417 buf_len -= NETLBL_LEN_U32 + tmp_len;
418 switch (list_iter->type) {
419 case NETLBL_NLTYPE_UNLABELED:
420 break;
421 case NETLBL_NLTYPE_CIPSOV4:
422 if (buf_len < 2 * NETLBL_LEN_U32)
423 goto dump_failure;
424 if (nla_put_u32(skb,
425 NLA_U32,
426 list_iter->type_def.cipsov4->type) != 0)
427 goto dump_failure;
428 if (nla_put_u32(skb,
429 NLA_U32,
430 list_iter->type_def.cipsov4->doi) != 0)
431 goto dump_failure;
432 buf_len -= 2 * NETLBL_LEN_U32;
433 break;
434 }
435 }
436 rcu_read_unlock();
437
438 return skb;
439
440dump_failure:
441 rcu_read_unlock();
442 kfree_skb(skb);
443 return NULL;
444}
445
446/**
447 * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff
448 *
449 * Description:
450 * Dump the default domain mapping into a buffer suitable for returning to an
451 * application in response to a NetLabel management DEFDOMAIN message. This
452 * function may fail if another process is changing the default domain mapping
453 * at the same time. The returned sk_buff has room at the front of the
454 * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message
455 * format. Returns a pointer to a sk_buff on success, NULL on error.
456 *
457 */
458struct sk_buff *netlbl_domhsh_dump_default(size_t headroom)
459{
460 struct sk_buff *skb;
461 ssize_t buf_len;
462 struct netlbl_dom_map *entry;
463
464 buf_len = NETLBL_LEN_U32;
465 rcu_read_lock();
466 entry = rcu_dereference(netlbl_domhsh_def);
467 if (entry != NULL)
468 switch (entry->type) {
469 case NETLBL_NLTYPE_UNLABELED:
470 break;
471 case NETLBL_NLTYPE_CIPSOV4:
472 buf_len += 2 * NETLBL_LEN_U32;
473 break;
474 }
475
476 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
477 if (skb == NULL)
478 goto dump_default_failure;
479
480 if (entry != rcu_dereference(netlbl_domhsh_def))
481 goto dump_default_failure;
482 if (entry != NULL) {
483 if (nla_put_u32(skb, NLA_U32, entry->type) != 0)
484 goto dump_default_failure;
485 buf_len -= NETLBL_LEN_U32;
486 switch (entry->type) {
487 case NETLBL_NLTYPE_UNLABELED:
488 break;
489 case NETLBL_NLTYPE_CIPSOV4:
490 if (buf_len < 2 * NETLBL_LEN_U32)
491 goto dump_default_failure;
492 if (nla_put_u32(skb,
493 NLA_U32,
494 entry->type_def.cipsov4->type) != 0)
495 goto dump_default_failure;
496 if (nla_put_u32(skb,
497 NLA_U32,
498 entry->type_def.cipsov4->doi) != 0)
499 goto dump_default_failure;
500 buf_len -= 2 * NETLBL_LEN_U32;
501 break;
502 }
503 } else
504 nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE);
505 rcu_read_unlock();
506
507 return skb;
508
509dump_default_failure:
510 rcu_read_unlock();
511 kfree_skb(skb);
512 return NULL;
513}
diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h
new file mode 100644
index 000000000000..9217863ce0d3
--- /dev/null
+++ b/net/netlabel/netlabel_domainhash.h
@@ -0,0 +1,63 @@
1/*
2 * NetLabel Domain Hash Table
3 *
4 * This file manages the domain hash table that NetLabel uses to determine
5 * which network labeling protocol to use for a given domain. The NetLabel
6 * system manages static and dynamic label mappings for network protocols such
7 * as CIPSO and RIPSO.
8 *
9 * Author: Paul Moore <paul.moore@hp.com>
10 *
11 */
12
13/*
14 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
24 * the GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#ifndef _NETLABEL_DOMAINHASH_H
33#define _NETLABEL_DOMAINHASH_H
34
35/* Domain hash table size */
36/* XXX - currently this number is an uneducated guess */
37#define NETLBL_DOMHSH_BITSIZE 7
38
39/* Domain mapping definition struct */
40struct netlbl_dom_map {
41 char *domain;
42 u32 type;
43 union {
44 struct cipso_v4_doi *cipsov4;
45 } type_def;
46
47 u32 valid;
48 struct list_head list;
49 struct rcu_head rcu;
50};
51
52/* init function */
53int netlbl_domhsh_init(u32 size);
54
55/* Manipulate the domain hash table */
56int netlbl_domhsh_add(struct netlbl_dom_map *entry);
57int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
58int netlbl_domhsh_remove_default(void);
59struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
60struct sk_buff *netlbl_domhsh_dump(size_t headroom);
61struct sk_buff *netlbl_domhsh_dump_default(size_t headroom);
62
63#endif
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
new file mode 100644
index 000000000000..0fd8aaafe23f
--- /dev/null
+++ b/net/netlabel/netlabel_kapi.c
@@ -0,0 +1,231 @@
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 */
59int 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
82socket_setattr_return:
83 rcu_read_unlock();
84 return ret_val;
85}
86
87/**
88 * netlbl_socket_getattr - Determine the security attributes of a socket
89 * @sock: the socket
90 * @secattr: the security attributes
91 *
92 * Description:
93 * Examines the given socket to see any NetLabel style labeling has been
94 * applied to the socket, 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 */
99int netlbl_socket_getattr(const struct socket *sock,
100 struct netlbl_lsm_secattr *secattr)
101{
102 int ret_val;
103
104 ret_val = cipso_v4_socket_getattr(sock, secattr);
105 if (ret_val == 0)
106 return 0;
107
108 return netlbl_unlabel_getattr(secattr);
109}
110
111/**
112 * netlbl_skbuff_getattr - Determine the security attributes of a packet
113 * @skb: the packet
114 * @secattr: the security attributes
115 *
116 * Description:
117 * Examines the given packet to see if a recognized form of packet labeling
118 * is present, if so it parses the packet label and returns the security
119 * attributes in @secattr. Returns zero on success, negative values on
120 * failure.
121 *
122 */
123int netlbl_skbuff_getattr(const struct sk_buff *skb,
124 struct netlbl_lsm_secattr *secattr)
125{
126 int ret_val;
127
128 ret_val = cipso_v4_skbuff_getattr(skb, secattr);
129 if (ret_val == 0)
130 return 0;
131
132 return netlbl_unlabel_getattr(secattr);
133}
134
135/**
136 * netlbl_skbuff_err - Handle a LSM error on a sk_buff
137 * @skb: the packet
138 * @error: the error code
139 *
140 * Description:
141 * Deal with a LSM problem when handling the packet in @skb, typically this is
142 * a permission denied problem (-EACCES). The correct action is determined
143 * according to the packet's labeling protocol.
144 *
145 */
146void netlbl_skbuff_err(struct sk_buff *skb, int error)
147{
148 if (CIPSO_V4_OPTEXIST(skb))
149 cipso_v4_error(skb, error, 0);
150}
151
152/**
153 * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
154 *
155 * Description:
156 * For all of the NetLabel protocols that support some form of label mapping
157 * cache, invalidate the cache. Returns zero on success, negative values on
158 * error.
159 *
160 */
161void netlbl_cache_invalidate(void)
162{
163 cipso_v4_cache_invalidate();
164}
165
166/**
167 * netlbl_cache_add - Add an entry to a NetLabel protocol cache
168 * @skb: the packet
169 * @secattr: the packet's security attributes
170 *
171 * Description:
172 * Add the LSM security attributes for the given packet to the underlying
173 * NetLabel protocol's label mapping cache. Returns zero on success, negative
174 * values on error.
175 *
176 */
177int netlbl_cache_add(const struct sk_buff *skb,
178 const struct netlbl_lsm_secattr *secattr)
179{
180 if (secattr->cache.data == NULL)
181 return -ENOMSG;
182
183 if (CIPSO_V4_OPTEXIST(skb))
184 return cipso_v4_cache_add(skb, secattr);
185
186 return -ENOMSG;
187}
188
189/*
190 * Setup Functions
191 */
192
193/**
194 * netlbl_init - Initialize NetLabel
195 *
196 * Description:
197 * Perform the required NetLabel initialization before first use.
198 *
199 */
200static int __init netlbl_init(void)
201{
202 int ret_val;
203
204 printk(KERN_INFO "NetLabel: Initializing\n");
205 printk(KERN_INFO "NetLabel: domain hash size = %u\n",
206 (1 << NETLBL_DOMHSH_BITSIZE));
207 printk(KERN_INFO "NetLabel: protocols ="
208 " UNLABELED"
209 " CIPSOv4"
210 "\n");
211
212 ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
213 if (ret_val != 0)
214 goto init_failure;
215
216 ret_val = netlbl_netlink_init();
217 if (ret_val != 0)
218 goto init_failure;
219
220 ret_val = netlbl_unlabel_defconf();
221 if (ret_val != 0)
222 goto init_failure;
223 printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
224
225 return 0;
226
227init_failure:
228 panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
229}
230
231subsys_initcall(netlbl_init);
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
new file mode 100644
index 000000000000..85bc11a1fc46
--- /dev/null
+++ b/net/netlabel/netlabel_mgmt.c
@@ -0,0 +1,624 @@
1/*
2 * NetLabel Management Support
3 *
4 * This file defines the management functions for the NetLabel system. The
5 * NetLabel system manages static and dynamic label mappings for network
6 * protocols such 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/types.h>
32#include <linux/socket.h>
33#include <linux/string.h>
34#include <linux/skbuff.h>
35#include <net/sock.h>
36#include <net/netlink.h>
37#include <net/genetlink.h>
38#include <net/netlabel.h>
39#include <net/cipso_ipv4.h>
40
41#include "netlabel_domainhash.h"
42#include "netlabel_user.h"
43#include "netlabel_mgmt.h"
44
45/* NetLabel Generic NETLINK CIPSOv4 family */
46static struct genl_family netlbl_mgmt_gnl_family = {
47 .id = GENL_ID_GENERATE,
48 .hdrsize = 0,
49 .name = NETLBL_NLTYPE_MGMT_NAME,
50 .version = NETLBL_PROTO_VERSION,
51 .maxattr = 0,
52};
53
54
55/*
56 * NetLabel Command Handlers
57 */
58
59/**
60 * netlbl_mgmt_add - Handle an ADD message
61 * @skb: the NETLINK buffer
62 * @info: the Generic NETLINK info block
63 *
64 * Description:
65 * Process a user generated ADD message and add the domains from the message
66 * to the hash table. See netlabel.h for a description of the message format.
67 * Returns zero on success, negative values on failure.
68 *
69 */
70static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
71{
72 int ret_val = -EINVAL;
73 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
74 int msg_len = netlbl_netlink_payload_len(skb);
75 u32 count;
76 struct netlbl_dom_map *entry = NULL;
77 u32 iter;
78 u32 tmp_val;
79 int tmp_size;
80
81 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
82 if (ret_val != 0)
83 goto add_failure;
84
85 if (msg_len < NETLBL_LEN_U32)
86 goto add_failure;
87 count = netlbl_getinc_u32(&msg_ptr, &msg_len);
88
89 for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) {
90 if (msg_len <= 0) {
91 ret_val = -EINVAL;
92 goto add_failure;
93 }
94 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
95 if (entry == NULL) {
96 ret_val = -ENOMEM;
97 goto add_failure;
98 }
99 tmp_size = nla_len(msg_ptr);
100 if (tmp_size <= 0 || tmp_size > msg_len) {
101 ret_val = -EINVAL;
102 goto add_failure;
103 }
104 entry->domain = kmalloc(tmp_size, GFP_KERNEL);
105 if (entry->domain == NULL) {
106 ret_val = -ENOMEM;
107 goto add_failure;
108 }
109 nla_strlcpy(entry->domain, msg_ptr, tmp_size);
110 entry->domain[tmp_size - 1] = '\0';
111 msg_ptr = nla_next(msg_ptr, &msg_len);
112
113 if (msg_len < NETLBL_LEN_U32) {
114 ret_val = -EINVAL;
115 goto add_failure;
116 }
117 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
118 entry->type = tmp_val;
119 switch (tmp_val) {
120 case NETLBL_NLTYPE_UNLABELED:
121 ret_val = netlbl_domhsh_add(entry);
122 break;
123 case NETLBL_NLTYPE_CIPSOV4:
124 if (msg_len < NETLBL_LEN_U32) {
125 ret_val = -EINVAL;
126 goto add_failure;
127 }
128 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
129 /* We should be holding a rcu_read_lock() here
130 * while we hold the result but since the entry
131 * will always be deleted when the CIPSO DOI
132 * is deleted we aren't going to keep the lock. */
133 rcu_read_lock();
134 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
135 if (entry->type_def.cipsov4 == NULL) {
136 rcu_read_unlock();
137 ret_val = -EINVAL;
138 goto add_failure;
139 }
140 ret_val = netlbl_domhsh_add(entry);
141 rcu_read_unlock();
142 break;
143 default:
144 ret_val = -EINVAL;
145 }
146 if (ret_val != 0)
147 goto add_failure;
148 }
149
150 netlbl_netlink_send_ack(info,
151 netlbl_mgmt_gnl_family.id,
152 NLBL_MGMT_C_ACK,
153 NETLBL_E_OK);
154 return 0;
155
156add_failure:
157 if (entry)
158 kfree(entry->domain);
159 kfree(entry);
160 netlbl_netlink_send_ack(info,
161 netlbl_mgmt_gnl_family.id,
162 NLBL_MGMT_C_ACK,
163 -ret_val);
164 return ret_val;
165}
166
167/**
168 * netlbl_mgmt_remove - Handle a REMOVE message
169 * @skb: the NETLINK buffer
170 * @info: the Generic NETLINK info block
171 *
172 * Description:
173 * Process a user generated REMOVE message and remove the specified domain
174 * mappings. Returns zero on success, negative values on failure.
175 *
176 */
177static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
178{
179 int ret_val = -EINVAL;
180 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
181 int msg_len = netlbl_netlink_payload_len(skb);
182 u32 count;
183 u32 iter;
184 int tmp_size;
185 unsigned char *domain;
186
187 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
188 if (ret_val != 0)
189 goto remove_return;
190
191 if (msg_len < NETLBL_LEN_U32)
192 goto remove_return;
193 count = netlbl_getinc_u32(&msg_ptr, &msg_len);
194
195 for (iter = 0; iter < count && msg_len > 0; iter++) {
196 if (msg_len <= 0) {
197 ret_val = -EINVAL;
198 goto remove_return;
199 }
200 tmp_size = nla_len(msg_ptr);
201 domain = nla_data(msg_ptr);
202 if (tmp_size <= 0 || tmp_size > msg_len ||
203 domain[tmp_size - 1] != '\0') {
204 ret_val = -EINVAL;
205 goto remove_return;
206 }
207 ret_val = netlbl_domhsh_remove(domain);
208 if (ret_val != 0)
209 goto remove_return;
210 msg_ptr = nla_next(msg_ptr, &msg_len);
211 }
212
213 ret_val = 0;
214
215remove_return:
216 netlbl_netlink_send_ack(info,
217 netlbl_mgmt_gnl_family.id,
218 NLBL_MGMT_C_ACK,
219 -ret_val);
220 return ret_val;
221}
222
223/**
224 * netlbl_mgmt_list - Handle a LIST message
225 * @skb: the NETLINK buffer
226 * @info: the Generic NETLINK info block
227 *
228 * Description:
229 * Process a user generated LIST message and dumps the domain hash table in a
230 * form suitable for use in a kernel generated LIST message. Returns zero on
231 * success, negative values on failure.
232 *
233 */
234static int netlbl_mgmt_list(struct sk_buff *skb, struct genl_info *info)
235{
236 int ret_val = -ENOMEM;
237 struct sk_buff *ans_skb;
238
239 ans_skb = netlbl_domhsh_dump(NLMSG_SPACE(GENL_HDRLEN));
240 if (ans_skb == NULL)
241 goto list_failure;
242 netlbl_netlink_hdr_push(ans_skb,
243 info->snd_pid,
244 0,
245 netlbl_mgmt_gnl_family.id,
246 NLBL_MGMT_C_LIST);
247
248 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
249 if (ret_val != 0)
250 goto list_failure;
251
252 return 0;
253
254list_failure:
255 netlbl_netlink_send_ack(info,
256 netlbl_mgmt_gnl_family.id,
257 NLBL_MGMT_C_ACK,
258 -ret_val);
259 return ret_val;
260}
261
262/**
263 * netlbl_mgmt_adddef - Handle an ADDDEF message
264 * @skb: the NETLINK buffer
265 * @info: the Generic NETLINK info block
266 *
267 * Description:
268 * Process a user generated ADDDEF message and respond accordingly. Returns
269 * zero on success, negative values on failure.
270 *
271 */
272static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
273{
274 int ret_val = -EINVAL;
275 struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
276 int msg_len = netlbl_netlink_payload_len(skb);
277 struct netlbl_dom_map *entry = NULL;
278 u32 tmp_val;
279
280 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
281 if (ret_val != 0)
282 goto adddef_failure;
283
284 if (msg_len < NETLBL_LEN_U32)
285 goto adddef_failure;
286 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
287
288 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
289 if (entry == NULL) {
290 ret_val = -ENOMEM;
291 goto adddef_failure;
292 }
293
294 entry->type = tmp_val;
295 switch (entry->type) {
296 case NETLBL_NLTYPE_UNLABELED:
297 ret_val = netlbl_domhsh_add_default(entry);
298 break;
299 case NETLBL_NLTYPE_CIPSOV4:
300 if (msg_len < NETLBL_LEN_U32) {
301 ret_val = -EINVAL;
302 goto adddef_failure;
303 }
304 tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
305 /* We should be holding a rcu_read_lock here while we
306 * hold the result but since the entry will always be
307 * deleted when the CIPSO DOI is deleted we are going
308 * to skip the lock. */
309 rcu_read_lock();
310 entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
311 if (entry->type_def.cipsov4 == NULL) {
312 rcu_read_unlock();
313 ret_val = -EINVAL;
314 goto adddef_failure;
315 }
316 ret_val = netlbl_domhsh_add_default(entry);
317 rcu_read_unlock();
318 break;
319 default:
320 ret_val = -EINVAL;
321 }
322 if (ret_val != 0)
323 goto adddef_failure;
324
325 netlbl_netlink_send_ack(info,
326 netlbl_mgmt_gnl_family.id,
327 NLBL_MGMT_C_ACK,
328 NETLBL_E_OK);
329 return 0;
330
331adddef_failure:
332 kfree(entry);
333 netlbl_netlink_send_ack(info,
334 netlbl_mgmt_gnl_family.id,
335 NLBL_MGMT_C_ACK,
336 -ret_val);
337 return ret_val;
338}
339
340/**
341 * netlbl_mgmt_removedef - Handle a REMOVEDEF message
342 * @skb: the NETLINK buffer
343 * @info: the Generic NETLINK info block
344 *
345 * Description:
346 * Process a user generated REMOVEDEF message and remove the default domain
347 * mapping. Returns zero on success, negative values on failure.
348 *
349 */
350static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
351{
352 int ret_val;
353
354 ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
355 if (ret_val != 0)
356 goto removedef_return;
357
358 ret_val = netlbl_domhsh_remove_default();
359
360removedef_return:
361 netlbl_netlink_send_ack(info,
362 netlbl_mgmt_gnl_family.id,
363 NLBL_MGMT_C_ACK,
364 -ret_val);
365 return ret_val;
366}
367
368/**
369 * netlbl_mgmt_listdef - Handle a LISTDEF message
370 * @skb: the NETLINK buffer
371 * @info: the Generic NETLINK info block
372 *
373 * Description:
374 * Process a user generated LISTDEF message and dumps the default domain
375 * mapping in a form suitable for use in a kernel generated LISTDEF message.
376 * Returns zero on success, negative values on failure.
377 *
378 */
379static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
380{
381 int ret_val = -ENOMEM;
382 struct sk_buff *ans_skb;
383
384 ans_skb = netlbl_domhsh_dump_default(NLMSG_SPACE(GENL_HDRLEN));
385 if (ans_skb == NULL)
386 goto listdef_failure;
387 netlbl_netlink_hdr_push(ans_skb,
388 info->snd_pid,
389 0,
390 netlbl_mgmt_gnl_family.id,
391 NLBL_MGMT_C_LISTDEF);
392
393 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
394 if (ret_val != 0)
395 goto listdef_failure;
396
397 return 0;
398
399listdef_failure:
400 netlbl_netlink_send_ack(info,
401 netlbl_mgmt_gnl_family.id,
402 NLBL_MGMT_C_ACK,
403 -ret_val);
404 return ret_val;
405}
406
407/**
408 * netlbl_mgmt_modules - Handle a MODULES message
409 * @skb: the NETLINK buffer
410 * @info: the Generic NETLINK info block
411 *
412 * Description:
413 * Process a user generated MODULES message and respond accordingly.
414 *
415 */
416static int netlbl_mgmt_modules(struct sk_buff *skb, struct genl_info *info)
417{
418 int ret_val = -ENOMEM;
419 size_t data_size;
420 u32 mod_count;
421 struct sk_buff *ans_skb = NULL;
422
423 /* unlabeled + cipsov4 */
424 mod_count = 2;
425
426 data_size = GENL_HDRLEN + NETLBL_LEN_U32 + mod_count * NETLBL_LEN_U32;
427 ans_skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL);
428 if (ans_skb == NULL)
429 goto modules_failure;
430
431 if (netlbl_netlink_hdr_put(ans_skb,
432 info->snd_pid,
433 0,
434 netlbl_mgmt_gnl_family.id,
435 NLBL_MGMT_C_MODULES) == NULL)
436 goto modules_failure;
437
438 ret_val = nla_put_u32(ans_skb, NLA_U32, mod_count);
439 if (ret_val != 0)
440 goto modules_failure;
441 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_UNLABELED);
442 if (ret_val != 0)
443 goto modules_failure;
444 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_CIPSOV4);
445 if (ret_val != 0)
446 goto modules_failure;
447
448 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
449 if (ret_val != 0)
450 goto modules_failure;
451
452 return 0;
453
454modules_failure:
455 kfree_skb(ans_skb);
456 netlbl_netlink_send_ack(info,
457 netlbl_mgmt_gnl_family.id,
458 NLBL_MGMT_C_ACK,
459 -ret_val);
460 return ret_val;
461}
462
463/**
464 * netlbl_mgmt_version - Handle a VERSION message
465 * @skb: the NETLINK buffer
466 * @info: the Generic NETLINK info block
467 *
468 * Description:
469 * Process a user generated VERSION message and respond accordingly. Returns
470 * zero on success, negative values on failure.
471 *
472 */
473static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
474{
475 int ret_val = -ENOMEM;
476 struct sk_buff *ans_skb = NULL;
477
478 ans_skb = netlbl_netlink_alloc_skb(0,
479 GENL_HDRLEN + NETLBL_LEN_U32,
480 GFP_KERNEL);
481 if (ans_skb == NULL)
482 goto version_failure;
483 if (netlbl_netlink_hdr_put(ans_skb,
484 info->snd_pid,
485 0,
486 netlbl_mgmt_gnl_family.id,
487 NLBL_MGMT_C_VERSION) == NULL)
488 goto version_failure;
489
490 ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_PROTO_VERSION);
491 if (ret_val != 0)
492 goto version_failure;
493
494 ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
495 if (ret_val != 0)
496 goto version_failure;
497
498 return 0;
499
500version_failure:
501 kfree_skb(ans_skb);
502 netlbl_netlink_send_ack(info,
503 netlbl_mgmt_gnl_family.id,
504 NLBL_MGMT_C_ACK,
505 -ret_val);
506 return ret_val;
507}
508
509
510/*
511 * NetLabel Generic NETLINK Command Definitions
512 */
513
514static struct genl_ops netlbl_mgmt_genl_c_add = {
515 .cmd = NLBL_MGMT_C_ADD,
516 .flags = 0,
517 .doit = netlbl_mgmt_add,
518 .dumpit = NULL,
519};
520
521static struct genl_ops netlbl_mgmt_genl_c_remove = {
522 .cmd = NLBL_MGMT_C_REMOVE,
523 .flags = 0,
524 .doit = netlbl_mgmt_remove,
525 .dumpit = NULL,
526};
527
528static struct genl_ops netlbl_mgmt_genl_c_list = {
529 .cmd = NLBL_MGMT_C_LIST,
530 .flags = 0,
531 .doit = netlbl_mgmt_list,
532 .dumpit = NULL,
533};
534
535static struct genl_ops netlbl_mgmt_genl_c_adddef = {
536 .cmd = NLBL_MGMT_C_ADDDEF,
537 .flags = 0,
538 .doit = netlbl_mgmt_adddef,
539 .dumpit = NULL,
540};
541
542static struct genl_ops netlbl_mgmt_genl_c_removedef = {
543 .cmd = NLBL_MGMT_C_REMOVEDEF,
544 .flags = 0,
545 .doit = netlbl_mgmt_removedef,
546 .dumpit = NULL,
547};
548
549static struct genl_ops netlbl_mgmt_genl_c_listdef = {
550 .cmd = NLBL_MGMT_C_LISTDEF,
551 .flags = 0,
552 .doit = netlbl_mgmt_listdef,
553 .dumpit = NULL,
554};
555
556static struct genl_ops netlbl_mgmt_genl_c_modules = {
557 .cmd = NLBL_MGMT_C_MODULES,
558 .flags = 0,
559 .doit = netlbl_mgmt_modules,
560 .dumpit = NULL,
561};
562
563static struct genl_ops netlbl_mgmt_genl_c_version = {
564 .cmd = NLBL_MGMT_C_VERSION,
565 .flags = 0,
566 .doit = netlbl_mgmt_version,
567 .dumpit = NULL,
568};
569
570/*
571 * NetLabel Generic NETLINK Protocol Functions
572 */
573
574/**
575 * netlbl_mgmt_genl_init - Register the NetLabel management component
576 *
577 * Description:
578 * Register the NetLabel management component with the Generic NETLINK
579 * mechanism. Returns zero on success, negative values on failure.
580 *
581 */
582int netlbl_mgmt_genl_init(void)
583{
584 int ret_val;
585
586 ret_val = genl_register_family(&netlbl_mgmt_gnl_family);
587 if (ret_val != 0)
588 return ret_val;
589
590 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
591 &netlbl_mgmt_genl_c_add);
592 if (ret_val != 0)
593 return ret_val;
594 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
595 &netlbl_mgmt_genl_c_remove);
596 if (ret_val != 0)
597 return ret_val;
598 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
599 &netlbl_mgmt_genl_c_list);
600 if (ret_val != 0)
601 return ret_val;
602 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
603 &netlbl_mgmt_genl_c_adddef);
604 if (ret_val != 0)
605 return ret_val;
606 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
607 &netlbl_mgmt_genl_c_removedef);
608 if (ret_val != 0)
609 return ret_val;
610 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
611 &netlbl_mgmt_genl_c_listdef);
612 if (ret_val != 0)
613 return ret_val;
614 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
615 &netlbl_mgmt_genl_c_modules);
616 if (ret_val != 0)
617 return ret_val;
618 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
619 &netlbl_mgmt_genl_c_version);
620 if (ret_val != 0)
621 return ret_val;
622
623 return 0;
624}
diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h
new file mode 100644
index 000000000000..fd6c6acbfa08
--- /dev/null
+++ b/net/netlabel/netlabel_mgmt.h
@@ -0,0 +1,246 @@
1/*
2 * NetLabel Management Support
3 *
4 * This file defines the management functions for the NetLabel system. The
5 * NetLabel system manages static and dynamic label mappings for network
6 * protocols such 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#ifndef _NETLABEL_MGMT_H
32#define _NETLABEL_MGMT_H
33
34#include <net/netlabel.h>
35
36/*
37 * The following NetLabel payloads are supported by the management interface,
38 * all of which are preceeded by the nlmsghdr struct.
39 *
40 * o ACK:
41 * Sent by the kernel in response to an applications message, applications
42 * should never send this message.
43 *
44 * +----------------------+-----------------------+
45 * | seq number (32 bits) | return code (32 bits) |
46 * +----------------------+-----------------------+
47 *
48 * seq number: the sequence number of the original message, taken from the
49 * nlmsghdr structure
50 * return code: return value, based on errno values
51 *
52 * o ADD:
53 * Sent by an application to add a domain mapping to the NetLabel system.
54 * The kernel should respond with an ACK.
55 *
56 * +-------------------+
57 * | domains (32 bits) | ...
58 * +-------------------+
59 *
60 * domains: the number of domains in the message
61 *
62 * +--------------------------+-------------------------+
63 * | domain string (variable) | protocol type (32 bits) | ...
64 * +--------------------------+-------------------------+
65 *
66 * +-------------- ---- --- -- -
67 * | mapping data ... repeated
68 * +-------------- ---- --- -- -
69 *
70 * domain string: the domain string, NULL terminated
71 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
72 * mapping data: specific to the map type (see below)
73 *
74 * NETLBL_NLTYPE_UNLABELED
75 *
76 * No mapping data for this protocol type.
77 *
78 * NETLBL_NLTYPE_CIPSOV4
79 *
80 * +---------------+
81 * | doi (32 bits) |
82 * +---------------+
83 *
84 * doi: the CIPSO DOI value
85 *
86 * o REMOVE:
87 * Sent by an application to remove a domain mapping from the NetLabel
88 * system. The kernel should ACK this message.
89 *
90 * +-------------------+
91 * | domains (32 bits) | ...
92 * +-------------------+
93 *
94 * domains: the number of domains in the message
95 *
96 * +--------------------------+
97 * | domain string (variable) | ...
98 * +--------------------------+
99 *
100 * domain string: the domain string, NULL terminated
101 *
102 * o LIST:
103 * This message can be sent either from an application or by the kernel in
104 * response to an application generated LIST message. When sent by an
105 * application there is no payload. The kernel should respond to a LIST
106 * message either with a LIST message on success or an ACK message on
107 * failure.
108 *
109 * +-------------------+
110 * | domains (32 bits) | ...
111 * +-------------------+
112 *
113 * domains: the number of domains in the message
114 *
115 * +--------------------------+
116 * | domain string (variable) | ...
117 * +--------------------------+
118 *
119 * +-------------------------+-------------- ---- --- -- -
120 * | protocol type (32 bits) | mapping data ... repeated
121 * +-------------------------+-------------- ---- --- -- -
122 *
123 * domain string: the domain string, NULL terminated
124 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
125 * mapping data: specific to the map type (see below)
126 *
127 * NETLBL_NLTYPE_UNLABELED
128 *
129 * No mapping data for this protocol type.
130 *
131 * NETLBL_NLTYPE_CIPSOV4
132 *
133 * +----------------+---------------+
134 * | type (32 bits) | doi (32 bits) |
135 * +----------------+---------------+
136 *
137 * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
138 * as CIPSO_V4_MAP_*)
139 * doi: the CIPSO DOI value
140 *
141 * o ADDDEF:
142 * Sent by an application to set the default domain mapping for the NetLabel
143 * system. The kernel should respond with an ACK.
144 *
145 * +-------------------------+-------------- ---- --- -- -
146 * | protocol type (32 bits) | mapping data ... repeated
147 * +-------------------------+-------------- ---- --- -- -
148 *
149 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
150 * mapping data: specific to the map type (see below)
151 *
152 * NETLBL_NLTYPE_UNLABELED
153 *
154 * No mapping data for this protocol type.
155 *
156 * NETLBL_NLTYPE_CIPSOV4
157 *
158 * +---------------+
159 * | doi (32 bits) |
160 * +---------------+
161 *
162 * doi: the CIPSO DOI value
163 *
164 * o REMOVEDEF:
165 * Sent by an application to remove the default domain mapping from the
166 * NetLabel system, there is no payload. The kernel should ACK this message.
167 *
168 * o LISTDEF:
169 * This message can be sent either from an application or by the kernel in
170 * response to an application generated LISTDEF message. When sent by an
171 * application there is no payload. The kernel should respond to a
172 * LISTDEF message either with a LISTDEF message on success or an ACK message
173 * on failure.
174 *
175 * +-------------------------+-------------- ---- --- -- -
176 * | protocol type (32 bits) | mapping data ... repeated
177 * +-------------------------+-------------- ---- --- -- -
178 *
179 * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
180 * mapping data: specific to the map type (see below)
181 *
182 * NETLBL_NLTYPE_UNLABELED
183 *
184 * No mapping data for this protocol type.
185 *
186 * NETLBL_NLTYPE_CIPSOV4
187 *
188 * +----------------+---------------+
189 * | type (32 bits) | doi (32 bits) |
190 * +----------------+---------------+
191 *
192 * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
193 * as CIPSO_V4_MAP_*)
194 * doi: the CIPSO DOI value
195 *
196 * o MODULES:
197 * Sent by an application to request a list of configured NetLabel modules
198 * in the kernel. When sent by an application there is no payload.
199 *
200 * +-------------------+
201 * | modules (32 bits) | ...
202 * +-------------------+
203 *
204 * modules: the number of modules in the message, if this is an application
205 * generated message and the value is zero then return a list of
206 * the configured modules
207 *
208 * +------------------+
209 * | module (32 bits) | ... repeated
210 * +------------------+
211 *
212 * module: the module number as defined by NETLBL_NLTYPE_*
213 *
214 * o VERSION:
215 * Sent by an application to request the NetLabel version string. When sent
216 * by an application there is no payload. This message type is also used by
217 * the kernel to respond to an VERSION request.
218 *
219 * +-------------------+
220 * | version (32 bits) |
221 * +-------------------+
222 *
223 * version: the protocol version number
224 *
225 */
226
227/* NetLabel Management commands */
228enum {
229 NLBL_MGMT_C_UNSPEC,
230 NLBL_MGMT_C_ACK,
231 NLBL_MGMT_C_ADD,
232 NLBL_MGMT_C_REMOVE,
233 NLBL_MGMT_C_LIST,
234 NLBL_MGMT_C_ADDDEF,
235 NLBL_MGMT_C_REMOVEDEF,
236 NLBL_MGMT_C_LISTDEF,
237 NLBL_MGMT_C_MODULES,
238 NLBL_MGMT_C_VERSION,
239 __NLBL_MGMT_C_MAX,
240};
241#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1)
242
243/* NetLabel protocol functions */
244int netlbl_mgmt_genl_init(void);
245
246#endif
diff --git a/net/netlabel/netlabel_unlabeled.h b/net/netlabel/netlabel_unlabeled.h
new file mode 100644
index 000000000000..f300e54e14b6
--- /dev/null
+++ b/net/netlabel/netlabel_unlabeled.h
@@ -0,0 +1,98 @@
1/*
2 * NetLabel Unlabeled Support
3 *
4 * This file defines functions for dealing with unlabeled packets for the
5 * NetLabel system. The NetLabel system manages static and dynamic label
6 * mappings for network protocols such 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#ifndef _NETLABEL_UNLABELED_H
32#define _NETLABEL_UNLABELED_H
33
34#include <net/netlabel.h>
35
36/*
37 * The following NetLabel payloads are supported by the Unlabeled subsystem.
38 *
39 * o ACK:
40 * Sent by the kernel in response to an applications message, applications
41 * should never send this message.
42 *
43 * +----------------------+-----------------------+
44 * | seq number (32 bits) | return code (32 bits) |
45 * +----------------------+-----------------------+
46 *
47 * seq number: the sequence number of the original message, taken from the
48 * nlmsghdr structure
49 * return code: return value, based on errno values
50 *
51 * o ACCEPT
52 * This message is sent from an application to specify if the kernel should
53 * allow unlabled packets to pass if they do not match any of the static
54 * mappings defined in the unlabeled module.
55 *
56 * +-----------------+
57 * | allow (32 bits) |
58 * +-----------------+
59 *
60 * allow: if true (1) then allow the packets to pass, if false (0) then
61 * reject the packets
62 *
63 * o LIST
64 * This message can be sent either from an application or by the kernel in
65 * response to an application generated LIST message. When sent by an
66 * application there is no payload. The kernel should respond to a LIST
67 * message either with a LIST message on success or an ACK message on
68 * failure.
69 *
70 * +-----------------------+
71 * | accept flag (32 bits) |
72 * +-----------------------+
73 *
74 * accept flag: if true (1) then unlabeled packets are allowed to pass,
75 * if false (0) then unlabeled packets are rejected
76 *
77 */
78
79/* NetLabel Unlabeled commands */
80enum {
81 NLBL_UNLABEL_C_UNSPEC,
82 NLBL_UNLABEL_C_ACK,
83 NLBL_UNLABEL_C_ACCEPT,
84 NLBL_UNLABEL_C_LIST,
85 __NLBL_UNLABEL_C_MAX,
86};
87#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1)
88
89/* NetLabel protocol functions */
90int netlbl_unlabel_genl_init(void);
91
92/* Process Unlabeled incoming network packets */
93int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr);
94
95/* Set the default configuration to allow Unlabeled packets */
96int netlbl_unlabel_defconf(void);
97
98#endif
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
new file mode 100644
index 000000000000..80022221b0a7
--- /dev/null
+++ b/net/netlabel/netlabel_user.c
@@ -0,0 +1,158 @@
1/*
2 * NetLabel NETLINK Interface
3 *
4 * This file defines the NETLINK interface for the NetLabel system. The
5 * NetLabel system manages static and dynamic label mappings for network
6 * protocols such 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 <linux/list.h>
34#include <linux/socket.h>
35#include <net/sock.h>
36#include <net/netlink.h>
37#include <net/genetlink.h>
38#include <net/netlabel.h>
39#include <asm/bug.h>
40
41#include "netlabel_mgmt.h"
42#include "netlabel_unlabeled.h"
43#include "netlabel_cipso_v4.h"
44#include "netlabel_user.h"
45
46/*
47 * NetLabel NETLINK Setup Functions
48 */
49
50/**
51 * netlbl_netlink_init - Initialize the NETLINK communication channel
52 *
53 * Description:
54 * Call out to the NetLabel components so they can register their families and
55 * commands with the Generic NETLINK mechanism. Returns zero on success and
56 * non-zero on failure.
57 *
58 */
59int netlbl_netlink_init(void)
60{
61 int ret_val;
62
63 ret_val = netlbl_mgmt_genl_init();
64 if (ret_val != 0)
65 return ret_val;
66
67 ret_val = netlbl_cipsov4_genl_init();
68 if (ret_val != 0)
69 return ret_val;
70
71 ret_val = netlbl_unlabel_genl_init();
72 if (ret_val != 0)
73 return ret_val;
74
75 return 0;
76}
77
78/*
79 * NetLabel Common Protocol Functions
80 */
81
82/**
83 * netlbl_netlink_send_ack - Send an ACK message
84 * @info: the generic NETLINK information
85 * @genl_family: the generic NETLINK family ID value
86 * @ack_cmd: the generic NETLINK family ACK command value
87 * @ret_code: return code to use
88 *
89 * Description:
90 * This function sends an ACK message to the sender of the NETLINK message
91 * specified by @info.
92 *
93 */
94void netlbl_netlink_send_ack(const struct genl_info *info,
95 u32 genl_family,
96 u8 ack_cmd,
97 u32 ret_code)
98{
99 size_t data_size;
100 struct sk_buff *skb;
101
102 data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32;
103 skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL);
104 if (skb == NULL)
105 return;
106
107 if (netlbl_netlink_hdr_put(skb,
108 info->snd_pid,
109 0,
110 genl_family,
111 ack_cmd) == NULL)
112 goto send_ack_failure;
113
114 if (nla_put_u32(skb, NLA_U32, info->snd_seq) != 0)
115 goto send_ack_failure;
116 if (nla_put_u32(skb, NLA_U32, ret_code) != 0)
117 goto send_ack_failure;
118
119 netlbl_netlink_snd(skb, info->snd_pid);
120 return;
121
122send_ack_failure:
123 kfree_skb(skb);
124}
125
126/*
127 * NETLINK I/O Functions
128 */
129
130/**
131 * netlbl_netlink_snd - Send a NetLabel message
132 * @skb: NetLabel message
133 * @pid: destination PID
134 *
135 * Description:
136 * Sends a unicast NetLabel message over the NETLINK socket.
137 *
138 */
139int netlbl_netlink_snd(struct sk_buff *skb, u32 pid)
140{
141 return genlmsg_unicast(skb, pid);
142}
143
144/**
145 * netlbl_netlink_snd - Send a NetLabel message
146 * @skb: NetLabel message
147 * @pid: sending PID
148 * @group: multicast group id
149 *
150 * Description:
151 * Sends a multicast NetLabel message over the NETLINK socket to all members
152 * of @group except @pid.
153 *
154 */
155int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group)
156{
157 return genlmsg_multicast(skb, pid, group);
158}
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
new file mode 100644
index 000000000000..ccf237b3a128
--- /dev/null
+++ b/net/netlabel/netlabel_user.h
@@ -0,0 +1,214 @@
1/*
2 * NetLabel NETLINK Interface
3 *
4 * This file defines the NETLINK interface for the NetLabel system. The
5 * NetLabel system manages static and dynamic label mappings for network
6 * protocols such 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#ifndef _NETLABEL_USER_H
32#define _NETLABEL_USER_H
33
34#include <linux/skbuff.h>
35#include <linux/capability.h>
36#include <linux/genetlink.h>
37#include <net/netlabel.h>
38#include <net/genetlink.h>
39
40/* NetLabel NETLINK helper functions */
41
42/**
43 * netlbl_netlink_cap_check - Check the NETLINK msg capabilities
44 * @skb: the NETLINK buffer
45 * @req_cap: the required capability
46 *
47 * Description:
48 * Check the NETLINK buffer's capabilities against the required capabilities.
49 * Returns zero on success, negative values on failure.
50 *
51 */
52static inline int netlbl_netlink_cap_check(const struct sk_buff *skb,
53 kernel_cap_t req_cap)
54{
55 if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap))
56 return 0;
57 return -EPERM;
58}
59
60/**
61 * netlbl_getinc_u8 - Read a u8 value from a nlattr stream and move on
62 * @nla: the attribute
63 * @rem_len: remaining length
64 *
65 * Description:
66 * Return a u8 value pointed to by @nla and advance it to the next attribute.
67 *
68 */
69static inline u8 netlbl_getinc_u8(struct nlattr **nla, int *rem_len)
70{
71 u8 val = nla_get_u8(*nla);
72 *nla = nla_next(*nla, rem_len);
73 return val;
74}
75
76/**
77 * netlbl_getinc_u16 - Read a u16 value from a nlattr stream and move on
78 * @nla: the attribute
79 * @rem_len: remaining length
80 *
81 * Description:
82 * Return a u16 value pointed to by @nla and advance it to the next attribute.
83 *
84 */
85static inline u16 netlbl_getinc_u16(struct nlattr **nla, int *rem_len)
86{
87 u16 val = nla_get_u16(*nla);
88 *nla = nla_next(*nla, rem_len);
89 return val;
90}
91
92/**
93 * netlbl_getinc_u32 - Read a u32 value from a nlattr stream and move on
94 * @nla: the attribute
95 * @rem_len: remaining length
96 *
97 * Description:
98 * Return a u32 value pointed to by @nla and advance it to the next attribute.
99 *
100 */
101static inline u32 netlbl_getinc_u32(struct nlattr **nla, int *rem_len)
102{
103 u32 val = nla_get_u32(*nla);
104 *nla = nla_next(*nla, rem_len);
105 return val;
106}
107
108/**
109 * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff
110 * @skb: the packet
111 * @pid: the PID of the receipient
112 * @seq: the sequence number
113 * @type: the generic NETLINK message family type
114 * @cmd: command
115 *
116 * Description:
117 * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
118 * struct to the packet. Returns a pointer to the start of the payload buffer
119 * on success or NULL on failure.
120 *
121 */
122static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb,
123 u32 pid,
124 u32 seq,
125 int type,
126 u8 cmd)
127{
128 return genlmsg_put(skb,
129 pid,
130 seq,
131 type,
132 0,
133 0,
134 cmd,
135 NETLBL_PROTO_VERSION);
136}
137
138/**
139 * netlbl_netlink_hdr_push - Write the NETLINK buffers into a sk_buff
140 * @skb: the packet
141 * @pid: the PID of the receipient
142 * @seq: the sequence number
143 * @type: the generic NETLINK message family type
144 * @cmd: command
145 *
146 * Description:
147 * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
148 * struct to the packet.
149 *
150 */
151static inline void netlbl_netlink_hdr_push(struct sk_buff *skb,
152 u32 pid,
153 u32 seq,
154 int type,
155 u8 cmd)
156
157{
158 struct nlmsghdr *nlh;
159 struct genlmsghdr *hdr;
160
161 nlh = (struct nlmsghdr *)skb_push(skb, NLMSG_SPACE(GENL_HDRLEN));
162 nlh->nlmsg_type = type;
163 nlh->nlmsg_len = skb->len;
164 nlh->nlmsg_flags = 0;
165 nlh->nlmsg_pid = pid;
166 nlh->nlmsg_seq = seq;
167
168 hdr = nlmsg_data(nlh);
169 hdr->cmd = cmd;
170 hdr->version = NETLBL_PROTO_VERSION;
171 hdr->reserved = 0;
172}
173
174/**
175 * netlbl_netlink_payload_len - Return the length of the payload
176 * @skb: the NETLINK buffer
177 *
178 * Description:
179 * This function returns the length of the NetLabel payload.
180 *
181 */
182static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb)
183{
184 return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN;
185}
186
187/**
188 * netlbl_netlink_payload_data - Returns a pointer to the start of the payload
189 * @skb: the NETLINK buffer
190 *
191 * Description:
192 * This function returns a pointer to the start of the NetLabel payload.
193 *
194 */
195static inline void *netlbl_netlink_payload_data(const struct sk_buff *skb)
196{
197 return (unsigned char *)nlmsg_data((struct nlmsghdr *)skb->data) +
198 GENL_HDRLEN;
199}
200
201/* NetLabel common protocol functions */
202
203void netlbl_netlink_send_ack(const struct genl_info *info,
204 u32 genl_family,
205 u8 ack_cmd,
206 u32 ret_code);
207
208/* NetLabel NETLINK I/O functions */
209
210int netlbl_netlink_init(void);
211int netlbl_netlink_snd(struct sk_buff *skb, u32 pid);
212int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group);
213
214#endif