2
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
3
* NOVELL (All rights reserved)
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of version 2 of the GNU General Public
7
* License published by the Free Software Foundation.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, contact Novell, Inc.
23
#include <linux/limits.h>
24
#define _(s) gettext(s)
29
#include "libapparmor_re/apparmor_re.h"
30
#include "libapparmor_re/aare_rules.h"
40
/* Filters out multiple slashes (except if the first two are slashes,
41
* that's a distinct namespace in linux) and trailing slashes.
42
* NOTE: modifies in place the contents of the path argument */
44
static void filter_slashes(char *path)
49
if (!path || (strlen(path) < 2))
54
/* special case for linux // namespace */
55
if (sptr[0] == '/' && sptr[1] == '/' && sptr[2] != '/') {
81
static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
82
char *pcre, size_t pcre_size,
85
#define STORE(_src, _dest, _len) \
86
if ((const char*)_dest + _len > (pcre + pcre_size)){ \
87
error = e_buffer_overflow; \
89
memcpy(_dest, _src, _len); \
92
#define update_re_pos(X) if (!(*first_re_pos)) { *first_re_pos = (X); }
97
/* flag to indicate input error */
98
enum error_type error;
104
BOOL bEscape = 0; /* flag to indicate escape */
105
int ingrouping = 0; /* flag to indicate {} context */
106
int incharclass = 0; /* flag to indicate [ ] context */
109
ptype = ePatternBasic; /* assume no regex */
114
if (dfaflags & DFA_DUMP_RULE_EXPR)
115
fprintf(stderr, "aare: %s -> ", aare);
118
/* anchor beginning of regular expression */
121
while (error == e_no_error && *sptr) {
125
/* concurrent escapes are allowed now and
126
* output as two consecutive escapes so that
127
* pcre won't interpret them
128
* \\\{...\\\} will be emitted as \\\{...\\\}
129
* for pcre matching. For string matching
130
* and globbing only one escape is output
131
* this is done by stripping later
134
STORE("\\\\", dptr, 2);
138
continue; /*skip turning bEscape off */
143
/* '*' is a PCRE special character */
144
/* We store an escaped *, in case we
145
* end up using this regex buffer (i.e another
146
* non-escaped regex follows)
148
STORE("\\*", dptr, 2);
150
if ((dptr > pcre) && *(dptr - 1) == '/') {
152
// handle comment containing use
153
// of C comment characters
154
// /* /*/ and /** to describe paths
156
// modify what is emitted for * and **
157
// when used as the only path
161
// this prevents these expressions
162
// from matching directories or
164
// in these case * and ** must
165
// match at least 1 character to
166
// get a valid path element.
168
// /foo/* -> should not match /foo/
169
// /foo/*bar -> should match /foo/bar
170
// /*/foo -> should not match //foo
172
const char *s = sptr;
175
if (*s == '/' || !*s) {
176
STORE("[^/\\x00]", dptr, 8);
179
if (*(sptr + 1) == '*') {
180
/* is this the first regex form we
181
* have seen and also the end of
182
* pattern? If so, we can use
183
* optimised tail globbing rather
186
update_re_pos(sptr - aare);
187
if (*(sptr + 2) == '\0' &&
188
ptype == ePatternBasic) {
189
ptype = ePatternTailGlob;
191
ptype = ePatternRegex;
194
STORE("[^\\x00]*", dptr, 8);
197
update_re_pos(sptr - aare);
198
ptype = ePatternRegex;
199
STORE("[^/\\x00]*", dptr, 9);
200
} /* *(sptr+1) == '*' */
207
/* ? is not a PCRE regex character
208
* so no need to escape, just skip
211
STORE(sptr, dptr, 1);
213
update_re_pos(sptr - aare);
214
ptype = ePatternRegex;
215
STORE("[^/\\x00]", dptr, 8);
221
/* [ is a PCRE special character */
222
STORE("\\[", dptr, 2);
224
update_re_pos(sptr - aare);
226
ptype = ePatternRegex;
227
STORE(sptr, dptr, 1);
233
/* ] is a PCRE special character */
234
STORE("\\]", dptr, 2);
237
STORE(sptr, dptr, 1);
243
/* { is a PCRE special character */
244
STORE("\\{", dptr, 2);
247
error = e_parse_error;
248
PERROR(_("%s: Illegal open {, nesting groupings not allowed\n"),
251
update_re_pos(sptr - aare);
253
ptype = ePatternRegex;
261
/* { is a PCRE special character */
262
STORE("\\}", dptr, 2);
264
if (ingrouping <= 1) {
266
error = e_parse_error;
268
if (ingrouping == 1) {
269
PERROR(_("%s: Regex grouping error: Invalid number of items between {}\n"),
272
ingrouping = 0; /* prevent further errors */
274
} else { /* ingrouping == 0 */
275
PERROR(_("%s: Regex grouping error: Invalid close }, no matching open { detected\n"),
278
} else { /* ingrouping > 1 */
288
/* , is not a PCRE regex character
289
* so no need to escape, just skip
292
STORE(sptr, dptr, 1);
298
STORE(sptr, dptr, 1);
303
/* these are special outside of character
304
* classes but not in them */
308
STORE(sptr, dptr, 1);
310
STORE("\\", dptr, 1);
311
STORE(sptr, dptr, 1);
316
* Not a subdomain regex, but needs to be
317
* escaped as it is a pcre metacharacter which
318
* we don't want to support. We always escape
319
* these, so no need to check bEscape
326
STORE("\\", dptr, 1);
327
// fall through to default
330
STORE(sptr, dptr, 1);
332
} /* switch (*sptr) */
336
} /* while error == e_no_error && *sptr) */
338
if (ingrouping > 0 || incharclass) {
339
error = e_parse_error;
341
PERROR(_("%s: Regex grouping error: Unclosed grouping or character class, expecting close }\n"),
345
/* anchor end and terminate pattern string */
346
if ((error == e_no_error) && anchor) {
347
STORE("$" , dptr, 1);
349
if (error == e_no_error) {
352
/* check error again, as above STORE may have set it */
353
if (error != e_no_error) {
354
if (error == e_buffer_overflow) {
355
PERROR(_("%s: Internal buffer overflow detected, %d characters exceeded\n"),
359
PERROR(_("%s: Unable to parse input line '%s'\n"),
368
ptype = ePatternInvalid;
370
if (dfaflags & DFA_DUMP_RULE_EXPR)
371
fprintf(stderr, "%s\n", pcre);
376
static const char *local_name(const char *name)
380
for (t = strstr(name, "//") ; t ; t = strstr(name, "//"))
386
static int process_profile_name_xmatch(struct codomain *cod)
388
char tbuf[PATH_MAX + 3]; /* +3 for ^, $ and \0 */
392
/* don't filter_slashes for profile names */
394
name = cod->attachment;
396
name = local_name(cod->name);
397
ptype = convert_aaregex_to_pcre(name, 0, tbuf, PATH_MAX + 3,
399
if (ptype == ePatternBasic)
400
cod->xmatch_len = strlen(name);
402
if (ptype == ePatternInvalid) {
403
PERROR(_("%s: Invalid profile name '%s' - bad regular expression\n"), progname, name);
405
} else if (ptype == ePatternBasic && !(cod->altnames || cod->attachment)) {
406
/* no regex so do not set xmatch */
409
cod->xmatch_size = 0;
412
aare_ruleset_t *rule = aare_new_ruleset(0);
415
if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0, dfaflags)) {
416
aare_delete_ruleset(rule);
420
struct alt_name *alt;
421
list_for_each(cod->altnames, alt) {
423
ptype = convert_aaregex_to_pcre(alt->name, 0,
427
if (ptype == ePatternBasic)
428
len = strlen(alt->name);
429
if (len < cod->xmatch_len)
430
cod->xmatch_len = len;
431
if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0, dfaflags)) {
432
aare_delete_ruleset(rule);
437
cod->xmatch = aare_create_dfa(rule, &cod->xmatch_size,
439
aare_delete_ruleset(rule);
447
static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry)
449
char tbuf[PATH_MAX + 3]; /* +3 for ^, $ and \0 */
453
if (!entry) /* shouldn't happen */
457
if (entry->mode & ~AA_CHANGE_PROFILE)
458
filter_slashes(entry->name);
459
ptype = convert_aaregex_to_pcre(entry->name, 0, tbuf, PATH_MAX+3, &pos);
460
if (ptype == ePatternInvalid)
463
entry->pattern_type = ptype;
465
/* ix implies m but the apparmor module does not add m bit to
466
* dfa states like it does for pcre
468
if ((entry->mode >> AA_OTHER_SHIFT) & AA_EXEC_INHERIT)
469
entry->mode |= AA_EXEC_MMAP << AA_OTHER_SHIFT;
470
if ((entry->mode >> AA_USER_SHIFT) & AA_EXEC_INHERIT)
471
entry->mode |= AA_EXEC_MMAP << AA_USER_SHIFT;
473
/* relying on ptrace and change_profile not getting merged earlier */
475
/* the link bit on the first pair entry should not get masked
476
* out by a deny rule, as both pieces of the link pair must
477
* match. audit info for the link is carried on the second
480
if (entry->deny && (entry->mode & AA_LINK_BITS)) {
481
if (!aare_add_rule(dfarules, tbuf, entry->deny,
482
entry->mode & ~AA_LINK_BITS,
483
entry->audit & ~AA_LINK_BITS, dfaflags))
485
} else if (entry->mode & ~AA_CHANGE_PROFILE) {
486
if (!aare_add_rule(dfarules, tbuf, entry->deny, entry->mode,
487
entry->audit, dfaflags))
491
if (entry->mode & (AA_LINK_BITS)) {
492
/* add the pair rule */
493
char lbuf[PATH_MAX + 8];
494
int perms = AA_LINK_BITS & entry->mode;
498
if (entry->link_name) {
499
ptype = convert_aaregex_to_pcre(entry->link_name, 0, lbuf, PATH_MAX + 8, &pos);
500
if (ptype == ePatternInvalid)
503
perms |= LINK_TO_LINK_SUBSET(perms);
506
perms |= LINK_TO_LINK_SUBSET(perms);
509
if (!aare_add_rule_vec(dfarules, entry->deny, perms, entry->audit & AA_LINK_BITS, 2, vec, dfaflags))
512
if (entry->mode & AA_CHANGE_PROFILE) {
514
char lbuf[PATH_MAX + 8];
517
/* allow change_profile for all execs */
518
vec[0] = "/[^\\x00]*";
520
if (entry->namespace) {
522
ptype = convert_aaregex_to_pcre(entry->namespace, 0, lbuf, PATH_MAX + 8, &pos);
527
/* regular change_profile rule */
528
if (!aare_add_rule_vec(dfarules, 0, AA_CHANGE_PROFILE, 0, index - 1, &vec[1], dfaflags))
530
/* onexec rules - both rules are needed for onexec */
531
if (!aare_add_rule_vec(dfarules, 0, AA_ONEXEC, 0, 1, vec, dfaflags))
533
if (!aare_add_rule_vec(dfarules, 0, AA_ONEXEC, 0, index, vec, dfaflags))
536
if (entry->mode & (AA_USER_PTRACE | AA_OTHER_PTRACE)) {
537
int mode = entry->mode & (AA_USER_PTRACE | AA_OTHER_PTRACE);
538
if (entry->namespace) {
540
vec[0] = entry->namespace;
541
vec[1] = entry->name;
542
if (!aare_add_rule_vec(dfarules, 0, mode, 0, 2, vec, dfaflags))
545
if (!aare_add_rule(dfarules, entry->name, 0, mode, 0, dfaflags))
552
int post_process_entries(struct codomain *cod)
555
struct cod_entry *entry;
558
list_for_each(cod->entries, entry) {
559
if (regex_type == AARE_DFA &&
560
!process_dfa_entry(cod->dfarules, entry))
565
cod->dfarule_count = count;
569
int process_regex(struct codomain *cod)
573
if (regex_type == AARE_DFA) {
574
if (!process_profile_name_xmatch(cod))
577
cod->dfarules = aare_new_ruleset(0);
581
if (!post_process_entries(cod))
584
if (regex_type == AARE_DFA && cod->dfarule_count > 0) {
585
cod->dfa = aare_create_dfa(cod->dfarules, &cod->dfa_size,
587
aare_delete_ruleset(cod->dfarules);
588
cod->dfarules = NULL;
592
if (cod->dfa_size == 0) {
593
PERROR(_("profile %s: has merged rules (%s) with "
594
"multiple x modifiers\n"),
595
cod->name, (char *) cod->dfa);
603
* Post process subdomain(s):
605
* They are chained from the toplevel subdomain pointer
606
* thru each <codomain> next pointer.
608
* i.e first subdomain is list->subdomain
609
* second subdomain is list->subdomain->next
611
* N.B sub-subdomains are not valid so:
612
* if (list->subdomain) {
613
* assert(list->subdomain->subdomain == NULL)
616
if (process_hat_regex(cod) != 0)
625
static int build_list_val_expr(char *buffer, int size, struct value_list *list)
627
struct value_list *ent;
628
char tmp[PATH_MAX + 3];
635
strncpy(buffer, "[^\\000]*", size);
640
strncpy(p, "(", size - (p - buffer));
642
if (p > buffer + size)
645
ptype = convert_aaregex_to_pcre(list->value, 0, tmp, PATH_MAX+3, &pos);
646
if (ptype == ePatternInvalid)
650
if (len > size - (p - buffer))
655
list_for_each(list->next, ent) {
656
ptype = convert_aaregex_to_pcre(ent->value, 0, tmp,
658
if (ptype == ePatternInvalid)
661
strncpy(p, "|", size - (p - buffer));
664
if (len > size - (p - buffer))
669
strncpy(p, ")", size - (p - buffer));
671
if (p > buffer + size)
679
static int convert_entry(char *buffer, int size, char *entry)
685
ptype = convert_aaregex_to_pcre(entry, 0, buffer, size, &pos);
686
if (ptype == ePatternInvalid)
689
/* match any char except \000 0 or more times */
693
strcpy(buffer, "[^\\000]*");
698
static int build_mnt_flags(char *buffer, int size, unsigned int flags,
699
unsigned int inv_flags)
704
if (flags == MS_ALL_FLAGS) {
705
/* all flags are optional */
706
len = snprintf(p, size, "[^\\000]*");
707
if (len < 0 || len >= size)
711
for (i = 0; i <= 31; ++i) {
712
if ((flags & inv_flags) & (1 << i))
713
len = snprintf(p, size, "(\\x%02x|)", i + 1);
714
else if (flags & (1 << i))
715
len = snprintf(p, size, "\\x%02x", i + 1);
716
else /* no entry = not set */
719
if (len < 0 || len >= size)
725
/* this needs to go once the backend is updated. */
727
/* match nothing - use impossible 254 as regex parser doesn't
728
* like the empty string
733
strcpy(p, "(\\xfe|)");
739
static int build_mnt_opts(char *buffer, int size, struct value_list *opts)
741
struct value_list *ent;
742
char tmp[PATH_MAX + 3];
751
strncpy(buffer, "[^\\000]*", size);
756
list_for_each(opts, ent) {
757
ptype = convert_aaregex_to_pcre(ent->value, 0, tmp,
759
if (ptype == ePatternInvalid)
763
if (len > size - (p - buffer))
767
if (ent->next && size - (p - buffer) > 1) {
779
static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
781
char mntbuf[PATH_MAX + 3];
782
char devbuf[PATH_MAX + 3];
783
char typebuf[PATH_MAX + 3];
784
char flagsbuf[PATH_MAX + 3];
785
char optsbuf[PATH_MAX + 3];
788
unsigned int flags, inv_flags;
790
/* a single mount rule may result in multiple matching rules being
791
* created in the backend to cover all the possible choices
794
if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_REMOUNT)
795
&& !entry->device && !entry->dev_type) {
797
/* remount can't be conditional on device and type */
799
/* rule class single byte header */
800
p += sprintf(p, "\\x%02x", AA_CLASS_MOUNT);
801
if (entry->mnt_point) {
802
/* both device && mnt_point or just mnt_point */
803
if (!convert_entry(p, PATH_MAX +3, entry->mnt_point))
807
if (!convert_entry(p, PATH_MAX +3, entry->device))
812
if (!convert_entry(devbuf, PATH_MAX +3, NULL))
818
flags = entry->flags;
819
inv_flags = entry->inv_flags;
820
if (flags != MS_ALL_FLAGS)
821
flags &= MS_REMOUNT_FLAGS;
822
if (inv_flags != MS_ALL_FLAGS)
823
flags &= MS_REMOUNT_FLAGS;
824
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
827
if (!build_mnt_opts(optsbuf, PATH_MAX, entry->opts))
831
allow = AA_MATCH_CONT;
833
allow = entry->allow;
835
/* rule for match without required data || data MATCH_CONT */
836
if (!aare_add_rule_vec(dfarules, entry->deny, allow,
837
entry->audit | AA_AUDIT_MNT_DATA, 4,
843
/* rule with data match required */
844
if (!build_mnt_opts(optsbuf, PATH_MAX, entry->opts))
847
if (!aare_add_rule_vec(dfarules, entry->deny,
849
entry->audit | AA_AUDIT_MNT_DATA,
855
if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_BIND)
856
&& !entry->dev_type && !entry->opts) {
857
/* bind mount rules can't be conditional on dev_type or data */
859
/* rule class single byte header */
860
p += sprintf(p, "\\x%02x", AA_CLASS_MOUNT);
861
if (!convert_entry(p, PATH_MAX +3, entry->mnt_point))
864
if (!convert_entry(devbuf, PATH_MAX +3, entry->device))
867
if (!convert_entry(typebuf, PATH_MAX +3, NULL))
871
flags = entry->flags;
872
inv_flags = entry->inv_flags;
873
if (flags != MS_ALL_FLAGS)
874
flags &= MS_BIND_FLAGS;
875
if (inv_flags != MS_ALL_FLAGS)
876
flags &= MS_BIND_FLAGS;
877
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
880
if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
881
entry->audit, 4, vec, dfaflags))
885
if ((entry->allow & AA_MAY_MOUNT) &&
886
(entry->flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
887
&& !entry->device && !entry->dev_type && !entry->opts) {
888
/* change type base rules can not be conditional on device,
889
* device type or data
892
/* rule class single byte header */
893
p += sprintf(p, "\\x%02x", AA_CLASS_MOUNT);
894
if (!convert_entry(p, PATH_MAX +3, entry->mnt_point))
897
/* skip device and type */
898
if (!convert_entry(devbuf, PATH_MAX +3, NULL))
903
flags = entry->flags;
904
inv_flags = entry->inv_flags;
905
if (flags != MS_ALL_FLAGS)
906
flags &= MS_MAKE_FLAGS;
907
if (inv_flags != MS_ALL_FLAGS)
908
flags &= MS_MAKE_FLAGS;
909
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
912
if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
913
entry->audit, 4, vec, dfaflags))
917
if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_MOVE)
918
&& !entry->dev_type && !entry->opts) {
919
/* mount move rules can not be conditional on dev_type,
923
/* rule class single byte header */
924
p += sprintf(p, "\\x%02x", AA_CLASS_MOUNT);
925
if (!convert_entry(p, PATH_MAX +3, entry->mnt_point))
928
if (!convert_entry(devbuf, PATH_MAX +3, entry->device))
932
if (!convert_entry(typebuf, PATH_MAX +3, NULL))
936
flags = entry->flags;
937
inv_flags = entry->inv_flags;
938
if (flags != MS_ALL_FLAGS)
939
flags &= MS_MOVE_FLAGS;
940
if (inv_flags != MS_ALL_FLAGS)
941
flags &= MS_MOVE_FLAGS;
942
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
945
if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
946
entry->audit, 4, vec, dfaflags))
950
if ((entry->allow & AA_MAY_MOUNT) &&
951
(entry->flags | entry->inv_flags) & ~MS_CMDS) {
953
/* generic mount if flags are set that are not covered by
957
/* rule class single byte header */
958
p += sprintf(p, "\\x%02x", AA_CLASS_MOUNT);
959
if (!convert_entry(p, PATH_MAX +3, entry->mnt_point))
962
if (!convert_entry(devbuf, PATH_MAX +3, entry->device))
965
if (!build_list_val_expr(typebuf, PATH_MAX+2, entry->dev_type))
969
flags = entry->flags;
970
inv_flags = entry->inv_flags;
971
if (flags != MS_ALL_FLAGS)
973
if (inv_flags != MS_ALL_FLAGS)
975
if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
980
allow = AA_MATCH_CONT;
982
allow = entry->allow;
984
/* rule for match without required data || data MATCH_CONT */
985
if (!aare_add_rule_vec(dfarules, entry->deny, allow,
986
entry->audit | AA_AUDIT_MNT_DATA, 4,
992
/* rule with data match required */
993
if (!build_mnt_opts(optsbuf, PATH_MAX, entry->opts))
996
if (!aare_add_rule_vec(dfarules, entry->deny,
998
entry->audit | AA_AUDIT_MNT_DATA,
1004
if (entry->allow & AA_MAY_UMOUNT) {
1006
/* rule class single byte header */
1007
p += sprintf(p, "\\x%02x", AA_CLASS_MOUNT);
1008
if (!convert_entry(p, PATH_MAX +3, entry->mnt_point))
1011
if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
1012
entry->audit, 1, vec, dfaflags))
1016
if (entry->allow & AA_MAY_PIVOTROOT) {
1018
/* rule class single byte header */
1019
p += sprintf(p, "\\x%02x", AA_CLASS_MOUNT);
1020
if (!convert_entry(p, PATH_MAX +3, entry->mnt_point))
1023
if (!convert_entry(devbuf, PATH_MAX +3, entry->device))
1026
if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
1027
entry->audit, 2, vec, dfaflags))
1033
/* didn't actually encode anything */
1039
PERROR("Enocoding of mount rule failed\n");
1044
int post_process_policydb_ents(struct codomain *cod)
1049
/* Add fns for rules that should be added to policydb here */
1050
if (cod->mnt_ents && kernel_supports_mount) {
1051
struct mnt_entry *entry;
1052
list_for_each(cod->mnt_ents, entry) {
1053
if (regex_type == AARE_DFA &&
1054
!process_mnt_entry(cod->policy_rules, entry))
1058
} else if (cod->mnt_ents && !kernel_supports_mount)
1059
pwarn("profile %s mount rules not enforced\n", cod->name);
1061
cod->policy_rule_count = count;
1065
int process_policydb(struct codomain *cod)
1069
if (regex_type == AARE_DFA) {
1070
cod->policy_rules = aare_new_ruleset(0);
1071
if (!cod->policy_rules)
1075
if (!post_process_policydb_ents(cod))
1078
if (regex_type == AARE_DFA && cod->policy_rule_count > 0) {
1079
cod->policy_dfa = aare_create_dfa(cod->policy_rules,
1080
&cod->policy_dfa_size,
1082
aare_delete_ruleset(cod->policy_rules);
1083
cod->policy_rules = NULL;
1084
if (!cod->policy_dfa)
1088
aare_reset_matchflags();
1089
if (process_hat_policydb(cod) != 0)
1098
void reset_regex(void)
1100
aare_reset_matchflags();
1104
static int test_filter_slashes(void)
1109
test_string = strdup("///foo//////f//oo////////////////");
1110
filter_slashes(test_string);
1111
MY_TEST(strcmp(test_string, "/foo/f/oo/") == 0, "simple tests");
1113
test_string = strdup("/foo/f/oo");
1114
filter_slashes(test_string);
1115
MY_TEST(strcmp(test_string, "/foo/f/oo") == 0, "simple test for no changes");
1117
test_string = strdup("/");
1118
filter_slashes(test_string);
1119
MY_TEST(strcmp(test_string, "/") == 0, "simple test for '/'");
1121
test_string = strdup("");
1122
filter_slashes(test_string);
1123
MY_TEST(strcmp(test_string, "") == 0, "simple test for ''");
1125
test_string = strdup("//usr");
1126
filter_slashes(test_string);
1127
MY_TEST(strcmp(test_string, "//usr") == 0, "simple test for // namespace");
1129
test_string = strdup("//");
1130
filter_slashes(test_string);
1131
MY_TEST(strcmp(test_string, "//") == 0, "simple test 2 for // namespace");
1133
test_string = strdup("///usr");
1134
filter_slashes(test_string);
1135
MY_TEST(strcmp(test_string, "/usr") == 0, "simple test for ///usr");
1137
test_string = strdup("///");
1138
filter_slashes(test_string);
1139
MY_TEST(strcmp(test_string, "/") == 0, "simple test for ///");
1141
test_string = strdup("/a/");
1142
filter_slashes(test_string);
1143
MY_TEST(strcmp(test_string, "/a/") == 0, "simple test for /a/");
1153
retval = test_filter_slashes();
1159
#endif /* UNIT_TEST */