~ubuntu-branches/ubuntu/gutsy/checkpolicy/gutsy

« back to all changes in this revision

Viewing changes to genpolusers.c

  • Committer: Bazaar Package Importer
  • Author(s): Manoj Srivastava
  • Date: 2004-11-24 14:01:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041124140141-2w64gbhqynveunlv
Tags: 1.18-2
Update download location and copyright file, since the locations we
were pointing to are now forbidden (return a code 403).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * genpolusers old-policy new-users new-policy
 
3
 *
 
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.
 
15
 */ 
 
16
 
 
17
#include <getopt.h>
 
18
#include <unistd.h>
 
19
#include <sys/types.h>
 
20
#include <sys/stat.h>
 
21
#include <fcntl.h>
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include <errno.h>
 
25
#include <sys/mman.h>
 
26
#include <sepol/policydb.h>
 
27
#include <sepol/services.h>
 
28
#include <sepol/conditional.h>
 
29
#include "queue.h"
 
30
#include "checkpolicy.h"
 
31
 
 
32
extern policydb_t *policydbp;
 
33
extern queue_t id_queue;
 
34
extern unsigned int policydb_errors;
 
35
 
 
36
extern FILE *yyin;
 
37
extern int yyparse(void);
 
38
extern void yyrestart(FILE *);
 
39
 
 
40
void usage(char *progname)
 
41
{
 
42
        printf("usage:  %s old-policy new-users new-policy\n", progname);
 
43
        exit(1);
 
44
}
 
45
 
 
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)
 
49
{
 
50
        char *name = key;
 
51
        user_datum_t *usrdatum = datum;
 
52
        
 
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);
 
57
                        return 0;
 
58
                }
 
59
                printf("Removing user %s\n", name);
 
60
                return 1;
 
61
        }
 
62
        return 0;
 
63
}
 
64
 
 
65
static struct ebitmap free_users;
 
66
 
 
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)
 
70
{
 
71
        user_datum_t *usrdatum;
 
72
        struct policydb *pol = p;
 
73
 
 
74
        if (key)
 
75
                free(key);
 
76
 
 
77
        usrdatum = (user_datum_t *) datum;
 
78
        ebitmap_set_bit(&free_users, usrdatum->value - 1, 1);
 
79
 
 
80
        ebitmap_destroy(&usrdatum->roles);
 
81
        free(datum);
 
82
        pol->p_users.nprim--;
 
83
}
 
84
 
 
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)
 
90
{
 
91
        user_datum_t *usrdatum = datum;
 
92
        struct policydb *pol = p;
 
93
        int i;
 
94
 
 
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);
 
101
                                return 0;
 
102
                        }
 
103
                }
 
104
        }
 
105
        return 0;
 
106
}
 
107
 
 
108
int main(int argc, char **argv)
 
109
{
 
110
        policydb_t policydb;
 
111
        struct policy_file pf;
 
112
        struct stat sb;
 
113
        FILE *outfp;
 
114
        int fd, rc;
 
115
        void *map;
 
116
 
 
117
        if (argc != 4) 
 
118
                usage(argv[0]);
 
119
 
 
120
        fd = open(argv[1], O_RDONLY);
 
121
        if (fd < 0) {
 
122
                fprintf(stderr, "Can't open '%s':  %s\n",
 
123
                        argv[1], strerror(errno));
 
124
                exit(1);
 
125
        }
 
126
        if (fstat(fd, &sb) < 0) {
 
127
                fprintf(stderr, "Can't stat '%s':  %s\n",
 
128
                        argv[1], strerror(errno));
 
129
                exit(1);
 
130
        }
 
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));
 
135
                exit(1);
 
136
        }
 
137
        pf.type = PF_USE_MEMORY;
 
138
        pf.data = map;
 
139
        pf.len = sb.st_size;
 
140
        if (policydb_read(&policydb,&pf, 0)) {
 
141
                fprintf(stderr, "Can't read binary policy from '%s':  %s\n",
 
142
                        argv[1], strerror(errno));
 
143
                exit(1);
 
144
        }
 
145
        close(fd);
 
146
 
 
147
        /* Preserve the policy version of the original policy
 
148
           for the new policy. */
 
149
        sepol_set_policyvers(policydb.policyvers);
 
150
 
 
151
        yyin = fopen(argv[2], "r");
 
152
        if (!yyin) {
 
153
                fprintf(stderr, "%s:  unable to open %s\n", argv[0], 
 
154
                        argv[2]);
 
155
                exit(1);
 
156
        }
 
157
        id_queue = queue_create();
 
158
        if (!id_queue) {
 
159
                fprintf(stderr, "%s:  out of memory\n", argv[0]);
 
160
                exit(1);
 
161
        }
 
162
        policydbp = &policydb;
 
163
        policydb_errors = 0;
 
164
        if (yyparse() || policydb_errors) {
 
165
                fprintf(stderr, "%s:  error(s) encountered while parsing configuration\n", argv[0]);
 
166
                exit(1);
 
167
        }
 
168
        queue_destroy(id_queue);
 
169
 
 
170
        if (policydb_errors) 
 
171
                exit(1);
 
172
 
 
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);
 
175
 
 
176
        outfp = fopen(argv[3], "w");
 
177
        if (!outfp) {
 
178
                perror(argv[3]);
 
179
                exit(1);
 
180
        }
 
181
        pf.type = PF_USE_STDIO;
 
182
        pf.fp = outfp;
 
183
        rc = policydb_write(&policydb, &pf);
 
184
        if (rc) {
 
185
                fprintf(stderr, "%s:  error writing %s\n",
 
186
                        argv[0], argv[3]);
 
187
                exit(1);
 
188
        }
 
189
        fclose(outfp);
 
190
        exit(0);
 
191
}