#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/xattr.h>
#include <unistd.h>
#include <sys/xattr.h>
#define LEVEL_MAX 255
#define NUM_LEN 4
#define BUF_SIZE 512
- #define CAT_MAX_COUNT 240
- #define CAT_MAX_VALUE 63
+ #define CAT_MAX_COUNT 184
#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 BITMASK(b) (1 << ((b) & 7))
+ #define BITSLOT(b) ((b) >> 3)
+ #define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
+ #define BITTEST(a, b) ((a)[BITSLOT(b)] & BITMASK(b))
+ #define BITNSLOTS(nb) ((nb + 7) >> 3)
+
#define ACCESS_TYPE_R 0x01
#define ACCESS_TYPE_W 0x02
#define ACCESS_TYPE_X 0x04
struct cipso_mapping {
char label[SMACK_LABEL_LEN + 1];
- int cats[CAT_MAX_VALUE];
+ uint8_t cats[BITNSLOTS(CAT_MAX_COUNT)];
int ncats;
int level;
struct cipso_mapping *next;
struct cipso_mapping *last;
};
+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*);
+
+static inline char* get_xattr_name(enum smack_label_type type);
+
struct smack_file_buffer {
int fd;
int pos;
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;
+ for (i = 0; i < CAT_MAX_COUNT; i++) {
+ if (BITTEST(m->cats, i)) {
+ sprintf(&buf[offset], CIPSO_NUM_LEN_STR, i + 1);
+ offset += NUM_LEN;
+ }
}
if (write(fd, buf, offset) < 0) {
if (errno)
goto err_out;
- if (val < 0 || val > CAT_MAX_VALUE)
+ if (val <= 0 || val > CAT_MAX_COUNT)
goto err_out;
- mapping->cats[i] = val;
+ if (!BITTEST(mapping->cats, val - 1)) {
+ BITSET(mapping->cats, val - 1);
+ ++(mapping->ncats);
+ }
cat = strtok_r(NULL, " \t\n", &ptr);
}
- mapping->ncats = i;
-
if (cipso->first == NULL) {
cipso->first = cipso->last = mapping;
} else {
return (ret < 0) ? -1 : 0;
}
+static int internal_getlabel(void* file, char** label,
+ enum smack_label_type type,
+ getxattr_func getfunc)
+{
+ char* xattr_name = get_xattr_name(type);
+ char value[SMACK_LABEL_LEN + 1];
+ int ret;
+
+ ret = getfunc(file, xattr_name, value, SMACK_LABEL_LEN + 1);
+ if (ret == -1) {
+ if (errno == ENODATA) {
+ *label = NULL;
+ return 0;
+ }
+ return -1;
+ }
+
+ value[ret] = '\0';
+ *label = calloc(ret + 1, 1);
+ if (*label == NULL)
+ return -1;
+ strncpy(*label, value, ret);
+ return 0;
+}
+
+static int internal_setlabel(void* file, const char* label,
+ enum smack_label_type type,
+ setxattr_func setfunc, removexattr_func removefunc)
+{
+ char* xattr_name = get_xattr_name(type);
+
+ /* Check validity of labels for LABEL_TRANSMUTE */
+ if (type == SMACK_LABEL_TRANSMUTE && label != NULL) {
+ if (!strcmp(label, "0"))
+ label = NULL;
+ else if (!strcmp(label, "1"))
+ label = "TRUE";
+ else
+ return -1;
+ }
+
+ if (label == NULL || label[0] == '\0') {
+ return removefunc(file, xattr_name);
+ } else {
+ int len = strnlen(label, SMACK_LABEL_LEN + 1);
+ if (len > SMACK_LABEL_LEN)
+ return -1;
+ return setfunc(file, xattr_name, label, len, 0);
+ }
+}
+
+int smack_getlabel(const char *path, char** label,
+ enum smack_label_type type)
+{
+ return internal_getlabel((void*) path, label, type,
+ (getxattr_func) getxattr);
+}
+
+int smack_lgetlabel(const char *path, char** label,
+ enum smack_label_type type)
+{
+ return internal_getlabel((void*) path, label, type,
+ (getxattr_func) lgetxattr);
+}
+
+int smack_fgetlabel(int fd, char** label,
+ enum smack_label_type type)
+{
+ return internal_getlabel((void*) ((unsigned long) fd), label, type,
+ (getxattr_func) fgetxattr);
+}
+
+int smack_setlabel(const char *path, const char* label,
+ enum smack_label_type type)
+{
+ return internal_setlabel((void*) path, label, type,
+ (setxattr_func) setxattr, (removexattr_func) removexattr);
+}
+
+int smack_lsetlabel(const char *path, const char* label,
+ enum smack_label_type type)
+{
+ return internal_setlabel((void*) path, label, type,
+ (setxattr_func) lsetxattr, (removexattr_func) lremovexattr);
+}
+
+int smack_fsetlabel(int fd, const char* label,
+ enum smack_label_type type)
+{
+ return internal_setlabel((void*) ((unsigned long) fd), label, type,
+ (setxattr_func) fsetxattr, (removexattr_func) fremovexattr);
+}
+
static int open_smackfs_file(const char *long_name, const char *short_name,
mode_t mode, int *use_long)
{
str[6] = '\0';
}
+static inline char* get_xattr_name(enum smack_label_type type)
+{
+ switch (type) {
+ case SMACK_LABEL_ACCESS:
+ return "security.SMACK64";
+ case SMACK_LABEL_EXEC:
+ return "security.SMACK64EXEC";
+ case SMACK_LABEL_MMAP:
+ return "security.SMACK64MMAP";
+ case SMACK_LABEL_TRANSMUTE:
+ return "security.SMACK64TRANSMUTE";
+ case SMACK_LABEL_IPIN:
+ return "security.SMACK64IPIN";
+ case SMACK_LABEL_IPOUT:
+ return "security.SMACK64IPOUT";
+ default:
+ /* Should not reach this point */
+ return NULL;
+ }
+}
+
static inline struct smack_label *
is_label_known(struct smack_accesses *handle, const char *label, int hash)
{