mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-31 06:16:03 +00:00
Add dfa support to the parser
This commit is contained in:
@@ -77,6 +77,9 @@ OBJECTS = parser_lex.o parser_yacc.o parser_main.o parser_interface.o \
|
|||||||
parser_include.o parser_merge.o parser_symtab.o parser_misc.o \
|
parser_include.o parser_merge.o parser_symtab.o parser_misc.o \
|
||||||
parser_regex.o parser_variable.o parser_policy.o
|
parser_regex.o parser_variable.o parser_policy.o
|
||||||
|
|
||||||
|
AAREDIR= libapparmor_re
|
||||||
|
AAREOBJECTS = ${AAREDIR}/libapparmor_re.a
|
||||||
|
|
||||||
PCREDIR= pcre
|
PCREDIR= pcre
|
||||||
PCREOBJECTS = ${PCREDIR}/pcre.o
|
PCREOBJECTS = ${PCREDIR}/pcre.o
|
||||||
|
|
||||||
@@ -110,8 +113,11 @@ all: $(LEX_C_FILES) $(YACC_C_FILES) $(TOOLS)
|
|||||||
$(Q)make -C po all
|
$(Q)make -C po all
|
||||||
$(Q)make -s tests
|
$(Q)make -s tests
|
||||||
|
|
||||||
apparmor_parser: $(OBJECTS) $(PCREOBJECTS)
|
apparmor_parser: $(OBJECTS) $(PCREOBJECTS) $(AAREOBJECTS)
|
||||||
$(CC) $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(PCREOBJECTS) $(LIBS) ${LEXLIB}
|
rm -f ./libstdc++.a
|
||||||
|
ln -s `g++ -print-file-name=libstdc++.a`
|
||||||
|
g++ $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(PCREOBJECTS) $(LIBS) \
|
||||||
|
${LEXLIB} $(AAREOBJECTS) -static-libgcc -L.
|
||||||
|
|
||||||
parser_yacc.c parser_yacc.h: parser_yacc.y parser.h
|
parser_yacc.c parser_yacc.h: parser_yacc.y parser.h
|
||||||
$(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y
|
$(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y
|
||||||
@@ -174,6 +180,10 @@ tests: ${TESTS}
|
|||||||
$(Q)make -s -C tst tests
|
$(Q)make -s -C tst tests
|
||||||
|
|
||||||
# always need to rebuild.
|
# always need to rebuild.
|
||||||
|
.SILENT: $(AAREOBJECTS)
|
||||||
|
$(AAREOBJECTS):
|
||||||
|
make -C $(AAREDIR)
|
||||||
|
|
||||||
.SILENT: $(PCREOBJECTS)
|
.SILENT: $(PCREOBJECTS)
|
||||||
$(PCREOBJECTS):
|
$(PCREOBJECTS):
|
||||||
make -C $(PCREDIR) "CFLAGS=$(CFLAGS)"
|
make -C $(PCREDIR) "CFLAGS=$(CFLAGS)"
|
||||||
@@ -229,7 +239,9 @@ clean:
|
|||||||
rm -f $(YACC_C_FILES)
|
rm -f $(YACC_C_FILES)
|
||||||
rm -f parser_version.h
|
rm -f parser_version.h
|
||||||
rm -f $(NAME)*.tar.gz $(NAME)*.tgz
|
rm -f $(NAME)*.tar.gz $(NAME)*.tgz
|
||||||
|
rm -rf libstdc++.a
|
||||||
make -s -C $(PCREDIR) clean
|
make -s -C $(PCREDIR) clean
|
||||||
|
make -s -C $(AAREDIR) clean
|
||||||
make -s -C po clean
|
make -s -C po clean
|
||||||
|
|
||||||
.SILENT: dist_clean
|
.SILENT: dist_clean
|
||||||
|
121
parser/immunix.h
121
parser/immunix.h
@@ -21,64 +21,70 @@
|
|||||||
#define _IMMUNIX_H
|
#define _IMMUNIX_H
|
||||||
|
|
||||||
/* start of system offsets */
|
/* start of system offsets */
|
||||||
#define POS_KERN_COD_FILE_MIN 0
|
#define POS_AA_FILE_MIN 0
|
||||||
#define POS_KERN_COD_MAY_EXEC POS_KERN_COD_FILE_MIN
|
#define POS_AA_MAY_EXEC POS_AA_FILE_MIN
|
||||||
#define POS_KERN_COD_MAY_WRITE (POS_KERN_COD_MAY_EXEC + 1)
|
#define POS_AA_MAY_WRITE (POS_AA_MAY_EXEC + 1)
|
||||||
#define POS_KERN_COD_MAY_READ (POS_KERN_COD_MAY_WRITE + 1)
|
#define POS_AA_MAY_READ (POS_AA_MAY_WRITE + 1)
|
||||||
/* not used by Subdomain */
|
/* not used by Subdomain */
|
||||||
#define POS_KERN_COD_MAY_APPEND (POS_KERN_COD_MAY_READ + 1)
|
#define POS_AA_MAY_APPEND (POS_AA_MAY_READ + 1)
|
||||||
/* end of system offsets */
|
/* end of system offsets */
|
||||||
|
|
||||||
#define POS_KERN_COD_MAY_LINK (POS_KERN_COD_MAY_APPEND + 1)
|
#define POS_AA_MAY_LINK (POS_AA_MAY_APPEND + 1)
|
||||||
#define POS_KERN_COD_EXEC_INHERIT (POS_KERN_COD_MAY_LINK + 1)
|
#define POS_AA_EXEC_INHERIT (POS_AA_MAY_LINK + 1)
|
||||||
#define POS_KERN_COD_EXEC_UNCONSTRAINED (POS_KERN_COD_EXEC_INHERIT + 1)
|
#define POS_AA_EXEC_UNCONSTRAINED (POS_AA_EXEC_INHERIT + 1)
|
||||||
#define POS_KERN_COD_EXEC_PROFILE (POS_KERN_COD_EXEC_UNCONSTRAINED + 1)
|
#define POS_AA_EXEC_PROFILE (POS_AA_EXEC_UNCONSTRAINED + 1)
|
||||||
#define POS_KERN_COD_EXEC_MMAP (POS_KERN_COD_EXEC_PROFILE + 1)
|
#define POS_AA_EXEC_MMAP (POS_AA_EXEC_PROFILE + 1)
|
||||||
#define POS_KERN_COD_EXEC_UNSAFE (POS_KERN_COD_EXEC_MMAP + 1)
|
#define POS_AA_EXEC_UNSAFE (POS_AA_EXEC_MMAP + 1)
|
||||||
#define POS_KERN_COD_FILE_MAX POS_KERN_COD_EXEC_UNSAFE
|
#define POS_AA_FILE_MAX POS_AA_EXEC_UNSAFE
|
||||||
|
|
||||||
#define POS_KERN_COD_NET_MIN (POS_KERN_COD_FILE_MAX + 1)
|
#define POS_AA_NET_MIN (POS_AA_FILE_MAX + 1)
|
||||||
#define POS_KERN_COD_TCP_CONNECT POS_KERN_COD_NET_MIN
|
#define POS_AA_TCP_CONNECT POS_AA_NET_MIN
|
||||||
#define POS_KERN_COD_TCP_ACCEPT (POS_KERN_COD_TCP_CONNECT + 1)
|
#define POS_AA_TCP_ACCEPT (POS_AA_TCP_CONNECT + 1)
|
||||||
#define POS_KERN_COD_TCP_CONNECTED (POS_KERN_COD_TCP_ACCEPT + 1)
|
#define POS_AA_TCP_CONNECTED (POS_AA_TCP_ACCEPT + 1)
|
||||||
#define POS_KERN_COD_TCP_ACCEPTED (POS_KERN_COD_TCP_CONNECTED + 1)
|
#define POS_AA_TCP_ACCEPTED (POS_AA_TCP_CONNECTED + 1)
|
||||||
#define POS_KERN_COD_UDP_SEND (POS_KERN_COD_TCP_ACCEPTED + 1)
|
#define POS_AA_UDP_SEND (POS_AA_TCP_ACCEPTED + 1)
|
||||||
#define POS_KERN_COD_UDP_RECEIVE (POS_KERN_COD_UDP_SEND + 1)
|
#define POS_AA_UDP_RECEIVE (POS_AA_UDP_SEND + 1)
|
||||||
#define POS_KERN_COD_NET_MAX POS_KERN_COD_UDP_RECEIVE
|
#define POS_AA_NET_MAX POS_AA_UDP_RECEIVE
|
||||||
|
|
||||||
/* logging only */
|
/* logging only */
|
||||||
#define POS_KERN_COD_LOGTCP_SEND (POS_KERN_COD_NET_MAX + 1)
|
#define POS_AA_LOGTCP_SEND (POS_AA_NET_MAX + 1)
|
||||||
#define POS_KERN_COD_LOGTCP_RECEIVE (POS_KERN_COD_LOGTCP_SEND + 1)
|
#define POS_AA_LOGTCP_RECEIVE (POS_AA_LOGTCP_SEND + 1)
|
||||||
|
|
||||||
/* Absolute MAX/MIN */
|
/* Absolute MAX/MIN */
|
||||||
#define POS_KERN_COD_MIN (POS_KERN_COD_FILE_MIN
|
#define POS_AA_MIN (POS_AA_FILE_MIN
|
||||||
#define POS_KERN_COD_MAX (POS_KERN_COD_NET_MAX
|
#define POS_AA_MAX (POS_AA_NET_MAX
|
||||||
|
|
||||||
|
/* Invalid perm permission */
|
||||||
|
#define POS_AA_INVALID_POS 31
|
||||||
|
|
||||||
/* Modeled after MAY_READ, MAY_WRITE, MAY_EXEC def'ns */
|
/* Modeled after MAY_READ, MAY_WRITE, MAY_EXEC def'ns */
|
||||||
#define KERN_COD_MAY_EXEC (0x01 << POS_KERN_COD_MAY_EXEC)
|
#define AA_MAY_EXEC (0x01 << POS_AA_MAY_EXEC)
|
||||||
#define KERN_COD_MAY_WRITE (0x01 << POS_KERN_COD_MAY_WRITE)
|
#define AA_MAY_WRITE (0x01 << POS_AA_MAY_WRITE)
|
||||||
#define KERN_COD_MAY_READ (0x01 << POS_KERN_COD_MAY_READ)
|
#define AA_MAY_READ (0x01 << POS_AA_MAY_READ)
|
||||||
#define KERN_COD_MAY_LINK (0x01 << POS_KERN_COD_MAY_LINK)
|
#define AA_MAY_LINK (0x01 << POS_AA_MAY_LINK)
|
||||||
#define KERN_COD_EXEC_INHERIT (0x01 << POS_KERN_COD_EXEC_INHERIT)
|
#define AA_EXEC_INHERIT (0x01 << POS_AA_EXEC_INHERIT)
|
||||||
#define KERN_COD_EXEC_UNCONSTRAINED (0x01 << POS_KERN_COD_EXEC_UNCONSTRAINED)
|
#define AA_EXEC_UNCONSTRAINED (0x01 << POS_AA_EXEC_UNCONSTRAINED)
|
||||||
#define KERN_COD_EXEC_PROFILE (0x01 << POS_KERN_COD_EXEC_PROFILE)
|
#define AA_EXEC_PROFILE (0x01 << POS_AA_EXEC_PROFILE)
|
||||||
#define KERN_COD_EXEC_MMAP (0x01 << POS_KERN_COD_EXEC_MMAP)
|
#define AA_EXEC_MMAP (0x01 << POS_AA_EXEC_MMAP)
|
||||||
#define KERN_COD_EXEC_UNSAFE (0x01 << POS_KERN_COD_EXEC_UNSAFE)
|
#define AA_EXEC_UNSAFE (0x01 << POS_AA_EXEC_UNSAFE)
|
||||||
#define KERN_EXEC_MODIFIERS(X) (X & (KERN_COD_EXEC_INHERIT | \
|
#define AA_EXEC_MODIFIERS (AA_EXEC_INHERIT | \
|
||||||
KERN_COD_EXEC_UNCONSTRAINED | \
|
AA_EXEC_UNCONSTRAINED | \
|
||||||
KERN_COD_EXEC_PROFILE))
|
AA_EXEC_PROFILE)
|
||||||
|
#define KERN_EXEC_MODIFIERS(X) (X & AA_EXEC_MODIFIERS)
|
||||||
|
|
||||||
/* Network subdomain extensions. */
|
/* Network subdomain extensions. */
|
||||||
#define KERN_COD_TCP_CONNECT (0x01 << POS_KERN_COD_TCP_CONNECT)
|
#define AA_TCP_CONNECT (0x01 << POS_AA_TCP_CONNECT)
|
||||||
#define KERN_COD_TCP_ACCEPT (0x01 << POS_KERN_COD_TCP_ACCEPT)
|
#define AA_TCP_ACCEPT (0x01 << POS_AA_TCP_ACCEPT)
|
||||||
#define KERN_COD_TCP_CONNECTED (0x01 << POS_KERN_COD_TCP_CONNECTED)
|
#define AA_TCP_CONNECTED (0x01 << POS_AA_TCP_CONNECTED)
|
||||||
#define KERN_COD_TCP_ACCEPTED (0x01 << POS_KERN_COD_TCP_ACCEPTED)
|
#define AA_TCP_ACCEPTED (0x01 << POS_AA_TCP_ACCEPTED)
|
||||||
#define KERN_COD_UDP_SEND (0x01 << POS_KERN_COD_UDP_SEND)
|
#define AA_UDP_SEND (0x01 << POS_AA_UDP_SEND)
|
||||||
#define KERN_COD_UDP_RECEIVE (0x01 << POS_KERN_COD_UDP_RECEIVE)
|
#define AA_UDP_RECEIVE (0x01 << POS_AA_UDP_RECEIVE)
|
||||||
|
|
||||||
#define KERN_COD_LOGTCP_SEND (0x01 << POS_KERN_COD_LOGTCP_SEND)
|
#define AA_LOGTCP_SEND (0x01 << POS_AA_LOGTCP_SEND)
|
||||||
#define KERN_COD_LOGTCP_RECEIVE (0x01 << POS_KERN_COD_LOGTCP_RECEIVE)
|
#define AA_LOGTCP_RECEIVE (0x01 << POS_AA_LOGTCP_RECEIVE)
|
||||||
|
#define AA_INVALID_PERM (0x01 << POS_AA_INVALID_POS)
|
||||||
|
|
||||||
#define KERN_COD_HAT_SIZE 975 /* Maximum size of a subdomain
|
#define AA_HAT_SIZE 975 /* Maximum size of a subdomain
|
||||||
* ident (hat) */
|
* ident (hat) */
|
||||||
|
|
||||||
enum pattern_t {
|
enum pattern_t {
|
||||||
@@ -88,14 +94,21 @@ enum pattern_t {
|
|||||||
ePatternInvalid,
|
ePatternInvalid,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HAS_MAY_READ(mode) ((mode) & KERN_COD_MAY_READ)
|
#define HAS_MAY_READ(mode) ((mode) & AA_MAY_READ)
|
||||||
#define HAS_MAY_WRITE(mode) ((mode) & KERN_COD_MAY_WRITE)
|
#define HAS_MAY_WRITE(mode) ((mode) & AA_MAY_WRITE)
|
||||||
#define HAS_MAY_LINK(mode) ((mode) & KERN_COD_MAY_LINK)
|
#define HAS_MAY_LINK(mode) ((mode) & AA_MAY_LINK)
|
||||||
#define HAS_MAY_EXEC(mode) ((mode) & KERN_COD_MAY_EXEC)
|
#define HAS_MAY_EXEC(mode) ((mode) & AA_MAY_EXEC)
|
||||||
#define HAS_EXEC_INHERIT(mode) ((mode) & KERN_COD_EXEC_INHERIT)
|
#define HAS_EXEC_INHERIT(mode) ((mode) & AA_EXEC_INHERIT)
|
||||||
#define HAS_EXEC_PROFILE(mode) ((mode) & KERN_COD_EXEC_PROFILE)
|
#define HAS_EXEC_PROFILE(mode) ((mode) & AA_EXEC_PROFILE)
|
||||||
#define HAS_EXEC_UNCONSTRAINED(mode) ((mode) & KERN_COD_EXEC_UNCONSTRAINED)
|
#define HAS_EXEC_UNCONSTRAINED(mode) ((mode) & AA_EXEC_UNCONSTRAINED)
|
||||||
#define HAS_EXEC_MMAP(mode) ((mode) & KERN_COD_EXEC_MMAP)
|
#define HAS_EXEC_MMAP(mode) ((mode) & AA_EXEC_MMAP)
|
||||||
#define HAS_EXEC_UNSAFE(mode) ((mode) & KERN_COD_EXEC_UNSAFE)
|
#define HAS_EXEC_UNSAFE(mode) ((mode) & AA_EXEC_UNSAFE)
|
||||||
|
|
||||||
|
#define AA_NOXMODS_PERM_MASK (AA_MAY_EXEC | AA_MAY_WRITE | \
|
||||||
|
AA_MAY_READ | AA_MAY_LINK | \
|
||||||
|
AA_EXEC_MMAP)
|
||||||
|
#define AA_VALID_PERM_MASK ((1 << (POS_AA_MAX + 1)) - 1)
|
||||||
|
|
||||||
|
#define SINGLE_BIT_SET(X) (!((X) & ((X) - 1)))
|
||||||
|
#define AA_EXEC_SINGLE_MODIFIER_SET(X) SINGLE_BIT_SET(((X) & AA_EXEC_MODIFIERS))
|
||||||
#endif /* ! _IMMUNIX_H */
|
#endif /* ! _IMMUNIX_H */
|
||||||
|
25
parser/libapparmor_re/Makefile
Normal file
25
parser/libapparmor_re/Makefile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Profiling:
|
||||||
|
#EXTRA_CFLAGS = -pg
|
||||||
|
|
||||||
|
TARGET=libapparmor_re.a
|
||||||
|
|
||||||
|
CFLAGS = -c -g -Wall -O2 ${EXTRA_CFLAGS}
|
||||||
|
CXXFLAGS := ${CFLAGS}
|
||||||
|
|
||||||
|
ARFLAGS=-rcs
|
||||||
|
|
||||||
|
BISON := bison
|
||||||
|
|
||||||
|
all : ${TARGET}
|
||||||
|
|
||||||
|
libapparmor_re.a: regexp.o
|
||||||
|
ar ${ARFLAGS} $@ $^
|
||||||
|
|
||||||
|
regexp.o : regexp.cc
|
||||||
|
$(LINK.cc) $^ -o $@
|
||||||
|
|
||||||
|
regexp.cc : regexp.y flex-tables.h
|
||||||
|
${BISON} -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f regexp{,.o,.cc,.so,.a} ${TARGET}
|
30
parser/libapparmor_re/apparmor_re.h
Normal file
30
parser/libapparmor_re/apparmor_re.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/* $Id: apparmor.h 6203 2006-02-02 22:03:41Z steve $
|
||||||
|
|
||||||
|
Copyright (c) 2003, 2004, 2005, 2006 Novell, Inc. (All rights reserved)
|
||||||
|
|
||||||
|
The libapparmor library is licensed under the terms of the GNU
|
||||||
|
Lesser General Public License, version 2.1. Please see the file
|
||||||
|
COPYING.LGPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef APPARMOR_RE_H
|
||||||
|
#define APPARMOR_RE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct aare_ruleset;
|
||||||
|
|
||||||
|
typedef struct aare_ruleset aare_ruleset_t;
|
||||||
|
|
||||||
|
aare_ruleset_t *aare_new_ruleset(int reverse);
|
||||||
|
void aare_delete_ruleset(aare_ruleset_t *rules);
|
||||||
|
int aare_add_rule(aare_ruleset_t *rules, char *rule, uint32_t perms);
|
||||||
|
void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes, size_t *size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* APPARMOR_RE_H */
|
40
parser/libapparmor_re/flex-tables.h
Normal file
40
parser/libapparmor_re/flex-tables.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __FLEX_TABLES_H
|
||||||
|
#define __FLEX_TABLES_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define YYTH_MAGIC 0xF13C57B1
|
||||||
|
|
||||||
|
struct table_set_header {
|
||||||
|
uint32_t th_magic; /* TH_MAGIC */
|
||||||
|
uint32_t th_hsize;
|
||||||
|
uint32_t th_ssize;
|
||||||
|
uint16_t th_flags;
|
||||||
|
char th_version[];
|
||||||
|
/* char th_name[];
|
||||||
|
char th_pad64[];*/
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define YYTD_ID_ACCEPT 1 /* 1 */
|
||||||
|
#define YYTD_ID_BASE 2 /* 2 */
|
||||||
|
#define YYTD_ID_CHK 3 /* 3 */
|
||||||
|
#define YYTD_ID_DEF 4 /* 4 */
|
||||||
|
#define YYTD_ID_EC 5 /* 5 */
|
||||||
|
#define YYTD_ID_NXT 6 /* 8 */
|
||||||
|
#define YYTD_ID_META 7 /* 6 */
|
||||||
|
|
||||||
|
#define YYTD_DATA8 1
|
||||||
|
#define YYTD_DATA16 2
|
||||||
|
#define YYTD_DATA32 4
|
||||||
|
|
||||||
|
struct table_header {
|
||||||
|
uint16_t td_id;
|
||||||
|
uint16_t td_flags;
|
||||||
|
uint32_t td_hilen;
|
||||||
|
uint32_t td_lolen;
|
||||||
|
char td_data[];
|
||||||
|
/* char td_pad64[];*/
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#endif
|
10
parser/libapparmor_re/regexp.h
Normal file
10
parser/libapparmor_re/regexp.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __REGEXP_H
|
||||||
|
#define __REGEXP_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flex file format, but without state compression and with negative
|
||||||
|
* match results in the YYTD_ID_DEF table instead.
|
||||||
|
*/
|
||||||
|
#define YYTH_REGEXP_MAGIC 0x1B5E783D
|
||||||
|
|
||||||
|
#endif /* __REGEXP_H */
|
1641
parser/libapparmor_re/regexp.y
Normal file
1641
parser/libapparmor_re/regexp.y
Normal file
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include "pcre/internal.h"
|
#include "pcre/internal.h"
|
||||||
#include "immunix.h"
|
#include "immunix.h"
|
||||||
|
#include "libapparmor_re/apparmor_re.h"
|
||||||
|
|
||||||
typedef enum pattern_t pattern_t;
|
typedef enum pattern_t pattern_t;
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ struct cod_entry {
|
|||||||
char * name ;
|
char * name ;
|
||||||
struct codomain *codomain ; /* Special codomain defined
|
struct codomain *codomain ; /* Special codomain defined
|
||||||
* just for this executable */
|
* just for this executable */
|
||||||
int mode ; /* mode is 'or' of KERN_COD_* bits */
|
int mode ; /* mode is 'or' of AA_* bits */
|
||||||
int deny ; /* TRUE or FALSE */
|
int deny ; /* TRUE or FALSE */
|
||||||
|
|
||||||
pattern_t pattern_type;
|
pattern_t pattern_type;
|
||||||
@@ -68,6 +69,11 @@ struct codomain {
|
|||||||
struct cod_net_entry * net_entries;
|
struct cod_net_entry * net_entries;
|
||||||
void *hat_table;
|
void *hat_table;
|
||||||
//struct codomain *next;
|
//struct codomain *next;
|
||||||
|
|
||||||
|
aare_ruleset_t *dfarules;
|
||||||
|
int dfarule_count;
|
||||||
|
void *dfa;
|
||||||
|
size_t dfa_size;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
struct cod_global_entry {
|
struct cod_global_entry {
|
||||||
@@ -116,6 +122,10 @@ struct var_string {
|
|||||||
#define OPTION_REPLACE 3
|
#define OPTION_REPLACE 3
|
||||||
#define OPTION_STDOUT 4
|
#define OPTION_STDOUT 4
|
||||||
|
|
||||||
|
#define AARE_NONE 0
|
||||||
|
#define AARE_PCRE 1
|
||||||
|
#define AARE_DFA 2
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define PDEBUG(fmt, args...) printf("parser: " fmt, ## args)
|
#define PDEBUG(fmt, args...) printf("parser: " fmt, ## args)
|
||||||
#else
|
#else
|
||||||
@@ -139,6 +149,11 @@ struct var_string {
|
|||||||
#define __unused __attribute__ ((unused))
|
#define __unused __attribute__ ((unused))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define list_for_each(LIST, ENTRY) \
|
||||||
|
for ((ENTRY) = (LIST); (ENTRY); (ENTRY) = (ENTRY)->next)
|
||||||
|
#define list_last_entry(LIST, ENTRY) \
|
||||||
|
for ((ENTRY) = (LIST); (ENTRY) && (ENTRY)->next; (ENTRY) = (ENTRY)->next)
|
||||||
|
|
||||||
/* Some external definitions to make b0rken programs happy */
|
/* Some external definitions to make b0rken programs happy */
|
||||||
extern char *progname;
|
extern char *progname;
|
||||||
extern char *subdomainbase;
|
extern char *subdomainbase;
|
||||||
@@ -146,6 +161,7 @@ extern char *profilename;
|
|||||||
|
|
||||||
/* from parser_main */
|
/* from parser_main */
|
||||||
extern int force_complain;
|
extern int force_complain;
|
||||||
|
extern int regex_type;
|
||||||
extern void pwarn(char *fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
|
extern void pwarn(char *fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
|
||||||
|
|
||||||
extern int yyparse(void);
|
extern int yyparse(void);
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#define _(s) gettext(s)
|
#define _(s) gettext(s)
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "libapparmor_re/apparmor_re.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
@@ -55,6 +56,7 @@
|
|||||||
#define SD_STR_LEN (sizeof(u16))
|
#define SD_STR_LEN (sizeof(u16))
|
||||||
|
|
||||||
#define SUBDOMAIN_INTERFACE_VERSION 2
|
#define SUBDOMAIN_INTERFACE_VERSION 2
|
||||||
|
#define SUBDOMAIN_INTERFACE_DFA_VERSION 3
|
||||||
|
|
||||||
int sd_serialize_codomain(int option, struct codomain *cod);
|
int sd_serialize_codomain(int option, struct codomain *cod);
|
||||||
|
|
||||||
@@ -334,6 +336,27 @@ inline int sd_write_blob(sd_serialize *p, void *b, int buf_size, char *name)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define align64(X) (((size_t) (X) + (size_t) 7) & ~((size_t) 7))
|
||||||
|
inline int sd_write_aligned_blob(sd_serialize *p, void *b, int buf_size,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
size_t pad;
|
||||||
|
u32 tmp;
|
||||||
|
if (!sd_write_name(p, name))
|
||||||
|
return 0;
|
||||||
|
pad = align64((p->pos + 5) - p->buffer) - ((p->pos + 5) - p->buffer);
|
||||||
|
if (!sd_prepare_write(p, SD_BLOB, 4 + buf_size + pad))
|
||||||
|
return 0;
|
||||||
|
tmp = cpu_to_le32(buf_size + pad);
|
||||||
|
memcpy(p->pos, &tmp, sizeof(tmp));
|
||||||
|
sd_inc(p, sizeof(tmp));
|
||||||
|
memset(p->pos, 0, pad);
|
||||||
|
sd_inc(p, pad);
|
||||||
|
memcpy(p->pos, b, buf_size);
|
||||||
|
sd_inc(p, buf_size);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
inline int sd_write_string(sd_serialize *p, char *b, char *name)
|
inline int sd_write_string(sd_serialize *p, char *b, char *name)
|
||||||
{
|
{
|
||||||
u16 tmp;
|
u16 tmp;
|
||||||
@@ -470,12 +493,20 @@ int sd_serialize_file_entry(sd_serialize *p, struct cod_entry *file_entry)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sd_serialize_dfa(sd_serialize *p, void *dfa, size_t size)
|
||||||
|
{
|
||||||
|
if (dfa && !sd_write_aligned_blob(p, dfa, size, "aadfa"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int count_file_ents(struct cod_entry *list)
|
int count_file_ents(struct cod_entry *list)
|
||||||
{
|
{
|
||||||
struct cod_entry *file_entry;
|
struct cod_entry *entry;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (file_entry = list; file_entry; file_entry = file_entry->next) {
|
list_for_each(list, entry) {
|
||||||
if (file_entry->pattern_type == ePatternBasic) {
|
if (entry->pattern_type == ePatternBasic) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -484,10 +515,10 @@ int count_file_ents(struct cod_entry *list)
|
|||||||
|
|
||||||
int count_tailglob_ents(struct cod_entry *list)
|
int count_tailglob_ents(struct cod_entry *list)
|
||||||
{
|
{
|
||||||
struct cod_entry *file_entry;
|
struct cod_entry *entry;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (file_entry = list; file_entry; file_entry = file_entry->next) {
|
list_for_each(list, entry) {
|
||||||
if (file_entry->pattern_type == ePatternTailGlob) {
|
if (entry->pattern_type == ePatternTailGlob) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -496,10 +527,10 @@ int count_tailglob_ents(struct cod_entry *list)
|
|||||||
|
|
||||||
int count_pcre_ents(struct cod_entry *list)
|
int count_pcre_ents(struct cod_entry *list)
|
||||||
{
|
{
|
||||||
struct cod_entry *file_entry;
|
struct cod_entry *entry;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (file_entry = list; file_entry; file_entry = file_entry->next) {
|
list_for_each(list, entry) {
|
||||||
if (file_entry->pattern_type == ePatternRegex) {
|
if (entry->pattern_type == ePatternRegex) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,7 +539,7 @@ int count_pcre_ents(struct cod_entry *list)
|
|||||||
|
|
||||||
int sd_serialize_profile(sd_serialize *p, struct codomain *profile)
|
int sd_serialize_profile(sd_serialize *p, struct codomain *profile)
|
||||||
{
|
{
|
||||||
struct cod_entry *file_entry;
|
struct cod_entry *entry;
|
||||||
struct cod_net_entry *net_entry;
|
struct cod_net_entry *net_entry;
|
||||||
|
|
||||||
if (!sd_write_struct(p, "profile"))
|
if (!sd_write_struct(p, "profile"))
|
||||||
@@ -529,14 +560,18 @@ int sd_serialize_profile(sd_serialize *p, struct codomain *profile)
|
|||||||
if (!sd_write32(p, profile->capabilities))
|
if (!sd_write32(p, profile->capabilities))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* either have a single dfa or lists of different entry types */
|
||||||
|
if (regex_type == AARE_DFA) {
|
||||||
|
if (!sd_serialize_dfa(p, profile->dfa, profile->dfa_size))
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
/* pcre globbing entries */
|
/* pcre globbing entries */
|
||||||
if (count_pcre_ents(profile->entries)) {
|
if (count_pcre_ents(profile->entries)) {
|
||||||
if (!sd_write_list(p, "pgent"))
|
if (!sd_write_list(p, "pgent"))
|
||||||
return 0;
|
return 0;
|
||||||
for (file_entry = profile->entries; file_entry;
|
list_for_each(profile->entries, entry) {
|
||||||
file_entry = file_entry->next) {
|
if (entry->pattern_type == ePatternRegex) {
|
||||||
if (file_entry->pattern_type == ePatternRegex) {
|
if (!sd_serialize_file_entry(p, entry))
|
||||||
if (!sd_serialize_file_entry(p, file_entry))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -548,10 +583,9 @@ int sd_serialize_profile(sd_serialize *p, struct codomain *profile)
|
|||||||
if (count_tailglob_ents(profile->entries)) {
|
if (count_tailglob_ents(profile->entries)) {
|
||||||
if (!sd_write_list(p, "sgent"))
|
if (!sd_write_list(p, "sgent"))
|
||||||
return 0;
|
return 0;
|
||||||
for (file_entry = profile->entries; file_entry;
|
list_for_each(profile->entries, entry) {
|
||||||
file_entry = file_entry->next) {
|
if (entry->pattern_type == ePatternTailGlob) {
|
||||||
if (file_entry->pattern_type == ePatternTailGlob) {
|
if (!sd_serialize_file_entry(p, entry))
|
||||||
if (!sd_serialize_file_entry(p, file_entry))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -563,21 +597,21 @@ int sd_serialize_profile(sd_serialize *p, struct codomain *profile)
|
|||||||
if (count_file_ents(profile->entries)) {
|
if (count_file_ents(profile->entries)) {
|
||||||
if (!sd_write_list(p, "fent"))
|
if (!sd_write_list(p, "fent"))
|
||||||
return 0;
|
return 0;
|
||||||
for (file_entry = profile->entries; file_entry;
|
list_for_each(profile->entries, entry) {
|
||||||
file_entry = file_entry->next) {
|
if (entry->pattern_type == ePatternBasic) {
|
||||||
if (file_entry->pattern_type == ePatternBasic) {
|
if (!sd_serialize_file_entry(p, entry))
|
||||||
if (!sd_serialize_file_entry(p, file_entry))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!sd_write_listend(p))
|
if (!sd_write_listend(p))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (profile->net_entries) {
|
if (profile->net_entries && (regex_type != AARE_DFA)) {
|
||||||
if (!sd_write_list(p, "net"))
|
if (!sd_write_list(p, "net"))
|
||||||
return 0;
|
return 0;
|
||||||
for (net_entry = profile->net_entries; net_entry; net_entry = net_entry->next) {
|
list_for_each(profile->net_entries, net_entry) {
|
||||||
if (!sd_serialize_net_entry(p, net_entry))
|
if (!sd_serialize_net_entry(p, net_entry))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -603,9 +637,18 @@ int sd_serialize_profile(sd_serialize *p, struct codomain *profile)
|
|||||||
|
|
||||||
int sd_serialize_top_profile(sd_serialize *p, struct codomain *profile)
|
int sd_serialize_top_profile(sd_serialize *p, struct codomain *profile)
|
||||||
{
|
{
|
||||||
|
int version;
|
||||||
|
|
||||||
|
if (regex_type == AARE_DFA)
|
||||||
|
version = SUBDOMAIN_INTERFACE_DFA_VERSION;
|
||||||
|
else
|
||||||
|
version = SUBDOMAIN_INTERFACE_VERSION;
|
||||||
|
|
||||||
|
|
||||||
if (!sd_write_name(p, "version"))
|
if (!sd_write_name(p, "version"))
|
||||||
return 0;
|
return 0;
|
||||||
if (!sd_write32(p, SUBDOMAIN_INTERFACE_VERSION))
|
|
||||||
|
if (!sd_write32(p, version))
|
||||||
return 0;
|
return 0;
|
||||||
return sd_serialize_profile(p, profile);
|
return sd_serialize_profile(p, profile);
|
||||||
}
|
}
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
#define MATCH_STRING "/sys/kernel/security/" MODULE_NAME "/matching"
|
#define MATCH_STRING "/sys/kernel/security/" MODULE_NAME "/matching"
|
||||||
#define MOUNTED_FS "/proc/mounts"
|
#define MOUNTED_FS "/proc/mounts"
|
||||||
#define PCRE "pattern=pcre"
|
#define PCRE "pattern=pcre"
|
||||||
|
#define AADFA "pattern=aadfa"
|
||||||
|
|
||||||
#define UNPRIVILEGED_OPS (debug || preprocess_only || option == OPTION_STDOUT || names_only || \
|
#define UNPRIVILEGED_OPS (debug || preprocess_only || option == OPTION_STDOUT || names_only || \
|
||||||
dump_vars || dump_expanded_vars)
|
dump_vars || dump_expanded_vars)
|
||||||
@@ -65,6 +66,8 @@ int conf_quiet = 0;
|
|||||||
char *subdomainbase = NULL;
|
char *subdomainbase = NULL;
|
||||||
char *profilename;
|
char *profilename;
|
||||||
char *match_string = NULL;
|
char *match_string = NULL;
|
||||||
|
int regex_type = AARE_NONE;
|
||||||
|
|
||||||
extern int current_lineno;
|
extern int current_lineno;
|
||||||
|
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
@@ -264,20 +267,12 @@ static inline char *try_subdomainfs_mountpoint(const char *mntpnt,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void find_subdomainfs_mountpoint(void)
|
int find_subdomainfs_mountpoint(void)
|
||||||
{
|
{
|
||||||
FILE *mntfile;
|
FILE *mntfile;
|
||||||
struct mntent *mntpt;
|
struct mntent *mntpt;
|
||||||
|
|
||||||
if (!(mntfile = setmntent(MOUNTED_FS, "r"))) {
|
if ((mntfile = setmntent(MOUNTED_FS, "r"))) {
|
||||||
/* Ugh, what's the right default if you can't open /proc/mounts? */
|
|
||||||
PERROR(_("Warning: unable to open %s, attempting to use %s\n"
|
|
||||||
"as the subdomainfs location. Use --subdomainfs to override.\n"),
|
|
||||||
MOUNTED_FS, DEFAULT_APPARMORFS);
|
|
||||||
subdomainbase = DEFAULT_APPARMORFS;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((mntpt = getmntent(mntfile))) {
|
while ((mntpt = getmntent(mntfile))) {
|
||||||
char *proposed = NULL;
|
char *proposed = NULL;
|
||||||
if (strcmp(mntpt->mnt_type, "securityfs") == 0) {
|
if (strcmp(mntpt->mnt_type, "securityfs") == 0) {
|
||||||
@@ -300,62 +295,23 @@ void find_subdomainfs_mountpoint(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
endmntent(mntfile);
|
||||||
|
}
|
||||||
|
|
||||||
if (!subdomainbase) {
|
if (!subdomainbase) {
|
||||||
PERROR(_("Warning: unable to find a suitable fs in %s, is it mounted?\n"
|
struct stat buf;
|
||||||
"Attempting to use %s as the subdomainfs location.\n"
|
if (stat(DEFAULT_APPARMORFS, &buf) == -1) {
|
||||||
"Use --subdomainfs to override.\n"),
|
PERROR(_("Warning: unable to find a suitable fs in %s, is it "
|
||||||
MOUNTED_FS, DEFAULT_APPARMORFS);
|
"mounted?\nUse --subdomainfs to override.\n"),
|
||||||
|
MOUNTED_FS);
|
||||||
|
} else {
|
||||||
subdomainbase = DEFAULT_APPARMORFS;
|
subdomainbase = DEFAULT_APPARMORFS;
|
||||||
}
|
}
|
||||||
endmntent(mntfile);
|
}
|
||||||
|
|
||||||
|
return (subdomainbase == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_module_loaded(void)
|
|
||||||
{
|
|
||||||
char *query_failed = NULL;
|
|
||||||
int module_loaded = 0;
|
|
||||||
int mlen = strlen(MODULE_NAME);
|
|
||||||
int oldmlen = strlen(OLD_MODULE_NAME);
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
fp = fopen(PROC_MODULES, "r");
|
|
||||||
if (fp) {
|
|
||||||
while (!feof(fp)) {
|
|
||||||
const int buflen = 256;
|
|
||||||
char buf[buflen];
|
|
||||||
|
|
||||||
if (fgets(buf, buflen, fp)) {
|
|
||||||
buf[buflen - 1] = 0;
|
|
||||||
|
|
||||||
if (strncmp(buf, MODULE_NAME, mlen) == 0 &&
|
|
||||||
buf[mlen] == ' ') {
|
|
||||||
module_loaded = 1;
|
|
||||||
}
|
|
||||||
if (strncmp(buf, OLD_MODULE_NAME, oldmlen) == 0 &&
|
|
||||||
buf[oldmlen] == ' ') {
|
|
||||||
module_loaded = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void)fclose(fp);
|
|
||||||
} else {
|
|
||||||
query_failed = "unable to open " PROC_MODULES;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query_failed) {
|
|
||||||
PERROR(_("%s: Unable to query modules - '%s'\n"
|
|
||||||
"Either modules are disabled or your kernel is"
|
|
||||||
" too old.\n"), progname, query_failed);
|
|
||||||
return 1;
|
|
||||||
} else if (!module_loaded) {
|
|
||||||
PERROR(_("%s: Unable to find " MODULE_NAME "!\n"
|
|
||||||
"Ensure that it has been loaded.\n"), progname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int have_enough_privilege(void)
|
int have_enough_privilege(void)
|
||||||
{
|
{
|
||||||
@@ -387,7 +343,7 @@ static void get_match_string(void) {
|
|||||||
|
|
||||||
/* has process_args() already assigned a match string? */
|
/* has process_args() already assigned a match string? */
|
||||||
if (match_string)
|
if (match_string)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
FILE *ms = fopen(MATCH_STRING, "r");
|
FILE *ms = fopen(MATCH_STRING, "r");
|
||||||
if (!ms)
|
if (!ms)
|
||||||
@@ -404,22 +360,28 @@ static void get_match_string(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (match_string) {
|
||||||
|
if (strstr(match_string, PCRE))
|
||||||
|
regex_type = AARE_PCRE;
|
||||||
|
|
||||||
|
if (strstr(match_string, AADFA))
|
||||||
|
regex_type = AARE_DFA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ms)
|
||||||
fclose(ms);
|
fclose(ms);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return 1 --> PCRE should work fine
|
/* return 1 --> PCRE should work fine
|
||||||
return 0 --> no PCRE support */
|
return 0 --> no PCRE support */
|
||||||
static int pcre_support(void) {
|
static int regex_support(void) {
|
||||||
|
|
||||||
get_match_string();
|
|
||||||
|
|
||||||
/* no match string, predates (or postdates?) the split matching
|
/* no match string, predates (or postdates?) the split matching
|
||||||
module design */
|
module design */
|
||||||
if (!match_string)
|
if (!match_string)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (strstr(match_string, PCRE))
|
if (regex_type != AARE_NONE)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -437,6 +399,9 @@ int process_profile(int option, char *profilename)
|
|||||||
if (retval != 0)
|
if (retval != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/* Get the match string to determine type of regex support needed */
|
||||||
|
get_match_string();
|
||||||
|
|
||||||
retval = post_process_policy();
|
retval = post_process_policy();
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
PERROR(_("%s: Errors found in file. Aborting.\n"), progname);
|
PERROR(_("%s: Errors found in file. Aborting.\n"), progname);
|
||||||
@@ -467,10 +432,7 @@ int process_profile(int option, char *profilename)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subdomainbase && !preprocess_only && !(option == OPTION_STDOUT))
|
if (!regex_support()) {
|
||||||
find_subdomainfs_mountpoint();
|
|
||||||
|
|
||||||
if (!pcre_support()) {
|
|
||||||
die_if_any_regex();
|
die_if_any_regex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,8 +464,9 @@ int main(int argc, char *argv[])
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check to make sure modules are enabled */
|
/* Check to make sure there is an interface to load policy */
|
||||||
if (!(UNPRIVILEGED_OPS) && ((retval = is_module_loaded()))) {
|
if (!(UNPRIVILEGED_OPS) && (subdomainbase == NULL) &&
|
||||||
|
(retval = find_subdomainfs_mountpoint())) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -296,17 +296,17 @@ reeval:
|
|||||||
switch (this) {
|
switch (this) {
|
||||||
case COD_READ_CHAR:
|
case COD_READ_CHAR:
|
||||||
PDEBUG("Parsing mode: found READ\n");
|
PDEBUG("Parsing mode: found READ\n");
|
||||||
mode |= KERN_COD_MAY_READ;
|
mode |= AA_MAY_READ;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COD_WRITE_CHAR:
|
case COD_WRITE_CHAR:
|
||||||
PDEBUG("Parsing mode: found WRITE\n");
|
PDEBUG("Parsing mode: found WRITE\n");
|
||||||
mode |= KERN_COD_MAY_WRITE;
|
mode |= AA_MAY_WRITE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COD_LINK_CHAR:
|
case COD_LINK_CHAR:
|
||||||
PDEBUG("Parsing mode: found LINK\n");
|
PDEBUG("Parsing mode: found LINK\n");
|
||||||
mode |= KERN_COD_MAY_LINK;
|
mode |= AA_MAY_LINK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COD_INHERIT_CHAR:
|
case COD_INHERIT_CHAR:
|
||||||
@@ -319,13 +319,13 @@ reeval:
|
|||||||
if (next != tolower(next))
|
if (next != tolower(next))
|
||||||
warn_uppercase();
|
warn_uppercase();
|
||||||
mode |=
|
mode |=
|
||||||
(KERN_COD_EXEC_INHERIT | KERN_COD_MAY_EXEC);
|
(AA_EXEC_INHERIT | AA_MAY_EXEC);
|
||||||
p++; /* skip 'x' */
|
p++; /* skip 'x' */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COD_UNSAFE_UNCONSTRAINED_CHAR:
|
case COD_UNSAFE_UNCONSTRAINED_CHAR:
|
||||||
mode |= KERN_COD_EXEC_UNSAFE;
|
mode |= AA_EXEC_UNSAFE;
|
||||||
pwarn(_("Unconstrained exec qualifier (%c%c) allows some dangerous environment variables "
|
pwarn(_("Unconstrained exec qualifier (%c%c) allows some dangerous environment variables "
|
||||||
"to be passed to the unconfined process; 'man 5 apparmor.d' for details.\n"),
|
"to be passed to the unconfined process; 'man 5 apparmor.d' for details.\n"),
|
||||||
COD_UNSAFE_UNCONSTRAINED_CHAR, COD_EXEC_CHAR);
|
COD_UNSAFE_UNCONSTRAINED_CHAR, COD_EXEC_CHAR);
|
||||||
@@ -342,14 +342,14 @@ reeval:
|
|||||||
if (next != tolower(next))
|
if (next != tolower(next))
|
||||||
warn_uppercase();
|
warn_uppercase();
|
||||||
mode |=
|
mode |=
|
||||||
(KERN_COD_EXEC_UNCONSTRAINED |
|
(AA_EXEC_UNCONSTRAINED |
|
||||||
KERN_COD_MAY_EXEC);
|
AA_MAY_EXEC);
|
||||||
p++; /* skip 'x' */
|
p++; /* skip 'x' */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COD_UNSAFE_PROFILE_CHAR:
|
case COD_UNSAFE_PROFILE_CHAR:
|
||||||
mode |= KERN_COD_EXEC_UNSAFE;
|
mode |= AA_EXEC_UNSAFE;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case COD_PROFILE_CHAR:
|
case COD_PROFILE_CHAR:
|
||||||
PDEBUG("Parsing mode: found PROFILE\n");
|
PDEBUG("Parsing mode: found PROFILE\n");
|
||||||
@@ -363,14 +363,14 @@ reeval:
|
|||||||
if (next != tolower(next))
|
if (next != tolower(next))
|
||||||
warn_uppercase();
|
warn_uppercase();
|
||||||
mode |=
|
mode |=
|
||||||
(KERN_COD_EXEC_PROFILE | KERN_COD_MAY_EXEC);
|
(AA_EXEC_PROFILE | AA_MAY_EXEC);
|
||||||
p++; /* skip 'x' */
|
p++; /* skip 'x' */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COD_MMAP_CHAR:
|
case COD_MMAP_CHAR:
|
||||||
PDEBUG("Parsing mode: found MMAP\n");
|
PDEBUG("Parsing mode: found MMAP\n");
|
||||||
mode |= KERN_COD_EXEC_MMAP;
|
mode |= AA_EXEC_MMAP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COD_EXEC_CHAR:
|
case COD_EXEC_CHAR:
|
||||||
@@ -557,7 +557,7 @@ void debug_cod_entries(struct cod_entry *list)
|
|||||||
|
|
||||||
printf("--- Entries ---\n");
|
printf("--- Entries ---\n");
|
||||||
|
|
||||||
for (item = list; item; item = item->next) {
|
list_for_each(list, item) {
|
||||||
if (!item)
|
if (!item)
|
||||||
printf("Item is NULL!\n");
|
printf("Item is NULL!\n");
|
||||||
|
|
||||||
@@ -603,7 +603,7 @@ void debug_cod_net_entries(struct cod_net_entry *list)
|
|||||||
|
|
||||||
printf("--- NetwerkEntries --- \n");
|
printf("--- NetwerkEntries --- \n");
|
||||||
|
|
||||||
for (item = list; item; item = item->next) {
|
list_for_each(list, item) {
|
||||||
if (!item)
|
if (!item)
|
||||||
printf("Item is NULL");
|
printf("Item is NULL");
|
||||||
|
|
||||||
@@ -623,17 +623,17 @@ void debug_cod_net_entries(struct cod_net_entry *list)
|
|||||||
printf("Destination netmask: %lx\n", dmask);
|
printf("Destination netmask: %lx\n", dmask);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
printf("Mode:\t");
|
printf("Mode:\t");
|
||||||
if (item->mode & KERN_COD_TCP_ACCEPT)
|
if (item->mode & AA_TCP_ACCEPT)
|
||||||
printf("TA");
|
printf("TA");
|
||||||
if (item->mode & KERN_COD_TCP_CONNECT)
|
if (item->mode & AA_TCP_CONNECT)
|
||||||
printf("TC");
|
printf("TC");
|
||||||
if (item->mode & KERN_COD_TCP_ACCEPTED)
|
if (item->mode & AA_TCP_ACCEPTED)
|
||||||
printf("Ta");
|
printf("Ta");
|
||||||
if (item->mode & KERN_COD_TCP_CONNECTED)
|
if (item->mode & AA_TCP_CONNECTED)
|
||||||
printf("Tc");
|
printf("Tc");
|
||||||
if (item->mode & KERN_COD_UDP_SEND)
|
if (item->mode & AA_UDP_SEND)
|
||||||
printf("US");
|
printf("US");
|
||||||
if (item->mode & KERN_COD_UDP_RECEIVE)
|
if (item->mode & AA_UDP_RECEIVE)
|
||||||
printf("UR");
|
printf("UR");
|
||||||
if (item->iface != NULL)
|
if (item->iface != NULL)
|
||||||
printf("\nInterface: %s\n", item->iface);
|
printf("\nInterface: %s\n", item->iface);
|
||||||
|
@@ -159,7 +159,7 @@ static int any_regex_entries(struct cod_entry *entry_list)
|
|||||||
{
|
{
|
||||||
struct cod_entry *entry;
|
struct cod_entry *entry;
|
||||||
|
|
||||||
for (entry = entry_list; entry; entry = entry->next) {
|
list_for_each(entry_list, entry) {
|
||||||
if (entry->pattern_type == ePatternRegex)
|
if (entry->pattern_type == ePatternRegex)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -374,8 +374,7 @@ struct codomain *merge_policy(struct codomain *a, struct codomain *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (a->entries) {
|
if (a->entries) {
|
||||||
for (last = a->entries; last->next; last = last->next)
|
list_last_entry(a->entries, last);
|
||||||
/* do nothing */ ;
|
|
||||||
last->next = b->entries;
|
last->next = b->entries;
|
||||||
} else {
|
} else {
|
||||||
a->entries = b->entries;
|
a->entries = b->entries;
|
||||||
@@ -383,8 +382,7 @@ struct codomain *merge_policy(struct codomain *a, struct codomain *b)
|
|||||||
b->entries = NULL;
|
b->entries = NULL;
|
||||||
|
|
||||||
if (a->net_entries) {
|
if (a->net_entries) {
|
||||||
for (lastnet = a->net_entries; lastnet->next; lastnet = lastnet->next)
|
list_last_entry(a->net_entries, lastnet);
|
||||||
/* do nothing */ ;
|
|
||||||
lastnet->next = b->net_entries;
|
lastnet->next = b->net_entries;
|
||||||
} else {
|
} else {
|
||||||
a->net_entries = b->net_entries;
|
a->net_entries = b->net_entries;
|
||||||
@@ -451,5 +449,9 @@ void free_policy(struct codomain *cod)
|
|||||||
free_hat_table(cod->hat_table);
|
free_hat_table(cod->hat_table);
|
||||||
free_cod_entries(cod->entries);
|
free_cod_entries(cod->entries);
|
||||||
free_net_entries(cod->net_entries);
|
free_net_entries(cod->net_entries);
|
||||||
|
if (cod->dfarules)
|
||||||
|
aare_delete_ruleset(cod->dfarules);
|
||||||
|
if (cod->dfa)
|
||||||
|
free(cod->dfa);
|
||||||
free(cod);
|
free(cod);
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
/* #define DEBUG */
|
/* #define DEBUG */
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "libapparmor_re/apparmor_re.h"
|
||||||
|
|
||||||
enum error_type {
|
enum error_type {
|
||||||
e_no_error,
|
e_no_error,
|
||||||
@@ -113,10 +114,11 @@ static void filter_slashes(char *path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_regex_entry(struct cod_entry *entry)
|
static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
|
||||||
|
char *pcre, size_t pcre_size)
|
||||||
{
|
{
|
||||||
#define STORE(_src, _dest, _len) \
|
#define STORE(_src, _dest, _len) \
|
||||||
if ((const char*)_dest + _len > tbufend){ \
|
if ((const char*)_dest + _len > (pcre + pcre_size)){ \
|
||||||
error = e_buffer_overflow; \
|
error = e_buffer_overflow; \
|
||||||
} else { \
|
} else { \
|
||||||
memcpy(_dest, _src, _len); \
|
memcpy(_dest, _src, _len); \
|
||||||
@@ -128,9 +130,6 @@ static int process_regex_entry(struct cod_entry *entry)
|
|||||||
/* flag to indicate input error */
|
/* flag to indicate input error */
|
||||||
enum error_type error;
|
enum error_type error;
|
||||||
|
|
||||||
char tbuf[PATH_MAX + 3]; /* +3 for ^, $ and \0 */
|
|
||||||
const char *tbufend = &tbuf[PATH_MAX];
|
|
||||||
|
|
||||||
const char *sptr;
|
const char *sptr;
|
||||||
char *dptr;
|
char *dptr;
|
||||||
pattern_t ptype;
|
pattern_t ptype;
|
||||||
@@ -142,12 +141,10 @@ static int process_regex_entry(struct cod_entry *entry)
|
|||||||
error = e_no_error;
|
error = e_no_error;
|
||||||
ptype = ePatternBasic; /* assume no regex */
|
ptype = ePatternBasic; /* assume no regex */
|
||||||
|
|
||||||
if (!entry) /* shouldn't happen */
|
sptr = aare;
|
||||||
return TRUE;
|
dptr = pcre;
|
||||||
|
|
||||||
sptr = entry->name;
|
|
||||||
dptr = tbuf;
|
|
||||||
|
|
||||||
|
if (anchor)
|
||||||
/* anchor beginning of regular expression */
|
/* anchor beginning of regular expression */
|
||||||
*dptr++ = '^';
|
*dptr++ = '^';
|
||||||
|
|
||||||
@@ -342,12 +339,12 @@ static int process_regex_entry(struct cod_entry *entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* anchor end and terminate pattern string */
|
/* anchor end and terminate pattern string */
|
||||||
if (error == e_no_error) {
|
if ((error == e_no_error) && anchor) {
|
||||||
char buf[2] = { '$', 0 };
|
STORE("$" , dptr, 1);
|
||||||
|
}
|
||||||
STORE(buf, dptr, 2);
|
if (error == e_no_error) {
|
||||||
|
STORE("", dptr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check error again, as above STORE may have set it */
|
/* check error again, as above STORE may have set it */
|
||||||
if (error != e_no_error) {
|
if (error != e_no_error) {
|
||||||
if (error == e_buffer_overflow) {
|
if (error == e_buffer_overflow) {
|
||||||
@@ -356,12 +353,31 @@ static int process_regex_entry(struct cod_entry *entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PERROR(_("%s: Unable to parse input line '%s'\n"),
|
PERROR(_("%s: Unable to parse input line '%s'\n"),
|
||||||
progname, entry->name);
|
progname, aare);
|
||||||
|
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (ret == FALSE)
|
||||||
|
ptype = ePatternInvalid;
|
||||||
|
return ptype;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_pcre_entry(struct cod_entry *entry)
|
||||||
|
{
|
||||||
|
char tbuf[PATH_MAX + 3]; /* +3 for ^, $ and \0 */
|
||||||
|
int ret = TRUE;
|
||||||
|
pattern_t ptype;
|
||||||
|
|
||||||
|
if (!entry) /* shouldn't happen */
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
ptype = convert_aaregex_to_pcre(entry->name, 1, tbuf, PATH_MAX + 3);
|
||||||
|
if (ptype == ePatternInvalid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
entry->pattern_type = ptype;
|
entry->pattern_type = ptype;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -422,33 +438,83 @@ static int process_regex_entry(struct cod_entry *entry)
|
|||||||
filter_escapes(entry->name);
|
filter_escapes(entry->name);
|
||||||
} /* ptype == ePatternRegex */
|
} /* ptype == ePatternRegex */
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int post_process_entries(struct cod_entry *entry_list)
|
static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry)
|
||||||
|
{
|
||||||
|
char tbuf[PATH_MAX + 3]; /* +3 for ^, $ and \0 */
|
||||||
|
int ret = TRUE;
|
||||||
|
pattern_t ptype;
|
||||||
|
|
||||||
|
if (!entry) /* shouldn't happen */
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
ptype = convert_aaregex_to_pcre(entry->name, 0, tbuf, PATH_MAX + 3);
|
||||||
|
if (ptype == ePatternInvalid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
entry->pattern_type = ptype;
|
||||||
|
|
||||||
|
/* ix implies m but the apparmor module does not add m bit to
|
||||||
|
* dfa states like it does for pcre
|
||||||
|
*/
|
||||||
|
if (entry->mode & AA_EXEC_INHERIT)
|
||||||
|
entry->mode |= AA_EXEC_MMAP;
|
||||||
|
if (!aare_add_rule(dfarules, tbuf, entry->mode))
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int post_process_entries(struct codomain *cod)
|
||||||
{
|
{
|
||||||
int ret = TRUE, rc;
|
int ret = TRUE, rc;
|
||||||
struct cod_entry *entry;
|
struct cod_entry *entry;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
for (entry = entry_list; entry; entry = entry->next) {
|
list_for_each(cod->entries, entry) {
|
||||||
filter_slashes(entry->name);
|
filter_slashes(entry->name);
|
||||||
rc = process_regex_entry(entry);
|
if (regex_type == AARE_DFA)
|
||||||
|
rc = process_dfa_entry(cod->dfarules, entry);
|
||||||
|
else
|
||||||
|
rc = process_pcre_entry(entry);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cod->dfarule_count = count;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_regex(struct codomain *cod)
|
int process_regex(struct codomain *cod)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = -1;
|
||||||
|
|
||||||
if (!post_process_entries(cod->entries)) {
|
if (regex_type == AARE_DFA) {
|
||||||
error = -1;
|
cod->dfarules = aare_new_ruleset(0);
|
||||||
|
if (!cod->dfarules)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (!post_process_entries(cod))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (regex_type == AARE_DFA && cod->dfarule_count > 0) {
|
||||||
|
cod->dfa = aare_create_dfa(cod->dfarules, 0, &cod->dfa_size);
|
||||||
|
if (!cod->dfa)
|
||||||
|
goto out;
|
||||||
|
/*
|
||||||
|
if (cod->dfa_size == 0) {
|
||||||
|
PERROR(_("profile %s: has merged rules (%s) with "
|
||||||
|
"multiple x modifiers\n"),
|
||||||
|
cod->name, (char *) cod->dfa);
|
||||||
|
free(cod->dfa);
|
||||||
|
cod->dfa = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Post process subdomain(s):
|
* Post process subdomain(s):
|
||||||
*
|
*
|
||||||
@@ -464,8 +530,11 @@ int process_regex(struct codomain *cod)
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
if (process_hat_regex(cod) != 0)
|
if (process_hat_regex(cod) != 0)
|
||||||
error = -1;
|
goto out;
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -184,7 +184,7 @@ static int process_variables_in_entries(struct cod_entry *entry_list)
|
|||||||
int ret = TRUE, rc;
|
int ret = TRUE, rc;
|
||||||
struct cod_entry *entry;
|
struct cod_entry *entry;
|
||||||
|
|
||||||
for (entry = entry_list; entry; entry = entry->next) {
|
list_for_each(entry_list, entry) {
|
||||||
rc = expand_entry_variables(entry);
|
rc = expand_entry_variables(entry);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
|
@@ -599,12 +599,12 @@ netrule: action addresses interface TOK_END_OF_RULE
|
|||||||
$$ = entry;
|
$$ = entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
action: TOK_TCP_CONN { $$ = KERN_COD_TCP_CONNECT; }
|
action: TOK_TCP_CONN { $$ = AA_TCP_CONNECT; }
|
||||||
| TOK_TCP_ACPT { $$ = KERN_COD_TCP_ACCEPT; }
|
| TOK_TCP_ACPT { $$ = AA_TCP_ACCEPT; }
|
||||||
| TOK_TCP_CONN_ESTB { $$ = KERN_COD_TCP_CONNECTED; }
|
| TOK_TCP_CONN_ESTB { $$ = AA_TCP_CONNECTED; }
|
||||||
| TOK_TCP_ACPT_ESTB { $$ = KERN_COD_TCP_ACCEPTED; }
|
| TOK_TCP_ACPT_ESTB { $$ = AA_TCP_ACCEPTED; }
|
||||||
| TOK_UDP_SEND { $$ = KERN_COD_UDP_SEND; }
|
| TOK_UDP_SEND { $$ = AA_UDP_SEND; }
|
||||||
| TOK_UDP_RECV { $$ = KERN_COD_UDP_RECEIVE; }
|
| TOK_UDP_RECV { $$ = AA_UDP_RECEIVE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user