From b9c9957d2b3b90f4a79a28c87d0e7bdd95bab32d Mon Sep 17 00:00:00 2001 From: "Passion,Zhao" Date: Mon, 5 Nov 2012 20:27:10 +0800 Subject: [PATCH] Add support for smackfs directory: /sys/fs/smackfs/ Signed-off-by: Passion,Zhao Suggested-by: Jarkko Sakkinen --- libsmack/Makefile.am | 2 +- libsmack/dso.h | 54 ++++++++++++++ libsmack/init.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++ libsmack/libsmack.c | 50 ++++++++++--- libsmack/libsmack.sym | 1 + libsmack/sys/smack.h | 5 ++ utils/common.c | 25 ++++++- utils/common.h | 1 - 8 files changed, 323 insertions(+), 16 deletions(-) create mode 100644 libsmack/dso.h create mode 100644 libsmack/init.c 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/dso.h b/libsmack/dso.h new file mode 100644 index 0000000..88b9b72 --- /dev/null +++ b/libsmack/dso.h @@ -0,0 +1,54 @@ +/* + * This file is part of libsmack. Derived from libselinux/src/dso.h. + * + * 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 + */ + +#ifndef _SMACK_DSO_H +#define _SMACK_DSO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SHARED +# define hidden __attribute__ ((visibility ("hidden"))) +# define hidden_proto(fct) __hidden_proto (fct, fct##_internal) +# define __hidden_proto(fct, internal) \ + extern __typeof (fct) internal; \ + extern __typeof (fct) fct __asm (#internal) hidden; +# if defined(__alpha__) || defined(__mips__) +# define hidden_def(fct) \ + asm (".globl " #fct "\n" #fct " = " #fct "_internal"); +# else +# define hidden_def(fct) \ + asm (".globl " #fct "\n.set " #fct ", " #fct "_internal"); +#endif +#else +# define hidden +# define hidden_proto(fct) +# define hidden_def(fct) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsmack/init.c b/libsmack/init.c new file mode 100644 index 0000000..d12f445 --- /dev/null +++ b/libsmack/init.c @@ -0,0 +1,201 @@ +/* + * 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 + +#include "dso.h" + +/* + * * smackfs magic number + * */ +#define SMACK_MAGIC 0x43415d53 /* "SMAC" */ + +/* smack file system type */ +#define SMACKFS "smackfs" + +#define SMACKFSMNT "/sys/fs/smackfs/" +#define OLDSMACKFSMNT "/smack" + +static char *smack_mnt = NULL; + +void set_smackmnt(const char *mnt) +{ + smack_mnt = strdup(mnt); +} + +hidden_def(set_smackmnt) + + +/* 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; +} + +hidden_def(smackfs_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; +} + +const char *smack_smackfs_path(void) +{ + return smack_mnt; +} + +void fini_smackmnt(void) +{ + free(smack_mnt); + smack_mnt = NULL; +} + +hidden_def(fini_smackmnt) + +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 adcdf76..3d034da 100644 --- a/libsmack/libsmack.c +++ b/libsmack/libsmack.c @@ -21,6 +21,7 @@ * Authors: * Jarkko Sakkinen * Brian McGillion + * Passion Zhao */ #include "sys/smack.h" @@ -33,6 +34,7 @@ #include #include #include +#include #define LABEL_LEN 255 #define ACC_LEN 5 @@ -56,9 +58,10 @@ #define KERNEL_LONG_FORMAT "%s %s %s" #define KERNEL_SHORT_FORMAT "%-23s %-23s %5s" #define READ_BUF_SIZE LOAD_LEN + 1 -#define SMACKFS_MNT "/smack" #define SELF_LABEL_FILE "/proc/self/attr/current" +const char *smack_mnt; + struct smack_rule { char subject[LABEL_LEN + 1]; char object[LABEL_LEN + 1]; @@ -242,20 +245,30 @@ int smack_have_access(const char *subject, const char *object, int ret; int fd; int access2 = 1; + char path[PATH_MAX]; - access_code = access_type_to_int(access_type); - int_to_access_type_k(access_code, access_type_k); - - fd = open(SMACKFS_MNT "/access2", O_RDWR); + smack_mnt = smack_smackfs_path(); + 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; - fd = open(SMACKFS_MNT "/access", O_RDWR); + + snprintf(path, sizeof path, "%s/access", smack_mnt); + fd = open(path, O_RDWR); if (fd < 0) return -1; access2 = 0; } + access_code = access_type_to_int(access_type); + int_to_access_type_k(access_code, access_type_k); + if (access2) ret = snprintf(buf, LOAD_LEN + 1, KERNEL_LONG_FORMAT, subject, object, access_type_k); @@ -395,8 +408,16 @@ int smack_cipso_apply(struct smack_cipso *cipso) char buf[CIPSO_MAX_SIZE]; int fd; int i; + char path[PATH_MAX]; - fd = open(SMACKFS_MNT "/cipso2", O_WRONLY); + smack_mnt = smack_smackfs_path(); + 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; @@ -455,7 +476,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; @@ -477,13 +498,22 @@ static int accesses_apply(struct smack_accesses *handle, int clear) int ret; int fd; int load2 = 1; + char path[PATH_MAX]; - fd = open(SMACKFS_MNT "/load2", O_WRONLY); + smack_mnt = smack_smackfs_path(); + if (!smack_mnt) { + errno = EFAULT; + return -1; + } + + snprintf(path, sizeof path, "%s/load2", smack_mnt); + fd = open(path, O_WRONLY); if (fd < 0) { if (errno != ENOENT) return -1; /* fallback */ - fd = open(SMACKFS_MNT "/load", O_WRONLY); + snprintf(path, sizeof path, "%s/load", smack_mnt); + fd = open(path, O_WRONLY); if (fd < 0) return -1; load2 = 0; diff --git a/libsmack/libsmack.sym b/libsmack/libsmack.sym index ed9da3c..f1b3cc1 100644 --- a/libsmack/libsmack.sym +++ b/libsmack/libsmack.sym @@ -11,6 +11,7 @@ global: smack_cipso_free; smack_cipso_new; smack_cipso_apply; + smack_smackfs_path; smack_new_label_from_self; smack_new_label_from_socket; local: diff --git a/libsmack/sys/smack.h b/libsmack/sys/smack.h index 28cce4e..ce0c0c1 100644 --- a/libsmack/sys/smack.h +++ b/libsmack/sys/smack.h @@ -124,6 +124,11 @@ 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 afa33a4..2f51815 100644 --- a/utils/common.c +++ b/utils/common.c @@ -34,8 +34,9 @@ #include #include #include +#include -#define SMACKFS_MAGIC 0x43415d53 +#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); @@ -44,15 +45,22 @@ 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; @@ -62,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; diff --git a/utils/common.h b/utils/common.h index 5606e96..8446828 100644 --- a/utils/common.h +++ b/utils/common.h @@ -26,7 +26,6 @@ #define COMMON_H #define LABEL_LEN 255 -#define SMACKFS_MNT "/smack" #define ACCESSES_D_PATH "/etc/smack/accesses.d" #define CIPSO_D_PATH "/etc/smack/cipso.d" -- 2.7.4