xfrm_user.c 70.5 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 147
	if (p->id.proto != IPPROTO_ESP)
		return -EINVAL;

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

	return 0;
}
153

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

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

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

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

	err = -EINVAL;
	switch (p->id.proto) {
	case IPPROTO_AH:
179 180
		if ((!attrs[XFRMA_ALG_AUTH]	&&
		     !attrs[XFRMA_ALG_AUTH_TRUNC]) ||
181
		    attrs[XFRMA_ALG_AEAD]	||
182
		    attrs[XFRMA_ALG_CRYPT]	||
183 184
		    attrs[XFRMA_ALG_COMP]	||
		    attrs[XFRMA_TFCPAD])
L
Linus Torvalds 已提交
185 186 187 188
			goto out;
		break;

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

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

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

L
Linus Torvalds 已提交
232 233
	default:
		goto out;
234
	}
L
Linus Torvalds 已提交
235

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

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

	default:
		goto out;
261
	}
L
Linus Torvalds 已提交
262 263 264 265 266 267 268 269

	err = 0;

out:
	return err;
}

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

	if (!rta)
		return 0;

279
	ualg = nla_data(rta);
L
Linus Torvalds 已提交
280 281 282 283 284 285

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

286
	p = kmemdup(ualg, xfrm_alg_len(ualg), GFP_KERNEL);
L
Linus Torvalds 已提交
287 288 289
	if (!p)
		return -ENOMEM;

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

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
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;
339 340
	if ((ualg->alg_trunc_len / 8) > MAX_AH_AUTH_LEN ||
	    ualg->alg_trunc_len > algo->uinfo.auth.icv_fullbits)
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
		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;
}

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

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

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

	up = nla_data(rp);
391
	ulen = xfrm_replay_state_esn_len(up);
392

393
	if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
394 395 396 397 398
		return -EINVAL;

	return 0;
}

399 400 401 402 403
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;
404
	int klen, ulen;
405 406 407 408 409

	if (!rta)
		return 0;

	up = nla_data(rta);
410 411
	klen = xfrm_replay_state_esn_len(up);
	ulen = nla_len(rta) >= klen ? klen : sizeof(*up);
412

413
	p = kzalloc(klen, GFP_KERNEL);
414 415 416
	if (!p)
		return -ENOMEM;

417
	pp = kzalloc(klen, GFP_KERNEL);
418 419 420 421 422
	if (!pp) {
		kfree(p);
		return -ENOMEM;
	}

423 424 425
	memcpy(p, up, ulen);
	memcpy(pp, up, ulen);

426 427 428 429 430 431
	*replay_esn = p;
	*preplay_esn = pp;

	return 0;
}

432
static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
433 434 435 436 437 438 439 440 441 442
{
	int len = 0;

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

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

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

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

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

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

499
	if (et)
500
		x->replay_maxage = nla_get_u32(et);
J
Jamal Hadi Salim 已提交
501

502
	if (rt)
503
		x->replay_maxdiff = nla_get_u32(rt);
J
Jamal Hadi Salim 已提交
504 505
}

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

	if (!x)
		goto error_no_put;

	copy_from_user_state(x, p);

519 520 521
	if (attrs[XFRMA_SA_EXTRA_FLAGS])
		x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);

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

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

549 550 551
	if (attrs[XFRMA_TFCPAD])
		x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]);

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

559 560
	xfrm_mark_get(attrs, &x->mark);

561
	err = __xfrm_init_state(x, false);
L
Linus Torvalds 已提交
562 563 564
	if (err)
		goto error;

565 566
	if (attrs[XFRMA_SEC_CTX] &&
	    security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX])))
567 568
		goto error;

569 570 571 572
	if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
					       attrs[XFRMA_REPLAY_ESN_VAL])))
		goto error;

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

578 579
	if ((err = xfrm_init_replay(x)))
		goto error;
J
Jamal Hadi Salim 已提交
580

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

	return x;

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

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

606
	err = verify_newsa_info(p, attrs);
L
Linus Torvalds 已提交
607 608 609
	if (err)
		return err;

610
	x = xfrm_state_construct(net, p, attrs, &err);
L
Linus Torvalds 已提交
611 612 613
	if (!x)
		return err;

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

620
	security_task_getsecid(current, &sid);
621
	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
622

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

629
	c.seq = nlh->nlmsg_seq;
630
	c.portid = nlh->nlmsg_pid;
631
	c.event = nlh->nlmsg_type;
632 633

	km_state_notify(x, &c);
634
out:
635
	xfrm_state_put(x);
L
Linus Torvalds 已提交
636 637 638
	return err;
}

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

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

655
		verify_one_addr(attrs, XFRMA_SRCADDR, &saddr);
656 657 658 659 660
		if (!saddr) {
			err = -EINVAL;
			goto out;
		}

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

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

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

685
	x = xfrm_user_state_lookup(net, p, attrs, &err);
L
Linus Torvalds 已提交
686
	if (x == NULL)
687
		return err;
L
Linus Torvalds 已提交
688

689
	if ((err = security_xfrm_state_delete(x)) != 0)
C
Catherine Zhang 已提交
690 691
		goto out;

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

697
	err = xfrm_state_delete(x);
J
Joy Latten 已提交
698

C
Catherine Zhang 已提交
699 700
	if (err < 0)
		goto out;
701 702

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

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

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

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

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

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

	return 0;
}

777 778 779 780
/* 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 已提交
781
{
782
	int ret = 0;
783

784
	copy_to_user_state(x, p);
785

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

793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 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
	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;
850 851 852 853 854 855 856 857 858 859 860
}

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;

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

877 878 879 880 881 882 883
static int xfrm_dump_sa_done(struct netlink_callback *cb)
{
	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
	xfrm_state_walk_done(walk);
	return 0;
}

L
Linus Torvalds 已提交
884 885
static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
{
886
	struct net *net = sock_net(skb->sk);
887
	struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
L
Linus Torvalds 已提交
888 889
	struct xfrm_dump_info info;

890 891 892
	BUILD_BUG_ON(sizeof(struct xfrm_state_walk) >
		     sizeof(cb->args) - sizeof(cb->args[0]));

L
Linus Torvalds 已提交
893 894 895 896
	info.in_skb = cb->skb;
	info.out_skb = skb;
	info.nlmsg_seq = cb->nlh->nlmsg_seq;
	info.nlmsg_flags = NLM_F_MULTI;
897 898 899 900 901 902

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

903
	(void) xfrm_state_walk(net, walk, dump_one_state, &info);
L
Linus Torvalds 已提交
904 905 906 907 908 909 910 911 912

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

915
	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
L
Linus Torvalds 已提交
916 917 918 919 920 921 922 923
	if (!skb)
		return ERR_PTR(-ENOMEM);

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

924 925
	err = dump_one_state(x, 0, &info);
	if (err) {
L
Linus Torvalds 已提交
926
		kfree_skb(skb);
927
		return ERR_PTR(err);
L
Linus Torvalds 已提交
928 929 930 931 932
	}

	return skb;
}

933 934 935 936 937 938 939
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));
}

940
static int build_spdinfo(struct sk_buff *skb, struct net *net,
941
			 u32 portid, u32 seq, u32 flags)
J
Jamal Hadi Salim 已提交
942
{
943 944 945
	struct xfrmk_spdinfo si;
	struct xfrmu_spdinfo spc;
	struct xfrmu_spdhinfo sph;
J
Jamal Hadi Salim 已提交
946
	struct nlmsghdr *nlh;
947
	int err;
J
Jamal Hadi Salim 已提交
948 949
	u32 *f;

950
	nlh = nlmsg_put(skb, portid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0);
L
Lucas De Marchi 已提交
951
	if (nlh == NULL) /* shouldn't really happen ... */
J
Jamal Hadi Salim 已提交
952 953 954 955
		return -EMSGSIZE;

	f = nlmsg_data(nlh);
	*f = flags;
956
	xfrm_spd_getinfo(net, &si);
957 958 959 960 961 962 963 964 965
	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;

966 967 968 969 970 971 972
	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 已提交
973 974 975 976 977

	return nlmsg_end(skb, nlh);
}

static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
978
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
979
{
980
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
981
	struct sk_buff *r_skb;
982
	u32 *flags = nlmsg_data(nlh);
983
	u32 sportid = NETLINK_CB(skb).portid;
J
Jamal Hadi Salim 已提交
984 985
	u32 seq = nlh->nlmsg_seq;

986
	r_skb = nlmsg_new(xfrm_spdinfo_msgsize(), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
987 988 989
	if (r_skb == NULL)
		return -ENOMEM;

990
	if (build_spdinfo(r_skb, net, sportid, seq, *flags) < 0)
J
Jamal Hadi Salim 已提交
991 992
		BUG();

993
	return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid);
J
Jamal Hadi Salim 已提交
994 995
}

996 997 998 999 1000 1001 1002
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 */
}

1003
static int build_sadinfo(struct sk_buff *skb, struct net *net,
1004
			 u32 portid, u32 seq, u32 flags)
J
Jamal Hadi Salim 已提交
1005
{
1006 1007
	struct xfrmk_sadinfo si;
	struct xfrmu_sadhinfo sh;
J
Jamal Hadi Salim 已提交
1008
	struct nlmsghdr *nlh;
1009
	int err;
J
Jamal Hadi Salim 已提交
1010 1011
	u32 *f;

1012
	nlh = nlmsg_put(skb, portid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0);
L
Lucas De Marchi 已提交
1013
	if (nlh == NULL) /* shouldn't really happen ... */
J
Jamal Hadi Salim 已提交
1014 1015 1016 1017
		return -EMSGSIZE;

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

1020 1021 1022
	sh.sadhmcnt = si.sadhmcnt;
	sh.sadhcnt = si.sadhcnt;

1023 1024 1025 1026 1027 1028 1029
	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 已提交
1030 1031 1032 1033 1034

	return nlmsg_end(skb, nlh);
}

static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
1035
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1036
{
1037
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1038
	struct sk_buff *r_skb;
1039
	u32 *flags = nlmsg_data(nlh);
1040
	u32 sportid = NETLINK_CB(skb).portid;
J
Jamal Hadi Salim 已提交
1041 1042
	u32 seq = nlh->nlmsg_seq;

1043
	r_skb = nlmsg_new(xfrm_sadinfo_msgsize(), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
1044 1045 1046
	if (r_skb == NULL)
		return -ENOMEM;

1047
	if (build_sadinfo(r_skb, net, sportid, seq, *flags) < 0)
J
Jamal Hadi Salim 已提交
1048 1049
		BUG();

1050
	return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid);
J
Jamal Hadi Salim 已提交
1051 1052
}

1053
static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1054
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1055
{
1056
	struct net *net = sock_net(skb->sk);
1057
	struct xfrm_usersa_id *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1058 1059
	struct xfrm_state *x;
	struct sk_buff *resp_skb;
1060
	int err = -ESRCH;
L
Linus Torvalds 已提交
1061

1062
	x = xfrm_user_state_lookup(net, p, attrs, &err);
L
Linus Torvalds 已提交
1063 1064 1065 1066 1067 1068 1069
	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 {
1070
		err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);
L
Linus Torvalds 已提交
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
	}
	xfrm_state_put(x);
out_noput:
	return err;
}

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

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

	default:
		return -EINVAL;
1092
	}
L
Linus Torvalds 已提交
1093 1094 1095 1096 1097 1098 1099

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

	return 0;
}

1100
static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
1101
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1102
{
1103
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1104 1105 1106 1107 1108 1109
	struct xfrm_state *x;
	struct xfrm_userspi_info *p;
	struct sk_buff *resp_skb;
	xfrm_address_t *daddr;
	int family;
	int err;
1110 1111
	u32 mark;
	struct xfrm_mark m;
L
Linus Torvalds 已提交
1112

1113
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1114 1115 1116 1117 1118 1119 1120 1121
	err = verify_userspi_info(p);
	if (err)
		goto out_noput;

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

	x = NULL;
1122 1123

	mark = xfrm_mark_get(attrs, &m);
L
Linus Torvalds 已提交
1124
	if (p->info.seq) {
1125
		x = xfrm_find_acq_byseq(net, mark, p->info.seq);
1126
		if (x && !xfrm_addr_equal(&x->id.daddr, daddr, family)) {
L
Linus Torvalds 已提交
1127 1128 1129 1130 1131 1132
			xfrm_state_put(x);
			x = NULL;
		}
	}

	if (!x)
1133
		x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid,
L
Linus Torvalds 已提交
1134 1135 1136 1137 1138 1139 1140
				  p->info.id.proto, daddr,
				  &p->info.saddr, 1,
				  family);
	err = -ENOENT;
	if (x == NULL)
		goto out_noput;

1141 1142 1143
	err = xfrm_alloc_spi(x, p->min, p->max);
	if (err)
		goto out;
L
Linus Torvalds 已提交
1144

1145
	resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq);
L
Linus Torvalds 已提交
1146 1147 1148 1149 1150
	if (IS_ERR(resp_skb)) {
		err = PTR_ERR(resp_skb);
		goto out;
	}

1151
	err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);
L
Linus Torvalds 已提交
1152 1153 1154 1155 1156 1157 1158

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

1159
static int verify_policy_dir(u8 dir)
L
Linus Torvalds 已提交
1160 1161 1162 1163 1164 1165 1166 1167 1168
{
	switch (dir) {
	case XFRM_POLICY_IN:
	case XFRM_POLICY_OUT:
	case XFRM_POLICY_FWD:
		break;

	default:
		return -EINVAL;
1169
	}
L
Linus Torvalds 已提交
1170 1171 1172 1173

	return 0;
}

1174
static int verify_policy_type(u8 type)
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
{
	switch (type) {
	case XFRM_POLICY_TYPE_MAIN:
#ifdef CONFIG_XFRM_SUB_POLICY
	case XFRM_POLICY_TYPE_SUB:
#endif
		break;

	default:
		return -EINVAL;
1185
	}
1186 1187 1188 1189

	return 0;
}

L
Linus Torvalds 已提交
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
{
	switch (p->share) {
	case XFRM_SHARE_ANY:
	case XFRM_SHARE_SESSION:
	case XFRM_SHARE_USER:
	case XFRM_SHARE_UNIQUE:
		break;

	default:
		return -EINVAL;
1201
	}
L
Linus Torvalds 已提交
1202 1203 1204 1205 1206 1207 1208 1209

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

	default:
		return -EINVAL;
1210
	}
L
Linus Torvalds 已提交
1211 1212 1213 1214 1215 1216

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

	case AF_INET6:
E
Eric Dumazet 已提交
1217
#if IS_ENABLED(CONFIG_IPV6)
L
Linus Torvalds 已提交
1218 1219 1220 1221 1222 1223 1224
		break;
#else
		return  -EAFNOSUPPORT;
#endif

	default:
		return -EINVAL;
1225
	}
L
Linus Torvalds 已提交
1226 1227 1228 1229

	return verify_policy_dir(p->dir);
}

1230
static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs)
1231
{
1232
	struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1233 1234 1235 1236 1237
	struct xfrm_user_sec_ctx *uctx;

	if (!rt)
		return 0;

1238
	uctx = nla_data(rt);
1239
	return security_xfrm_policy_alloc(&pol->security, uctx);
1240 1241
}

L
Linus Torvalds 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
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;
1261 1262
		/* If all masks are ~0, then we allow all algorithms. */
		t->allalgs = !~(t->aalgos & t->ealgos & t->calgos);
1263
		t->encap_family = ut->family;
L
Linus Torvalds 已提交
1264 1265 1266
	}
}

1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
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 已提交
1288
#if IS_ENABLED(CONFIG_IPV6)
1289 1290 1291 1292 1293
		case AF_INET6:
			break;
#endif
		default:
			return -EINVAL;
1294
		}
1295 1296 1297 1298 1299
	}

	return 0;
}

1300
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs)
L
Linus Torvalds 已提交
1301
{
1302
	struct nlattr *rt = attrs[XFRMA_TMPL];
L
Linus Torvalds 已提交
1303 1304 1305 1306

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

1311 1312 1313
		err = validate_tmpl(nr, utmpl, pol->family);
		if (err)
			return err;
L
Linus Torvalds 已提交
1314

1315
		copy_templates(pol, utmpl, nr);
L
Linus Torvalds 已提交
1316 1317 1318 1319
	}
	return 0;
}

1320
static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs)
1321
{
1322
	struct nlattr *rt = attrs[XFRMA_POLICY_TYPE];
1323
	struct xfrm_userpolicy_type *upt;
1324
	u8 type = XFRM_POLICY_TYPE_MAIN;
1325 1326 1327
	int err;

	if (rt) {
1328
		upt = nla_data(rt);
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
		type = upt->type;
	}

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

	*tp = type;
	return 0;
}

L
Linus Torvalds 已提交
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
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)
{
1354
	memset(p, 0, sizeof(*p));
L
Linus Torvalds 已提交
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366
	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 */
}

1367
static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp)
L
Linus Torvalds 已提交
1368
{
1369
	struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL);
L
Linus Torvalds 已提交
1370 1371 1372 1373 1374 1375 1376 1377
	int err;

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

	copy_from_user_policy(xp, p);
1378

1379
	err = copy_from_user_policy_type(&xp->type, attrs);
1380 1381 1382
	if (err)
		goto error;

1383 1384
	if (!(err = copy_from_user_tmpl(xp, attrs)))
		err = copy_from_user_sec_ctx(xp, attrs);
1385 1386
	if (err)
		goto error;
L
Linus Torvalds 已提交
1387

1388 1389
	xfrm_mark_get(attrs, &xp->mark);

L
Linus Torvalds 已提交
1390
	return xp;
1391 1392
 error:
	*errp = err;
H
Herbert Xu 已提交
1393
	xp->walk.dead = 1;
1394
	xfrm_policy_destroy(xp);
1395
	return NULL;
L
Linus Torvalds 已提交
1396 1397
}

1398
static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1399
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1400
{
1401
	struct net *net = sock_net(skb->sk);
1402
	struct xfrm_userpolicy_info *p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1403
	struct xfrm_policy *xp;
1404
	struct km_event c;
L
Linus Torvalds 已提交
1405 1406
	int err;
	int excl;
1407
	kuid_t loginuid = audit_get_loginuid(current);
1408
	unsigned int sessionid = audit_get_sessionid(current);
1409
	u32 sid;
L
Linus Torvalds 已提交
1410 1411

	err = verify_newpolicy_info(p);
1412 1413
	if (err)
		return err;
1414
	err = verify_sec_ctx_len(attrs);
L
Linus Torvalds 已提交
1415 1416 1417
	if (err)
		return err;

1418
	xp = xfrm_policy_construct(net, p, attrs, &err);
L
Linus Torvalds 已提交
1419 1420 1421
	if (!xp)
		return err;

L
Lucas De Marchi 已提交
1422
	/* shouldn't excl be based on nlh flags??
1423 1424 1425
	 * 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 已提交
1426 1427
	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
	err = xfrm_policy_insert(p->dir, xp, excl);
1428
	security_task_getsecid(current, &sid);
1429
	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
1430

L
Linus Torvalds 已提交
1431
	if (err) {
1432
		security_xfrm_policy_free(xp->security);
L
Linus Torvalds 已提交
1433 1434 1435 1436
		kfree(xp);
		return err;
	}

1437
	c.event = nlh->nlmsg_type;
1438
	c.seq = nlh->nlmsg_seq;
1439
	c.portid = nlh->nlmsg_pid;
1440 1441
	km_policy_notify(xp, p->dir, &c);

L
Linus Torvalds 已提交
1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
	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];

1459
		memset(up, 0, sizeof(*up));
L
Linus Torvalds 已提交
1460
		memcpy(&up->id, &kp->id, sizeof(up->id));
1461
		up->family = kp->encap_family;
L
Linus Torvalds 已提交
1462 1463 1464 1465 1466 1467 1468 1469 1470
		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;
	}
1471

1472 1473
	return nla_put(skb, XFRMA_TMPL,
		       sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr, vec);
1474 1475 1476 1477 1478 1479
}

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);
1480 1481
	}
	return 0;
1482
}
1483

1484 1485
static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
{
1486
	if (xp->security)
1487 1488
		return copy_sec_ctx(xp->security, skb);
	return 0;
1489
}
1490 1491 1492 1493 1494 1495 1496 1497
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
}
1498

1499
#ifdef CONFIG_XFRM_SUB_POLICY
1500
static int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
1501
{
1502 1503 1504
	struct xfrm_userpolicy_type upt = {
		.type = type,
	};
1505

1506
	return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
1507 1508 1509
}

#else
1510
static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb)
1511 1512 1513 1514 1515
{
	return 0;
}
#endif

L
Linus Torvalds 已提交
1516 1517 1518 1519 1520 1521 1522
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;
1523
	int err;
L
Linus Torvalds 已提交
1524

1525
	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, sp->nlmsg_seq,
1526 1527 1528
			XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
1529

1530
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1531
	copy_to_user_policy(xp, p, dir);
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542
	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;
	}
1543
	nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
1544 1545 1546
	return 0;
}

1547 1548 1549 1550 1551 1552 1553 1554
static int xfrm_dump_policy_done(struct netlink_callback *cb)
{
	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];

	xfrm_policy_walk_done(walk);
	return 0;
}

L
Linus Torvalds 已提交
1555 1556
static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
{
1557
	struct net *net = sock_net(skb->sk);
1558
	struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
L
Linus Torvalds 已提交
1559 1560
	struct xfrm_dump_info info;

1561 1562 1563
	BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
		     sizeof(cb->args) - sizeof(cb->args[0]));

L
Linus Torvalds 已提交
1564 1565 1566 1567
	info.in_skb = cb->skb;
	info.out_skb = skb;
	info.nlmsg_seq = cb->nlh->nlmsg_seq;
	info.nlmsg_flags = NLM_F_MULTI;
1568 1569 1570 1571 1572 1573

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

1574
	(void) xfrm_policy_walk(net, walk, dump_one_policy, &info);
L
Linus Torvalds 已提交
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584

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

1587
	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
L
Linus Torvalds 已提交
1588 1589 1590 1591 1592 1593 1594 1595
	if (!skb)
		return ERR_PTR(-ENOMEM);

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

1596 1597
	err = dump_one_policy(xp, dir, 0, &info);
	if (err) {
L
Linus Torvalds 已提交
1598
		kfree_skb(skb);
1599
		return ERR_PTR(err);
L
Linus Torvalds 已提交
1600 1601 1602 1603 1604
	}

	return skb;
}

1605
static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1606
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1607
{
1608
	struct net *net = sock_net(skb->sk);
L
Linus Torvalds 已提交
1609 1610
	struct xfrm_policy *xp;
	struct xfrm_userpolicy_id *p;
1611
	u8 type = XFRM_POLICY_TYPE_MAIN;
L
Linus Torvalds 已提交
1612
	int err;
1613
	struct km_event c;
L
Linus Torvalds 已提交
1614
	int delete;
1615 1616
	struct xfrm_mark m;
	u32 mark = xfrm_mark_get(attrs, &m);
L
Linus Torvalds 已提交
1617

1618
	p = nlmsg_data(nlh);
L
Linus Torvalds 已提交
1619 1620
	delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;

1621
	err = copy_from_user_policy_type(&type, attrs);
1622 1623 1624
	if (err)
		return err;

L
Linus Torvalds 已提交
1625 1626 1627 1628 1629
	err = verify_policy_dir(p->dir);
	if (err)
		return err;

	if (p->index)
1630
		xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err);
1631
	else {
1632
		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1633
		struct xfrm_sec_ctx *ctx;
1634

1635
		err = verify_sec_ctx_len(attrs);
1636 1637 1638
		if (err)
			return err;

1639
		ctx = NULL;
1640
		if (rt) {
1641
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1642

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

1669
		security_task_getsecid(current, &sid);
1670 1671
		xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
					 sid);
1672 1673

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

1676
		c.data.byid = p->index;
1677
		c.event = nlh->nlmsg_type;
1678
		c.seq = nlh->nlmsg_seq;
1679
		c.portid = nlh->nlmsg_pid;
1680
		km_policy_notify(xp, p->dir, &c);
L
Linus Torvalds 已提交
1681 1682
	}

C
Catherine Zhang 已提交
1683
out:
1684
	xfrm_pol_put(xp);
1685 1686
	if (delete && err == 0)
		xfrm_garbage_collect(net);
L
Linus Torvalds 已提交
1687 1688 1689
	return err;
}

1690
static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1691
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1692
{
1693
	struct net *net = sock_net(skb->sk);
1694
	struct km_event c;
1695
	struct xfrm_usersa_flush *p = nlmsg_data(nlh);
J
Joy Latten 已提交
1696
	struct xfrm_audit audit_info;
1697
	int err;
L
Linus Torvalds 已提交
1698

1699 1700 1701
	audit_info.loginuid = audit_get_loginuid(current);
	audit_info.sessionid = audit_get_sessionid(current);
	security_task_getsecid(current, &audit_info.secid);
1702
	err = xfrm_state_flush(net, p->proto, &audit_info);
1703 1704 1705
	if (err) {
		if (err == -ESRCH) /* empty table */
			return 0;
1706
		return err;
1707
	}
1708
	c.data.proto = p->proto;
1709
	c.event = nlh->nlmsg_type;
1710
	c.seq = nlh->nlmsg_seq;
1711
	c.portid = nlh->nlmsg_pid;
1712
	c.net = net;
1713 1714
	km_state_notify(NULL, &c);

L
Linus Torvalds 已提交
1715 1716 1717
	return 0;
}

1718
static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x)
1719
{
1720 1721 1722 1723
	size_t replay_size = x->replay_esn ?
			      xfrm_replay_state_esn_len(x->replay_esn) :
			      sizeof(struct xfrm_replay_state);

1724
	return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
1725
	       + nla_total_size(replay_size)
1726
	       + nla_total_size(sizeof(struct xfrm_lifetime_cur))
1727
	       + nla_total_size(sizeof(struct xfrm_mark))
1728 1729 1730
	       + nla_total_size(4) /* XFRM_AE_RTHR */
	       + nla_total_size(4); /* XFRM_AE_ETHR */
}
J
Jamal Hadi Salim 已提交
1731

1732
static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
J
Jamal Hadi Salim 已提交
1733 1734 1735
{
	struct xfrm_aevent_id *id;
	struct nlmsghdr *nlh;
1736
	int err;
J
Jamal Hadi Salim 已提交
1737

1738
	nlh = nlmsg_put(skb, c->portid, c->seq, XFRM_MSG_NEWAE, sizeof(*id), 0);
1739 1740
	if (nlh == NULL)
		return -EMSGSIZE;
J
Jamal Hadi Salim 已提交
1741

1742
	id = nlmsg_data(nlh);
1743
	memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr));
J
Jamal Hadi Salim 已提交
1744 1745 1746
	id->sa_id.spi = x->id.spi;
	id->sa_id.family = x->props.family;
	id->sa_id.proto = x->id.proto;
1747 1748
	memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr));
	id->reqid = x->props.reqid;
J
Jamal Hadi Salim 已提交
1749 1750
	id->flags = c->data.aevent;

1751
	if (x->replay_esn) {
1752 1753 1754
		err = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
			      xfrm_replay_state_esn_len(x->replay_esn),
			      x->replay_esn);
1755
	} else {
1756 1757
		err = nla_put(skb, XFRMA_REPLAY_VAL, sizeof(x->replay),
			      &x->replay);
1758
	}
1759 1760 1761 1762 1763
	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 已提交
1764

1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
	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;
1779

1780
	return nlmsg_end(skb, nlh);
J
Jamal Hadi Salim 已提交
1781

1782
out_cancel:
1783
	nlmsg_cancel(skb, nlh);
1784
	return err;
J
Jamal Hadi Salim 已提交
1785 1786
}

1787
static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1788
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1789
{
1790
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1791 1792 1793 1794
	struct xfrm_state *x;
	struct sk_buff *r_skb;
	int err;
	struct km_event c;
1795 1796
	u32 mark;
	struct xfrm_mark m;
1797
	struct xfrm_aevent_id *p = nlmsg_data(nlh);
J
Jamal Hadi Salim 已提交
1798 1799
	struct xfrm_usersa_id *id = &p->sa_id;

1800 1801 1802
	mark = xfrm_mark_get(attrs, &m);

	x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
1803
	if (x == NULL)
J
Jamal Hadi Salim 已提交
1804
		return -ESRCH;
1805 1806 1807 1808 1809

	r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
	if (r_skb == NULL) {
		xfrm_state_put(x);
		return -ENOMEM;
J
Jamal Hadi Salim 已提交
1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
	}

	/*
	 * 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;
1820
	c.portid = nlh->nlmsg_pid;
J
Jamal Hadi Salim 已提交
1821 1822 1823

	if (build_aevent(r_skb, x, &c) < 0)
		BUG();
1824
	err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).portid);
J
Jamal Hadi Salim 已提交
1825 1826 1827 1828 1829
	spin_unlock_bh(&x->lock);
	xfrm_state_put(x);
	return err;
}

1830
static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1831
		struct nlattr **attrs)
J
Jamal Hadi Salim 已提交
1832
{
1833
	struct net *net = sock_net(skb->sk);
J
Jamal Hadi Salim 已提交
1834 1835 1836
	struct xfrm_state *x;
	struct km_event c;
	int err = - EINVAL;
1837 1838
	u32 mark = 0;
	struct xfrm_mark m;
1839
	struct xfrm_aevent_id *p = nlmsg_data(nlh);
1840
	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
1841
	struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
1842
	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
J
Jamal Hadi Salim 已提交
1843

1844
	if (!lt && !rp && !re)
J
Jamal Hadi Salim 已提交
1845 1846 1847 1848 1849 1850
		return err;

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

1851 1852 1853
	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 已提交
1854 1855 1856 1857 1858 1859
	if (x == NULL)
		return -ESRCH;

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

1860
	err = xfrm_replay_verify_len(x->replay_esn, re);
1861 1862 1863
	if (err)
		goto out;

J
Jamal Hadi Salim 已提交
1864
	spin_lock_bh(&x->lock);
1865
	xfrm_update_ae_params(x, attrs, 1);
J
Jamal Hadi Salim 已提交
1866 1867 1868 1869
	spin_unlock_bh(&x->lock);

	c.event = nlh->nlmsg_type;
	c.seq = nlh->nlmsg_seq;
1870
	c.portid = nlh->nlmsg_pid;
J
Jamal Hadi Salim 已提交
1871 1872 1873 1874 1875 1876 1877 1878
	c.data.aevent = XFRM_AE_CU;
	km_state_notify(x, &c);
	err = 0;
out:
	xfrm_state_put(x);
	return err;
}

1879
static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1880
		struct nlattr **attrs)
L
Linus Torvalds 已提交
1881
{
1882
	struct net *net = sock_net(skb->sk);
1883
	struct km_event c;
1884
	u8 type = XFRM_POLICY_TYPE_MAIN;
1885
	int err;
J
Joy Latten 已提交
1886
	struct xfrm_audit audit_info;
1887

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

1892 1893 1894
	audit_info.loginuid = audit_get_loginuid(current);
	audit_info.sessionid = audit_get_sessionid(current);
	security_task_getsecid(current, &audit_info.secid);
1895
	err = xfrm_policy_flush(net, type, &audit_info);
1896 1897 1898
	if (err) {
		if (err == -ESRCH) /* empty table */
			return 0;
1899
		return err;
1900 1901
	}

1902
	c.data.type = type;
1903
	c.event = nlh->nlmsg_type;
1904
	c.seq = nlh->nlmsg_seq;
1905
	c.portid = nlh->nlmsg_pid;
1906
	c.net = net;
1907
	km_policy_notify(NULL, 0, &c);
L
Linus Torvalds 已提交
1908 1909 1910
	return 0;
}

1911
static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1912
		struct nlattr **attrs)
1913
{
1914
	struct net *net = sock_net(skb->sk);
1915
	struct xfrm_policy *xp;
1916
	struct xfrm_user_polexpire *up = nlmsg_data(nlh);
1917
	struct xfrm_userpolicy_info *p = &up->pol;
1918
	u8 type = XFRM_POLICY_TYPE_MAIN;
1919
	int err = -ENOENT;
1920 1921
	struct xfrm_mark m;
	u32 mark = xfrm_mark_get(attrs, &m);
1922

1923
	err = copy_from_user_policy_type(&type, attrs);
1924 1925 1926
	if (err)
		return err;

1927 1928 1929 1930
	err = verify_policy_dir(p->dir);
	if (err)
		return err;

1931
	if (p->index)
1932
		xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err);
1933
	else {
1934
		struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1935
		struct xfrm_sec_ctx *ctx;
1936

1937
		err = verify_sec_ctx_len(attrs);
1938 1939 1940
		if (err)
			return err;

1941
		ctx = NULL;
1942
		if (rt) {
1943
			struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1944

1945 1946
			err = security_xfrm_policy_alloc(&ctx, uctx);
			if (err)
1947
				return err;
1948
		}
1949
		xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir,
1950
					   &p->sel, ctx, 0, &err);
1951
		security_xfrm_policy_free(ctx);
1952 1953
	}
	if (xp == NULL)
1954
		return -ENOENT;
1955

1956
	if (unlikely(xp->walk.dead))
1957 1958 1959 1960
		goto out;

	err = 0;
	if (up->hard) {
1961
		kuid_t loginuid = audit_get_loginuid(current);
1962
		unsigned int sessionid = audit_get_sessionid(current);
1963 1964 1965
		u32 sid;

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

1969 1970
	} else {
		// reset the timers here?
S
stephen hemminger 已提交
1971
		WARN(1, "Dont know what to do with soft policy expire\n");
1972
	}
1973
	km_policy_expired(xp, p->dir, up->hard, nlh->nlmsg_pid);
1974 1975 1976 1977 1978 1979

out:
	xfrm_pol_put(xp);
	return err;
}

1980
static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1981
		struct nlattr **attrs)
1982
{
1983
	struct net *net = sock_net(skb->sk);
1984 1985
	struct xfrm_state *x;
	int err;
1986
	struct xfrm_user_expire *ue = nlmsg_data(nlh);
1987
	struct xfrm_usersa_info *p = &ue->state;
1988
	struct xfrm_mark m;
1989
	u32 mark = xfrm_mark_get(attrs, &m);
1990

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

1993
	err = -ENOENT;
1994 1995 1996 1997
	if (x == NULL)
		return err;

	spin_lock_bh(&x->lock);
1998
	err = -EINVAL;
1999 2000
	if (x->km.state != XFRM_STATE_VALID)
		goto out;
2001
	km_state_expired(x, ue->hard, nlh->nlmsg_pid);
2002

J
Joy Latten 已提交
2003
	if (ue->hard) {
2004
		kuid_t loginuid = audit_get_loginuid(current);
2005
		unsigned int sessionid = audit_get_sessionid(current);
2006 2007 2008
		u32 sid;

		security_task_getsecid(current, &sid);
2009
		__xfrm_state_delete(x);
2010
		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
J
Joy Latten 已提交
2011
	}
2012
	err = 0;
2013 2014 2015 2016 2017 2018
out:
	spin_unlock_bh(&x->lock);
	xfrm_state_put(x);
	return err;
}

2019
static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
2020
		struct nlattr **attrs)
2021
{
2022
	struct net *net = sock_net(skb->sk);
2023 2024 2025
	struct xfrm_policy *xp;
	struct xfrm_user_tmpl *ut;
	int i;
2026
	struct nlattr *rt = attrs[XFRMA_TMPL];
2027
	struct xfrm_mark mark;
2028

2029
	struct xfrm_user_acquire *ua = nlmsg_data(nlh);
2030
	struct xfrm_state *x = xfrm_state_alloc(net);
2031 2032 2033
	int err = -ENOMEM;

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

2036 2037
	xfrm_mark_get(attrs, &mark);

2038
	err = verify_newpolicy_info(&ua->policy);
I
Ilpo Järvinen 已提交
2039 2040
	if (err)
		goto bad_policy;
2041 2042

	/*   build an XP */
2043
	xp = xfrm_policy_construct(net, &ua->policy, attrs, &err);
I
Ilpo Järvinen 已提交
2044 2045
	if (!xp)
		goto free_state;
2046 2047 2048 2049

	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));
2050 2051
	xp->mark.m = x->mark.m = mark.m;
	xp->mark.v = x->mark.v = mark.v;
2052
	ut = nla_data(rt);
2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070
	/* 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 已提交
2071 2072

bad_policy:
S
stephen hemminger 已提交
2073
	WARN(1, "BAD policy passed\n");
I
Ilpo Järvinen 已提交
2074 2075 2076 2077
free_state:
	kfree(x);
nomem:
	return err;
2078 2079
}

2080 2081
#ifdef CONFIG_XFRM_MIGRATE
static int copy_from_user_migrate(struct xfrm_migrate *ma,
2082
				  struct xfrm_kmaddress *k,
2083
				  struct nlattr **attrs, int *num)
2084
{
2085
	struct nlattr *rt = attrs[XFRMA_MIGRATE];
2086 2087 2088
	struct xfrm_user_migrate *um;
	int i, num_migrate;

2089 2090 2091 2092 2093 2094 2095 2096 2097 2098
	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;
	}

2099 2100
	um = nla_data(rt);
	num_migrate = nla_len(rt) / sizeof(*um);
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123

	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,
2124
			   struct nlattr **attrs)
2125
{
2126
	struct xfrm_userpolicy_id *pi = nlmsg_data(nlh);
2127
	struct xfrm_migrate m[XFRM_MAX_DEPTH];
2128
	struct xfrm_kmaddress km, *kmp;
2129 2130 2131 2132
	u8 type;
	int err;
	int n = 0;

2133
	if (attrs[XFRMA_MIGRATE] == NULL)
2134
		return -EINVAL;
2135

2136 2137
	kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL;

2138
	err = copy_from_user_policy_type(&type, attrs);
2139 2140 2141
	if (err)
		return err;

2142
	err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n);
2143 2144 2145 2146 2147 2148
	if (err)
		return err;

	if (!n)
		return 0;

2149
	xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp);
2150 2151 2152 2153 2154

	return 0;
}
#else
static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
2155
			   struct nlattr **attrs)
2156 2157 2158 2159 2160 2161
{
	return -ENOPROTOOPT;
}
#endif

#ifdef CONFIG_XFRM_MIGRATE
2162
static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb)
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176
{
	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));

2177
	return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um);
2178 2179
}

2180
static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb)
2181 2182 2183 2184 2185 2186 2187
{
	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));
2188
	memcpy(&uk.remote, &k->remote, sizeof(uk.remote));
2189 2190 2191 2192 2193

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

static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma)
2194 2195
{
	return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))
2196 2197 2198
	      + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0)
	      + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)
	      + userpolicy_type_attrsize();
2199 2200
}

2201 2202 2203
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)
2204
{
2205
	const struct xfrm_migrate *mp;
2206 2207
	struct xfrm_userpolicy_id *pol_id;
	struct nlmsghdr *nlh;
2208
	int i, err;
2209

2210 2211 2212
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
2213

2214
	pol_id = nlmsg_data(nlh);
2215 2216 2217 2218 2219
	/* 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;

2220 2221 2222 2223 2224 2225 2226 2227
	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;
2228
	for (i = 0, mp = m ; i < num_migrate; i++, mp++) {
2229 2230 2231
		err = copy_to_user_migrate(mp, skb);
		if (err)
			goto out_cancel;
2232 2233
	}

2234
	return nlmsg_end(skb, nlh);
2235 2236

out_cancel:
2237
	nlmsg_cancel(skb, nlh);
2238
	return err;
2239 2240
}

2241 2242 2243
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)
2244
{
2245
	struct net *net = &init_net;
2246 2247
	struct sk_buff *skb;

2248
	skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC);
2249 2250 2251 2252
	if (skb == NULL)
		return -ENOMEM;

	/* build migrate */
2253
	if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0)
2254 2255
		BUG();

2256
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC);
2257 2258
}
#else
2259 2260 2261
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)
2262 2263 2264 2265
{
	return -ENOPROTOOPT;
}
#endif
J
Jamal Hadi Salim 已提交
2266

2267
#define XMSGSIZE(type) sizeof(struct type)
2268 2269

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

2292 2293
#undef XMSGSIZE

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

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

2351
static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
L
Linus Torvalds 已提交
2352
{
2353
	struct net *net = sock_net(skb->sk);
2354
	struct nlattr *attrs[XFRMA_MAX+1];
2355
	const struct xfrm_link *link;
2356
	int type, err;
L
Linus Torvalds 已提交
2357 2358 2359

	type = nlh->nlmsg_type;
	if (type > XFRM_MSG_MAX)
2360
		return -EINVAL;
L
Linus Torvalds 已提交
2361 2362 2363 2364 2365

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

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

2369 2370
	if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
	     type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) &&
2371
	    (nlh->nlmsg_flags & NLM_F_DUMP)) {
L
Linus Torvalds 已提交
2372
		if (link->dump == NULL)
2373
			return -EINVAL;
2374

2375 2376 2377 2378 2379 2380 2381
		{
			struct netlink_dump_control c = {
				.dump = link->dump,
				.done = link->done,
			};
			return netlink_dump_start(net->xfrm.nlsk, skb, nlh, &c);
		}
L
Linus Torvalds 已提交
2382 2383
	}

2384
	err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
2385
			  xfrma_policy);
2386 2387
	if (err < 0)
		return err;
L
Linus Torvalds 已提交
2388 2389

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

2392
	return link->doit(skb, nlh, attrs);
L
Linus Torvalds 已提交
2393 2394
}

2395
static void xfrm_netlink_rcv(struct sk_buff *skb)
L
Linus Torvalds 已提交
2396
{
2397 2398 2399
	mutex_lock(&xfrm_cfg_mutex);
	netlink_rcv_skb(skb, &xfrm_user_rcv_msg);
	mutex_unlock(&xfrm_cfg_mutex);
L
Linus Torvalds 已提交
2400 2401
}

2402 2403
static inline size_t xfrm_expire_msgsize(void)
{
2404 2405
	return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
	       + nla_total_size(sizeof(struct xfrm_mark));
2406 2407
}

2408
static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
L
Linus Torvalds 已提交
2409 2410 2411
{
	struct xfrm_user_expire *ue;
	struct nlmsghdr *nlh;
2412
	int err;
L
Linus Torvalds 已提交
2413

2414
	nlh = nlmsg_put(skb, c->portid, 0, XFRM_MSG_EXPIRE, sizeof(*ue), 0);
2415 2416
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2417

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

2422 2423 2424
	err = xfrm_mark_put(skb, &x->mark);
	if (err)
		return err;
2425

2426
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2427 2428
}

2429
static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c)
L
Linus Torvalds 已提交
2430
{
2431
	struct net *net = xs_net(x);
L
Linus Torvalds 已提交
2432 2433
	struct sk_buff *skb;

2434
	skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC);
L
Linus Torvalds 已提交
2435 2436 2437
	if (skb == NULL)
		return -ENOMEM;

2438 2439 2440 2441
	if (build_expire(skb, x, c) < 0) {
		kfree_skb(skb);
		return -EMSGSIZE;
	}
L
Linus Torvalds 已提交
2442

2443
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2444 2445
}

2446
static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c)
J
Jamal Hadi Salim 已提交
2447
{
2448
	struct net *net = xs_net(x);
J
Jamal Hadi Salim 已提交
2449 2450
	struct sk_buff *skb;

2451
	skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
J
Jamal Hadi Salim 已提交
2452 2453 2454 2455 2456 2457
	if (skb == NULL)
		return -ENOMEM;

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

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

2461
static int xfrm_notify_sa_flush(const struct km_event *c)
2462
{
2463
	struct net *net = c->net;
2464 2465 2466
	struct xfrm_usersa_flush *p;
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2467
	int len = NLMSG_ALIGN(sizeof(struct xfrm_usersa_flush));
2468

2469
	skb = nlmsg_new(len, GFP_ATOMIC);
2470 2471 2472
	if (skb == NULL)
		return -ENOMEM;

2473
	nlh = nlmsg_put(skb, c->portid, c->seq, XFRM_MSG_FLUSHSA, sizeof(*p), 0);
2474 2475 2476 2477
	if (nlh == NULL) {
		kfree_skb(skb);
		return -EMSGSIZE;
	}
2478

2479
	p = nlmsg_data(nlh);
2480
	p->proto = c->data.proto;
2481

2482
	nlmsg_end(skb, nlh);
2483

2484
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC);
2485 2486
}

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

2515 2516
	/* Must count x->lastused as it may become non-zero behind our back. */
	l += nla_total_size(sizeof(u64));
2517 2518 2519 2520

	return l;
}

2521
static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c)
2522
{
2523
	struct net *net = xs_net(x);
2524
	struct xfrm_usersa_info *p;
2525
	struct xfrm_usersa_id *id;
2526 2527 2528
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
	int len = xfrm_sa_len(x);
2529
	int headlen, err;
2530 2531 2532

	headlen = sizeof(*p);
	if (c->event == XFRM_MSG_DELSA) {
2533
		len += nla_total_size(headlen);
2534
		headlen = sizeof(*id);
2535
		len += nla_total_size(sizeof(struct xfrm_mark));
2536
	}
2537
	len += NLMSG_ALIGN(headlen);
2538

2539
	skb = nlmsg_new(len, GFP_ATOMIC);
2540 2541 2542
	if (skb == NULL)
		return -ENOMEM;

2543
	nlh = nlmsg_put(skb, c->portid, c->seq, c->event, headlen, 0);
2544
	err = -EMSGSIZE;
2545
	if (nlh == NULL)
2546
		goto out_free_skb;
2547

2548
	p = nlmsg_data(nlh);
2549
	if (c->event == XFRM_MSG_DELSA) {
2550 2551
		struct nlattr *attr;

2552
		id = nlmsg_data(nlh);
2553 2554 2555 2556 2557
		memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
		id->spi = x->id.spi;
		id->family = x->props.family;
		id->proto = x->id.proto;

2558
		attr = nla_reserve(skb, XFRMA_SA, sizeof(*p));
2559
		err = -EMSGSIZE;
2560
		if (attr == NULL)
2561
			goto out_free_skb;
2562 2563

		p = nla_data(attr);
2564
	}
2565 2566 2567
	err = copy_to_user_state_extra(x, p, skb);
	if (err)
		goto out_free_skb;
2568

2569
	nlmsg_end(skb, nlh);
2570

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

2573
out_free_skb:
2574
	kfree_skb(skb);
2575
	return err;
2576 2577
}

2578
static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c)
2579 2580 2581
{

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

	return 0;

}

2602 2603 2604 2605 2606
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)
2607
	       + nla_total_size(sizeof(struct xfrm_mark))
2608 2609 2610 2611
	       + nla_total_size(xfrm_user_sec_ctx_size(x->security))
	       + userpolicy_type_attrsize();
}

L
Linus Torvalds 已提交
2612
static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
2613
			 struct xfrm_tmpl *xt, struct xfrm_policy *xp)
L
Linus Torvalds 已提交
2614
{
2615
	__u32 seq = xfrm_get_acqseq();
L
Linus Torvalds 已提交
2616 2617
	struct xfrm_user_acquire *ua;
	struct nlmsghdr *nlh;
2618
	int err;
L
Linus Torvalds 已提交
2619

2620 2621 2622
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2623

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

2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644
	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 已提交
2645

2646
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2647 2648 2649
}

static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
2650
			     struct xfrm_policy *xp)
L
Linus Torvalds 已提交
2651
{
2652
	struct net *net = xs_net(x);
L
Linus Torvalds 已提交
2653 2654
	struct sk_buff *skb;

2655
	skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC);
L
Linus Torvalds 已提交
2656 2657 2658
	if (skb == NULL)
		return -ENOMEM;

2659
	if (build_acquire(skb, x, xt, xp) < 0)
L
Linus Torvalds 已提交
2660 2661
		BUG();

2662
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2663 2664 2665 2666 2667
}

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

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

2707 2708 2709
	if (p->dir > XFRM_POLICY_OUT)
		return NULL;

2710
	xp = xfrm_policy_alloc(net, GFP_ATOMIC);
L
Linus Torvalds 已提交
2711 2712 2713 2714 2715 2716
	if (xp == NULL) {
		*dir = -ENOBUFS;
		return NULL;
	}

	copy_from_user_policy(xp, p);
2717
	xp->type = XFRM_POLICY_TYPE_MAIN;
L
Linus Torvalds 已提交
2718 2719 2720 2721 2722 2723 2724
	copy_templates(xp, ut, nr);

	*dir = p->dir;

	return xp;
}

2725 2726 2727 2728 2729
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))
2730
	       + nla_total_size(sizeof(struct xfrm_mark))
2731 2732 2733
	       + userpolicy_type_attrsize();
}

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

2742
	nlh = nlmsg_put(skb, c->portid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe), 0);
2743 2744
	if (nlh == NULL)
		return -EMSGSIZE;
L
Linus Torvalds 已提交
2745

2746
	upe = nlmsg_data(nlh);
L
Linus Torvalds 已提交
2747
	copy_to_user_policy(xp, &upe->pol, dir);
2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758
	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 已提交
2759 2760
	upe->hard = !!hard;

2761
	return nlmsg_end(skb, nlh);
L
Linus Torvalds 已提交
2762 2763
}

2764
static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
L
Linus Torvalds 已提交
2765
{
2766
	struct net *net = xp_net(xp);
L
Linus Torvalds 已提交
2767 2768
	struct sk_buff *skb;

2769
	skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC);
L
Linus Torvalds 已提交
2770 2771 2772
	if (skb == NULL)
		return -ENOMEM;

J
Jamal Hadi Salim 已提交
2773
	if (build_polexpire(skb, xp, dir, c) < 0)
L
Linus Torvalds 已提交
2774 2775
		BUG();

2776
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
L
Linus Torvalds 已提交
2777 2778
}

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

	headlen = sizeof(*p);
	if (c->event == XFRM_MSG_DELPOLICY) {
2791
		len += nla_total_size(headlen);
2792 2793
		headlen = sizeof(*id);
	}
2794
	len += userpolicy_type_attrsize();
2795
	len += nla_total_size(sizeof(struct xfrm_mark));
2796
	len += NLMSG_ALIGN(headlen);
2797

2798
	skb = nlmsg_new(len, GFP_ATOMIC);
2799 2800 2801
	if (skb == NULL)
		return -ENOMEM;

2802
	nlh = nlmsg_put(skb, c->portid, c->seq, c->event, headlen, 0);
2803
	err = -EMSGSIZE;
2804
	if (nlh == NULL)
2805
		goto out_free_skb;
2806

2807
	p = nlmsg_data(nlh);
2808
	if (c->event == XFRM_MSG_DELPOLICY) {
2809 2810
		struct nlattr *attr;

2811
		id = nlmsg_data(nlh);
2812 2813 2814 2815 2816 2817 2818
		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));

2819
		attr = nla_reserve(skb, XFRMA_POLICY, sizeof(*p));
2820
		err = -EMSGSIZE;
2821
		if (attr == NULL)
2822
			goto out_free_skb;
2823 2824

		p = nla_data(attr);
2825
	}
2826 2827

	copy_to_user_policy(xp, p, dir);
2828 2829 2830 2831 2832 2833 2834
	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;
2835

2836
	nlmsg_end(skb, nlh);
2837

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

2840
out_free_skb:
2841
	kfree_skb(skb);
2842
	return err;
2843 2844
}

2845
static int xfrm_notify_policy_flush(const struct km_event *c)
2846
{
2847
	struct net *net = c->net;
2848 2849
	struct nlmsghdr *nlh;
	struct sk_buff *skb;
2850
	int err;
2851

2852
	skb = nlmsg_new(userpolicy_type_attrsize(), GFP_ATOMIC);
2853 2854 2855
	if (skb == NULL)
		return -ENOMEM;

2856
	nlh = nlmsg_put(skb, c->portid, c->seq, XFRM_MSG_FLUSHPOLICY, 0, 0);
2857
	err = -EMSGSIZE;
2858
	if (nlh == NULL)
2859 2860 2861 2862
		goto out_free_skb;
	err = copy_to_user_policy_type(c->data.type, skb);
	if (err)
		goto out_free_skb;
2863

2864
	nlmsg_end(skb, nlh);
2865

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

2868
out_free_skb:
2869
	kfree_skb(skb);
2870
	return err;
2871 2872
}

2873
static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
2874 2875 2876
{

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

	return 0;

}

2894 2895 2896 2897 2898
static inline size_t xfrm_report_msgsize(void)
{
	return NLMSG_ALIGN(sizeof(struct xfrm_user_report));
}

2899 2900 2901 2902 2903 2904
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;

2905 2906 2907
	nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur), 0);
	if (nlh == NULL)
		return -EMSGSIZE;
2908

2909
	ur = nlmsg_data(nlh);
2910 2911 2912
	ur->proto = proto;
	memcpy(&ur->sel, sel, sizeof(ur->sel));

2913 2914 2915 2916 2917 2918 2919
	if (addr) {
		int err = nla_put(skb, XFRMA_COADDR, sizeof(*addr), addr);
		if (err) {
			nlmsg_cancel(skb, nlh);
			return err;
		}
	}
2920
	return nlmsg_end(skb, nlh);
2921 2922
}

2923 2924
static int xfrm_send_report(struct net *net, u8 proto,
			    struct xfrm_selector *sel, xfrm_address_t *addr)
2925 2926 2927
{
	struct sk_buff *skb;

2928
	skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC);
2929 2930 2931 2932 2933 2934
	if (skb == NULL)
		return -ENOMEM;

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

2935
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC);
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 2966 2967 2968 2969 2970
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)
{
2971
	struct net *net = xs_net(x);
2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
	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();

2987
	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC);
2988 2989
}

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,
L
Linus Torvalds 已提交
2999 3000
};

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

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

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

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

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