Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/security/selinux/xfrm.c
10814 views
1
/*
2
* NSA Security-Enhanced Linux (SELinux) security module
3
*
4
* This file contains the SELinux XFRM hook function implementations.
5
*
6
* Authors: Serge Hallyn <[email protected]>
7
* Trent Jaeger <[email protected]>
8
*
9
* Updated: Venkat Yekkirala <[email protected]>
10
*
11
* Granular IPSec Associations for use in MLS environments.
12
*
13
* Copyright (C) 2005 International Business Machines Corporation
14
* Copyright (C) 2006 Trusted Computer Solutions, Inc.
15
*
16
* This program is free software; you can redistribute it and/or modify
17
* it under the terms of the GNU General Public License version 2,
18
* as published by the Free Software Foundation.
19
*/
20
21
/*
22
* USAGE:
23
* NOTES:
24
* 1. Make sure to enable the following options in your kernel config:
25
* CONFIG_SECURITY=y
26
* CONFIG_SECURITY_NETWORK=y
27
* CONFIG_SECURITY_NETWORK_XFRM=y
28
* CONFIG_SECURITY_SELINUX=m/y
29
* ISSUES:
30
* 1. Caching packets, so they are not dropped during negotiation
31
* 2. Emulating a reasonable SO_PEERSEC across machines
32
* 3. Testing addition of sk_policy's with security context via setsockopt
33
*/
34
#include <linux/kernel.h>
35
#include <linux/init.h>
36
#include <linux/security.h>
37
#include <linux/types.h>
38
#include <linux/netfilter.h>
39
#include <linux/netfilter_ipv4.h>
40
#include <linux/netfilter_ipv6.h>
41
#include <linux/slab.h>
42
#include <linux/ip.h>
43
#include <linux/tcp.h>
44
#include <linux/skbuff.h>
45
#include <linux/xfrm.h>
46
#include <net/xfrm.h>
47
#include <net/checksum.h>
48
#include <net/udp.h>
49
#include <asm/atomic.h>
50
51
#include "avc.h"
52
#include "objsec.h"
53
#include "xfrm.h"
54
55
/* Labeled XFRM instance counter */
56
atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
57
58
/*
59
* Returns true if an LSM/SELinux context
60
*/
61
static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
62
{
63
return (ctx &&
64
(ctx->ctx_doi == XFRM_SC_DOI_LSM) &&
65
(ctx->ctx_alg == XFRM_SC_ALG_SELINUX));
66
}
67
68
/*
69
* Returns true if the xfrm contains a security blob for SELinux
70
*/
71
static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
72
{
73
return selinux_authorizable_ctx(x->security);
74
}
75
76
/*
77
* LSM hook implementation that authorizes that a flow can use
78
* a xfrm policy rule.
79
*/
80
int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
81
{
82
int rc;
83
u32 sel_sid;
84
85
/* Context sid is either set to label or ANY_ASSOC */
86
if (ctx) {
87
if (!selinux_authorizable_ctx(ctx))
88
return -EINVAL;
89
90
sel_sid = ctx->ctx_sid;
91
} else
92
/*
93
* All flows should be treated as polmatch'ing an
94
* otherwise applicable "non-labeled" policy. This
95
* would prevent inadvertent "leaks".
96
*/
97
return 0;
98
99
rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
100
ASSOCIATION__POLMATCH,
101
NULL);
102
103
if (rc == -EACCES)
104
return -ESRCH;
105
106
return rc;
107
}
108
109
/*
110
* LSM hook implementation that authorizes that a state matches
111
* the given policy, flow combo.
112
*/
113
114
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp,
115
const struct flowi *fl)
116
{
117
u32 state_sid;
118
int rc;
119
120
if (!xp->security)
121
if (x->security)
122
/* unlabeled policy and labeled SA can't match */
123
return 0;
124
else
125
/* unlabeled policy and unlabeled SA match all flows */
126
return 1;
127
else
128
if (!x->security)
129
/* unlabeled SA and labeled policy can't match */
130
return 0;
131
else
132
if (!selinux_authorizable_xfrm(x))
133
/* Not a SELinux-labeled SA */
134
return 0;
135
136
state_sid = x->security->ctx_sid;
137
138
if (fl->flowi_secid != state_sid)
139
return 0;
140
141
rc = avc_has_perm(fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION,
142
ASSOCIATION__SENDTO,
143
NULL)? 0:1;
144
145
/*
146
* We don't need a separate SA Vs. policy polmatch check
147
* since the SA is now of the same label as the flow and
148
* a flow Vs. policy polmatch check had already happened
149
* in selinux_xfrm_policy_lookup() above.
150
*/
151
152
return rc;
153
}
154
155
/*
156
* LSM hook implementation that checks and/or returns the xfrm sid for the
157
* incoming packet.
158
*/
159
160
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
161
{
162
struct sec_path *sp;
163
164
*sid = SECSID_NULL;
165
166
if (skb == NULL)
167
return 0;
168
169
sp = skb->sp;
170
if (sp) {
171
int i, sid_set = 0;
172
173
for (i = sp->len-1; i >= 0; i--) {
174
struct xfrm_state *x = sp->xvec[i];
175
if (selinux_authorizable_xfrm(x)) {
176
struct xfrm_sec_ctx *ctx = x->security;
177
178
if (!sid_set) {
179
*sid = ctx->ctx_sid;
180
sid_set = 1;
181
182
if (!ckall)
183
break;
184
} else if (*sid != ctx->ctx_sid)
185
return -EINVAL;
186
}
187
}
188
}
189
190
return 0;
191
}
192
193
/*
194
* Security blob allocation for xfrm_policy and xfrm_state
195
* CTX does not have a meaningful value on input
196
*/
197
static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
198
struct xfrm_user_sec_ctx *uctx, u32 sid)
199
{
200
int rc = 0;
201
const struct task_security_struct *tsec = current_security();
202
struct xfrm_sec_ctx *ctx = NULL;
203
char *ctx_str = NULL;
204
u32 str_len;
205
206
BUG_ON(uctx && sid);
207
208
if (!uctx)
209
goto not_from_user;
210
211
if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
212
return -EINVAL;
213
214
str_len = uctx->ctx_len;
215
if (str_len >= PAGE_SIZE)
216
return -ENOMEM;
217
218
*ctxp = ctx = kmalloc(sizeof(*ctx) +
219
str_len + 1,
220
GFP_KERNEL);
221
222
if (!ctx)
223
return -ENOMEM;
224
225
ctx->ctx_doi = uctx->ctx_doi;
226
ctx->ctx_len = str_len;
227
ctx->ctx_alg = uctx->ctx_alg;
228
229
memcpy(ctx->ctx_str,
230
uctx+1,
231
str_len);
232
ctx->ctx_str[str_len] = 0;
233
rc = security_context_to_sid(ctx->ctx_str,
234
str_len,
235
&ctx->ctx_sid);
236
237
if (rc)
238
goto out;
239
240
/*
241
* Does the subject have permission to set security context?
242
*/
243
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
244
SECCLASS_ASSOCIATION,
245
ASSOCIATION__SETCONTEXT, NULL);
246
if (rc)
247
goto out;
248
249
return rc;
250
251
not_from_user:
252
rc = security_sid_to_context(sid, &ctx_str, &str_len);
253
if (rc)
254
goto out;
255
256
*ctxp = ctx = kmalloc(sizeof(*ctx) +
257
str_len,
258
GFP_ATOMIC);
259
260
if (!ctx) {
261
rc = -ENOMEM;
262
goto out;
263
}
264
265
ctx->ctx_doi = XFRM_SC_DOI_LSM;
266
ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
267
ctx->ctx_sid = sid;
268
ctx->ctx_len = str_len;
269
memcpy(ctx->ctx_str,
270
ctx_str,
271
str_len);
272
273
goto out2;
274
275
out:
276
*ctxp = NULL;
277
kfree(ctx);
278
out2:
279
kfree(ctx_str);
280
return rc;
281
}
282
283
/*
284
* LSM hook implementation that allocs and transfers uctx spec to
285
* xfrm_policy.
286
*/
287
int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
288
struct xfrm_user_sec_ctx *uctx)
289
{
290
int err;
291
292
BUG_ON(!uctx);
293
294
err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
295
if (err == 0)
296
atomic_inc(&selinux_xfrm_refcount);
297
298
return err;
299
}
300
301
302
/*
303
* LSM hook implementation that copies security data structure from old to
304
* new for policy cloning.
305
*/
306
int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
307
struct xfrm_sec_ctx **new_ctxp)
308
{
309
struct xfrm_sec_ctx *new_ctx;
310
311
if (old_ctx) {
312
new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
313
GFP_KERNEL);
314
if (!new_ctx)
315
return -ENOMEM;
316
317
memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
318
memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
319
*new_ctxp = new_ctx;
320
}
321
return 0;
322
}
323
324
/*
325
* LSM hook implementation that frees xfrm_sec_ctx security information.
326
*/
327
void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
328
{
329
kfree(ctx);
330
}
331
332
/*
333
* LSM hook implementation that authorizes deletion of labeled policies.
334
*/
335
int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
336
{
337
const struct task_security_struct *tsec = current_security();
338
int rc = 0;
339
340
if (ctx) {
341
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
342
SECCLASS_ASSOCIATION,
343
ASSOCIATION__SETCONTEXT, NULL);
344
if (rc == 0)
345
atomic_dec(&selinux_xfrm_refcount);
346
}
347
348
return rc;
349
}
350
351
/*
352
* LSM hook implementation that allocs and transfers sec_ctx spec to
353
* xfrm_state.
354
*/
355
int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
356
u32 secid)
357
{
358
int err;
359
360
BUG_ON(!x);
361
362
err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
363
if (err == 0)
364
atomic_inc(&selinux_xfrm_refcount);
365
return err;
366
}
367
368
/*
369
* LSM hook implementation that frees xfrm_state security information.
370
*/
371
void selinux_xfrm_state_free(struct xfrm_state *x)
372
{
373
struct xfrm_sec_ctx *ctx = x->security;
374
kfree(ctx);
375
}
376
377
/*
378
* LSM hook implementation that authorizes deletion of labeled SAs.
379
*/
380
int selinux_xfrm_state_delete(struct xfrm_state *x)
381
{
382
const struct task_security_struct *tsec = current_security();
383
struct xfrm_sec_ctx *ctx = x->security;
384
int rc = 0;
385
386
if (ctx) {
387
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
388
SECCLASS_ASSOCIATION,
389
ASSOCIATION__SETCONTEXT, NULL);
390
if (rc == 0)
391
atomic_dec(&selinux_xfrm_refcount);
392
}
393
394
return rc;
395
}
396
397
/*
398
* LSM hook that controls access to unlabelled packets. If
399
* a xfrm_state is authorizable (defined by macro) then it was
400
* already authorized by the IPSec process. If not, then
401
* we need to check for unlabelled access since this may not have
402
* gone thru the IPSec process.
403
*/
404
int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
405
struct common_audit_data *ad)
406
{
407
int i, rc = 0;
408
struct sec_path *sp;
409
u32 sel_sid = SECINITSID_UNLABELED;
410
411
sp = skb->sp;
412
413
if (sp) {
414
for (i = 0; i < sp->len; i++) {
415
struct xfrm_state *x = sp->xvec[i];
416
417
if (x && selinux_authorizable_xfrm(x)) {
418
struct xfrm_sec_ctx *ctx = x->security;
419
sel_sid = ctx->ctx_sid;
420
break;
421
}
422
}
423
}
424
425
/*
426
* This check even when there's no association involved is
427
* intended, according to Trent Jaeger, to make sure a
428
* process can't engage in non-ipsec communication unless
429
* explicitly allowed by policy.
430
*/
431
432
rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
433
ASSOCIATION__RECVFROM, ad);
434
435
return rc;
436
}
437
438
/*
439
* POSTROUTE_LAST hook's XFRM processing:
440
* If we have no security association, then we need to determine
441
* whether the socket is allowed to send to an unlabelled destination.
442
* If we do have a authorizable security association, then it has already been
443
* checked in the selinux_xfrm_state_pol_flow_match hook above.
444
*/
445
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
446
struct common_audit_data *ad, u8 proto)
447
{
448
struct dst_entry *dst;
449
int rc = 0;
450
451
dst = skb_dst(skb);
452
453
if (dst) {
454
struct dst_entry *dst_test;
455
456
for (dst_test = dst; dst_test != NULL;
457
dst_test = dst_test->child) {
458
struct xfrm_state *x = dst_test->xfrm;
459
460
if (x && selinux_authorizable_xfrm(x))
461
goto out;
462
}
463
}
464
465
switch (proto) {
466
case IPPROTO_AH:
467
case IPPROTO_ESP:
468
case IPPROTO_COMP:
469
/*
470
* We should have already seen this packet once before
471
* it underwent xfrm(s). No need to subject it to the
472
* unlabeled check.
473
*/
474
goto out;
475
default:
476
break;
477
}
478
479
/*
480
* This check even when there's no association involved is
481
* intended, according to Trent Jaeger, to make sure a
482
* process can't engage in non-ipsec communication unless
483
* explicitly allowed by policy.
484
*/
485
486
rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
487
ASSOCIATION__SENDTO, ad);
488
out:
489
return rc;
490
}
491
492