2
* genpolusers old-policy new-users new-policy
4
* Given an existing binary policy configuration and a new source users
5
* configuration (post-processed), generate a new binary policy
6
* configuration that is identical to the old one except that it has
7
* the new user declarations. User declarations from the old binary
8
* policy are replaced if they also exist in the new source users
9
* configuration or removed otherwise. Special exceptions are made
10
* for system_u and user_u, which can be replaced but not removed as
11
* a safety against reloading a user configuration generated from
12
* passwd information that would not include these special SELinux users.
13
* This needs to be generalized in some manner. New users may also be
14
* added by including them in the new source users configuration.
19
#include <sys/types.h>
26
#include <sepol/policydb.h>
27
#include <sepol/services.h>
28
#include <sepol/conditional.h>
30
#include "checkpolicy.h"
32
extern policydb_t *policydbp;
33
extern queue_t id_queue;
34
extern unsigned int policydb_errors;
37
extern int yyparse(void);
38
extern void yyrestart(FILE *);
40
void usage(char *progname)
42
printf("usage: %s old-policy new-users new-policy\n", progname);
46
/* Select users for removal based on whether they were defined in the
47
new source users configuration. */
48
static int select_user(hashtab_key_t key, hashtab_datum_t datum, void *datap)
51
user_datum_t *usrdatum = datum;
53
if (!usrdatum->defined) {
54
/* XXX Hack: Don't accidentally remove SELinux-only users. */
55
if (!strcmp(name, "system_u") || !strcmp(name, "user_u")) {
56
printf("Warning! %s not defined, but not removing.\n", name);
59
printf("Removing user %s\n", name);
65
static struct ebitmap free_users;
67
/* Kill the user entries selected by select_user, and
68
record that their slots are free. */
69
void kill_user(hashtab_key_t key, hashtab_datum_t datum, void *p)
71
user_datum_t *usrdatum;
72
struct policydb *pol = p;
77
usrdatum = (user_datum_t *) datum;
78
ebitmap_set_bit(&free_users, usrdatum->value - 1, 1);
80
ebitmap_destroy(&usrdatum->roles);
85
/* Fold user values down to avoid holes generated by removal.
86
As the SID table is remapped by the kernel upon a policy reload,
87
this is safe for existing SIDs. But it could be a problem for
88
constraints if they refer to the particular user. */
89
int remap_users(hashtab_key_t key, hashtab_datum_t datum, void *p)
91
user_datum_t *usrdatum = datum;
92
struct policydb *pol = p;
95
if (usrdatum->value > pol->p_users.nprim) {
96
for (i = ebitmap_startbit(&free_users); i < ebitmap_length(&free_users); i++) {
97
if (ebitmap_get_bit(&free_users, i)) {
98
printf("Remapping user %s (%u -> %u)\n", key, usrdatum->value, i+1);
99
usrdatum->value = i+1;
100
ebitmap_set_bit(&free_users, i, 0);
108
int main(int argc, char **argv)
111
struct policy_file pf;
120
fd = open(argv[1], O_RDONLY);
122
fprintf(stderr, "Can't open '%s': %s\n",
123
argv[1], strerror(errno));
126
if (fstat(fd, &sb) < 0) {
127
fprintf(stderr, "Can't stat '%s': %s\n",
128
argv[1], strerror(errno));
131
map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
132
if (map == MAP_FAILED) {
133
fprintf(stderr, "Can't map '%s': %s\n",
134
argv[1], strerror(errno));
137
pf.type = PF_USE_MEMORY;
140
if (policydb_read(&policydb,&pf, 0)) {
141
fprintf(stderr, "Can't read binary policy from '%s': %s\n",
142
argv[1], strerror(errno));
147
/* Preserve the policy version of the original policy
148
for the new policy. */
149
sepol_set_policyvers(policydb.policyvers);
151
yyin = fopen(argv[2], "r");
153
fprintf(stderr, "%s: unable to open %s\n", argv[0],
157
id_queue = queue_create();
159
fprintf(stderr, "%s: out of memory\n", argv[0]);
162
policydbp = &policydb;
164
if (yyparse() || policydb_errors) {
165
fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", argv[0]);
168
queue_destroy(id_queue);
173
hashtab_map_remove_on_error(policydb.p_users.table, select_user, kill_user, &policydb);
174
hashtab_map(policydb.p_users.table, remap_users, &policydb);
176
outfp = fopen(argv[3], "w");
181
pf.type = PF_USE_STDIO;
183
rc = policydb_write(&policydb, &pf);
185
fprintf(stderr, "%s: error writing %s\n",