[GENL]: Add genlmsg_put_reply() to simplify building reply headers
[powerpc.git] / net / netlabel / netlabel_unlabeled.c
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 = NLBL_UNLABEL_A_MAX,
59 };
60
61 /* NetLabel Netlink attribute policy */
62 static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
63         [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
64 };
65
66 /*
67  * Helper Functions
68  */
69
70 /**
71  * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
72  * @value: desired value
73  * @audit_info: NetLabel audit information
74  *
75  * Description:
76  * Set the value of the unlabeled accept flag to @value.
77  *
78  */
79 static void netlbl_unlabel_acceptflg_set(u8 value,
80                                          struct netlbl_audit *audit_info)
81 {
82         struct audit_buffer *audit_buf;
83         u8 old_val;
84
85         old_val = atomic_read(&netlabel_unlabel_accept_flg);
86         atomic_set(&netlabel_unlabel_accept_flg, value);
87
88         audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
89                                               audit_info);
90         audit_log_format(audit_buf, " unlbl_accept=%u old=%u", value, old_val);
91         audit_log_end(audit_buf);
92 }
93
94 /*
95  * NetLabel Command Handlers
96  */
97
98 /**
99  * netlbl_unlabel_accept - Handle an ACCEPT message
100  * @skb: the NETLINK buffer
101  * @info: the Generic NETLINK info block
102  *
103  * Description:
104  * Process a user generated ACCEPT message and set the accept flag accordingly.
105  * Returns zero on success, negative values on failure.
106  *
107  */
108 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
109 {
110         u8 value;
111         struct netlbl_audit audit_info;
112
113         if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
114                 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
115                 if (value == 1 || value == 0) {
116                         netlbl_netlink_auditinfo(skb, &audit_info);
117                         netlbl_unlabel_acceptflg_set(value, &audit_info);
118                         return 0;
119                 }
120         }
121
122         return -EINVAL;
123 }
124
125 /**
126  * netlbl_unlabel_list - Handle a LIST message
127  * @skb: the NETLINK buffer
128  * @info: the Generic NETLINK info block
129  *
130  * Description:
131  * Process a user generated LIST message and respond with the current status.
132  * Returns zero on success, negative values on failure.
133  *
134  */
135 static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
136 {
137         int ret_val = -EINVAL;
138         struct sk_buff *ans_skb;
139         void *data;
140
141         ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
142         if (ans_skb == NULL)
143                 goto list_failure;
144         data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
145                                  0, NLBL_UNLABEL_C_LIST);
146         if (data == NULL) {
147                 ret_val = -ENOMEM;
148                 goto list_failure;
149         }
150
151         ret_val = nla_put_u8(ans_skb,
152                              NLBL_UNLABEL_A_ACPTFLG,
153                              atomic_read(&netlabel_unlabel_accept_flg));
154         if (ret_val != 0)
155                 goto list_failure;
156
157         genlmsg_end(ans_skb, data);
158
159         ret_val = genlmsg_reply(ans_skb, info);
160         if (ret_val != 0)
161                 goto list_failure;
162         return 0;
163
164 list_failure:
165         kfree(ans_skb);
166         return ret_val;
167 }
168
169
170 /*
171  * NetLabel Generic NETLINK Command Definitions
172  */
173
174 static struct genl_ops netlbl_unlabel_genl_c_accept = {
175         .cmd = NLBL_UNLABEL_C_ACCEPT,
176         .flags = GENL_ADMIN_PERM,
177         .policy = netlbl_unlabel_genl_policy,
178         .doit = netlbl_unlabel_accept,
179         .dumpit = NULL,
180 };
181
182 static struct genl_ops netlbl_unlabel_genl_c_list = {
183         .cmd = NLBL_UNLABEL_C_LIST,
184         .flags = 0,
185         .policy = netlbl_unlabel_genl_policy,
186         .doit = netlbl_unlabel_list,
187         .dumpit = NULL,
188 };
189
190
191 /*
192  * NetLabel Generic NETLINK Protocol Functions
193  */
194
195 /**
196  * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
197  *
198  * Description:
199  * Register the unlabeled packet NetLabel component with the Generic NETLINK
200  * mechanism.  Returns zero on success, negative values on failure.
201  *
202  */
203 int netlbl_unlabel_genl_init(void)
204 {
205         int ret_val;
206
207         ret_val = genl_register_family(&netlbl_unlabel_gnl_family);
208         if (ret_val != 0)
209                 return ret_val;
210
211         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
212                                     &netlbl_unlabel_genl_c_accept);
213         if (ret_val != 0)
214                 return ret_val;
215
216         ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
217                                     &netlbl_unlabel_genl_c_list);
218         if (ret_val != 0)
219                 return ret_val;
220
221         return 0;
222 }
223
224 /*
225  * NetLabel KAPI Hooks
226  */
227
228 /**
229  * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
230  * @secattr: the security attributes
231  *
232  * Description:
233  * Determine the security attributes, if any, for an unlabled packet and return
234  * them in @secattr.  Returns zero on success and negative values on failure.
235  *
236  */
237 int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr)
238 {
239         if (atomic_read(&netlabel_unlabel_accept_flg) == 1)
240                 return netlbl_secattr_init(secattr);
241
242         return -ENOMSG;
243 }
244
245 /**
246  * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
247  *
248  * Description:
249  * Set the default NetLabel configuration to allow incoming unlabeled packets
250  * and to send unlabeled network traffic by default.
251  *
252  */
253 int netlbl_unlabel_defconf(void)
254 {
255         int ret_val;
256         struct netlbl_dom_map *entry;
257         struct netlbl_audit audit_info;
258
259         /* Only the kernel is allowed to call this function and the only time
260          * it is called is at bootup before the audit subsystem is reporting
261          * messages so don't worry to much about these values. */
262         security_task_getsecid(current, &audit_info.secid);
263         audit_info.loginuid = 0;
264
265         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
266         if (entry == NULL)
267                 return -ENOMEM;
268         entry->type = NETLBL_NLTYPE_UNLABELED;
269         ret_val = netlbl_domhsh_add_default(entry, &audit_info);
270         if (ret_val != 0)
271                 return ret_val;
272
273         netlbl_unlabel_acceptflg_set(1, &audit_info);
274
275         return 0;
276 }