[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])
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])
if HAVE_SYSTEMD
+if HAVE_SYSTEMD_NEW
+
+else
systemdsystemunit_DATA = \
smack.mount \
smack.service
endif
+endif
ExecStart=/usr/bin/smackctl apply
ExecStop=/usr/bin/smackctl clear
RemainAfterExit=yes
+
+[Install]
+WantedBy=basic.target
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
--- /dev/null
+/*
+ * 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 <passion.zhao@intel.com>
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <dlfcn.h>
+#include <sys/statvfs.h>
+#include <sys/vfs.h>
+#include <stdint.h>
+#include <limits.h>
+
+/*
+ * * 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();
+}
* Authors:
* Jarkko Sakkinen <jarkko.sakkinen@intel.com>
* Brian McGillion <brian.mcgillion@intel.com>
+ * Passion Zhao <passion.zhao@intel.com>
* Rafal Krypa <r.krypa@samsung.com>
*/
#include <sys/types.h>
#include <sys/xattr.h>
#include <unistd.h>
+#include <limits.h>
#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*);
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);
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;
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)
{
if (ret < 0 && errno != ERANGE)
return -1;
- result = calloc(length + 1, 1);
+ result = calloc(length + 1, 1);
if (result == NULL)
return -1;
{
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;
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;
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;
*/
struct smack_accesses;
+/*!
+ *
+ */
+struct smack_cipso;
+
#ifdef __cplusplus
extern "C" {
#endif
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.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
-#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;
{
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;
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;
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;
-}
#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"