2 * This file is part of libsmack
4 * Copyright (C) 2010, 2011 Nokia Corporation
5 * Copyright (C) 2011, 2012, 2013 Intel Corporation
6 * Copyright (C) 2012, 2013 Samsung Electronics Co.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * version 2.1 as published by the Free Software Foundation.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 #include "sys/smack.h"
30 #include <sys/socket.h>
32 #include <sys/types.h>
33 #include <sys/xattr.h>
35 #include <sys/xattr.h>
37 #define SELF_LABEL_FILE "/proc/self/attr/current"
39 #define SHORT_LABEL_LEN 23
41 #define LOAD_LEN (2 * (SMACK_LABEL_LEN + 1) + 2 * ACC_LEN + 1)
42 #define KERNEL_LONG_FORMAT "%s %s %s"
43 #define KERNEL_SHORT_FORMAT "%-23s %-23s %5.5s"
44 #define KERNEL_MODIFY_FORMAT "%s %s %s %s"
49 #define CAT_MAX_COUNT 184
50 #define CIPSO_POS(i) (SMACK_LABEL_LEN + 1 + NUM_LEN + NUM_LEN + i * NUM_LEN)
51 #define CIPSO_MAX_SIZE CIPSO_POS(CAT_MAX_COUNT)
52 #define CIPSO_NUM_LEN_STR "%-4d"
54 #define BITMASK(b) (1 << ((b) & 7))
55 #define BITSLOT(b) ((b) >> 3)
56 #define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
57 #define BITTEST(a, b) ((a)[BITSLOT(b)] & BITMASK(b))
58 #define BITNSLOTS(nb) ((nb + 7) >> 3)
60 #define ACCESS_TYPE_R 0x01
61 #define ACCESS_TYPE_W 0x02
62 #define ACCESS_TYPE_X 0x04
63 #define ACCESS_TYPE_A 0x08
64 #define ACCESS_TYPE_T 0x10
65 #define ACCESS_TYPE_L 0x20
67 #define ACCESS_TYPE_ALL ((1 << ACC_LEN) - 1)
69 #define DICT_HASH_SIZE 4096
71 extern char *smackfs_mnt;
72 extern int smackfs_mnt_dirfd;
74 extern int init_smackfs_mnt(void);
81 uint16_t allow_deny_code;
85 union smack_perm perm;
87 struct smack_rule *next_rule;
94 struct smack_rule *first_rule;
95 struct smack_rule *last_rule;
96 struct smack_label *next_label;
99 struct smack_hash_entry {
100 struct smack_label *first;
101 struct smack_label *last;
104 struct smack_accesses {
109 struct smack_label **labels;
110 struct smack_hash_entry *label_hash;
111 union smack_perm *merge_perms;
112 int *merge_object_ids;
115 struct cipso_mapping {
116 char label[SMACK_LABEL_LEN + 1];
117 uint8_t cats[BITNSLOTS(CAT_MAX_COUNT)];
120 struct cipso_mapping *next;
125 struct cipso_mapping *first;
126 struct cipso_mapping *last;
129 typedef int (*getxattr_func)(void*, const char*, void*, size_t);
130 typedef int (*setxattr_func)(const void*, const char*, const void*, size_t, int);
131 typedef int (*removexattr_func)(void*, const char*);
133 static inline char* get_xattr_name(enum smack_label_type type);
135 struct smack_file_buffer {
142 static int open_smackfs_file(const char *long_name, const char *short_name,
143 mode_t mode, int *use_long);
144 static int accesses_apply(struct smack_accesses *handle, int clear);
145 static int accesses_print(struct smack_accesses *handle,
146 int clear, int use_long, int multiline,
147 struct smack_file_buffer *load_buffer,
148 struct smack_file_buffer *change_buffer);
149 static inline ssize_t get_label(char *dest, const char *src, unsigned int *hash);
150 static inline int str_to_access_code(const char *str);
151 static inline void access_code_to_str(unsigned code, char *str);
152 static struct smack_label *label_add(struct smack_accesses *handle, const char *src);
154 int smack_accesses_new(struct smack_accesses **accesses)
156 struct smack_accesses *result;
158 result = calloc(1, sizeof(struct smack_accesses));
162 result->labels_alloc = 128;
163 result->labels = malloc(result->labels_alloc * sizeof(struct smack_label *));
164 if (result->labels == NULL)
166 result->merge_perms = malloc(result->labels_alloc * sizeof(union smack_perm));
167 if (result->merge_perms == NULL)
169 result->merge_object_ids = malloc(result->labels_alloc * sizeof(int));
170 if (result->merge_object_ids == NULL)
173 result->label_hash = calloc(DICT_HASH_SIZE, sizeof(struct smack_hash_entry));
174 if (result->label_hash == NULL)
177 result->page_size = sysconf(_SC_PAGESIZE);
182 free(result->merge_object_ids);
183 free(result->merge_perms);
184 free(result->labels);
189 void smack_accesses_free(struct smack_accesses *handle)
191 struct smack_rule *rule;
192 struct smack_rule *next_rule;
198 for (i = 0; i < handle->labels_cnt; ++i) {
199 rule = handle->labels[i]->first_rule;
200 while (rule != NULL) {
201 next_rule = rule->next_rule;
205 free(handle->labels[i]->label);
206 free(handle->labels[i]);
209 free(handle->label_hash);
210 free(handle->merge_object_ids);
211 free(handle->merge_perms);
212 free(handle->labels);
216 int smack_accesses_save(struct smack_accesses *handle, int fd)
218 struct smack_file_buffer buffer;
222 buffer.buf = malloc(handle->page_size + LOAD_LEN);
223 if (buffer.buf == NULL)
226 ret = accesses_print(handle, 0, 1, 1, &buffer, &buffer);
231 int smack_accesses_apply(struct smack_accesses *handle)
233 return accesses_apply(handle, 0);
236 int smack_accesses_clear(struct smack_accesses *handle)
238 return accesses_apply(handle, 1);
241 static int accesses_add(struct smack_accesses *handle, const char *subject,
242 const char *object, const char *allow_access_type,
243 const char *deny_access_type)
245 struct smack_rule *rule;
246 struct smack_label *subject_label;
247 struct smack_label *object_label;
249 rule = calloc(sizeof(struct smack_rule), 1);
253 subject_label = label_add(handle, subject);
254 if (subject_label == NULL)
256 object_label = label_add(handle, object);
257 if (object_label == NULL)
260 if (subject_label->len > SHORT_LABEL_LEN ||
261 object_label->len > SHORT_LABEL_LEN)
262 handle->has_long = 1;
264 rule->object_id = object_label->id;
266 rule->perm.allow_code = str_to_access_code(allow_access_type);
267 if (rule->perm.allow_code == -1)
270 if (deny_access_type != NULL) {
271 rule->perm.deny_code = str_to_access_code(deny_access_type);
272 if (rule->perm.deny_code == -1)
275 rule->perm.deny_code = ACCESS_TYPE_ALL & ~rule->perm.allow_code;
277 if (subject_label->first_rule == NULL) {
278 subject_label->first_rule = subject_label->last_rule = rule;
280 subject_label->last_rule->next_rule = rule;
281 subject_label->last_rule = rule;
290 int smack_accesses_add(struct smack_accesses *handle, const char *subject,
291 const char *object, const char *access_type)
293 return accesses_add(handle, subject, object, access_type, NULL);
296 int smack_accesses_add_modify(struct smack_accesses *handle,
299 const char *allow_access_type,
300 const char *deny_access_type)
302 return accesses_add(handle, subject, object,
303 allow_access_type, deny_access_type);
306 int smack_accesses_add_from_file(struct smack_accesses *accesses, int fd)
309 char buf[LOAD_LEN + 1];
311 const char *subject, *object, *access, *access2;
319 file = fdopen(newfd, "r");
325 while (fgets(buf, LOAD_LEN + 1, file) != NULL) {
326 if (strcmp(buf, "\n") == 0)
328 subject = strtok_r(buf, " \t\n", &ptr);
329 object = strtok_r(NULL, " \t\n", &ptr);
330 access = strtok_r(NULL, " \t\n", &ptr);
331 access2 = strtok_r(NULL, " \t\n", &ptr);
333 if (subject == NULL || object == NULL || access == NULL ||
334 strtok_r(NULL, " \t\n", &ptr) != NULL) {
340 ret = smack_accesses_add(accesses, subject, object, access);
342 ret = smack_accesses_add_modify(accesses, subject, object, access, access2);
359 int smack_have_access(const char *subject, const char *object,
360 const char *access_type)
362 char buf[LOAD_LEN + 1];
363 char str[ACC_LEN + 1];
371 if (init_smackfs_mnt())
374 slen = get_label(NULL, subject, NULL);
375 olen = get_label(NULL, object, NULL);
377 if (slen < 0 || olen < 0)
380 fd = open_smackfs_file("access2", "access", O_RDWR, &use_long);
384 if (!use_long && (slen > SHORT_LABEL_LEN || olen > SHORT_LABEL_LEN)) {
389 if ((code = str_to_access_code(access_type)) < 0)
391 access_code_to_str(code, str);
394 ret = snprintf(buf, LOAD_LEN + 1, KERNEL_LONG_FORMAT,
395 subject, object, str);
397 ret = snprintf(buf, LOAD_LEN + 1, KERNEL_SHORT_FORMAT,
398 subject, object, str);
405 ret = write(fd, buf, strlen(buf));
411 ret = read(fd, buf, 1);
416 return buf[0] == '1';
419 int smack_cipso_new(struct smack_cipso **cipso)
421 struct smack_cipso *result;
423 result = calloc(sizeof(struct smack_cipso), 1);
431 void smack_cipso_free(struct smack_cipso *cipso)
436 struct cipso_mapping *mapping = cipso->first;
437 struct cipso_mapping *next_mapping = NULL;
439 while (mapping != NULL) {
440 next_mapping = mapping->next;
442 mapping = next_mapping;
448 int smack_cipso_apply(struct smack_cipso *cipso)
450 struct cipso_mapping *m = NULL;
451 char buf[CIPSO_MAX_SIZE];
457 if (init_smackfs_mnt())
460 fd = open_smackfs_file("cipso2", "cipso", O_WRONLY, &use_long);
464 if (!use_long && cipso->has_long)
467 memset(buf,0,CIPSO_MAX_SIZE);
468 for (m = cipso->first; m != NULL; m = m->next) {
469 offset = (int)snprintf(buf, SMACK_LABEL_LEN + 1,
470 use_long ? "%s " : "%-23s ", m->label);
472 sprintf(&buf[offset], CIPSO_NUM_LEN_STR, m->level);
475 sprintf(&buf[offset], CIPSO_NUM_LEN_STR, m->ncats);
478 for (i = 0; i < CAT_MAX_COUNT; i++) {
479 if (BITTEST(m->cats, i)) {
480 sprintf(&buf[offset], CIPSO_NUM_LEN_STR, i + 1);
485 if (write(fd, buf, offset) < 0) {
495 int smack_cipso_add_from_file(struct smack_cipso *cipso, int fd)
497 struct cipso_mapping *mapping = NULL;
500 char *label, *level, *cat, *ptr;
509 file = fdopen(newfd, "r");
515 while (fgets(buf, BUF_SIZE, file) != NULL) {
516 mapping = calloc(sizeof(struct cipso_mapping), 1);
520 label = strtok_r(buf, " \t\n", &ptr);
521 level = strtok_r(NULL, " \t\n", &ptr);
522 cat = strtok_r(NULL, " \t\n", &ptr);
527 val = get_label(mapping->label, label, NULL);
530 if (val > SHORT_LABEL_LEN)
534 val = strtol(level, NULL, 10);
538 if (val < 0 || val > LEVEL_MAX)
541 mapping->level = val;
543 for (i = 0; i < CAT_MAX_COUNT && cat != NULL; i++) {
545 val = strtol(cat, NULL, 10);
549 if (val <= 0 || val > CAT_MAX_COUNT)
552 if (!BITTEST(mapping->cats, val - 1)) {
553 BITSET(mapping->cats, val - 1);
557 cat = strtok_r(NULL, " \t\n", &ptr);
560 if (cipso->first == NULL) {
561 cipso->first = cipso->last = mapping;
563 cipso->last->next = mapping;
564 cipso->last = mapping;
579 const char *smack_smackfs_path(void)
585 ssize_t smack_new_label_from_self(char **label)
591 result = calloc(SMACK_LABEL_LEN + 1, 1);
595 fd = open(SELF_LABEL_FILE, O_RDONLY);
601 ret = read(fd, result, SMACK_LABEL_LEN);
612 ssize_t smack_new_label_from_socket(int fd, char **label)
616 socklen_t length = 1;
619 ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, &dummy, &length);
620 if (ret < 0 && errno != ERANGE)
623 result = calloc(length + 1, 1);
627 ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, result, &length);
637 ssize_t smack_new_label_from_path(const char *path, const char *xattr,
638 int follow, char **label)
640 char buf[SMACK_LABEL_LEN + 1];
645 getxattr(path, xattr, buf, SMACK_LABEL_LEN + 1) :
646 lgetxattr(path, xattr, buf, SMACK_LABEL_LEN + 1);
651 result = calloc(ret + 1, 1);
655 ret = get_label(result, buf, NULL);
665 int smack_set_label_for_self(const char *label)
671 len = get_label(NULL, label, NULL);
675 fd = open(SELF_LABEL_FILE, O_WRONLY);
679 ret = write(fd, label, len);
682 return (ret < 0) ? -1 : 0;
685 int smack_revoke_subject(const char *subject)
691 if (init_smackfs_mnt())
694 len = get_label(NULL, subject, NULL);
698 fd = openat(smackfs_mnt_dirfd, "revoke-subject", O_WRONLY);
702 ret = write(fd, subject, len);
705 return (ret < 0) ? -1 : 0;
708 static int internal_getlabel(void* file, char** label,
709 enum smack_label_type type,
710 getxattr_func getfunc)
712 char* xattr_name = get_xattr_name(type);
713 char value[SMACK_LABEL_LEN + 1];
716 ret = getfunc(file, xattr_name, value, SMACK_LABEL_LEN + 1);
718 if (errno == ENODATA) {
726 *label = calloc(ret + 1, 1);
729 strncpy(*label, value, ret);
733 static int internal_setlabel(void* file, const char* label,
734 enum smack_label_type type,
735 setxattr_func setfunc, removexattr_func removefunc)
737 char* xattr_name = get_xattr_name(type);
739 /* Check validity of labels for LABEL_TRANSMUTE */
740 if (type == SMACK_LABEL_TRANSMUTE && label != NULL) {
741 if (!strcmp(label, "0"))
743 else if (!strcmp(label, "1"))
749 if (label == NULL || label[0] == '\0') {
750 return removefunc(file, xattr_name);
752 int len = strnlen(label, SMACK_LABEL_LEN + 1);
753 if (len > SMACK_LABEL_LEN)
755 return setfunc(file, xattr_name, label, len, 0);
759 int smack_getlabel(const char *path, char** label,
760 enum smack_label_type type)
762 return internal_getlabel((void*) path, label, type,
763 (getxattr_func) getxattr);
766 int smack_lgetlabel(const char *path, char** label,
767 enum smack_label_type type)
769 return internal_getlabel((void*) path, label, type,
770 (getxattr_func) lgetxattr);
773 int smack_fgetlabel(int fd, char** label,
774 enum smack_label_type type)
776 return internal_getlabel((void*) ((unsigned long) fd), label, type,
777 (getxattr_func) fgetxattr);
780 int smack_setlabel(const char *path, const char* label,
781 enum smack_label_type type)
783 return internal_setlabel((void*) path, label, type,
784 (setxattr_func) setxattr, (removexattr_func) removexattr);
787 int smack_lsetlabel(const char *path, const char* label,
788 enum smack_label_type type)
790 return internal_setlabel((void*) path, label, type,
791 (setxattr_func) lsetxattr, (removexattr_func) lremovexattr);
794 int smack_fsetlabel(int fd, const char* label,
795 enum smack_label_type type)
797 return internal_setlabel((void*) ((unsigned long) fd), label, type,
798 (setxattr_func) fsetxattr, (removexattr_func) fremovexattr);
801 static int open_smackfs_file(const char *long_name, const char *short_name,
802 mode_t mode, int *use_long)
806 fd = openat(smackfs_mnt_dirfd, long_name, mode);
811 fd = openat(smackfs_mnt_dirfd, short_name, mode);
823 static inline int check_multiline(int change_fd)
825 /* This string will be written to kernel Smack "change-rule" interface
826 * to check if it can handle multiple rules in one write.
827 * It consists of two rules, separated by '\n': first that does nothing
828 * and second that has invalid format. If kernel parses only the first
829 * line (pre-3.12 behavior), it won't see the invalid rule and succeed.
830 * If it parses both lines, an error will be returned.
832 static const char test_str[] = "^ ^ - -\n-";
835 ret = write(change_fd, test_str, sizeof(test_str) - 1);
836 if (ret == -1 && errno == EINVAL)
841 static int accesses_apply(struct smack_accesses *handle, int clear)
846 struct smack_file_buffer load_buffer = {.fd = -1, .buf = NULL};
847 struct smack_file_buffer change_buffer = {.fd = -1, .buf = NULL};
849 if (init_smackfs_mnt())
852 load_buffer.fd = open_smackfs_file("load2", "load", O_WRONLY, &use_long);
853 if (load_buffer.fd < 0)
855 load_buffer.buf = malloc(handle->page_size + LOAD_LEN);
856 if (load_buffer.buf == NULL)
859 change_buffer.fd = openat(smackfs_mnt_dirfd, "change-rule", O_WRONLY);
860 if (change_buffer.fd >= 0) {
861 change_buffer.buf = malloc(handle->page_size + LOAD_LEN);
862 if (change_buffer.buf == NULL)
865 multiline = check_multiline(change_buffer.fd);
867 /* Try to continue if "change-rule" doesn't exist, we might
873 ret = accesses_print(handle, clear, use_long, multiline,
874 &load_buffer, &change_buffer);
880 if (load_buffer.fd >= 0)
881 close(load_buffer.fd);
882 if (change_buffer.fd >= 0)
883 close(change_buffer.fd);
884 free(load_buffer.buf);
885 free(change_buffer.buf);
889 static int buffer_flush(struct smack_file_buffer *buf)
894 /* Write buffered bytes to kernel, up to flush_pos */
895 for (pos = 0; pos < buf->flush_pos; ) {
896 ret = write(buf->fd, buf->buf + pos, buf->flush_pos - pos);
904 /* Move remaining, not flushed bytes to the buffer start */
905 memcpy(buf->buf, buf->buf + pos, buf->pos - pos);
912 static inline void rule_print_long(char *buf, int *pos,
913 struct smack_label *subject_label, struct smack_label *object_label,
914 const char *allow_str, const char *deny_str)
916 memcpy(buf + *pos, subject_label->label, subject_label->len);
917 *pos += subject_label->len;
919 memcpy(buf + *pos, object_label->label, object_label->len);
920 *pos += object_label->len;
922 memcpy(buf + *pos, allow_str, ACC_LEN);
924 if (deny_str != NULL) {
926 memcpy(buf + *pos, deny_str, ACC_LEN);
931 static int accesses_print(struct smack_accesses *handle, int clear,
932 int use_long, int multiline,
933 struct smack_file_buffer *load_buffer,
934 struct smack_file_buffer *change_buffer)
936 struct smack_file_buffer *buffer;
937 char allow_str[ACC_LEN + 1];
938 char deny_str[ACC_LEN + 1];
939 struct smack_label *subject_label;
940 struct smack_label *object_label;
941 struct smack_rule *rule;
942 union smack_perm *perm;
947 if (!use_long && handle->has_long)
950 load_buffer->pos = 0;
951 change_buffer->pos = 0;
952 bzero(handle->merge_perms, handle->labels_cnt * sizeof(union smack_perm));
953 for (x = 0; x < handle->labels_cnt; ++x) {
954 subject_label = handle->labels[x];
956 for (rule = subject_label->first_rule; rule != NULL; rule = rule->next_rule) {
957 perm = &(handle->merge_perms[rule->object_id]);
958 if (perm->allow_deny_code == 0)
959 handle->merge_object_ids[merge_cnt++] = rule->object_id;
962 perm->allow_code = 0;
963 perm->deny_code = ACCESS_TYPE_ALL;
965 perm->allow_code |= rule->perm.allow_code;
966 perm->allow_code &= ~rule->perm.deny_code;
967 perm->deny_code &= ~rule->perm.allow_code;
968 perm->deny_code |= rule->perm.deny_code;
972 for (y = 0; y < merge_cnt; ++y) {
973 object_label = handle->labels[handle->merge_object_ids[y]];
974 perm = &(handle->merge_perms[object_label->id]);
975 access_code_to_str(perm->allow_code, allow_str);
977 if ((perm->allow_code | perm->deny_code) != ACCESS_TYPE_ALL) {
978 /* Fail immediately without doing any further processing
979 if modify rules are not supported. */
980 if (change_buffer->fd < 0)
983 buffer = change_buffer;
984 buffer->flush_pos = buffer->pos;
985 access_code_to_str(perm->deny_code, deny_str);
986 rule_print_long(buffer->buf, &(buffer->pos),
987 subject_label, object_label, allow_str, deny_str);
989 buffer = load_buffer;
990 buffer->flush_pos = buffer->pos;
992 rule_print_long(buffer->buf, &(buffer->pos),
993 subject_label, object_label, allow_str, NULL);
995 buffer->pos += sprintf(buffer->buf + buffer->pos,
997 subject_label->label, object_label->label,
1000 perm->allow_deny_code = 0;
1003 buffer->buf[buffer->pos++] = '\n';
1004 if (buffer->pos >= handle->page_size)
1005 if (buffer_flush(buffer))
1008 /* When no multi-line is supported, just flush
1009 * the rule that was just generated */
1010 buffer->flush_pos = buffer->pos;
1011 if (buffer_flush(buffer))
1017 if (load_buffer->pos > 0) {
1018 load_buffer->flush_pos = load_buffer->pos;
1019 if (buffer_flush(load_buffer))
1022 if (change_buffer->pos > 0) {
1023 change_buffer->flush_pos = change_buffer->pos;
1024 if (buffer_flush(change_buffer))
1031 static inline ssize_t get_label(char *dest, const char *src, unsigned int *hash)
1034 unsigned int h = 5381;/*DJB2 hashing function magic number*/;
1036 if (!src || src[0] == '\0' || src[0] == '-')
1039 for (i = 0; i < (SMACK_LABEL_LEN + 1) && src[i]; i++) {
1040 if (src[i] <= ' ' || src[i] > '~')
1055 /* This efficient hash function,
1056 * created by Daniel J. Bernstein,
1057 * is known as DJB2 algorithm */
1058 h = (h << 5) + h + src[i];
1061 if (dest && i < (SMACK_LABEL_LEN + 1))
1064 *hash = h % DICT_HASH_SIZE;
1066 return i < (SMACK_LABEL_LEN + 1) ? i : -1;
1070 static inline int str_to_access_code(const char *str)
1073 unsigned int code = 0;
1075 for (i = 0; str[i] != '\0'; i++) {
1079 code |= ACCESS_TYPE_R;
1083 code |= ACCESS_TYPE_W;
1087 code |= ACCESS_TYPE_X;
1091 code |= ACCESS_TYPE_A;
1095 code |= ACCESS_TYPE_T;
1099 code |= ACCESS_TYPE_L;
1111 static inline void access_code_to_str(unsigned int code, char *str)
1113 str[0] = ((code & ACCESS_TYPE_R) != 0) ? 'r' : '-';
1114 str[1] = ((code & ACCESS_TYPE_W) != 0) ? 'w' : '-';
1115 str[2] = ((code & ACCESS_TYPE_X) != 0) ? 'x' : '-';
1116 str[3] = ((code & ACCESS_TYPE_A) != 0) ? 'a' : '-';
1117 str[4] = ((code & ACCESS_TYPE_T) != 0) ? 't' : '-';
1118 str[5] = ((code & ACCESS_TYPE_L) != 0) ? 'l' : '-';
1122 static inline char* get_xattr_name(enum smack_label_type type)
1125 case SMACK_LABEL_ACCESS:
1126 return "security.SMACK64";
1127 case SMACK_LABEL_EXEC:
1128 return "security.SMACK64EXEC";
1129 case SMACK_LABEL_MMAP:
1130 return "security.SMACK64MMAP";
1131 case SMACK_LABEL_TRANSMUTE:
1132 return "security.SMACK64TRANSMUTE";
1133 case SMACK_LABEL_IPIN:
1134 return "security.SMACK64IPIN";
1135 case SMACK_LABEL_IPOUT:
1136 return "security.SMACK64IPOUT";
1138 /* Should not reach this point */
1143 static inline struct smack_label *
1144 is_label_known(struct smack_accesses *handle, const char *label, int hash)
1146 struct smack_label *lab = handle->label_hash[hash].first;
1147 while (lab != NULL && strcmp(label, lab->label) != 0)
1148 lab = lab->next_label;
1152 static inline int accesses_resize(struct smack_accesses *handle)
1154 struct smack_label **labels;
1155 union smack_perm *merge_perms;
1156 int *merge_object_ids;
1157 int alloc = handle->labels_alloc << 1;
1159 labels = realloc(handle->labels, alloc * sizeof(struct smack_label *));
1162 handle->labels = labels;
1164 merge_perms = realloc(handle->merge_perms, alloc * sizeof(union smack_perm));
1165 if (merge_perms == NULL)
1167 handle->merge_perms = merge_perms;
1169 merge_object_ids = realloc(handle->merge_object_ids, alloc * sizeof(int));
1170 if (merge_object_ids == NULL)
1172 handle->merge_object_ids = merge_object_ids;
1174 handle->labels_alloc = alloc;
1178 static struct smack_label *label_add(struct smack_accesses *handle, const char *label)
1180 struct smack_hash_entry *hash_entry;
1181 unsigned int hash_value = 0;
1182 struct smack_label *new_label;
1185 len = get_label(NULL, label, &hash_value);
1189 new_label = is_label_known(handle, label, hash_value);
1190 if (new_label == NULL) {/*no entry added yet*/
1191 if (handle->labels_cnt == handle->labels_alloc)
1192 if (accesses_resize(handle))
1195 new_label = malloc(sizeof(struct smack_label));
1196 if (new_label == NULL)
1198 new_label->label = malloc(len + 1);
1199 if (new_label->label == NULL) {
1204 memcpy(new_label->label, label, len + 1);
1205 new_label->id = handle->labels_cnt;
1206 new_label->len = len;
1207 new_label->first_rule = NULL;
1208 new_label->last_rule = NULL;
1209 new_label->next_label = NULL;
1210 hash_entry = &(handle->label_hash[hash_value]);
1211 if (hash_entry->first == NULL) {
1212 hash_entry->first = new_label;
1213 hash_entry->last = new_label;
1215 hash_entry->last->next_label = new_label;
1216 hash_entry->last = new_label;
1218 handle->labels[handle->labels_cnt++] = new_label;