Merge remote-tracking branch 'aosp/upstream-master' into mymerge

Bug: 69566734
Bug: 68133473
Test: build and boot aosp_marlin
Test: sepolicy-analyze <aosp_taimen policy> attributes -l
    Verify socket_between_core_and_vendor_violators is still in policy
Change-Id: Id77bfc049e74cc7041a9876b06347b08fa5eeaf8
This commit is contained in:
Jeff Vander Stoep 2017-11-22 09:31:25 -08:00 committed by Jeffrey Vander Stoep
commit 68ea5ce1fe
20 changed files with 105 additions and 642 deletions

View File

@ -64,10 +64,10 @@ addons:
install:
# Download refpolicy Makefile for sepolgen tests
- sudo mkdir -p /usr/share/selinux/default
- sudo curl -o /usr/share/selinux/default/Makefile 'https://raw.githubusercontent.com/TresysTechnology/refpolicy/RELEASE_2_20170204/support/Makefile.devel'
- sudo curl --retry 10 -o /usr/share/selinux/default/Makefile 'https://raw.githubusercontent.com/TresysTechnology/refpolicy/RELEASE_2_20170204/support/Makefile.devel'
- sudo sed "s,^PREFIX :=.*,PREFIX := $TRAVIS_BUILD_DIR/installdir/usr," -i /usr/share/selinux/default/Makefile
- sudo mkdir -p /usr/share/selinux/refpolicy/include
- sudo curl -o /usr/share/selinux/refpolicy/include/build.conf 'https://raw.githubusercontent.com/TresysTechnology/refpolicy/RELEASE_2_20170204/build.conf'
- sudo curl --retry 10 -o /usr/share/selinux/refpolicy/include/build.conf 'https://raw.githubusercontent.com/TresysTechnology/refpolicy/RELEASE_2_20170204/build.conf'
- sudo mkdir -p /etc/selinux
- echo 'SELINUXTYPE=refpolicy' | sudo tee /etc/selinux/config
@ -77,7 +77,7 @@ install:
# Download the required python version if it is not installed
- VIRTUAL_ENV="$HOME/virtualenv/$PYVER"
- if ! [ -d "$VIRTUAL_ENV" ] ; then
curl -o python.tar.bz2 "https://s3.amazonaws.com/travis-python-archives/binaries/ubuntu/14.04/x86_64/${PYVER/python/python-}.tar.bz2" &&
curl --retry 10 -o python.tar.bz2 "https://s3.amazonaws.com/travis-python-archives/binaries/ubuntu/14.04/x86_64/${PYVER/python/python-}.tar.bz2" &&
sudo tar xjf python.tar.bz2 --directory / &&
rm python.tar.bz2 ;
fi

View File

@ -21,13 +21,14 @@ export DISABLE_SETRANS DISABLE_RPM DISABLE_FLAGS ANDROID_HOST
USE_PCRE2 ?= n
ifeq ($(USE_PCRE2),y)
PCRE_CFLAGS := -DUSE_PCRE2 -DPCRE2_CODE_UNIT_WIDTH=8 $(shell $(PKG_CONFIG) --cflags libpcre2-8)
PCRE_LDLIBS := $(shell $(PKG_CONFIG) --libs libpcre2-8)
PCRE_MODULE := libpcre2-8
PCRE_CFLAGS := -DUSE_PCRE2 -DPCRE2_CODE_UNIT_WIDTH=8
else
PCRE_CFLAGS := $(shell $(PKG_CONFIG) --cflags libpcre)
PCRE_LDLIBS := $(shell $(PKG_CONFIG) --libs libpcre)
PCRE_MODULE := libpcre
endif
export PCRE_CFLAGS PCRE_LDLIBS
PCRE_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(PCRE_MODULE))
PCRE_LDLIBS := $(shell $(PKG_CONFIG) --libs $(PCRE_MODULE))
export PCRE_MODULE PCRE_CFLAGS PCRE_LDLIBS
OS := $(shell uname)
export OS

View File

@ -148,7 +148,7 @@ $(LIBSO): $(LOBJS)
ln -sf $@ $(TARGET)
$(LIBPC): $(LIBPC).in ../VERSION
sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBBASE):; s:@includedir@:$(INCLUDEDIR):' < $< > $@
sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBBASE):; s:@includedir@:$(INCLUDEDIR):; s:@PCRE_MODULE@:$(PCRE_MODULE):' < $< > $@
selinuxswig_python_exception.i: ../include/selinux/selinux.h
bash -e exception.sh > $@ || (rm -f $@ ; false)

View File

@ -7,6 +7,6 @@ Name: libselinux
Description: SELinux utility library
Version: @VERSION@
URL: http://userspace.selinuxproject.org/
Requires.private: libsepol libpcre
Requires.private: libsepol @PCRE_MODULE@
Libs: -L${libdir} -lselinux
Cflags: -I${includedir}

View File

@ -1385,7 +1385,9 @@ done:
if (out != NULL)
fclose(out);
pop_user_entry(&(s.fallback));
while (s.fallback)
pop_user_entry(&(s.fallback));
ignore_free();
return retval;

View File

@ -2064,6 +2064,7 @@ void cil_typeattribute_init(struct cil_typeattribute **attr)
(*attr)->expr_list = NULL;
(*attr)->types = NULL;
(*attr)->used = CIL_FALSE;
(*attr)->keep = CIL_FALSE;
}
void cil_typeattributeset_init(struct cil_typeattributeset **attrset)

View File

@ -567,7 +567,7 @@ int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil
char *key = NULL;
type_datum_t *sepol_attr = NULL;
if (!cil_attr->used) {
if (!cil_attr->keep) {
return SEPOL_OK;
}
@ -632,7 +632,7 @@ int cil_typeattribute_to_bitmap(policydb_t *pdb, const struct cil_db *db, struct
ebitmap_node_t *tnode;
unsigned int i;
if (!cil_attr->used) {
if (!cil_attr->keep) {
return SEPOL_OK;
}
@ -1442,7 +1442,7 @@ static int __cil_should_expand_attribute( const struct cil_db *db, struct cil_sy
attr = (struct cil_typeattribute *)datum;
return !attr->used || (ebitmap_cardinality(attr->types) < db->attrs_expand_size);
return !attr->keep || (ebitmap_cardinality(attr->types) < db->attrs_expand_size);
}
int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule, cond_node_t *cond_node, enum cil_flavor cond_flavor)
@ -2525,7 +2525,7 @@ int __cil_constrain_expr_datum_to_sepol_expr(policydb_t *pdb, const struct cil_d
if (rc != SEPOL_OK) {
if (FLAVOR(item->data) == CIL_TYPEATTRIBUTE) {
struct cil_typeattribute *attr = item->data;
if (!attr->used) {
if (!attr->keep) {
rc = 0;
}
}

View File

@ -531,6 +531,7 @@ struct cil_typeattribute {
struct cil_list *expr_list;
ebitmap_t *types;
int used; // whether or not this attribute was used in a binary policy rule
int keep;
};
struct cil_typeattributeset {

View File

@ -1085,7 +1085,7 @@ static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, stru
type = i1->data;
cil_list_for_each(i2, attributes) {
attribute = i2->data;
if (!attribute->used)
if (!attribute->keep)
continue;
if (ebitmap_get_bit(attribute->types, type->value)) {
if (first) {

View File

@ -1369,7 +1369,7 @@ static int __cil_post_db_attr_helper(struct cil_tree_node *node, uint32_t *finis
rc = __evaluate_type_expression(attr, db);
if (rc != SEPOL_OK) goto exit;
}
attr->used = cil_typeattribute_used(attr, db);
attr->keep = cil_typeattribute_used(attr, db);
break;
}
case CIL_ROLEATTRIBUTE: {

View File

@ -186,6 +186,7 @@ static void cil_reset_typeattr(struct cil_typeattribute *attr)
attr->expr_list = NULL;
}
attr->used = CIL_FALSE;
attr->keep = CIL_FALSE;
}
static void cil_reset_typeattributeset(struct cil_typeattributeset *tas)

View File

@ -1420,6 +1420,8 @@ void ocontext_selinux_free(ocontext_t **ocontexts)
if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF
|| i == OCON_FSUSE)
free(ctmp->u.name);
else if (i == OCON_IBENDPORT)
free(ctmp->u.ibendport.dev_name);
free(ctmp);
}
}

View File

@ -89,16 +89,6 @@ class CheckRole(argparse.Action):
newval.append(v)
setattr(namespace, self.dest, newval)
store = ''
class SetStore(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
global store
store = values
setattr(namespace, self.dest, values)
class seParser(argparse.ArgumentParser):
@ -134,67 +124,21 @@ class SetImportFile(argparse.Action):
sys.exit(1)
setattr(namespace, self.dest, values)
# functions for OBJECT initialization
def login_ini():
OBJECT = seobject.loginRecords(store)
return OBJECT
def user_ini():
OBJECT = seobject.seluserRecords(store)
return OBJECT
def port_ini():
OBJECT = seobject.portRecords(store)
return OBJECT
def ibpkey_ini():
OBJECT = seobject.ibpkeyRecords(store)
return OBJECT
def ibendport_ini():
OBJECT = seobject.ibendportRecords(store)
return OBJECT
def module_ini():
OBJECT = seobject.moduleRecords(store)
return OBJECT
def interface_ini():
OBJECT = seobject.interfaceRecords(store)
return OBJECT
def node_ini():
OBJECT = seobject.nodeRecords(store)
return OBJECT
def fcontext_ini():
OBJECT = seobject.fcontextRecords(store)
return OBJECT
def boolean_ini():
OBJECT = seobject.booleanRecords(store)
return OBJECT
def permissive_ini():
OBJECT = seobject.permissiveRecords(store)
return OBJECT
def dontaudit_ini():
OBJECT = seobject.dontauditClass(store)
return OBJECT
# define dictonary for seobject OBEJCTS
object_dict = {'login': login_ini, 'user': user_ini, 'port': port_ini, 'module': module_ini, 'interface': interface_ini, 'node': node_ini, 'fcontext': fcontext_ini, 'boolean': boolean_ini, 'permissive': permissive_ini, 'dontaudit': dontaudit_ini, 'ibpkey': ibpkey_ini, 'ibendport': ibendport_ini}
object_dict = {
'login': seobject.loginRecords,
'user': seobject.seluserRecords,
'port': seobject.portRecords,
'module': seobject.moduleRecords,
'interface': seobject.interfaceRecords,
'node': seobject.nodeRecords,
'fcontext': seobject.fcontextRecords,
'boolean': seobject.booleanRecords,
'permissive': seobject.permissiveRecords,
'dontaudit': seobject.dontauditClass,
'ibpkey': seobject.ibpkeyRecords,
'ibendport': seobject.ibendportRecords
}
def generate_custom_usage(usage_text, usage_dict):
# generate custom usage from given text and dictonary
@ -238,8 +182,7 @@ def handleLogin(args):
handle_opts(args, login_args, args.action)
OBJECT = object_dict['login']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['login'](args)
if args.action is "add":
OBJECT.add(args.login, args.seuser, args.range)
@ -257,7 +200,7 @@ def handleLogin(args):
def parser_add_store(parser, name):
parser.add_argument('-S', '--store', action=SetStore, help=_("Select an alternate SELinux Policy Store to manage"))
parser.add_argument('-S', '--store', default='', help=_("Select an alternate SELinux Policy Store to manage"))
def parser_add_priority(parser, name):
@ -269,7 +212,7 @@ def parser_add_noheading(parser, name):
def parser_add_noreload(parser, name):
parser.add_argument('-N', '--noreload', action='store_false', default=True, help=_('Do not reload policy after commit'))
parser.add_argument('-N', '--noreload', action='store_true', default=False, help=_('Do not reload policy after commit'))
def parser_add_locallist(parser, name):
@ -372,8 +315,7 @@ def handleFcontext(args):
else:
handle_opts(args, fcontext_args, args.action)
OBJECT = object_dict['fcontext']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['fcontext'](args)
if args.action is "add":
if args.equal:
@ -441,8 +383,7 @@ def handleUser(args):
handle_opts(args, user_args, args.action)
OBJECT = object_dict['user']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['user'](args)
if args.action is "add":
OBJECT.add(args.selinux_name, args.roles, args.level, args.range, args.prefix)
@ -492,8 +433,7 @@ def handlePort(args):
handle_opts(args, port_args, args.action)
OBJECT = object_dict['port']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['port'](args)
if args.action is "add":
OBJECT.add(args.port, args.proto, args.range, args.type)
@ -538,8 +478,7 @@ def handlePkey(args):
handle_opts(args, ibpkey_args, args.action)
OBJECT = object_dict['ibpkey']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['ibpkey'](args)
if args.action is "add":
OBJECT.add(args.ibpkey, args.subnet_prefix, args.range, args.type)
@ -582,8 +521,7 @@ def handleIbendport(args):
handle_opts(args, ibendport_args, args.action)
OBJECT = object_dict['ibendport']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['ibendport'](args)
if args.action is "add":
OBJECT.add(args.ibendport, args.ibdev_name, args.range, args.type)
@ -626,8 +564,7 @@ def handleInterface(args):
handle_opts(args, interface_args, args.action)
OBJECT = object_dict['interface']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['interface'](args)
if args.action is "add":
OBJECT.add(args.interface, args.range, args.type)
@ -666,8 +603,7 @@ def setupInterfaceParser(subparsers):
def handleModule(args):
OBJECT = seobject.moduleRecords(store)
OBJECT.set_reload(args.noreload)
OBJECT = seobject.moduleRecords(args)
if args.action == "add":
OBJECT.add(args.module_name, args.priority)
if args.action == "enable":
@ -709,8 +645,7 @@ def handleNode(args):
node_args = {'list': [('node', 'type', 'proto', 'netmask'), ('')], 'add': [('locallist'), ('type', 'node', 'proto', 'netmask')], 'modify': [('locallist'), ('node', 'netmask', 'proto')], 'delete': [('locallist'), ('node', 'netmask', 'prototype')], 'extract': [('locallist', 'node', 'type', 'proto', 'netmask'), ('')], 'deleteall': [('locallist'), ('')]}
handle_opts(args, node_args, args.action)
OBJECT = object_dict['node']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['node'](args)
if args.action is "add":
OBJECT.add(args.node, args.netmask, args.proto, args.range, args.type)
@ -756,8 +691,7 @@ def handleBoolean(args):
handle_opts(args, boolean_args, args.action)
OBJECT = object_dict['boolean']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['boolean'](args)
if args.action is "modify":
if args.boolean:
@ -795,8 +729,7 @@ def setupBooleanParser(subparsers):
def handlePermissive(args):
OBJECT = object_dict['permissive']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['permissive'](args)
if args.action is "list":
OBJECT.list(args.noheading)
@ -830,8 +763,7 @@ def setupPermissiveParser(subparsers):
def handleDontaudit(args):
OBJECT = object_dict['dontaudit']()
OBJECT.set_reload(args.noreload)
OBJECT = object_dict['dontaudit'](args)
OBJECT.toggle(args.action)
@ -848,7 +780,7 @@ def handleExport(args):
for i in manageditems:
print("%s -D" % i)
for i in manageditems:
OBJECT = object_dict[i]()
OBJECT = object_dict[i](args)
for c in OBJECT.customized():
print("%s %s" % (i, str(c)))
@ -912,7 +844,7 @@ def mkargv(line):
def handleImport(args):
trans = seobject.semanageRecords(store)
trans = seobject.semanageRecords(args)
trans.start()
for l in sys.stdin.readlines():
@ -932,7 +864,6 @@ def handleImport(args):
except KeyboardInterrupt:
sys.exit(0)
trans.set_reload(args.noreload)
trans.finish()

View File

@ -238,21 +238,23 @@ class semanageRecords:
transaction = False
handle = None
store = None
args = None
def __init__(self, store):
def __init__(self, args):
global handle
self.load = True
self.sh = self.get_handle(store)
self.args = args
try:
self.noreload = args.noreload
except:
self.noreload = False
self.sh = self.get_handle(args.store)
rc, localstore = selinux.selinux_getpolicytype()
if store == "" or store == localstore:
if args.store == "" or args.store == localstore:
self.mylog = logger()
else:
self.mylog = nulllogger()
def set_reload(self, load):
self.load = load
def get_handle(self, store):
global is_mls_enabled
@ -312,7 +314,8 @@ class semanageRecords:
if semanageRecords.transaction:
return
semanage_set_reload(self.sh, self.load)
if self.noreload:
semanage_set_reload(self.sh, 0)
rc = semanage_commit(self.sh)
if rc < 0:
self.mylog.commit(0)
@ -328,8 +331,8 @@ class semanageRecords:
class moduleRecords(semanageRecords):
def __init__(self, store):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def get_all(self):
l = []
@ -440,8 +443,8 @@ class moduleRecords(semanageRecords):
class dontauditClass(semanageRecords):
def __init__(self, store):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def toggle(self, dontaudit):
if dontaudit not in ["on", "off"]:
@ -453,8 +456,8 @@ class dontauditClass(semanageRecords):
class permissiveRecords(semanageRecords):
def __init__(self, store):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def get_all(self):
l = []
@ -522,8 +525,8 @@ class permissiveRecords(semanageRecords):
class loginRecords(semanageRecords):
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
self.oldsename = None
self.oldserange = None
self.sename = None
@ -534,7 +537,7 @@ class loginRecords(semanageRecords):
if sename == "":
sename = "user_u"
userrec = seluserRecords()
userrec = seluserRecords(self.args)
range, (rc, oldserole) = userrec.get(self.oldsename)
range, (rc, serole) = userrec.get(sename)
@ -603,7 +606,7 @@ class loginRecords(semanageRecords):
if sename == "" and serange == "":
raise ValueError(_("Requires seuser or serange"))
userrec = seluserRecords()
userrec = seluserRecords(self.args)
range, (rc, oldserole) = userrec.get(self.oldsename)
if sename != "":
@ -660,7 +663,7 @@ class loginRecords(semanageRecords):
def __delete(self, name):
rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
userrec = seluserRecords()
userrec = seluserRecords(self.args)
range, (rc, oldserole) = userrec.get(self.oldsename)
(rc, k) = semanage_seuser_key_create(self.sh, name)
@ -779,8 +782,8 @@ class loginRecords(semanageRecords):
class seluserRecords(semanageRecords):
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def get(self, name):
(rc, k) = semanage_user_key_create(self.sh, name)
@ -1042,8 +1045,8 @@ class portRecords(semanageRecords):
except RuntimeError:
valid_types = []
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def __genkey(self, port, proto):
if proto == "tcp":
@ -1317,8 +1320,8 @@ class ibpkeyRecords(semanageRecords):
except:
valid_types = []
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def __genkey(self, pkey, subnet_prefix):
if subnet_prefix == "":
@ -1540,9 +1543,8 @@ class ibpkeyRecords(semanageRecords):
def customized(self):
l = []
ddict = self.get_all(True)
keys = ddict.keys()
keys.sort()
for k in keys:
for k in sorted(ddict.keys()):
if k[0] == k[1]:
l.append("-a -t %s -x %s %s" % (ddict[k][0], k[2], k[0]))
else:
@ -1554,11 +1556,10 @@ class ibpkeyRecords(semanageRecords):
keys = ddict.keys()
if len(keys) == 0:
return
keys.sort()
if heading:
print("%-30s %-18s %s\n" % (_("SELinux IB Pkey Type"), _("Subnet_Prefix"), _("Pkey Number")))
for i in keys:
for i in sorted(keys):
rec = "%-30s %-18s " % i
rec += "%s" % ddict[i][0]
for p in ddict[i][1:]:
@ -1572,8 +1573,8 @@ class ibendportRecords(semanageRecords):
except:
valid_types = []
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def __genkey(self, ibendport, ibdev_name):
if ibdev_name == "":
@ -1782,10 +1783,9 @@ class ibendportRecords(semanageRecords):
def customized(self):
l = []
ddict = self.get_all(True)
keys = ddict.keys()
keys.sort()
for k in keys:
l.append("-a -t %s -x %s %s" % (ddict[k][0], k[2], k[0]))
for k in sorted(ddict.keys()):
l.append("-a -t %s -r %s -z %s %s" % (ddict[k][0], ddict[k][1], k[1], k[0]))
return l
def list(self, heading=1, locallist=0):
@ -1793,11 +1793,10 @@ class ibendportRecords(semanageRecords):
keys = ddict.keys()
if len(keys) == 0:
return
keys.sort()
if heading:
print("%-30s %-18s %s\n" % (_("SELinux IB End Port Type"), _("IB Device Name"), _("Port Number")))
for i in keys:
for i in sorted(keys):
rec = "%-30s %-18s " % i
rec += "%s" % ddict[i][0]
for p in ddict[i][1:]:
@ -1810,8 +1809,8 @@ class nodeRecords(semanageRecords):
except RuntimeError:
valid_types = []
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
self.protocol = ["ipv4", "ipv6"]
def validate(self, addr, mask, protocol):
@ -2046,8 +2045,8 @@ class nodeRecords(semanageRecords):
class interfaceRecords(semanageRecords):
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
def __add(self, interface, serange, ctype):
if is_mls_enabled == 1:
@ -2243,8 +2242,8 @@ class fcontextRecords(semanageRecords):
except RuntimeError:
valid_types = []
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
self.equiv = {}
self.equiv_dist = {}
self.equal_ind = False
@ -2632,8 +2631,8 @@ class fcontextRecords(semanageRecords):
class booleanRecords(semanageRecords):
def __init__(self, store=""):
semanageRecords.__init__(self, store)
def __init__(self, args):
semanageRecords.__init__(self, args)
self.dict = {}
self.dict["TRUE"] = 1
self.dict["FALSE"] = 0

View File

@ -22,14 +22,15 @@ Query SELinux policy to see if domains can communicate with each other
.br
.B generate
.br
.br
Generate SELinux Policy module template
.B sepolicy-generate(8)
.br
.B gui
.br
.br
Launch Graphical User Interface for SELinux Policy, requires policycoreutils-gui package.
.B sepolicy-generate(8)
.B sepolicy-gui(8)
.br
.B interface

View File

@ -1,5 +1,4 @@
semodule_package/semodule_package
semodule_package/semodule_unpackage
semodule_deps/semodule_deps
semodule_expand/semodule_expand
semodule_link/semodule_link

View File

@ -1,4 +1,4 @@
SUBDIRS = semodule_package semodule_link semodule_expand semodule_deps
SUBDIRS = semodule_package semodule_link semodule_expand
all install relabel clean indent:
@for subdir in $(SUBDIRS); do \

View File

@ -1,28 +0,0 @@
# Installation directories.
PREFIX ?= $(DESTDIR)/usr
INCLUDEDIR ?= $(PREFIX)/include
BINDIR ?= $(PREFIX)/bin
LIBDIR ?= $(PREFIX)/lib
MANDIR ?= $(PREFIX)/share/man
LIBSEPOLA ?= $(LIBDIR)/libsepol.a
CFLAGS ?= -Werror -Wall -W
all: semodule_deps
semodule_deps: semodule_deps.o $(LIBSEPOLA)
install: all
-mkdir -p $(BINDIR)
install -m 755 semodule_deps $(BINDIR)
test -d $(MANDIR)/man8 || install -m 755 -d $(MANDIR)/man8
install -m 644 semodule_deps.8 $(MANDIR)/man8/
relabel:
clean:
-rm -f semodule_deps *.o
indent:
../../scripts/Lindent $(wildcard *.[ch])

View File

@ -1,46 +0,0 @@
.TH SEMODULE_DEPS "8" "June 2006" "Security Enhanced Linux" NSA
.SH NAME
semodule_deps \- show the dependencies between SELinux policy packages.
.SH SYNOPSIS
.B semodule_deps [\-v \-g \-b] basemodpkg modpkg1 [modpkg2 ... ]
.br
.SH DESCRIPTION
.PP
semodule_deps is a developer tool for showing the dependencies
between policy packages. For each module it prints a list of
modules that must be present for a module's requirements to
be satisfied. It only deals with requirements, not optional
dependencies.
In order for semodule_deps to give useful information the list
of packages passed in cannot have unsatisfied dependencies. In
general this means that the list of modules will usually be
quite long.
By default options to the base module are excluded as almost every
module has this dependency. The \-b option will include these
dependencies.
In addition to human readable output, semodule_deps can output the
dependencies in the Graphviz dot format (http://www.graphviz.org/)
using the \-g option. This is useful for producing a picture of the
dependencies.
.SH "OPTIONS"
.TP
.B \-v
verbose mode
.TP
.B \-g
output dependency information in Graphviz dot format
.TP
.B \-b
include dependencies to the base module - by default these are excluded
.SH SEE ALSO
.B checkmodule(8), semodule_package(8), semodule(8), semodule_link(8)
.SH AUTHORS
.nf
This manual page was written by Karl MacMillan <kmacmillan@mentalrootkit.com>.
The program was written by Karl MacMillan <kmacmillan@mentalrootkit.com>.

View File

@ -1,401 +0,0 @@
/* Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
*
* Copyright (C) 2006 Tresys Technology, LLC
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
*/
/* Because we _must_ muck around in the internal representation of
* the policydb (and include the internal header below) this program
* must be statically linked to libsepol like checkpolicy. It is
* not clear if it is worthwhile to fix this, as exposing the details
* of avrule_blocks - even in an ABI safe way - seems undesirable.
*/
#include <sepol/module.h>
#include <sepol/errcodes.h>
#include <sepol/policydb/policydb.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
/* for getopt */
extern char *optarg;
extern int optind;
/* This is really a horrible hack, but the base module
* is referred to with the following name. The same
* thing is done in the linker for displaying error
* messages.
*/
#define BASE_NAME ((char *)"BASE")
static __attribute__((__noreturn__)) void usage(const char *program_name)
{
printf("usage: %s [-v -g -b] basemodpkg modpkg1 [modpkg2 ... ]\n",
program_name);
exit(1);
}
/* Basic string hash and compare for the hashtables used in
* generate_requires. Copied from symtab.c.
*/
static unsigned int reqsymhash(hashtab_t h, const_hashtab_key_t key)
{
const char *p, *keyp;
size_t size;
unsigned int val;
val = 0;
keyp = (const char *)key;
size = strlen(keyp);
for (p = keyp; ((size_t) (p - keyp)) < size; p++)
val =
(val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
return val & (h->size - 1);
}
static int reqsymcmp(hashtab_t h
__attribute__ ((unused)), const_hashtab_key_t key1,
const_hashtab_key_t key2)
{
return strcmp(key1, key2);
}
/* Load a policy package from the given filename. Progname is used for
* error reporting.
*/
static sepol_module_package_t *load_module(char *filename, char *progname)
{
int ret;
FILE *fp = NULL;
struct sepol_policy_file *pf = NULL;
sepol_module_package_t *p = NULL;
if (sepol_module_package_create(&p)) {
fprintf(stderr, "%s: Out of memory\n", progname);
goto bad;
}
if (sepol_policy_file_create(&pf)) {
fprintf(stderr, "%s: Out of memory\n", progname);
goto bad;
}
fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "%s: Could not open package %s: %s", progname,
filename, strerror(errno));
goto bad;
}
sepol_policy_file_set_fp(pf, fp);
ret = sepol_module_package_read(p, pf, 0);
if (ret) {
fprintf(stderr, "%s: Error while reading package from %s\n",
progname, filename);
goto bad;
}
fclose(fp);
sepol_policy_file_free(pf);
return p;
bad:
sepol_module_package_free(p);
sepol_policy_file_free(pf);
if (fp)
fclose(fp);
return NULL;
}
/* This function generates the requirements graph and stores it in
* a set of nested hashtables. The top level hash table stores modules
* keyed by name. The value of that module is a hashtable storing all
* of the requirements keyed by name. There is no value for the requirements
* hashtable.
*
* This only tracks symbols that are _required_ - optional symbols
* are completely ignored. A future version might look at this.
*
* This requirement generation only looks at booleans and types because:
* - object classes: (for now) only present in bases
* - roles: since they are multiply declared it is not clear how
* to present these requirements as they will be satisfied
* by multiple modules.
* - users: same problem as roles plus they are usually defined outside
* of the policy.
* - levels / cats: can't be required or used in modules.
*/
static hashtab_t generate_requires(policydb_t * p)
{
avrule_block_t *block;
avrule_decl_t *decl;
char *mod_name, *req_name, *id;
ebitmap_t *b;
ebitmap_node_t *node;
uint32_t i, j;
int ret;
scope_datum_t *scope;
hashtab_t mods;
hashtab_t reqs;
mods = hashtab_create(reqsymhash, reqsymcmp, 64);
if (mods == NULL)
return NULL;
for (block = p->global; block != NULL; block = block->next) {
if (block->flags & AVRULE_OPTIONAL)
continue;
for (decl = block->branch_list; decl != NULL; decl = decl->next) {
mod_name =
decl->module_name ? decl->module_name : BASE_NAME;
for (i = 0; i < SYM_NUM; i++) {
if (!(i == SYM_TYPES || i == SYM_BOOLS))
continue;
b = &decl->required.scope[i];
ebitmap_for_each_bit(b, node, j) {
if (!ebitmap_node_get_bit(node, j))
continue;
id = p->sym_val_to_name[i][j];
scope =
(scope_datum_t *) hashtab_search(p->
scope
[i].
table,
id);
/* since this is only called after a successful link,
* this should never happen */
assert(scope->scope == SCOPE_DECL);
req_name =
p->decl_val_to_struct[scope->
decl_ids[0]]->
module_name ? p->
decl_val_to_struct[scope->
decl_ids[0]]->
module_name : BASE_NAME;
reqs =
(hashtab_t) hashtab_search(mods,
mod_name);
if (!reqs) {
reqs =
hashtab_create(reqsymhash,
reqsymcmp,
64);
if (reqs == NULL) {
return NULL;
}
ret =
hashtab_insert(mods,
mod_name,
reqs);
if (ret != SEPOL_OK)
return NULL;
}
ret =
hashtab_insert(reqs, req_name,
NULL);
if (!
(ret == SEPOL_EEXIST
|| ret == SEPOL_OK))
return NULL;
}
}
}
}
return mods;
}
static void free_requires(hashtab_t req)
{
unsigned int i;
hashtab_ptr_t cur;
/* We steal memory for everything stored in the hash tables
* from the policydb, so this only looks like it leaks.
*/
for (i = 0; i < req->size; i++) {
cur = req->htable[i];
while (cur != NULL) {
hashtab_destroy((hashtab_t) cur->datum);
cur = cur->next;
}
}
hashtab_destroy(req);
}
static void output_graphviz(hashtab_t mods, int exclude_base, FILE * f)
{
unsigned int i, j;
hashtab_ptr_t cur, cur2;
hashtab_t reqs;
fprintf(f, "digraph mod_deps {\n");
fprintf(f, "\toverlap=false\n");
for (i = 0; i < mods->size; i++) {
cur = mods->htable[i];
while (cur != NULL) {
reqs = (hashtab_t) cur->datum;
assert(reqs);
for (j = 0; j < reqs->size; j++) {
cur2 = reqs->htable[j];
while (cur2 != NULL) {
if (exclude_base
&& strcmp(cur2->key,
BASE_NAME) == 0) {
cur2 = cur2->next;
continue;
}
fprintf(f, "\t%s -> %s\n", cur->key,
cur2->key);
cur2 = cur2->next;
}
}
cur = cur->next;
}
}
fprintf(f, "}\n");
}
static void output_requirements(hashtab_t mods, int exclude_base, FILE * f)
{
unsigned int i, j;
hashtab_ptr_t cur, cur2;
hashtab_t reqs;
int found_req;
for (i = 0; i < mods->size; i++) {
cur = mods->htable[i];
while (cur != NULL) {
reqs = (hashtab_t) cur->datum;
assert(reqs);
fprintf(f, "module: %s\n", cur->key);
found_req = 0;
for (j = 0; j < reqs->size; j++) {
cur2 = reqs->htable[j];
while (cur2 != NULL) {
if (exclude_base
&& strcmp(cur2->key,
BASE_NAME) == 0) {
cur2 = cur2->next;
continue;
}
found_req = 1;
fprintf(f, "\t%s\n", cur2->key);
cur2 = cur2->next;
}
}
if (!found_req)
fprintf(f, "\t[no dependencies]\n");
cur = cur->next;
}
}
fprintf(f, "}\n");
}
/* Possible commands - see the command variable in
* main below and the man page for more info.
*/
#define SHOW_DEPS 1
#define GEN_GRAPHVIZ 2
int main(int argc, char **argv)
{
int ch, i, num_mods;
int verbose = 0, exclude_base = 1, command = SHOW_DEPS;
char *basename;
sepol_module_package_t *base, **mods;
policydb_t *p;
hashtab_t req;
while ((ch = getopt(argc, argv, "vgb")) != EOF) {
switch (ch) {
case 'v':
verbose = 1;
break;
case 'g':
command = GEN_GRAPHVIZ;
break;
case 'b':
exclude_base = 0;
break;
default:
usage(argv[0]);
}
}
/* check args */
if (argc < 3 || !(optind != (argc - 1))) {
fprintf(stderr,
"%s: You must provide the base module package and at least one other module package\n",
argv[0]);
usage(argv[0]);
}
basename = argv[optind++];
base = load_module(basename, argv[0]);
if (!base) {
fprintf(stderr,
"%s: Could not load base module from file %s\n",
argv[0], basename);
exit(1);
}
num_mods = argc - optind;
mods =
(sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *)
* num_mods);
if (!mods) {
fprintf(stderr, "%s: Out of memory\n", argv[0]);
exit(1);
}
memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods);
for (i = 0; optind < argc; optind++, i++) {
mods[i] = load_module(argv[optind], argv[0]);
if (!mods[i]) {
fprintf(stderr,
"%s: Could not load module from file %s\n",
argv[0], argv[optind]);
exit(1);
}
}
if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
fprintf(stderr, "%s: Error while linking packages\n", argv[0]);
exit(1);
}
p = (policydb_t *) sepol_module_package_get_policy(base);
if (p == NULL)
exit(1);
req = generate_requires(p);
if (req == NULL)
exit(1);
if (command == SHOW_DEPS)
output_requirements(req, exclude_base, stdout);
else
output_graphviz(req, exclude_base, stdout);
sepol_module_package_free(base);
for (i = 0; i < num_mods; i++)
sepol_module_package_free(mods[i]);
free_requires(req);
exit(0);
}