Commit 4f9a60f5 authored by James Morris's avatar James Morris

Merge branch 'smack-for-4.1' of git://github.com/cschaufler/smack-next into next

parents 1018bc26 18779b75
This diff is collapsed.
......@@ -105,6 +105,7 @@ struct task_smack {
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
#define SMK_INODE_IMPURE 0x08 /* involved in an impure transaction */
/*
* A label access rule.
......@@ -193,6 +194,10 @@ struct smk_port_label {
#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */
#define MAY_BRINGUP 0x00004000 /* Report use of this rule */
#define SMACK_BRINGUP_ALLOW 1 /* Allow bringup mode */
#define SMACK_UNCONFINED_SUBJECT 2 /* Allow unconfined label */
#define SMACK_UNCONFINED_OBJECT 3 /* Allow unconfined label */
/*
* Just to make the common cases easier to deal with
*/
......@@ -254,6 +259,9 @@ extern int smack_cipso_mapped;
extern struct smack_known *smack_net_ambient;
extern struct smack_known *smack_onlycap;
extern struct smack_known *smack_syslog_label;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
extern struct smack_known *smack_unconfined;
#endif
extern struct smack_known smack_cipso_option;
extern int smack_ptrace_rule;
......
......@@ -130,7 +130,8 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
/*
* Hardcoded comparisons.
*
*/
/*
* A star subject can't access any object.
*/
if (subject == &smack_known_star) {
......@@ -189,10 +190,20 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
* succeed because of "b" rules.
*/
if (may & MAY_BRINGUP)
rc = MAY_BRINGUP;
rc = SMACK_BRINGUP_ALLOW;
#endif
out_audit:
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
if (rc < 0) {
if (object == smack_unconfined)
rc = SMACK_UNCONFINED_OBJECT;
if (subject == smack_unconfined)
rc = SMACK_UNCONFINED_SUBJECT;
}
#endif
#ifdef CONFIG_AUDIT
if (a)
smack_log(subject->smk_known, object->smk_known,
......@@ -338,19 +349,16 @@ static void smack_log_callback(struct audit_buffer *ab, void *a)
void smack_log(char *subject_label, char *object_label, int request,
int result, struct smk_audit_info *ad)
{
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
#else
char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
#endif
struct smack_audit_data *sad;
struct common_audit_data *a = &ad->a;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
/*
* The result may be positive in bringup mode.
*/
if (result > 0)
result = 0;
#endif
/* check if we have to log the current event */
if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
return;
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
return;
......@@ -364,6 +372,21 @@ void smack_log(char *subject_label, char *object_label, int request,
smack_str_from_perm(request_buffer, request);
sad->subject = subject_label;
sad->object = object_label;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
/*
* The result may be positive in bringup mode.
* A positive result is an allow, but not for normal reasons.
* Mark it as successful, but don't filter it out even if
* the logging policy says to do so.
*/
if (result == SMACK_UNCONFINED_SUBJECT)
strcat(request_buffer, "(US)");
else if (result == SMACK_UNCONFINED_OBJECT)
strcat(request_buffer, "(UO)");
if (result > 0)
result = 0;
#endif
sad->request = request_buffer;
sad->result = result;
......
......@@ -57,6 +57,13 @@ static struct kmem_cache *smack_inode_cache;
int smack_enabled;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static char *smk_bu_mess[] = {
"Bringup Error", /* Unused */
"Bringup", /* SMACK_BRINGUP_ALLOW */
"Unconfined Subject", /* SMACK_UNCONFINED_SUBJECT */
"Unconfined Object", /* SMACK_UNCONFINED_OBJECT */
};
static void smk_bu_mode(int mode, char *s)
{
int i = 0;
......@@ -87,9 +94,11 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
if (rc <= 0)
return rc;
if (rc > SMACK_UNCONFINED_OBJECT)
rc = 0;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) %s\n",
pr_info("Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc],
sskp->smk_known, oskp->smk_known, acc, note);
return 0;
}
......@@ -106,9 +115,11 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
if (rc <= 0)
return rc;
if (rc > SMACK_UNCONFINED_OBJECT)
rc = 0;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) %s %s\n",
pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
tsp->smk_task->smk_known, oskp->smk_known,
acc, current->comm, note);
return 0;
......@@ -126,9 +137,11 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
if (rc <= 0)
return rc;
if (rc > SMACK_UNCONFINED_OBJECT)
rc = 0;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) %s to %s\n",
pr_info("Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc],
tsp->smk_task->smk_known, smk_task->smk_known, acc,
current->comm, otp->comm);
return 0;
......@@ -141,14 +154,25 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
static int smk_bu_inode(struct inode *inode, int mode, int rc)
{
struct task_smack *tsp = current_security();
struct inode_smack *isp = inode->i_security;
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (isp->smk_flags & SMK_INODE_IMPURE)
pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
inode->i_sb->s_id, inode->i_ino, current->comm);
if (rc <= 0)
return rc;
if (rc > SMACK_UNCONFINED_OBJECT)
rc = 0;
if (rc == SMACK_UNCONFINED_SUBJECT &&
(mode & (MAY_WRITE | MAY_APPEND)))
isp->smk_flags |= SMK_INODE_IMPURE;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n",
tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc,
pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, current->comm);
return 0;
}
......@@ -162,13 +186,20 @@ static int smk_bu_file(struct file *file, int mode, int rc)
struct task_smack *tsp = current_security();
struct smack_known *sskp = tsp->smk_task;
struct inode *inode = file_inode(file);
struct inode_smack *isp = inode->i_security;
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (isp->smk_flags & SMK_INODE_IMPURE)
pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
inode->i_sb->s_id, inode->i_ino, current->comm);
if (rc <= 0)
return rc;
if (rc > SMACK_UNCONFINED_OBJECT)
rc = 0;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, file,
current->comm);
......@@ -185,13 +216,20 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
struct task_smack *tsp = cred->security;
struct smack_known *sskp = tsp->smk_task;
struct inode *inode = file->f_inode;
struct inode_smack *isp = inode->i_security;
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (isp->smk_flags & SMK_INODE_IMPURE)
pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
inode->i_sb->s_id, inode->i_ino, current->comm);
if (rc <= 0)
return rc;
if (rc > SMACK_UNCONFINED_OBJECT)
rc = 0;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, file,
current->comm);
......@@ -2452,7 +2490,21 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
static int smack_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
if (family != PF_INET || sock->sk == NULL)
struct socket_smack *ssp;
if (sock->sk == NULL)
return 0;
/*
* Sockets created by kernel threads receive web label.
*/
if (unlikely(current->flags & PF_KTHREAD)) {
ssp = sock->sk->sk_security;
ssp->smk_in = &smack_known_web;
ssp->smk_out = &smack_known_web;
}
if (family != PF_INET)
return 0;
/*
* Set the outbound netlbl.
......@@ -3986,6 +4038,36 @@ static int smack_key_permission(key_ref_t key_ref,
rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
return rc;
}
/*
* smack_key_getsecurity - Smack label tagging the key
* @key points to the key to be queried
* @_buffer points to a pointer that should be set to point to the
* resulting string (if no label or an error occurs).
* Return the length of the string (including terminating NUL) or -ve if
* an error.
* May also return 0 (and a NULL buffer pointer) if there is no label.
*/
static int smack_key_getsecurity(struct key *key, char **_buffer)
{
struct smack_known *skp = key->security;
size_t length;
char *copy;
if (key->security == NULL) {
*_buffer = NULL;
return 0;
}
copy = kstrdup(skp->smk_known, GFP_KERNEL);
if (copy == NULL)
return -ENOMEM;
length = strlen(copy) + 1;
*_buffer = copy;
return length;
}
#endif /* CONFIG_KEYS */
/*
......@@ -4310,6 +4392,7 @@ struct security_operations smack_ops = {
.key_alloc = smack_key_alloc,
.key_free = smack_key_free,
.key_permission = smack_key_permission,
.key_getsecurity = smack_key_getsecurity,
#endif /* CONFIG_KEYS */
/* Audit hooks */
......
......@@ -54,6 +54,9 @@ enum smk_inos {
SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
SMK_SYSLOG = 20, /* change syslog label) */
SMK_PTRACE = 21, /* set ptrace rule */
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
SMK_UNCONFINED = 22, /* define an unconfined label */
#endif
};
/*
......@@ -61,7 +64,6 @@ enum smk_inos {
*/
static DEFINE_MUTEX(smack_cipso_lock);
static DEFINE_MUTEX(smack_ambient_lock);
static DEFINE_MUTEX(smack_syslog_lock);
static DEFINE_MUTEX(smk_netlbladdr_lock);
/*
......@@ -95,6 +97,16 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
*/
struct smack_known *smack_onlycap;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
/*
* Allow one label to be unconfined. This is for
* debugging and application bring-up purposes only.
* It is bad and wrong, but everyone seems to expect
* to have it.
*/
struct smack_known *smack_unconfined;
#endif
/*
* If this value is set restrict syslog use to the label specified.
* It can be reset via smackfs/syslog
......@@ -1717,6 +1729,85 @@ static const struct file_operations smk_onlycap_ops = {
.llseek = default_llseek,
};
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
/**
* smk_read_unconfined - read() for smackfs/unconfined
* @filp: file pointer, not actually used
* @buf: where to put the result
* @cn: maximum to send along
* @ppos: where to start
*
* Returns number of bytes read or error code, as appropriate
*/
static ssize_t smk_read_unconfined(struct file *filp, char __user *buf,
size_t cn, loff_t *ppos)
{
char *smack = "";
ssize_t rc = -EINVAL;
int asize;
if (*ppos != 0)
return 0;
if (smack_unconfined != NULL)
smack = smack_unconfined->smk_known;
asize = strlen(smack) + 1;
if (cn >= asize)
rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
return rc;
}
/**
* smk_write_unconfined - write() for smackfs/unconfined
* @file: file pointer, not actually used
* @buf: where to get the data from
* @count: bytes sent
* @ppos: where to start
*
* Returns number of bytes written or error code, as appropriate
*/
static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
char *data;
int rc = count;
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
data = kzalloc(count + 1, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
/*
* Should the null string be passed in unset the unconfined value.
* This seems like something to be careful with as usually
* smk_import only expects to return NULL for errors. It
* is usually the case that a nullstring or "\n" would be
* bad to pass to smk_import but in fact this is useful here.
*
* smk_import will also reject a label beginning with '-',
* so "-confine" will also work.
*/
if (copy_from_user(data, buf, count) != 0)
rc = -EFAULT;
else
smack_unconfined = smk_import_entry(data, count);
kfree(data);
return rc;
}
static const struct file_operations smk_unconfined_ops = {
.read = smk_read_unconfined,
.write = smk_write_unconfined,
.llseek = default_llseek,
};
#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
/**
* smk_read_logging - read() for /smack/logging
* @filp: file pointer, not actually used
......@@ -2384,6 +2475,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
"syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
[SMK_PTRACE] = {
"ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
[SMK_UNCONFINED] = {
"unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
#endif
/* last one */
{""}
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment