semodule-utils: remove semodule_deps

As discussed in https://github.com/SELinuxProject/selinux/issues/64,
semodule_deps has apparently been broken for a very long time for
binary modules and is completely irrelevant for CIL modules.  If there
are any users of it, they ought to be rewritten anyway since it is
not producing correct dependency information, and the ultimate goal
is to stop using binary modules altogether so it is not worth fixing.
Remove it to avoid any further broken usage.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
This commit is contained in:
Stephen Smalley 2017-10-03 10:21:43 -04:00 committed by William Roberts
parent 393bafd3c5
commit ae5f219d7a
5 changed files with 1 additions and 477 deletions

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);
}