xfrm_user.c 70.7 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
static inline int verify_replay(struct xfrm_usersa_info *p,
				struct nlattr **attrs)
{
	struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
126
	struct xfrm_replay_state_esn *rs;
127

128 129 130 131 132 133 134 135 136 137 138 139 140
	if (p->flags & XFRM_STATE_ESN) {
		if (!rt)
			return -EINVAL;

		rs = nla_data(rt);

		if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
			return -EINVAL;

		if (nla_len(rt) < xfrm_replay_state_esn_len(rs) &&
		    nla_len(rt) != sizeof(*rs))
			return -EINVAL;
	}
141

142 143 144
	if (!rt)
		return 0;

145 146
	/* As only ESP and AH support ESN feature. */
	if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH))
147 148
		return -EINVAL;

149 150 151 152 153
	if (p->replay_window != 0)
		return -EINVAL;

	return 0;
}
154

L
Linus Torvalds 已提交
155
static int verify_newsa_info(struct xfrm_usersa_info *p,
156
			     struct nlattr **attrs)
L
Linus Torvalds 已提交
157 158 159 160 161 162 163 164 165
{
	int err;

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

	case AF_INET6:
E
Eric Dumazet 已提交
166
#if IS_ENABLED(CONFIG_IPV6)
L
Linus Torvalds 已提交
167 168 169 170 171 172 173 174
		break;
#else
		err = -EAFNOSUPPORT;
		goto out;
#endif

	default:
		goto out;
175
	}
L
Linus Torvalds 已提交
176 177 178 179

	err = -EINVAL;
	switch (p->id.proto) {
	case IPPROTO_AH:
180 181
		if ((!attrs[XFRMA_ALG_AUTH]	&&
		     !attrs[XFRMA_ALG_AUTH_TRUNC]) ||
182
		    attrs[XFRMA_ALG_AEAD]	||
183
		    attrs[XFRMA_ALG_CRYPT]	||
184
		    attrs[XFRMA_ALG_COMP]	||
F
Fan Du 已提交
185 186 187
		    attrs[XFRMA_TFCPAD]		||
		    (ntohl(p->id.spi) >= 0x10000))

L
Linus Torvalds 已提交
188 189 190 191
			goto out;
		break;

	case IPPROTO_ESP:
192 193 194
		if (attrs[XFRMA_ALG_COMP])
			goto out;
		if (!attrs[XFRMA_ALG_AUTH] &&
195
		    !attrs[XFRMA_ALG_AUTH_TRUNC] &&
196 197 198 199
		    !attrs[XFRMA_ALG_CRYPT] &&
		    !attrs[XFRMA_ALG_AEAD])
			goto out;
		if ((attrs[XFRMA_ALG_AUTH] ||
200
		     attrs[XFRMA_ALG_AUTH_TRUNC] ||
201 202
		     attrs[XFRMA_ALG_CRYPT]) &&
		    attrs[XFRMA_ALG_AEAD])
L
Linus Torvalds 已提交
203
			goto out;
204 205 206
		if (attrs[XFRMA_TFCPAD] &&
		    p->mode != XFRM_MODE_TUNNEL)
			goto out;
L
Linus Torvalds 已提交
207 208 209
		break;

	case IPPROTO_COMP:
210
		if (!attrs[XFRMA_ALG_COMP]	||
211
		    attrs[XFRMA_ALG_AEAD]	||
212
		    attrs[XFRMA_ALG_AUTH]	||
213
		    attrs[XFRMA_ALG_AUTH_TRUNC]	||
214 215
		    attrs[XFRMA_ALG_CRYPT]	||
		    attrs[XFRMA_TFCPAD])
L
Linus Torvalds 已提交
216 217 218
			goto out;
		break;

E
Eric Dumazet 已提交
219
#if IS_ENABLED(CONFIG_IPV6)
220 221
	case IPPROTO_DSTOPTS:
	case IPPROTO_ROUTING:
222 223
		if (attrs[XFRMA_ALG_COMP]	||
		    attrs[XFRMA_ALG_AUTH]	||
224
		    attrs[XFRMA_ALG_AUTH_TRUNC]	||
225
		    attrs[XFRMA_ALG_AEAD]	||
226 227 228
		    attrs[XFRMA_ALG_CRYPT]	||
		    attrs[XFRMA_ENCAP]		||
		    attrs[XFRMA_SEC_CTX]	||
229
		    attrs[XFRMA_TFCPAD]		||
230
		    !attrs[XFRMA_COADDR])
231 232 233 234
			goto out;
		break;
#endif

L
Linus Torvalds 已提交
235 236
	default:
		goto out;
237
	}
L
Linus Torvalds 已提交
238

239 240
	if ((err = verify_aead(attrs)))
		goto out;
241 242
	if ((err = verify_auth_trunc(attrs)))
		goto out;
243
	if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH)))
L
Linus Torvalds 已提交
244
		goto out;
245
	if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT)))
L
Linus Torvalds 已提交
246
		goto out;
247
	if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP)))
L
Linus Torvalds 已提交
248
		goto out;
249
	if ((err = verify_sec_ctx_len(attrs)))
250
		goto out;
251 252
	if ((err = verify_replay(p, attrs)))
		goto out;
L
Linus Torvalds 已提交
253 254 255

	err = -EINVAL;
	switch (p->mode) {
256 257
	case XFRM_MODE_TRANSPORT:
	case XFRM_MODE_TUNNEL:
258
	case XFRM_MODE_ROUTEOPTIMIZATION:
D
Diego Beltrami 已提交
259
	case XFRM_MODE_BEET:
L
Linus Torvalds 已提交
260 261 262 263
		break;

	default:
		goto out;
264
	}
L
Linus Torvalds 已提交
265 266 267 268 269 270 271 272

	err = 0;

out:
	return err;
}

static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
273
			   struct xfrm_algo_desc *(*get_byname)(const char *, int),
274
			   struct nlattr *rta)
L
Linus Torvalds 已提交
275 276 277 278 279 280 281
{
	struct xfrm_algo *p, *ualg;
	struct xfrm_algo_desc *algo;

	if (!rta)
		return 0;

282
	ualg = nla_data(rta);
L
Linus Torvalds 已提交
283 284 285 286 287 288

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

289
	p = kmemdup(ualg, xfrm_alg_len(ualg), GFP_KERNEL);
L
Linus Torvalds 已提交
290 291 292
	if (!p)
		return -ENOMEM;

293
	strcpy(p->alg_name, algo->name);
L
Linus Torvalds 已提交
294 295 296 297
	*algpp = p;
	return 0;
}

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 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
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;
342 343
	if ((ualg->alg_trunc_len / 8) > MAX_AH_AUTH_LEN ||
	    ualg->alg_trunc_len > algo->uinfo.auth.icv_fullbits)
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
		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;
}

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
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;
}

384 385 386 387
static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn,
					 struct nlattr *rp)
{
	struct xfrm_replay_state_esn *up;
388
	int ulen;
389 390 391 392 393

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

	up = nla_data(rp);
394
	ulen = xfrm_replay_state_esn_len(up);
395

396
	if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
397 398 399 400 401
		return -EINVAL;

	return 0;
}

402 403 404 405 406
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;
407
	int klen, ulen;
408 409 410 411 412

	if (!rta)
		return 0;

	up = nla_data(rta);
413 414
	klen = xfrm_replay_state_esn_len(up);
	ulen = nla_len(rta) >= klen ? klen : sizeof(*up);
415

416
	p = kzalloc(klen, GFP_KERNEL);
417 418 419
	if (!p)
		return -ENOMEM;

420
	pp = kzalloc(klen, GFP_KERNEL);
421 422 423 424 425
	if (!pp) {
		kfree(p);
		return -ENOMEM;
	}

426 427 428
	memcpy(p, up, ulen);
	memcpy(pp, up, ulen);

429 430 431 432 433 434
	*replay_esn = p;
	*preplay_esn = pp;

	return 0;
}

435
static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
436 437 438 439 440 441 442 443 444 445
{
	int len = 0;

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

L
Linus Torvalds 已提交
446 447 448 449 450 451
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;
452 453
	x->props.replay_window = min_t(unsigned int, p->replay_window,
					sizeof(x->replay.bitmap) * 8);
L
Linus Torvalds 已提交
454 455
	x->props.reqid = p->reqid;
	x->props.family = p->family;
456
	memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
L
Linus Torvalds 已提交
457
	x->props.flags = p->flags;
458

459
	if (!x->sel.family && !(p->flags & XFRM_STATE_AF_UNSPEC))
460
		x->sel.family = p->family;
L
Linus Torvalds 已提交
461 462
}

J
Jamal Hadi Salim 已提交
463 464 465 466 467
/*
 * someday when pfkey also has support, we could have the code
 * somehow made shareable and move it to xfrm_state.c - JHS
 *
*/
468 469
static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
				  int update_esn)
J
Jamal Hadi Salim 已提交
470
{
471
	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
472
	struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL;
473 474 475
	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 已提交
476

477 478 479 480 481 482 483 484 485
	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 已提交
486 487
	if (rp) {
		struct xfrm_replay_state *replay;
488
		replay = nla_data(rp);
J
Jamal Hadi Salim 已提交
489 490 491 492 493 494
		memcpy(&x->replay, replay, sizeof(*replay));
		memcpy(&x->preplay, replay, sizeof(*replay));
	}

	if (lt) {
		struct xfrm_lifetime_cur *ltime;
495
		ltime = nla_data(lt);
J
Jamal Hadi Salim 已提交
496 497 498 499 500 501
		x->curlft.bytes = ltime->bytes;
		x->curlft.packets = ltime->packets;
		x->curlft.add_time = ltime->add_time;
		x->curlft.use_time = ltime->use_time;
	}

502
	if (et)
503
		x->replay_maxage = nla_get_u32(et);
J
Jamal Hadi Salim 已提交
504

505
	if (rt)
506
		x->replay_maxdiff = nla_get_u32(rt);
J
Jamal Hadi Salim 已提交
507 508
}

509 510
static struct xfrm_state *xfrm_state_construct(struct net *net,
					       struct xfrm_usersa_info *p,
511
					       struct nlattr **attrs,
L
Linus Torvalds 已提交
512 513
					       int *errp)
{
514
	struct xfrm_state *x = xfrm_state_alloc(net);
L
Linus Torvalds 已提交
515 516 517 518 519 520 521
	int err = -ENOMEM;

	if (!x)
		goto error_no_put;

	copy_from_user_state(x, p);

522 523 524
	if (attrs[XFRMA_SA_EXTRA_FLAGS])
		x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);

525 526 527
	if ((err = attach_aead(&x->aead, &x->props.ealgo,
			       attrs[XFRMA_ALG_AEAD])))
		goto error;
528 529
	if ((err = attach_auth_trunc(&x->aalg, &x->props.aalgo,
				     attrs[XFRMA_ALG_AUTH_TRUNC])))
L
Linus Torvalds 已提交
530
		goto error;
531 532 533 534 535
	if (!x->props.aalgo) {
		if ((err = attach_auth(&x->aalg, &x->props.aalgo,
				       attrs[XFRMA_ALG_AUTH])))
			goto error;
	}
L
Linus Torvalds 已提交
536 537
	if ((err = attach_one_algo(&x->ealg, &x->props.ealgo,
				   xfrm_ealg_get_byname,
538
				   attrs[XFRMA_ALG_CRYPT])))
L
Linus Torvalds 已提交
539 540 541
		goto error;
	if ((err = attach_one_algo(&x->calg, &x->props.calgo,
				   xfrm_calg_get_byname,
542
				   attrs[XFRMA_ALG_COMP])))
L
Linus Torvalds 已提交
543
		goto error;
544 545 546 547 548 549 550 551

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

552 553 554
	if (attrs[XFRMA_TFCPAD])
		x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]);

555 556 557 558 559 560 561
	if (attrs[XFRMA_COADDR]) {
		x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]),
				    sizeof(*x->coaddr), GFP_KERNEL);
		if (x->coaddr == NULL)
			goto error;
	}

562 563
	xfrm_mark_get(attrs, &x->mark);

564
	err = __xfrm_init_state(x, false);
L
Linus Torvalds 已提交
565 566 567
	if (err)
		goto error;

568 569
	if (attrs[XFRMA_SEC_CTX] &&
	    security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX])))
570 571
		goto error;

572 573 574 575
	if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
					       attrs[XFRMA_REPLAY_ESN_VAL])))
		goto error;

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

581 582
	if ((err = xfrm_init_replay(x)))
		goto error;
J
Jamal Hadi Salim 已提交
583

584
	/* override default values from above */
585
	xfrm_update_ae_params(x, attrs, 0);
L
Linus Torvalds 已提交
586 587 588 589 590 591 592 593 594 595 596

	return x;

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

597
static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
598
		struct nlattr **attrs)
L
Linus Torvalds 已提交
599
{
600
	struct net *net = sock_net(skb->sk);
601
	struct xfrm_usersa_info *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
602 603
	struct xfrm_state *x;
	int err;
604
	struct km_event c;
605
	kuid_t loginuid = audit_get_loginuid(current);
606
	unsigned int sessionid = audit_get_sessionid(current);
607
	u32 sid;
L
Linus Torvalds 已提交
608

609
	err = verify_newsa_info(p, attrs);
L
Linus Torvalds 已提交
610 611 612
	if (err)
		return err;

613
	x = xfrm_state_construct(net, p, attrs, &err);
L
Linus Torvalds 已提交
614 615 616
	if (!x)
		return err;

617
	xfrm_state_hold(x);
L
Linus Torvalds 已提交
618 619 620 621 622
	if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
		err = xfrm_state_add(x);
	else
		err = xfrm_state_update(x);

623
	security_task_getsecid(current, &sid);
624
	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
625

L
Linus Torvalds 已提交
626 627
	if (err < 0) {
		x->km.state = XFRM_STATE_DEAD;
628
		__xfrm_state_put(x);
629
		goto out;
L
Linus Torvalds 已提交
630 631
	}

632
	c.seq = nlh->nlmsg_seq;
633
	c.portid = nlh->nlmsg_pid;
634
	c.event = nlh->nlmsg_type;
635 636

	km_state_notify(x, &c);
637
out:
638
	xfrm_state_put(x);
L
Linus Torvalds 已提交
639 640 641
	return err;
}

642 643
static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
						 struct xfrm_usersa_id *p,
644
						 struct nlattr **attrs,
645 646 647
						 int *errp)
{
	struct xfrm_state *x = NULL;
648
	struct xfrm_mark m;
649
	int err;
650
	u32 mark = xfrm_mark_get(attrs, &m);
651 652 653

	if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
		err = -ESRCH;
654
		x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family);
655 656 657
	} else {
		xfrm_address_t *saddr = NULL;

658
		verify_one_addr(attrs, XFRMA_SRCADDR, &saddr);
659 660 661 662 663
		if (!saddr) {
			err = -EINVAL;
			goto out;
		}

664
		err = -ESRCH;
665 666
		x = xfrm_state_lookup_byaddr(net, mark,
					     &p->daddr, saddr,
667
					     p->proto, p->family);
668 669 670 671 672 673 674 675
	}

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

676
static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
677
		struct nlattr **attrs)
L
Linus Torvalds 已提交
678
{
679
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
680
	struct xfrm_state *x;
681
	int err = -ESRCH;
682
	struct km_event c;
683
	struct xfrm_usersa_id *p = nlmsg_data(nlh);
684
	kuid_t loginuid = audit_get_loginuid(current);
685
	unsigned int sessionid = audit_get_sessionid(current);
686
	u32 sid;
L
Linus Torvalds 已提交
687

688
	x = xfrm_user_state_lookup(net, p, attrs, &err);
L
Linus Torvalds 已提交
689
	if (x == NULL)
690
		return err;
L
Linus Torvalds 已提交
691

692
	if ((err = security_xfrm_state_delete(x)) != 0)
C
Catherine Zhang 已提交
693 694
		goto out;

L
Linus Torvalds 已提交
695
	if (xfrm_state_kern(x)) {
C
Catherine Zhang 已提交
696 697
		err = -EPERM;
		goto out;
L
Linus Torvalds 已提交
698 699
	}

700
	err = xfrm_state_delete(x);
J
Joy Latten 已提交
701

C
Catherine Zhang 已提交
702 703
	if (err < 0)
		goto out;
704 705

	c.seq = nlh->nlmsg_seq;
706
	c.portid = nlh->nlmsg_pid;
707
	c.event = nlh->nlmsg_type;
708
	km_state_notify(x, &c);
L
Linus Torvalds 已提交
709

C
Catherine Zhang 已提交
710
out:
711
	security_task_getsecid(current, &sid);
712
	xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
C
Catherine Zhang 已提交
713
	xfrm_state_put(x);
714
	return err;
L
Linus Torvalds 已提交
715 716 717 718
}

static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
{
719
	memset(p, 0, sizeof(*p));
L
Linus Torvalds 已提交
720 721 722 723 724
	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));
725
	memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr));
L
Linus Torvalds 已提交
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740
	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;
};

741 742 743 744
static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb)
{
	struct xfrm_user_sec_ctx *uctx;
	struct nlattr *attr;
745
	int ctx_size = sizeof(*uctx) + s->ctx_len;
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761

	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;
}

762 763 764 765 766 767 768 769 770 771 772
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);
773
	strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));
774 775 776 777 778 779
	memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
	algo->alg_key_len = auth->alg_key_len;

	return 0;
}

780 781 782 783
/* 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 已提交
784
{
785
	int ret = 0;
786

787
	copy_to_user_state(x, p);
788

789 790 791 792 793 794 795
	if (x->props.extra_flags) {
		ret = nla_put_u32(skb, XFRMA_SA_EXTRA_FLAGS,
				  x->props.extra_flags);
		if (ret)
			goto out;
	}

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
	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;
853 854 855 856 857 858 859 860 861 862 863
}

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;

864
	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, sp->nlmsg_seq,
865 866 867 868 869 870 871
			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);
872 873 874 875
	if (err) {
		nlmsg_cancel(skb, nlh);
		return err;
	}
876
	nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
877 878 879
	return 0;
}

880 881 882
static int xfrm_dump_sa_done(struct netlink_callback *cb)
{
	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
F
Fan Du 已提交
883 884 885 886
	struct sock *sk = cb->skb->sk;
	struct net *net = sock_net(sk);

	xfrm_state_walk_done(walk, net);
887 888 889
	return 0;
}

L
Linus Torvalds 已提交
890 891
static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
{
892
	struct net *net = sock_net(skb->sk);
893
	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
L
Linus Torvalds 已提交
894 895
	struct xfrm_dump_info info;

896 897 898
	BUILD_BUG_ON(sizeof(struct xfrm_state_walk) >
		     sizeof(cb->args) - sizeof(cb->args[0]));

L
Linus Torvalds 已提交
899 900 901 902
	info.in_skb = cb->skb;
	info.out_skb = skb;
	info.nlmsg_seq = cb->nlh->nlmsg_seq;
	info.nlmsg_flags = NLM_F_MULTI;
903 904 905 906 907 908

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

909
	(void) xfrm_state_walk(net, walk, dump_one_state, &info);
L
Linus Torvalds 已提交
910 911 912 913 914 915 916 917 918

	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;
919
	int err;
L
Linus Torvalds 已提交
920

921
	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
L
Linus Torvalds 已提交
922 923 924 925 926 927 928 929
	if (!skb)
		return ERR_PTR(-ENOMEM);

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

930 931
	err = dump_one_state(x, 0, &info);
	if (err) {
L
Linus Torvalds 已提交
932
		kfree_skb(skb);
933
		return ERR_PTR(err);
L
Linus Torvalds 已提交
934 935 936 937 938
	}

	return skb;
}

939 940 941 942 943 944 945
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));
}

946
static int build_spdinfo(struct sk_buff *skb, struct net *net,
947
			 u32 portid, u32 seq, u32 flags)
J
Jamal Hadi Salim 已提交
948
{
949 950 951
	struct xfrmk_spdinfo si;
	struct xfrmu_spdinfo spc;
	struct xfrmu_spdhinfo sph;
J
Jamal Hadi Salim 已提交
952
	struct nlmsghdr *nlh;
953
	int err;
J
Jamal Hadi Salim 已提交
954 955
	u32 *f;

956
	nlh = nlmsg_put(skb, portid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0);
L
Lucas De Marchi 已提交
957
	if (nlh == NULL) /* shouldn't really happen ... */
J
Jamal Hadi Salim 已提交
958 959 960 961
		return -EMSGSIZE;

	f = nlmsg_data(nlh);
	*f = flags;
962
	xfrm_spd_getinfo(net, &si);
963 964 965 966 967 968 969 970 971
	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;

972 973 974 975 976 977 978
	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 已提交
979 980 981 982 983

	return nlmsg_end(skb, nlh);
}

static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
984
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
985
{
986
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
987
	struct sk_buff *r_skb;
988
	u32 *flags = nlmsg_data(nlh);
989
	u32 sportid = NETLINK_CB(skb).portid;
J
Jamal Hadi Salim 已提交
990 991
	u32 seq = nlh->nlmsg_seq;

992
	r_skb = nlmsg_new(xfrm_spdinfo_msgsize(), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
993 994 995
	if (r_skb == NULL)
		return -ENOMEM;

996
	if (build_spdinfo(r_skb, net, sportid, seq, *flags) < 0)
J
Jamal Hadi Salim 已提交
997 998
		BUG();

999
	return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid);
J
Jamal Hadi Salim 已提交
1000 1001
}

1002 1003 1004 1005 1006 1007 1008
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 */
}

1009
static int build_sadinfo(struct sk_buff *skb, struct net *net,
1010
			 u32 portid, u32 seq, u32 flags)
J
Jamal Hadi Salim 已提交
1011
{
1012 1013
	struct xfrmk_sadinfo si;
	struct xfrmu_sadhinfo sh;
J
Jamal Hadi Salim 已提交
1014
	struct nlmsghdr *nlh;
1015
	int err;
J
Jamal Hadi Salim 已提交
1016 1017
	u32 *f;

1018
	nlh = nlmsg_put(skb, portid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0);
L
Lucas De Marchi 已提交
1019
	if (nlh == NULL) /* shouldn't really happen ... */
J
Jamal Hadi Salim 已提交
1020 1021 1022 1023
		return -EMSGSIZE;

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

1026 1027 1028
	sh.sadhmcnt = si.sadhmcnt;
	sh.sadhcnt = si.sadhcnt;

1029 1030 1031 1032 1033 1034 1035
	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 已提交
1036 1037 1038 1039 1040

	return nlmsg_end(skb, nlh);
}

static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
1041
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1042
{
1043
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1044
	struct sk_buff *r_skb;
1045
	u32 *flags = nlmsg_data(nlh);
1046
	u32 sportid = NETLINK_CB(skb).portid;
J
Jamal Hadi Salim 已提交
1047 1048
	u32 seq = nlh->nlmsg_seq;

1049
	r_skb = nlmsg_new(xfrm_sadinfo_msgsize(), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
1050 1051 1052
	if (r_skb == NULL)
		return -ENOMEM;

1053
	if (build_sadinfo(r_skb, net, sportid, seq, *flags) < 0)
J
Jamal Hadi Salim 已提交
1054 1055
		BUG();

1056
	return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid);
J
Jamal Hadi Salim 已提交
1057 1058
}

1059
static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1060
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1061
{
1062
	struct net *net = sock_net(skb->sk);
1063
	struct xfrm_usersa_id *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1064 1065
	struct xfrm_state *x;
	struct sk_buff *resp_skb;
1066
	int err = -ESRCH;
L
Linus Torvalds 已提交
1067

1068
	x = xfrm_user_state_lookup(net, p, attrs, &err);
L
Linus Torvalds 已提交
1069 1070 1071 1072 1073 1074 1075
	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 {
1076
		err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);
L
Linus Torvalds 已提交
1077 1078 1079 1080 1081 1082
	}
	xfrm_state_put(x);
out_noput:
	return err;
}

1083
static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
1084
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1085
{
1086
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1087 1088 1089 1090 1091 1092
	struct xfrm_state *x;
	struct xfrm_userspi_info *p;
	struct sk_buff *resp_skb;
	xfrm_address_t *daddr;
	int family;
	int err;
1093 1094
	u32 mark;
	struct xfrm_mark m;
L
Linus Torvalds 已提交
1095

1096
	p = nlmsg_data(nlh);
1097
	err = verify_spi_info(p->info.id.proto, p->min, p->max);
L
Linus Torvalds 已提交
1098 1099 1100 1101 1102 1103 1104
	if (err)
		goto out_noput;

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

	x = NULL;
1105 1106

	mark = xfrm_mark_get(attrs, &m);
L
Linus Torvalds 已提交
1107
	if (p->info.seq) {
1108
		x = xfrm_find_acq_byseq(net, mark, p->info.seq);
1109
		if (x && !xfrm_addr_equal(&x->id.daddr, daddr, family)) {
L
Linus Torvalds 已提交
1110 1111 1112 1113 1114 1115
			xfrm_state_put(x);
			x = NULL;
		}
	}

	if (!x)
1116
		x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid,
L
Linus Torvalds 已提交
1117 1118 1119 1120 1121 1122 1123
				  p->info.id.proto, daddr,
				  &p->info.saddr, 1,
				  family);
	err = -ENOENT;
	if (x == NULL)
		goto out_noput;

1124 1125 1126
	err = xfrm_alloc_spi(x, p->min, p->max);
	if (err)
		goto out;
L
Linus Torvalds 已提交
1127

1128
	resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq);
L
Linus Torvalds 已提交
1129 1130 1131 1132 1133
	if (IS_ERR(resp_skb)) {
		err = PTR_ERR(resp_skb);
		goto out;
	}

1134
	err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);
L
Linus Torvalds 已提交
1135 1136 1137 1138 1139 1140 1141

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

1142
static int verify_policy_dir(u8 dir)
L
Linus Torvalds 已提交
1143 1144 1145 1146 1147 1148 1149 1150 1151
{
	switch (dir) {
	case XFRM_POLICY_IN:
	case XFRM_POLICY_OUT:
	case XFRM_POLICY_FWD:
		break;

	default:
		return -EINVAL;
1152
	}
L
Linus Torvalds 已提交
1153 1154 1155 1156

	return 0;
}

1157
static int verify_policy_type(u8 type)
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
{
	switch (type) {
	case XFRM_POLICY_TYPE_MAIN:
#ifdef CONFIG_XFRM_SUB_POLICY
	case XFRM_POLICY_TYPE_SUB:
#endif
		break;

	default:
		return -EINVAL;
1168
	}
1169 1170 1171 1172

	return 0;
}

L
Linus Torvalds 已提交
1173 1174
static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
{
1175 1176
	int ret;

L
Linus Torvalds 已提交
1177 1178 1179 1180 1181 1182 1183 1184 1185
	switch (p->share) {
	case XFRM_SHARE_ANY:
	case XFRM_SHARE_SESSION:
	case XFRM_SHARE_USER:
	case XFRM_SHARE_UNIQUE:
		break;

	default:
		return -EINVAL;
1186
	}
L
Linus Torvalds 已提交
1187 1188 1189 1190 1191 1192 1193 1194

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

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

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

	case AF_INET6:
E
Eric Dumazet 已提交
1202
#if IS_ENABLED(CONFIG_IPV6)
L
Linus Torvalds 已提交
1203 1204 1205 1206 1207 1208 1209
		break;
#else
		return  -EAFNOSUPPORT;
#endif

	default:
		return -EINVAL;
1210
	}
L
Linus Torvalds 已提交
1211

1212 1213 1214 1215 1216 1217 1218
	ret = verify_policy_dir(p->dir);
	if (ret)
		return ret;
	if (p->index && ((p->index & XFRM_POLICY_MAX) != p->dir))
		return -EINVAL;

	return 0;
L
Linus Torvalds 已提交
1219 1220
}

1221
static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs)
1222
{
1223
	struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1224 1225 1226 1227 1228
	struct xfrm_user_sec_ctx *uctx;

	if (!rt)
		return 0;

1229
	uctx = nla_data(rt);
1230
	return security_xfrm_policy_alloc(&pol->security, uctx);
1231 1232
}

L
Linus Torvalds 已提交
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
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;
1252 1253
		/* If all masks are ~0, then we allow all algorithms. */
		t->allalgs = !~(t->aalgos & t->ealgos & t->calgos);
1254
		t->encap_family = ut->family;
L
Linus Torvalds 已提交
1255 1256 1257
	}
}

1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
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 已提交
1279
#if IS_ENABLED(CONFIG_IPV6)
1280 1281 1282 1283 1284
		case AF_INET6:
			break;
#endif
		default:
			return -EINVAL;
1285
		}
1286 1287 1288 1289 1290
	}

	return 0;
}

1291
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs)
L
Linus Torvalds 已提交
1292
{
1293
	struct nlattr *rt = attrs[XFRMA_TMPL];
L
Linus Torvalds 已提交
1294 1295 1296 1297

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

1302 1303 1304
		err = validate_tmpl(nr, utmpl, pol->family);
		if (err)
			return err;
L
Linus Torvalds 已提交
1305

1306
		copy_templates(pol, utmpl, nr);
L
Linus Torvalds 已提交
1307 1308 1309 1310
	}
	return 0;
}

1311
static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs)
1312
{
1313
	struct nlattr *rt = attrs[XFRMA_POLICY_TYPE];
1314
	struct xfrm_userpolicy_type *upt;
1315
	u8 type = XFRM_POLICY_TYPE_MAIN;
1316 1317 1318
	int err;

	if (rt) {
1319
		upt = nla_data(rt);
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
		type = upt->type;
	}

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

	*tp = type;
	return 0;
}

L
Linus Torvalds 已提交
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
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)
{
1345
	memset(p, 0, sizeof(*p));
L
Linus Torvalds 已提交
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
	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 */
}

1358
static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp)
L
Linus Torvalds 已提交
1359
{
1360
	struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL);
L
Linus Torvalds 已提交
1361 1362 1363 1364 1365 1366 1367 1368
	int err;

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

	copy_from_user_policy(xp, p);
1369

1370
	err = copy_from_user_policy_type(&xp->type, attrs);
1371 1372 1373
	if (err)
		goto error;

1374 1375
	if (!(err = copy_from_user_tmpl(xp, attrs)))
		err = copy_from_user_sec_ctx(xp, attrs);
1376 1377
	if (err)
		goto error;
L
Linus Torvalds 已提交
1378

1379 1380
	xfrm_mark_get(attrs, &xp->mark);

L
Linus Torvalds 已提交
1381
	return xp;
1382 1383
 error:
	*errp = err;
H
Herbert Xu 已提交
1384
	xp->walk.dead = 1;
1385
	xfrm_policy_destroy(xp);
1386
	return NULL;
L
Linus Torvalds 已提交
1387 1388
}

1389
static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1390
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1391
{
1392
	struct net *net = sock_net(skb->sk);
1393
	struct xfrm_userpolicy_info *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1394
	struct xfrm_policy *xp;
1395
	struct km_event c;
L
Linus Torvalds 已提交
1396 1397
	int err;
	int excl;
1398
	kuid_t loginuid = audit_get_loginuid(current);
1399
	unsigned int sessionid = audit_get_sessionid(current);
1400
	u32 sid;
L
Linus Torvalds 已提交
1401 1402

	err = verify_newpolicy_info(p);
1403 1404
	if (err)
		return err;
1405
	err = verify_sec_ctx_len(attrs);
L
Linus Torvalds 已提交
1406 1407 1408
	if (err)
		return err;

1409
	xp = xfrm_policy_construct(net, p, attrs, &err);
L
Linus Torvalds 已提交
1410 1411 1412
	if (!xp)
		return err;

L
Lucas De Marchi 已提交
1413
	/* shouldn't excl be based on nlh flags??
1414 1415 1416
	 * 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 已提交
1417 1418
	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
	err = xfrm_policy_insert(p->dir, xp, excl);
1419
	security_task_getsecid(current, &sid);
1420
	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
1421

L
Linus Torvalds 已提交
1422
	if (err) {
1423
		security_xfrm_policy_free(xp->security);
L
Linus Torvalds 已提交
1424 1425 1426 1427
		kfree(xp);
		return err;
	}

1428
	c.event = nlh->nlmsg_type;
1429
	c.seq = nlh->nlmsg_seq;
1430
	c.portid = nlh->nlmsg_pid;
1431 1432
	km_policy_notify(xp, p->dir, &c);

L
Linus Torvalds 已提交
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
	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];

1450
		memset(up, 0, sizeof(*up));
L
Linus Torvalds 已提交
1451
		memcpy(&up->id, &kp->id, sizeof(up->id));
1452
		up->family = kp->encap_family;
L
Linus Torvalds 已提交
1453 1454 1455 1456 1457 1458 1459 1460 1461
		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;
	}
1462

1463 1464
	return nla_put(skb, XFRMA_TMPL,
		       sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr, vec);
1465 1466 1467 1468 1469 1470
}

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);
1471 1472
	}
	return 0;
1473
}
1474

1475 1476
static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
{
1477
	if (xp->security)
1478 1479
		return copy_sec_ctx(xp->security, skb);
	return 0;
1480
}
1481 1482 1483 1484 1485 1486 1487 1488
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
}
1489

1490
#ifdef CONFIG_XFRM_SUB_POLICY
1491
static int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
1492
{
1493 1494 1495
	struct xfrm_userpolicy_type upt = {
		.type = type,
	};
1496

1497
	return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
1498 1499 1500
}

#else
1501
static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
1502 1503 1504 1505 1506
{
	return 0;
}
#endif

L
Linus Torvalds 已提交
1507 1508 1509 1510 1511 1512 1513
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;
1514
	int err;
L
Linus Torvalds 已提交
1515

1516
	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, sp->nlmsg_seq,
1517 1518 1519
			XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
1520

1521
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1522
	copy_to_user_policy(xp, p, dir);
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
	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;
	}
1534
	nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
1535 1536 1537
	return 0;
}

1538 1539 1540
static int xfrm_dump_policy_done(struct netlink_callback *cb)
{
	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
F
Fan Du 已提交
1541
	struct net *net = sock_net(cb->skb->sk);
1542

F
Fan Du 已提交
1543
	xfrm_policy_walk_done(walk, net);
1544 1545 1546
	return 0;
}

L
Linus Torvalds 已提交
1547 1548
static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
{
1549
	struct net *net = sock_net(skb->sk);
1550
	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
L
Linus Torvalds 已提交
1551 1552
	struct xfrm_dump_info info;

1553 1554 1555
	BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
		     sizeof(cb->args) - sizeof(cb->args[0]));

L
Linus Torvalds 已提交
1556 1557 1558 1559
	info.in_skb = cb->skb;
	info.out_skb = skb;
	info.nlmsg_seq = cb->nlh->nlmsg_seq;
	info.nlmsg_flags = NLM_F_MULTI;
1560 1561 1562 1563 1564 1565

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

1566
	(void) xfrm_policy_walk(net, walk, dump_one_policy, &info);
L
Linus Torvalds 已提交
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576

	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;
1577
	int err;
L
Linus Torvalds 已提交
1578

1579
	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
L
Linus Torvalds 已提交
1580 1581 1582 1583 1584 1585 1586 1587
	if (!skb)
		return ERR_PTR(-ENOMEM);

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

1588 1589
	err = dump_one_policy(xp, dir, 0, &info);
	if (err) {
L
Linus Torvalds 已提交
1590
		kfree_skb(skb);
1591
		return ERR_PTR(err);
L
Linus Torvalds 已提交
1592 1593 1594 1595 1596
	}

	return skb;
}

1597
static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1598
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1599
{
1600
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1601 1602
	struct xfrm_policy *xp;
	struct xfrm_userpolicy_id *p;
1603
	u8 type = XFRM_POLICY_TYPE_MAIN;
L
Linus Torvalds 已提交
1604
	int err;
1605
	struct km_event c;
L
Linus Torvalds 已提交
1606
	int delete;
1607 1608
	struct xfrm_mark m;
	u32 mark = xfrm_mark_get(attrs, &m);
L
Linus Torvalds 已提交
1609

1610
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1611 1612
	delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;

1613
	err = copy_from_user_policy_type(&type, attrs);
1614 1615 1616
	if (err)
		return err;

L
Linus Torvalds 已提交
1617 1618 1619 1620 1621
	err = verify_policy_dir(p->dir);
	if (err)
		return err;

	if (p->index)
1622
		xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err);
1623
	else {
1624
		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1625
		struct xfrm_sec_ctx *ctx;
1626

1627
		err = verify_sec_ctx_len(attrs);
1628 1629 1630
		if (err)
			return err;

1631
		ctx = NULL;
1632
		if (rt) {
1633
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1634

1635 1636
			err = security_xfrm_policy_alloc(&ctx, uctx);
			if (err)
1637
				return err;
1638
		}
1639
		xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel,
1640
					   ctx, delete, &err);
1641
		security_xfrm_policy_free(ctx);
1642
	}
L
Linus Torvalds 已提交
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
	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 {
1653
			err = nlmsg_unicast(net->xfrm.nlsk, resp_skb,
1654
					    NETLINK_CB(skb).portid);
L
Linus Torvalds 已提交
1655
		}
1656
	} else {
1657
		kuid_t loginuid = audit_get_loginuid(current);
1658
		unsigned int sessionid = audit_get_sessionid(current);
1659
		u32 sid;
1660

1661
		security_task_getsecid(current, &sid);
1662 1663
		xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
					 sid);
1664 1665

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

1668
		c.data.byid = p->index;
1669
		c.event = nlh->nlmsg_type;
1670
		c.seq = nlh->nlmsg_seq;
1671
		c.portid = nlh->nlmsg_pid;
1672
		km_policy_notify(xp, p->dir, &c);
L
Linus Torvalds 已提交
1673 1674
	}

C
Catherine Zhang 已提交
1675
out:
1676
	xfrm_pol_put(xp);
1677 1678
	if (delete && err == 0)
		xfrm_garbage_collect(net);
L
Linus Torvalds 已提交
1679 1680 1681
	return err;
}

1682
static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1683
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1684
{
1685
	struct net *net = sock_net(skb->sk);
1686
	struct km_event c;
1687
	struct xfrm_usersa_flush *p = nlmsg_data(nlh);
J
Joy Latten 已提交
1688
	struct xfrm_audit audit_info;
1689
	int err;
L
Linus Torvalds 已提交
1690

1691 1692 1693
	audit_info.loginuid = audit_get_loginuid(current);
	audit_info.sessionid = audit_get_sessionid(current);
	security_task_getsecid(current, &audit_info.secid);
1694
	err = xfrm_state_flush(net, p->proto, &audit_info);
1695 1696 1697
	if (err) {
		if (err == -ESRCH) /* empty table */
			return 0;
1698
		return err;
1699
	}
1700
	c.data.proto = p->proto;
1701
	c.event = nlh->nlmsg_type;
1702
	c.seq = nlh->nlmsg_seq;
1703
	c.portid = nlh->nlmsg_pid;
1704
	c.net = net;
1705 1706
	km_state_notify(NULL, &c);

L
Linus Torvalds 已提交
1707 1708 1709
	return 0;
}

1710
static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x)
1711
{
1712 1713 1714 1715
	size_t replay_size = x->replay_esn ?
			      xfrm_replay_state_esn_len(x->replay_esn) :
			      sizeof(struct xfrm_replay_state);

1716
	return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
1717
	       + nla_total_size(replay_size)
1718
	       + nla_total_size(sizeof(struct xfrm_lifetime_cur))
1719
	       + nla_total_size(sizeof(struct xfrm_mark))
1720 1721 1722
	       + nla_total_size(4) /* XFRM_AE_RTHR */
	       + nla_total_size(4); /* XFRM_AE_ETHR */
}
J
Jamal Hadi Salim 已提交
1723

1724
static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
J
Jamal Hadi Salim 已提交
1725 1726 1727
{
	struct xfrm_aevent_id *id;
	struct nlmsghdr *nlh;
1728
	int err;
J
Jamal Hadi Salim 已提交
1729

1730
	nlh = nlmsg_put(skb, c->portid, c->seq, XFRM_MSG_NEWAE, sizeof(*id), 0);
1731 1732
	if (nlh == NULL)
		return -EMSGSIZE;
J
Jamal Hadi Salim 已提交
1733

1734
	id = nlmsg_data(nlh);
1735
	memcpy(&id->sa_id.daddr, &x->id.daddr, sizeof(x->id.daddr));
J
Jamal Hadi Salim 已提交
1736 1737 1738
	id->sa_id.spi = x->id.spi;
	id->sa_id.family = x->props.family;
	id->sa_id.proto = x->id.proto;
1739
	memcpy(&id->saddr, &x->props.saddr, sizeof(x->props.saddr));
1740
	id->reqid = x->props.reqid;
J
Jamal Hadi Salim 已提交
1741 1742
	id->flags = c->data.aevent;

1743
	if (x->replay_esn) {
1744 1745 1746
		err = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
			      xfrm_replay_state_esn_len(x->replay_esn),
			      x->replay_esn);
1747
	} else {
1748 1749
		err = nla_put(skb, XFRMA_REPLAY_VAL, sizeof(x->replay),
			      &x->replay);
1750
	}
1751 1752 1753 1754 1755
	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 已提交
1756

1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
	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;
1771

1772
	return nlmsg_end(skb, nlh);
J
Jamal Hadi Salim 已提交
1773

1774
out_cancel:
1775
	nlmsg_cancel(skb, nlh);
1776
	return err;
J
Jamal Hadi Salim 已提交
1777 1778
}

1779
static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1780
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1781
{
1782
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1783 1784 1785 1786
	struct xfrm_state *x;
	struct sk_buff *r_skb;
	int err;
	struct km_event c;
1787 1788
	u32 mark;
	struct xfrm_mark m;
1789
	struct xfrm_aevent_id *p = nlmsg_data(nlh);
J
Jamal Hadi Salim 已提交
1790 1791
	struct xfrm_usersa_id *id = &p->sa_id;

1792 1793 1794
	mark = xfrm_mark_get(attrs, &m);

	x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
1795
	if (x == NULL)
J
Jamal Hadi Salim 已提交
1796
		return -ESRCH;
1797 1798 1799 1800 1801

	r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
	if (r_skb == NULL) {
		xfrm_state_put(x);
		return -ENOMEM;
J
Jamal Hadi Salim 已提交
1802 1803 1804 1805 1806 1807 1808 1809 1810 1811
	}

	/*
	 * 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;
1812
	c.portid = nlh->nlmsg_pid;
J
Jamal Hadi Salim 已提交
1813 1814 1815

	if (build_aevent(r_skb, x, &c) < 0)
		BUG();
1816
	err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).portid);
J
Jamal Hadi Salim 已提交
1817 1818 1819 1820 1821
	spin_unlock_bh(&x->lock);
	xfrm_state_put(x);
	return err;
}

1822
static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1823
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1824
{
1825
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1826 1827
	struct xfrm_state *x;
	struct km_event c;
1828
	int err = -EINVAL;
1829 1830
	u32 mark = 0;
	struct xfrm_mark m;
1831
	struct xfrm_aevent_id *p = nlmsg_data(nlh);
1832
	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
1833
	struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
1834
	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
J
Jamal Hadi Salim 已提交
1835

1836
	if (!lt && !rp && !re)
J
Jamal Hadi Salim 已提交
1837 1838 1839 1840 1841 1842
		return err;

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

1843 1844 1845
	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 已提交
1846 1847 1848 1849 1850 1851
	if (x == NULL)
		return -ESRCH;

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

1852
	err = xfrm_replay_verify_len(x->replay_esn, re);
1853 1854 1855
	if (err)
		goto out;

J
Jamal Hadi Salim 已提交
1856
	spin_lock_bh(&x->lock);
1857
	xfrm_update_ae_params(x, attrs, 1);
J
Jamal Hadi Salim 已提交
1858 1859 1860 1861
	spin_unlock_bh(&x->lock);

	c.event = nlh->nlmsg_type;
	c.seq = nlh->nlmsg_seq;
1862
	c.portid = nlh->nlmsg_pid;
J
Jamal Hadi Salim 已提交
1863 1864 1865 1866 1867 1868 1869 1870
	c.data.aevent = XFRM_AE_CU;
	km_state_notify(x, &c);
	err = 0;
out:
	xfrm_state_put(x);
	return err;
}

1871
static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1872
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1873
{
1874
	struct net *net = sock_net(skb->sk);
1875
	struct km_event c;
1876
	u8 type = XFRM_POLICY_TYPE_MAIN;
1877
	int err;
J
Joy Latten 已提交
1878
	struct xfrm_audit audit_info;
1879

1880
	err = copy_from_user_policy_type(&type, attrs);
1881 1882
	if (err)
		return err;
1883

1884 1885 1886
	audit_info.loginuid = audit_get_loginuid(current);
	audit_info.sessionid = audit_get_sessionid(current);
	security_task_getsecid(current, &audit_info.secid);
1887
	err = xfrm_policy_flush(net, type, &audit_info);
1888 1889 1890
	if (err) {
		if (err == -ESRCH) /* empty table */
			return 0;
1891
		return err;
1892 1893
	}

1894
	c.data.type = type;
1895
	c.event = nlh->nlmsg_type;
1896
	c.seq = nlh->nlmsg_seq;
1897
	c.portid = nlh->nlmsg_pid;
1898
	c.net = net;
1899
	km_policy_notify(NULL, 0, &c);
L
Linus Torvalds 已提交
1900 1901 1902
	return 0;
}

1903
static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1904
		struct nlattr **attrs)
1905
{
1906
	struct net *net = sock_net(skb->sk);
1907
	struct xfrm_policy *xp;
1908
	struct xfrm_user_polexpire *up = nlmsg_data(nlh);
1909
	struct xfrm_userpolicy_info *p = &up->pol;
1910
	u8 type = XFRM_POLICY_TYPE_MAIN;
1911
	int err = -ENOENT;
1912 1913
	struct xfrm_mark m;
	u32 mark = xfrm_mark_get(attrs, &m);
1914

1915
	err = copy_from_user_policy_type(&type, attrs);
1916 1917 1918
	if (err)
		return err;

1919 1920 1921 1922
	err = verify_policy_dir(p->dir);
	if (err)
		return err;

1923
	if (p->index)
1924
		xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err);
1925
	else {
1926
		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1927
		struct xfrm_sec_ctx *ctx;
1928

1929
		err = verify_sec_ctx_len(attrs);
1930 1931 1932
		if (err)
			return err;

1933
		ctx = NULL;
1934
		if (rt) {
1935
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1936

1937 1938
			err = security_xfrm_policy_alloc(&ctx, uctx);
			if (err)
1939
				return err;
1940
		}
1941
		xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir,
1942
					   &p->sel, ctx, 0, &err);
1943
		security_xfrm_policy_free(ctx);
1944 1945
	}
	if (xp == NULL)
1946
		return -ENOENT;
1947

1948
	if (unlikely(xp->walk.dead))
1949 1950 1951 1952
		goto out;

	err = 0;
	if (up->hard) {
1953
		kuid_t loginuid = audit_get_loginuid(current);
1954
		unsigned int sessionid = audit_get_sessionid(current);
1955 1956 1957
		u32 sid;

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

1961 1962
	} else {
		// reset the timers here?
S
stephen hemminger 已提交
1963
		WARN(1, "Dont know what to do with soft policy expire\n");
1964
	}
1965
	km_policy_expired(xp, p->dir, up->hard, nlh->nlmsg_pid);
1966 1967 1968 1969 1970 1971

out:
	xfrm_pol_put(xp);
	return err;
}

1972
static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1973
		struct nlattr **attrs)
1974
{
1975
	struct net *net = sock_net(skb->sk);
1976 1977
	struct xfrm_state *x;
	int err;
1978
	struct xfrm_user_expire *ue = nlmsg_data(nlh);
1979
	struct xfrm_usersa_info *p = &ue->state;
1980
	struct xfrm_mark m;
1981
	u32 mark = xfrm_mark_get(attrs, &m);
1982

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

1985
	err = -ENOENT;
1986 1987 1988 1989
	if (x == NULL)
		return err;

	spin_lock_bh(&x->lock);
1990
	err = -EINVAL;
1991 1992
	if (x->km.state != XFRM_STATE_VALID)
		goto out;
1993
	km_state_expired(x, ue->hard, nlh->nlmsg_pid);
1994

J
Joy Latten 已提交
1995
	if (ue->hard) {
1996
		kuid_t loginuid = audit_get_loginuid(current);
1997
		unsigned int sessionid = audit_get_sessionid(current);
1998 1999 2000
		u32 sid;

		security_task_getsecid(current, &sid);
2001
		__xfrm_state_delete(x);
2002
		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
2003
	}
2004
	err = 0;
2005 2006 2007 2008 2009 2010
out:
	spin_unlock_bh(&x->lock);
	xfrm_state_put(x);
	return err;
}

2011
static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
2012
		struct nlattr **attrs)
2013
{
2014
	struct net *net = sock_net(skb->sk);
2015 2016 2017
	struct xfrm_policy *xp;
	struct xfrm_user_tmpl *ut;
	int i;
2018
	struct nlattr *rt = attrs[XFRMA_TMPL];
2019
	struct xfrm_mark mark;
2020

2021
	struct xfrm_user_acquire *ua = nlmsg_data(nlh);
2022
	struct xfrm_state *x = xfrm_state_alloc(net);
2023 2024 2025
	int err = -ENOMEM;

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

2028 2029
	xfrm_mark_get(attrs, &mark);

2030
	err = verify_newpolicy_info(&ua->policy);
I
Ilpo Järvinen 已提交
2031 2032
	if (err)
		goto bad_policy;
2033 2034

	/*   build an XP */
2035
	xp = xfrm_policy_construct(net, &ua->policy, attrs, &err);
I
Ilpo Järvinen 已提交
2036 2037
	if (!xp)
		goto free_state;
2038 2039 2040 2041

	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));
2042 2043
	xp->mark.m = x->mark.m = mark.m;
	xp->mark.v = x->mark.v = mark.v;
2044
	ut = nla_data(rt);
2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
	/* 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 已提交
2063 2064

bad_policy:
S
stephen hemminger 已提交
2065
	WARN(1, "BAD policy passed\n");
I
Ilpo Järvinen 已提交
2066 2067 2068 2069
free_state:
	kfree(x);
nomem:
	return err;
2070 2071
}

2072 2073
#ifdef CONFIG_XFRM_MIGRATE
static int copy_from_user_migrate(struct xfrm_migrate *ma,
2074
				  struct xfrm_kmaddress *k,
2075
				  struct nlattr **attrs, int *num)
2076
{
2077
	struct nlattr *rt = attrs[XFRMA_MIGRATE];
2078 2079 2080
	struct xfrm_user_migrate *um;
	int i, num_migrate;

2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
	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;
	}

2091 2092
	um = nla_data(rt);
	num_migrate = nla_len(rt) / sizeof(*um);
2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115

	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,
2116
			   struct nlattr **attrs)
2117
{
2118
	struct xfrm_userpolicy_id *pi = nlmsg_data(nlh);
2119
	struct xfrm_migrate m[XFRM_MAX_DEPTH];
2120
	struct xfrm_kmaddress km, *kmp;
2121 2122 2123
	u8 type;
	int err;
	int n = 0;
2124
	struct net *net = sock_net(skb->sk);
2125

2126
	if (attrs[XFRMA_MIGRATE] == NULL)
2127
		return -EINVAL;
2128

2129 2130
	kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL;

2131
	err = copy_from_user_policy_type(&type, attrs);
2132 2133 2134
	if (err)
		return err;

2135
	err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n);
2136 2137 2138 2139 2140 2141
	if (err)
		return err;

	if (!n)
		return 0;

2142
	xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net);
2143 2144 2145 2146 2147

	return 0;
}
#else
static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
2148
			   struct nlattr **attrs)
2149 2150 2151 2152 2153 2154
{
	return -ENOPROTOOPT;
}
#endif

#ifdef CONFIG_XFRM_MIGRATE
2155
static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb)
2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
{
	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));

2170
	return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um);
2171 2172
}

2173
static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb)
2174 2175 2176 2177 2178 2179 2180
{
	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));
2181
	memcpy(&uk.remote, &k->remote, sizeof(uk.remote));
2182 2183 2184 2185 2186

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

static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma)
2187 2188
{
	return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))
2189 2190 2191
	      + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0)
	      + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)
	      + userpolicy_type_attrsize();
2192 2193
}

2194 2195 2196
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)
2197
{
2198
	const struct xfrm_migrate *mp;
2199 2200
	struct xfrm_userpolicy_id *pol_id;
	struct nlmsghdr *nlh;
2201
	int i, err;
2202

2203 2204 2205
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
2206

2207
	pol_id = nlmsg_data(nlh);
2208 2209 2210 2211 2212
	/* 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;

2213 2214 2215 2216 2217 2218 2219 2220
	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;
2221
	for (i = 0, mp = m ; i < num_migrate; i++, mp++) {
2222 2223 2224
		err = copy_to_user_migrate(mp, skb);
		if (err)
			goto out_cancel;
2225 2226
	}

2227
	return nlmsg_end(skb, nlh);
2228 2229

out_cancel:
2230
	nlmsg_cancel(skb, nlh);
2231
	return err;
2232 2233
}

2234 2235 2236
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)
2237
{
2238
	struct net *net = &init_net;
2239 2240
	struct sk_buff *skb;

2241
	skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC);
2242 2243 2244 2245
	if (skb == NULL)
		return -ENOMEM;

	/* build migrate */
2246
	if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0)
2247 2248
		BUG();

2249
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC);
2250 2251
}
#else
2252 2253 2254
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)
2255 2256 2257 2258
{
	return -ENOPROTOOPT;
}
#endif
J
Jamal Hadi Salim 已提交
2259

2260
#define XMSGSIZE(type) sizeof(struct type)
2261 2262

static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
2263
	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
2264 2265 2266 2267 2268 2269
	[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),
2270
	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire),
2271
	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire),
2272
	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),
2273
	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
2274
	[XFRM_MSG_POLEXPIRE   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire),
2275
	[XFRM_MSG_FLUSHSA     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush),
2276
	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0,
J
Jamal Hadi Salim 已提交
2277 2278
	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
2279
	[XFRM_MSG_REPORT      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
2280
	[XFRM_MSG_MIGRATE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
2281 2282
	[XFRM_MSG_GETSADINFO  - XFRM_MSG_BASE] = sizeof(u32),
	[XFRM_MSG_GETSPDINFO  - XFRM_MSG_BASE] = sizeof(u32),
L
Linus Torvalds 已提交
2283 2284
};

2285 2286
#undef XMSGSIZE

2287
static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
J
jamal 已提交
2288 2289 2290 2291
	[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)},
2292
	[XFRMA_ALG_AEAD]	= { .len = sizeof(struct xfrm_algo_aead) },
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306
	[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) },
2307
	[XFRMA_KMADDRESS]	= { .len = sizeof(struct xfrm_user_kmaddress) },
2308
	[XFRMA_MARK]		= { .len = sizeof(struct xfrm_mark) },
2309
	[XFRMA_TFCPAD]		= { .type = NLA_U32 },
2310
	[XFRMA_REPLAY_ESN_VAL]	= { .len = sizeof(struct xfrm_replay_state_esn) },
2311
	[XFRMA_SA_EXTRA_FLAGS]	= { .type = NLA_U32 },
2312 2313
};

2314
static const struct xfrm_link {
2315
	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
L
Linus Torvalds 已提交
2316
	int (*dump)(struct sk_buff *, struct netlink_callback *);
2317
	int (*done)(struct netlink_callback *);
2318 2319 2320 2321
} 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,
2322 2323
						   .dump = xfrm_dump_sa,
						   .done = xfrm_dump_sa_done  },
2324 2325 2326
	[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,
2327 2328
						   .dump = xfrm_dump_policy,
						   .done = xfrm_dump_policy_done },
2329
	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
2330
	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire   },
2331
	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire },
2332 2333
	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = { .doit = xfrm_add_sa        },
2334
	[XFRM_MSG_POLEXPIRE   - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire},
2335 2336
	[XFRM_MSG_FLUSHSA     - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa      },
	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy  },
J
Jamal Hadi Salim 已提交
2337 2338
	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = { .doit = xfrm_new_ae  },
	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = { .doit = xfrm_get_ae  },
2339
	[XFRM_MSG_MIGRATE     - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate    },
2340
	[XFRM_MSG_GETSADINFO  - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo   },
J
Jamal Hadi Salim 已提交
2341
	[XFRM_MSG_GETSPDINFO  - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo   },
L
Linus Torvalds 已提交
2342 2343
};

2344
static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
L
Linus Torvalds 已提交
2345
{
2346
	struct net *net = sock_net(skb->sk);
2347
	struct nlattr *attrs[XFRMA_MAX+1];
2348
	const struct xfrm_link *link;
2349
	int type, err;
L
Linus Torvalds 已提交
2350 2351 2352

	type = nlh->nlmsg_type;
	if (type > XFRM_MSG_MAX)
2353
		return -EINVAL;
L
Linus Torvalds 已提交
2354 2355 2356 2357 2358

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

	/* All operations require privileges, even GET */
2359
	if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2360
		return -EPERM;
L
Linus Torvalds 已提交
2361

2362 2363
	if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
	     type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) &&
2364
	    (nlh->nlmsg_flags & NLM_F_DUMP)) {
L
Linus Torvalds 已提交
2365
		if (link->dump == NULL)
2366
			return -EINVAL;
2367

2368 2369 2370 2371 2372 2373 2374
		{
			struct netlink_dump_control c = {
				.dump = link->dump,
				.done = link->done,
			};
			return netlink_dump_start(net->xfrm.nlsk, skb, nlh, &c);
		}
L
Linus Torvalds 已提交
2375 2376
	}

2377
	err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
2378
			  xfrma_policy);
2379 2380
	if (err < 0)
		return err;
L
Linus Torvalds 已提交
2381 2382

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

2385
	return link->doit(skb, nlh, attrs);
L
Linus Torvalds 已提交
2386 2387
}

2388
static void xfrm_netlink_rcv(struct sk_buff *skb)
L
Linus Torvalds 已提交
2389
{
F
Fan Du 已提交
2390 2391 2392
	struct net *net = sock_net(skb->sk);

	mutex_lock(&net->xfrm.xfrm_cfg_mutex);
2393
	netlink_rcv_skb(skb, &xfrm_user_rcv_msg);
F
Fan Du 已提交
2394
	mutex_unlock(&net->xfrm.xfrm_cfg_mutex);
L
Linus Torvalds 已提交
2395 2396
}

2397 2398
static inline size_t xfrm_expire_msgsize(void)
{
2399 2400
	return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
	       + nla_total_size(sizeof(struct xfrm_mark));
2401 2402
}

2403
static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
L
Linus Torvalds 已提交
2404 2405 2406
{
	struct xfrm_user_expire *ue;
	struct nlmsghdr *nlh;
2407
	int err;
L
Linus Torvalds 已提交
2408

2409
	nlh = nlmsg_put(skb, c->portid, 0, XFRM_MSG_EXPIRE, sizeof(*ue), 0);
2410 2411
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2412

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

2417 2418 2419
	err = xfrm_mark_put(skb, &x->mark);
	if (err)
		return err;
2420

2421
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2422 2423
}

2424
static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c)
L
Linus Torvalds 已提交
2425
{
2426
	struct net *net = xs_net(x);
L
Linus Torvalds 已提交
2427 2428
	struct sk_buff *skb;

2429
	skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC);
L
Linus Torvalds 已提交
2430 2431 2432
	if (skb == NULL)
		return -ENOMEM;

2433 2434 2435 2436
	if (build_expire(skb, x, c) < 0) {
		kfree_skb(skb);
		return -EMSGSIZE;
	}
L
Linus Torvalds 已提交
2437

2438
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2439 2440
}

2441
static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c)
J
Jamal Hadi Salim 已提交
2442
{
2443
	struct net *net = xs_net(x);
J
Jamal Hadi Salim 已提交
2444 2445
	struct sk_buff *skb;

2446
	skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
2447 2448 2449 2450 2451 2452
	if (skb == NULL)
		return -ENOMEM;

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

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

2456
static int xfrm_notify_sa_flush(const struct km_event *c)
2457
{
2458
	struct net *net = c->net;
2459 2460 2461
	struct xfrm_usersa_flush *p;
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2462
	int len = NLMSG_ALIGN(sizeof(struct xfrm_usersa_flush));
2463

2464
	skb = nlmsg_new(len, GFP_ATOMIC);
2465 2466 2467
	if (skb == NULL)
		return -ENOMEM;

2468
	nlh = nlmsg_put(skb, c->portid, c->seq, XFRM_MSG_FLUSHSA, sizeof(*p), 0);
2469 2470 2471 2472
	if (nlh == NULL) {
		kfree_skb(skb);
		return -EMSGSIZE;
	}
2473

2474
	p = nlmsg_data(nlh);
2475
	p->proto = c->data.proto;
2476

2477
	nlmsg_end(skb, nlh);
2478

2479
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
2480 2481
}

2482
static inline size_t xfrm_sa_len(struct xfrm_state *x)
2483
{
2484
	size_t l = 0;
2485 2486
	if (x->aead)
		l += nla_total_size(aead_len(x->aead));
2487 2488 2489 2490 2491
	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));
	}
2492
	if (x->ealg)
2493
		l += nla_total_size(xfrm_alg_len(x->ealg));
2494
	if (x->calg)
2495
		l += nla_total_size(sizeof(*x->calg));
2496
	if (x->encap)
2497
		l += nla_total_size(sizeof(*x->encap));
2498 2499
	if (x->tfcpad)
		l += nla_total_size(sizeof(x->tfcpad));
2500 2501
	if (x->replay_esn)
		l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn));
2502 2503 2504 2505 2506
	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));
2507 2508
	if (x->props.extra_flags)
		l += nla_total_size(sizeof(x->props.extra_flags));
2509

2510 2511
	/* Must count x->lastused as it may become non-zero behind our back. */
	l += nla_total_size(sizeof(u64));
2512 2513 2514 2515

	return l;
}

2516
static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c)
2517
{
2518
	struct net *net = xs_net(x);
2519
	struct xfrm_usersa_info *p;
2520
	struct xfrm_usersa_id *id;
2521 2522 2523
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
	int len = xfrm_sa_len(x);
2524
	int headlen, err;
2525 2526 2527

	headlen = sizeof(*p);
	if (c->event == XFRM_MSG_DELSA) {
2528
		len += nla_total_size(headlen);
2529
		headlen = sizeof(*id);
2530
		len += nla_total_size(sizeof(struct xfrm_mark));
2531
	}
2532
	len += NLMSG_ALIGN(headlen);
2533

2534
	skb = nlmsg_new(len, GFP_ATOMIC);
2535 2536 2537
	if (skb == NULL)
		return -ENOMEM;

2538
	nlh = nlmsg_put(skb, c->portid, c->seq, c->event, headlen, 0);
2539
	err = -EMSGSIZE;
2540
	if (nlh == NULL)
2541
		goto out_free_skb;
2542

2543
	p = nlmsg_data(nlh);
2544
	if (c->event == XFRM_MSG_DELSA) {
2545 2546
		struct nlattr *attr;

2547
		id = nlmsg_data(nlh);
2548 2549 2550 2551 2552
		memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
		id->spi = x->id.spi;
		id->family = x->props.family;
		id->proto = x->id.proto;

2553
		attr = nla_reserve(skb, XFRMA_SA, sizeof(*p));
2554
		err = -EMSGSIZE;
2555
		if (attr == NULL)
2556
			goto out_free_skb;
2557 2558

		p = nla_data(attr);
2559
	}
2560 2561 2562
	err = copy_to_user_state_extra(x, p, skb);
	if (err)
		goto out_free_skb;
2563

2564
	nlmsg_end(skb, nlh);
2565

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

2568
out_free_skb:
2569
	kfree_skb(skb);
2570
	return err;
2571 2572
}

2573
static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c)
2574 2575 2576
{

	switch (c->event) {
2577
	case XFRM_MSG_EXPIRE:
2578
		return xfrm_exp_state_notify(x, c);
J
Jamal Hadi Salim 已提交
2579 2580
	case XFRM_MSG_NEWAE:
		return xfrm_aevent_state_notify(x, c);
2581 2582 2583
	case XFRM_MSG_DELSA:
	case XFRM_MSG_UPDSA:
	case XFRM_MSG_NEWSA:
2584
		return xfrm_notify_sa(x, c);
2585
	case XFRM_MSG_FLUSHSA:
2586 2587
		return xfrm_notify_sa_flush(c);
	default:
S
stephen hemminger 已提交
2588 2589 2590
		printk(KERN_NOTICE "xfrm_user: Unknown SA event %d\n",
		       c->event);
		break;
2591 2592 2593 2594 2595 2596
	}

	return 0;

}

2597 2598 2599 2600 2601
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)
2602
	       + nla_total_size(sizeof(struct xfrm_mark))
2603 2604 2605 2606
	       + nla_total_size(xfrm_user_sec_ctx_size(x->security))
	       + userpolicy_type_attrsize();
}

L
Linus Torvalds 已提交
2607
static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
2608
			 struct xfrm_tmpl *xt, struct xfrm_policy *xp)
L
Linus Torvalds 已提交
2609
{
2610
	__u32 seq = xfrm_get_acqseq();
L
Linus Torvalds 已提交
2611 2612
	struct xfrm_user_acquire *ua;
	struct nlmsghdr *nlh;
2613
	int err;
L
Linus Torvalds 已提交
2614

2615 2616 2617
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2618

2619
	ua = nlmsg_data(nlh);
L
Linus Torvalds 已提交
2620 2621 2622
	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));
2623
	copy_to_user_policy(xp, &ua->policy, XFRM_POLICY_OUT);
L
Linus Torvalds 已提交
2624 2625 2626 2627 2628
	ua->aalgos = xt->aalgos;
	ua->ealgos = xt->ealgos;
	ua->calgos = xt->calgos;
	ua->seq = x->km.seq = seq;

2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639
	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 已提交
2640

2641
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2642 2643 2644
}

static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
2645
			     struct xfrm_policy *xp)
L
Linus Torvalds 已提交
2646
{
2647
	struct net *net = xs_net(x);
L
Linus Torvalds 已提交
2648 2649
	struct sk_buff *skb;

2650
	skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC);
L
Linus Torvalds 已提交
2651 2652 2653
	if (skb == NULL)
		return -ENOMEM;

2654
	if (build_acquire(skb, x, xt, xp) < 0)
L
Linus Torvalds 已提交
2655 2656
		BUG();

2657
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2658 2659 2660 2661 2662
}

/* User gives us xfrm_user_policy_info followed by an array of 0
 * or more templates.
 */
2663
static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
L
Linus Torvalds 已提交
2664 2665
					       u8 *data, int len, int *dir)
{
2666
	struct net *net = sock_net(sk);
L
Linus Torvalds 已提交
2667 2668 2669 2670 2671
	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;

2672
	switch (sk->sk_family) {
L
Linus Torvalds 已提交
2673 2674 2675 2676 2677 2678
	case AF_INET:
		if (opt != IP_XFRM_POLICY) {
			*dir = -EOPNOTSUPP;
			return NULL;
		}
		break;
E
Eric Dumazet 已提交
2679
#if IS_ENABLED(CONFIG_IPV6)
L
Linus Torvalds 已提交
2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698
	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));
2699
	if (validate_tmpl(nr, ut, p->sel.family))
L
Linus Torvalds 已提交
2700 2701
		return NULL;

2702 2703 2704
	if (p->dir > XFRM_POLICY_OUT)
		return NULL;

2705
	xp = xfrm_policy_alloc(net, GFP_ATOMIC);
L
Linus Torvalds 已提交
2706 2707 2708 2709 2710 2711
	if (xp == NULL) {
		*dir = -ENOBUFS;
		return NULL;
	}

	copy_from_user_policy(xp, p);
2712
	xp->type = XFRM_POLICY_TYPE_MAIN;
L
Linus Torvalds 已提交
2713 2714 2715 2716 2717 2718 2719
	copy_templates(xp, ut, nr);

	*dir = p->dir;

	return xp;
}

2720 2721 2722 2723 2724
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))
2725
	       + nla_total_size(sizeof(struct xfrm_mark))
2726 2727 2728
	       + userpolicy_type_attrsize();
}

L
Linus Torvalds 已提交
2729
static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
2730
			   int dir, const struct km_event *c)
L
Linus Torvalds 已提交
2731 2732
{
	struct xfrm_user_polexpire *upe;
J
Jamal Hadi Salim 已提交
2733
	int hard = c->data.hard;
2734 2735
	struct nlmsghdr *nlh;
	int err;
L
Linus Torvalds 已提交
2736

2737
	nlh = nlmsg_put(skb, c->portid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe), 0);
2738 2739
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2740

2741
	upe = nlmsg_data(nlh);
L
Linus Torvalds 已提交
2742
	copy_to_user_policy(xp, &upe->pol, dir);
2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753
	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 已提交
2754 2755
	upe->hard = !!hard;

2756
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2757 2758
}

2759
static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
L
Linus Torvalds 已提交
2760
{
2761
	struct net *net = xp_net(xp);
L
Linus Torvalds 已提交
2762 2763
	struct sk_buff *skb;

2764
	skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC);
L
Linus Torvalds 已提交
2765 2766 2767
	if (skb == NULL)
		return -ENOMEM;

J
Jamal Hadi Salim 已提交
2768
	if (build_polexpire(skb, xp, dir, c) < 0)
L
Linus Torvalds 已提交
2769 2770
		BUG();

2771
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2772 2773
}

2774
static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c)
2775
{
2776
	int len = nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
2777
	struct net *net = xp_net(xp);
2778
	struct xfrm_userpolicy_info *p;
2779
	struct xfrm_userpolicy_id *id;
2780 2781
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2782
	int headlen, err;
2783 2784 2785

	headlen = sizeof(*p);
	if (c->event == XFRM_MSG_DELPOLICY) {
2786
		len += nla_total_size(headlen);
2787 2788
		headlen = sizeof(*id);
	}
2789
	len += userpolicy_type_attrsize();
2790
	len += nla_total_size(sizeof(struct xfrm_mark));
2791
	len += NLMSG_ALIGN(headlen);
2792

2793
	skb = nlmsg_new(len, GFP_ATOMIC);
2794 2795 2796
	if (skb == NULL)
		return -ENOMEM;

2797
	nlh = nlmsg_put(skb, c->portid, c->seq, c->event, headlen, 0);
2798
	err = -EMSGSIZE;
2799
	if (nlh == NULL)
2800
		goto out_free_skb;
2801

2802
	p = nlmsg_data(nlh);
2803
	if (c->event == XFRM_MSG_DELPOLICY) {
2804 2805
		struct nlattr *attr;

2806
		id = nlmsg_data(nlh);
2807 2808 2809 2810 2811 2812 2813
		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));

2814
		attr = nla_reserve(skb, XFRMA_POLICY, sizeof(*p));
2815
		err = -EMSGSIZE;
2816
		if (attr == NULL)
2817
			goto out_free_skb;
2818 2819

		p = nla_data(attr);
2820
	}
2821 2822

	copy_to_user_policy(xp, p, dir);
2823 2824 2825 2826 2827 2828 2829
	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;
2830

2831
	nlmsg_end(skb, nlh);
2832

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

2835
out_free_skb:
2836
	kfree_skb(skb);
2837
	return err;
2838 2839
}

2840
static int xfrm_notify_policy_flush(const struct km_event *c)
2841
{
2842
	struct net *net = c->net;
2843 2844
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2845
	int err;
2846

2847
	skb = nlmsg_new(userpolicy_type_attrsize(), GFP_ATOMIC);
2848 2849 2850
	if (skb == NULL)
		return -ENOMEM;

2851
	nlh = nlmsg_put(skb, c->portid, c->seq, XFRM_MSG_FLUSHPOLICY, 0, 0);
2852
	err = -EMSGSIZE;
2853
	if (nlh == NULL)
2854 2855 2856 2857
		goto out_free_skb;
	err = copy_to_user_policy_type(c->data.type, skb);
	if (err)
		goto out_free_skb;
2858

2859
	nlmsg_end(skb, nlh);
2860

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

2863
out_free_skb:
2864
	kfree_skb(skb);
2865
	return err;
2866 2867
}

2868
static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
2869 2870 2871
{

	switch (c->event) {
2872 2873 2874
	case XFRM_MSG_NEWPOLICY:
	case XFRM_MSG_UPDPOLICY:
	case XFRM_MSG_DELPOLICY:
2875
		return xfrm_notify_policy(xp, dir, c);
2876
	case XFRM_MSG_FLUSHPOLICY:
2877
		return xfrm_notify_policy_flush(c);
2878
	case XFRM_MSG_POLEXPIRE:
2879 2880
		return xfrm_exp_policy_notify(xp, dir, c);
	default:
S
stephen hemminger 已提交
2881 2882
		printk(KERN_NOTICE "xfrm_user: Unknown Policy event %d\n",
		       c->event);
2883 2884 2885 2886 2887 2888
	}

	return 0;

}

2889 2890 2891 2892 2893
static inline size_t xfrm_report_msgsize(void)
{
	return NLMSG_ALIGN(sizeof(struct xfrm_user_report));
}

2894 2895 2896 2897 2898 2899
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;

2900 2901 2902
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
2903

2904
	ur = nlmsg_data(nlh);
2905 2906 2907
	ur->proto = proto;
	memcpy(&ur->sel, sel, sizeof(ur->sel));

2908 2909 2910 2911 2912 2913 2914
	if (addr) {
		int err = nla_put(skb, XFRMA_COADDR, sizeof(*addr), addr);
		if (err) {
			nlmsg_cancel(skb, nlh);
			return err;
		}
	}
2915
	return nlmsg_end(skb, nlh);
2916 2917
}

2918 2919
static int xfrm_send_report(struct net *net, u8 proto,
			    struct xfrm_selector *sel, xfrm_address_t *addr)
2920 2921 2922
{
	struct sk_buff *skb;

2923
	skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC);
2924 2925 2926 2927 2928 2929
	if (skb == NULL)
		return -ENOMEM;

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

2930
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC);
2931 2932
}

2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965
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)
{
2966
	struct net *net = xs_net(x);
2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981
	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();

2982
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC);
2983 2984
}

2985 2986 2987 2988 2989
static bool xfrm_is_alive(const struct km_event *c)
{
	return (bool)xfrm_acquire_is_on(c->net);
}

L
Linus Torvalds 已提交
2990 2991 2992 2993 2994 2995
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,
2996
	.report		= xfrm_send_report,
2997
	.migrate	= xfrm_send_migrate,
2998
	.new_mapping	= xfrm_send_mapping,
2999
	.is_alive	= xfrm_is_alive,
L
Linus Torvalds 已提交
3000 3001
};

3002
static int __net_init xfrm_user_net_init(struct net *net)
L
Linus Torvalds 已提交
3003
{
3004
	struct sock *nlsk;
3005 3006 3007 3008
	struct netlink_kernel_cfg cfg = {
		.groups	= XFRMNLGRP_MAX,
		.input	= xfrm_netlink_rcv,
	};
3009

3010
	nlsk = netlink_kernel_create(net, NETLINK_XFRM, &cfg);
3011
	if (nlsk == NULL)
L
Linus Torvalds 已提交
3012
		return -ENOMEM;
3013
	net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */
3014
	rcu_assign_pointer(net->xfrm.nlsk, nlsk);
L
Linus Torvalds 已提交
3015 3016 3017
	return 0;
}

3018
static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list)
L
Linus Torvalds 已提交
3019
{
3020 3021
	struct net *net;
	list_for_each_entry(net, net_exit_list, exit_list)
3022
		RCU_INIT_POINTER(net->xfrm.nlsk, NULL);
3023 3024 3025
	synchronize_net();
	list_for_each_entry(net, net_exit_list, exit_list)
		netlink_kernel_release(net->xfrm.nlsk_stash);
L
Linus Torvalds 已提交
3026 3027
}

3028
static struct pernet_operations xfrm_user_net_ops = {
3029 3030
	.init	    = xfrm_user_net_init,
	.exit_batch = xfrm_user_net_exit,
3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053
};

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 已提交
3054 3055 3056
module_init(xfrm_user_init);
module_exit(xfrm_user_exit);
MODULE_LICENSE("GPL");
3057
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
3058