2 * This file is part of libsmack.
4 * Copyright (C) 2011 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * version 2.1 as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * Jarkko Sakkinen <jarkko.sakkinen@intel.com>
22 * Brian McGillion <brian.mcgillion@intel.com>
26 #include <sys/types.h>
32 #include <sys/smack.h>
38 #define SMACKFS_MAGIC 0x43415d53
39 #define CAT_MAX_COUNT 240
40 #define CAT_MAX_VALUE 63
44 #define CIPSO_POS(i) (SMACK_LABEL_LEN + 1 + NUM_LEN + NUM_LEN + i * NUM_LEN)
45 #define CIPSO_MAX_SIZE CIPSO_POS(CAT_MAX_COUNT)
46 #define CIPSO_NUM_LEN_STR "%-4d"
50 struct cipso_mapping {
51 char label[SMACK_LABEL_LEN + 1];
52 int cats[CAT_MAX_VALUE];
55 struct cipso_mapping *next;
59 struct cipso_mapping *first;
60 struct cipso_mapping *last;
63 static int apply_rules_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
64 static int apply_cipso_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
65 static struct cipso *cipso_new(int fd);
66 static void cipso_free(struct cipso *cipso);
67 static int cipso_apply(struct cipso *cipso);
69 int is_smackfs_mounted(void)
75 ret = statfs(SMACKFS_MNT, &sfs);
76 } while (ret < 0 && errno == EINTR);
81 if (sfs.f_type == SMACKFS_MAGIC)
92 if (is_smackfs_mounted() != 1)
95 fd = open(SMACKFS_MNT "/load2", O_RDONLY);
99 ret = apply_rules_file(fd, 1);
104 int apply_rules(const char *path, int clear)
111 if (stat(path, &sbuf))
114 if (S_ISDIR(sbuf.st_mode))
115 return nftw(path, apply_rules_cb, 1, FTW_PHYS|FTW_ACTIONRETVAL);
117 fd = open(path, O_RDONLY);
121 ret = apply_rules_file(fd, clear);
126 int apply_cipso(const char *path)
133 if (stat(path, &sbuf))
136 if (S_ISDIR(sbuf.st_mode))
137 return nftw(path, apply_cipso_cb, 1, FTW_PHYS|FTW_ACTIONRETVAL);
139 fd = open(path, O_RDONLY);
143 ret = apply_cipso_file(fd);
148 int apply_rules_file(int fd, int clear)
150 struct smack_accesses *rules = NULL;
153 if (smack_accesses_new(&rules))
156 if (smack_accesses_add_from_file(rules, fd)) {
157 smack_accesses_free(rules);
162 ret = smack_accesses_apply(rules);
164 ret = smack_accesses_clear(rules);
166 smack_accesses_free(rules);
171 int apply_cipso_file(int fd)
173 struct cipso *cipso = NULL;
176 cipso = cipso_new(fd);
180 ret = cipso_apply(cipso);
188 static int apply_rules_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
193 if (typeflag == FTW_D)
194 return ftwbuf->level ? FTW_SKIP_SUBTREE : FTW_CONTINUE;
195 else if (typeflag != FTW_F)
198 fd = open(fpath, O_RDONLY);
202 ret = apply_rules_file(fd, 0) ? FTW_STOP : FTW_CONTINUE;
207 static int apply_cipso_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
212 if (typeflag == FTW_D)
213 return ftwbuf->level ? FTW_SKIP_SUBTREE : FTW_CONTINUE;
214 else if (typeflag != FTW_F)
217 fd = open(fpath, O_RDONLY);
221 ret = apply_rules_file(fd, 0) ? FTW_STOP : FTW_CONTINUE;
226 static struct cipso *cipso_new(int fd)
228 struct cipso *cipso = NULL;
229 struct cipso_mapping *mapping = NULL;
232 char *label, *level, *cat, *ptr;
241 file = fdopen(newfd, "r");
247 cipso = calloc(sizeof(struct cipso), 1);
253 while (fgets(buf, BUF_SIZE, file) != NULL) {
254 mapping = calloc(sizeof(struct cipso_mapping), 1);
258 label = strtok_r(buf, " \t\n", &ptr);
259 level = strtok_r(NULL, " \t\n", &ptr);
260 cat = strtok_r(NULL, " \t\n", &ptr);
261 if (label == NULL || cat == NULL || level == NULL ||
262 strlen(label) > SMACK_LABEL_LEN) {
267 strcpy(mapping->label, label);
270 val = strtol(level, NULL, 10);
274 if (val < 0 || val > LEVEL_MAX) {
279 mapping->level = val;
281 for (i = 0; i < CAT_MAX_COUNT && cat != NULL; i++) {
283 val = strtol(cat, NULL, 10);
287 if (val < 0 || val > CAT_MAX_VALUE) {
292 mapping->cats[i] = val;
294 cat = strtok_r(NULL, " \t\n", &ptr);
299 if (cipso->first == NULL) {
300 cipso->first = cipso->last = mapping;
302 cipso->last->next = mapping;
303 cipso->last = mapping;
319 static void cipso_free(struct cipso *cipso)
324 struct cipso_mapping *mapping = cipso->first;
325 struct cipso_mapping *next_mapping = NULL;
327 while (mapping != NULL) {
328 next_mapping = mapping->next;
330 mapping = next_mapping;
334 static int cipso_apply(struct cipso *cipso)
336 struct cipso_mapping *m = NULL;
337 char buf[CIPSO_MAX_SIZE];
341 fd = open(SMACKFS_MNT "/cipso2", O_WRONLY);
345 for (m = cipso->first; m != NULL; m = m->next) {
346 sprintf(buf, "%s ", m->label);
347 sprintf(&buf[SMACK_LABEL_LEN + 1], CIPSO_NUM_LEN_STR, m->level);
348 sprintf(&buf[SMACK_LABEL_LEN + 1 + NUM_LEN], CIPSO_NUM_LEN_STR, m->ncats);
350 for (i = 0; i < m->ncats; i++)
351 sprintf(&buf[CIPSO_POS(i)], CIPSO_NUM_LEN_STR, m->cats[i]);
353 if (write(fd, buf, strlen(buf)) < 0) {