OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [security/] [selinux/] [xfrm.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  NSA Security-Enhanced Linux (SELinux) security module
3
 *
4
 *  This file contains the SELinux XFRM hook function implementations.
5
 *
6
 *  Authors:  Serge Hallyn <sergeh@us.ibm.com>
7
 *            Trent Jaeger <jaegert@us.ibm.com>
8
 *
9
 *  Updated: Venkat Yekkirala <vyekkirala@TrustedCS.com>
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/ip.h>
42
#include <linux/tcp.h>
43
#include <linux/skbuff.h>
44
#include <linux/xfrm.h>
45
#include <net/xfrm.h>
46
#include <net/checksum.h>
47
#include <net/udp.h>
48
#include <asm/semaphore.h>
49
 
50
#include "avc.h"
51
#include "objsec.h"
52
#include "xfrm.h"
53
 
54
 
55
/*
56
 * Returns true if an LSM/SELinux context
57
 */
58
static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
59
{
60
        return (ctx &&
61
                (ctx->ctx_doi == XFRM_SC_DOI_LSM) &&
62
                (ctx->ctx_alg == XFRM_SC_ALG_SELINUX));
63
}
64
 
65
/*
66
 * Returns true if the xfrm contains a security blob for SELinux
67
 */
68
static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
69
{
70
        return selinux_authorizable_ctx(x->security);
71
}
72
 
73
/*
74
 * LSM hook implementation that authorizes that a flow can use
75
 * a xfrm policy rule.
76
 */
77
int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
78
{
79
        int rc;
80
        u32 sel_sid;
81
        struct xfrm_sec_ctx *ctx;
82
 
83
        /* Context sid is either set to label or ANY_ASSOC */
84
        if ((ctx = xp->security)) {
85
                if (!selinux_authorizable_ctx(ctx))
86
                        return -EINVAL;
87
 
88
                sel_sid = ctx->ctx_sid;
89
        }
90
        else
91
                /*
92
                 * All flows should be treated as polmatch'ing an
93
                 * otherwise applicable "non-labeled" policy. This
94
                 * would prevent inadvertent "leaks".
95
                 */
96
                return 0;
97
 
98
        rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
99
                          ASSOCIATION__POLMATCH,
100
                          NULL);
101
 
102
        if (rc == -EACCES)
103
                rc = -ESRCH;
104
 
105
        return rc;
106
}
107
 
108
/*
109
 * LSM hook implementation that authorizes that a state matches
110
 * the given policy, flow combo.
111
 */
112
 
113
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp,
114
                        struct flowi *fl)
115
{
116
        u32 state_sid;
117
        int rc;
118
 
119
        if (!xp->security)
120
                if (x->security)
121
                        /* unlabeled policy and labeled SA can't match */
122
                        return 0;
123
                else
124
                        /* unlabeled policy and unlabeled SA match all flows */
125
                        return 1;
126
        else
127
                if (!x->security)
128
                        /* unlabeled SA and labeled policy can't match */
129
                        return 0;
130
                else
131
                        if (!selinux_authorizable_xfrm(x))
132
                                /* Not a SELinux-labeled SA */
133
                                return 0;
134
 
135
        state_sid = x->security->ctx_sid;
136
 
137
        if (fl->secid != state_sid)
138
                return 0;
139
 
140
        rc = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
141
                          ASSOCIATION__SENDTO,
142
                          NULL)? 0:1;
143
 
144
        /*
145
         * We don't need a separate SA Vs. policy polmatch check
146
         * since the SA is now of the same label as the flow and
147
         * a flow Vs. policy polmatch check had already happened
148
         * in selinux_xfrm_policy_lookup() above.
149
         */
150
 
151
        return rc;
152
}
153
 
154
/*
155
 * LSM hook implementation that checks and/or returns the xfrm sid for the
156
 * incoming packet.
157
 */
158
 
159
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
160
{
161
        struct sec_path *sp;
162
 
163
        *sid = SECSID_NULL;
164
 
165
        if (skb == NULL)
166
                return 0;
167
 
168
        sp = skb->sp;
169
        if (sp) {
170
                int i, sid_set = 0;
171
 
172
                for (i = sp->len-1; i >= 0; i--) {
173
                        struct xfrm_state *x = sp->xvec[i];
174
                        if (selinux_authorizable_xfrm(x)) {
175
                                struct xfrm_sec_ctx *ctx = x->security;
176
 
177
                                if (!sid_set) {
178
                                        *sid = ctx->ctx_sid;
179
                                        sid_set = 1;
180
 
181
                                        if (!ckall)
182
                                                break;
183
                                }
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
        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_doi != 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_policy *xp,
288
                struct xfrm_user_sec_ctx *uctx)
289
{
290
        int err;
291
 
292
        BUG_ON(!xp);
293
        BUG_ON(!uctx);
294
 
295
        err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
296
        return err;
297
}
298
 
299
 
300
/*
301
 * LSM hook implementation that copies security data structure from old to
302
 * new for policy cloning.
303
 */
304
int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
305
{
306
        struct xfrm_sec_ctx *old_ctx, *new_ctx;
307
 
308
        old_ctx = old->security;
309
 
310
        if (old_ctx) {
311
                new_ctx = new->security = kmalloc(sizeof(*new_ctx) +
312
                                                  old_ctx->ctx_len,
313
                                                  GFP_KERNEL);
314
 
315
                if (!new_ctx)
316
                        return -ENOMEM;
317
 
318
                memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
319
                memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
320
        }
321
        return 0;
322
}
323
 
324
/*
325
 * LSM hook implementation that frees xfrm_policy security information.
326
 */
327
void selinux_xfrm_policy_free(struct xfrm_policy *xp)
328
{
329
        struct xfrm_sec_ctx *ctx = xp->security;
330
        if (ctx)
331
                kfree(ctx);
332
}
333
 
334
/*
335
 * LSM hook implementation that authorizes deletion of labeled policies.
336
 */
337
int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
338
{
339
        struct task_security_struct *tsec = current->security;
340
        struct xfrm_sec_ctx *ctx = xp->security;
341
        int rc = 0;
342
 
343
        if (ctx)
344
                rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
345
                                  SECCLASS_ASSOCIATION,
346
                                  ASSOCIATION__SETCONTEXT, NULL);
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
        return err;
364
}
365
 
366
/*
367
 * LSM hook implementation that frees xfrm_state security information.
368
 */
369
void selinux_xfrm_state_free(struct xfrm_state *x)
370
{
371
        struct xfrm_sec_ctx *ctx = x->security;
372
        if (ctx)
373
                kfree(ctx);
374
}
375
 
376
 /*
377
  * LSM hook implementation that authorizes deletion of labeled SAs.
378
  */
379
int selinux_xfrm_state_delete(struct xfrm_state *x)
380
{
381
        struct task_security_struct *tsec = current->security;
382
        struct xfrm_sec_ctx *ctx = x->security;
383
        int rc = 0;
384
 
385
        if (ctx)
386
                rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
387
                                  SECCLASS_ASSOCIATION,
388
                                  ASSOCIATION__SETCONTEXT, NULL);
389
 
390
        return rc;
391
}
392
 
393
/*
394
 * LSM hook that controls access to unlabelled packets.  If
395
 * a xfrm_state is authorizable (defined by macro) then it was
396
 * already authorized by the IPSec process.  If not, then
397
 * we need to check for unlabelled access since this may not have
398
 * gone thru the IPSec process.
399
 */
400
int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
401
                                struct avc_audit_data *ad)
402
{
403
        int i, rc = 0;
404
        struct sec_path *sp;
405
        u32 sel_sid = SECINITSID_UNLABELED;
406
 
407
        sp = skb->sp;
408
 
409
        if (sp) {
410
                for (i = 0; i < sp->len; i++) {
411
                        struct xfrm_state *x = sp->xvec[i];
412
 
413
                        if (x && selinux_authorizable_xfrm(x)) {
414
                                struct xfrm_sec_ctx *ctx = x->security;
415
                                sel_sid = ctx->ctx_sid;
416
                                break;
417
                        }
418
                }
419
        }
420
 
421
        /*
422
         * This check even when there's no association involved is
423
         * intended, according to Trent Jaeger, to make sure a
424
         * process can't engage in non-ipsec communication unless
425
         * explicitly allowed by policy.
426
         */
427
 
428
        rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
429
                          ASSOCIATION__RECVFROM, ad);
430
 
431
        return rc;
432
}
433
 
434
/*
435
 * POSTROUTE_LAST hook's XFRM processing:
436
 * If we have no security association, then we need to determine
437
 * whether the socket is allowed to send to an unlabelled destination.
438
 * If we do have a authorizable security association, then it has already been
439
 * checked in the selinux_xfrm_state_pol_flow_match hook above.
440
 */
441
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
442
                                        struct avc_audit_data *ad, u8 proto)
443
{
444
        struct dst_entry *dst;
445
        int rc = 0;
446
 
447
        dst = skb->dst;
448
 
449
        if (dst) {
450
                struct dst_entry *dst_test;
451
 
452
                for (dst_test = dst; dst_test != NULL;
453
                     dst_test = dst_test->child) {
454
                        struct xfrm_state *x = dst_test->xfrm;
455
 
456
                        if (x && selinux_authorizable_xfrm(x))
457
                                goto out;
458
                }
459
        }
460
 
461
        switch (proto) {
462
        case IPPROTO_AH:
463
        case IPPROTO_ESP:
464
        case IPPROTO_COMP:
465
                /*
466
                 * We should have already seen this packet once before
467
                 * it underwent xfrm(s). No need to subject it to the
468
                 * unlabeled check.
469
                 */
470
                goto out;
471
        default:
472
                break;
473
        }
474
 
475
        /*
476
         * This check even when there's no association involved is
477
         * intended, according to Trent Jaeger, to make sure a
478
         * process can't engage in non-ipsec communication unless
479
         * explicitly allowed by policy.
480
         */
481
 
482
        rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
483
                          ASSOCIATION__SENDTO, ad);
484
out:
485
        return rc;
486
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.