Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
halo
external_sepolicy
Commits
bdc8c77a
Commit
bdc8c77a
authored
10 years ago
by
dcashman
Committed by
Gerrit Code Review
10 years ago
Browse files
Options
Download
Plain Diff
Merge "Accept command-line input for neverallow-check."
parents
c457572b
ef4fd306
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1212 additions
and
89 deletions
+1212
-89
tools/Android.mk
tools/Android.mk
+1
-11
tools/README
tools/README
+1
-78
tools/sepolicy-analyze/Android.mk
tools/sepolicy-analyze/Android.mk
+13
-0
tools/sepolicy-analyze/README
tools/sepolicy-analyze/README
+82
-0
tools/sepolicy-analyze/dups.c
tools/sepolicy-analyze/dups.c
+91
-0
tools/sepolicy-analyze/dups.h
tools/sepolicy-analyze/dups.h
+11
-0
tools/sepolicy-analyze/neverallow.c
tools/sepolicy-analyze/neverallow.c
+515
-0
tools/sepolicy-analyze/neverallow.h
tools/sepolicy-analyze/neverallow.h
+11
-0
tools/sepolicy-analyze/perm.c
tools/sepolicy-analyze/perm.c
+30
-0
tools/sepolicy-analyze/perm.h
tools/sepolicy-analyze/perm.h
+11
-0
tools/sepolicy-analyze/sepolicy-analyze.c
tools/sepolicy-analyze/sepolicy-analyze.c
+56
-0
tools/sepolicy-analyze/typecmp.c
tools/sepolicy-analyze/typecmp.c
+295
-0
tools/sepolicy-analyze/typecmp.h
tools/sepolicy-analyze/typecmp.h
+11
-0
tools/sepolicy-analyze/utils.c
tools/sepolicy-analyze/utils.c
+68
-0
tools/sepolicy-analyze/utils.h
tools/sepolicy-analyze/utils.h
+16
-0
No files found.
tools/Android.mk
View file @
bdc8c77a
...
...
@@ -46,14 +46,4 @@ LOCAL_STATIC_LIBRARIES := libsepol
include
$(BUILD_HOST_EXECUTABLE)
###################################
include
$(CLEAR_VARS)
LOCAL_MODULE
:=
sepolicy-analyze
LOCAL_MODULE_TAGS
:=
optional
LOCAL_C_INCLUDES
:=
external/libsepol/include
LOCAL_CFLAGS
:=
-Wall
-Werror
LOCAL_SRC_FILES
:=
sepolicy-analyze.c
LOCAL_STATIC_LIBRARIES
:=
libsepol
include
$(BUILD_HOST_EXECUTABLE)
include
$(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
This diff is collapsed.
Click to expand it.
tools/README
View file @
bdc8c77a
...
...
@@ -50,81 +50,4 @@ sepolicy-check
sepolicy-analyze
A tool for performing various kinds of analysis on a sepolicy
file. The current kinds of analysis that are currently supported
include:
TYPE EQUIVALENCE
sepolicy-analyze -e -P out/target/product/<board>/root/sepolicy
Display all type pairs that are "equivalent", i.e. they are
identical with respect to allow rules, including indirect allow
rules via attributes and default-enabled conditional rules
(i.e. default boolean values yield a true conditional expression).
Equivalent types are candidates for being coalesced into a single
type. However, there may be legitimate reasons for them to remain
separate, for example: - the types may differ in a respect not
included in the current analysis, such as default-disabled
conditional rules, audit-related rules (auditallow or dontaudit),
default type transitions, or constraints (e.g. mls), or - the
current policy may be overly permissive with respect to one or the
other of the types and thus the correct action may be to tighten
access to one or the other rather than coalescing them together,
or - the domains that would in fact have different accesses to the
types may not yet be defined or may be unconfined in the policy
you are analyzing.
TYPE DIFFERENCE
sepolicy-analyze -d -P out/target/product/<board>/root/sepolicy
Display type pairs that differ and the first difference found
between the two types. This may be used in looking for similar
types that are not equivalent but may be candidates for coalescing.
DUPLICATE ALLOW RULES
sepolicy-analyze -D -P out/target/product/<board>/root/sepolicy
Displays duplicate allow rules, i.e. pairs of allow rules that
grant the same permissions where one allow rule is written
directly in terms of individual types and the other is written in
terms of attributes associated with those same types. The rule
with individual types is a candidate for removal. The rule with
individual types may be directly represented in the source policy
or may be a result of expansion of a type negation (e.g. domain
-foo -bar is expanded to individual allow rules by the policy
compiler). Domains with unconfineddomain will typically have such
duplicate rules as a natural side effect and can be ignored.
PERMISSIVE DOMAINS
sepolicy-analyze -p -P out/target/product/<board>/root/sepolicy
Displays domains in the policy that are permissive, i.e. avc
denials are logged but not enforced for these domains. While
permissive domains can be helpful during development, they
should not be present in a final -user build.
NEVERALLOW CHECKING
sepolicy-analyze [-w] [-z] -n neverallows.conf -P out/target/product/<board>/root/sepolicy
Check whether the sepolicy file violates any of the neverallow rules
from neverallows.conf. neverallows.conf is a file containing neverallow
statements in the same format as the SELinux policy.conf file, i.e. after
m4 macro expansion of the rules from a .te file. You can use an entire
policy.conf file as the neverallows.conf file and sepolicy-analyze will
ignore everything except for the neverallows within it. If there are
no violations, sepolicy-analyze will exit successfully with no output.
Otherwise, sepolicy-analyze will report all violations and exit
with a non-zero exit status.
The -w or --warn option may be used to warn on any types, attributes,
classes, or permissions from a neverallow rule that could not be resolved
within the sepolicy file. This can be normal due to differences between
the policy from which the neverallow rules were taken and the policy
being checked. Such values are ignored for the purposes of neverallow
checking.
The -z (-d was already taken!) or --debug option may be used to cause
sepolicy-analyze to emit the neverallow rules as it parses them from
the neverallows.conf file. This is principally a debugging facility
for the parser but could also be used to extract neverallow rules from
a full policy.conf file and output them in a more easily parsed format.
file.
\ No newline at end of file
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/Android.mk
0 → 100644
View file @
bdc8c77a
LOCAL_PATH
:=
$(
call
my-dir
)
###################################
include
$(CLEAR_VARS)
LOCAL_MODULE
:=
sepolicy-analyze
LOCAL_MODULE_TAGS
:=
optional
LOCAL_C_INCLUDES
:=
external/libsepol/include
LOCAL_CFLAGS
:=
-Wall
-Werror
LOCAL_SRC_FILES
:=
sepolicy-analyze.c dups.c neverallow.c perm.c typecmp.c utils.c
LOCAL_STATIC_LIBRARIES
:=
libsepol
include
$(BUILD_HOST_EXECUTABLE)
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/README
0 → 100644
View file @
bdc8c77a
sepolicy-analyze
A component-ized tool for performing various kinds of analysis on a
sepolicy file. The current kinds of analysis that are currently
supported include:
TYPE EQUIVALENCE (typecmp)
sepolicy-analyze out/target/product/<board>/root/sepolicy typecmp -e
Display all type pairs that are "equivalent", i.e. they are
identical with respect to allow rules, including indirect allow
rules via attributes and default-enabled conditional rules
(i.e. default boolean values yield a true conditional expression).
Equivalent types are candidates for being coalesced into a single
type. However, there may be legitimate reasons for them to remain
separate, for example: - the types may differ in a respect not
included in the current analysis, such as default-disabled
conditional rules, audit-related rules (auditallow or dontaudit),
default type transitions, or constraints (e.g. mls), or - the
current policy may be overly permissive with respect to one or the
other of the types and thus the correct action may be to tighten
access to one or the other rather than coalescing them together,
or - the domains that would in fact have different accesses to the
types may not yet be defined or may be unconfined in the policy
you are analyzing.
TYPE DIFFERENCE (typecmp)
sepolicy-analyze out/target/product/<board>/root/sepolicy typecmp -d
Display type pairs that differ and the first difference found
between the two types. This may be used in looking for similar
types that are not equivalent but may be candidates for coalescing.
DUPLICATE ALLOW RULES (dups)
sepolicy-analyze out/target/product/<board>/root/sepolicy dups
Displays duplicate allow rules, i.e. pairs of allow rules that
grant the same permissions where one allow rule is written
directly in terms of individual types and the other is written in
terms of attributes associated with those same types. The rule
with individual types is a candidate for removal. The rule with
individual types may be directly represented in the source policy
or may be a result of expansion of a type negation (e.g. domain
-foo -bar is expanded to individual allow rules by the policy
compiler). Domains with unconfineddomain will typically have such
duplicate rules as a natural side effect and can be ignored.
PERMISSIVE DOMAINS (permissive)
sepolicy-analyze out/target/product/<board>/root/sepolicy permissive
Displays domains in the policy that are permissive, i.e. avc
denials are logged but not enforced for these domains. While
permissive domains can be helpful during development, they
should not be present in a final -user build.
NEVERALLOW CHECKING (neverallow)
sepolicy-analyze out/target/product/<board>/root/sepolicy neverallow \
[-w] [-d] [-f neverallows.conf] | [-n "neverallow string"]
Check whether the sepolicy file violates any of the neverallow rules
from the neverallows.conf file or a given string, which contain neverallow
statements in the same format as the SELinux policy.conf file, i.e. after
m4 macro expansion of the rules from a .te file. You can use an entire
policy.conf file as the neverallows.conf file and sepolicy-analyze will
ignore everything except for the neverallows within it. You can also
specify this as a command-line string argument, which could be useful for
quickly checking an individual expanded rule or group of rules. If there are
no violations, sepolicy-analyze will exit successfully with no output.
Otherwise, sepolicy-analyze will report all violations and exit
with a non-zero exit status.
The -w or --warn option may be used to warn on any types, attributes,
classes, or permissions from a neverallow rule that could not be resolved
within the sepolicy file. This can be normal due to differences between
the policy from which the neverallow rules were taken and the policy
being checked. Such values are ignored for the purposes of neverallow
checking.
The -d or --debug option may be used to cause sepolicy-analyze to emit the
neverallow rules as it parses them. This is principally a debugging facility
for the parser but could also be used to extract neverallow rules from
a full policy.conf file and output them in a more easily parsed format.
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/dups.c
0 → 100644
View file @
bdc8c77a
#include <stdbool.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "dups.h"
void
dups_usage
()
{
fprintf
(
stderr
,
"
\t
dups
\n
"
);
}
static
int
find_dups_helper
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
policydb_t
*
policydb
=
args
;
ebitmap_t
*
sattr
,
*
tattr
;
ebitmap_node_t
*
snode
,
*
tnode
;
unsigned
int
i
,
j
;
avtab_key_t
avkey
;
avtab_ptr_t
node
;
struct
type_datum
*
stype
,
*
ttype
,
*
stype2
,
*
ttype2
;
bool
attrib1
,
attrib2
;
if
(
!
(
k
->
specified
&
AVTAB_ALLOWED
))
return
0
;
if
(
k
->
source_type
==
k
->
target_type
)
return
0
;
/* self rule */
avkey
.
target_class
=
k
->
target_class
;
avkey
.
specified
=
k
->
specified
;
sattr
=
&
policydb
->
type_attr_map
[
k
->
source_type
-
1
];
tattr
=
&
policydb
->
type_attr_map
[
k
->
target_type
-
1
];
stype
=
policydb
->
type_val_to_struct
[
k
->
source_type
-
1
];
ttype
=
policydb
->
type_val_to_struct
[
k
->
target_type
-
1
];
attrib1
=
stype
->
flavor
||
ttype
->
flavor
;
ebitmap_for_each_bit
(
sattr
,
snode
,
i
)
{
if
(
!
ebitmap_node_get_bit
(
snode
,
i
))
continue
;
ebitmap_for_each_bit
(
tattr
,
tnode
,
j
)
{
if
(
!
ebitmap_node_get_bit
(
tnode
,
j
))
continue
;
avkey
.
source_type
=
i
+
1
;
avkey
.
target_type
=
j
+
1
;
if
(
avkey
.
source_type
==
k
->
source_type
&&
avkey
.
target_type
==
k
->
target_type
)
continue
;
if
(
avkey
.
source_type
==
avkey
.
target_type
)
continue
;
/* self rule */
stype2
=
policydb
->
type_val_to_struct
[
avkey
.
source_type
-
1
];
ttype2
=
policydb
->
type_val_to_struct
[
avkey
.
target_type
-
1
];
attrib2
=
stype2
->
flavor
||
ttype2
->
flavor
;
if
(
attrib1
&&
attrib2
)
continue
;
/* overlapping attribute-based rules */
for
(
node
=
avtab_search_node
(
&
policydb
->
te_avtab
,
&
avkey
);
node
!=
NULL
;
node
=
avtab_search_node_next
(
node
,
avkey
.
specified
))
{
uint32_t
perms
=
node
->
datum
.
data
&
d
->
data
;
if
((
attrib1
&&
perms
==
node
->
datum
.
data
)
||
(
attrib2
&&
perms
==
d
->
data
))
{
/*
* The attribute-based rule is a superset of the
* non-attribute-based rule. This is a dup.
*/
printf
(
"Duplicate allow rule found:
\n
"
);
display_allow
(
policydb
,
k
,
i
,
d
->
data
);
display_allow
(
policydb
,
&
node
->
key
,
i
,
node
->
datum
.
data
);
printf
(
"
\n
"
);
}
}
}
}
return
0
;
}
static
int
find_dups
(
policydb_t
*
policydb
)
{
if
(
avtab_map
(
&
policydb
->
te_avtab
,
find_dups_helper
,
policydb
))
return
-
1
;
return
0
;
}
int
dups_func
(
int
argc
,
__attribute__
((
unused
))
char
**
argv
,
policydb_t
*
policydb
)
{
if
(
argc
!=
1
)
{
USAGE_ERROR
=
true
;
return
-
1
;
}
return
find_dups
(
policydb
);
}
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/dups.h
0 → 100644
View file @
bdc8c77a
#ifndef DUPS_H
#define DUPS_H
#include <sepol/policydb/policydb.h>
#include "utils.h"
void
dups_usage
(
void
);
int
dups_func
(
int
argc
,
char
**
argv
,
policydb_t
*
policydb
);
#endif
/* DUPS_H */
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze.c
→
tools/sepolicy-analyze
/neverallow
.c
View file @
bdc8c77a
#include <ctype.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/util.h>
#include <stdbool.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include "neverallow.h"
static
int
debug
;
static
int
warn
;
void
usage
(
char
*
arg0
)
{
fprintf
(
stderr
,
"%s [-w|--warn] [-z|--debug] [-e|--equiv] [-d|--diff] [-D|--dups] [-p|--permissive] [-n|--neverallow <neverallow file>] -P <policy file>
\n
"
,
arg0
);
exit
(
1
);
}
int
load_policy
(
char
*
filename
,
policydb_t
*
policydb
,
struct
policy_file
*
pf
)
{
int
fd
;
struct
stat
sb
;
void
*
map
;
int
ret
;
fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
<
0
)
{
fprintf
(
stderr
,
"Can't open '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
return
1
;
}
if
(
fstat
(
fd
,
&
sb
)
<
0
)
{
fprintf
(
stderr
,
"Can't stat '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
1
;
}
map
=
mmap
(
NULL
,
sb
.
st_size
,
PROT_READ
|
PROT_WRITE
,
MAP_PRIVATE
,
fd
,
0
);
if
(
map
==
MAP_FAILED
)
{
fprintf
(
stderr
,
"Can't mmap '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
1
;
}
policy_file_init
(
pf
);
pf
->
type
=
PF_USE_MEMORY
;
pf
->
data
=
map
;
pf
->
len
=
sb
.
st_size
;
if
(
policydb_init
(
policydb
))
{
fprintf
(
stderr
,
"Could not initialize policydb!
\n
"
);
close
(
fd
);
munmap
(
map
,
sb
.
st_size
);
return
1
;
}
ret
=
policydb_read
(
policydb
,
pf
,
0
);
if
(
ret
)
{
fprintf
(
stderr
,
"error(s) encountered while parsing configuration
\n
"
);
close
(
fd
);
munmap
(
map
,
sb
.
st_size
);
return
1
;
}
return
0
;
}
static
int
insert_type_rule
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
struct
avtab_node
*
type_rules
)
{
struct
avtab_node
*
p
,
*
c
,
*
n
;
for
(
p
=
type_rules
,
c
=
type_rules
->
next
;
c
;
p
=
c
,
c
=
c
->
next
)
{
/*
* Find the insertion point, keeping the list
* ordered by source type, then target type, then
* target class.
*/
if
(
k
->
source_type
<
c
->
key
.
source_type
)
break
;
if
(
k
->
source_type
==
c
->
key
.
source_type
&&
k
->
target_type
<
c
->
key
.
target_type
)
break
;
if
(
k
->
source_type
==
c
->
key
.
source_type
&&
k
->
target_type
==
c
->
key
.
target_type
&&
k
->
target_class
<=
c
->
key
.
target_class
)
break
;
}
if
(
c
&&
k
->
source_type
==
c
->
key
.
source_type
&&
k
->
target_type
==
c
->
key
.
target_type
&&
k
->
target_class
==
c
->
key
.
target_class
)
{
c
->
datum
.
data
|=
d
->
data
;
return
0
;
}
/* Insert the rule */
n
=
malloc
(
sizeof
(
struct
avtab_node
));
if
(
!
n
)
{
fprintf
(
stderr
,
"out of memory
\n
"
);
exit
(
1
);
}
n
->
key
=
*
k
;
n
->
datum
=
*
d
;
n
->
next
=
p
->
next
;
p
->
next
=
n
;
return
0
;
}
static
int
create_type_rules_helper
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
struct
avtab_node
*
type_rules
=
args
;
avtab_key_t
key
;
/*
* Insert the rule into the list for
* the source type. The source type value
* is cleared as we want to compare against other type
* rules with different source types.
*/
key
=
*
k
;
key
.
source_type
=
0
;
if
(
k
->
source_type
==
k
->
target_type
)
{
/* Clear target type as well; this is a self rule. */
key
.
target_type
=
0
;
}
if
(
insert_type_rule
(
&
key
,
d
,
&
type_rules
[
k
->
source_type
-
1
]))
return
-
1
;
if
(
k
->
source_type
==
k
->
target_type
)
return
0
;
/*
* If the target type differs, then we also
* insert the rule into the list for the target
* type. We clear the target type value so that
* we can compare against other type rules with
* different target types.
*/
key
=
*
k
;
key
.
target_type
=
0
;
if
(
insert_type_rule
(
&
key
,
d
,
&
type_rules
[
k
->
target_type
-
1
]))
return
-
1
;
return
0
;
}
static
int
create_type_rules
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
if
(
k
->
specified
&
AVTAB_ALLOWED
)
return
create_type_rules_helper
(
k
,
d
,
args
);
return
0
;
}
static
int
create_type_rules_cond
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
if
((
k
->
specified
&
(
AVTAB_ALLOWED
|
AVTAB_ENABLED
))
==
(
AVTAB_ALLOWED
|
AVTAB_ENABLED
))
return
create_type_rules_helper
(
k
,
d
,
args
);
return
0
;
}
static
void
free_type_rules
(
struct
avtab_node
*
l
)
{
struct
avtab_node
*
tmp
;
while
(
l
)
{
tmp
=
l
;
l
=
l
->
next
;
free
(
tmp
);
}
}
static
void
display_allow
(
policydb_t
*
policydb
,
avtab_key_t
*
key
,
int
idx
,
uint32_t
perms
)
{
printf
(
" allow %s %s:%s { %s };
\n
"
,
policydb
->
p_type_val_to_name
[
key
->
source_type
?
key
->
source_type
-
1
:
idx
],
key
->
target_type
==
key
->
source_type
?
"self"
:
policydb
->
p_type_val_to_name
[
key
->
target_type
?
key
->
target_type
-
1
:
idx
],
policydb
->
p_class_val_to_name
[
key
->
target_class
-
1
],
sepol_av_to_string
(
policydb
,
key
->
target_class
,
perms
));
}
static
int
find_match
(
policydb_t
*
policydb
,
struct
avtab_node
*
l1
,
int
idx1
,
struct
avtab_node
*
l2
,
int
idx2
)
{
struct
avtab_node
*
c
;
uint32_t
perms1
,
perms2
;
for
(
c
=
l2
;
c
;
c
=
c
->
next
)
{
if
(
l1
->
key
.
source_type
<
c
->
key
.
source_type
)
break
;
if
(
l1
->
key
.
source_type
==
c
->
key
.
source_type
&&
l1
->
key
.
target_type
<
c
->
key
.
target_type
)
break
;
if
(
l1
->
key
.
source_type
==
c
->
key
.
source_type
&&
l1
->
key
.
target_type
==
c
->
key
.
target_type
&&
l1
->
key
.
target_class
<=
c
->
key
.
target_class
)
break
;
}
if
(
c
&&
l1
->
key
.
source_type
==
c
->
key
.
source_type
&&
l1
->
key
.
target_type
==
c
->
key
.
target_type
&&
l1
->
key
.
target_class
==
c
->
key
.
target_class
)
{
perms1
=
l1
->
datum
.
data
&
~
c
->
datum
.
data
;
perms2
=
c
->
datum
.
data
&
~
l1
->
datum
.
data
;
if
(
perms1
||
perms2
)
{
if
(
perms1
)
display_allow
(
policydb
,
&
l1
->
key
,
idx1
,
perms1
);
if
(
perms2
)
display_allow
(
policydb
,
&
c
->
key
,
idx2
,
perms2
);
printf
(
"
\n
"
);
return
1
;
}
}
return
0
;
}
static
int
analyze_types
(
policydb_t
*
policydb
,
char
equiv
,
char
diff
)
{
avtab_t
exp_avtab
,
exp_cond_avtab
;
struct
avtab_node
*
type_rules
,
*
l1
,
*
l2
;
struct
type_datum
*
type
;
size_t
i
,
j
;
/*
* Create a list of access vector rules for each type
* from the access vector table.
*/
type_rules
=
malloc
(
sizeof
(
struct
avtab_node
)
*
policydb
->
p_types
.
nprim
);
if
(
!
type_rules
)
{
fprintf
(
stderr
,
"out of memory
\n
"
);
exit
(
1
);
}
memset
(
type_rules
,
0
,
sizeof
(
struct
avtab_node
)
*
policydb
->
p_types
.
nprim
);
if
(
avtab_init
(
&
exp_avtab
)
||
avtab_init
(
&
exp_cond_avtab
))
{
fputs
(
"out of memory
\n
"
,
stderr
);
return
-
1
;
}
if
(
expand_avtab
(
policydb
,
&
policydb
->
te_avtab
,
&
exp_avtab
))
{
fputs
(
"out of memory
\n
"
,
stderr
);
avtab_destroy
(
&
exp_avtab
);
return
-
1
;
}
if
(
expand_avtab
(
policydb
,
&
policydb
->
te_cond_avtab
,
&
exp_cond_avtab
))
{
fputs
(
"out of memory
\n
"
,
stderr
);
avtab_destroy
(
&
exp_avtab
);
return
-
1
;
}
if
(
avtab_map
(
&
exp_avtab
,
create_type_rules
,
type_rules
))
exit
(
1
);
if
(
avtab_map
(
&
exp_cond_avtab
,
create_type_rules_cond
,
type_rules
))
exit
(
1
);
avtab_destroy
(
&
exp_avtab
);
avtab_destroy
(
&
exp_cond_avtab
);
/*
* Compare the type lists and identify similar types.
*/
for
(
i
=
0
;
i
<
policydb
->
p_types
.
nprim
-
1
;
i
++
)
{
if
(
!
type_rules
[
i
].
next
)
continue
;
type
=
policydb
->
type_val_to_struct
[
i
];
if
(
type
->
flavor
)
{
free_type_rules
(
type_rules
[
i
].
next
);
type_rules
[
i
].
next
=
NULL
;
continue
;
}
for
(
j
=
i
+
1
;
j
<
policydb
->
p_types
.
nprim
;
j
++
)
{
type
=
policydb
->
type_val_to_struct
[
j
];
if
(
type
->
flavor
)
{
free_type_rules
(
type_rules
[
j
].
next
);
type_rules
[
j
].
next
=
NULL
;
continue
;
}
for
(
l1
=
type_rules
[
i
].
next
,
l2
=
type_rules
[
j
].
next
;
l1
&&
l2
;
l1
=
l1
->
next
,
l2
=
l2
->
next
)
{
if
(
l1
->
key
.
source_type
!=
l2
->
key
.
source_type
)
break
;
if
(
l1
->
key
.
target_type
!=
l2
->
key
.
target_type
)
break
;
if
(
l1
->
key
.
target_class
!=
l2
->
key
.
target_class
||
l1
->
datum
.
data
!=
l2
->
datum
.
data
)
break
;
}
if
(
l1
||
l2
)
{
if
(
diff
)
{
printf
(
"Types %s and %s differ, starting with:
\n
"
,
policydb
->
p_type_val_to_name
[
i
],
policydb
->
p_type_val_to_name
[
j
]);
if
(
l1
&&
l2
)
{
if
(
find_match
(
policydb
,
l1
,
i
,
l2
,
j
))
continue
;
if
(
find_match
(
policydb
,
l2
,
j
,
l1
,
i
))
continue
;
}
if
(
l1
)
display_allow
(
policydb
,
&
l1
->
key
,
i
,
l1
->
datum
.
data
);
if
(
l2
)
display_allow
(
policydb
,
&
l2
->
key
,
j
,
l2
->
datum
.
data
);
printf
(
"
\n
"
);
}
continue
;
}
free_type_rules
(
type_rules
[
j
].
next
);
type_rules
[
j
].
next
=
NULL
;
if
(
equiv
)
{
printf
(
"Types %s and %s are equivalent.
\n
"
,
policydb
->
p_type_val_to_name
[
i
],
policydb
->
p_type_val_to_name
[
j
]);
}
}
free_type_rules
(
type_rules
[
i
].
next
);
type_rules
[
i
].
next
=
NULL
;
}
free
(
type_rules
);
return
0
;
}
static
int
find_dups_helper
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
policydb_t
*
policydb
=
args
;
ebitmap_t
*
sattr
,
*
tattr
;
ebitmap_node_t
*
snode
,
*
tnode
;
unsigned
int
i
,
j
;
avtab_key_t
avkey
;
avtab_ptr_t
node
;
struct
type_datum
*
stype
,
*
ttype
,
*
stype2
,
*
ttype2
;
bool
attrib1
,
attrib2
;
if
(
!
(
k
->
specified
&
AVTAB_ALLOWED
))
return
0
;
if
(
k
->
source_type
==
k
->
target_type
)
return
0
;
/* self rule */
avkey
.
target_class
=
k
->
target_class
;
avkey
.
specified
=
k
->
specified
;
sattr
=
&
policydb
->
type_attr_map
[
k
->
source_type
-
1
];
tattr
=
&
policydb
->
type_attr_map
[
k
->
target_type
-
1
];
stype
=
policydb
->
type_val_to_struct
[
k
->
source_type
-
1
];
ttype
=
policydb
->
type_val_to_struct
[
k
->
target_type
-
1
];
attrib1
=
stype
->
flavor
||
ttype
->
flavor
;
ebitmap_for_each_bit
(
sattr
,
snode
,
i
)
{
if
(
!
ebitmap_node_get_bit
(
snode
,
i
))
continue
;
ebitmap_for_each_bit
(
tattr
,
tnode
,
j
)
{
if
(
!
ebitmap_node_get_bit
(
tnode
,
j
))
continue
;
avkey
.
source_type
=
i
+
1
;
avkey
.
target_type
=
j
+
1
;
if
(
avkey
.
source_type
==
k
->
source_type
&&
avkey
.
target_type
==
k
->
target_type
)
continue
;
if
(
avkey
.
source_type
==
avkey
.
target_type
)
continue
;
/* self rule */
stype2
=
policydb
->
type_val_to_struct
[
avkey
.
source_type
-
1
];
ttype2
=
policydb
->
type_val_to_struct
[
avkey
.
target_type
-
1
];
attrib2
=
stype2
->
flavor
||
ttype2
->
flavor
;
if
(
attrib1
&&
attrib2
)
continue
;
/* overlapping attribute-based rules */
for
(
node
=
avtab_search_node
(
&
policydb
->
te_avtab
,
&
avkey
);
node
!=
NULL
;
node
=
avtab_search_node_next
(
node
,
avkey
.
specified
))
{
uint32_t
perms
=
node
->
datum
.
data
&
d
->
data
;
if
((
attrib1
&&
perms
==
node
->
datum
.
data
)
||
(
attrib2
&&
perms
==
d
->
data
))
{
/*
* The attribute-based rule is a superset of the
* non-attribute-based rule. This is a dup.
*/
printf
(
"Duplicate allow rule found:
\n
"
);
display_allow
(
policydb
,
k
,
i
,
d
->
data
);
display_allow
(
policydb
,
&
node
->
key
,
i
,
node
->
datum
.
data
);
printf
(
"
\n
"
);
}
}
}
}
return
0
;
}
static
int
find_dups
(
policydb_t
*
policydb
)
{
if
(
avtab_map
(
&
policydb
->
te_avtab
,
find_dups_helper
,
policydb
))
return
-
1
;
return
0
;
}
static
int
list_permissive
(
policydb_t
*
policydb
)
{
struct
ebitmap_node
*
n
;
unsigned
int
bit
;
/*
* iterate over all domains and check if domain is in permissive
*/
ebitmap_for_each_bit
(
&
policydb
->
permissive_map
,
n
,
bit
)
{
if
(
ebitmap_node_get_bit
(
n
,
bit
))
{
printf
(
"%s
\n
"
,
policydb
->
p_type_val_to_name
[
bit
-
1
]);
}
}
return
0
;
void
neverallow_usage
()
{
fprintf
(
stderr
,
"
\t
neverallow [-w|--warn] [-d|--debug] [-n|--neverallows <neverallow-rules>] | [-f|--file <neverallow-file>]
\n
"
);
}
static
int
read_typeset
(
policydb_t
*
policydb
,
char
**
ptr
,
char
*
end
,
...
...
@@ -779,34 +367,12 @@ err:
return
-
1
;
}
static
int
check_neverallows
(
policydb_t
*
policydb
,
c
onst
char
*
filename
)
static
int
check_neverallows
(
policydb_t
*
policydb
,
c
har
*
text
,
char
*
end
)
{
const
char
*
keyword
=
"neverallow"
;
size_t
keyword_size
=
strlen
(
keyword
),
len
;
struct
avrule
*
neverallows
=
NULL
,
*
avrule
;
int
fd
;
struct
stat
sb
;
char
*
text
,
*
end
,
*
start
;
char
*
p
;
fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
<
0
)
{
fprintf
(
stderr
,
"Could not open %s: %s
\n
"
,
filename
,
strerror
(
errno
));
return
-
1
;
}
if
(
fstat
(
fd
,
&
sb
)
<
0
)
{
fprintf
(
stderr
,
"Can't stat '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
-
1
;
}
text
=
mmap
(
NULL
,
sb
.
st_size
,
PROT_READ
,
MAP_PRIVATE
,
fd
,
0
);
end
=
text
+
sb
.
st_size
;
if
(
text
==
MAP_FAILED
)
{
fprintf
(
stderr
,
"Can't mmap '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
-
1
;
}
close
(
fd
);
char
*
p
,
*
start
;
p
=
text
;
while
(
p
<
end
)
{
...
...
@@ -858,86 +424,92 @@ static int check_neverallows(policydb_t *policydb, const char *filename)
neverallows
=
avrule
;
}
if
(
!
neverallows
)
goto
err
;
return
check_assertions
(
NULL
,
policydb
,
neverallows
);
err:
if
(
errno
==
ENOMEM
)
{
fprintf
(
stderr
,
"Out of memory while parsing
%s
\n
"
,
filename
);
fprintf
(
stderr
,
"Out of memory while parsing
neverallow rules
\n
"
);
}
else
fprintf
(
stderr
,
"Error while parsing
%s
\n
"
,
filename
);
fprintf
(
stderr
,
"Error while parsing
neverallow rules
\n
"
);
return
-
1
;
}
int
main
(
int
argc
,
char
**
argv
)
static
int
check_neverallows_file
(
policydb_t
*
policydb
,
const
char
*
filename
)
{
int
fd
;
struct
stat
sb
;
char
*
text
,
*
end
;
fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
<
0
)
{
fprintf
(
stderr
,
"Could not open %s: %s
\n
"
,
filename
,
strerror
(
errno
));
return
-
1
;
}
if
(
fstat
(
fd
,
&
sb
)
<
0
)
{
fprintf
(
stderr
,
"Can't stat '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
-
1
;
}
text
=
mmap
(
NULL
,
sb
.
st_size
,
PROT_READ
,
MAP_PRIVATE
,
fd
,
0
);
end
=
text
+
sb
.
st_size
;
if
(
text
==
MAP_FAILED
)
{
fprintf
(
stderr
,
"Can't mmap '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
-
1
;
}
close
(
fd
);
return
check_neverallows
(
policydb
,
text
,
end
);
}
static
int
check_neverallows_string
(
policydb_t
*
policydb
,
char
*
string
,
size_t
len
)
{
char
*
policy
=
NULL
,
*
neverallows
=
NULL
;
struct
policy_file
pf
;
policydb_t
policydb
;
char
*
text
,
*
end
;
text
=
string
;
end
=
text
+
len
;
return
check_neverallows
(
policydb
,
text
,
end
);
}
int
neverallow_func
(
int
argc
,
char
**
argv
,
policydb_t
*
policydb
)
{
char
*
rules
=
0
,
*
file
=
0
;
char
ch
;
char
equiv
=
0
,
diff
=
0
,
dups
=
0
,
permissive
=
0
;
int
rc
=
0
;
struct
option
long_options
[]
=
{
{
"equiv"
,
no_argument
,
NULL
,
'e'
},
{
"debug"
,
no_argument
,
NULL
,
'z'
},
{
"diff"
,
no_argument
,
NULL
,
'd'
},
{
"dups"
,
no_argument
,
NULL
,
'D'
},
struct
option
neverallow_options
[]
=
{
{
"debug"
,
no_argument
,
NULL
,
'd'
},
{
"file_input"
,
required_argument
,
NULL
,
'f'
},
{
"neverallow"
,
required_argument
,
NULL
,
'n'
},
{
"permissive"
,
no_argument
,
NULL
,
'p'
},
{
"policy"
,
required_argument
,
NULL
,
'P'
},
{
"warn"
,
no_argument
,
NULL
,
'w'
},
{
NULL
,
0
,
NULL
,
0
}
};
while
((
ch
=
getopt_long
(
argc
,
argv
,
"
edDpn:P:wz"
,
long
_options
,
NULL
))
!=
-
1
)
{
while
((
ch
=
getopt_long
(
argc
,
argv
,
"
df:n:w"
,
neverallow
_options
,
NULL
))
!=
-
1
)
{
switch
(
ch
)
{
case
'e'
:
equiv
=
1
;
break
;
case
'd'
:
d
iff
=
1
;
d
ebug
=
1
;
break
;
case
'
D
'
:
dups
=
1
;
case
'
f
'
:
file
=
optarg
;
break
;
case
'n'
:
neverallows
=
optarg
;
break
;
case
'p'
:
permissive
=
1
;
break
;
case
'P'
:
policy
=
optarg
;
rules
=
optarg
;
break
;
case
'w'
:
warn
=
1
;
break
;
case
'z'
:
debug
=
1
;
break
;
default:
usage
(
argv
[
0
]);
USAGE_ERROR
=
true
;
return
-
1
;
}
}
if
(
!
policy
||
(
!
equiv
&&
!
diff
&&
!
dups
&&
!
permissive
&&
!
neverallows
))
usage
(
argv
[
0
]);
if
(
load_policy
(
policy
,
&
policydb
,
&
pf
))
exit
(
1
);
if
(
equiv
||
diff
)
analyze_types
(
&
policydb
,
equiv
,
diff
);
if
(
dups
)
find_dups
(
&
policydb
);
if
(
permissive
)
list_permissive
(
&
policydb
);
if
(
neverallows
)
rc
|=
check_neverallows
(
&
policydb
,
neverallows
);
policydb_destroy
(
&
policydb
);
return
rc
;
if
(
!
(
rules
||
file
)
||
(
rules
&&
file
)){
USAGE_ERROR
=
true
;
return
-
1
;
}
if
(
file
)
{
return
check_neverallows_file
(
policydb
,
file
);
}
else
{
return
check_neverallows_string
(
policydb
,
rules
,
strlen
(
rules
));
}
}
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/neverallow.h
0 → 100644
View file @
bdc8c77a
#ifndef NEVERALLOW_H
#define NEVERALLOW_H
#include <sepol/policydb/policydb.h>
#include "utils.h"
void
neverallow_usage
(
void
);
int
neverallow_func
(
int
argc
,
char
**
argv
,
policydb_t
*
policydb
);
#endif
/* NEVERALLOW_H */
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/perm.c
0 → 100644
View file @
bdc8c77a
#include "perm.h"
void
permissive_usage
()
{
fprintf
(
stderr
,
"
\t
permissive
\n
"
);
}
static
int
list_permissive
(
policydb_t
*
policydb
)
{
struct
ebitmap_node
*
n
;
unsigned
int
bit
;
/*
* iterate over all domains and check if domain is in permissive
*/
ebitmap_for_each_bit
(
&
policydb
->
permissive_map
,
n
,
bit
)
{
if
(
ebitmap_node_get_bit
(
n
,
bit
))
{
printf
(
"%s
\n
"
,
policydb
->
p_type_val_to_name
[
bit
-
1
]);
}
}
return
0
;
}
int
permissive_func
(
int
argc
,
__attribute__
((
unused
))
char
**
argv
,
policydb_t
*
policydb
)
{
if
(
argc
!=
1
)
{
USAGE_ERROR
=
true
;
return
-
1
;
}
return
list_permissive
(
policydb
);
}
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/perm.h
0 → 100644
View file @
bdc8c77a
#ifndef PERM_H
#define PERM_H
#include <sepol/policydb/policydb.h>
#include "utils.h"
void
permissive_usage
(
void
);
int
permissive_func
(
int
argc
,
char
**
argv
,
policydb_t
*
policydb
);
#endif
/* PERM_H */
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/sepolicy-analyze.c
0 → 100644
View file @
bdc8c77a
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "dups.h"
#include "neverallow.h"
#include "perm.h"
#include "typecmp.h"
#include "utils.h"
#define NUM_COMPONENTS (int) (sizeof(analyze_components)/sizeof(analyze_components[0]))
#define COMP(x) { #x, sizeof(#x) - 1, x ##_usage, x ##_func }
static
struct
{
const
char
*
key
;
size_t
keylen
;
void
(
*
usage
)
(
void
);
int
(
*
func
)
(
int
argc
,
char
**
argv
,
policydb_t
*
policydb
);
}
analyze_components
[]
=
{
COMP
(
dups
),
COMP
(
neverallow
),
COMP
(
permissive
),
COMP
(
typecmp
)
};
void
usage
(
char
*
arg0
)
{
fprintf
(
stderr
,
"%s must be called on a policy file with a component and the appropriate arguments specified
\n
"
,
arg0
);
fprintf
(
stderr
,
"%s <policy-file>:
\n
"
,
arg0
);
for
(
int
i
=
0
;
i
<
NUM_COMPONENTS
;
i
++
)
{
analyze_components
[
i
].
usage
();
}
exit
(
1
);
}
int
main
(
int
argc
,
char
**
argv
)
{
char
*
policy
;
struct
policy_file
pf
;
policydb_t
policydb
;
int
rc
;
if
(
argc
<
3
)
usage
(
argv
[
0
]);
policy
=
argv
[
1
];
if
(
load_policy
(
policy
,
&
policydb
,
&
pf
))
exit
(
1
);
for
(
int
i
=
0
;
i
<
NUM_COMPONENTS
;
i
++
)
{
if
(
!
strcmp
(
analyze_components
[
i
].
key
,
argv
[
2
]))
{
rc
=
analyze_components
[
i
].
func
(
argc
-
2
,
argv
+
2
,
&
policydb
);
if
(
rc
&&
USAGE_ERROR
)
{
usage
(
argv
[
0
]);
}
return
rc
;
}
}
usage
(
argv
[
0
]);
}
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/typecmp.c
0 → 100644
View file @
bdc8c77a
#include <getopt.h>
#include <sepol/policydb/expand.h>
#include "typecmp.h"
void
typecmp_usage
()
{
fprintf
(
stderr
,
"
\t
typecmp [-d|--diff] [-e|--equiv]
\n
"
);
}
static
int
insert_type_rule
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
struct
avtab_node
*
type_rules
)
{
struct
avtab_node
*
p
,
*
c
,
*
n
;
for
(
p
=
type_rules
,
c
=
type_rules
->
next
;
c
;
p
=
c
,
c
=
c
->
next
)
{
/*
* Find the insertion point, keeping the list
* ordered by source type, then target type, then
* target class.
*/
if
(
k
->
source_type
<
c
->
key
.
source_type
)
break
;
if
(
k
->
source_type
==
c
->
key
.
source_type
&&
k
->
target_type
<
c
->
key
.
target_type
)
break
;
if
(
k
->
source_type
==
c
->
key
.
source_type
&&
k
->
target_type
==
c
->
key
.
target_type
&&
k
->
target_class
<=
c
->
key
.
target_class
)
break
;
}
if
(
c
&&
k
->
source_type
==
c
->
key
.
source_type
&&
k
->
target_type
==
c
->
key
.
target_type
&&
k
->
target_class
==
c
->
key
.
target_class
)
{
c
->
datum
.
data
|=
d
->
data
;
return
0
;
}
/* Insert the rule */
n
=
malloc
(
sizeof
(
struct
avtab_node
));
if
(
!
n
)
{
fprintf
(
stderr
,
"out of memory
\n
"
);
exit
(
1
);
}
n
->
key
=
*
k
;
n
->
datum
=
*
d
;
n
->
next
=
p
->
next
;
p
->
next
=
n
;
return
0
;
}
static
int
create_type_rules_helper
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
struct
avtab_node
*
type_rules
=
args
;
avtab_key_t
key
;
/*
* Insert the rule into the list for
* the source type. The source type value
* is cleared as we want to compare against other type
* rules with different source types.
*/
key
=
*
k
;
key
.
source_type
=
0
;
if
(
k
->
source_type
==
k
->
target_type
)
{
/* Clear target type as well; this is a self rule. */
key
.
target_type
=
0
;
}
if
(
insert_type_rule
(
&
key
,
d
,
&
type_rules
[
k
->
source_type
-
1
]))
return
-
1
;
if
(
k
->
source_type
==
k
->
target_type
)
return
0
;
/*
* If the target type differs, then we also
* insert the rule into the list for the target
* type. We clear the target type value so that
* we can compare against other type rules with
* different target types.
*/
key
=
*
k
;
key
.
target_type
=
0
;
if
(
insert_type_rule
(
&
key
,
d
,
&
type_rules
[
k
->
target_type
-
1
]))
return
-
1
;
return
0
;
}
static
int
create_type_rules
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
if
(
k
->
specified
&
AVTAB_ALLOWED
)
return
create_type_rules_helper
(
k
,
d
,
args
);
return
0
;
}
static
int
create_type_rules_cond
(
avtab_key_t
*
k
,
avtab_datum_t
*
d
,
void
*
args
)
{
if
((
k
->
specified
&
(
AVTAB_ALLOWED
|
AVTAB_ENABLED
))
==
(
AVTAB_ALLOWED
|
AVTAB_ENABLED
))
return
create_type_rules_helper
(
k
,
d
,
args
);
return
0
;
}
static
void
free_type_rules
(
struct
avtab_node
*
l
)
{
struct
avtab_node
*
tmp
;
while
(
l
)
{
tmp
=
l
;
l
=
l
->
next
;
free
(
tmp
);
}
}
static
int
find_match
(
policydb_t
*
policydb
,
struct
avtab_node
*
l1
,
int
idx1
,
struct
avtab_node
*
l2
,
int
idx2
)
{
struct
avtab_node
*
c
;
uint32_t
perms1
,
perms2
;
for
(
c
=
l2
;
c
;
c
=
c
->
next
)
{
if
(
l1
->
key
.
source_type
<
c
->
key
.
source_type
)
break
;
if
(
l1
->
key
.
source_type
==
c
->
key
.
source_type
&&
l1
->
key
.
target_type
<
c
->
key
.
target_type
)
break
;
if
(
l1
->
key
.
source_type
==
c
->
key
.
source_type
&&
l1
->
key
.
target_type
==
c
->
key
.
target_type
&&
l1
->
key
.
target_class
<=
c
->
key
.
target_class
)
break
;
}
if
(
c
&&
l1
->
key
.
source_type
==
c
->
key
.
source_type
&&
l1
->
key
.
target_type
==
c
->
key
.
target_type
&&
l1
->
key
.
target_class
==
c
->
key
.
target_class
)
{
perms1
=
l1
->
datum
.
data
&
~
c
->
datum
.
data
;
perms2
=
c
->
datum
.
data
&
~
l1
->
datum
.
data
;
if
(
perms1
||
perms2
)
{
if
(
perms1
)
display_allow
(
policydb
,
&
l1
->
key
,
idx1
,
perms1
);
if
(
perms2
)
display_allow
(
policydb
,
&
c
->
key
,
idx2
,
perms2
);
printf
(
"
\n
"
);
return
1
;
}
}
return
0
;
}
static
int
analyze_types
(
policydb_t
*
policydb
,
char
diff
,
char
equiv
)
{
avtab_t
exp_avtab
,
exp_cond_avtab
;
struct
avtab_node
*
type_rules
,
*
l1
,
*
l2
;
struct
type_datum
*
type
;
size_t
i
,
j
;
/*
* Create a list of access vector rules for each type
* from the access vector table.
*/
type_rules
=
malloc
(
sizeof
(
struct
avtab_node
)
*
policydb
->
p_types
.
nprim
);
if
(
!
type_rules
)
{
fprintf
(
stderr
,
"out of memory
\n
"
);
exit
(
1
);
}
memset
(
type_rules
,
0
,
sizeof
(
struct
avtab_node
)
*
policydb
->
p_types
.
nprim
);
if
(
avtab_init
(
&
exp_avtab
)
||
avtab_init
(
&
exp_cond_avtab
))
{
fputs
(
"out of memory
\n
"
,
stderr
);
return
-
1
;
}
if
(
expand_avtab
(
policydb
,
&
policydb
->
te_avtab
,
&
exp_avtab
))
{
fputs
(
"out of memory
\n
"
,
stderr
);
avtab_destroy
(
&
exp_avtab
);
return
-
1
;
}
if
(
expand_avtab
(
policydb
,
&
policydb
->
te_cond_avtab
,
&
exp_cond_avtab
))
{
fputs
(
"out of memory
\n
"
,
stderr
);
avtab_destroy
(
&
exp_avtab
);
/* */
return
-
1
;
}
if
(
avtab_map
(
&
exp_avtab
,
create_type_rules
,
type_rules
))
exit
(
1
);
if
(
avtab_map
(
&
exp_cond_avtab
,
create_type_rules_cond
,
type_rules
))
exit
(
1
);
avtab_destroy
(
&
exp_avtab
);
avtab_destroy
(
&
exp_cond_avtab
);
/*
* Compare the type lists and identify similar types.
*/
for
(
i
=
0
;
i
<
policydb
->
p_types
.
nprim
-
1
;
i
++
)
{
if
(
!
type_rules
[
i
].
next
)
continue
;
type
=
policydb
->
type_val_to_struct
[
i
];
if
(
type
->
flavor
)
{
free_type_rules
(
type_rules
[
i
].
next
);
type_rules
[
i
].
next
=
NULL
;
continue
;
}
for
(
j
=
i
+
1
;
j
<
policydb
->
p_types
.
nprim
;
j
++
)
{
type
=
policydb
->
type_val_to_struct
[
j
];
if
(
type
->
flavor
)
{
free_type_rules
(
type_rules
[
j
].
next
);
type_rules
[
j
].
next
=
NULL
;
continue
;
}
for
(
l1
=
type_rules
[
i
].
next
,
l2
=
type_rules
[
j
].
next
;
l1
&&
l2
;
l1
=
l1
->
next
,
l2
=
l2
->
next
)
{
if
(
l1
->
key
.
source_type
!=
l2
->
key
.
source_type
)
break
;
if
(
l1
->
key
.
target_type
!=
l2
->
key
.
target_type
)
break
;
if
(
l1
->
key
.
target_class
!=
l2
->
key
.
target_class
||
l1
->
datum
.
data
!=
l2
->
datum
.
data
)
break
;
}
if
(
l1
||
l2
)
{
if
(
diff
)
{
printf
(
"Types %s and %s differ, starting with:
\n
"
,
policydb
->
p_type_val_to_name
[
i
],
policydb
->
p_type_val_to_name
[
j
]);
if
(
l1
&&
l2
)
{
if
(
find_match
(
policydb
,
l1
,
i
,
l2
,
j
))
continue
;
if
(
find_match
(
policydb
,
l2
,
j
,
l1
,
i
))
continue
;
}
if
(
l1
)
display_allow
(
policydb
,
&
l1
->
key
,
i
,
l1
->
datum
.
data
);
if
(
l2
)
display_allow
(
policydb
,
&
l2
->
key
,
j
,
l2
->
datum
.
data
);
printf
(
"
\n
"
);
}
continue
;
}
free_type_rules
(
type_rules
[
j
].
next
);
type_rules
[
j
].
next
=
NULL
;
if
(
equiv
)
{
printf
(
"Types %s and %s are equivalent.
\n
"
,
policydb
->
p_type_val_to_name
[
i
],
policydb
->
p_type_val_to_name
[
j
]);
}
}
free_type_rules
(
type_rules
[
i
].
next
);
type_rules
[
i
].
next
=
NULL
;
}
free
(
type_rules
);
return
0
;
}
int
typecmp_func
(
int
argc
,
char
**
argv
,
policydb_t
*
policydb
)
{
char
ch
,
diff
=
0
,
equiv
=
0
;
struct
option
typecmp_options
[]
=
{
{
"diff"
,
no_argument
,
NULL
,
'd'
},
{
"equiv"
,
no_argument
,
NULL
,
'e'
},
{
NULL
,
0
,
NULL
,
0
}
};
while
((
ch
=
getopt_long
(
argc
,
argv
,
"de"
,
typecmp_options
,
NULL
))
!=
-
1
)
{
switch
(
ch
)
{
case
'd'
:
diff
=
1
;
break
;
case
'e'
:
equiv
=
1
;
break
;
default:
USAGE_ERROR
=
true
;
return
-
1
;
}
}
if
(
!
(
diff
||
equiv
))
{
USAGE_ERROR
=
true
;
return
-
1
;
}
return
analyze_types
(
policydb
,
diff
,
equiv
);
}
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/typecmp.h
0 → 100644
View file @
bdc8c77a
#ifndef TYPECMP_H
#define TYPECMP_H
#include <sepol/policydb/policydb.h>
#include "utils.h"
void
typecmp_usage
(
void
);
int
typecmp_func
(
int
argc
,
char
**
argv
,
policydb_t
*
policydb
);
#endif
/* TYPECMP_H */
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/utils.c
0 → 100644
View file @
bdc8c77a
#include <fcntl.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/util.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "utils.h"
bool
USAGE_ERROR
=
false
;
void
display_allow
(
policydb_t
*
policydb
,
avtab_key_t
*
key
,
int
idx
,
uint32_t
perms
)
{
printf
(
" allow %s %s:%s { %s };
\n
"
,
policydb
->
p_type_val_to_name
[
key
->
source_type
?
key
->
source_type
-
1
:
idx
],
key
->
target_type
==
key
->
source_type
?
"self"
:
policydb
->
p_type_val_to_name
[
key
->
target_type
?
key
->
target_type
-
1
:
idx
],
policydb
->
p_class_val_to_name
[
key
->
target_class
-
1
],
sepol_av_to_string
(
policydb
,
key
->
target_class
,
perms
));
}
int
load_policy
(
char
*
filename
,
policydb_t
*
policydb
,
struct
policy_file
*
pf
)
{
int
fd
;
struct
stat
sb
;
void
*
map
;
int
ret
;
fd
=
open
(
filename
,
O_RDONLY
);
if
(
fd
<
0
)
{
fprintf
(
stderr
,
"Can't open '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
return
1
;
}
if
(
fstat
(
fd
,
&
sb
)
<
0
)
{
fprintf
(
stderr
,
"Can't stat '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
1
;
}
map
=
mmap
(
NULL
,
sb
.
st_size
,
PROT_READ
|
PROT_WRITE
,
MAP_PRIVATE
,
fd
,
0
);
if
(
map
==
MAP_FAILED
)
{
fprintf
(
stderr
,
"Can't mmap '%s': %s
\n
"
,
filename
,
strerror
(
errno
));
close
(
fd
);
return
1
;
}
policy_file_init
(
pf
);
pf
->
type
=
PF_USE_MEMORY
;
pf
->
data
=
map
;
pf
->
len
=
sb
.
st_size
;
if
(
policydb_init
(
policydb
))
{
fprintf
(
stderr
,
"Could not initialize policydb!
\n
"
);
close
(
fd
);
munmap
(
map
,
sb
.
st_size
);
return
1
;
}
ret
=
policydb_read
(
policydb
,
pf
,
0
);
if
(
ret
)
{
fprintf
(
stderr
,
"error(s) encountered while parsing configuration
\n
"
);
close
(
fd
);
munmap
(
map
,
sb
.
st_size
);
return
1
;
}
return
0
;
}
This diff is collapsed.
Click to expand it.
tools/sepolicy-analyze/utils.h
0 → 100644
View file @
bdc8c77a
#ifndef UTILS_H
#define UTILS_H
#include <stdbool.h>
#include <stdint.h>
#include <sepol/policydb/avtab.h>
#include <sepol/policydb/policydb.h>
extern
bool
USAGE_ERROR
;
void
display_allow
(
policydb_t
*
policydb
,
avtab_key_t
*
key
,
int
idx
,
uint32_t
perms
);
int
load_policy
(
char
*
filename
,
policydb_t
*
policydb
,
struct
policy_file
*
pf
);
#endif
/* UTILS_H */
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment