~ubuntu-branches/ubuntu/trusty/linux-linaro-omap/trusty

« back to all changes in this revision

Viewing changes to kernel/seccomp_filter.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-57i0gl3v99b3lkfg
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* filter engine-based seccomp system call filtering
 
2
 *
 
3
 * This program is free software; you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation; either version 2 of the License, or
 
6
 * (at your option) any later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program; if not, write to the Free Software
 
15
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
16
 *
 
17
 * Copyright (C) 2011 The Chromium OS Authors <chromium-os-dev@chromium.org>
 
18
 */
 
19
 
 
20
#include <linux/compat.h>
 
21
#include <linux/err.h>
 
22
#include <linux/errno.h>
 
23
#include <linux/ftrace_event.h>
 
24
#include <linux/kallsyms.h>
 
25
#include <linux/kref.h>
 
26
#include <linux/perf_event.h>
 
27
#include <linux/prctl.h>
 
28
#include <linux/seccomp.h>
 
29
#include <linux/seq_file.h>
 
30
#include <linux/sched.h>
 
31
#include <linux/slab.h>
 
32
#include <linux/uaccess.h>
 
33
 
 
34
#include <asm/syscall.h>
 
35
#include <trace/syscall.h>
 
36
 
 
37
/* Pull in *just* to access event_filter->filter_string. */
 
38
#include "trace/trace.h"
 
39
 
 
40
#define SECCOMP_MAX_FILTER_LENGTH MAX_FILTER_STR_VAL
 
41
 
 
42
#define SECCOMP_FILTER_ALLOW "1"
 
43
#define SECCOMP_ACTION_DENY 0xffff
 
44
#define SECCOMP_ACTION_ALLOW 0xfffe
 
45
 
 
46
/**
 
47
 * struct seccomp_filters - container for seccomp filters
 
48
 *
 
49
 * @usage: reference count to manage the object lifetime.
 
50
 *         get/put helpers should be used when accessing an instance
 
51
 *         outside of a lifetime-guarded section.  In general, this
 
52
 *         is only needed for handling shared filters across tasks.
 
53
 * @flags: anonymous struct to wrap filters-specific flags
 
54
 * @syscalls: array of 16-bit indices into @event_filters by syscall_nr
 
55
 *            May also be SECCOMP_ACTION_DENY or SECCOMP_ACTION_ALLOW
 
56
 * @count: size of @event_filters
 
57
 * @event_filters: array of pointers to ftrace event filters
 
58
 *
 
59
 * seccomp_filters objects should never be modified after being attached
 
60
 * to a task_struct.
 
61
 */
 
62
struct seccomp_filters {
 
63
        struct kref usage;
 
64
        struct {
 
65
                uint32_t compat:1,
 
66
                         __reserved:31;
 
67
        } flags;
 
68
        uint16_t syscalls[NR_syscalls];
 
69
        uint16_t count;
 
70
        struct event_filter *event_filters[0];
 
71
};
 
72
 
 
73
/* Make sure we can get to the syscall metadata that ftrace hordes. */
 
74
extern struct syscall_metadata *__start_syscalls_metadata[];
 
75
extern struct syscall_metadata *__stop_syscalls_metadata[];
 
76
 
 
77
static struct syscall_metadata **syscalls_metadata;
 
78
static struct syscall_metadata *syscall_nr_to_meta(int nr)
 
79
{
 
80
        if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
 
81
                return NULL;
 
82
 
 
83
        return syscalls_metadata[nr];
 
84
}
 
85
 
 
86
/*
 
87
 * Make ftrace support optional
 
88
 */
 
89
 
 
90
#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PERF_EVENTS)
 
91
 
 
92
/* Fix up buffer creation to allow the ftrace filter engine to
 
93
 * work with seccomp filter events.
 
94
 * Lifted from kernel/trace/trace_syscalls.c
 
95
 */
 
96
 
 
97
#ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME
 
98
static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
 
99
{
 
100
        /*
 
101
         * Only compare after the "sys" prefix. Archs that use
 
102
         * syscall wrappers may have syscalls symbols aliases prefixed
 
103
         * with "SyS" instead of "sys", leading to an unwanted
 
104
         * mismatch.
 
105
         */
 
106
        return !strcmp(sym + 3, name + 3);
 
107
}
 
108
#endif
 
109
 
 
110
static __init struct syscall_metadata *
 
111
find_syscall_meta(unsigned long syscall)
 
112
{
 
113
        struct syscall_metadata **start;
 
114
        struct syscall_metadata **stop;
 
115
        char str[KSYM_SYMBOL_LEN];
 
116
 
 
117
 
 
118
        start = __start_syscalls_metadata;
 
119
        stop = __stop_syscalls_metadata;
 
120
        kallsyms_lookup(syscall, NULL, NULL, NULL, str);
 
121
 
 
122
        if (arch_syscall_match_sym_name(str, "sys_ni_syscall"))
 
123
                return NULL;
 
124
 
 
125
        for ( ; start < stop; start++) {
 
126
                if ((*start)->name && arch_syscall_match_sym_name(str, (*start)->name))
 
127
                        return *start;
 
128
        }
 
129
        return NULL;
 
130
}
 
131
 
 
132
int __init init_seccomp_filter(void)
 
133
{
 
134
        struct syscall_metadata *meta;
 
135
        unsigned long addr;
 
136
        int i;
 
137
 
 
138
        syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
 
139
                                        NR_syscalls, GFP_KERNEL);
 
140
        if (!syscalls_metadata) {
 
141
                WARN_ON(1);
 
142
                return -ENOMEM;
 
143
        }
 
144
 
 
145
        for (i = 0; i < NR_syscalls; i++) {
 
146
                addr = arch_syscall_addr(i);
 
147
                meta = find_syscall_meta(addr);
 
148
                if (!meta)
 
149
                        continue;
 
150
 
 
151
                meta->syscall_nr = i;
 
152
                syscalls_metadata[i] = meta;
 
153
        }
 
154
 
 
155
        return 0;
 
156
}
 
157
core_initcall(init_seccomp_filter);
 
158
 
 
159
/*
 
160
 * End of the ftrace metadata access fixup.
 
161
 */
 
162
 
 
163
 
 
164
static int create_event_filter(struct event_filter **filter,
 
165
                               int event_type,
 
166
                               char *filter_string)
 
167
{
 
168
        int ret = -ENOSYS;
 
169
        struct perf_event event;
 
170
        event.filter = NULL;
 
171
        ret = ftrace_profile_set_filter(&event, event_type, filter_string);
 
172
        if (ret)
 
173
                goto out;
 
174
        *filter = event.filter;
 
175
        (*filter)->filter_string = kstrdup(filter_string, GFP_KERNEL);
 
176
        if (!(*filter)->filter_string) {
 
177
                ftrace_profile_free_filter(&event);
 
178
                ret = -ENOMEM;
 
179
        }
 
180
out:
 
181
        return ret;
 
182
}
 
183
 
 
184
static char *get_filter_string(struct event_filter *filter)
 
185
{
 
186
        if (filter)
 
187
                return filter->filter_string;
 
188
        return NULL;
 
189
}
 
190
 
 
191
static void free_event_filter(struct event_filter *filter)
 
192
{
 
193
        struct perf_event event;
 
194
        if (!filter)
 
195
                return;
 
196
        event.filter = filter;
 
197
        ftrace_profile_free_filter(&event);
 
198
}
 
199
 
 
200
/* ftrace_syscall_enter_state_size - returns the state size required.
 
201
 *
 
202
 * @nb_args: number of system call args expected.
 
203
 *           a negative value implies the maximum allowed.
 
204
 */
 
205
static size_t ftrace_syscall_enter_state_size(int nb_args)
 
206
{
 
207
        /* syscall_get_arguments only supports up to 6 arguments. */
 
208
        int arg_count = (nb_args >= 0 ? nb_args : 6);
 
209
        size_t size = (sizeof(unsigned long) * arg_count) +
 
210
                      sizeof(struct syscall_trace_enter);
 
211
        size = ALIGN(size + sizeof(u32), sizeof(u64));
 
212
        size -= sizeof(u32);
 
213
        return size;
 
214
}
 
215
 
 
216
#if 0  /* If we need exit interception. */
 
217
static size_t ftrace_syscall_exit_state_size(void)
 
218
{
 
219
        return ALIGN(sizeof(struct syscall_trace_exit) + sizeof(u32),
 
220
                     sizeof(u64)) - sizeof(u32);
 
221
}
 
222
#endif
 
223
 
 
224
/* ftrace_syscall_enter_state - build state for filter matching
 
225
 *
 
226
 * @buf: buffer to populate with current task state for matching
 
227
 * @available: size available for use in the buffer.
 
228
 * @entry: optional pointer to the trace_entry member of the state.
 
229
 *
 
230
 * Returns 0 on success and non-zero otherwise.
 
231
 * If @entry is NULL, it will be ignored.
 
232
 */
 
233
static int ftrace_syscall_enter_state(u8 *buf, size_t available,
 
234
                                      struct trace_entry **entry)
 
235
{
 
236
        struct syscall_trace_enter *sys_enter;
 
237
        struct syscall_metadata *sys_data;
 
238
        int size;
 
239
        int syscall_nr;
 
240
        struct pt_regs *regs = task_pt_regs(current);
 
241
 
 
242
        syscall_nr = syscall_get_nr(current, regs);
 
243
        if (syscall_nr < 0)
 
244
                return -EINVAL;
 
245
 
 
246
        sys_data = syscall_nr_to_meta(syscall_nr);
 
247
        if (!sys_data)
 
248
                return -EINVAL;
 
249
 
 
250
        /* Determine the actual size needed. */
 
251
        size = ftrace_syscall_enter_state_size(sys_data->nb_args);
 
252
        BUG_ON(size > available);
 
253
        sys_enter = (struct syscall_trace_enter *)buf;
 
254
 
 
255
        /* Populating the struct trace_sys_enter is left to the caller, but
 
256
         * a pointer is returned to encourage opacity.
 
257
         */
 
258
        if (entry)
 
259
                *entry = &sys_enter->ent;
 
260
 
 
261
        sys_enter->nr = syscall_nr;
 
262
        syscall_get_arguments(current, regs, 0, sys_data->nb_args,
 
263
                              sys_enter->args);
 
264
        return 0;
 
265
}
 
266
 
 
267
#else  /*  defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PERF_EVENTS) */
 
268
 
 
269
#define create_event_filter(_ef_pptr, _event_type, _str) (-ENOSYS)
 
270
#define get_filter_string(_ef) (NULL)
 
271
#define free_event_filter(_f) do { } while (0)
 
272
 
 
273
#endif
 
274
 
 
275
/**
 
276
 * seccomp_filters_alloc - allocates a new filters object
 
277
 * @count: count to allocate for the event_filters array
 
278
 *
 
279
 * Returns ERR_PTR on error or an allocated object.
 
280
 */
 
281
static struct seccomp_filters *seccomp_filters_alloc(uint16_t count)
 
282
{
 
283
        struct seccomp_filters *f;
 
284
 
 
285
        if (count >= SECCOMP_ACTION_ALLOW)
 
286
                return ERR_PTR(-EINVAL);
 
287
 
 
288
        f = kzalloc(sizeof(struct seccomp_filters) +
 
289
                    (count * sizeof(struct event_filter *)), GFP_KERNEL);
 
290
        if (!f)
 
291
                return ERR_PTR(-ENOMEM);
 
292
 
 
293
        /* Lazy SECCOMP_ACTION_DENY assignment. */
 
294
        memset(f->syscalls, 0xff, sizeof(f->syscalls));
 
295
        kref_init(&f->usage);
 
296
 
 
297
        f->count = count;
 
298
        if (!count)
 
299
                return f;
 
300
 
 
301
        return f;
 
302
}
 
303
 
 
304
/**
 
305
 * seccomp_filters_free - cleans up the filter list and frees the table
 
306
 * @filters: NULL or live object to be completely destructed.
 
307
 */
 
308
static void seccomp_filters_free(struct seccomp_filters *filters)
 
309
{
 
310
        uint16_t count = 0;
 
311
        if (!filters)
 
312
                return;
 
313
        while (count < filters->count) {
 
314
                struct event_filter *f = filters->event_filters[count];
 
315
                free_event_filter(f);
 
316
                count++;
 
317
        }
 
318
        kfree(filters);
 
319
}
 
320
 
 
321
static void __put_seccomp_filters(struct kref *kref)
 
322
{
 
323
        struct seccomp_filters *orig =
 
324
                container_of(kref, struct seccomp_filters, usage);
 
325
        seccomp_filters_free(orig);
 
326
}
 
327
 
 
328
#define seccomp_filter_allow(_id) ((_id) == SECCOMP_ACTION_ALLOW)
 
329
#define seccomp_filter_deny(_id) ((_id) == SECCOMP_ACTION_DENY)
 
330
#define seccomp_filter_dynamic(_id) \
 
331
        (!seccomp_filter_allow(_id) && !seccomp_filter_deny(_id))
 
332
static inline uint16_t seccomp_filter_id(const struct seccomp_filters *f,
 
333
                                         int syscall_nr)
 
334
{
 
335
        if (!f)
 
336
                return SECCOMP_ACTION_DENY;
 
337
        return f->syscalls[syscall_nr];
 
338
}
 
339
 
 
340
static inline struct event_filter *seccomp_dynamic_filter(
 
341
                const struct seccomp_filters *filters, uint16_t id)
 
342
{
 
343
        if (!seccomp_filter_dynamic(id))
 
344
                return NULL;
 
345
        return filters->event_filters[id];
 
346
}
 
347
 
 
348
static inline void set_seccomp_filter_id(struct seccomp_filters *filters,
 
349
                                         int syscall_nr, uint16_t id)
 
350
{
 
351
        filters->syscalls[syscall_nr] = id;
 
352
}
 
353
 
 
354
static inline void set_seccomp_filter(struct seccomp_filters *filters,
 
355
                                      int syscall_nr, uint16_t id,
 
356
                                      struct event_filter *dynamic_filter)
 
357
{
 
358
        filters->syscalls[syscall_nr] = id;
 
359
        if (seccomp_filter_dynamic(id))
 
360
                filters->event_filters[id] = dynamic_filter;
 
361
}
 
362
 
 
363
static struct event_filter *alloc_event_filter(int syscall_nr,
 
364
                                               char *filter_string)
 
365
{
 
366
        struct syscall_metadata *data;
 
367
        struct event_filter *filter = NULL;
 
368
        int err;
 
369
 
 
370
        data = syscall_nr_to_meta(syscall_nr);
 
371
        /* Argument-based filtering only works on ftrace-hooked syscalls. */
 
372
        err = -ENOSYS;
 
373
        if (!data)
 
374
                goto fail;
 
375
        err = create_event_filter(&filter,
 
376
                                  data->enter_event->event.type,
 
377
                                  filter_string);
 
378
        if (err)
 
379
                goto fail;
 
380
 
 
381
        return filter;
 
382
fail:
 
383
        kfree(filter);
 
384
        return ERR_PTR(err);
 
385
}
 
386
 
 
387
/**
 
388
 * seccomp_filters_copy - copies filters from src to dst.
 
389
 *
 
390
 * @dst: seccomp_filters to populate.
 
391
 * @src: table to read from.
 
392
 * @skip: specifies an entry, by system call, to skip.
 
393
 *
 
394
 * Returns non-zero on failure.
 
395
 * Both the source and the destination should have no simultaneous
 
396
 * writers, and dst should be exclusive to the caller.
 
397
 * If @skip is < 0, it is ignored.
 
398
 */
 
399
static int seccomp_filters_copy(struct seccomp_filters *dst,
 
400
                                const struct seccomp_filters *src,
 
401
                                int skip)
 
402
{
 
403
        int id = 0, ret = 0, nr;
 
404
        memcpy(&dst->flags, &src->flags, sizeof(src->flags));
 
405
        memcpy(dst->syscalls, src->syscalls, sizeof(dst->syscalls));
 
406
        if (!src->count)
 
407
                goto done;
 
408
        for (nr = 0; nr < NR_syscalls; ++nr) {
 
409
                struct event_filter *filter;
 
410
                char *str;
 
411
                uint16_t src_id = seccomp_filter_id(src, nr);
 
412
                if (nr == skip) {
 
413
                        set_seccomp_filter(dst, nr, SECCOMP_ACTION_DENY,
 
414
                                           NULL);
 
415
                        continue;
 
416
                }
 
417
                if (!seccomp_filter_dynamic(src_id))
 
418
                        continue;
 
419
                if (id >= dst->count) {
 
420
                        ret = -EINVAL;
 
421
                        goto done;
 
422
                }
 
423
                str = get_filter_string(seccomp_dynamic_filter(src, src_id));
 
424
                filter = alloc_event_filter(nr, str);
 
425
                if (IS_ERR(filter)) {
 
426
                        ret = PTR_ERR(filter);
 
427
                        goto done;
 
428
                }
 
429
                set_seccomp_filter(dst, nr, id, filter);
 
430
                id++;
 
431
        }
 
432
 
 
433
done:
 
434
        return ret;
 
435
}
 
436
 
 
437
/**
 
438
 * seccomp_extend_filter - appends more text to a syscall_nr's filter
 
439
 * @filters: unattached filter object to operate on
 
440
 * @syscall_nr: syscall number to update filters for
 
441
 * @filter_string: string to append to the existing filter
 
442
 *
 
443
 * The new string will be &&'d to the original filter string to ensure that it
 
444
 * always matches the existing predicates or less:
 
445
 *   (old_filter) && @filter_string
 
446
 * A new seccomp_filters instance is returned on success and a ERR_PTR on
 
447
 * failure.
 
448
 */
 
449
static int seccomp_extend_filter(struct seccomp_filters *filters,
 
450
                                 int syscall_nr, char *filter_string)
 
451
{
 
452
        struct event_filter *filter;
 
453
        uint16_t id = seccomp_filter_id(filters, syscall_nr);
 
454
        char *merged = NULL;
 
455
        int ret = -EINVAL, expected;
 
456
 
 
457
        /* No extending with a "1". */
 
458
        if (!strcmp(SECCOMP_FILTER_ALLOW, filter_string))
 
459
                goto out;
 
460
 
 
461
        /* ftrace events are not aware of CONFIG_COMPAT system calls and will
 
462
         * use the incorrect argument metadata if enabled.
 
463
         */
 
464
        ret = -ENOSYS;
 
465
        if (filters->flags.compat)
 
466
                goto out;
 
467
 
 
468
        filter = seccomp_dynamic_filter(filters, id);
 
469
        ret = -ENOENT;
 
470
        if (!filter)
 
471
                goto out;
 
472
 
 
473
        merged = kzalloc(SECCOMP_MAX_FILTER_LENGTH + 1, GFP_KERNEL);
 
474
        ret = -ENOMEM;
 
475
        if (!merged)
 
476
                goto out;
 
477
 
 
478
        /* Encapsulate the filter strings in parentheses to isolate operator
 
479
         * precedence behavior.
 
480
         */
 
481
        expected = snprintf(merged, SECCOMP_MAX_FILTER_LENGTH, "(%s) && (%s)",
 
482
                            get_filter_string(filter), filter_string);
 
483
        ret = -E2BIG;
 
484
        if (expected >= SECCOMP_MAX_FILTER_LENGTH || expected < 0)
 
485
                goto out;
 
486
 
 
487
        /* Free the old filter */
 
488
        free_event_filter(filter);
 
489
        set_seccomp_filter(filters, syscall_nr, id, NULL);
 
490
 
 
491
        /* Replace it */
 
492
        filter = alloc_event_filter(syscall_nr, merged);
 
493
        if (IS_ERR(filter)) {
 
494
                ret = PTR_ERR(filter);
 
495
                goto out;
 
496
        }
 
497
        set_seccomp_filter(filters, syscall_nr, id, filter);
 
498
        ret = 0;
 
499
 
 
500
out:
 
501
        kfree(merged);
 
502
        return ret;
 
503
}
 
504
 
 
505
/**
 
506
 * seccomp_add_filter - adds a filter for an unfiltered syscall
 
507
 * @filters: filters object to add a filter/action to
 
508
 * @syscall_nr: system call number to add a filter for
 
509
 * @filter_string: the filter string to apply
 
510
 *
 
511
 * Returns 0 on success and non-zero otherwise.
 
512
 */
 
513
static int seccomp_add_filter(struct seccomp_filters *filters, int syscall_nr,
 
514
                              char *filter_string)
 
515
{
 
516
        struct event_filter *filter;
 
517
        int ret = 0;
 
518
 
 
519
        if (!strcmp(SECCOMP_FILTER_ALLOW, filter_string)) {
 
520
                set_seccomp_filter(filters, syscall_nr,
 
521
                                   SECCOMP_ACTION_ALLOW, NULL);
 
522
                goto out;
 
523
        }
 
524
 
 
525
        /* ftrace events are not aware of CONFIG_COMPAT system calls and will
 
526
         * use the incorrect argument metadata if enabled.
 
527
         */
 
528
        ret = -ENOSYS;
 
529
        if (filters->flags.compat)
 
530
                goto out;
 
531
 
 
532
        ret = 0;
 
533
        filter = alloc_event_filter(syscall_nr, filter_string);
 
534
        if (IS_ERR(filter)) {
 
535
                ret = PTR_ERR(filter);
 
536
                goto out;
 
537
        }
 
538
        /* Always add to the last slot available since additions are
 
539
         * are only done one at a time.
 
540
         */
 
541
        set_seccomp_filter(filters, syscall_nr, filters->count - 1, filter);
 
542
out:
 
543
        return ret;
 
544
}
 
545
 
 
546
/* Wrap optional ftrace syscall support. Returns 1 on match or 0 otherwise. */
 
547
static int filter_match_current(struct event_filter *event_filter)
 
548
{
 
549
        int err = 0;
 
550
#ifdef CONFIG_FTRACE_SYSCALLS
 
551
        uint8_t syscall_state[64];
 
552
 
 
553
        memset(syscall_state, 0, sizeof(syscall_state));
 
554
 
 
555
        /* The generic tracing entry can remain zeroed. */
 
556
        err = ftrace_syscall_enter_state(syscall_state, sizeof(syscall_state),
 
557
                                         NULL);
 
558
        if (err)
 
559
                return 0;
 
560
 
 
561
        err = filter_match_preds(event_filter, syscall_state);
 
562
#endif
 
563
        return err;
 
564
}
 
565
 
 
566
static const char *syscall_nr_to_name(int syscall)
 
567
{
 
568
        const char *syscall_name = "unknown";
 
569
        struct syscall_metadata *data = syscall_nr_to_meta(syscall);
 
570
        if (data)
 
571
                syscall_name = data->name;
 
572
        return syscall_name;
 
573
}
 
574
 
 
575
/* Encodes translation from sys_enter events to system call numbers.
 
576
 * Returns -ENOSYS when the event doesn't match a system call or if
 
577
 * current is_compat_task().  ftrace has no awareness of CONFIG_COMPAT
 
578
 * yet.
 
579
 */
 
580
static int event_to_syscall_nr(int event_id)
 
581
{
 
582
        int nr, nosys = 1;
 
583
#ifdef CONFIG_COMPAT
 
584
        if (is_compat_task())
 
585
                return -ENOSYS;
 
586
#endif
 
587
        for (nr = 0; nr < NR_syscalls; ++nr) {
 
588
                struct syscall_metadata *data = syscall_nr_to_meta(nr);
 
589
                if (!data)
 
590
                        continue;
 
591
                nosys = 0;
 
592
                if (data->enter_event->event.type == event_id)
 
593
                        return nr;
 
594
        }
 
595
        if (nosys)
 
596
                return -ENOSYS;
 
597
        return -EINVAL;
 
598
}
 
599
 
 
600
static void filters_set_compat(struct seccomp_filters *filters)
 
601
{
 
602
#ifdef CONFIG_COMPAT
 
603
        if (is_compat_task())
 
604
                filters->flags.compat = 1;
 
605
#endif
 
606
}
 
607
 
 
608
static inline int filters_compat_mismatch(struct seccomp_filters *filters)
 
609
{
 
610
        int ret = 0;
 
611
        if (!filters)
 
612
                return 0;
 
613
#ifdef CONFIG_COMPAT
 
614
        if (!!(is_compat_task()) != filters->flags.compat)
 
615
                ret = 1;
 
616
#endif
 
617
        return ret;
 
618
}
 
619
 
 
620
static inline int syscall_is_execve(int syscall)
 
621
{
 
622
        int nr = __NR_execve;
 
623
#ifdef CONFIG_COMPAT
 
624
        if (is_compat_task())
 
625
                nr = __NR_seccomp_execve_32;
 
626
#endif
 
627
        return syscall == nr;
 
628
}
 
629
 
 
630
#ifndef KSTK_EIP
 
631
#define KSTK_EIP(x) 0L
 
632
#endif
 
633
 
 
634
void seccomp_filter_log_failure(int syscall)
 
635
{
 
636
        pr_info("%s[%d]: system call %d (%s) blocked at 0x%lx\n",
 
637
                current->comm, task_pid_nr(current), syscall,
 
638
                syscall_nr_to_name(syscall), KSTK_EIP(current));
 
639
}
 
640
 
 
641
/* put_seccomp_filters - decrements the ref count of @orig and may free. */
 
642
void put_seccomp_filters(struct seccomp_filters *orig)
 
643
{
 
644
        if (!orig)
 
645
                return;
 
646
        kref_put(&orig->usage, __put_seccomp_filters);
 
647
}
 
648
 
 
649
/* get_seccomp_filters - increments the reference count of @orig. */
 
650
struct seccomp_filters *get_seccomp_filters(struct seccomp_filters *orig)
 
651
{
 
652
        if (!orig)
 
653
                return NULL;
 
654
        /* XXX: kref needs overflow prevention support. */
 
655
        kref_get(&orig->usage);
 
656
        return orig;
 
657
}
 
658
 
 
659
/**
 
660
 * seccomp_test_filters - tests 'current' against the given syscall
 
661
 * @syscall: number of the system call to test
 
662
 *
 
663
 * Returns 0 on ok and non-zero on error/failure.
 
664
 */
 
665
int seccomp_test_filters(int syscall)
 
666
{
 
667
        uint16_t id;
 
668
        struct event_filter *filter;
 
669
        struct seccomp_filters *filters;
 
670
        int ret = -EACCES;
 
671
 
 
672
        mutex_lock(&current->seccomp.filters_guard);
 
673
        /* No reference counting is done. filters_guard should protect the
 
674
         * lifetime of any existing pointer below.
 
675
         */
 
676
        filters = current->seccomp.filters;
 
677
        if (!filters)
 
678
                goto out;
 
679
 
 
680
        if (filters_compat_mismatch(filters)) {
 
681
                pr_info("%s[%d]: seccomp_filter compat() mismatch.\n",
 
682
                        current->comm, task_pid_nr(current));
 
683
                goto out;
 
684
        }
 
685
 
 
686
        /* execve is never allowed. */
 
687
        if (syscall_is_execve(syscall))
 
688
                goto out;
 
689
 
 
690
        ret = 0;
 
691
        id = seccomp_filter_id(filters, syscall);
 
692
        if (seccomp_filter_allow(id))
 
693
                goto out;
 
694
 
 
695
        ret = -EACCES;
 
696
        if (!seccomp_filter_dynamic(id))
 
697
                goto out;
 
698
 
 
699
        filter = seccomp_dynamic_filter(filters, id);
 
700
        if (filter && filter_match_current(filter))
 
701
                ret = 0;
 
702
out:
 
703
        mutex_unlock(&current->seccomp.filters_guard);
 
704
        return ret;
 
705
}
 
706
 
 
707
/**
 
708
 * seccomp_show_filters - prints the current filter state to a seq_file
 
709
 * @filters: properly get()'d filters object
 
710
 * @m: the prepared seq_file to receive the data
 
711
 *
 
712
 * Returns 0 on a successful write.
 
713
 */
 
714
int seccomp_show_filters(struct seccomp_filters *filters, struct seq_file *m)
 
715
{
 
716
        int syscall;
 
717
        if (!filters)
 
718
                goto out;
 
719
 
 
720
        for (syscall = 0; syscall < NR_syscalls; ++syscall) {
 
721
                uint16_t id = seccomp_filter_id(filters, syscall);
 
722
                const char *filter_string = SECCOMP_FILTER_ALLOW;
 
723
                if (seccomp_filter_deny(id))
 
724
                        continue;
 
725
                seq_printf(m, "%d (%s): ",
 
726
                              syscall,
 
727
                              syscall_nr_to_name(syscall));
 
728
                if (seccomp_filter_dynamic(id))
 
729
                        filter_string = get_filter_string(
 
730
                                          seccomp_dynamic_filter(filters, id));
 
731
                seq_printf(m, "%s\n", filter_string);
 
732
        }
 
733
out:
 
734
        return 0;
 
735
}
 
736
EXPORT_SYMBOL_GPL(seccomp_show_filters);
 
737
 
 
738
/**
 
739
 * seccomp_get_filter - copies the filter_string into "buf"
 
740
 * @syscall_nr: system call number to look up
 
741
 * @buf: destination buffer
 
742
 * @bufsize: available space in the buffer.
 
743
 *
 
744
 * Context: User context only. This function may sleep on allocation and
 
745
 *          operates on current. current must be attempting a system call
 
746
 *          when this is called.
 
747
 *
 
748
 * Looks up the filter for the given system call number on current.  If found,
 
749
 * the string length of the NUL-terminated buffer is returned and < 0 is
 
750
 * returned on error. The NUL byte is not included in the length.
 
751
 */
 
752
long seccomp_get_filter(int syscall_nr, char *buf, unsigned long bufsize)
 
753
{
 
754
        struct seccomp_filters *filters;
 
755
        struct event_filter *filter;
 
756
        long ret = -EINVAL;
 
757
        uint16_t id;
 
758
 
 
759
        if (bufsize > SECCOMP_MAX_FILTER_LENGTH)
 
760
                bufsize = SECCOMP_MAX_FILTER_LENGTH;
 
761
 
 
762
        mutex_lock(&current->seccomp.filters_guard);
 
763
        filters = current->seccomp.filters;
 
764
 
 
765
        if (!filters)
 
766
                goto out;
 
767
 
 
768
        ret = -ENOENT;
 
769
        id = seccomp_filter_id(filters, syscall_nr);
 
770
        if (seccomp_filter_deny(id))
 
771
                goto out;
 
772
 
 
773
        if (seccomp_filter_allow(id)) {
 
774
                ret = strlcpy(buf, SECCOMP_FILTER_ALLOW, bufsize);
 
775
                goto copied;
 
776
        }
 
777
 
 
778
        filter = seccomp_dynamic_filter(filters, id);
 
779
        if (!filter)
 
780
                goto out;
 
781
        ret = strlcpy(buf, get_filter_string(filter), bufsize);
 
782
 
 
783
copied:
 
784
        if (ret >= bufsize) {
 
785
                ret = -ENOSPC;
 
786
                goto out;
 
787
        }
 
788
out:
 
789
        mutex_unlock(&current->seccomp.filters_guard);
 
790
        return ret;
 
791
}
 
792
EXPORT_SYMBOL_GPL(seccomp_get_filter);
 
793
 
 
794
/**
 
795
 * seccomp_clear_filter: clears the seccomp filter for a syscall.
 
796
 * @syscall_nr: the system call number to clear filters for.
 
797
 *
 
798
 * Context: User context only. This function may sleep on allocation and
 
799
 *          operates on current. current must be attempting a system call
 
800
 *          when this is called.
 
801
 *
 
802
 * Returns 0 on success.
 
803
 */
 
804
long seccomp_clear_filter(int syscall_nr)
 
805
{
 
806
        struct seccomp_filters *filters = NULL, *orig_filters;
 
807
        uint16_t id;
 
808
        int ret = -EINVAL;
 
809
 
 
810
        mutex_lock(&current->seccomp.filters_guard);
 
811
        orig_filters = current->seccomp.filters;
 
812
 
 
813
        if (!orig_filters)
 
814
                goto out;
 
815
 
 
816
        if (filters_compat_mismatch(orig_filters))
 
817
                goto out;
 
818
 
 
819
        id = seccomp_filter_id(orig_filters, syscall_nr);
 
820
        if (seccomp_filter_deny(id))
 
821
                goto out;
 
822
 
 
823
        /* Create a new filters object for the task */
 
824
        if (seccomp_filter_dynamic(id))
 
825
                filters = seccomp_filters_alloc(orig_filters->count - 1);
 
826
        else
 
827
                filters = seccomp_filters_alloc(orig_filters->count);
 
828
 
 
829
        if (IS_ERR(filters)) {
 
830
                ret = PTR_ERR(filters);
 
831
                goto out;
 
832
        }
 
833
 
 
834
        /* Copy, but drop the requested entry. */
 
835
        ret = seccomp_filters_copy(filters, orig_filters, syscall_nr);
 
836
        if (ret)
 
837
                goto out;
 
838
        get_seccomp_filters(filters);  /* simplify the out: path */
 
839
 
 
840
        current->seccomp.filters = filters;
 
841
        put_seccomp_filters(orig_filters);  /* for the task */
 
842
out:
 
843
        put_seccomp_filters(filters);  /* for the extra get */
 
844
        mutex_unlock(&current->seccomp.filters_guard);
 
845
        return ret;
 
846
}
 
847
EXPORT_SYMBOL_GPL(seccomp_clear_filter);
 
848
 
 
849
/**
 
850
 * seccomp_set_filter: - Adds/extends a seccomp filter for a syscall.
 
851
 * @syscall_nr: system call number to apply the filter to.
 
852
 * @filter: ftrace filter string to apply.
 
853
 *
 
854
 * Context: User context only. This function may sleep on allocation and
 
855
 *          operates on current. current must be attempting a system call
 
856
 *          when this is called.
 
857
 *
 
858
 * New filters may be added for system calls when the current task is
 
859
 * not in a secure computing mode (seccomp).  Otherwise, existing filters may
 
860
 * be extended.
 
861
 *
 
862
 * Returns 0 on success or an errno on failure.
 
863
 */
 
864
long seccomp_set_filter(int syscall_nr, char *filter)
 
865
{
 
866
        struct seccomp_filters *filters = NULL, *orig_filters = NULL;
 
867
        uint16_t id;
 
868
        long ret = -EINVAL;
 
869
        uint16_t filters_needed;
 
870
 
 
871
        mutex_lock(&current->seccomp.filters_guard);
 
872
        if (!filter)
 
873
                goto out;
 
874
 
 
875
        filter = strstrip(filter);
 
876
        /* Disallow empty strings. */
 
877
        if (filter[0] == 0)
 
878
                goto out;
 
879
 
 
880
        orig_filters = current->seccomp.filters;
 
881
 
 
882
        /* After the first call, compatibility mode is selected permanently. */
 
883
        ret = -EACCES;
 
884
        if (filters_compat_mismatch(orig_filters))
 
885
                goto out;
 
886
 
 
887
        filters_needed = orig_filters ? orig_filters->count : 0;
 
888
        id = seccomp_filter_id(orig_filters, syscall_nr);
 
889
        if (seccomp_filter_deny(id)) {
 
890
                /* Don't allow DENYs to be changed when in a seccomp mode */
 
891
                ret = -EACCES;
 
892
                if (current->seccomp.mode)
 
893
                        goto out;
 
894
                filters_needed++;
 
895
        }
 
896
 
 
897
        filters = seccomp_filters_alloc(filters_needed);
 
898
        if (IS_ERR(filters)) {
 
899
                ret = PTR_ERR(filters);
 
900
                goto out;
 
901
        }
 
902
 
 
903
        filters_set_compat(filters);
 
904
        if (orig_filters) {
 
905
                ret = seccomp_filters_copy(filters, orig_filters, -1);
 
906
                if (ret)
 
907
                        goto out;
 
908
        }
 
909
 
 
910
        if (seccomp_filter_deny(id))
 
911
                ret = seccomp_add_filter(filters, syscall_nr, filter);
 
912
        else
 
913
                ret = seccomp_extend_filter(filters, syscall_nr, filter);
 
914
        if (ret)
 
915
                goto out;
 
916
        get_seccomp_filters(filters);  /* simplify the error paths */
 
917
 
 
918
        current->seccomp.filters = filters;
 
919
        put_seccomp_filters(orig_filters);  /* for the task */
 
920
out:
 
921
        put_seccomp_filters(filters);  /* for get or task, on err */
 
922
        mutex_unlock(&current->seccomp.filters_guard);
 
923
        return ret;
 
924
}
 
925
EXPORT_SYMBOL_GPL(seccomp_set_filter);
 
926
 
 
927
long prctl_set_seccomp_filter(unsigned long id_type,
 
928
                              unsigned long id,
 
929
                              char __user *user_filter)
 
930
{
 
931
        int nr;
 
932
        long ret;
 
933
        char *filter = NULL;
 
934
 
 
935
        ret = -EINVAL;
 
936
        if (id_type != PR_SECCOMP_FILTER_EVENT &&
 
937
            id_type != PR_SECCOMP_FILTER_SYSCALL)
 
938
                goto out;
 
939
 
 
940
        if (id > (unsigned long) INT_MAX)
 
941
                goto out;
 
942
        nr = (int) id;
 
943
 
 
944
        if (id_type == PR_SECCOMP_FILTER_EVENT)
 
945
                nr = event_to_syscall_nr(nr);
 
946
 
 
947
        if (nr < 0) {
 
948
                ret = nr;
 
949
                goto out;
 
950
        }
 
951
 
 
952
        if (nr >= NR_syscalls)
 
953
                goto out;
 
954
 
 
955
        ret = -EFAULT;
 
956
        if (!user_filter)
 
957
                goto out;
 
958
 
 
959
        filter = kzalloc(SECCOMP_MAX_FILTER_LENGTH + 1, GFP_KERNEL);
 
960
        ret = -ENOMEM;
 
961
        if (!filter)
 
962
                goto out;
 
963
 
 
964
        ret = -EFAULT;
 
965
        if (strncpy_from_user(filter, user_filter,
 
966
                              SECCOMP_MAX_FILTER_LENGTH - 1) < 0)
 
967
                goto out;
 
968
 
 
969
        ret = seccomp_set_filter(nr, filter);
 
970
 
 
971
out:
 
972
        kfree(filter);
 
973
        return ret;
 
974
}
 
975
 
 
976
long prctl_clear_seccomp_filter(unsigned long id_type, unsigned long id)
 
977
{
 
978
        int nr = -1;
 
979
        long ret = -EINVAL;
 
980
 
 
981
        if (id_type != PR_SECCOMP_FILTER_EVENT &&
 
982
            id_type != PR_SECCOMP_FILTER_SYSCALL)
 
983
                goto out;
 
984
 
 
985
        if (id > (unsigned long) INT_MAX)
 
986
                goto out;
 
987
 
 
988
        nr = (int) id;
 
989
        if (id_type == PR_SECCOMP_FILTER_EVENT)
 
990
                nr = event_to_syscall_nr(nr);
 
991
 
 
992
        if (nr < 0) {
 
993
                ret = nr;
 
994
                goto out;
 
995
        }
 
996
 
 
997
        if (nr >= NR_syscalls)
 
998
                goto out;
 
999
 
 
1000
        ret = seccomp_clear_filter(nr);
 
1001
 
 
1002
out:
 
1003
        return ret;
 
1004
}
 
1005
 
 
1006
long prctl_get_seccomp_filter(unsigned long id_type, unsigned long id,
 
1007
                              char __user *dst, unsigned long available)
 
1008
{
 
1009
        unsigned long copied;
 
1010
        char *buf = NULL;
 
1011
        int nr, ret = -EINVAL;
 
1012
 
 
1013
        if (!available)
 
1014
                goto out;
 
1015
 
 
1016
        /* Ignore extra buffer space. */
 
1017
        if (available > SECCOMP_MAX_FILTER_LENGTH)
 
1018
                available = SECCOMP_MAX_FILTER_LENGTH;
 
1019
 
 
1020
        if (id_type != PR_SECCOMP_FILTER_EVENT &&
 
1021
            id_type != PR_SECCOMP_FILTER_SYSCALL)
 
1022
                goto out;
 
1023
 
 
1024
        if (id > (unsigned long) INT_MAX)
 
1025
                goto out;
 
1026
        nr = (int) id;
 
1027
 
 
1028
        if (id_type == PR_SECCOMP_FILTER_EVENT)
 
1029
                nr = event_to_syscall_nr(nr);
 
1030
 
 
1031
        if (nr < 0) {
 
1032
                ret = nr;
 
1033
                goto out;
 
1034
        }
 
1035
 
 
1036
        if (nr >= NR_syscalls)
 
1037
                goto out;
 
1038
 
 
1039
        ret = -ENOMEM;
 
1040
        buf = kzalloc(available, GFP_KERNEL);
 
1041
        if (!buf)
 
1042
                goto out;
 
1043
 
 
1044
        ret = seccomp_get_filter(nr, buf, available);
 
1045
        if (ret < 0)
 
1046
                goto out;
 
1047
 
 
1048
        /* Include the NUL byte in the copy. */
 
1049
        copied = copy_to_user(dst, buf, ret + 1);
 
1050
        ret = -ENOSPC;
 
1051
        if (copied)
 
1052
                goto out;
 
1053
        ret = 0;
 
1054
out:
 
1055
        kfree(buf);
 
1056
        return ret;
 
1057
}