Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 227794
b: refs/heads/master
c: 5c6d112
h: refs/heads/master
v: v3
  • Loading branch information
Jarkko Sakkinen authored and Casey Schaufler committed Dec 7, 2010
1 parent 95e7c87 commit c6bd845
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 44 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fe27d4b012273640e033be80f143bdc54daa8e16
refs/heads/master: 5c6d1125f8dbd1bfef39e38fbc2837003be78a59
2 changes: 2 additions & 0 deletions trunk/include/linux/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@
#define XATTR_SMACK_IPIN "SMACK64IPIN"
#define XATTR_SMACK_IPOUT "SMACK64IPOUT"
#define XATTR_SMACK_EXEC "SMACK64EXEC"
#define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE"
#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_CAPS_SUFFIX "capability"
#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
Expand Down
17 changes: 16 additions & 1 deletion trunk/security/smack/smack.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct task_smack {
};

#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */

/*
* A label access rule.
Expand Down Expand Up @@ -166,6 +167,10 @@ struct smack_known {
#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */

/*
* Flag for transmute access
*/
#define MAY_TRANSMUTE 64
/*
* Just to make the common cases easier to deal with
*/
Expand Down Expand Up @@ -197,6 +202,7 @@ struct inode_smack *new_inode_smack(char *);
/*
* These functions are in smack_access.c
*/
int smk_access_entry(char *, char *);
int smk_access(char *, char *, int, struct smk_audit_info *);
int smk_curacc(char *, u32, struct smk_audit_info *);
int smack_to_cipso(const char *, struct smack_cipso *);
Expand Down Expand Up @@ -239,6 +245,15 @@ static inline void smack_catset_bit(int cat, char *catsetp)
catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
}

/*
* Is the directory transmuting?
*/
static inline int smk_inode_transmutable(const struct inode *isp)
{
struct inode_smack *sip = isp->i_security;
return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0;
}

/*
* Present a pointer to the smack label in an inode blob.
*/
Expand All @@ -265,7 +280,7 @@ static inline char *smk_of_forked(const struct task_smack *tsp)
}

/*
* Present a pointer to the smack label in the curren task blob.
* Present a pointer to the smack label in the current task blob.
*/
static inline char *smk_of_current(void)
{
Expand Down
54 changes: 41 additions & 13 deletions trunk/security/smack/smack_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,46 @@ static u32 smack_next_secid = 10;
*/
int log_policy = SMACK_AUDIT_DENIED;

/**
* smk_access_entry - look up matching access rule
* @subject_label: a pointer to the subject's Smack label
* @object_label: a pointer to the object's Smack label
*
* This function looks up the subject/object pair in the
* access rule list and returns pointer to the matching rule if found,
* NULL otherwise.
*
* NOTE:
* Even though Smack labels are usually shared on smack_list
* labels that come in off the network can't be imported
* and added to the list for locking reasons.
*
* Therefore, it is necessary to check the contents of the labels,
* not just the pointer values. Of course, in most cases the labels
* will be on the list, so checking the pointers may be a worthwhile
* optimization.
*/
int smk_access_entry(char *subject_label, char *object_label)
{
u32 may = MAY_NOT;
struct smack_rule *srp;

rcu_read_lock();
list_for_each_entry_rcu(srp, &smack_rule_list, list) {
if (srp->smk_subject == subject_label ||
strcmp(srp->smk_subject, subject_label) == 0) {
if (srp->smk_object == object_label ||
strcmp(srp->smk_object, object_label) == 0) {
may = srp->smk_access;
break;
}
}
}
rcu_read_unlock();

return may;
}

/**
* smk_access - determine if a subject has a specific access to an object
* @subject_label: a pointer to the subject's Smack label
Expand All @@ -90,7 +130,6 @@ int smk_access(char *subject_label, char *object_label, int request,
struct smk_audit_info *a)
{
u32 may = MAY_NOT;
struct smack_rule *srp;
int rc = 0;

/*
Expand Down Expand Up @@ -144,18 +183,7 @@ int smk_access(char *subject_label, char *object_label, int request,
* access (e.g. read is included in readwrite) it's
* good.
*/
rcu_read_lock();
list_for_each_entry_rcu(srp, &smack_rule_list, list) {
if (srp->smk_subject == subject_label ||
strcmp(srp->smk_subject, subject_label) == 0) {
if (srp->smk_object == object_label ||
strcmp(srp->smk_object, object_label) == 0) {
may = srp->smk_access;
break;
}
}
}
rcu_read_unlock();
may = smk_access_entry(subject_label, object_label);
/*
* This is a bit map operation.
*/
Expand Down
74 changes: 50 additions & 24 deletions trunk/security/smack/smack_lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
*
* This file contains the smack hook function implementations.
*
* Author:
* Authors:
* Casey Schaufler <casey@schaufler-ca.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.moore@hp.com>
* Copyright (C) 2010 Nokia 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,
Expand All @@ -35,6 +37,9 @@

#define task_security(task) (task_cred_xxx((task), security))

#define TRANS_TRUE "TRUE"
#define TRANS_TRUE_SIZE 4

/**
* smk_fetch - Fetch the smack label from a file.
* @ip: a pointer to the inode
Expand Down Expand Up @@ -468,6 +473,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
char **name, void **value, size_t *len)
{
char *isp = smk_of_inode(inode);
char *dsp = smk_of_inode(dir);
u32 may;

if (name) {
*name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
Expand All @@ -476,6 +483,16 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
}

if (value) {
may = smk_access_entry(smk_of_current(), dsp);

/*
* If the access rule allows transmutation and
* the directory requests transmutation then
* by all means transmute.
*/
if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir))
isp = dsp;

*value = kstrdup(isp, GFP_KERNEL);
if (*value == NULL)
return -ENOMEM;
Expand Down Expand Up @@ -709,6 +726,12 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
if (size == 0 || size >= SMK_LABELLEN ||
smk_import(value, size) == NULL)
rc = -EINVAL;
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
if (!capable(CAP_MAC_ADMIN))
rc = -EPERM;
if (size != TRANS_TRUE_SIZE ||
strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
rc = -EINVAL;
} else
rc = cap_inode_setxattr(dentry, name, value, size, flags);

Expand All @@ -735,35 +758,23 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
struct inode_smack *isp;
char *nsp;

/*
* Not SMACK or SMACKEXEC
*/
if (strcmp(name, XATTR_NAME_SMACK) &&
strcmp(name, XATTR_NAME_SMACKEXEC))
return;

isp = dentry->d_inode->i_security;

/*
* No locking is done here. This is a pointer
* assignment.
*/
nsp = smk_import(value, size);
struct inode_smack *isp = dentry->d_inode->i_security;

if (strcmp(name, XATTR_NAME_SMACK) == 0) {
nsp = smk_import(value, size);
if (nsp != NULL)
isp->smk_inode = nsp;
else
isp->smk_inode = smack_known_invalid.smk_known;
} else {
} else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
nsp = smk_import(value, size);
if (nsp != NULL)
isp->smk_task = nsp;
else
isp->smk_task = smack_known_invalid.smk_known;
}
} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
isp->smk_flags |= SMK_INODE_TRANSMUTE;

return;
}
Expand Down Expand Up @@ -803,7 +814,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
if (!capable(CAP_MAC_ADMIN))
rc = -EPERM;
} else
Expand Down Expand Up @@ -2274,6 +2286,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
char *csp = smk_of_current();
char *fetched;
char *final;
char trattr[TRANS_TRUE_SIZE];
int transflag = 0;
struct dentry *dp;

if (inode == NULL)
Expand Down Expand Up @@ -2392,10 +2406,19 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/
dp = dget(opt_dentry);
fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
if (fetched != NULL)
if (fetched != NULL) {
final = fetched;
isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode,
dp);
if (S_ISDIR(inode->i_mode)) {
trattr[0] = '\0';
inode->i_op->getxattr(dp,
XATTR_NAME_SMACKTRANSMUTE,
trattr, TRANS_TRUE_SIZE);
if (strncmp(trattr, TRANS_TRUE,
TRANS_TRUE_SIZE) == 0)
transflag = SMK_INODE_TRANSMUTE;
}
}
isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);

dput(dp);
break;
Expand All @@ -2406,7 +2429,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
else
isp->smk_inode = final;

isp->smk_flags |= SMK_INODE_INSTANT;
isp->smk_flags |= (SMK_INODE_INSTANT | transflag);

unlockandout:
mutex_unlock(&isp->smk_lock);
Expand Down Expand Up @@ -2456,6 +2479,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
void *value, size_t size)
{
struct task_smack *tsp;
struct task_smack *oldtsp;
struct cred *new;
char *newsmack;

Expand Down Expand Up @@ -2485,6 +2509,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
if (newsmack == smack_known_web.smk_known)
return -EPERM;

oldtsp = p->cred->security;
new = prepare_creds();
if (new == NULL)
return -ENOMEM;
Expand All @@ -2494,6 +2519,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
return -ENOMEM;
}
tsp->smk_task = newsmack;
tsp->smk_forked = oldtsp->smk_forked;
new->security = tsp;
commit_creds(new);
return size;
Expand Down
37 changes: 32 additions & 5 deletions trunk/security/smack/smackfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,12 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION;
* SMK_ACCESSLEN: Maximum length for a rule access field
* SMK_LOADLEN: Smack rule length
*/
#define SMK_ACCESS "rwxa"
#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
#define SMK_OACCESS "rwxa"
#define SMK_ACCESS "rwxat"
#define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)

/**
* smk_netlabel_audit_set - fill a netlbl_audit struct
Expand Down Expand Up @@ -175,6 +178,8 @@ static int load_seq_show(struct seq_file *s, void *v)
seq_putc(s, 'x');
if (srp->smk_access & MAY_APPEND)
seq_putc(s, 'a');
if (srp->smk_access & MAY_TRANSMUTE)
seq_putc(s, 't');
if (srp->smk_access == 0)
seq_putc(s, '-');

Expand Down Expand Up @@ -273,10 +278,15 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
if (!capable(CAP_MAC_ADMIN))
return -EPERM;

if (*ppos != 0 || count != SMK_LOADLEN)
if (*ppos != 0)
return -EINVAL;
/*
* Minor hack for backward compatability
*/
if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN)
return -EINVAL;

data = kzalloc(count, GFP_KERNEL);
data = kzalloc(SMK_LOADLEN, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;

Expand All @@ -285,6 +295,12 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
goto out;
}

/*
* More on the minor hack for backward compatability
*/
if (count == (SMK_OLOADLEN))
data[SMK_OLOADLEN] = '-';

rule = kzalloc(sizeof(*rule), GFP_KERNEL);
if (rule == NULL) {
rc = -ENOMEM;
Expand Down Expand Up @@ -345,6 +361,17 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
goto out_free_rule;
}

switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) {
case '-':
break;
case 't':
case 'T':
rule->smk_access |= MAY_TRANSMUTE;
break;
default:
goto out_free_rule;
}

rc = smk_set_access(rule);

if (!rc)
Expand Down

0 comments on commit c6bd845

Please sign in to comment.