From a371df8d5d79810247efef4f8ca0032842c88203 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Wed, 24 Apr 2013 19:29:46 +0200 Subject: [PATCH] Merge changes from current upstream master branch. This should be done as a proper git merge, but our infrastructure doesn't allow such "exotic" git usage as maintaining upstream branch... Please note: accesses_apply() function includes merge of upstream changes and not yet upstreamed code relying on /smack/change-rule. That code will be sent upstream once the relevant interface show up in kernel (v3.10). Change-Id: Ieac4e0fad82621d6fb24f531385d965c045532fe --- configure.ac | 10 +- init/Makefile.am | 4 + init/smack.service | 3 + libsmack/Makefile.am | 2 +- libsmack/init.c | 187 ++++++++++++++++++++++++++++++ libsmack/libsmack.c | 306 +++++++++++++++++++++++++++++++++++++++++++++----- libsmack/libsmack.sym | 4 + libsmack/sys/smack.h | 16 +++ utils/common.c | 196 +++++--------------------------- utils/common.h | 1 - 10 files changed, 524 insertions(+), 205 deletions(-) create mode 100644 libsmack/init.c diff --git a/configure.ac b/configure.ac index 9f9ce2b..8e9d470 100644 --- a/configure.ac +++ b/configure.ac @@ -3,13 +3,14 @@ AC_INIT([libsmack], [1.0], [jarkko.sakkinen@intel.com], [libsmack], - [https://github.com/organizations/smack-team/smack]) + [https://github.com/smack-team/smack]) AC_CONFIG_SRCDIR([libsmack/libsmack.c]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2 foreign]) AC_USE_SYSTEM_EXTENSIONS AC_CONFIG_MACRO_DIR([m4]) AM_SILENT_RULES([yes]) +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) LT_INIT([disable-static]) AC_PREFIX_DEFAULT([/usr]) @@ -24,12 +25,19 @@ AM_CONDITIONAL([ENABLE_DOXYGEN],[test ! -z "$DOXYGEN"], [Build API documentation AC_SUBST([DOXYGEN], [$DOXYGEN]) # systemd +systemd_new=no +PKG_CHECK_MODULES([SYSTEMD], + systemd >= 198, + [systemd_new=yes], + [systemd_new=no]) + AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), [], [with_systemdsystemunitdir=$(pkg-config --silence-errors --variable=systemdsystemunitdir systemd)]) AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir"]) +AM_CONDITIONAL(HAVE_SYSTEMD_NEW, [test "$systemd_new" = "yes"]) AC_CONFIG_FILES([Makefile libsmack/Makefile libsmack/libsmack.pc utils/Makefile doc/Makefile init/Makefile]) diff --git a/init/Makefile.am b/init/Makefile.am index 8dd3ac4..875263f 100644 --- a/init/Makefile.am +++ b/init/Makefile.am @@ -1,5 +1,9 @@ if HAVE_SYSTEMD +if HAVE_SYSTEMD_NEW + +else systemdsystemunit_DATA = \ smack.mount \ smack.service endif +endif diff --git a/init/smack.service b/init/smack.service index 7c76661..920a3f6 100644 --- a/init/smack.service +++ b/init/smack.service @@ -9,3 +9,6 @@ Before=basic.target ExecStart=/usr/bin/smackctl apply ExecStop=/usr/bin/smackctl clear RemainAfterExit=yes + +[Install] +WantedBy=basic.target diff --git a/libsmack/Makefile.am b/libsmack/Makefile.am index 4ee9c84..09d0778 100644 --- a/libsmack/Makefile.am +++ b/libsmack/Makefile.am @@ -10,7 +10,7 @@ lib_LTLIBRARIES = libsmack.la libsmack_la_LDFLAGS = \ -version-info 1:0:0 \ -Wl,--version-script=$(top_srcdir)/libsmack/libsmack.sym -libsmack_la_SOURCES = libsmack.c +libsmack_la_SOURCES = libsmack.c init.c pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsmack.pc diff --git a/libsmack/init.c b/libsmack/init.c new file mode 100644 index 0000000..bec59f2 --- /dev/null +++ b/libsmack/init.c @@ -0,0 +1,187 @@ +/* + * This file is part of libsmack. Derived from libselinux/src/init.c. + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Authors: + * Passion Zhao + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * * smackfs magic number + * */ +#define SMACK_MAGIC 0x43415d53 /* "SMAC" */ + +/* smack file system type */ +#define SMACKFS "smackfs" + +#define SMACKFSMNT "/sys/fs/smackfs/" +#define OLDSMACKFSMNT "/smack" + +char *smack_mnt = NULL; + +void set_smackmnt(const char *mnt) +{ + smack_mnt = strdup(mnt); +} + +/* Verify the mount point for smack file system has a smackfs. + * If the file system: + * Exist, + * Is mounted with an smack file system, + * The file system is read/write + * then set this as the default file system. + */ +static int verify_smackmnt(const char *mnt) +{ + struct statfs sfbuf; + int rc; + + do { + rc = statfs(mnt, &sfbuf); + } while (rc < 0 && errno == EINTR); + + if (rc == 0) { + if ((uint32_t)sfbuf.f_type == (uint32_t)SMACK_MAGIC) { + struct statvfs vfsbuf; + rc = statvfs(mnt, &vfsbuf); + if (rc == 0) { + if (!(vfsbuf.f_flag & ST_RDONLY)) { + set_smackmnt(mnt); + } + return 0; + } + } + } + + return -1; +} + +int smackfs_exists(void) +{ + int exists = 0; + FILE *fp = NULL; + char *buf = NULL; + size_t len; + ssize_t num; + + fp = fopen("/proc/filesystems", "r"); + if (!fp) + return 1; /* Fail as if it exists */ + + __fsetlocking(fp, FSETLOCKING_BYCALLER); + + num = getline(&buf, &len, fp); + while (num != -1) { + if (strstr(buf, SMACKFS)) { + exists = 1; + break; + } + num = getline(&buf, &len, fp); + } + + free(buf); + fclose(fp); + return exists; +} + +static void init_smackmnt(void) +{ + char *buf=NULL, *p; + FILE *fp=NULL; + size_t len; + ssize_t num; + + if (smack_mnt) + return; + + if (verify_smackmnt(SMACKFSMNT) == 0) + return; + + if (verify_smackmnt(OLDSMACKFSMNT) == 0) + return; + + /* Drop back to detecting it the long way. */ + if (!smackfs_exists()) + goto out; + + /* At this point, the usual spot doesn't have an smackfs so + * we look around for it */ + fp = fopen("/proc/mounts", "r"); + if (!fp) + goto out; + + __fsetlocking(fp, FSETLOCKING_BYCALLER); + while ((num = getline(&buf, &len, fp)) != -1) { + char *tmp; + p = strchr(buf, ' '); + if (!p) + goto out; + p++; + + tmp = strchr(p, ' '); + if (!tmp) + goto out; + + if (!strncmp(tmp + 1, SMACKFS" ", strlen(SMACKFS)+1)) { + *tmp = '\0'; + break; + } + } + + /* If we found something, dup it */ + if (num > 0) + verify_smackmnt(p); + + out: + free(buf); + if (fp) + fclose(fp); + return; +} + +void fini_smackmnt(void) +{ + free(smack_mnt); + smack_mnt = NULL; +} + +static void init_lib(void) __attribute__ ((constructor)); +static void init_lib(void) +{ + init_smackmnt(); +} + +static void fini_lib(void) __attribute__ ((destructor)); +static void fini_lib(void) +{ + fini_smackmnt(); +} diff --git a/libsmack/libsmack.c b/libsmack/libsmack.c index 37843b9..4fb7bbd 100644 --- a/libsmack/libsmack.c +++ b/libsmack/libsmack.c @@ -22,6 +22,7 @@ * Authors: * Jarkko Sakkinen * Brian McGillion + * Passion Zhao * Rafal Krypa */ @@ -36,16 +37,28 @@ #include #include #include +#include #define ACC_LEN 5 #define LOAD_LEN (2 * (SMACK_LABEL_LEN + 1) + 2 * ACC_LEN + 1) -#define KERNEL_FORMAT "%s %s %s" -#define KERNEL_FORMAT_MODIFY "%s %s %s %s" -#define READ_BUF_SIZE LOAD_LEN + 10 -#define SMACKFS_MNT "/smack" +#define LEVEL_MAX 255 +#define NUM_LEN 4 +#define BUF_SIZE 512 +#define CAT_MAX_COUNT 240 +#define CAT_MAX_VALUE 63 +#define CIPSO_POS(i) (SMACK_LABEL_LEN + 1 + NUM_LEN + NUM_LEN + i * NUM_LEN) +#define CIPSO_MAX_SIZE CIPSO_POS(CAT_MAX_COUNT) +#define CIPSO_NUM_LEN_STR "%-4d" + +#define KERNEL_LONG_FORMAT "%s %s %s" +#define KERNEL_SHORT_FORMAT "%-23s %-23s %5s" +#define KERNEL_MODIFY_FORMAT "%s %s %s %s" +#define READ_BUF_SIZE LOAD_LEN + 1 #define SELF_LABEL_FILE "/proc/self/attr/current" +extern char *smack_mnt; + typedef int (*getxattr_func)(void*, const char*, void*, size_t); typedef int (*setxattr_func)(const void*, const char*, const void*, size_t, int); typedef int (*removexattr_func)(void*, const char*); @@ -65,6 +78,19 @@ struct smack_accesses { struct smack_rule *last; }; +struct cipso_mapping { + char label[SMACK_LABEL_LEN + 1]; + int cats[CAT_MAX_VALUE]; + int ncats; + int level; + struct cipso_mapping *next; +}; + +struct smack_cipso { + struct cipso_mapping *first; + struct cipso_mapping *last; +}; + static int accesses_apply(struct smack_accesses *handle, int clear); static inline void parse_access_type(const char *in, char out[ACC_LEN + 1]); static inline char* get_xattr_name(enum smack_label_type type); @@ -257,19 +283,42 @@ int smack_have_access(const char *subject, const char *object, char access_type_k[ACC_LEN + 1]; int ret; int fd; + int access2 = 1; + char path[PATH_MAX]; + + if (!smack_mnt) { + errno = EFAULT; + return -1; + } + + snprintf(path, sizeof path, "%s/access2", smack_mnt); + fd = open(path, O_RDWR); + if (fd < 0) { + if (errno != ENOENT) + return -1; + + snprintf(path, sizeof path, "%s/access", smack_mnt); + fd = open(path, O_RDWR); + if (fd < 0) + return -1; + access2 = 0; + } parse_access_type(access_type, access_type_k); - ret = snprintf(buf, LOAD_LEN + 1, KERNEL_FORMAT, subject, object, - access_type_k); - if (ret < 0) - return -1; + if (access2) + ret = snprintf(buf, LOAD_LEN + 1, KERNEL_LONG_FORMAT, + subject, object, access_type_k); + else + ret = snprintf(buf, LOAD_LEN + 1, KERNEL_SHORT_FORMAT, + subject, object, access_type_k); - fd = open(SMACKFS_MNT "/access2", O_RDWR); - if (fd < 0) + if (ret < 0) { + close(fd); return -1; + } - ret = write(fd, buf, LOAD_LEN); + ret = write(fd, buf, strlen(buf)); if (ret < 0) { close(fd); return -1; @@ -282,6 +331,163 @@ int smack_have_access(const char *subject, const char *object, return buf[0] == '1'; } +void smack_cipso_free(struct smack_cipso *cipso) +{ + if (cipso == NULL) + return; + + struct cipso_mapping *mapping = cipso->first; + struct cipso_mapping *next_mapping = NULL; + + while (mapping != NULL) { + next_mapping = mapping->next; + free(mapping); + mapping = next_mapping; + } +} + +struct smack_cipso *smack_cipso_new(int fd) +{ + struct smack_cipso *cipso = NULL; + struct cipso_mapping *mapping = NULL; + FILE *file = NULL; + char buf[BUF_SIZE]; + char *label, *level, *cat, *ptr; + long int val; + int i; + int newfd; + + newfd = dup(fd); + if (newfd == -1) + return NULL; + + file = fdopen(newfd, "r"); + if (file == NULL) { + close(newfd); + return NULL; + } + + cipso = calloc(sizeof(struct smack_cipso ), 1); + if (cipso == NULL) { + fclose(file); + return NULL; + } + + while (fgets(buf, BUF_SIZE, file) != NULL) { + mapping = calloc(sizeof(struct cipso_mapping), 1); + if (mapping == NULL) + goto err_out; + + label = strtok_r(buf, " \t\n", &ptr); + level = strtok_r(NULL, " \t\n", &ptr); + cat = strtok_r(NULL, " \t\n", &ptr); + if (label == NULL || cat == NULL || level == NULL || + strlen(label) > SMACK_LABEL_LEN) { + errno = EINVAL; + goto err_out; + } + + strcpy(mapping->label, label); + + errno = 0; + val = strtol(level, NULL, 10); + if (errno) + goto err_out; + + if (val < 0 || val > LEVEL_MAX) { + errno = ERANGE; + goto err_out; + } + + mapping->level = val; + + for (i = 0; i < CAT_MAX_COUNT && cat != NULL; i++) { + errno = 0; + val = strtol(cat, NULL, 10); + if (errno) + goto err_out; + + if (val < 0 || val > CAT_MAX_VALUE) { + errno = ERANGE; + goto err_out; + } + + mapping->cats[i] = val; + + cat = strtok_r(NULL, " \t\n", &ptr); + } + + mapping->ncats = i; + + if (cipso->first == NULL) { + cipso->first = cipso->last = mapping; + } else { + cipso->last->next = mapping; + cipso->last = mapping; + } + } + + if (ferror(file)) + goto err_out; + + fclose(file); + return cipso; +err_out: + fclose(file); + smack_cipso_free(cipso); + free(mapping); + return NULL; +} + +const char *smack_smackfs_path(void) +{ + return smack_mnt; +} + +int smack_cipso_apply(struct smack_cipso *cipso) +{ + struct cipso_mapping *m = NULL; + char buf[CIPSO_MAX_SIZE]; + int fd; + int i; + char path[PATH_MAX]; + int offset=0; + + if (!smack_mnt) { + errno = EFAULT; + return -1; + } + + snprintf(path, sizeof path, "%s/cipso2", smack_mnt); + fd = open(path, O_WRONLY); + if (fd < 0) + return -1; + + memset(buf,0,CIPSO_MAX_SIZE); + for (m = cipso->first; m != NULL; m = m->next) { + snprintf(buf, SMACK_LABEL_LEN + 1, "%s", m->label); + offset += strlen(buf) + 1; + + sprintf(&buf[offset], CIPSO_NUM_LEN_STR, m->level); + offset += NUM_LEN; + + sprintf(&buf[offset], CIPSO_NUM_LEN_STR, m->ncats); + offset += NUM_LEN; + + for (i = 0; i < m->ncats; i++){ + sprintf(&buf[offset], CIPSO_NUM_LEN_STR, m->cats[i]); + offset += NUM_LEN; + } + + if (write(fd, buf, offset) < 0) { + close(fd); + return -1; + } + } + + close(fd); + return 0; +} int smack_new_label_from_self(char **label) { @@ -321,7 +527,7 @@ int smack_new_label_from_socket(int fd, char **label) if (ret < 0 && errno != ERANGE) return -1; - result = calloc(length + 1, 1); + result = calloc(length + 1, 1); if (result == NULL) return -1; @@ -359,12 +565,19 @@ int smack_revoke_subject(const char *subject) { int ret; int fd; + int len; + char path[PATH_MAX]; + + len = strnlen(subject, SMACK_LABEL_LEN + 1); + if (len > SMACK_LABEL_LEN) + return -1; - fd = open(SMACKFS_MNT "/revoke-subject", O_RDWR); + snprintf(path, sizeof path, "%s/revoke-subject", smack_mnt); + fd = open(path, O_WRONLY); if (fd < 0) return -1; - ret = write(fd, subject, strnlen(subject, SMACK_LABEL_LEN)); + ret = write(fd, subject, len); close(fd); return (ret < 0) ? -1 : 0; @@ -475,34 +688,65 @@ static int accesses_apply(struct smack_accesses *handle, int clear) int fd; int load_fd; int change_fd; - int size; + int load2 = 1; + char path[PATH_MAX]; - load_fd = open(SMACKFS_MNT "/load2", O_WRONLY); - change_fd = open(SMACKFS_MNT "/change-rule", O_WRONLY); + if (!smack_mnt) { + errno = EFAULT; + return -1; + } + + snprintf(path, sizeof path, "%s/load2", smack_mnt); + load_fd = open(path, O_WRONLY); + if (load_fd < 0) { + if (errno != ENOENT) + return -1; + /* fallback */ + snprintf(path, sizeof path, "%s/load", smack_mnt); + load_fd = open(path, O_WRONLY); + /* Try to continue if the file doesn't exist, we might not need it. */ + if (load_fd < 0 && errno != ENOENT) + return -1; + load2 = 0; + } + + snprintf(path, sizeof path, "%s/change-rule", smack_mnt); + change_fd = open(path, O_WRONLY); + /* Try to continue if the file doesn't exist, we might not need it. */ + if (change_fd < 0 && errno != ENOENT) { + ret = -1; + goto err_out; + } for (rule = handle->first; rule != NULL; rule = rule->next) { - fd = load_fd; if (clear) { - size = snprintf(buf, LOAD_LEN + 1, KERNEL_FORMAT, rule->subject, rule->object, "-----"); - } else { - - if (rule->is_modify) { - fd = change_fd; - size = snprintf(buf, LOAD_LEN + 1, KERNEL_FORMAT_MODIFY, - rule->subject, rule->object, rule->access_add, rule->access_del); + strcpy(rule->access_set, "-----"); + rule->is_modify = 0; + } - } else { - size = snprintf(buf, LOAD_LEN + 1, KERNEL_FORMAT, - rule->subject, rule->object, rule->access_set); - } + if (rule->is_modify) { + fd = change_fd; + ret = snprintf(buf, LOAD_LEN + 1, KERNEL_MODIFY_FORMAT, + rule->subject, rule->object, + rule->access_add, rule->access_del); + } else { + fd = load_fd; + if (load2) + ret = snprintf(buf, LOAD_LEN + 1, KERNEL_LONG_FORMAT, + rule->subject, rule->object, + rule->access_set); + else + ret = snprintf(buf, LOAD_LEN + 1, KERNEL_SHORT_FORMAT, + rule->subject, rule->object, + rule->access_set); } - if (size == -1 || size > LOAD_LEN || fd == -1) { + if (ret < 0 || fd < 0) { ret = -1; goto err_out; } - ret = write(fd, buf, size); + ret = write(fd, buf, strlen(buf)); if (ret < 0) { ret = -1; goto err_out; diff --git a/libsmack/libsmack.sym b/libsmack/libsmack.sym index 18bb4e1..1d5c25c 100644 --- a/libsmack/libsmack.sym +++ b/libsmack/libsmack.sym @@ -9,6 +9,10 @@ global: smack_accesses_add_modify; smack_accesses_add_from_file; smack_have_access; + smack_cipso_free; + smack_cipso_new; + smack_cipso_apply; + smack_smackfs_path; smack_new_label_from_self; smack_new_label_from_socket; smack_set_label_for_self; diff --git a/libsmack/sys/smack.h b/libsmack/sys/smack.h index f5c0277..50504a5 100644 --- a/libsmack/sys/smack.h +++ b/libsmack/sys/smack.h @@ -52,6 +52,11 @@ enum smack_label_type { */ struct smack_accesses; +/*! + * + */ +struct smack_cipso; + #ifdef __cplusplus extern "C" { #endif @@ -146,6 +151,17 @@ int smack_accesses_add_from_file(struct smack_accesses *accesses, int fd); int smack_have_access(const char *subject, const char *object, const char *access_type); +struct smack_cipso *smack_cipso_new(int fd); + +void smack_cipso_free(struct smack_cipso *cipso); + +int smack_cipso_apply(struct smack_cipso *cipso); + +/*! + * Get the smackfs directory. + */ +const char *smack_smackfs_path(void); + /*! * Get the label that is associated with the callers process. * Caller is responsible of freeing the returned label. diff --git a/utils/common.c b/utils/common.c index 02e5644..2f51815 100644 --- a/utils/common.c +++ b/utils/common.c @@ -34,51 +34,33 @@ #include #include #include +#include -#define SMACKFS_MAGIC 0x43415d53 -#define CAT_MAX_COUNT 240 -#define CAT_MAX_VALUE 63 -#define LEVEL_MAX 255 -#define NUM_LEN 4 - -#define CIPSO_POS(i) (SMACK_LABEL_LEN + 1 + NUM_LEN + NUM_LEN + i * NUM_LEN) -#define CIPSO_MAX_SIZE CIPSO_POS(CAT_MAX_COUNT) -#define CIPSO_NUM_LEN_STR "%-4d" - -#define BUF_SIZE 512 - -struct cipso_mapping { - char label[SMACK_LABEL_LEN + 1]; - int cats[CAT_MAX_VALUE]; - int ncats; - int level; - struct cipso_mapping *next; -}; - -struct cipso { - struct cipso_mapping *first; - struct cipso_mapping *last; -}; +#define SMACK_MAGIC 0x43415d53 static int apply_rules_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); static int apply_cipso_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); -static struct cipso *cipso_new(int fd); -static void cipso_free(struct cipso *cipso); -static int cipso_apply(struct cipso *cipso); int is_smackfs_mounted(void) { struct statfs sfs; int ret; + const char * smack_mnt; + + smack_mnt = smack_smackfs_path(); + if (!smack_mnt) { + errno = EFAULT; + return -1; + } do { - ret = statfs(SMACKFS_MNT, &sfs); + ret = statfs(smack_mnt, &sfs); } while (ret < 0 && errno == EINTR); if (ret) return -1; - if (sfs.f_type == SMACKFS_MAGIC) + if (sfs.f_type == SMACK_MAGIC) return 1; return 0; @@ -88,11 +70,20 @@ int clear(void) { int fd; int ret; + const char * smack_mnt; + char path[PATH_MAX]; + + smack_mnt = smack_smackfs_path(); + if (!smack_mnt) { + errno = EFAULT; + return -1; + } if (is_smackfs_mounted() != 1) return -1; - fd = open(SMACKFS_MNT "/load2", O_RDONLY); + snprintf(path, sizeof path, "%s/load2", smack_mnt); + fd = open(path, O_RDONLY); if (fd < 0) return -1; @@ -170,15 +161,15 @@ int apply_rules_file(int fd, int clear) int apply_cipso_file(int fd) { - struct cipso *cipso = NULL; + struct smack_cipso *cipso = NULL; int ret; - cipso = cipso_new(fd); + cipso = smack_cipso_new(fd); if (cipso == NULL) return -1; - ret = cipso_apply(cipso); - cipso_free(cipso); + ret = smack_cipso_apply(cipso); + smack_cipso_free(cipso); if (ret) return -1; @@ -222,140 +213,3 @@ static int apply_cipso_cb(const char *fpath, const struct stat *sb, int typeflag close(fd); return ret; } - -static struct cipso *cipso_new(int fd) -{ - struct cipso *cipso = NULL; - struct cipso_mapping *mapping = NULL; - FILE *file = NULL; - char buf[BUF_SIZE]; - char *label, *level, *cat, *ptr; - long int val; - int i; - int newfd; - - newfd = dup(fd); - if (newfd == -1) - return NULL; - - file = fdopen(newfd, "r"); - if (file == NULL) { - close(newfd); - return NULL; - } - - cipso = calloc(sizeof(struct cipso), 1); - if (cipso == NULL) { - fclose(file); - return NULL; - } - - while (fgets(buf, BUF_SIZE, file) != NULL) { - mapping = calloc(sizeof(struct cipso_mapping), 1); - if (mapping == NULL) - goto err_out; - - label = strtok_r(buf, " \t\n", &ptr); - level = strtok_r(NULL, " \t\n", &ptr); - cat = strtok_r(NULL, " \t\n", &ptr); - if (label == NULL || cat == NULL || level == NULL || - strlen(label) > SMACK_LABEL_LEN) { - errno = EINVAL; - goto err_out; - } - - strcpy(mapping->label, label); - - errno = 0; - val = strtol(level, NULL, 10); - if (errno) - goto err_out; - - if (val < 0 || val > LEVEL_MAX) { - errno = ERANGE; - goto err_out; - } - - mapping->level = val; - - for (i = 0; i < CAT_MAX_COUNT && cat != NULL; i++) { - errno = 0; - val = strtol(cat, NULL, 10); - if (errno) - goto err_out; - - if (val < 0 || val > CAT_MAX_VALUE) { - errno = ERANGE; - goto err_out; - } - - mapping->cats[i] = val; - - cat = strtok_r(NULL, " \t\n", &ptr); - } - - mapping->ncats = i; - - if (cipso->first == NULL) { - cipso->first = cipso->last = mapping; - } else { - cipso->last->next = mapping; - cipso->last = mapping; - } - } - - if (ferror(file)) - goto err_out; - - fclose(file); - return cipso; -err_out: - fclose(file); - cipso_free(cipso); - free(mapping); - return NULL; -} - -static void cipso_free(struct cipso *cipso) -{ - if (cipso == NULL) - return; - - struct cipso_mapping *mapping = cipso->first; - struct cipso_mapping *next_mapping = NULL; - - while (mapping != NULL) { - next_mapping = mapping->next; - free(mapping); - mapping = next_mapping; - } -} - -static int cipso_apply(struct cipso *cipso) -{ - struct cipso_mapping *m = NULL; - char buf[CIPSO_MAX_SIZE]; - int fd; - int i; - - fd = open(SMACKFS_MNT "/cipso2", O_WRONLY); - if (fd < 0) - return -1; - - for (m = cipso->first; m != NULL; m = m->next) { - sprintf(buf, "%s ", m->label); - sprintf(&buf[SMACK_LABEL_LEN + 1], CIPSO_NUM_LEN_STR, m->level); - sprintf(&buf[SMACK_LABEL_LEN + 1 + NUM_LEN], CIPSO_NUM_LEN_STR, m->ncats); - - for (i = 0; i < m->ncats; i++) - sprintf(&buf[CIPSO_POS(i)], CIPSO_NUM_LEN_STR, m->cats[i]); - - if (write(fd, buf, strlen(buf)) < 0) { - close(fd); - return -1; - } - } - - close(fd); - return 0; -} diff --git a/utils/common.h b/utils/common.h index fa12f24..0fd69ca 100644 --- a/utils/common.h +++ b/utils/common.h @@ -25,7 +25,6 @@ #ifndef COMMON_H #define COMMON_H -#define SMACKFS_MNT "/smack" #define ACCESSES_D_PATH "/etc/smack/accesses.d" #define CIPSO_D_PATH "/etc/smack/cipso.d" -- 2.7.4