xfrm_user.c 69.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/* xfrm_user.c: User interface to configure xfrm engine.
 *
 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
 *
 * Changes:
 *	Mitsuru KANDA @USAGI
 * 	Kazunori MIYAZAWA @USAGI
 * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
 * 		IPv6 support
10
 *
L
Linus Torvalds 已提交
11 12
 */

13
#include <linux/crypto.h>
L
Linus Torvalds 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/string.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
#include <linux/init.h>
#include <linux/security.h>
#include <net/sock.h>
#include <net/xfrm.h>
28
#include <net/netlink.h>
29
#include <net/ah.h>
L
Linus Torvalds 已提交
30
#include <asm/uaccess.h>
E
Eric Dumazet 已提交
31
#if IS_ENABLED(CONFIG_IPV6)
32 33
#include <linux/in6.h>
#endif
L
Linus Torvalds 已提交
34

35 36 37 38 39
static inline int aead_len(struct xfrm_algo_aead *alg)
{
	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
}

40
static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
L
Linus Torvalds 已提交
41
{
42
	struct nlattr *rt = attrs[type];
L
Linus Torvalds 已提交
43 44 45 46 47
	struct xfrm_algo *algp;

	if (!rt)
		return 0;

48
	algp = nla_data(rt);
49
	if (nla_len(rt) < xfrm_alg_len(algp))
50 51
		return -EINVAL;

L
Linus Torvalds 已提交
52 53 54 55 56 57 58 59
	switch (type) {
	case XFRMA_ALG_AUTH:
	case XFRMA_ALG_CRYPT:
	case XFRMA_ALG_COMP:
		break;

	default:
		return -EINVAL;
60
	}
L
Linus Torvalds 已提交
61 62 63 64 65

	algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0';
	return 0;
}

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
static int verify_auth_trunc(struct nlattr **attrs)
{
	struct nlattr *rt = attrs[XFRMA_ALG_AUTH_TRUNC];
	struct xfrm_algo_auth *algp;

	if (!rt)
		return 0;

	algp = nla_data(rt);
	if (nla_len(rt) < xfrm_alg_auth_len(algp))
		return -EINVAL;

	algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0';
	return 0;
}

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
static int verify_aead(struct nlattr **attrs)
{
	struct nlattr *rt = attrs[XFRMA_ALG_AEAD];
	struct xfrm_algo_aead *algp;

	if (!rt)
		return 0;

	algp = nla_data(rt);
	if (nla_len(rt) < aead_len(algp))
		return -EINVAL;

	algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0';
	return 0;
}

98
static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type,
99 100
			   xfrm_address_t **addrp)
{
101
	struct nlattr *rt = attrs[type];
102

103
	if (rt && addrp)
104
		*addrp = nla_data(rt);
105
}
106

107
static inline int verify_sec_ctx_len(struct nlattr **attrs)
108
{
109
	struct nlattr *rt = attrs[XFRMA_SEC_CTX];
110 111 112 113 114
	struct xfrm_user_sec_ctx *uctx;

	if (!rt)
		return 0;

115
	uctx = nla_data(rt);
116
	if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
117 118 119 120 121
		return -EINVAL;

	return 0;
}

122 123 124 125 126
static inline int verify_replay(struct xfrm_usersa_info *p,
				struct nlattr **attrs)
{
	struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];

127 128 129
	if ((p->flags & XFRM_STATE_ESN) && !rt)
		return -EINVAL;

130 131 132
	if (!rt)
		return 0;

133 134 135
	if (p->id.proto != IPPROTO_ESP)
		return -EINVAL;

136 137 138 139 140
	if (p->replay_window != 0)
		return -EINVAL;

	return 0;
}
141

L
Linus Torvalds 已提交
142
static int verify_newsa_info(struct xfrm_usersa_info *p,
143
			     struct nlattr **attrs)
L
Linus Torvalds 已提交
144 145 146 147 148 149 150 151 152
{
	int err;

	err = -EINVAL;
	switch (p->family) {
	case AF_INET:
		break;

	case AF_INET6:
E
Eric Dumazet 已提交
153
#if IS_ENABLED(CONFIG_IPV6)
L
Linus Torvalds 已提交
154 155 156 157 158 159 160 161
		break;
#else
		err = -EAFNOSUPPORT;
		goto out;
#endif

	default:
		goto out;
162
	}
L
Linus Torvalds 已提交
163 164 165 166

	err = -EINVAL;
	switch (p->id.proto) {
	case IPPROTO_AH:
167 168
		if ((!attrs[XFRMA_ALG_AUTH]	&&
		     !attrs[XFRMA_ALG_AUTH_TRUNC]) ||
169
		    attrs[XFRMA_ALG_AEAD]	||
170
		    attrs[XFRMA_ALG_CRYPT]	||
171 172
		    attrs[XFRMA_ALG_COMP]	||
		    attrs[XFRMA_TFCPAD])
L
Linus Torvalds 已提交
173 174 175 176
			goto out;
		break;

	case IPPROTO_ESP:
177 178 179
		if (attrs[XFRMA_ALG_COMP])
			goto out;
		if (!attrs[XFRMA_ALG_AUTH] &&
180
		    !attrs[XFRMA_ALG_AUTH_TRUNC] &&
181 182 183 184
		    !attrs[XFRMA_ALG_CRYPT] &&
		    !attrs[XFRMA_ALG_AEAD])
			goto out;
		if ((attrs[XFRMA_ALG_AUTH] ||
185
		     attrs[XFRMA_ALG_AUTH_TRUNC] ||
186 187
		     attrs[XFRMA_ALG_CRYPT]) &&
		    attrs[XFRMA_ALG_AEAD])
L
Linus Torvalds 已提交
188
			goto out;
189 190 191
		if (attrs[XFRMA_TFCPAD] &&
		    p->mode != XFRM_MODE_TUNNEL)
			goto out;
L
Linus Torvalds 已提交
192 193 194
		break;

	case IPPROTO_COMP:
195
		if (!attrs[XFRMA_ALG_COMP]	||
196
		    attrs[XFRMA_ALG_AEAD]	||
197
		    attrs[XFRMA_ALG_AUTH]	||
198
		    attrs[XFRMA_ALG_AUTH_TRUNC]	||
199 200
		    attrs[XFRMA_ALG_CRYPT]	||
		    attrs[XFRMA_TFCPAD])
L
Linus Torvalds 已提交
201 202 203
			goto out;
		break;

E
Eric Dumazet 已提交
204
#if IS_ENABLED(CONFIG_IPV6)
205 206
	case IPPROTO_DSTOPTS:
	case IPPROTO_ROUTING:
207 208
		if (attrs[XFRMA_ALG_COMP]	||
		    attrs[XFRMA_ALG_AUTH]	||
209
		    attrs[XFRMA_ALG_AUTH_TRUNC]	||
210
		    attrs[XFRMA_ALG_AEAD]	||
211 212 213
		    attrs[XFRMA_ALG_CRYPT]	||
		    attrs[XFRMA_ENCAP]		||
		    attrs[XFRMA_SEC_CTX]	||
214
		    attrs[XFRMA_TFCPAD]		||
215
		    !attrs[XFRMA_COADDR])
216 217 218 219
			goto out;
		break;
#endif

L
Linus Torvalds 已提交
220 221
	default:
		goto out;
222
	}
L
Linus Torvalds 已提交
223

224 225
	if ((err = verify_aead(attrs)))
		goto out;
226 227
	if ((err = verify_auth_trunc(attrs)))
		goto out;
228
	if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH)))
L
Linus Torvalds 已提交
229
		goto out;
230
	if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT)))
L
Linus Torvalds 已提交
231
		goto out;
232
	if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP)))
L
Linus Torvalds 已提交
233
		goto out;
234
	if ((err = verify_sec_ctx_len(attrs)))
235
		goto out;
236 237
	if ((err = verify_replay(p, attrs)))
		goto out;
L
Linus Torvalds 已提交
238 239 240

	err = -EINVAL;
	switch (p->mode) {
241 242
	case XFRM_MODE_TRANSPORT:
	case XFRM_MODE_TUNNEL:
243
	case XFRM_MODE_ROUTEOPTIMIZATION:
D
Diego Beltrami 已提交
244
	case XFRM_MODE_BEET:
L
Linus Torvalds 已提交
245 246 247 248
		break;

	default:
		goto out;
249
	}
L
Linus Torvalds 已提交
250 251 252 253 254 255 256 257

	err = 0;

out:
	return err;
}

static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
258
			   struct xfrm_algo_desc *(*get_byname)(const char *, int),
259
			   struct nlattr *rta)
L
Linus Torvalds 已提交
260 261 262 263 264 265 266
{
	struct xfrm_algo *p, *ualg;
	struct xfrm_algo_desc *algo;

	if (!rta)
		return 0;

267
	ualg = nla_data(rta);
L
Linus Torvalds 已提交
268 269 270 271 272 273

	algo = get_byname(ualg->alg_name, 1);
	if (!algo)
		return -ENOSYS;
	*props = algo->desc.sadb_alg_id;

274
	p = kmemdup(ualg, xfrm_alg_len(ualg), GFP_KERNEL);
L
Linus Torvalds 已提交
275 276 277
	if (!p)
		return -ENOMEM;

278
	strcpy(p->alg_name, algo->name);
L
Linus Torvalds 已提交
279 280 281 282
	*algpp = p;
	return 0;
}

283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
static int attach_auth(struct xfrm_algo_auth **algpp, u8 *props,
		       struct nlattr *rta)
{
	struct xfrm_algo *ualg;
	struct xfrm_algo_auth *p;
	struct xfrm_algo_desc *algo;

	if (!rta)
		return 0;

	ualg = nla_data(rta);

	algo = xfrm_aalg_get_byname(ualg->alg_name, 1);
	if (!algo)
		return -ENOSYS;
	*props = algo->desc.sadb_alg_id;

	p = kmalloc(sizeof(*p) + (ualg->alg_key_len + 7) / 8, GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	strcpy(p->alg_name, algo->name);
	p->alg_key_len = ualg->alg_key_len;
	p->alg_trunc_len = algo->uinfo.auth.icv_truncbits;
	memcpy(p->alg_key, ualg->alg_key, (ualg->alg_key_len + 7) / 8);

	*algpp = p;
	return 0;
}

static int attach_auth_trunc(struct xfrm_algo_auth **algpp, u8 *props,
			     struct nlattr *rta)
{
	struct xfrm_algo_auth *p, *ualg;
	struct xfrm_algo_desc *algo;

	if (!rta)
		return 0;

	ualg = nla_data(rta);

	algo = xfrm_aalg_get_byname(ualg->alg_name, 1);
	if (!algo)
		return -ENOSYS;
327 328
	if ((ualg->alg_trunc_len / 8) > MAX_AH_AUTH_LEN ||
	    ualg->alg_trunc_len > algo->uinfo.auth.icv_fullbits)
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
		return -EINVAL;
	*props = algo->desc.sadb_alg_id;

	p = kmemdup(ualg, xfrm_alg_auth_len(ualg), GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	strcpy(p->alg_name, algo->name);
	if (!p->alg_trunc_len)
		p->alg_trunc_len = algo->uinfo.auth.icv_truncbits;

	*algpp = p;
	return 0;
}

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
		       struct nlattr *rta)
{
	struct xfrm_algo_aead *p, *ualg;
	struct xfrm_algo_desc *algo;

	if (!rta)
		return 0;

	ualg = nla_data(rta);

	algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1);
	if (!algo)
		return -ENOSYS;
	*props = algo->desc.sadb_alg_id;

	p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	strcpy(p->alg_name, algo->name);
	*algpp = p;
	return 0;
}

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn,
					 struct nlattr *rp)
{
	struct xfrm_replay_state_esn *up;

	if (!replay_esn || !rp)
		return 0;

	up = nla_data(rp);

	if (xfrm_replay_state_esn_len(replay_esn) !=
			xfrm_replay_state_esn_len(up))
		return -EINVAL;

	return 0;
}

386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn,
				       struct xfrm_replay_state_esn **preplay_esn,
				       struct nlattr *rta)
{
	struct xfrm_replay_state_esn *p, *pp, *up;

	if (!rta)
		return 0;

	up = nla_data(rta);

	p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
	if (!pp) {
		kfree(p);
		return -ENOMEM;
	}

	*replay_esn = p;
	*preplay_esn = pp;

	return 0;
}

413
static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
414 415 416 417 418 419 420 421 422 423
{
	int len = 0;

	if (xfrm_ctx) {
		len += sizeof(struct xfrm_user_sec_ctx);
		len += xfrm_ctx->ctx_len;
	}
	return len;
}

L
Linus Torvalds 已提交
424 425 426 427 428 429 430 431 432
static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
{
	memcpy(&x->id, &p->id, sizeof(x->id));
	memcpy(&x->sel, &p->sel, sizeof(x->sel));
	memcpy(&x->lft, &p->lft, sizeof(x->lft));
	x->props.mode = p->mode;
	x->props.replay_window = p->replay_window;
	x->props.reqid = p->reqid;
	x->props.family = p->family;
433
	memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
L
Linus Torvalds 已提交
434
	x->props.flags = p->flags;
435

436
	if (!x->sel.family && !(p->flags & XFRM_STATE_AF_UNSPEC))
437
		x->sel.family = p->family;
L
Linus Torvalds 已提交
438 439
}

J
Jamal Hadi Salim 已提交
440 441 442 443 444
/*
 * someday when pfkey also has support, we could have the code
 * somehow made shareable and move it to xfrm_state.c - JHS
 *
*/
445
static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
446
{
447
	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
448
	struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
449 450 451
	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
	struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
	struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
J
Jamal Hadi Salim 已提交
452

453 454 455 456 457 458 459 460 461
	if (re) {
		struct xfrm_replay_state_esn *replay_esn;
		replay_esn = nla_data(re);
		memcpy(x->replay_esn, replay_esn,
		       xfrm_replay_state_esn_len(replay_esn));
		memcpy(x->preplay_esn, replay_esn,
		       xfrm_replay_state_esn_len(replay_esn));
	}

J
Jamal Hadi Salim 已提交
462 463
	if (rp) {
		struct xfrm_replay_state *replay;
464
		replay = nla_data(rp);
J
Jamal Hadi Salim 已提交
465 466 467 468 469 470
		memcpy(&x->replay, replay, sizeof(*replay));
		memcpy(&x->preplay, replay, sizeof(*replay));
	}

	if (lt) {
		struct xfrm_lifetime_cur *ltime;
471
		ltime = nla_data(lt);
J
Jamal Hadi Salim 已提交
472 473 474 475 476 477
		x->curlft.bytes = ltime->bytes;
		x->curlft.packets = ltime->packets;
		x->curlft.add_time = ltime->add_time;
		x->curlft.use_time = ltime->use_time;
	}

478
	if (et)
479
		x->replay_maxage = nla_get_u32(et);
J
Jamal Hadi Salim 已提交
480

481
	if (rt)
482
		x->replay_maxdiff = nla_get_u32(rt);
J
Jamal Hadi Salim 已提交
483 484
}

485 486
static struct xfrm_state *xfrm_state_construct(struct net *net,
					       struct xfrm_usersa_info *p,
487
					       struct nlattr **attrs,
L
Linus Torvalds 已提交
488 489
					       int *errp)
{
490
	struct xfrm_state *x = xfrm_state_alloc(net);
L
Linus Torvalds 已提交
491 492 493 494 495 496 497
	int err = -ENOMEM;

	if (!x)
		goto error_no_put;

	copy_from_user_state(x, p);

498 499 500
	if ((err = attach_aead(&x->aead, &x->props.ealgo,
			       attrs[XFRMA_ALG_AEAD])))
		goto error;
501 502
	if ((err = attach_auth_trunc(&x->aalg, &x->props.aalgo,
				     attrs[XFRMA_ALG_AUTH_TRUNC])))
L
Linus Torvalds 已提交
503
		goto error;
504 505 506 507 508
	if (!x->props.aalgo) {
		if ((err = attach_auth(&x->aalg, &x->props.aalgo,
				       attrs[XFRMA_ALG_AUTH])))
			goto error;
	}
L
Linus Torvalds 已提交
509 510
	if ((err = attach_one_algo(&x->ealg, &x->props.ealgo,
				   xfrm_ealg_get_byname,
511
				   attrs[XFRMA_ALG_CRYPT])))
L
Linus Torvalds 已提交
512 513 514
		goto error;
	if ((err = attach_one_algo(&x->calg, &x->props.calgo,
				   xfrm_calg_get_byname,
515
				   attrs[XFRMA_ALG_COMP])))
L
Linus Torvalds 已提交
516
		goto error;
517 518 519 520 521 522 523 524

	if (attrs[XFRMA_ENCAP]) {
		x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]),
				   sizeof(*x->encap), GFP_KERNEL);
		if (x->encap == NULL)
			goto error;
	}

525 526 527
	if (attrs[XFRMA_TFCPAD])
		x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]);

528 529 530 531 532 533 534
	if (attrs[XFRMA_COADDR]) {
		x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]),
				    sizeof(*x->coaddr), GFP_KERNEL);
		if (x->coaddr == NULL)
			goto error;
	}

535 536
	xfrm_mark_get(attrs, &x->mark);

537
	err = __xfrm_init_state(x, false);
L
Linus Torvalds 已提交
538 539 540
	if (err)
		goto error;

541 542
	if (attrs[XFRMA_SEC_CTX] &&
	    security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX])))
543 544
		goto error;

545 546 547 548
	if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
					       attrs[XFRMA_REPLAY_ESN_VAL])))
		goto error;

L
Linus Torvalds 已提交
549
	x->km.seq = p->seq;
A
Alexey Dobriyan 已提交
550
	x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth;
J
Jamal Hadi Salim 已提交
551
	/* sysctl_xfrm_aevent_etime is in 100ms units */
A
Alexey Dobriyan 已提交
552
	x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M;
J
Jamal Hadi Salim 已提交
553

554 555
	if ((err = xfrm_init_replay(x)))
		goto error;
J
Jamal Hadi Salim 已提交
556

557
	/* override default values from above */
558
	xfrm_update_ae_params(x, attrs);
L
Linus Torvalds 已提交
559 560 561 562 563 564 565 566 567 568 569

	return x;

error:
	x->km.state = XFRM_STATE_DEAD;
	xfrm_state_put(x);
error_no_put:
	*errp = err;
	return NULL;
}

570
static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
571
		struct nlattr **attrs)
L
Linus Torvalds 已提交
572
{
573
	struct net *net = sock_net(skb->sk);
574
	struct xfrm_usersa_info *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
575 576
	struct xfrm_state *x;
	int err;
577
	struct km_event c;
578 579 580
	uid_t loginuid = audit_get_loginuid(current);
	u32 sessionid = audit_get_sessionid(current);
	u32 sid;
L
Linus Torvalds 已提交
581

582
	err = verify_newsa_info(p, attrs);
L
Linus Torvalds 已提交
583 584 585
	if (err)
		return err;

586
	x = xfrm_state_construct(net, p, attrs, &err);
L
Linus Torvalds 已提交
587 588 589
	if (!x)
		return err;

590
	xfrm_state_hold(x);
L
Linus Torvalds 已提交
591 592 593 594 595
	if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
		err = xfrm_state_add(x);
	else
		err = xfrm_state_update(x);

596
	security_task_getsecid(current, &sid);
597
	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
598

L
Linus Torvalds 已提交
599 600
	if (err < 0) {
		x->km.state = XFRM_STATE_DEAD;
601
		__xfrm_state_put(x);
602
		goto out;
L
Linus Torvalds 已提交
603 604
	}

605 606
	c.seq = nlh->nlmsg_seq;
	c.pid = nlh->nlmsg_pid;
607
	c.event = nlh->nlmsg_type;
608 609

	km_state_notify(x, &c);
610
out:
611
	xfrm_state_put(x);
L
Linus Torvalds 已提交
612 613 614
	return err;
}

615 616
static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
						 struct xfrm_usersa_id *p,
617
						 struct nlattr **attrs,
618 619 620
						 int *errp)
{
	struct xfrm_state *x = NULL;
621
	struct xfrm_mark m;
622
	int err;
623
	u32 mark = xfrm_mark_get(attrs, &m);
624 625 626

	if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
		err = -ESRCH;
627
		x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family);
628 629 630
	} else {
		xfrm_address_t *saddr = NULL;

631
		verify_one_addr(attrs, XFRMA_SRCADDR, &saddr);
632 633 634 635 636
		if (!saddr) {
			err = -EINVAL;
			goto out;
		}

637
		err = -ESRCH;
638 639
		x = xfrm_state_lookup_byaddr(net, mark,
					     &p->daddr, saddr,
640
					     p->proto, p->family);
641 642 643 644 645 646 647 648
	}

 out:
	if (!x && errp)
		*errp = err;
	return x;
}

649
static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
650
		struct nlattr **attrs)
L
Linus Torvalds 已提交
651
{
652
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
653
	struct xfrm_state *x;
654
	int err = -ESRCH;
655
	struct km_event c;
656
	struct xfrm_usersa_id *p = nlmsg_data(nlh);
657 658 659
	uid_t loginuid = audit_get_loginuid(current);
	u32 sessionid = audit_get_sessionid(current);
	u32 sid;
L
Linus Torvalds 已提交
660

661
	x = xfrm_user_state_lookup(net, p, attrs, &err);
L
Linus Torvalds 已提交
662
	if (x == NULL)
663
		return err;
L
Linus Torvalds 已提交
664

665
	if ((err = security_xfrm_state_delete(x)) != 0)
C
Catherine Zhang 已提交
666 667
		goto out;

L
Linus Torvalds 已提交
668
	if (xfrm_state_kern(x)) {
C
Catherine Zhang 已提交
669 670
		err = -EPERM;
		goto out;
L
Linus Torvalds 已提交
671 672
	}

673
	err = xfrm_state_delete(x);
J
Joy Latten 已提交
674

C
Catherine Zhang 已提交
675 676
	if (err < 0)
		goto out;
677 678 679

	c.seq = nlh->nlmsg_seq;
	c.pid = nlh->nlmsg_pid;
680
	c.event = nlh->nlmsg_type;
681
	km_state_notify(x, &c);
L
Linus Torvalds 已提交
682

C
Catherine Zhang 已提交
683
out:
684
	security_task_getsecid(current, &sid);
685
	xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
C
Catherine Zhang 已提交
686
	xfrm_state_put(x);
687
	return err;
L
Linus Torvalds 已提交
688 689 690 691
}

static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
{
692
	memset(p, 0, sizeof(*p));
L
Linus Torvalds 已提交
693 694 695 696 697
	memcpy(&p->id, &x->id, sizeof(p->id));
	memcpy(&p->sel, &x->sel, sizeof(p->sel));
	memcpy(&p->lft, &x->lft, sizeof(p->lft));
	memcpy(&p->curlft, &x->curlft, sizeof(p->curlft));
	memcpy(&p->stats, &x->stats, sizeof(p->stats));
698
	memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr));
L
Linus Torvalds 已提交
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
	p->mode = x->props.mode;
	p->replay_window = x->props.replay_window;
	p->reqid = x->props.reqid;
	p->family = x->props.family;
	p->flags = x->props.flags;
	p->seq = x->km.seq;
}

struct xfrm_dump_info {
	struct sk_buff *in_skb;
	struct sk_buff *out_skb;
	u32 nlmsg_seq;
	u16 nlmsg_flags;
};

714 715 716 717
static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb)
{
	struct xfrm_user_sec_ctx *uctx;
	struct nlattr *attr;
718
	int ctx_size = sizeof(*uctx) + s->ctx_len;
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734

	attr = nla_reserve(skb, XFRMA_SEC_CTX, ctx_size);
	if (attr == NULL)
		return -EMSGSIZE;

	uctx = nla_data(attr);
	uctx->exttype = XFRMA_SEC_CTX;
	uctx->len = ctx_size;
	uctx->ctx_doi = s->ctx_doi;
	uctx->ctx_alg = s->ctx_alg;
	uctx->ctx_len = s->ctx_len;
	memcpy(uctx + 1, s->ctx_str, s->ctx_len);

	return 0;
}

735 736 737 738 739 740 741 742 743 744 745
static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
{
	struct xfrm_algo *algo;
	struct nlattr *nla;

	nla = nla_reserve(skb, XFRMA_ALG_AUTH,
			  sizeof(*algo) + (auth->alg_key_len + 7) / 8);
	if (!nla)
		return -EMSGSIZE;

	algo = nla_data(nla);
746
	strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));
747 748 749 750 751 752
	memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
	algo->alg_key_len = auth->alg_key_len;

	return 0;
}

753 754 755 756
/* Don't change this without updating xfrm_sa_len! */
static int copy_to_user_state_extra(struct xfrm_state *x,
				    struct xfrm_usersa_info *p,
				    struct sk_buff *skb)
L
Linus Torvalds 已提交
757
{
758
	int ret = 0;
759

760
	copy_to_user_state(x, p);
761

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
	if (x->coaddr) {
		ret = nla_put(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr);
		if (ret)
			goto out;
	}
	if (x->lastused) {
		ret = nla_put_u64(skb, XFRMA_LASTUSED, x->lastused);
		if (ret)
			goto out;
	}
	if (x->aead) {
		ret = nla_put(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead);
		if (ret)
			goto out;
	}
	if (x->aalg) {
		ret = copy_to_user_auth(x->aalg, skb);
		if (!ret)
			ret = nla_put(skb, XFRMA_ALG_AUTH_TRUNC,
				      xfrm_alg_auth_len(x->aalg), x->aalg);
		if (ret)
			goto out;
	}
	if (x->ealg) {
		ret = nla_put(skb, XFRMA_ALG_CRYPT, xfrm_alg_len(x->ealg), x->ealg);
		if (ret)
			goto out;
	}
	if (x->calg) {
		ret = nla_put(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
		if (ret)
			goto out;
	}
	if (x->encap) {
		ret = nla_put(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
		if (ret)
			goto out;
	}
	if (x->tfcpad) {
		ret = nla_put_u32(skb, XFRMA_TFCPAD, x->tfcpad);
		if (ret)
			goto out;
	}
	ret = xfrm_mark_put(skb, &x->mark);
	if (ret)
		goto out;
	if (x->replay_esn) {
		ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
			      xfrm_replay_state_esn_len(x->replay_esn),
			      x->replay_esn);
		if (ret)
			goto out;
	}
	if (x->security)
		ret = copy_sec_ctx(x->security, skb);
out:
	return ret;
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
}

static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
{
	struct xfrm_dump_info *sp = ptr;
	struct sk_buff *in_skb = sp->in_skb;
	struct sk_buff *skb = sp->out_skb;
	struct xfrm_usersa_info *p;
	struct nlmsghdr *nlh;
	int err;

	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
			XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags);
	if (nlh == NULL)
		return -EMSGSIZE;

	p = nlmsg_data(nlh);

	err = copy_to_user_state_extra(x, p, skb);
838 839 840 841
	if (err) {
		nlmsg_cancel(skb, nlh);
		return err;
	}
842
	nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
843 844 845
	return 0;
}

846 847 848 849 850 851 852
static int xfrm_dump_sa_done(struct netlink_callback *cb)
{
	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
	xfrm_state_walk_done(walk);
	return 0;
}

L
Linus Torvalds 已提交
853 854
static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
{
855
	struct net *net = sock_net(skb->sk);
856
	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
L
Linus Torvalds 已提交
857 858
	struct xfrm_dump_info info;

859 860 861
	BUILD_BUG_ON(sizeof(struct xfrm_state_walk) >
		     sizeof(cb->args) - sizeof(cb->args[0]));

L
Linus Torvalds 已提交
862 863 864 865
	info.in_skb = cb->skb;
	info.out_skb = skb;
	info.nlmsg_seq = cb->nlh->nlmsg_seq;
	info.nlmsg_flags = NLM_F_MULTI;
866 867 868 869 870 871

	if (!cb->args[0]) {
		cb->args[0] = 1;
		xfrm_state_walk_init(walk, 0);
	}

872
	(void) xfrm_state_walk(net, walk, dump_one_state, &info);
L
Linus Torvalds 已提交
873 874 875 876 877 878 879 880 881

	return skb->len;
}

static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
					  struct xfrm_state *x, u32 seq)
{
	struct xfrm_dump_info info;
	struct sk_buff *skb;
882
	int err;
L
Linus Torvalds 已提交
883

884
	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
L
Linus Torvalds 已提交
885 886 887 888 889 890 891 892
	if (!skb)
		return ERR_PTR(-ENOMEM);

	info.in_skb = in_skb;
	info.out_skb = skb;
	info.nlmsg_seq = seq;
	info.nlmsg_flags = 0;

893 894
	err = dump_one_state(x, 0, &info);
	if (err) {
L
Linus Torvalds 已提交
895
		kfree_skb(skb);
896
		return ERR_PTR(err);
L
Linus Torvalds 已提交
897 898 899 900 901
	}

	return skb;
}

902 903 904 905 906 907 908
static inline size_t xfrm_spdinfo_msgsize(void)
{
	return NLMSG_ALIGN(4)
	       + nla_total_size(sizeof(struct xfrmu_spdinfo))
	       + nla_total_size(sizeof(struct xfrmu_spdhinfo));
}

909 910
static int build_spdinfo(struct sk_buff *skb, struct net *net,
			 u32 pid, u32 seq, u32 flags)
J
Jamal Hadi Salim 已提交
911
{
912 913 914
	struct xfrmk_spdinfo si;
	struct xfrmu_spdinfo spc;
	struct xfrmu_spdhinfo sph;
J
Jamal Hadi Salim 已提交
915
	struct nlmsghdr *nlh;
916
	int err;
J
Jamal Hadi Salim 已提交
917 918 919
	u32 *f;

	nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0);
L
Lucas De Marchi 已提交
920
	if (nlh == NULL) /* shouldn't really happen ... */
J
Jamal Hadi Salim 已提交
921 922 923 924
		return -EMSGSIZE;

	f = nlmsg_data(nlh);
	*f = flags;
925
	xfrm_spd_getinfo(net, &si);
926 927 928 929 930 931 932 933 934
	spc.incnt = si.incnt;
	spc.outcnt = si.outcnt;
	spc.fwdcnt = si.fwdcnt;
	spc.inscnt = si.inscnt;
	spc.outscnt = si.outscnt;
	spc.fwdscnt = si.fwdscnt;
	sph.spdhcnt = si.spdhcnt;
	sph.spdhmcnt = si.spdhmcnt;

935 936 937 938 939 940 941
	err = nla_put(skb, XFRMA_SPD_INFO, sizeof(spc), &spc);
	if (!err)
		err = nla_put(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph);
	if (err) {
		nlmsg_cancel(skb, nlh);
		return err;
	}
J
Jamal Hadi Salim 已提交
942 943 944 945 946

	return nlmsg_end(skb, nlh);
}

static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
947
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
948
{
949
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
950
	struct sk_buff *r_skb;
951
	u32 *flags = nlmsg_data(nlh);
J
Jamal Hadi Salim 已提交
952 953 954
	u32 spid = NETLINK_CB(skb).pid;
	u32 seq = nlh->nlmsg_seq;

955
	r_skb = nlmsg_new(xfrm_spdinfo_msgsize(), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
956 957 958
	if (r_skb == NULL)
		return -ENOMEM;

959
	if (build_spdinfo(r_skb, net, spid, seq, *flags) < 0)
J
Jamal Hadi Salim 已提交
960 961
		BUG();

962
	return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid);
J
Jamal Hadi Salim 已提交
963 964
}

965 966 967 968 969 970 971
static inline size_t xfrm_sadinfo_msgsize(void)
{
	return NLMSG_ALIGN(4)
	       + nla_total_size(sizeof(struct xfrmu_sadhinfo))
	       + nla_total_size(4); /* XFRMA_SAD_CNT */
}

972 973
static int build_sadinfo(struct sk_buff *skb, struct net *net,
			 u32 pid, u32 seq, u32 flags)
J
Jamal Hadi Salim 已提交
974
{
975 976
	struct xfrmk_sadinfo si;
	struct xfrmu_sadhinfo sh;
J
Jamal Hadi Salim 已提交
977
	struct nlmsghdr *nlh;
978
	int err;
J
Jamal Hadi Salim 已提交
979 980 981
	u32 *f;

	nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0);
L
Lucas De Marchi 已提交
982
	if (nlh == NULL) /* shouldn't really happen ... */
J
Jamal Hadi Salim 已提交
983 984 985 986
		return -EMSGSIZE;

	f = nlmsg_data(nlh);
	*f = flags;
987
	xfrm_sad_getinfo(net, &si);
J
Jamal Hadi Salim 已提交
988

989 990 991
	sh.sadhmcnt = si.sadhmcnt;
	sh.sadhcnt = si.sadhcnt;

992 993 994 995 996 997 998
	err = nla_put_u32(skb, XFRMA_SAD_CNT, si.sadcnt);
	if (!err)
		err = nla_put(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh);
	if (err) {
		nlmsg_cancel(skb, nlh);
		return err;
	}
J
Jamal Hadi Salim 已提交
999 1000 1001 1002 1003

	return nlmsg_end(skb, nlh);
}

static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
1004
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1005
{
1006
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1007
	struct sk_buff *r_skb;
1008
	u32 *flags = nlmsg_data(nlh);
J
Jamal Hadi Salim 已提交
1009 1010 1011
	u32 spid = NETLINK_CB(skb).pid;
	u32 seq = nlh->nlmsg_seq;

1012
	r_skb = nlmsg_new(xfrm_sadinfo_msgsize(), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
1013 1014 1015
	if (r_skb == NULL)
		return -ENOMEM;

1016
	if (build_sadinfo(r_skb, net, spid, seq, *flags) < 0)
J
Jamal Hadi Salim 已提交
1017 1018
		BUG();

1019
	return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid);
J
Jamal Hadi Salim 已提交
1020 1021
}

1022
static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1023
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1024
{
1025
	struct net *net = sock_net(skb->sk);
1026
	struct xfrm_usersa_id *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1027 1028
	struct xfrm_state *x;
	struct sk_buff *resp_skb;
1029
	int err = -ESRCH;
L
Linus Torvalds 已提交
1030

1031
	x = xfrm_user_state_lookup(net, p, attrs, &err);
L
Linus Torvalds 已提交
1032 1033 1034 1035 1036 1037 1038
	if (x == NULL)
		goto out_noput;

	resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq);
	if (IS_ERR(resp_skb)) {
		err = PTR_ERR(resp_skb);
	} else {
1039
		err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid);
L
Linus Torvalds 已提交
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
	}
	xfrm_state_put(x);
out_noput:
	return err;
}

static int verify_userspi_info(struct xfrm_userspi_info *p)
{
	switch (p->info.id.proto) {
	case IPPROTO_AH:
	case IPPROTO_ESP:
		break;

	case IPPROTO_COMP:
		/* IPCOMP spi is 16-bits. */
		if (p->max >= 0x10000)
			return -EINVAL;
		break;

	default:
		return -EINVAL;
1061
	}
L
Linus Torvalds 已提交
1062 1063 1064 1065 1066 1067 1068

	if (p->min > p->max)
		return -EINVAL;

	return 0;
}

1069
static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
1070
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1071
{
1072
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1073 1074 1075 1076 1077 1078
	struct xfrm_state *x;
	struct xfrm_userspi_info *p;
	struct sk_buff *resp_skb;
	xfrm_address_t *daddr;
	int family;
	int err;
1079 1080
	u32 mark;
	struct xfrm_mark m;
L
Linus Torvalds 已提交
1081

1082
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1083 1084 1085 1086 1087 1088 1089 1090
	err = verify_userspi_info(p);
	if (err)
		goto out_noput;

	family = p->info.family;
	daddr = &p->info.id.daddr;

	x = NULL;
1091 1092

	mark = xfrm_mark_get(attrs, &m);
L
Linus Torvalds 已提交
1093
	if (p->info.seq) {
1094
		x = xfrm_find_acq_byseq(net, mark, p->info.seq);
L
Linus Torvalds 已提交
1095 1096 1097 1098 1099 1100 1101
		if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
			xfrm_state_put(x);
			x = NULL;
		}
	}

	if (!x)
1102
		x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid,
L
Linus Torvalds 已提交
1103 1104 1105 1106 1107 1108 1109
				  p->info.id.proto, daddr,
				  &p->info.saddr, 1,
				  family);
	err = -ENOENT;
	if (x == NULL)
		goto out_noput;

1110 1111 1112
	err = xfrm_alloc_spi(x, p->min, p->max);
	if (err)
		goto out;
L
Linus Torvalds 已提交
1113

1114
	resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq);
L
Linus Torvalds 已提交
1115 1116 1117 1118 1119
	if (IS_ERR(resp_skb)) {
		err = PTR_ERR(resp_skb);
		goto out;
	}

1120
	err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid);
L
Linus Torvalds 已提交
1121 1122 1123 1124 1125 1126 1127

out:
	xfrm_state_put(x);
out_noput:
	return err;
}

1128
static int verify_policy_dir(u8 dir)
L
Linus Torvalds 已提交
1129 1130 1131 1132 1133 1134 1135 1136 1137
{
	switch (dir) {
	case XFRM_POLICY_IN:
	case XFRM_POLICY_OUT:
	case XFRM_POLICY_FWD:
		break;

	default:
		return -EINVAL;
1138
	}
L
Linus Torvalds 已提交
1139 1140 1141 1142

	return 0;
}

1143
static int verify_policy_type(u8 type)
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
{
	switch (type) {
	case XFRM_POLICY_TYPE_MAIN:
#ifdef CONFIG_XFRM_SUB_POLICY
	case XFRM_POLICY_TYPE_SUB:
#endif
		break;

	default:
		return -EINVAL;
1154
	}
1155 1156 1157 1158

	return 0;
}

L
Linus Torvalds 已提交
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
{
	switch (p->share) {
	case XFRM_SHARE_ANY:
	case XFRM_SHARE_SESSION:
	case XFRM_SHARE_USER:
	case XFRM_SHARE_UNIQUE:
		break;

	default:
		return -EINVAL;
1170
	}
L
Linus Torvalds 已提交
1171 1172 1173 1174 1175 1176 1177 1178

	switch (p->action) {
	case XFRM_POLICY_ALLOW:
	case XFRM_POLICY_BLOCK:
		break;

	default:
		return -EINVAL;
1179
	}
L
Linus Torvalds 已提交
1180 1181 1182 1183 1184 1185

	switch (p->sel.family) {
	case AF_INET:
		break;

	case AF_INET6:
E
Eric Dumazet 已提交
1186
#if IS_ENABLED(CONFIG_IPV6)
L
Linus Torvalds 已提交
1187 1188 1189 1190 1191 1192 1193
		break;
#else
		return  -EAFNOSUPPORT;
#endif

	default:
		return -EINVAL;
1194
	}
L
Linus Torvalds 已提交
1195 1196 1197 1198

	return verify_policy_dir(p->dir);
}

1199
static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs)
1200
{
1201
	struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1202 1203 1204 1205 1206
	struct xfrm_user_sec_ctx *uctx;

	if (!rt)
		return 0;

1207
	uctx = nla_data(rt);
1208
	return security_xfrm_policy_alloc(&pol->security, uctx);
1209 1210
}

L
Linus Torvalds 已提交
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
			   int nr)
{
	int i;

	xp->xfrm_nr = nr;
	for (i = 0; i < nr; i++, ut++) {
		struct xfrm_tmpl *t = &xp->xfrm_vec[i];

		memcpy(&t->id, &ut->id, sizeof(struct xfrm_id));
		memcpy(&t->saddr, &ut->saddr,
		       sizeof(xfrm_address_t));
		t->reqid = ut->reqid;
		t->mode = ut->mode;
		t->share = ut->share;
		t->optional = ut->optional;
		t->aalgos = ut->aalgos;
		t->ealgos = ut->ealgos;
		t->calgos = ut->calgos;
1230 1231
		/* If all masks are ~0, then we allow all algorithms. */
		t->allalgs = !~(t->aalgos & t->ealgos & t->calgos);
1232
		t->encap_family = ut->family;
L
Linus Torvalds 已提交
1233 1234 1235
	}
}

1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
{
	int i;

	if (nr > XFRM_MAX_DEPTH)
		return -EINVAL;

	for (i = 0; i < nr; i++) {
		/* We never validated the ut->family value, so many
		 * applications simply leave it at zero.  The check was
		 * never made and ut->family was ignored because all
		 * templates could be assumed to have the same family as
		 * the policy itself.  Now that we will have ipv4-in-ipv6
		 * and ipv6-in-ipv4 tunnels, this is no longer true.
		 */
		if (!ut[i].family)
			ut[i].family = family;

		switch (ut[i].family) {
		case AF_INET:
			break;
E
Eric Dumazet 已提交
1257
#if IS_ENABLED(CONFIG_IPV6)
1258 1259 1260 1261 1262
		case AF_INET6:
			break;
#endif
		default:
			return -EINVAL;
1263
		}
1264 1265 1266 1267 1268
	}

	return 0;
}

1269
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs)
L
Linus Torvalds 已提交
1270
{
1271
	struct nlattr *rt = attrs[XFRMA_TMPL];
L
Linus Torvalds 已提交
1272 1273 1274 1275

	if (!rt) {
		pol->xfrm_nr = 0;
	} else {
1276 1277
		struct xfrm_user_tmpl *utmpl = nla_data(rt);
		int nr = nla_len(rt) / sizeof(*utmpl);
1278
		int err;
L
Linus Torvalds 已提交
1279

1280 1281 1282
		err = validate_tmpl(nr, utmpl, pol->family);
		if (err)
			return err;
L
Linus Torvalds 已提交
1283

1284
		copy_templates(pol, utmpl, nr);
L
Linus Torvalds 已提交
1285 1286 1287 1288
	}
	return 0;
}

1289
static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs)
1290
{
1291
	struct nlattr *rt = attrs[XFRMA_POLICY_TYPE];
1292
	struct xfrm_userpolicy_type *upt;
1293
	u8 type = XFRM_POLICY_TYPE_MAIN;
1294 1295 1296
	int err;

	if (rt) {
1297
		upt = nla_data(rt);
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
		type = upt->type;
	}

	err = verify_policy_type(type);
	if (err)
		return err;

	*tp = type;
	return 0;
}

L
Linus Torvalds 已提交
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p)
{
	xp->priority = p->priority;
	xp->index = p->index;
	memcpy(&xp->selector, &p->sel, sizeof(xp->selector));
	memcpy(&xp->lft, &p->lft, sizeof(xp->lft));
	xp->action = p->action;
	xp->flags = p->flags;
	xp->family = p->sel.family;
	/* XXX xp->share = p->share; */
}

static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)
{
1323
	memset(p, 0, sizeof(*p));
L
Linus Torvalds 已提交
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
	memcpy(&p->sel, &xp->selector, sizeof(p->sel));
	memcpy(&p->lft, &xp->lft, sizeof(p->lft));
	memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
	p->priority = xp->priority;
	p->index = xp->index;
	p->sel.family = xp->family;
	p->dir = dir;
	p->action = xp->action;
	p->flags = xp->flags;
	p->share = XFRM_SHARE_ANY; /* XXX xp->share */
}

1336
static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp)
L
Linus Torvalds 已提交
1337
{
1338
	struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL);
L
Linus Torvalds 已提交
1339 1340 1341 1342 1343 1344 1345 1346
	int err;

	if (!xp) {
		*errp = -ENOMEM;
		return NULL;
	}

	copy_from_user_policy(xp, p);
1347

1348
	err = copy_from_user_policy_type(&xp->type, attrs);
1349 1350 1351
	if (err)
		goto error;

1352 1353
	if (!(err = copy_from_user_tmpl(xp, attrs)))
		err = copy_from_user_sec_ctx(xp, attrs);
1354 1355
	if (err)
		goto error;
L
Linus Torvalds 已提交
1356

1357 1358
	xfrm_mark_get(attrs, &xp->mark);

L
Linus Torvalds 已提交
1359
	return xp;
1360 1361
 error:
	*errp = err;
H
Herbert Xu 已提交
1362
	xp->walk.dead = 1;
1363
	xfrm_policy_destroy(xp);
1364
	return NULL;
L
Linus Torvalds 已提交
1365 1366
}

1367
static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1368
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1369
{
1370
	struct net *net = sock_net(skb->sk);
1371
	struct xfrm_userpolicy_info *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1372
	struct xfrm_policy *xp;
1373
	struct km_event c;
L
Linus Torvalds 已提交
1374 1375
	int err;
	int excl;
1376 1377 1378
	uid_t loginuid = audit_get_loginuid(current);
	u32 sessionid = audit_get_sessionid(current);
	u32 sid;
L
Linus Torvalds 已提交
1379 1380

	err = verify_newpolicy_info(p);
1381 1382
	if (err)
		return err;
1383
	err = verify_sec_ctx_len(attrs);
L
Linus Torvalds 已提交
1384 1385 1386
	if (err)
		return err;

1387
	xp = xfrm_policy_construct(net, p, attrs, &err);
L
Linus Torvalds 已提交
1388 1389 1390
	if (!xp)
		return err;

L
Lucas De Marchi 已提交
1391
	/* shouldn't excl be based on nlh flags??
1392 1393 1394
	 * Aha! this is anti-netlink really i.e  more pfkey derived
	 * in netlink excl is a flag and you wouldnt need
	 * a type XFRM_MSG_UPDPOLICY - JHS */
L
Linus Torvalds 已提交
1395 1396
	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
	err = xfrm_policy_insert(p->dir, xp, excl);
1397
	security_task_getsecid(current, &sid);
1398
	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
1399

L
Linus Torvalds 已提交
1400
	if (err) {
1401
		security_xfrm_policy_free(xp->security);
L
Linus Torvalds 已提交
1402 1403 1404 1405
		kfree(xp);
		return err;
	}

1406
	c.event = nlh->nlmsg_type;
1407 1408 1409 1410
	c.seq = nlh->nlmsg_seq;
	c.pid = nlh->nlmsg_pid;
	km_policy_notify(xp, p->dir, &c);

L
Linus Torvalds 已提交
1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
	xfrm_pol_put(xp);

	return 0;
}

static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb)
{
	struct xfrm_user_tmpl vec[XFRM_MAX_DEPTH];
	int i;

	if (xp->xfrm_nr == 0)
		return 0;

	for (i = 0; i < xp->xfrm_nr; i++) {
		struct xfrm_user_tmpl *up = &vec[i];
		struct xfrm_tmpl *kp = &xp->xfrm_vec[i];

		memcpy(&up->id, &kp->id, sizeof(up->id));
1429
		up->family = kp->encap_family;
L
Linus Torvalds 已提交
1430 1431 1432 1433 1434 1435 1436 1437 1438
		memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
		up->reqid = kp->reqid;
		up->mode = kp->mode;
		up->share = kp->share;
		up->optional = kp->optional;
		up->aalgos = kp->aalgos;
		up->ealgos = kp->ealgos;
		up->calgos = kp->calgos;
	}
1439

1440 1441
	return nla_put(skb, XFRMA_TMPL,
		       sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr, vec);
1442 1443 1444 1445 1446 1447
}

static inline int copy_to_user_state_sec_ctx(struct xfrm_state *x, struct sk_buff *skb)
{
	if (x->security) {
		return copy_sec_ctx(x->security, skb);
1448 1449
	}
	return 0;
1450
}
1451

1452 1453
static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
{
1454
	if (xp->security)
1455 1456
		return copy_sec_ctx(xp->security, skb);
	return 0;
1457
}
1458 1459 1460 1461 1462 1463 1464 1465
static inline size_t userpolicy_type_attrsize(void)
{
#ifdef CONFIG_XFRM_SUB_POLICY
	return nla_total_size(sizeof(struct xfrm_userpolicy_type));
#else
	return 0;
#endif
}
1466

1467
#ifdef CONFIG_XFRM_SUB_POLICY
1468
static int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
1469
{
1470 1471 1472
	struct xfrm_userpolicy_type upt = {
		.type = type,
	};
1473

1474
	return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
1475 1476 1477
}

#else
1478
static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
1479 1480 1481 1482 1483
{
	return 0;
}
#endif

L
Linus Torvalds 已提交
1484 1485 1486 1487 1488 1489 1490
static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
{
	struct xfrm_dump_info *sp = ptr;
	struct xfrm_userpolicy_info *p;
	struct sk_buff *in_skb = sp->in_skb;
	struct sk_buff *skb = sp->out_skb;
	struct nlmsghdr *nlh;
1491
	int err;
L
Linus Torvalds 已提交
1492

1493 1494 1495 1496
	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
			XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
1497

1498
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1499
	copy_to_user_policy(xp, p, dir);
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
	err = copy_to_user_tmpl(xp, skb);
	if (!err)
		err = copy_to_user_sec_ctx(xp, skb);
	if (!err)
		err = copy_to_user_policy_type(xp->type, skb);
	if (!err)
		err = xfrm_mark_put(skb, &xp->mark);
	if (err) {
		nlmsg_cancel(skb, nlh);
		return err;
	}
1511
	nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
1512 1513 1514
	return 0;
}

1515 1516 1517 1518 1519 1520 1521 1522
static int xfrm_dump_policy_done(struct netlink_callback *cb)
{
	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];

	xfrm_policy_walk_done(walk);
	return 0;
}

L
Linus Torvalds 已提交
1523 1524
static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
{
1525
	struct net *net = sock_net(skb->sk);
1526
	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
L
Linus Torvalds 已提交
1527 1528
	struct xfrm_dump_info info;

1529 1530 1531
	BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
		     sizeof(cb->args) - sizeof(cb->args[0]));

L
Linus Torvalds 已提交
1532 1533 1534 1535
	info.in_skb = cb->skb;
	info.out_skb = skb;
	info.nlmsg_seq = cb->nlh->nlmsg_seq;
	info.nlmsg_flags = NLM_F_MULTI;
1536 1537 1538 1539 1540 1541

	if (!cb->args[0]) {
		cb->args[0] = 1;
		xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
	}

1542
	(void) xfrm_policy_walk(net, walk, dump_one_policy, &info);
L
Linus Torvalds 已提交
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552

	return skb->len;
}

static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
					  struct xfrm_policy *xp,
					  int dir, u32 seq)
{
	struct xfrm_dump_info info;
	struct sk_buff *skb;
1553
	int err;
L
Linus Torvalds 已提交
1554

1555
	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
L
Linus Torvalds 已提交
1556 1557 1558 1559 1560 1561 1562 1563
	if (!skb)
		return ERR_PTR(-ENOMEM);

	info.in_skb = in_skb;
	info.out_skb = skb;
	info.nlmsg_seq = seq;
	info.nlmsg_flags = 0;

1564 1565
	err = dump_one_policy(xp, dir, 0, &info);
	if (err) {
L
Linus Torvalds 已提交
1566
		kfree_skb(skb);
1567
		return ERR_PTR(err);
L
Linus Torvalds 已提交
1568 1569 1570 1571 1572
	}

	return skb;
}

1573
static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1574
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1575
{
1576
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1577 1578
	struct xfrm_policy *xp;
	struct xfrm_userpolicy_id *p;
1579
	u8 type = XFRM_POLICY_TYPE_MAIN;
L
Linus Torvalds 已提交
1580
	int err;
1581
	struct km_event c;
L
Linus Torvalds 已提交
1582
	int delete;
1583 1584
	struct xfrm_mark m;
	u32 mark = xfrm_mark_get(attrs, &m);
L
Linus Torvalds 已提交
1585

1586
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1587 1588
	delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;

1589
	err = copy_from_user_policy_type(&type, attrs);
1590 1591 1592
	if (err)
		return err;

L
Linus Torvalds 已提交
1593 1594 1595 1596 1597
	err = verify_policy_dir(p->dir);
	if (err)
		return err;

	if (p->index)
1598
		xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err);
1599
	else {
1600
		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1601
		struct xfrm_sec_ctx *ctx;
1602

1603
		err = verify_sec_ctx_len(attrs);
1604 1605 1606
		if (err)
			return err;

1607
		ctx = NULL;
1608
		if (rt) {
1609
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1610

1611 1612
			err = security_xfrm_policy_alloc(&ctx, uctx);
			if (err)
1613
				return err;
1614
		}
1615
		xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel,
1616
					   ctx, delete, &err);
1617
		security_xfrm_policy_free(ctx);
1618
	}
L
Linus Torvalds 已提交
1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
	if (xp == NULL)
		return -ENOENT;

	if (!delete) {
		struct sk_buff *resp_skb;

		resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq);
		if (IS_ERR(resp_skb)) {
			err = PTR_ERR(resp_skb);
		} else {
1629
			err = nlmsg_unicast(net->xfrm.nlsk, resp_skb,
1630
					    NETLINK_CB(skb).pid);
L
Linus Torvalds 已提交
1631
		}
1632
	} else {
1633 1634 1635
		uid_t loginuid = audit_get_loginuid(current);
		u32 sessionid = audit_get_sessionid(current);
		u32 sid;
1636

1637
		security_task_getsecid(current, &sid);
1638 1639
		xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
					 sid);
1640 1641

		if (err != 0)
C
Catherine Zhang 已提交
1642
			goto out;
1643

1644
		c.data.byid = p->index;
1645
		c.event = nlh->nlmsg_type;
1646 1647 1648
		c.seq = nlh->nlmsg_seq;
		c.pid = nlh->nlmsg_pid;
		km_policy_notify(xp, p->dir, &c);
L
Linus Torvalds 已提交
1649 1650
	}

C
Catherine Zhang 已提交
1651
out:
1652
	xfrm_pol_put(xp);
L
Linus Torvalds 已提交
1653 1654 1655
	return err;
}

1656
static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1657
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1658
{
1659
	struct net *net = sock_net(skb->sk);
1660
	struct km_event c;
1661
	struct xfrm_usersa_flush *p = nlmsg_data(nlh);
J
Joy Latten 已提交
1662
	struct xfrm_audit audit_info;
1663
	int err;
L
Linus Torvalds 已提交
1664

1665 1666 1667
	audit_info.loginuid = audit_get_loginuid(current);
	audit_info.sessionid = audit_get_sessionid(current);
	security_task_getsecid(current, &audit_info.secid);
1668
	err = xfrm_state_flush(net, p->proto, &audit_info);
1669 1670 1671
	if (err) {
		if (err == -ESRCH) /* empty table */
			return 0;
1672
		return err;
1673
	}
1674
	c.data.proto = p->proto;
1675
	c.event = nlh->nlmsg_type;
1676 1677
	c.seq = nlh->nlmsg_seq;
	c.pid = nlh->nlmsg_pid;
1678
	c.net = net;
1679 1680
	km_state_notify(NULL, &c);

L
Linus Torvalds 已提交
1681 1682 1683
	return 0;
}

1684
static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x)
1685
{
1686 1687 1688 1689
	size_t replay_size = x->replay_esn ?
			      xfrm_replay_state_esn_len(x->replay_esn) :
			      sizeof(struct xfrm_replay_state);

1690
	return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
1691
	       + nla_total_size(replay_size)
1692
	       + nla_total_size(sizeof(struct xfrm_lifetime_cur))
1693
	       + nla_total_size(sizeof(struct xfrm_mark))
1694 1695 1696
	       + nla_total_size(4) /* XFRM_AE_RTHR */
	       + nla_total_size(4); /* XFRM_AE_ETHR */
}
J
Jamal Hadi Salim 已提交
1697

1698
static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
J
Jamal Hadi Salim 已提交
1699 1700 1701
{
	struct xfrm_aevent_id *id;
	struct nlmsghdr *nlh;
1702
	int err;
J
Jamal Hadi Salim 已提交
1703

1704 1705 1706
	nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
J
Jamal Hadi Salim 已提交
1707

1708
	id = nlmsg_data(nlh);
1709
	memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr));
J
Jamal Hadi Salim 已提交
1710 1711 1712
	id->sa_id.spi = x->id.spi;
	id->sa_id.family = x->props.family;
	id->sa_id.proto = x->id.proto;
1713 1714
	memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr));
	id->reqid = x->props.reqid;
J
Jamal Hadi Salim 已提交
1715 1716
	id->flags = c->data.aevent;

1717
	if (x->replay_esn) {
1718 1719 1720
		err = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
			      xfrm_replay_state_esn_len(x->replay_esn),
			      x->replay_esn);
1721
	} else {
1722 1723
		err = nla_put(skb, XFRMA_REPLAY_VAL, sizeof(x->replay),
			      &x->replay);
1724
	}
1725 1726 1727 1728 1729
	if (err)
		goto out_cancel;
	err = nla_put(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft);
	if (err)
		goto out_cancel;
J
Jamal Hadi Salim 已提交
1730

1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
	if (id->flags & XFRM_AE_RTHR) {
		err = nla_put_u32(skb, XFRMA_REPLAY_THRESH, x->replay_maxdiff);
		if (err)
			goto out_cancel;
	}
	if (id->flags & XFRM_AE_ETHR) {
		err = nla_put_u32(skb, XFRMA_ETIMER_THRESH,
				  x->replay_maxage * 10 / HZ);
		if (err)
			goto out_cancel;
	}
	err = xfrm_mark_put(skb, &x->mark);
	if (err)
		goto out_cancel;
1745

1746
	return nlmsg_end(skb, nlh);
J
Jamal Hadi Salim 已提交
1747

1748
out_cancel:
1749
	nlmsg_cancel(skb, nlh);
1750
	return err;
J
Jamal Hadi Salim 已提交
1751 1752
}

1753
static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1754
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1755
{
1756
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1757 1758 1759 1760
	struct xfrm_state *x;
	struct sk_buff *r_skb;
	int err;
	struct km_event c;
1761 1762
	u32 mark;
	struct xfrm_mark m;
1763
	struct xfrm_aevent_id *p = nlmsg_data(nlh);
J
Jamal Hadi Salim 已提交
1764 1765
	struct xfrm_usersa_id *id = &p->sa_id;

1766 1767 1768
	mark = xfrm_mark_get(attrs, &m);

	x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
1769
	if (x == NULL)
J
Jamal Hadi Salim 已提交
1770
		return -ESRCH;
1771 1772 1773 1774 1775

	r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
	if (r_skb == NULL) {
		xfrm_state_put(x);
		return -ENOMEM;
J
Jamal Hadi Salim 已提交
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789
	}

	/*
	 * XXX: is this lock really needed - none of the other
	 * gets lock (the concern is things getting updated
	 * while we are still reading) - jhs
	*/
	spin_lock_bh(&x->lock);
	c.data.aevent = p->flags;
	c.seq = nlh->nlmsg_seq;
	c.pid = nlh->nlmsg_pid;

	if (build_aevent(r_skb, x, &c) < 0)
		BUG();
1790
	err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).pid);
J
Jamal Hadi Salim 已提交
1791 1792 1793 1794 1795
	spin_unlock_bh(&x->lock);
	xfrm_state_put(x);
	return err;
}

1796
static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1797
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1798
{
1799
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1800 1801 1802
	struct xfrm_state *x;
	struct km_event c;
	int err = - EINVAL;
1803 1804
	u32 mark = 0;
	struct xfrm_mark m;
1805
	struct xfrm_aevent_id *p = nlmsg_data(nlh);
1806
	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
1807
	struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
1808
	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
J
Jamal Hadi Salim 已提交
1809

1810
	if (!lt && !rp && !re)
J
Jamal Hadi Salim 已提交
1811 1812 1813 1814 1815 1816
		return err;

	/* pedantic mode - thou shalt sayeth replaceth */
	if (!(nlh->nlmsg_flags&NLM_F_REPLACE))
		return err;

1817 1818 1819
	mark = xfrm_mark_get(attrs, &m);

	x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family);
J
Jamal Hadi Salim 已提交
1820 1821 1822 1823 1824 1825
	if (x == NULL)
		return -ESRCH;

	if (x->km.state != XFRM_STATE_VALID)
		goto out;

1826 1827 1828 1829
	err = xfrm_replay_verify_len(x->replay_esn, rp);
	if (err)
		goto out;

J
Jamal Hadi Salim 已提交
1830
	spin_lock_bh(&x->lock);
1831
	xfrm_update_ae_params(x, attrs);
J
Jamal Hadi Salim 已提交
1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844
	spin_unlock_bh(&x->lock);

	c.event = nlh->nlmsg_type;
	c.seq = nlh->nlmsg_seq;
	c.pid = nlh->nlmsg_pid;
	c.data.aevent = XFRM_AE_CU;
	km_state_notify(x, &c);
	err = 0;
out:
	xfrm_state_put(x);
	return err;
}

1845
static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1846
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1847
{
1848
	struct net *net = sock_net(skb->sk);
1849
	struct km_event c;
1850
	u8 type = XFRM_POLICY_TYPE_MAIN;
1851
	int err;
J
Joy Latten 已提交
1852
	struct xfrm_audit audit_info;
1853

1854
	err = copy_from_user_policy_type(&type, attrs);
1855 1856
	if (err)
		return err;
1857

1858 1859 1860
	audit_info.loginuid = audit_get_loginuid(current);
	audit_info.sessionid = audit_get_sessionid(current);
	security_task_getsecid(current, &audit_info.secid);
1861
	err = xfrm_policy_flush(net, type, &audit_info);
1862 1863 1864
	if (err) {
		if (err == -ESRCH) /* empty table */
			return 0;
1865
		return err;
1866 1867
	}

1868
	c.data.type = type;
1869
	c.event = nlh->nlmsg_type;
1870 1871
	c.seq = nlh->nlmsg_seq;
	c.pid = nlh->nlmsg_pid;
1872
	c.net = net;
1873
	km_policy_notify(NULL, 0, &c);
L
Linus Torvalds 已提交
1874 1875 1876
	return 0;
}

1877
static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1878
		struct nlattr **attrs)
1879
{
1880
	struct net *net = sock_net(skb->sk);
1881
	struct xfrm_policy *xp;
1882
	struct xfrm_user_polexpire *up = nlmsg_data(nlh);
1883
	struct xfrm_userpolicy_info *p = &up->pol;
1884
	u8 type = XFRM_POLICY_TYPE_MAIN;
1885
	int err = -ENOENT;
1886 1887
	struct xfrm_mark m;
	u32 mark = xfrm_mark_get(attrs, &m);
1888

1889
	err = copy_from_user_policy_type(&type, attrs);
1890 1891 1892
	if (err)
		return err;

1893 1894 1895 1896
	err = verify_policy_dir(p->dir);
	if (err)
		return err;

1897
	if (p->index)
1898
		xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err);
1899
	else {
1900
		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1901
		struct xfrm_sec_ctx *ctx;
1902

1903
		err = verify_sec_ctx_len(attrs);
1904 1905 1906
		if (err)
			return err;

1907
		ctx = NULL;
1908
		if (rt) {
1909
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1910

1911 1912
			err = security_xfrm_policy_alloc(&ctx, uctx);
			if (err)
1913
				return err;
1914
		}
1915
		xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir,
1916
					   &p->sel, ctx, 0, &err);
1917
		security_xfrm_policy_free(ctx);
1918 1919
	}
	if (xp == NULL)
1920
		return -ENOENT;
1921

1922
	if (unlikely(xp->walk.dead))
1923 1924 1925 1926
		goto out;

	err = 0;
	if (up->hard) {
1927 1928 1929 1930 1931
		uid_t loginuid = audit_get_loginuid(current);
		u32 sessionid = audit_get_sessionid(current);
		u32 sid;

		security_task_getsecid(current, &sid);
1932
		xfrm_policy_delete(xp, p->dir);
1933
		xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
1934

1935 1936
	} else {
		// reset the timers here?
S
stephen hemminger 已提交
1937
		WARN(1, "Dont know what to do with soft policy expire\n");
1938 1939 1940 1941 1942 1943 1944 1945
	}
	km_policy_expired(xp, p->dir, up->hard, current->pid);

out:
	xfrm_pol_put(xp);
	return err;
}

1946
static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1947
		struct nlattr **attrs)
1948
{
1949
	struct net *net = sock_net(skb->sk);
1950 1951
	struct xfrm_state *x;
	int err;
1952
	struct xfrm_user_expire *ue = nlmsg_data(nlh);
1953
	struct xfrm_usersa_info *p = &ue->state;
1954
	struct xfrm_mark m;
1955
	u32 mark = xfrm_mark_get(attrs, &m);
1956

1957
	x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family);
1958

1959
	err = -ENOENT;
1960 1961 1962 1963
	if (x == NULL)
		return err;

	spin_lock_bh(&x->lock);
1964
	err = -EINVAL;
1965 1966 1967 1968
	if (x->km.state != XFRM_STATE_VALID)
		goto out;
	km_state_expired(x, ue->hard, current->pid);

J
Joy Latten 已提交
1969
	if (ue->hard) {
1970 1971 1972 1973 1974
		uid_t loginuid = audit_get_loginuid(current);
		u32 sessionid = audit_get_sessionid(current);
		u32 sid;

		security_task_getsecid(current, &sid);
1975
		__xfrm_state_delete(x);
1976
		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
1977
	}
1978
	err = 0;
1979 1980 1981 1982 1983 1984
out:
	spin_unlock_bh(&x->lock);
	xfrm_state_put(x);
	return err;
}

1985
static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
1986
		struct nlattr **attrs)
1987
{
1988
	struct net *net = sock_net(skb->sk);
1989 1990 1991
	struct xfrm_policy *xp;
	struct xfrm_user_tmpl *ut;
	int i;
1992
	struct nlattr *rt = attrs[XFRMA_TMPL];
1993
	struct xfrm_mark mark;
1994

1995
	struct xfrm_user_acquire *ua = nlmsg_data(nlh);
1996
	struct xfrm_state *x = xfrm_state_alloc(net);
1997 1998 1999
	int err = -ENOMEM;

	if (!x)
I
Ilpo Järvinen 已提交
2000
		goto nomem;
2001

2002 2003
	xfrm_mark_get(attrs, &mark);

2004
	err = verify_newpolicy_info(&ua->policy);
I
Ilpo Järvinen 已提交
2005 2006
	if (err)
		goto bad_policy;
2007 2008

	/*   build an XP */
2009
	xp = xfrm_policy_construct(net, &ua->policy, attrs, &err);
I
Ilpo Järvinen 已提交
2010 2011
	if (!xp)
		goto free_state;
2012 2013 2014 2015

	memcpy(&x->id, &ua->id, sizeof(ua->id));
	memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr));
	memcpy(&x->sel, &ua->sel, sizeof(ua->sel));
2016 2017
	xp->mark.m = x->mark.m = mark.m;
	xp->mark.v = x->mark.v = mark.v;
2018
	ut = nla_data(rt);
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
	/* extract the templates and for each call km_key */
	for (i = 0; i < xp->xfrm_nr; i++, ut++) {
		struct xfrm_tmpl *t = &xp->xfrm_vec[i];
		memcpy(&x->id, &t->id, sizeof(x->id));
		x->props.mode = t->mode;
		x->props.reqid = t->reqid;
		x->props.family = ut->family;
		t->aalgos = ua->aalgos;
		t->ealgos = ua->ealgos;
		t->calgos = ua->calgos;
		err = km_query(x, t, xp);

	}

	kfree(x);
	kfree(xp);

	return 0;
I
Ilpo Järvinen 已提交
2037 2038

bad_policy:
S
stephen hemminger 已提交
2039
	WARN(1, "BAD policy passed\n");
I
Ilpo Järvinen 已提交
2040 2041 2042 2043
free_state:
	kfree(x);
nomem:
	return err;
2044 2045
}

2046 2047
#ifdef CONFIG_XFRM_MIGRATE
static int copy_from_user_migrate(struct xfrm_migrate *ma,
2048
				  struct xfrm_kmaddress *k,
2049
				  struct nlattr **attrs, int *num)
2050
{
2051
	struct nlattr *rt = attrs[XFRMA_MIGRATE];
2052 2053 2054
	struct xfrm_user_migrate *um;
	int i, num_migrate;

2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
	if (k != NULL) {
		struct xfrm_user_kmaddress *uk;

		uk = nla_data(attrs[XFRMA_KMADDRESS]);
		memcpy(&k->local, &uk->local, sizeof(k->local));
		memcpy(&k->remote, &uk->remote, sizeof(k->remote));
		k->family = uk->family;
		k->reserved = uk->reserved;
	}

2065 2066
	um = nla_data(rt);
	num_migrate = nla_len(rt) / sizeof(*um);
2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089

	if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH)
		return -EINVAL;

	for (i = 0; i < num_migrate; i++, um++, ma++) {
		memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr));
		memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr));
		memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr));
		memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr));

		ma->proto = um->proto;
		ma->mode = um->mode;
		ma->reqid = um->reqid;

		ma->old_family = um->old_family;
		ma->new_family = um->new_family;
	}

	*num = i;
	return 0;
}

static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
2090
			   struct nlattr **attrs)
2091
{
2092
	struct xfrm_userpolicy_id *pi = nlmsg_data(nlh);
2093
	struct xfrm_migrate m[XFRM_MAX_DEPTH];
2094
	struct xfrm_kmaddress km, *kmp;
2095 2096 2097 2098
	u8 type;
	int err;
	int n = 0;

2099
	if (attrs[XFRMA_MIGRATE] == NULL)
2100
		return -EINVAL;
2101

2102 2103
	kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL;

2104
	err = copy_from_user_policy_type(&type, attrs);
2105 2106 2107
	if (err)
		return err;

2108
	err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n);
2109 2110 2111 2112 2113 2114
	if (err)
		return err;

	if (!n)
		return 0;

2115
	xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp);
2116 2117 2118 2119 2120

	return 0;
}
#else
static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
2121
			   struct nlattr **attrs)
2122 2123 2124 2125 2126 2127
{
	return -ENOPROTOOPT;
}
#endif

#ifdef CONFIG_XFRM_MIGRATE
2128
static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb)
2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142
{
	struct xfrm_user_migrate um;

	memset(&um, 0, sizeof(um));
	um.proto = m->proto;
	um.mode = m->mode;
	um.reqid = m->reqid;
	um.old_family = m->old_family;
	memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr));
	memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr));
	um.new_family = m->new_family;
	memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr));
	memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr));

2143
	return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um);
2144 2145
}

2146
static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb)
2147 2148 2149 2150 2151 2152 2153
{
	struct xfrm_user_kmaddress uk;

	memset(&uk, 0, sizeof(uk));
	uk.family = k->family;
	uk.reserved = k->reserved;
	memcpy(&uk.local, &k->local, sizeof(uk.local));
2154
	memcpy(&uk.remote, &k->remote, sizeof(uk.remote));
2155 2156 2157 2158 2159

	return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk);
}

static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma)
2160 2161
{
	return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))
2162 2163 2164
	      + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0)
	      + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)
	      + userpolicy_type_attrsize();
2165 2166
}

2167 2168 2169
static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
			 int num_migrate, const struct xfrm_kmaddress *k,
			 const struct xfrm_selector *sel, u8 dir, u8 type)
2170
{
2171
	const struct xfrm_migrate *mp;
2172 2173
	struct xfrm_userpolicy_id *pol_id;
	struct nlmsghdr *nlh;
2174
	int i, err;
2175

2176 2177 2178
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
2179

2180
	pol_id = nlmsg_data(nlh);
2181 2182 2183 2184 2185
	/* copy data from selector, dir, and type to the pol_id */
	memset(pol_id, 0, sizeof(*pol_id));
	memcpy(&pol_id->sel, sel, sizeof(pol_id->sel));
	pol_id->dir = dir;

2186 2187 2188 2189 2190 2191 2192 2193
	if (k != NULL) {
		err = copy_to_user_kmaddress(k, skb);
		if (err)
			goto out_cancel;
	}
	err = copy_to_user_policy_type(type, skb);
	if (err)
		goto out_cancel;
2194
	for (i = 0, mp = m ; i < num_migrate; i++, mp++) {
2195 2196 2197
		err = copy_to_user_migrate(mp, skb);
		if (err)
			goto out_cancel;
2198 2199
	}

2200
	return nlmsg_end(skb, nlh);
2201 2202

out_cancel:
2203
	nlmsg_cancel(skb, nlh);
2204
	return err;
2205 2206
}

2207 2208 2209
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
			     const struct xfrm_migrate *m, int num_migrate,
			     const struct xfrm_kmaddress *k)
2210
{
2211
	struct net *net = &init_net;
2212 2213
	struct sk_buff *skb;

2214
	skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC);
2215 2216 2217 2218
	if (skb == NULL)
		return -ENOMEM;

	/* build migrate */
2219
	if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0)
2220 2221
		BUG();

2222
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC);
2223 2224
}
#else
2225 2226 2227
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
			     const struct xfrm_migrate *m, int num_migrate,
			     const struct xfrm_kmaddress *k)
2228 2229 2230 2231
{
	return -ENOPROTOOPT;
}
#endif
J
Jamal Hadi Salim 已提交
2232

2233
#define XMSGSIZE(type) sizeof(struct type)
2234 2235

static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
2236
	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
2237 2238 2239 2240 2241 2242
	[XFRM_MSG_DELSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),
	[XFRM_MSG_GETSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),
	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),
	[XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
	[XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info),
2243
	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire),
2244
	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire),
2245
	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),
2246
	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
2247
	[XFRM_MSG_POLEXPIRE   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire),
2248
	[XFRM_MSG_FLUSHSA     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush),
2249
	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0,
J
Jamal Hadi Salim 已提交
2250 2251
	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
2252
	[XFRM_MSG_REPORT      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
2253
	[XFRM_MSG_MIGRATE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
2254 2255
	[XFRM_MSG_GETSADINFO  - XFRM_MSG_BASE] = sizeof(u32),
	[XFRM_MSG_GETSPDINFO  - XFRM_MSG_BASE] = sizeof(u32),
L
Linus Torvalds 已提交
2256 2257
};

2258 2259
#undef XMSGSIZE

2260
static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
J
jamal 已提交
2261 2262 2263 2264
	[XFRMA_SA]		= { .len = sizeof(struct xfrm_usersa_info)},
	[XFRMA_POLICY]		= { .len = sizeof(struct xfrm_userpolicy_info)},
	[XFRMA_LASTUSED]	= { .type = NLA_U64},
	[XFRMA_ALG_AUTH_TRUNC]	= { .len = sizeof(struct xfrm_algo_auth)},
2265
	[XFRMA_ALG_AEAD]	= { .len = sizeof(struct xfrm_algo_aead) },
2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279
	[XFRMA_ALG_AUTH]	= { .len = sizeof(struct xfrm_algo) },
	[XFRMA_ALG_CRYPT]	= { .len = sizeof(struct xfrm_algo) },
	[XFRMA_ALG_COMP]	= { .len = sizeof(struct xfrm_algo) },
	[XFRMA_ENCAP]		= { .len = sizeof(struct xfrm_encap_tmpl) },
	[XFRMA_TMPL]		= { .len = sizeof(struct xfrm_user_tmpl) },
	[XFRMA_SEC_CTX]		= { .len = sizeof(struct xfrm_sec_ctx) },
	[XFRMA_LTIME_VAL]	= { .len = sizeof(struct xfrm_lifetime_cur) },
	[XFRMA_REPLAY_VAL]	= { .len = sizeof(struct xfrm_replay_state) },
	[XFRMA_REPLAY_THRESH]	= { .type = NLA_U32 },
	[XFRMA_ETIMER_THRESH]	= { .type = NLA_U32 },
	[XFRMA_SRCADDR]		= { .len = sizeof(xfrm_address_t) },
	[XFRMA_COADDR]		= { .len = sizeof(xfrm_address_t) },
	[XFRMA_POLICY_TYPE]	= { .len = sizeof(struct xfrm_userpolicy_type)},
	[XFRMA_MIGRATE]		= { .len = sizeof(struct xfrm_user_migrate) },
2280
	[XFRMA_KMADDRESS]	= { .len = sizeof(struct xfrm_user_kmaddress) },
2281
	[XFRMA_MARK]		= { .len = sizeof(struct xfrm_mark) },
2282
	[XFRMA_TFCPAD]		= { .type = NLA_U32 },
2283
	[XFRMA_REPLAY_ESN_VAL]	= { .len = sizeof(struct xfrm_replay_state_esn) },
2284 2285
};

L
Linus Torvalds 已提交
2286
static struct xfrm_link {
2287
	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
L
Linus Torvalds 已提交
2288
	int (*dump)(struct sk_buff *, struct netlink_callback *);
2289
	int (*done)(struct netlink_callback *);
2290 2291 2292 2293
} xfrm_dispatch[XFRM_NR_MSGTYPES] = {
	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = { .doit = xfrm_add_sa        },
	[XFRM_MSG_DELSA       - XFRM_MSG_BASE] = { .doit = xfrm_del_sa        },
	[XFRM_MSG_GETSA       - XFRM_MSG_BASE] = { .doit = xfrm_get_sa,
2294 2295
						   .dump = xfrm_dump_sa,
						   .done = xfrm_dump_sa_done  },
2296 2297 2298
	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
	[XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy    },
	[XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
2299 2300
						   .dump = xfrm_dump_policy,
						   .done = xfrm_dump_policy_done },
2301
	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
2302
	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire   },
2303
	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire },
2304 2305
	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = { .doit = xfrm_add_sa        },
2306
	[XFRM_MSG_POLEXPIRE   - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire},
2307 2308
	[XFRM_MSG_FLUSHSA     - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa      },
	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy  },
J
Jamal Hadi Salim 已提交
2309 2310
	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = { .doit = xfrm_new_ae  },
	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = { .doit = xfrm_get_ae  },
2311
	[XFRM_MSG_MIGRATE     - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate    },
2312
	[XFRM_MSG_GETSADINFO  - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo   },
J
Jamal Hadi Salim 已提交
2313
	[XFRM_MSG_GETSPDINFO  - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo   },
L
Linus Torvalds 已提交
2314 2315
};

2316
static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
L
Linus Torvalds 已提交
2317
{
2318
	struct net *net = sock_net(skb->sk);
2319
	struct nlattr *attrs[XFRMA_MAX+1];
L
Linus Torvalds 已提交
2320
	struct xfrm_link *link;
2321
	int type, err;
L
Linus Torvalds 已提交
2322 2323 2324

	type = nlh->nlmsg_type;
	if (type > XFRM_MSG_MAX)
2325
		return -EINVAL;
L
Linus Torvalds 已提交
2326 2327 2328 2329 2330

	type -= XFRM_MSG_BASE;
	link = &xfrm_dispatch[type];

	/* All operations require privileges, even GET */
2331
	if (!capable(CAP_NET_ADMIN))
2332
		return -EPERM;
L
Linus Torvalds 已提交
2333

2334 2335
	if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
	     type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) &&
2336
	    (nlh->nlmsg_flags & NLM_F_DUMP)) {
L
Linus Torvalds 已提交
2337
		if (link->dump == NULL)
2338
			return -EINVAL;
2339

2340 2341 2342 2343 2344 2345 2346
		{
			struct netlink_dump_control c = {
				.dump = link->dump,
				.done = link->done,
			};
			return netlink_dump_start(net->xfrm.nlsk, skb, nlh, &c);
		}
L
Linus Torvalds 已提交
2347 2348
	}

2349
	err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
2350
			  xfrma_policy);
2351 2352
	if (err < 0)
		return err;
L
Linus Torvalds 已提交
2353 2354

	if (link->doit == NULL)
2355
		return -EINVAL;
L
Linus Torvalds 已提交
2356

2357
	return link->doit(skb, nlh, attrs);
L
Linus Torvalds 已提交
2358 2359
}

2360
static void xfrm_netlink_rcv(struct sk_buff *skb)
L
Linus Torvalds 已提交
2361
{
2362 2363 2364
	mutex_lock(&xfrm_cfg_mutex);
	netlink_rcv_skb(skb, &xfrm_user_rcv_msg);
	mutex_unlock(&xfrm_cfg_mutex);
L
Linus Torvalds 已提交
2365 2366
}

2367 2368
static inline size_t xfrm_expire_msgsize(void)
{
2369 2370
	return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
	       + nla_total_size(sizeof(struct xfrm_mark));
2371 2372
}

2373
static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
L
Linus Torvalds 已提交
2374 2375 2376
{
	struct xfrm_user_expire *ue;
	struct nlmsghdr *nlh;
2377
	int err;
L
Linus Torvalds 已提交
2378

2379 2380 2381
	nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_EXPIRE, sizeof(*ue), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2382

2383
	ue = nlmsg_data(nlh);
L
Linus Torvalds 已提交
2384
	copy_to_user_state(x, &ue->state);
J
Jamal Hadi Salim 已提交
2385
	ue->hard = (c->data.hard != 0) ? 1 : 0;
L
Linus Torvalds 已提交
2386

2387 2388 2389
	err = xfrm_mark_put(skb, &x->mark);
	if (err)
		return err;
2390

2391
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2392 2393
}

2394
static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c)
L
Linus Torvalds 已提交
2395
{
2396
	struct net *net = xs_net(x);
L
Linus Torvalds 已提交
2397 2398
	struct sk_buff *skb;

2399
	skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC);
L
Linus Torvalds 已提交
2400 2401 2402
	if (skb == NULL)
		return -ENOMEM;

2403 2404 2405 2406
	if (build_expire(skb, x, c) < 0) {
		kfree_skb(skb);
		return -EMSGSIZE;
	}
L
Linus Torvalds 已提交
2407

2408
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2409 2410
}

2411
static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c)
J
Jamal Hadi Salim 已提交
2412
{
2413
	struct net *net = xs_net(x);
J
Jamal Hadi Salim 已提交
2414 2415
	struct sk_buff *skb;

2416
	skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
2417 2418 2419 2420 2421 2422
	if (skb == NULL)
		return -ENOMEM;

	if (build_aevent(skb, x, c) < 0)
		BUG();

2423
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
2424 2425
}

2426
static int xfrm_notify_sa_flush(const struct km_event *c)
2427
{
2428
	struct net *net = c->net;
2429 2430 2431
	struct xfrm_usersa_flush *p;
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2432
	int len = NLMSG_ALIGN(sizeof(struct xfrm_usersa_flush));
2433

2434
	skb = nlmsg_new(len, GFP_ATOMIC);
2435 2436 2437
	if (skb == NULL)
		return -ENOMEM;

2438 2439 2440 2441 2442
	nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHSA, sizeof(*p), 0);
	if (nlh == NULL) {
		kfree_skb(skb);
		return -EMSGSIZE;
	}
2443

2444
	p = nlmsg_data(nlh);
2445
	p->proto = c->data.proto;
2446

2447
	nlmsg_end(skb, nlh);
2448

2449
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
2450 2451
}

2452
static inline size_t xfrm_sa_len(struct xfrm_state *x)
2453
{
2454
	size_t l = 0;
2455 2456
	if (x->aead)
		l += nla_total_size(aead_len(x->aead));
2457 2458 2459 2460 2461
	if (x->aalg) {
		l += nla_total_size(sizeof(struct xfrm_algo) +
				    (x->aalg->alg_key_len + 7) / 8);
		l += nla_total_size(xfrm_alg_auth_len(x->aalg));
	}
2462
	if (x->ealg)
2463
		l += nla_total_size(xfrm_alg_len(x->ealg));
2464
	if (x->calg)
2465
		l += nla_total_size(sizeof(*x->calg));
2466
	if (x->encap)
2467
		l += nla_total_size(sizeof(*x->encap));
2468 2469
	if (x->tfcpad)
		l += nla_total_size(sizeof(x->tfcpad));
2470 2471
	if (x->replay_esn)
		l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn));
2472 2473 2474 2475 2476 2477
	if (x->security)
		l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
				    x->security->ctx_len);
	if (x->coaddr)
		l += nla_total_size(sizeof(*x->coaddr));

2478 2479
	/* Must count x->lastused as it may become non-zero behind our back. */
	l += nla_total_size(sizeof(u64));
2480 2481 2482 2483

	return l;
}

2484
static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c)
2485
{
2486
	struct net *net = xs_net(x);
2487
	struct xfrm_usersa_info *p;
2488
	struct xfrm_usersa_id *id;
2489 2490 2491
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
	int len = xfrm_sa_len(x);
2492
	int headlen, err;
2493 2494 2495

	headlen = sizeof(*p);
	if (c->event == XFRM_MSG_DELSA) {
2496
		len += nla_total_size(headlen);
2497
		headlen = sizeof(*id);
2498
		len += nla_total_size(sizeof(struct xfrm_mark));
2499
	}
2500
	len += NLMSG_ALIGN(headlen);
2501

2502
	skb = nlmsg_new(len, GFP_ATOMIC);
2503 2504 2505
	if (skb == NULL)
		return -ENOMEM;

2506
	nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0);
2507
	err = -EMSGSIZE;
2508
	if (nlh == NULL)
2509
		goto out_free_skb;
2510

2511
	p = nlmsg_data(nlh);
2512
	if (c->event == XFRM_MSG_DELSA) {
2513 2514
		struct nlattr *attr;

2515
		id = nlmsg_data(nlh);
2516 2517 2518 2519 2520
		memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
		id->spi = x->id.spi;
		id->family = x->props.family;
		id->proto = x->id.proto;

2521
		attr = nla_reserve(skb, XFRMA_SA, sizeof(*p));
2522
		err = -EMSGSIZE;
2523
		if (attr == NULL)
2524
			goto out_free_skb;
2525 2526

		p = nla_data(attr);
2527
	}
2528 2529 2530
	err = copy_to_user_state_extra(x, p, skb);
	if (err)
		goto out_free_skb;
2531

2532
	nlmsg_end(skb, nlh);
2533

2534
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
2535

2536
out_free_skb:
2537
	kfree_skb(skb);
2538
	return err;
2539 2540
}

2541
static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c)
2542 2543 2544
{

	switch (c->event) {
2545
	case XFRM_MSG_EXPIRE:
2546
		return xfrm_exp_state_notify(x, c);
J
Jamal Hadi Salim 已提交
2547 2548
	case XFRM_MSG_NEWAE:
		return xfrm_aevent_state_notify(x, c);
2549 2550 2551
	case XFRM_MSG_DELSA:
	case XFRM_MSG_UPDSA:
	case XFRM_MSG_NEWSA:
2552
		return xfrm_notify_sa(x, c);
2553
	case XFRM_MSG_FLUSHSA:
2554 2555
		return xfrm_notify_sa_flush(c);
	default:
S
stephen hemminger 已提交
2556 2557 2558
		printk(KERN_NOTICE "xfrm_user: Unknown SA event %d\n",
		       c->event);
		break;
2559 2560 2561 2562 2563 2564
	}

	return 0;

}

2565 2566 2567 2568 2569
static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x,
					  struct xfrm_policy *xp)
{
	return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire))
	       + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
2570
	       + nla_total_size(sizeof(struct xfrm_mark))
2571 2572 2573 2574
	       + nla_total_size(xfrm_user_sec_ctx_size(x->security))
	       + userpolicy_type_attrsize();
}

L
Linus Torvalds 已提交
2575 2576 2577 2578
static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
			 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
			 int dir)
{
2579
	__u32 seq = xfrm_get_acqseq();
L
Linus Torvalds 已提交
2580 2581
	struct xfrm_user_acquire *ua;
	struct nlmsghdr *nlh;
2582
	int err;
L
Linus Torvalds 已提交
2583

2584 2585 2586
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2587

2588
	ua = nlmsg_data(nlh);
L
Linus Torvalds 已提交
2589 2590 2591 2592 2593 2594 2595 2596 2597
	memcpy(&ua->id, &x->id, sizeof(ua->id));
	memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr));
	memcpy(&ua->sel, &x->sel, sizeof(ua->sel));
	copy_to_user_policy(xp, &ua->policy, dir);
	ua->aalgos = xt->aalgos;
	ua->ealgos = xt->ealgos;
	ua->calgos = xt->calgos;
	ua->seq = x->km.seq = seq;

2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608
	err = copy_to_user_tmpl(xp, skb);
	if (!err)
		err = copy_to_user_state_sec_ctx(x, skb);
	if (!err)
		err = copy_to_user_policy_type(xp->type, skb);
	if (!err)
		err = xfrm_mark_put(skb, &xp->mark);
	if (err) {
		nlmsg_cancel(skb, nlh);
		return err;
	}
L
Linus Torvalds 已提交
2609

2610
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2611 2612 2613 2614 2615
}

static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
			     struct xfrm_policy *xp, int dir)
{
2616
	struct net *net = xs_net(x);
L
Linus Torvalds 已提交
2617 2618
	struct sk_buff *skb;

2619
	skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC);
L
Linus Torvalds 已提交
2620 2621 2622 2623 2624 2625
	if (skb == NULL)
		return -ENOMEM;

	if (build_acquire(skb, x, xt, xp, dir) < 0)
		BUG();

2626
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2627 2628 2629 2630 2631
}

/* User gives us xfrm_user_policy_info followed by an array of 0
 * or more templates.
 */
2632
static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
L
Linus Torvalds 已提交
2633 2634
					       u8 *data, int len, int *dir)
{
2635
	struct net *net = sock_net(sk);
L
Linus Torvalds 已提交
2636 2637 2638 2639 2640
	struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
	struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
	struct xfrm_policy *xp;
	int nr;

2641
	switch (sk->sk_family) {
L
Linus Torvalds 已提交
2642 2643 2644 2645 2646 2647
	case AF_INET:
		if (opt != IP_XFRM_POLICY) {
			*dir = -EOPNOTSUPP;
			return NULL;
		}
		break;
E
Eric Dumazet 已提交
2648
#if IS_ENABLED(CONFIG_IPV6)
L
Linus Torvalds 已提交
2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667
	case AF_INET6:
		if (opt != IPV6_XFRM_POLICY) {
			*dir = -EOPNOTSUPP;
			return NULL;
		}
		break;
#endif
	default:
		*dir = -EINVAL;
		return NULL;
	}

	*dir = -EINVAL;

	if (len < sizeof(*p) ||
	    verify_newpolicy_info(p))
		return NULL;

	nr = ((len - sizeof(*p)) / sizeof(*ut));
2668
	if (validate_tmpl(nr, ut, p->sel.family))
L
Linus Torvalds 已提交
2669 2670
		return NULL;

2671 2672 2673
	if (p->dir > XFRM_POLICY_OUT)
		return NULL;

2674
	xp = xfrm_policy_alloc(net, GFP_ATOMIC);
L
Linus Torvalds 已提交
2675 2676 2677 2678 2679 2680
	if (xp == NULL) {
		*dir = -ENOBUFS;
		return NULL;
	}

	copy_from_user_policy(xp, p);
2681
	xp->type = XFRM_POLICY_TYPE_MAIN;
L
Linus Torvalds 已提交
2682 2683 2684 2685 2686 2687 2688
	copy_templates(xp, ut, nr);

	*dir = p->dir;

	return xp;
}

2689 2690 2691 2692 2693
static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp)
{
	return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire))
	       + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
	       + nla_total_size(xfrm_user_sec_ctx_size(xp->security))
2694
	       + nla_total_size(sizeof(struct xfrm_mark))
2695 2696 2697
	       + userpolicy_type_attrsize();
}

L
Linus Torvalds 已提交
2698
static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
2699
			   int dir, const struct km_event *c)
L
Linus Torvalds 已提交
2700 2701
{
	struct xfrm_user_polexpire *upe;
J
Jamal Hadi Salim 已提交
2702
	int hard = c->data.hard;
2703 2704
	struct nlmsghdr *nlh;
	int err;
L
Linus Torvalds 已提交
2705

2706 2707 2708
	nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2709

2710
	upe = nlmsg_data(nlh);
L
Linus Torvalds 已提交
2711
	copy_to_user_policy(xp, &upe->pol, dir);
2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722
	err = copy_to_user_tmpl(xp, skb);
	if (!err)
		err = copy_to_user_sec_ctx(xp, skb);
	if (!err)
		err = copy_to_user_policy_type(xp->type, skb);
	if (!err)
		err = xfrm_mark_put(skb, &xp->mark);
	if (err) {
		nlmsg_cancel(skb, nlh);
		return err;
	}
L
Linus Torvalds 已提交
2723 2724
	upe->hard = !!hard;

2725
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2726 2727
}

2728
static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
L
Linus Torvalds 已提交
2729
{
2730
	struct net *net = xp_net(xp);
L
Linus Torvalds 已提交
2731 2732
	struct sk_buff *skb;

2733
	skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC);
L
Linus Torvalds 已提交
2734 2735 2736
	if (skb == NULL)
		return -ENOMEM;

J
Jamal Hadi Salim 已提交
2737
	if (build_polexpire(skb, xp, dir, c) < 0)
L
Linus Torvalds 已提交
2738 2739
		BUG();

2740
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2741 2742
}

2743
static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c)
2744
{
2745
	int len = nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
2746
	struct net *net = xp_net(xp);
2747
	struct xfrm_userpolicy_info *p;
2748
	struct xfrm_userpolicy_id *id;
2749 2750
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2751
	int headlen, err;
2752 2753 2754

	headlen = sizeof(*p);
	if (c->event == XFRM_MSG_DELPOLICY) {
2755
		len += nla_total_size(headlen);
2756 2757
		headlen = sizeof(*id);
	}
2758
	len += userpolicy_type_attrsize();
2759
	len += nla_total_size(sizeof(struct xfrm_mark));
2760
	len += NLMSG_ALIGN(headlen);
2761

2762
	skb = nlmsg_new(len, GFP_ATOMIC);
2763 2764 2765
	if (skb == NULL)
		return -ENOMEM;

2766
	nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0);
2767
	err = -EMSGSIZE;
2768
	if (nlh == NULL)
2769
		goto out_free_skb;
2770

2771
	p = nlmsg_data(nlh);
2772
	if (c->event == XFRM_MSG_DELPOLICY) {
2773 2774
		struct nlattr *attr;

2775
		id = nlmsg_data(nlh);
2776 2777 2778 2779 2780 2781 2782
		memset(id, 0, sizeof(*id));
		id->dir = dir;
		if (c->data.byid)
			id->index = xp->index;
		else
			memcpy(&id->sel, &xp->selector, sizeof(id->sel));

2783
		attr = nla_reserve(skb, XFRMA_POLICY, sizeof(*p));
2784
		err = -EMSGSIZE;
2785
		if (attr == NULL)
2786
			goto out_free_skb;
2787 2788

		p = nla_data(attr);
2789
	}
2790 2791

	copy_to_user_policy(xp, p, dir);
2792 2793 2794 2795 2796 2797 2798
	err = copy_to_user_tmpl(xp, skb);
	if (!err)
		err = copy_to_user_policy_type(xp->type, skb);
	if (!err)
		err = xfrm_mark_put(skb, &xp->mark);
	if (err)
		goto out_free_skb;
2799

2800
	nlmsg_end(skb, nlh);
2801

2802
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
2803

2804
out_free_skb:
2805
	kfree_skb(skb);
2806
	return err;
2807 2808
}

2809
static int xfrm_notify_policy_flush(const struct km_event *c)
2810
{
2811
	struct net *net = c->net;
2812 2813
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2814
	int err;
2815

2816
	skb = nlmsg_new(userpolicy_type_attrsize(), GFP_ATOMIC);
2817 2818 2819
	if (skb == NULL)
		return -ENOMEM;

2820
	nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0, 0);
2821
	err = -EMSGSIZE;
2822
	if (nlh == NULL)
2823 2824 2825 2826
		goto out_free_skb;
	err = copy_to_user_policy_type(c->data.type, skb);
	if (err)
		goto out_free_skb;
2827

2828
	nlmsg_end(skb, nlh);
2829

2830
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
2831

2832
out_free_skb:
2833
	kfree_skb(skb);
2834
	return err;
2835 2836
}

2837
static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
2838 2839 2840
{

	switch (c->event) {
2841 2842 2843
	case XFRM_MSG_NEWPOLICY:
	case XFRM_MSG_UPDPOLICY:
	case XFRM_MSG_DELPOLICY:
2844
		return xfrm_notify_policy(xp, dir, c);
2845
	case XFRM_MSG_FLUSHPOLICY:
2846
		return xfrm_notify_policy_flush(c);
2847
	case XFRM_MSG_POLEXPIRE:
2848 2849
		return xfrm_exp_policy_notify(xp, dir, c);
	default:
S
stephen hemminger 已提交
2850 2851
		printk(KERN_NOTICE "xfrm_user: Unknown Policy event %d\n",
		       c->event);
2852 2853 2854 2855 2856 2857
	}

	return 0;

}

2858 2859 2860 2861 2862
static inline size_t xfrm_report_msgsize(void)
{
	return NLMSG_ALIGN(sizeof(struct xfrm_user_report));
}

2863 2864 2865 2866 2867 2868
static int build_report(struct sk_buff *skb, u8 proto,
			struct xfrm_selector *sel, xfrm_address_t *addr)
{
	struct xfrm_user_report *ur;
	struct nlmsghdr *nlh;

2869 2870 2871
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
2872

2873
	ur = nlmsg_data(nlh);
2874 2875 2876
	ur->proto = proto;
	memcpy(&ur->sel, sel, sizeof(ur->sel));

2877 2878 2879 2880 2881 2882 2883
	if (addr) {
		int err = nla_put(skb, XFRMA_COADDR, sizeof(*addr), addr);
		if (err) {
			nlmsg_cancel(skb, nlh);
			return err;
		}
	}
2884
	return nlmsg_end(skb, nlh);
2885 2886
}

2887 2888
static int xfrm_send_report(struct net *net, u8 proto,
			    struct xfrm_selector *sel, xfrm_address_t *addr)
2889 2890 2891
{
	struct sk_buff *skb;

2892
	skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC);
2893 2894 2895 2896 2897 2898
	if (skb == NULL)
		return -ENOMEM;

	if (build_report(skb, proto, sel, addr) < 0)
		BUG();

2899
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC);
2900 2901
}

2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934
static inline size_t xfrm_mapping_msgsize(void)
{
	return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping));
}

static int build_mapping(struct sk_buff *skb, struct xfrm_state *x,
			 xfrm_address_t *new_saddr, __be16 new_sport)
{
	struct xfrm_user_mapping *um;
	struct nlmsghdr *nlh;

	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0);
	if (nlh == NULL)
		return -EMSGSIZE;

	um = nlmsg_data(nlh);

	memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr));
	um->id.spi = x->id.spi;
	um->id.family = x->props.family;
	um->id.proto = x->id.proto;
	memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr));
	memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr));
	um->new_sport = new_sport;
	um->old_sport = x->encap->encap_sport;
	um->reqid = x->props.reqid;

	return nlmsg_end(skb, nlh);
}

static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
			     __be16 sport)
{
2935
	struct net *net = xs_net(x);
2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950
	struct sk_buff *skb;

	if (x->id.proto != IPPROTO_ESP)
		return -EINVAL;

	if (!x->encap)
		return -EINVAL;

	skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC);
	if (skb == NULL)
		return -ENOMEM;

	if (build_mapping(skb, x, ipaddr, sport) < 0)
		BUG();

2951
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC);
2952 2953
}

L
Linus Torvalds 已提交
2954 2955 2956 2957 2958 2959
static struct xfrm_mgr netlink_mgr = {
	.id		= "netlink",
	.notify		= xfrm_send_state_notify,
	.acquire	= xfrm_send_acquire,
	.compile_policy	= xfrm_compile_policy,
	.notify_policy	= xfrm_send_policy_notify,
2960
	.report		= xfrm_send_report,
2961
	.migrate	= xfrm_send_migrate,
2962
	.new_mapping	= xfrm_send_mapping,
L
Linus Torvalds 已提交
2963 2964
};

2965
static int __net_init xfrm_user_net_init(struct net *net)
L
Linus Torvalds 已提交
2966
{
2967
	struct sock *nlsk;
2968 2969 2970 2971
	struct netlink_kernel_cfg cfg = {
		.groups	= XFRMNLGRP_MAX,
		.input	= xfrm_netlink_rcv,
	};
2972

2973
	nlsk = netlink_kernel_create(net, NETLINK_XFRM, THIS_MODULE, &cfg);
2974
	if (nlsk == NULL)
L
Linus Torvalds 已提交
2975
		return -ENOMEM;
2976
	net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */
2977
	rcu_assign_pointer(net->xfrm.nlsk, nlsk);
L
Linus Torvalds 已提交
2978 2979 2980
	return 0;
}

2981
static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list)
L
Linus Torvalds 已提交
2982
{
2983 2984
	struct net *net;
	list_for_each_entry(net, net_exit_list, exit_list)
2985
		RCU_INIT_POINTER(net->xfrm.nlsk, NULL);
2986 2987 2988
	synchronize_net();
	list_for_each_entry(net, net_exit_list, exit_list)
		netlink_kernel_release(net->xfrm.nlsk_stash);
L
Linus Torvalds 已提交
2989 2990
}

2991
static struct pernet_operations xfrm_user_net_ops = {
2992 2993
	.init	    = xfrm_user_net_init,
	.exit_batch = xfrm_user_net_exit,
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016
};

static int __init xfrm_user_init(void)
{
	int rv;

	printk(KERN_INFO "Initializing XFRM netlink socket\n");

	rv = register_pernet_subsys(&xfrm_user_net_ops);
	if (rv < 0)
		return rv;
	rv = xfrm_register_km(&netlink_mgr);
	if (rv < 0)
		unregister_pernet_subsys(&xfrm_user_net_ops);
	return rv;
}

static void __exit xfrm_user_exit(void)
{
	xfrm_unregister_km(&netlink_mgr);
	unregister_pernet_subsys(&xfrm_user_net_ops);
}

L
Linus Torvalds 已提交
3017 3018 3019
module_init(xfrm_user_init);
module_exit(xfrm_user_exit);
MODULE_LICENSE("GPL");
3020
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
3021