| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 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> | 
| Paul Moore | de64688 | 2006-11-17 17:38:55 -0500 | [diff] [blame] | 38 | #include <linux/audit.h> | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 39 | #include <net/sock.h> | 
 | 40 | #include <net/netlink.h> | 
 | 41 | #include <net/genetlink.h> | 
 | 42 |  | 
 | 43 | #include <net/netlabel.h> | 
 | 44 | #include <asm/bug.h> | 
 | 45 |  | 
 | 46 | #include "netlabel_user.h" | 
 | 47 | #include "netlabel_domainhash.h" | 
 | 48 | #include "netlabel_unlabeled.h" | 
 | 49 |  | 
 | 50 | /* Accept unlabeled packets flag */ | 
| Paul Moore | cd28786 | 2006-11-17 17:38:44 -0500 | [diff] [blame] | 51 | static DEFINE_SPINLOCK(netlabel_unlabel_acceptflg_lock); | 
 | 52 | static u8 netlabel_unlabel_acceptflg = 0; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 53 |  | 
 | 54 | /* NetLabel Generic NETLINK CIPSOv4 family */ | 
 | 55 | static struct genl_family netlbl_unlabel_gnl_family = { | 
 | 56 | 	.id = GENL_ID_GENERATE, | 
 | 57 | 	.hdrsize = 0, | 
 | 58 | 	.name = NETLBL_NLTYPE_UNLABELED_NAME, | 
 | 59 | 	.version = NETLBL_PROTO_VERSION, | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 60 | 	.maxattr = NLBL_UNLABEL_A_MAX, | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 61 | }; | 
 | 62 |  | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 63 | /* NetLabel Netlink attribute policy */ | 
| Patrick McHardy | ef7c79e | 2007-06-05 12:38:30 -0700 | [diff] [blame] | 64 | static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = { | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 65 | 	[NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 }, | 
 | 66 | }; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 67 |  | 
 | 68 | /* | 
| Paul Moore | 32f50cd | 2006-09-28 14:51:47 -0700 | [diff] [blame] | 69 |  * Helper Functions | 
 | 70 |  */ | 
 | 71 |  | 
 | 72 | /** | 
 | 73 |  * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag | 
 | 74 |  * @value: desired value | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 75 |  * @audit_info: NetLabel audit information | 
| Paul Moore | 32f50cd | 2006-09-28 14:51:47 -0700 | [diff] [blame] | 76 |  * | 
 | 77 |  * Description: | 
 | 78 |  * Set the value of the unlabeled accept flag to @value. | 
 | 79 |  * | 
 | 80 |  */ | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 81 | static void netlbl_unlabel_acceptflg_set(u8 value, | 
 | 82 | 					 struct netlbl_audit *audit_info) | 
| Paul Moore | 32f50cd | 2006-09-28 14:51:47 -0700 | [diff] [blame] | 83 | { | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 84 | 	struct audit_buffer *audit_buf; | 
 | 85 | 	u8 old_val; | 
 | 86 |  | 
| Paul Moore | cd28786 | 2006-11-17 17:38:44 -0500 | [diff] [blame] | 87 | 	rcu_read_lock(); | 
 | 88 | 	old_val = netlabel_unlabel_acceptflg; | 
 | 89 | 	spin_lock(&netlabel_unlabel_acceptflg_lock); | 
 | 90 | 	netlabel_unlabel_acceptflg = value; | 
 | 91 | 	spin_unlock(&netlabel_unlabel_acceptflg_lock); | 
 | 92 | 	rcu_read_unlock(); | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 93 |  | 
 | 94 | 	audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, | 
 | 95 | 					      audit_info); | 
| Paul Moore | de64688 | 2006-11-17 17:38:55 -0500 | [diff] [blame] | 96 | 	if (audit_buf != NULL) { | 
 | 97 | 		audit_log_format(audit_buf, | 
 | 98 | 				 " unlbl_accept=%u old=%u", value, old_val); | 
 | 99 | 		audit_log_end(audit_buf); | 
 | 100 | 	} | 
| Paul Moore | 32f50cd | 2006-09-28 14:51:47 -0700 | [diff] [blame] | 101 | } | 
 | 102 |  | 
 | 103 | /* | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 104 |  * NetLabel Command Handlers | 
 | 105 |  */ | 
 | 106 |  | 
 | 107 | /** | 
 | 108 |  * netlbl_unlabel_accept - Handle an ACCEPT message | 
 | 109 |  * @skb: the NETLINK buffer | 
 | 110 |  * @info: the Generic NETLINK info block | 
 | 111 |  * | 
 | 112 |  * Description: | 
 | 113 |  * Process a user generated ACCEPT message and set the accept flag accordingly. | 
 | 114 |  * Returns zero on success, negative values on failure. | 
 | 115 |  * | 
 | 116 |  */ | 
 | 117 | static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) | 
 | 118 | { | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 119 | 	u8 value; | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 120 | 	struct netlbl_audit audit_info; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 121 |  | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 122 | 	if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) { | 
 | 123 | 		value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]); | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 124 | 		if (value == 1 || value == 0) { | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 125 | 			netlbl_netlink_auditinfo(skb, &audit_info); | 
 | 126 | 			netlbl_unlabel_acceptflg_set(value, &audit_info); | 
| Paul Moore | 32f50cd | 2006-09-28 14:51:47 -0700 | [diff] [blame] | 127 | 			return 0; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 128 | 		} | 
 | 129 | 	} | 
 | 130 |  | 
| Paul Moore | 32f50cd | 2006-09-28 14:51:47 -0700 | [diff] [blame] | 131 | 	return -EINVAL; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 132 | } | 
 | 133 |  | 
 | 134 | /** | 
 | 135 |  * netlbl_unlabel_list - Handle a LIST message | 
 | 136 |  * @skb: the NETLINK buffer | 
 | 137 |  * @info: the Generic NETLINK info block | 
 | 138 |  * | 
 | 139 |  * Description: | 
 | 140 |  * Process a user generated LIST message and respond with the current status. | 
 | 141 |  * Returns zero on success, negative values on failure. | 
 | 142 |  * | 
 | 143 |  */ | 
 | 144 | static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) | 
 | 145 | { | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 146 | 	int ret_val = -EINVAL; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 147 | 	struct sk_buff *ans_skb; | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 148 | 	void *data; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 149 |  | 
| Thomas Graf | 339bf98 | 2006-11-10 14:10:15 -0800 | [diff] [blame] | 150 | 	ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 151 | 	if (ans_skb == NULL) | 
 | 152 | 		goto list_failure; | 
| Thomas Graf | 17c157c | 2006-11-14 19:46:02 -0800 | [diff] [blame] | 153 | 	data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family, | 
 | 154 | 				 0, NLBL_UNLABEL_C_LIST); | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 155 | 	if (data == NULL) { | 
 | 156 | 		ret_val = -ENOMEM; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 157 | 		goto list_failure; | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 158 | 	} | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 159 |  | 
| Paul Moore | cd28786 | 2006-11-17 17:38:44 -0500 | [diff] [blame] | 160 | 	rcu_read_lock(); | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 161 | 	ret_val = nla_put_u8(ans_skb, | 
 | 162 | 			     NLBL_UNLABEL_A_ACPTFLG, | 
| Paul Moore | cd28786 | 2006-11-17 17:38:44 -0500 | [diff] [blame] | 163 | 			     netlabel_unlabel_acceptflg); | 
 | 164 | 	rcu_read_unlock(); | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 165 | 	if (ret_val != 0) | 
 | 166 | 		goto list_failure; | 
 | 167 |  | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 168 | 	genlmsg_end(ans_skb, data); | 
 | 169 |  | 
| Thomas Graf | 81878d2 | 2006-11-14 19:45:27 -0800 | [diff] [blame] | 170 | 	ret_val = genlmsg_reply(ans_skb, info); | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 171 | 	if (ret_val != 0) | 
 | 172 | 		goto list_failure; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 173 | 	return 0; | 
 | 174 |  | 
 | 175 | list_failure: | 
| Patrick McHardy | b08d584 | 2007-02-27 09:57:37 -0800 | [diff] [blame] | 176 | 	kfree_skb(ans_skb); | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 177 | 	return ret_val; | 
 | 178 | } | 
 | 179 |  | 
 | 180 |  | 
 | 181 | /* | 
 | 182 |  * NetLabel Generic NETLINK Command Definitions | 
 | 183 |  */ | 
 | 184 |  | 
 | 185 | static struct genl_ops netlbl_unlabel_genl_c_accept = { | 
 | 186 | 	.cmd = NLBL_UNLABEL_C_ACCEPT, | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 187 | 	.flags = GENL_ADMIN_PERM, | 
 | 188 | 	.policy = netlbl_unlabel_genl_policy, | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 189 | 	.doit = netlbl_unlabel_accept, | 
 | 190 | 	.dumpit = NULL, | 
 | 191 | }; | 
 | 192 |  | 
 | 193 | static struct genl_ops netlbl_unlabel_genl_c_list = { | 
 | 194 | 	.cmd = NLBL_UNLABEL_C_LIST, | 
 | 195 | 	.flags = 0, | 
| Paul Moore | fd38585 | 2006-09-25 15:56:37 -0700 | [diff] [blame] | 196 | 	.policy = netlbl_unlabel_genl_policy, | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 197 | 	.doit = netlbl_unlabel_list, | 
 | 198 | 	.dumpit = NULL, | 
 | 199 | }; | 
 | 200 |  | 
 | 201 |  | 
 | 202 | /* | 
 | 203 |  * NetLabel Generic NETLINK Protocol Functions | 
 | 204 |  */ | 
 | 205 |  | 
 | 206 | /** | 
 | 207 |  * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component | 
 | 208 |  * | 
 | 209 |  * Description: | 
 | 210 |  * Register the unlabeled packet NetLabel component with the Generic NETLINK | 
 | 211 |  * mechanism.  Returns zero on success, negative values on failure. | 
 | 212 |  * | 
 | 213 |  */ | 
 | 214 | int netlbl_unlabel_genl_init(void) | 
 | 215 | { | 
 | 216 | 	int ret_val; | 
 | 217 |  | 
 | 218 | 	ret_val = genl_register_family(&netlbl_unlabel_gnl_family); | 
 | 219 | 	if (ret_val != 0) | 
 | 220 | 		return ret_val; | 
 | 221 |  | 
 | 222 | 	ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, | 
 | 223 | 				    &netlbl_unlabel_genl_c_accept); | 
 | 224 | 	if (ret_val != 0) | 
 | 225 | 		return ret_val; | 
 | 226 |  | 
 | 227 | 	ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, | 
 | 228 | 				    &netlbl_unlabel_genl_c_list); | 
 | 229 | 	if (ret_val != 0) | 
 | 230 | 		return ret_val; | 
 | 231 |  | 
 | 232 | 	return 0; | 
 | 233 | } | 
 | 234 |  | 
 | 235 | /* | 
 | 236 |  * NetLabel KAPI Hooks | 
 | 237 |  */ | 
 | 238 |  | 
 | 239 | /** | 
 | 240 |  * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet | 
 | 241 |  * @secattr: the security attributes | 
 | 242 |  * | 
 | 243 |  * Description: | 
 | 244 |  * Determine the security attributes, if any, for an unlabled packet and return | 
 | 245 |  * them in @secattr.  Returns zero on success and negative values on failure. | 
 | 246 |  * | 
 | 247 |  */ | 
 | 248 | int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) | 
 | 249 | { | 
| Paul Moore | cd28786 | 2006-11-17 17:38:44 -0500 | [diff] [blame] | 250 | 	int ret_val; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 251 |  | 
| Paul Moore | cd28786 | 2006-11-17 17:38:44 -0500 | [diff] [blame] | 252 | 	rcu_read_lock(); | 
 | 253 | 	if (netlabel_unlabel_acceptflg == 1) { | 
 | 254 | 		netlbl_secattr_init(secattr); | 
 | 255 | 		ret_val = 0; | 
 | 256 | 	} else | 
 | 257 | 		ret_val = -ENOMSG; | 
 | 258 | 	rcu_read_unlock(); | 
 | 259 |  | 
 | 260 | 	return ret_val; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 261 | } | 
 | 262 |  | 
 | 263 | /** | 
 | 264 |  * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets | 
 | 265 |  * | 
 | 266 |  * Description: | 
 | 267 |  * Set the default NetLabel configuration to allow incoming unlabeled packets | 
 | 268 |  * and to send unlabeled network traffic by default. | 
 | 269 |  * | 
 | 270 |  */ | 
 | 271 | int netlbl_unlabel_defconf(void) | 
 | 272 | { | 
 | 273 | 	int ret_val; | 
 | 274 | 	struct netlbl_dom_map *entry; | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 275 | 	struct netlbl_audit audit_info; | 
| Paul Moore | 32f50cd | 2006-09-28 14:51:47 -0700 | [diff] [blame] | 276 |  | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 277 | 	/* Only the kernel is allowed to call this function and the only time | 
 | 278 | 	 * it is called is at bootup before the audit subsystem is reporting | 
 | 279 | 	 * messages so don't worry to much about these values. */ | 
 | 280 | 	security_task_getsecid(current, &audit_info.secid); | 
 | 281 | 	audit_info.loginuid = 0; | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 282 |  | 
 | 283 | 	entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 
 | 284 | 	if (entry == NULL) | 
 | 285 | 		return -ENOMEM; | 
 | 286 | 	entry->type = NETLBL_NLTYPE_UNLABELED; | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 287 | 	ret_val = netlbl_domhsh_add_default(entry, &audit_info); | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 288 | 	if (ret_val != 0) | 
 | 289 | 		return ret_val; | 
 | 290 |  | 
| Paul Moore | 95d4e6b | 2006-09-29 17:05:05 -0700 | [diff] [blame] | 291 | 	netlbl_unlabel_acceptflg_set(1, &audit_info); | 
| Paul Moore | 96cb8e3 | 2006-08-03 16:48:59 -0700 | [diff] [blame] | 292 |  | 
 | 293 | 	return 0; | 
 | 294 | } |