]>
Commit | Line | Data |
---|---|---|
96cb8e33 PM |
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 | #include <linux/types.h> | |
32 | #include <linux/rcupdate.h> | |
33 | #include <linux/list.h> | |
34 | #include <linux/spinlock.h> | |
35 | #include <linux/socket.h> | |
36 | #include <linux/string.h> | |
37 | #include <linux/skbuff.h> | |
38 | #include <net/sock.h> | |
39 | #include <net/netlink.h> | |
40 | #include <net/genetlink.h> | |
41 | ||
42 | #include <net/netlabel.h> | |
43 | #include <asm/bug.h> | |
44 | ||
45 | #include "netlabel_user.h" | |
46 | #include "netlabel_domainhash.h" | |
47 | #include "netlabel_unlabeled.h" | |
48 | ||
49 | /* Accept unlabeled packets flag */ | |
50 | static atomic_t netlabel_unlabel_accept_flg = ATOMIC_INIT(0); | |
51 | ||
52 | /* NetLabel Generic NETLINK CIPSOv4 family */ | |
53 | static struct genl_family netlbl_unlabel_gnl_family = { | |
54 | .id = GENL_ID_GENERATE, | |
55 | .hdrsize = 0, | |
56 | .name = NETLBL_NLTYPE_UNLABELED_NAME, | |
57 | .version = NETLBL_PROTO_VERSION, | |
58 | .maxattr = 0, | |
59 | }; | |
60 | ||
61 | ||
62 | /* | |
63 | * NetLabel Command Handlers | |
64 | */ | |
65 | ||
66 | /** | |
67 | * netlbl_unlabel_accept - Handle an ACCEPT message | |
68 | * @skb: the NETLINK buffer | |
69 | * @info: the Generic NETLINK info block | |
70 | * | |
71 | * Description: | |
72 | * Process a user generated ACCEPT message and set the accept flag accordingly. | |
73 | * Returns zero on success, negative values on failure. | |
74 | * | |
75 | */ | |
76 | static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) | |
77 | { | |
78 | int ret_val; | |
79 | struct nlattr *data = netlbl_netlink_payload_data(skb); | |
80 | u32 value; | |
81 | ||
82 | ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); | |
83 | if (ret_val != 0) | |
84 | return ret_val; | |
85 | ||
86 | if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) { | |
87 | value = nla_get_u32(data); | |
88 | if (value == 1 || value == 0) { | |
89 | atomic_set(&netlabel_unlabel_accept_flg, value); | |
90 | netlbl_netlink_send_ack(info, | |
91 | netlbl_unlabel_gnl_family.id, | |
92 | NLBL_UNLABEL_C_ACK, | |
93 | NETLBL_E_OK); | |
94 | return 0; | |
95 | } | |
96 | } | |
97 | ||
98 | netlbl_netlink_send_ack(info, | |
99 | netlbl_unlabel_gnl_family.id, | |
100 | NLBL_UNLABEL_C_ACK, | |
101 | EINVAL); | |
102 | return -EINVAL; | |
103 | } | |
104 | ||
105 | /** | |
106 | * netlbl_unlabel_list - Handle a LIST message | |
107 | * @skb: the NETLINK buffer | |
108 | * @info: the Generic NETLINK info block | |
109 | * | |
110 | * Description: | |
111 | * Process a user generated LIST message and respond with the current status. | |
112 | * Returns zero on success, negative values on failure. | |
113 | * | |
114 | */ | |
115 | static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) | |
116 | { | |
117 | int ret_val = -ENOMEM; | |
118 | struct sk_buff *ans_skb; | |
119 | ||
120 | ans_skb = netlbl_netlink_alloc_skb(0, | |
121 | GENL_HDRLEN + NETLBL_LEN_U32, | |
122 | GFP_KERNEL); | |
123 | if (ans_skb == NULL) | |
124 | goto list_failure; | |
125 | ||
126 | if (netlbl_netlink_hdr_put(ans_skb, | |
127 | info->snd_pid, | |
128 | 0, | |
129 | netlbl_unlabel_gnl_family.id, | |
130 | NLBL_UNLABEL_C_LIST) == NULL) | |
131 | goto list_failure; | |
132 | ||
133 | ret_val = nla_put_u32(ans_skb, | |
134 | NLA_U32, | |
135 | atomic_read(&netlabel_unlabel_accept_flg)); | |
136 | if (ret_val != 0) | |
137 | goto list_failure; | |
138 | ||
139 | ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); | |
140 | if (ret_val != 0) | |
141 | goto list_failure; | |
142 | ||
143 | return 0; | |
144 | ||
145 | list_failure: | |
146 | netlbl_netlink_send_ack(info, | |
147 | netlbl_unlabel_gnl_family.id, | |
148 | NLBL_UNLABEL_C_ACK, | |
149 | -ret_val); | |
150 | return ret_val; | |
151 | } | |
152 | ||
153 | ||
154 | /* | |
155 | * NetLabel Generic NETLINK Command Definitions | |
156 | */ | |
157 | ||
158 | static struct genl_ops netlbl_unlabel_genl_c_accept = { | |
159 | .cmd = NLBL_UNLABEL_C_ACCEPT, | |
160 | .flags = 0, | |
161 | .doit = netlbl_unlabel_accept, | |
162 | .dumpit = NULL, | |
163 | }; | |
164 | ||
165 | static struct genl_ops netlbl_unlabel_genl_c_list = { | |
166 | .cmd = NLBL_UNLABEL_C_LIST, | |
167 | .flags = 0, | |
168 | .doit = netlbl_unlabel_list, | |
169 | .dumpit = NULL, | |
170 | }; | |
171 | ||
172 | ||
173 | /* | |
174 | * NetLabel Generic NETLINK Protocol Functions | |
175 | */ | |
176 | ||
177 | /** | |
178 | * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component | |
179 | * | |
180 | * Description: | |
181 | * Register the unlabeled packet NetLabel component with the Generic NETLINK | |
182 | * mechanism. Returns zero on success, negative values on failure. | |
183 | * | |
184 | */ | |
185 | int netlbl_unlabel_genl_init(void) | |
186 | { | |
187 | int ret_val; | |
188 | ||
189 | ret_val = genl_register_family(&netlbl_unlabel_gnl_family); | |
190 | if (ret_val != 0) | |
191 | return ret_val; | |
192 | ||
193 | ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, | |
194 | &netlbl_unlabel_genl_c_accept); | |
195 | if (ret_val != 0) | |
196 | return ret_val; | |
197 | ||
198 | ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, | |
199 | &netlbl_unlabel_genl_c_list); | |
200 | if (ret_val != 0) | |
201 | return ret_val; | |
202 | ||
203 | return 0; | |
204 | } | |
205 | ||
206 | /* | |
207 | * NetLabel KAPI Hooks | |
208 | */ | |
209 | ||
210 | /** | |
211 | * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet | |
212 | * @secattr: the security attributes | |
213 | * | |
214 | * Description: | |
215 | * Determine the security attributes, if any, for an unlabled packet and return | |
216 | * them in @secattr. Returns zero on success and negative values on failure. | |
217 | * | |
218 | */ | |
219 | int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) | |
220 | { | |
221 | if (atomic_read(&netlabel_unlabel_accept_flg) == 1) { | |
222 | memset(secattr, 0, sizeof(*secattr)); | |
223 | return 0; | |
224 | } | |
225 | ||
226 | return -ENOMSG; | |
227 | } | |
228 | ||
229 | /** | |
230 | * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets | |
231 | * | |
232 | * Description: | |
233 | * Set the default NetLabel configuration to allow incoming unlabeled packets | |
234 | * and to send unlabeled network traffic by default. | |
235 | * | |
236 | */ | |
237 | int netlbl_unlabel_defconf(void) | |
238 | { | |
239 | int ret_val; | |
240 | struct netlbl_dom_map *entry; | |
241 | ||
242 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | |
243 | if (entry == NULL) | |
244 | return -ENOMEM; | |
245 | entry->type = NETLBL_NLTYPE_UNLABELED; | |
246 | ret_val = netlbl_domhsh_add_default(entry); | |
247 | if (ret_val != 0) | |
248 | return ret_val; | |
249 | ||
250 | atomic_set(&netlabel_unlabel_accept_flg, 1); | |
251 | ||
252 | return 0; | |
253 | } |