1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
2 *
3 * Copyright (C) 2004 Tresys Technology, LLC
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 2.
7 */
8
9 #include <sepol/module.h>
10
11 #include <getopt.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <sys/mman.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21
22 #define LINKPOLICY_VERSION "1.0"
23
24 char *progname;
25 extern char *optarg;
26 extern int optind;
27
usage(const char * program_name)28 static __attribute__((__noreturn__)) void usage(const char *program_name)
29 {
30 printf("usage: %s [-Vv] [-o outfile] basemodpkg modpkg1 [modpkg2]...\n",
31 program_name);
32 exit(1);
33 }
34
load_module(char * filename)35 static sepol_module_package_t *load_module(char *filename)
36 {
37 int ret;
38 FILE *fp = NULL;
39 struct sepol_policy_file *pf = NULL;
40 sepol_module_package_t *p = NULL;
41
42 if (sepol_module_package_create(&p)) {
43 fprintf(stderr, "%s: Out of memory\n", progname);
44 goto bad;
45 }
46 if (sepol_policy_file_create(&pf)) {
47 fprintf(stderr, "%s: Out of memory\n", progname);
48 goto bad;
49 }
50 fp = fopen(filename, "r");
51 if (!fp) {
52 fprintf(stderr, "%s: Could not open package %s: %s", progname,
53 filename, strerror(errno));
54 goto bad;
55 }
56 sepol_policy_file_set_fp(pf, fp);
57
58 printf("%s: loading package from file %s\n", progname, filename);
59
60 ret = sepol_module_package_read(p, pf, 0);
61 if (ret) {
62 fprintf(stderr, "%s: Error while reading package from %s\n",
63 progname, filename);
64 goto bad;
65 }
66 fclose(fp);
67 sepol_policy_file_free(pf);
68 return p;
69 bad:
70 sepol_module_package_free(p);
71 sepol_policy_file_free(pf);
72 if (fp)
73 fclose(fp);
74 return NULL;
75 }
76
main(int argc,char ** argv)77 int main(int argc, char **argv)
78 {
79 int ch, i, show_version = 0, verbose = 0, num_mods;
80 char *basename, *outname = NULL;
81 sepol_module_package_t *base, **mods;
82 FILE *outfile;
83 struct sepol_policy_file *pf;
84
85 progname = argv[0];
86
87 while ((ch = getopt(argc, argv, "o:Vv")) != EOF) {
88 switch (ch) {
89 case 'V':
90 show_version = 1;
91 break;
92 case 'v':
93 verbose = 1;
94 break;
95 case 'o':
96 outname = optarg;
97 break;
98 default:
99 usage(argv[0]);
100 }
101 }
102
103 if (show_version) {
104 printf("%s\n", LINKPOLICY_VERSION);
105 exit(0);
106 }
107
108 /* check args */
109 if (argc < 3 || !(optind != (argc - 1))) {
110 fprintf(stderr,
111 "%s: You must provide the base module package and at least one other module package\n",
112 argv[0]);
113 usage(argv[0]);
114 }
115
116 basename = argv[optind++];
117 base = load_module(basename);
118 if (!base) {
119 fprintf(stderr,
120 "%s: Could not load base module from file %s\n",
121 argv[0], basename);
122 exit(1);
123 }
124
125 num_mods = argc - optind;
126 mods =
127 (sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *)
128 * num_mods);
129 if (!mods) {
130 fprintf(stderr, "%s: Out of memory\n", argv[0]);
131 exit(1);
132 }
133 memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods);
134
135 for (i = 0; optind < argc; optind++, i++) {
136 mods[i] = load_module(argv[optind]);
137 if (!mods[i]) {
138 fprintf(stderr,
139 "%s: Could not load module from file %s\n",
140 argv[0], argv[optind]);
141 exit(1);
142 }
143 }
144
145 if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
146 fprintf(stderr, "%s: Error while linking packages\n", argv[0]);
147 exit(1);
148 }
149
150 if (outname) {
151 outfile = fopen(outname, "w");
152 if (!outfile) {
153 perror(outname);
154 exit(1);
155 }
156
157 if (sepol_policy_file_create(&pf)) {
158 fprintf(stderr, "%s: Out of memory\n", argv[0]);
159 exit(1);
160 }
161 sepol_policy_file_set_fp(pf, outfile);
162 if (sepol_module_package_write(base, pf)) {
163 fprintf(stderr, "%s: Error writing linked package.\n",
164 argv[0]);
165 exit(1);
166 }
167 sepol_policy_file_free(pf);
168 fclose(outfile);
169 }
170
171 sepol_module_package_free(base);
172 for (i = 0; i < num_mods; i++)
173 sepol_module_package_free(mods[i]);
174 free(mods);
175 exit(0);
176 }
177