#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
-#define XATTR_SMACK_SUFFIX "SMACK64"
-#define XATTR_SMACK_IPIN "SMACK64IPIN"
-#define XATTR_SMACK_IPOUT "SMACK64IPOUT"
-#define XATTR_SMACK_EXEC "SMACK64EXEC"
-#define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE"
-#define XATTR_SMACK_MMAP "SMACK64MMAP"
-#define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX
-#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
-#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
-#define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC
-#define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE
-#define XATTR_NAME_SMACKMMAP XATTR_SECURITY_PREFIX XATTR_SMACK_MMAP
-
#ifdef __KERNEL__
#include <linux/types.h>
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
-#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
/*
* A label access rule.
#define SMK_FSHAT "smackfshat="
#define SMK_FSROOT "smackfsroot="
+#define XATTR_SMACK_SUFFIX "SMACK64"
+#define XATTR_SMACK_IPIN "SMACK64IPIN"
+#define XATTR_SMACK_IPOUT "SMACK64IPOUT"
+#define XATTR_SMACK_EXEC "SMACK64EXEC"
+#define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE"
+#define XATTR_SMACK_MMAP "SMACK64MMAP"
+#define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX
+#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
+#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
+#define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC
+#define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE
+#define XATTR_NAME_SMACKMMAP XATTR_SECURITY_PREFIX XATTR_SMACK_MMAP
+
#define SMACK_CIPSO_OPTION "-CIPSO"
/*
/*
* smackfs magic number
+ * smackfs macic number
*/
#define SMACK_MAGIC 0x43415d53 /* "SMAC" */
#define MAY_NOT 0
/*
- * Number of access types used by Smack (rwxat)
+ * Number of access types used by Smack (rwxa)
*/
-#define SMK_NUM_ACCESS_TYPE 5
+#define SMK_NUM_ACCESS_TYPE 4
/*
* Smack audit data; is empty if CONFIG_AUDIT not set
int smack_to_cipso(const char *, struct smack_cipso *);
char *smack_from_cipso(u32, char *);
char *smack_from_secid(const u32);
-void smk_parse_smack(const char *string, int len, char *smack);
char *smk_import(const char *, int);
struct smack_known *smk_import_entry(const char *, int);
struct smack_known *smk_find_entry(const char *);
}
/**
- * smk_parse_smack - parse smack label from a text string
- * @string: a text string that might contain a Smack label
+ * smk_import_entry - import a label, return the list entry
+ * @string: a text string that might be a Smack label
* @len: the maximum size, or zero if it is NULL terminated.
- * @smack: parsed smack label, or NULL if parse error
+ *
+ * Returns a pointer to the entry in the label list that
+ * matches the passed string, adding it if necessary.
*/
-void smk_parse_smack(const char *string, int len, char *smack)
+struct smack_known *smk_import_entry(const char *string, int len)
{
+ struct smack_known *skp;
+ char smack[SMK_LABELLEN];
int found;
int i;
} else
smack[i] = string[i];
}
-}
-
-/**
- * smk_import_entry - import a label, return the list entry
- * @string: a text string that might be a Smack label
- * @len: the maximum size, or zero if it is NULL terminated.
- *
- * Returns a pointer to the entry in the label list that
- * matches the passed string, adding it if necessary.
- */
-struct smack_known *smk_import_entry(const char *string, int len)
-{
- struct smack_known *skp;
- char smack[SMK_LABELLEN];
- smk_parse_smack(string, len, smack);
if (smack[0] == '\0')
return NULL;
*
* Authors:
* Casey Schaufler <casey@schaufler-ca.com>
- * Jarkko Sakkinen <jarkko.sakkinen@intel.com>
+ * Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com>
*
* Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
* Paul Moore <paul@paul-moore.com>
* Copyright (C) 2010 Nokia Corporation
- * Copyright (C) 2011 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
#include <linux/audit.h>
#include <linux/magic.h>
#include <linux/dcache.h>
-#include <linux/personality.h>
#include "smack.h"
#define task_security(task) (task_cred_xxx((task), security))
* BPRM hooks
*/
-/**
- * smack_bprm_set_creds - set creds for exec
- * @bprm: the exec information
- *
- * Returns 0 if it gets a blob, -ENOMEM otherwise
- */
static int smack_bprm_set_creds(struct linux_binprm *bprm)
{
- struct inode *inode = bprm->file->f_path.dentry->d_inode;
- struct task_smack *bsp = bprm->cred->security;
+ struct task_smack *tsp = bprm->cred->security;
struct inode_smack *isp;
+ struct dentry *dp;
int rc;
rc = cap_bprm_set_creds(bprm);
if (bprm->cred_prepared)
return 0;
- isp = inode->i_security;
- if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task)
+ if (bprm->file == NULL || bprm->file->f_dentry == NULL)
return 0;
- if (bprm->unsafe)
- return -EPERM;
-
- bsp->smk_task = isp->smk_task;
- bprm->per_clear |= PER_CLEAR_ON_SETID;
+ dp = bprm->file->f_dentry;
- return 0;
-}
-
-/**
- * smack_bprm_committing_creds - Prepare to install the new credentials
- * from bprm.
- *
- * @bprm: binprm for exec
- */
-static void smack_bprm_committing_creds(struct linux_binprm *bprm)
-{
- struct task_smack *bsp = bprm->cred->security;
-
- if (bsp->smk_task != bsp->smk_forked)
- current->pdeath_signal = 0;
-}
+ if (dp->d_inode == NULL)
+ return 0;
-/**
- * smack_bprm_secureexec - Return the decision to use secureexec.
- * @bprm: binprm for exec
- *
- * Returns 0 on success.
- */
-static int smack_bprm_secureexec(struct linux_binprm *bprm)
-{
- struct task_smack *tsp = current_security();
- int ret = cap_bprm_secureexec(bprm);
+ isp = dp->d_inode->i_security;
- if (!ret && (tsp->smk_task != tsp->smk_forked))
- ret = 1;
+ if (isp->smk_task != NULL)
+ tsp->smk_task = isp->smk_task;
- return ret;
+ return 0;
}
/*
{
struct smack_known *skp;
- struct inode_smack *issp = inode->i_security;
char *csp = smk_of_current();
char *isp = smk_of_inode(inode);
char *dsp = smk_of_inode(dir);
* If the access rule allows transmutation and
* the directory requests transmutation then
* by all means transmute.
- * Mark the inode as changed.
*/
if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
- smk_inode_transmutable(dir)) {
- isp = dsp;
- issp->smk_flags |= SMK_INODE_CHANGED;
- }
+ smk_inode_transmutable(dir))
+ isp = dsp;
*value = kstrdup(isp, GFP_KERNEL);
if (*value == NULL)
* smack_inode_permission - Smack version of permission()
* @inode: the inode in question
* @mask: the access requested
- * @flags: special case
*
* This is the important Smack hook.
*
if (mask == 0)
return 0;
- /* May be droppable after audit
- if (flags & IPERM_FLAG_RCU)
- return -ECHILD;*/
-
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
smk_ad_setfield_u_fs_inode(&ad, inode);
return smk_curacc(smk_of_inode(inode), mask, &ad);
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
}
-/**
+/*
* smack_inode_removexattr - Smack check on removexattr
* @dentry: the object
* @name: name of the attribute
char *final;
char trattr[TRANS_TRUE_SIZE];
int transflag = 0;
- int rc;
struct dentry *dp;
if (inode == NULL)
*/
dp = dget(opt_dentry);
fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
- if (fetched != NULL)
+ if (fetched != NULL) {
final = fetched;
-
- /*
- * Transmuting directory
- */
- if (S_ISDIR(inode->i_mode)) {
- /*
- * If there is a transmute attribute on the
- * directory mark the inode.
- */
- rc = inode->i_op->getxattr(dp,
- XATTR_NAME_SMACKTRANSMUTE, trattr,
- TRANS_TRUE_SIZE);
- if (rc >= 0 &&
- strncmp(trattr, TRANS_TRUE, TRANS_TRUE_SIZE) == 0)
- transflag = SMK_INODE_TRANSMUTE;
- /*
- * If this is a new directory and the label was
- * transmuted when the inode was initialized
- * set the transmute attribute on the directory
- * and mark the inode.
- */
- if (isp->smk_flags & SMK_INODE_CHANGED) {
- isp->smk_flags &= ~SMK_INODE_CHANGED;
- rc = inode->i_op->setxattr(dp,
+ if (S_ISDIR(inode->i_mode)) {
+ trattr[0] = '\0';
+ inode->i_op->getxattr(dp,
XATTR_NAME_SMACKTRANSMUTE,
- TRANS_TRUE, TRANS_TRUE_SIZE,
- 0);
- if (rc >= 0)
+ trattr, TRANS_TRUE_SIZE);
+ if (strncmp(trattr, TRANS_TRUE,
+ TRANS_TRUE_SIZE) == 0)
transflag = SMK_INODE_TRANSMUTE;
}
}
.sb_umount = smack_sb_umount,
.bprm_set_creds = smack_bprm_set_creds,
- .bprm_committing_creds = smack_bprm_committing_creds,
- .bprm_secureexec = smack_bprm_secureexec,
.inode_alloc_security = smack_inode_alloc_security,
.inode_free_security = smack_inode_free_security,
}
/**
- * smk_parse_rule - parse Smack rule from load string
+ * smk_parse_rule - parse subject, object and access type
* @data: string to be parsed whose size is SMK_LOADLEN
- * @rule: Smack rule
- * @import: if non-zero, import labels
+ * @rule: parsed entities are stored in here
*/
-static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
+static int smk_parse_rule(const char *data, struct smack_rule *rule)
{
- char smack[SMK_LABELLEN];
- struct smack_known *skp;
-
- if (import) {
- rule->smk_subject = smk_import(data, 0);
- if (rule->smk_subject == NULL)
- return -1;
-
- rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
- if (rule->smk_object == NULL)
- return -1;
- } else {
- smk_parse_smack(data, 0, smack);
- skp = smk_find_entry(smack);
- if (skp == NULL)
- return -1;
- rule->smk_subject = skp->smk_known;
+ rule->smk_subject = smk_import(data, 0);
+ if (rule->smk_subject == NULL)
+ return -1;
- smk_parse_smack(data + SMK_LABELLEN, 0, smack);
- skp = smk_find_entry(smack);
- if (skp == NULL)
- return -1;
- rule->smk_object = skp->smk_known;
- }
+ rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
+ if (rule->smk_object == NULL)
+ return -1;
rule->smk_access = 0;
goto out;
}
- if (smk_parse_rule(data, rule, 1))
+ if (smk_parse_rule(data, rule))
goto out_free_rule;
if (rule_list == NULL) {
rc = count;
/*
- * If this is "load" as opposed to "load-self" and a new rule
- * it needs to get added for reporting.
* smk_set_access returns true if there was already a rule
* for the subject/object pair, and false if it was new.
*/
- if (load && !smk_set_access(rule, rule_list, rule_lock)) {
+ if (!smk_set_access(rule, rule_list, rule_lock)) {
smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
if (smlp != NULL) {
smlp->smk_rule = rule;
/*
- * Core logic for smackfs seq list operations.
+ * Seq_file read operations for /smack/load
*/
-static void *smk_seq_start(struct seq_file *s, loff_t *pos,
- struct list_head *head)
+static void *load_seq_start(struct seq_file *s, loff_t *pos)
{
struct list_head *list;
* This is 0 the first time through.
*/
if (s->index == 0)
- s->private = head;
+ s->private = &smack_rule_list;
if (s->private == NULL)
return NULL;
return list;
}
-static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
- struct list_head *head)
+static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
struct list_head *list = v;
- if (list_is_last(list, head)) {
+ if (list_is_last(list, &smack_rule_list)) {
s->private = NULL;
return NULL;
}
return list->next;
}
-static void smk_seq_stop(struct seq_file *s, void *v)
-{
- /* No-op */
-}
-
-/*
- * Seq_file read operations for /smack/load
- */
-
-static void *load_seq_start(struct seq_file *s, loff_t *pos)
-{
- return smk_seq_start(s, pos, &smack_rule_list);
-}
-
-static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
- return smk_seq_next(s, v, pos, &smack_rule_list);
-}
-
static int load_seq_show(struct seq_file *s, void *v)
{
struct list_head *list = v;
return 0;
}
+static void load_seq_stop(struct seq_file *s, void *v)
+{
+ /* No-op */
+}
+
static const struct seq_operations load_seq_ops = {
.start = load_seq_start,
.next = load_seq_next,
.show = load_seq_show,
- .stop = smk_seq_stop,
+ .stop = load_seq_stop,
};
/**
if (!capable(CAP_MAC_ADMIN))
return -EPERM;
+/*
+ return smk_write_load_list(file, buf, count, ppos, &smack_rule_list,
+ &smack_list_lock);
+*/
return smk_write_load_list(file, buf, count, ppos, NULL, NULL);
}
static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
{
- return smk_seq_start(s, pos, &smack_known_list);
+ if (*pos == SEQ_READ_FINISHED)
+ return NULL;
+ if (list_empty(&smack_known_list))
+ return NULL;
+
+ return smack_known_list.next;
}
static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
- return smk_seq_next(s, v, pos, &smack_known_list);
+ struct list_head *list = v;
+
+ /*
+ * labels with no associated cipso value wont be printed
+ * in cipso_seq_show
+ */
+ if (list_is_last(list, &smack_known_list)) {
+ *pos = SEQ_READ_FINISHED;
+ return NULL;
+ }
+
+ return list->next;
}
/*
return 0;
}
+static void cipso_seq_stop(struct seq_file *s, void *v)
+{
+ /* No-op */
+}
+
static const struct seq_operations cipso_seq_ops = {
.start = cipso_seq_start,
+ .stop = cipso_seq_stop,
.next = cipso_seq_next,
.show = cipso_seq_show,
- .stop = smk_seq_stop,
};
/**
static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
{
- return smk_seq_start(s, pos, &smk_netlbladdr_list);
+ if (*pos == SEQ_READ_FINISHED)
+ return NULL;
+ if (list_empty(&smk_netlbladdr_list))
+ return NULL;
+ return smk_netlbladdr_list.next;
}
static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
- return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
+ struct list_head *list = v;
+
+ if (list_is_last(list, &smk_netlbladdr_list)) {
+ *pos = SEQ_READ_FINISHED;
+ return NULL;
+ }
+
+ return list->next;
}
#define BEBITS (sizeof(__be32) * 8)
return 0;
}
+static void netlbladdr_seq_stop(struct seq_file *s, void *v)
+{
+ /* No-op */
+}
+
static const struct seq_operations netlbladdr_seq_ops = {
.start = netlbladdr_seq_start,
+ .stop = netlbladdr_seq_stop,
.next = netlbladdr_seq_next,
.show = netlbladdr_seq_show,
- .stop = smk_seq_stop,
};
/**
{
struct task_smack *tsp = current_security();
- return smk_seq_start(s, pos, &tsp->smk_rules);
+ if (*pos == SEQ_READ_FINISHED)
+ return NULL;
+ if (list_empty(&tsp->smk_rules))
+ return NULL;
+ return tsp->smk_rules.next;
}
static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
struct task_smack *tsp = current_security();
+ struct list_head *list = v;
- return smk_seq_next(s, v, pos, &tsp->smk_rules);
+ if (list_is_last(list, &tsp->smk_rules)) {
+ *pos = SEQ_READ_FINISHED;
+ return NULL;
+ }
+ return list->next;
}
static int load_self_seq_show(struct seq_file *s, void *v)
return 0;
}
+static void load_self_seq_stop(struct seq_file *s, void *v)
+{
+ /* No-op */
+}
static const struct seq_operations load_self_seq_ops = {
.start = load_self_seq_start,
.next = load_self_seq_next,
.show = load_self_seq_show,
- .stop = smk_seq_stop,
+ .stop = load_self_seq_stop,
};
{
struct smack_rule rule;
char *data;
- int res;
if (!capable(CAP_MAC_ADMIN))
return -EPERM;
if (IS_ERR(data))
return PTR_ERR(data);
- if (count < SMK_LOADLEN || smk_parse_rule(data, &rule, 0))
+ if (count < SMK_LOADLEN || smk_parse_rule(data, &rule))
return -EINVAL;
- res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access,
- NULL);
- data[0] = res == 0 ? '1' : '0';
- data[1] = '\0';
+ data[0] = smk_access(rule.smk_subject, rule.smk_object,
+ rule.smk_access, NULL) == 0;
- simple_transaction_set(file, 2);
+ simple_transaction_set(file, 1);
return SMK_LOADLEN;
}
[SMK_LOAD_SELF] = {
"load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
[SMK_ACCESSES] = {
- "access", &smk_access_ops, S_IRUGO|S_IWUGO},
+ "access", &smk_access_ops, S_IRUGO|S_IWUSR},
/* last one */
{""}
};