From 7a9fa494cb1a9287370854d70215e967f903402b Mon Sep 17 00:00:00 2001 From: "jk7744.park" Date: Fri, 23 Oct 2015 15:08:11 +0900 Subject: [PATCH] tizen 2.4 release --- init/smack.service | 1 + libsmack/libsmack.c | 102 +++++++++- libsmack/libsmack.sym | 4 + libsmack/sys/smack.h | 51 +++++ packaging/smack.spec | 4 +- utils/Makefile.am | 12 -- utils/chsmack.c | 392 +++++++++++++++++++++++++++------------ utils/smackload-fast/Makefile.am | 5 +- 8 files changed, 439 insertions(+), 132 deletions(-) diff --git a/init/smack.service b/init/smack.service index 0a063d5..473c9cc 100644 --- a/init/smack.service +++ b/init/smack.service @@ -10,6 +10,7 @@ Type=oneshot ExecStart=/usr/bin/smackload-fast ExecStop=/usr/bin/smackctl clear RemainAfterExit=yes +SmackProcessLabel=system::smack-utils::script [Install] WantedBy=basic.target diff --git a/libsmack/libsmack.c b/libsmack/libsmack.c index 2d2d364..41dbd7e 100644 --- a/libsmack/libsmack.c +++ b/libsmack/libsmack.c @@ -57,6 +57,8 @@ #define READ_BUF_SIZE LOAD_LEN + 1 #define SELF_LABEL_FILE "/proc/self/attr/current" +#define DICT_HASH_SIZE 4096 + extern char *smack_mnt; typedef int (*getxattr_func)(void*, const char*, void*, size_t); @@ -475,8 +477,10 @@ int smack_cipso_apply(struct smack_cipso *cipso) if (fd < 0) return -1; - memset(buf,0,CIPSO_MAX_SIZE); for (m = cipso->first; m != NULL; m = m->next) { + memset(buf,0,CIPSO_MAX_SIZE); + offset = 0; + snprintf(buf, SMACK_LABEL_LEN + 1, "%s", m->label); offset += strlen(buf) + 1; @@ -834,3 +838,99 @@ static inline char* get_xattr_name(enum smack_label_type type) } } + +static inline ssize_t get_label(char *dest, const char *src, unsigned int *hash) +{ + int i; + unsigned int h = 5381;/*DJB2 hashing function magic number*/; + + if (!src || src[0] == '\0' || src[0] == '-') + return -1; + + for (i = 0; i < (SMACK_LABEL_LEN + 1) && src[i]; i++) { + if (src[i] <= ' ' || src[i] > '~') + return -1; + switch (src[i]) { + case '/': + case '"': + case '\\': + case '\'': + return -1; + default: + break; + } + + if (dest) + dest[i] = src[i]; + if (hash) + /* This efficient hash function, + * created by Daniel J. Bernstein, + * is known as DJB2 algorithm */ + h = (h << 5) + h + src[i]; + } + + if (dest && i < (SMACK_LABEL_LEN + 1)) + dest[i] = '\0'; + if (hash) + *hash = h % DICT_HASH_SIZE; + + return i < (SMACK_LABEL_LEN + 1) ? i : -1; +} + +ssize_t smack_label_length(const char *label) +{ + return get_label(NULL, label, NULL); +} + +ssize_t smack_new_label_from_path(const char *path, const char *xattr, + int follow, char **label) +{ + char buf[SMACK_LABEL_LEN + 1]; + char *result; + ssize_t ret = 0; + + ret = follow ? + getxattr(path, xattr, buf, SMACK_LABEL_LEN + 1) : + lgetxattr(path, xattr, buf, SMACK_LABEL_LEN + 1); + if (ret < 0) + return -1; + buf[ret] = '\0'; + + result = calloc(ret + 1, 1); + if (result == NULL) + return -1; + + ret = get_label(result, buf, NULL); + if (ret < 0) { + free(result); + return -1; + } + + *label = result; + return ret; +} + +int smack_set_label_for_path(const char *path, + const char *xattr, + int follow, + const char *label) +{ + int len; + int ret; + + len = (int)smack_label_length(label); + if (len < 0) + return -2; + + ret = follow ? + setxattr(path, xattr, label, len, 0) : + lsetxattr(path, xattr, label, len, 0); + return ret; +} + +int smack_remove_label_for_path(const char *path, + const char *xattr, + int follow) +{ + return follow ? removexattr(path, xattr) : lremovexattr(path, xattr); +} diff --git a/libsmack/libsmack.sym b/libsmack/libsmack.sym index 1d5c25c..362012c 100644 --- a/libsmack/libsmack.sym +++ b/libsmack/libsmack.sym @@ -23,6 +23,10 @@ global: smack_setlabel; smack_lsetlabel; smack_fsetlabel; + smack_label_length; + smack_new_label_from_path; + smack_set_label_for_path; + smack_remove_label_for_path; local: *; }; diff --git a/libsmack/sys/smack.h b/libsmack/sys/smack.h index 50504a5..8e3c885 100644 --- a/libsmack/sys/smack.h +++ b/libsmack/sys/smack.h @@ -280,6 +280,57 @@ int smack_lsetlabel(const char *path, const char* label, int smack_fsetlabel(int fd, const char* label, enum smack_label_type type); +/*! + * Validate a SMACK label and calculate its length. + * + * @param label label to verify + * @return Returns length of the label on success and negative on failure. + */ +ssize_t smack_label_length(const char *label); + +/*! + * Get the SMACK label that is contained in an extended attribute. + * Caller is responsible of freeing the returned label. + * + * @param path path of the file + * @param xattr the extended attribute containing the SMACK label + * @param follow whether or not to follow symbolic link + * @param label output variable for the returned label + * @return Returns length of the label on success and negative value + * on failure. + */ +ssize_t smack_new_label_from_path(const char *path, + const char *xattr, + int follow, + char **label); + +/*! + * Set the SMACK label in an extended attribute. + * + * @param path path of the file + * @param xattr the extended attribute containing the SMACK label + * @param follow whether or not to follow symbolic link + * @param label output variable for the returned label + * @return Returns length of the label on success and negative value + * on failure. + */ +int smack_set_label_for_path(const char *path, + const char *xattr, + int follow, + const char *label); + +/*! + * Remove the SMACK label in an extended attribute. + * + * @param path path of the file + * @param xattr the extended attribute containing the SMACK label + * @param follow whether or not to follow symbolic link + * @return Returns 0 on success and negative on failure. + */ +int smack_remove_label_for_path(const char *path, + const char *xattr, + int follow); + #ifdef __cplusplus } #endif diff --git a/packaging/smack.spec b/packaging/smack.spec index 7dd3343..295fdeb 100644 --- a/packaging/smack.spec +++ b/packaging/smack.spec @@ -12,6 +12,7 @@ Source3: smack-utils.manifest BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: automake autoconf libtool +Provides: libsmack %description Library allows applications to work with Smack @@ -39,7 +40,8 @@ Tools provided to load and unload rules from the kernel and query the policy autoreconf --install --symlink %build -%configure --with-systemdsystemunitdir=%{_libdir}/systemd/system +%configure --with-systemdsystemunitdir=%{_libdir}/systemd/system CFLAGS=-fPIE LDFLAGS=-pie + make %{?_smp_mflags} %install diff --git a/utils/Makefile.am b/utils/Makefile.am index ddef4dc..83bcddf 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -5,33 +5,21 @@ AM_CPPFLAGS = \ smackctl_SOURCES = smackctl.c common.c smackctl_LDADD = ../libsmack/libsmack.la -smackctl_LDFLAGS = -pie -smackctl_CFLAGS = -fPIE smackaccess_SOURCES = smackaccess.c smackaccess_LDADD = ../libsmack/libsmack.la -smackaccess_LDFLAGS = -pie -smackaccess_CFLAGS = -fPIE smackload_SOURCES = smackload.c common.c smackload_LDADD = ../libsmack/libsmack.la -smackload_LDFLAGS = -pie -smackload_CFLAGS = -fPIE smackcipso_SOURCES = smackcipso.c common.c smackcipso_LDADD = ../libsmack/libsmack.la -smackcipso_LDFLAGS = -pie -smackcipso_CFLAGS = -fPIE smackd_SOURCES = smackd.c common.c smackd_LDADD = ../libsmack/libsmack.la -smackd_LDFLAGS = -pie -smackd_CFLAGS = -fPIE chsmack_SOURCES = chsmack.c chsmack_LDADD = ../libsmack/libsmack.la -chsmack_LDFLAGS = -pie -chsmack_CFLAGS = -fPIE EXTRA_DIST = common.h diff --git a/utils/chsmack.c b/utils/chsmack.c index 2a40687..49e4ca5 100644 --- a/utils/chsmack.c +++ b/utils/chsmack.c @@ -2,149 +2,313 @@ * chsmack - Set smack attributes on files * * Copyright (C) 2011 Nokia Corporation. - * Copyright (C) 2012 Samsung Electronics Co. + * Copyright (C) 2011, 2012, 2013 Intel Corporation * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2. * - * This program 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 - * General Public License for more details. + * This program 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 + * General Public License for more details. * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * Author: - * Casey Schaufler - * Rafal Krypa + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA */ #include #include +#include +#include #include #include #include #include #include #include +#include +#include +#include +static const char usage[] = + "Usage: %s [options] \n" + "options:\n" + " -v --version output version information and exit\n" + " -h --help output usage information and exit\n" + " -a --access set/remove "XATTR_NAME_SMACK"\n" + " -e --exec set/remove "XATTR_NAME_SMACKEXEC"\n" + " -m --mmap set/remove "XATTR_NAME_SMACKMMAP"\n" + " -t --transmute set/remove "XATTR_NAME_SMACKTRANSMUTE"\n" + " -d --remove tell to remove the attribute\n" + " -L --dereference tell to follow the symbolic links\n" +; -static inline int leads(char *in, char *lead) +/* main */ +int main(int argc, char *argv[]) { - return (strncmp(in, lead, strlen(lead)) == 0); -} + static const char shortoptions[] = "vha::e::m::tdL"; + static struct option options[] = { + {"version", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {"access", optional_argument, 0, 'a'}, + {"exec", optional_argument, 0, 'e'}, + {"mmap", optional_argument, 0, 'm'}, + {"transmute", no_argument, 0, 't'}, + {"dereference", no_argument, 0, 'L'}, + {NULL, 0, 0, 0} + }; -int -main(int argc, char *argv[]) -{ + /* Buffers are zeroed automatically by keeping them static variables. + * No separate memset is needed this way. + */ + static int options_map[128]; + + /* structure for recording options of label and their init */ + struct labelset { + int isset; /* 0 if option not set, 1 if option set */ + const char *value; /* value of the option set if any or NULL else */ + }; + struct labelset access_set = { 0, NULL }; /* for option "access" */ + struct labelset exec_set = { 0, NULL }; /* for option "exec" */ + struct labelset mmap_set = { 0, NULL }; /* for option "mmap" */ + + struct labelset *labelset; + struct stat st; + char *label; + + int delete_flag = 0; + int follow_flag = 0; + int transmute_flag = 0; + int option_flag = 0; int rc; - int argi; - int transmute = 0; - char *buffer; - char *access = NULL; - char *mm = NULL; - char *execute = NULL; - - for (argi = 1; argi < argc; argi++) { - if (strcmp(argv[argi], "-a") == 0) - access = argv[++argi]; - else if (leads(argv[argi], "--access=")) - access = argv[argi] + strlen("--access="); - else if (strcmp(argv[argi], "-e") == 0) - execute = argv[++argi]; - else if (leads(argv[argi], "--exec=")) - execute = argv[argi] + strlen("--exec="); - else if (leads(argv[argi], "--execute=")) - execute = argv[argi] + strlen("--execute="); - else if (strcmp(argv[argi], "-m") == 0) - mm = argv[++argi]; - else if (leads(argv[argi], "--mmap=")) - mm = argv[argi] + strlen("--mmap="); - else if (strcmp(argv[argi], "-t") == 0) - transmute = 1; - else if (strcmp(argv[argi], "--transmute") == 0) - transmute = 1; - else if (*argv[argi] == '-') { - fprintf(stderr, "Invalid argument \"%s\".\n", - argv[argi]); - exit(1); + int c; + int i; + + for (i = 0; options[i].name != NULL; i++) + options_map[options[i].val] = i; + + /* scan options without argument */ + while ((c = getopt_long(argc, argv, shortoptions, options, NULL)) != -1) { + + switch (c) { + case 'a': + case 'e': + case 'm': + /* greedy on optional arguments */ + if (optarg == NULL && argv[optind] != NULL + && argv[optind][0] != '-') { + optind++; + } + break; + case 't': + if (transmute_flag) + fprintf(stderr, "%s: %s: option set many times.\n", + basename(argv[0]), options[options_map[c]].name); + transmute_flag = 1; + option_flag = 1; + break; + case 'd': + if (delete_flag) + fprintf(stderr, "%s: %s: option set many times.\n", + basename(argv[0]), options[options_map[c]].name); + delete_flag = 1; + break; + case 'L': + if (follow_flag) + fprintf(stderr, "%s: %s: option set many times.\n", + basename(argv[0]), options[options_map[c]].name); + follow_flag = 1; + break; + case 'v': + printf("%s (libsmack) version " PACKAGE_VERSION "\n", + basename(argv[0])); + exit(0); + case 'h': + printf(usage, basename(argv[0])); + exit(0); + default: + printf(usage, basename(argv[0])); + exit(1); } - /* - * Indicates the start of filenames. - */ - else - break; } - if (argi >= argc) { - fprintf(stderr, "No files specified.\n"); - exit(1); - } - if (access != NULL && strlen(access) > SMACK_LABEL_LEN) { - fprintf(stderr, "Access label \"%s\" exceeds %d characters.\n", - access, SMACK_LABEL_LEN); - exit(1); + + /* scan options with argument (possibly) */ + optind = 1; + while ((c = getopt_long(argc, argv, shortoptions, options, NULL)) != -1) { + + switch (c) { + case 'a': + labelset = &access_set; + break; + case 'e': + labelset = &exec_set; + break; + case 'm': + labelset = &mmap_set; + break; + default: + continue; + } + + if (labelset->isset) { + fprintf(stderr, "%s: %s: option set many times.\n", + basename(argv[0]), options[options_map[c]].name); + exit(1); + } + /* greedy on optional arguments */ + if (optarg == NULL && argv[optind] != NULL && argv[optind][0] != '-') { + optarg = argv[optind++]; + } + if (optarg == NULL) { + if (!delete_flag) { + fprintf(stderr, "%s: %s: requires a label when setting.\n", + basename(argv[0]), options[options_map[c]].name); + exit(1); + } + } + else if (delete_flag) { + fprintf(stderr, "%s: %s: requires no label when deleting.\n", + basename(argv[0]), options[options_map[c]].name); + exit(1); + } + else if (strnlen(optarg, SMACK_LABEL_LEN + 1) == SMACK_LABEL_LEN + 1) { + fprintf(stderr, "%s: %s: \"%s\" exceeds %d characters.\n", + basename(argv[0]), options[options_map[c]].name, optarg, + SMACK_LABEL_LEN); + exit(1); + } + else if (smack_label_length(optarg) < 0) { + fprintf(stderr, "%s: %s: \"%s\" is an invalid Smack label.\n", + basename(argv[0]), options[options_map[c]].name, optarg); + exit(1); + } + labelset->isset = 1; + labelset->value = optarg; + option_flag = 1; } - if (mm != NULL && strlen(mm) > SMACK_LABEL_LEN) { - fprintf(stderr, "mmap label \"%s\" exceeds %d characters.\n", - mm, SMACK_LABEL_LEN); - exit(1); + + /* deleting labels */ + if (delete_flag) { + if (!option_flag) { + access_set.isset = 1; + exec_set.isset = 1; + mmap_set.isset = 1; + transmute_flag = 1; + } + for (i = optind; i < argc; i++) { + if (access_set.isset) { + rc = smack_remove_label_for_path(argv[i], + XATTR_NAME_SMACK, follow_flag); + if (rc < 0 && (option_flag || errno != ENODATA)) + perror(argv[i]); + } + + if (exec_set.isset) { + rc = smack_remove_label_for_path(argv[i], + XATTR_NAME_SMACKEXEC, follow_flag); + if (rc < 0 && (option_flag || errno != ENODATA)) + perror(argv[i]); + } + + if (mmap_set.isset) { + rc = smack_remove_label_for_path(argv[i], + XATTR_NAME_SMACKMMAP, follow_flag); + if (rc < 0 && (option_flag || errno != ENODATA)) + perror(argv[i]); + } + + if (transmute_flag) { + rc = smack_remove_label_for_path(argv[i], + XATTR_NAME_SMACKTRANSMUTE, follow_flag); + if (rc < 0 && (option_flag || errno != ENODATA)) + perror(argv[i]); + } + } } - if (execute != NULL && strlen(execute) > SMACK_LABEL_LEN) { - fprintf(stderr, "execute label \"%s\" exceeds %d characters.\n", - execute, SMACK_LABEL_LEN); - exit(1); + + /* setting labels */ + else if (option_flag) { + for (i = optind; i < argc; i++) { + if (access_set.isset) { + rc = smack_set_label_for_path(argv[i], + XATTR_NAME_SMACK, follow_flag, access_set.value); + if (rc < 0) + perror(argv[i]); + } + + if (exec_set.isset) { + rc = smack_set_label_for_path(argv[i], + XATTR_NAME_SMACKEXEC, follow_flag, exec_set.value); + if (rc < 0) + perror(argv[i]); + } + + if (mmap_set.isset) { + rc = smack_set_label_for_path(argv[i], + XATTR_NAME_SMACKMMAP, follow_flag, mmap_set.value); + if (rc < 0) + perror(argv[i]); + } + + if (transmute_flag) { + rc = follow_flag ? stat(argv[i], &st) : lstat(argv[i], &st); + if (rc < 0) + perror(argv[i]); + else if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "%s: transmute: not a directory %s\n", + basename(argv[0]), argv[i]); + } + else { + rc = smack_set_label_for_path(argv[i], + XATTR_NAME_SMACKTRANSMUTE, follow_flag, "TRUE"); + if (rc < 0) + perror(argv[i]); + } + } + } } - for (; argi < argc; argi++) { - if (access == NULL && mm == NULL && - execute == NULL && !transmute) { - printf("%s", argv[argi]); - rc = smack_lgetlabel(argv[argi], &buffer, SMACK_LABEL_ACCESS); - if (rc == 0 && buffer != NULL) { - printf(" access=\"%s\"", buffer); - free(buffer); + + /* listing labels */ + else { + for (i = optind; i < argc; i++) { + + /* Print file path. */ + printf("%s", argv[i]); + + rc = (int)smack_new_label_from_path(argv[i], + XATTR_NAME_SMACK, follow_flag, &label); + if (rc > 0) { + printf(" access=\"%s\"", label); + free(label); } - rc = smack_lgetlabel(argv[argi], &buffer, SMACK_LABEL_EXEC); - if (rc == 0 && buffer != NULL) { - printf(" execute=\"%s\"", buffer); - free(buffer); + + rc = (int)smack_new_label_from_path(argv[i], + XATTR_NAME_SMACKEXEC, follow_flag, &label); + if (rc > 0) { + printf(" execute=\"%s\"", label); + free(label); } - rc = smack_lgetlabel(argv[argi], &buffer, SMACK_LABEL_MMAP); - if (rc == 0 && buffer != NULL) { - printf(" mmap=\"%s\"", buffer); - free(buffer); + + rc = (int)smack_new_label_from_path(argv[i], + XATTR_NAME_SMACKMMAP, follow_flag, &label); + if (rc > 0) { + printf(" mmap=\"%s\"", label); + free(label); } - rc = smack_lgetlabel(argv[argi], &buffer, SMACK_LABEL_TRANSMUTE); - if (rc == 0 && buffer != NULL) { - printf(" transmute=\"%s\"", buffer); - free(buffer); + + rc = (int)smack_new_label_from_path(argv[i], + XATTR_NAME_SMACKTRANSMUTE, follow_flag, &label); + if (rc > 0) { + printf(" transmute=\"%s\"", label); + free(label); } + printf("\n"); - continue; - } - if (access != NULL) { - rc = smack_lsetlabel(argv[argi], access, SMACK_LABEL_ACCESS); - if (rc < 0) - perror(argv[argi]); - } - if (execute != NULL) { - rc = smack_lsetlabel(argv[argi], execute, SMACK_LABEL_EXEC); - if (rc < 0) - perror(argv[argi]); - } - if (mm != NULL) { - rc = smack_lsetlabel(argv[argi], mm, SMACK_LABEL_MMAP); - if (rc < 0) - perror(argv[argi]); - } - if (transmute) { - rc = smack_lsetlabel(argv[argi], "1", SMACK_LABEL_TRANSMUTE); - if (rc < 0) - perror(argv[argi]); } } + exit(0); } diff --git a/utils/smackload-fast/Makefile.am b/utils/smackload-fast/Makefile.am index 32a015e..01c101d 100644 --- a/utils/smackload-fast/Makefile.am +++ b/utils/smackload-fast/Makefile.am @@ -4,12 +4,9 @@ noinst_PROGRAMS = genmodes genmodes_SOURCES = genmodes.c smackload_fast_SOURCES = main.c input.c output.c common.h -smackload_fast_LDFLAGS = -pie -smackload_fast_CPPFLAGS = -fPIE nodist_smackload_fast_SOURCES = modes.h -BUILD_SOURCES: modes.h -output.c: modes.h +output.$(OBJEXT): modes.h CLEANFILES = modes.h modes.h: genmodes -- 2.7.4