linux/security/apparmor/include/match.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * AppArmor security module
   4 *
   5 * This file contains AppArmor policy dfa matching engine definitions.
   6 *
   7 * Copyright (C) 1998-2008 Novell/SUSE
   8 * Copyright 2009-2012 Canonical Ltd.
   9 */
  10
  11#ifndef __AA_MATCH_H
  12#define __AA_MATCH_H
  13
  14#include <linux/kref.h>
  15
  16#define DFA_NOMATCH                     0
  17#define DFA_START                       1
  18
  19
  20/**
  21 * The format used for transition tables is based on the GNU flex table
  22 * file format (--tables-file option; see Table File Format in the flex
  23 * info pages and the flex sources for documentation). The magic number
  24 * used in the header is 0x1B5E783D instead of 0xF13C57B1 though, because
  25 * new tables have been defined and others YY_ID_CHK (check) and YY_ID_DEF
  26 * (default) tables are used slightly differently (see the apparmor-parser
  27 * package).
  28 *
  29 *
  30 * The data in the packed dfa is stored in network byte order, and the tables
  31 * are arranged for flexibility.  We convert the table data to host native
  32 * byte order.
  33 *
  34 * The dfa begins with a table set header, and is followed by the actual
  35 * tables.
  36 */
  37
  38#define YYTH_MAGIC      0x1B5E783D
  39#define YYTH_FLAG_DIFF_ENCODE   1
  40#define YYTH_FLAG_OOB_TRANS     2
  41#define YYTH_FLAGS (YYTH_FLAG_DIFF_ENCODE | YYTH_FLAG_OOB_TRANS)
  42
  43#define MAX_OOB_SUPPORTED       1
  44
  45struct table_set_header {
  46        u32 th_magic;           /* YYTH_MAGIC */
  47        u32 th_hsize;
  48        u32 th_ssize;
  49        u16 th_flags;
  50        char th_version[];
  51};
  52
  53/* The YYTD_ID are one less than flex table mappings.  The flex id
  54 * has 1 subtracted at table load time, this allows us to directly use the
  55 * ID's as indexes.
  56 */
  57#define YYTD_ID_ACCEPT  0
  58#define YYTD_ID_BASE    1
  59#define YYTD_ID_CHK     2
  60#define YYTD_ID_DEF     3
  61#define YYTD_ID_EC      4
  62#define YYTD_ID_META    5
  63#define YYTD_ID_ACCEPT2 6
  64#define YYTD_ID_NXT     7
  65#define YYTD_ID_TSIZE   8
  66#define YYTD_ID_MAX     8
  67
  68#define YYTD_DATA8      1
  69#define YYTD_DATA16     2
  70#define YYTD_DATA32     4
  71#define YYTD_DATA64     8
  72
  73/* ACCEPT & ACCEPT2 tables gets 6 dedicated flags, YYTD_DATAX define the
  74 * first flags
  75 */
  76#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
  77#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2)
  78#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X)
  79#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2)
  80#define DFA_FLAG_VERIFY_STATES 0x1000
  81
  82struct table_header {
  83        u16 td_id;
  84        u16 td_flags;
  85        u32 td_hilen;
  86        u32 td_lolen;
  87        char td_data[];
  88};
  89
  90#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
  91#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
  92#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
  93#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
  94#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
  95#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
  96#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
  97
  98struct aa_dfa {
  99        struct kref count;
 100        u16 flags;
 101        u32 max_oob;
 102        struct table_header *tables[YYTD_ID_TSIZE];
 103};
 104
 105extern struct aa_dfa *nulldfa;
 106extern struct aa_dfa *stacksplitdfa;
 107
 108#define byte_to_byte(X) (X)
 109
 110#define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX)     \
 111        do { \
 112                typeof(LEN) __i; \
 113                TTYPE *__t = (TTYPE *) TABLE; \
 114                BTYPE *__b = (BTYPE *) BLOB; \
 115                for (__i = 0; __i < LEN; __i++) { \
 116                        __t[__i] = NTOHX(__b[__i]); \
 117                } \
 118        } while (0)
 119
 120static inline size_t table_size(size_t len, size_t el_size)
 121{
 122        return ALIGN(sizeof(struct table_header) + len * el_size, 8);
 123}
 124
 125int aa_setup_dfa_engine(void);
 126void aa_teardown_dfa_engine(void);
 127
 128struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
 129unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
 130                              const char *str, int len);
 131unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
 132                          const char *str);
 133unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
 134                         const char c);
 135unsigned int aa_dfa_outofband_transition(struct aa_dfa *dfa,
 136                                         unsigned int state);
 137unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start,
 138                                const char *str, const char **retpos);
 139unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start,
 140                                 const char *str, int n, const char **retpos);
 141
 142void aa_dfa_free_kref(struct kref *kref);
 143
 144#define WB_HISTORY_SIZE 24
 145struct match_workbuf {
 146        unsigned int count;
 147        unsigned int pos;
 148        unsigned int len;
 149        unsigned int size;      /* power of 2, same as history size */
 150        unsigned int history[WB_HISTORY_SIZE];
 151};
 152#define DEFINE_MATCH_WB(N)              \
 153struct match_workbuf N = {              \
 154        .count = 0,                     \
 155        .pos = 0,                       \
 156        .len = 0,                       \
 157}
 158
 159unsigned int aa_dfa_leftmatch(struct aa_dfa *dfa, unsigned int start,
 160                              const char *str, unsigned int *count);
 161
 162/**
 163 * aa_get_dfa - increment refcount on dfa @p
 164 * @dfa: dfa  (MAYBE NULL)
 165 *
 166 * Returns: pointer to @dfa if @dfa is NULL will return NULL
 167 * Requires: @dfa must be held with valid refcount when called
 168 */
 169static inline struct aa_dfa *aa_get_dfa(struct aa_dfa *dfa)
 170{
 171        if (dfa)
 172                kref_get(&(dfa->count));
 173
 174        return dfa;
 175}
 176
 177/**
 178 * aa_put_dfa - put a dfa refcount
 179 * @dfa: dfa to put refcount   (MAYBE NULL)
 180 *
 181 * Requires: if @dfa != NULL that a valid refcount be held
 182 */
 183static inline void aa_put_dfa(struct aa_dfa *dfa)
 184{
 185        if (dfa)
 186                kref_put(&dfa->count, aa_dfa_free_kref);
 187}
 188
 189#define MATCH_FLAG_DIFF_ENCODE 0x80000000
 190#define MARK_DIFF_ENCODE 0x40000000
 191#define MATCH_FLAG_OOB_TRANSITION 0x20000000
 192#define MATCH_FLAGS_MASK 0xff000000
 193#define MATCH_FLAGS_VALID (MATCH_FLAG_DIFF_ENCODE | MATCH_FLAG_OOB_TRANSITION)
 194#define MATCH_FLAGS_INVALID (MATCH_FLAGS_MASK & ~MATCH_FLAGS_VALID)
 195
 196#endif /* __AA_MATCH_H */
 197