1893851c0a146ef392b8d77de737d52245345129eSteve Lawrence/* 2893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * Copyright (C) 2014 Tresys Technology, LLC 3893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * 4893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * This program is free software; you can redistribute it and/or 5893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * modify it under the terms of the GNU General Public License 6893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * as published by the Free Software Foundation; either version 2 7893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * of the License, or (at your option) any later version. 8893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * 9893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * This program is distributed in the hope that it will be useful, 10893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * but WITHOUT ANY WARRANTY; without even the implied warranty of 11893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * GNU General Public License for more details. 13893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * 14893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * You should have received a copy of the GNU General Public License 15893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * along with this program; if not, write to the Free Software 16893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17893851c0a146ef392b8d77de737d52245345129eSteve Lawrence * 02110-1301, USA. 18893851c0a146ef392b8d77de737d52245345129eSteve Lawrence */ 19893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 20893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <errno.h> 21893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <getopt.h> 22893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <libgen.h> 23893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <signal.h> 24893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <stdarg.h> 25893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <stdlib.h> 26893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <string.h> 27893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <unistd.h> 28893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 29893851c0a146ef392b8d77de737d52245345129eSteve Lawrence#include <sepol/module.h> 30758a7fe501586f0f952f6790304ac0f343a64518James Carter#include <sepol/module_to_cil.h> 318fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter#include <sepol/policydb/module.h> 32893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 33893851c0a146ef392b8d77de737d52245345129eSteve Lawrencechar *progname; 34893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 353642a57cd049f4ac71433652aac0c4b92729a728Nicolas Iooss__attribute__ ((format(printf, 1, 2))) 363642a57cd049f4ac71433652aac0c4b92729a728Nicolas Ioossstatic void log_err(const char *fmt, ...) 37893851c0a146ef392b8d77de737d52245345129eSteve Lawrence{ 38893851c0a146ef392b8d77de737d52245345129eSteve Lawrence va_list argptr; 39893851c0a146ef392b8d77de737d52245345129eSteve Lawrence va_start(argptr, fmt); 40893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (vfprintf(stderr, fmt, argptr) < 0) { 41893851c0a146ef392b8d77de737d52245345129eSteve Lawrence _exit(EXIT_FAILURE); 42893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 43893851c0a146ef392b8d77de737d52245345129eSteve Lawrence va_end(argptr); 44893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (fprintf(stderr, "\n") < 0) { 45893851c0a146ef392b8d77de737d52245345129eSteve Lawrence _exit(EXIT_FAILURE); 46893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 47893851c0a146ef392b8d77de737d52245345129eSteve Lawrence} 48893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 49cd20f9c257e7e86fde2259f698677c914c35cfeeNicolas Ioossstatic __attribute__((__noreturn__)) void usage(int err) 50893851c0a146ef392b8d77de737d52245345129eSteve Lawrence{ 51893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "Usage: %s [OPTIONS] [IN_FILE [OUT_FILE]]\n", progname); 52893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "\n"); 53893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "Read an SELinux policy package (.pp) and output the equivilent CIL.\n"); 54893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "If IN_FILE is not provided or is -, read SELinux policy package from\n"); 55893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "standard input. If OUT_FILE is not provided or is -, output CIL to\n"); 56893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "standard output.\n"); 57893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "\n"); 58893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, "Options:\n"); 59893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fprintf(stderr, " -h, --help print this message and exit\n"); 60893851c0a146ef392b8d77de737d52245345129eSteve Lawrence exit(err); 61893851c0a146ef392b8d77de737d52245345129eSteve Lawrence} 62893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 63893851c0a146ef392b8d77de737d52245345129eSteve Lawrenceint main(int argc, char **argv) 64893851c0a146ef392b8d77de737d52245345129eSteve Lawrence{ 65893851c0a146ef392b8d77de737d52245345129eSteve Lawrence int rc = -1; 66893851c0a146ef392b8d77de737d52245345129eSteve Lawrence int opt; 67893851c0a146ef392b8d77de737d52245345129eSteve Lawrence static struct option long_opts[] = { 68893851c0a146ef392b8d77de737d52245345129eSteve Lawrence { "help", 0, NULL, 'h' }, 69893851c0a146ef392b8d77de737d52245345129eSteve Lawrence { NULL, 0, NULL, 0 } 70893851c0a146ef392b8d77de737d52245345129eSteve Lawrence }; 71893851c0a146ef392b8d77de737d52245345129eSteve Lawrence struct sepol_module_package *mod_pkg = NULL; 722f94ac47d5b4c8e4aa5ea8014fa630565730c172Nicolas Iooss const char *ifile = NULL; 732f94ac47d5b4c8e4aa5ea8014fa630565730c172Nicolas Iooss const char *ofile = NULL; 74893851c0a146ef392b8d77de737d52245345129eSteve Lawrence FILE *in = NULL; 75893851c0a146ef392b8d77de737d52245345129eSteve Lawrence FILE *out = NULL; 76893851c0a146ef392b8d77de737d52245345129eSteve Lawrence int outfd = -1; 77893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 78893851c0a146ef392b8d77de737d52245345129eSteve Lawrence // ignore sigpipe so we can check the return code of write, and potentially 79893851c0a146ef392b8d77de737d52245345129eSteve Lawrence // return a more helpful error message 80893851c0a146ef392b8d77de737d52245345129eSteve Lawrence signal(SIGPIPE, SIG_IGN); 81893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 82893851c0a146ef392b8d77de737d52245345129eSteve Lawrence progname = basename(argv[0]); 83893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 84893851c0a146ef392b8d77de737d52245345129eSteve Lawrence while ((opt = getopt_long(argc, argv, "h", long_opts, NULL)) != -1) { 85893851c0a146ef392b8d77de737d52245345129eSteve Lawrence switch (opt) { 86893851c0a146ef392b8d77de737d52245345129eSteve Lawrence case 'h': 87893851c0a146ef392b8d77de737d52245345129eSteve Lawrence usage(0); 88893851c0a146ef392b8d77de737d52245345129eSteve Lawrence case '?': 89893851c0a146ef392b8d77de737d52245345129eSteve Lawrence default: 90893851c0a146ef392b8d77de737d52245345129eSteve Lawrence usage(1); 91893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 92893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 93893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 94893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (argc >= optind + 1 && strcmp(argv[1], "-") != 0) { 958fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter ifile = argv[1]; 968fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter in = fopen(ifile, "rb"); 97893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (in == NULL) { 988fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter log_err("Failed to open %s: %s", ifile, strerror(errno)); 99893851c0a146ef392b8d77de737d52245345129eSteve Lawrence rc = -1; 100893851c0a146ef392b8d77de737d52245345129eSteve Lawrence goto exit; 101893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 102893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } else { 1038fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter ifile = "stdin"; 104893851c0a146ef392b8d77de737d52245345129eSteve Lawrence in = stdin; 105893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 106893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 107893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (argc >= optind + 2 && strcmp(argv[2], "-") != 0) { 1088fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter ofile = argv[2]; 1098fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter out = fopen(ofile, "w"); 110893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (out == NULL) { 1118fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter log_err("Failed to open %s: %s", ofile, strerror(errno)); 112893851c0a146ef392b8d77de737d52245345129eSteve Lawrence rc = -1; 113893851c0a146ef392b8d77de737d52245345129eSteve Lawrence goto exit; 114893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 115893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } else { 116893851c0a146ef392b8d77de737d52245345129eSteve Lawrence out = stdout; 117893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 118893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 119893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (argc >= optind + 3) { 120893851c0a146ef392b8d77de737d52245345129eSteve Lawrence log_err("Too many arguments"); 121893851c0a146ef392b8d77de737d52245345129eSteve Lawrence usage(1); 122893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 123893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 124758a7fe501586f0f952f6790304ac0f343a64518James Carter rc = sepol_ppfile_to_module_package(in, &mod_pkg); 125893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (rc != 0) { 126893851c0a146ef392b8d77de737d52245345129eSteve Lawrence goto exit; 127893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 128893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fclose(in); 129893851c0a146ef392b8d77de737d52245345129eSteve Lawrence in = NULL; 130893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 1318fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter if (ofile) { 1328fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter char *mod_name = mod_pkg->policy->p.name; 1338fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter char *cil_path = strdup(ofile); 1348fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter if (cil_path == NULL) { 1358fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter log_err("No memory available for strdup\n"); 1368fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter rc = -1; 1378fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter goto exit; 1388fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter } 1398fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter char *cil_name = basename(cil_path); 1408fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter char *separator = strrchr(cil_name, '.'); 1418fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter if (separator) { 1428fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter *separator = '\0'; 1438fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter } 144cdc653a447a807298d158c22759f76c2892d9008Vit Mojzis if (mod_name && strcmp(mod_name, cil_name) != 0) { 1457a728e46a50082197e4072e4f0e804421e8f0c2bPetr Lautrbach fprintf(stderr, "Warning: SELinux userspace will refer to the module from %s as %s rather than %s\n", ifile, mod_name, cil_name); 1468fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter } 1478fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter free(cil_path); 1488fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter } 1498fb088a33d4ebbd6d843eb3ac70a05f4c6956f0fJames Carter 150758a7fe501586f0f952f6790304ac0f343a64518James Carter rc = sepol_module_package_to_cil(out, mod_pkg); 151893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (rc != 0) { 152893851c0a146ef392b8d77de737d52245345129eSteve Lawrence goto exit; 153893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 154893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 155893851c0a146ef392b8d77de737d52245345129eSteve Lawrenceexit: 156893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (in != NULL) { 157893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fclose(in); 158893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 159893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (out != NULL) { 160893851c0a146ef392b8d77de737d52245345129eSteve Lawrence fclose(out); 161893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 162893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (outfd != -1) { 163893851c0a146ef392b8d77de737d52245345129eSteve Lawrence close(outfd); 164893851c0a146ef392b8d77de737d52245345129eSteve Lawrence if (rc != 0) { 165893851c0a146ef392b8d77de737d52245345129eSteve Lawrence unlink(argv[2]); 166893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 167893851c0a146ef392b8d77de737d52245345129eSteve Lawrence } 168893851c0a146ef392b8d77de737d52245345129eSteve Lawrence sepol_module_package_free(mod_pkg); 169893851c0a146ef392b8d77de737d52245345129eSteve Lawrence 170893851c0a146ef392b8d77de737d52245345129eSteve Lawrence return rc; 171893851c0a146ef392b8d77de737d52245345129eSteve Lawrence} 172