Commit 6f98e892 authored by James Morris's avatar James Morris

Merge branch 'smack-for-3.18' of git://git.gitorious.org/smack-next/kernel into next

parents ac60ab4b 21c7eae2
......@@ -12,3 +12,19 @@ config SECURITY_SMACK
of other mandatory security schemes.
If you are unsure how to answer this question, answer N.
config SECURITY_SMACK_BRINGUP
bool "Reporting on access granted by Smack rules"
depends on SECURITY_SMACK
default n
help
Enable the bring-up ("b") access mode in Smack rules.
When access is granted by a rule with the "b" mode a
message about the access requested is generated. The
intention is that a process can be granted a wide set
of access initially with the bringup mode set on the
rules. The developer can use the information to
identify which rules are necessary and what accesses
may be inappropriate. The developer can reduce the
access rule set once the behavior is well understood.
This is a superior mechanism to the oft abused
"permissive" mode of other systems.
......@@ -71,10 +71,10 @@ struct smack_known {
#define SMK_CIPSOLEN 24
struct superblock_smack {
char *smk_root;
char *smk_floor;
char *smk_hat;
char *smk_default;
struct smack_known *smk_root;
struct smack_known *smk_floor;
struct smack_known *smk_hat;
struct smack_known *smk_default;
int smk_initialized;
};
......@@ -88,7 +88,7 @@ struct socket_smack {
* Inode smack data
*/
struct inode_smack {
char *smk_inode; /* label of the fso */
struct smack_known *smk_inode; /* label of the fso */
struct smack_known *smk_task; /* label of the task */
struct smack_known *smk_mmap; /* label of the mmap domain */
struct mutex smk_lock; /* initialization lock */
......@@ -112,7 +112,7 @@ struct task_smack {
struct smack_rule {
struct list_head list;
struct smack_known *smk_subject;
char *smk_object;
struct smack_known *smk_object;
int smk_access;
};
......@@ -123,7 +123,7 @@ struct smk_netlbladdr {
struct list_head list;
struct sockaddr_in smk_host; /* network address */
struct in_addr smk_mask; /* network mask */
char *smk_label; /* label */
struct smack_known *smk_label; /* label */
};
/*
......@@ -191,6 +191,7 @@ struct smk_port_label {
*/
#define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */
#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */
#define MAY_BRINGUP 0x00004000 /* Report use of this rule */
/*
* Just to make the common cases easier to deal with
......@@ -200,9 +201,9 @@ struct smk_port_label {
#define MAY_NOT 0
/*
* Number of access types used by Smack (rwxatl)
* Number of access types used by Smack (rwxatlb)
*/
#define SMK_NUM_ACCESS_TYPE 6
#define SMK_NUM_ACCESS_TYPE 7
/* SMACK data */
struct smack_audit_data {
......@@ -226,23 +227,23 @@ struct smk_audit_info {
/*
* These functions are in smack_lsm.c
*/
struct inode_smack *new_inode_smack(char *);
struct inode_smack *new_inode_smack(struct smack_known *);
/*
* These functions are in smack_access.c
*/
int smk_access_entry(char *, char *, struct list_head *);
int smk_access(struct smack_known *, char *, int, struct smk_audit_info *);
int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *);
int smk_curacc(char *, u32, struct smk_audit_info *);
int smk_access(struct smack_known *, struct smack_known *,
int, struct smk_audit_info *);
int smk_tskacc(struct task_smack *, struct smack_known *,
u32, struct smk_audit_info *);
int smk_curacc(struct smack_known *, u32, struct smk_audit_info *);
struct smack_known *smack_from_secid(const u32);
char *smk_parse_smack(const char *string, int len);
int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
char *smk_import(const char *, int);
struct smack_known *smk_import_entry(const char *, int);
void smk_insert_entry(struct smack_known *skp);
struct smack_known *smk_find_entry(const char *);
u32 smack_to_secid(const char *);
/*
* Shared data.
......@@ -252,7 +253,7 @@ 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;
extern const char *smack_cipso_option;
extern struct smack_known smack_cipso_option;
extern int smack_ptrace_rule;
extern struct smack_known smack_known_floor;
......@@ -281,9 +282,9 @@ static inline int smk_inode_transmutable(const struct inode *isp)
}
/*
* Present a pointer to the smack label in an inode blob.
* Present a pointer to the smack label entry in an inode blob.
*/
static inline char *smk_of_inode(const struct inode *isp)
static inline struct smack_known *smk_of_inode(const struct inode *isp)
{
struct inode_smack *sip = isp->i_security;
return sip->smk_inode;
......
......@@ -94,7 +94,7 @@ int smk_access_entry(char *subject_label, char *object_label,
struct smack_rule *srp;
list_for_each_entry_rcu(srp, rule_list, list) {
if (srp->smk_object == object_label &&
if (srp->smk_object->smk_known == object_label &&
srp->smk_subject->smk_known == subject_label) {
may = srp->smk_access;
break;
......@@ -111,8 +111,8 @@ int smk_access_entry(char *subject_label, char *object_label,
/**
* smk_access - determine if a subject has a specific access to an object
* @subject_known: a pointer to the subject's Smack label entry
* @object_label: a pointer to the object's Smack label
* @subject: a pointer to the subject's Smack label entry
* @object: a pointer to the object's Smack label entry
* @request: the access requested, in "MAY" format
* @a : a pointer to the audit data
*
......@@ -122,7 +122,7 @@ int smk_access_entry(char *subject_label, char *object_label,
*
* Smack labels are shared on smack_list
*/
int smk_access(struct smack_known *subject_known, char *object_label,
int smk_access(struct smack_known *subject, struct smack_known *object,
int request, struct smk_audit_info *a)
{
int may = MAY_NOT;
......@@ -133,7 +133,7 @@ int smk_access(struct smack_known *subject_known, char *object_label,
*
* A star subject can't access any object.
*/
if (subject_known == &smack_known_star) {
if (subject == &smack_known_star) {
rc = -EACCES;
goto out_audit;
}
......@@ -142,28 +142,28 @@ int smk_access(struct smack_known *subject_known, char *object_label,
* Tasks cannot be assigned the internet label.
* An internet subject can access any object.
*/
if (object_label == smack_known_web.smk_known ||
subject_known == &smack_known_web)
if (object == &smack_known_web ||
subject == &smack_known_web)
goto out_audit;
/*
* A star object can be accessed by any subject.
*/
if (object_label == smack_known_star.smk_known)
if (object == &smack_known_star)
goto out_audit;
/*
* An object can be accessed in any way by a subject
* with the same label.
*/
if (subject_known->smk_known == object_label)
if (subject->smk_known == object->smk_known)
goto out_audit;
/*
* A hat subject can read any object.
* A floor object can be read by any subject.
*/
if ((request & MAY_ANYREAD) == request) {
if (object_label == smack_known_floor.smk_known)
if (object == &smack_known_floor)
goto out_audit;
if (subject_known == &smack_known_hat)
if (subject == &smack_known_hat)
goto out_audit;
}
/*
......@@ -174,27 +174,38 @@ int smk_access(struct smack_known *subject_known, char *object_label,
* indicates there is no entry for this pair.
*/
rcu_read_lock();
may = smk_access_entry(subject_known->smk_known, object_label,
&subject_known->smk_rules);
may = smk_access_entry(subject->smk_known, object->smk_known,
&subject->smk_rules);
rcu_read_unlock();
if (may > 0 && (request & may) == request)
if (may <= 0 || (request & may) != request) {
rc = -EACCES;
goto out_audit;
}
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
/*
* Return a positive value if using bringup mode.
* This allows the hooks to identify checks that
* succeed because of "b" rules.
*/
if (may & MAY_BRINGUP)
rc = MAY_BRINGUP;
#endif
rc = -EACCES;
out_audit:
#ifdef CONFIG_AUDIT
if (a)
smack_log(subject_known->smk_known, object_label, request,
rc, a);
smack_log(subject->smk_known, object->smk_known,
request, rc, a);
#endif
return rc;
}
/**
* smk_tskacc - determine if a task has a specific access to an object
* @tsp: a pointer to the subject task
* @obj_label: a pointer to the object's Smack label
* @tsp: a pointer to the subject's task
* @obj_known: a pointer to the object's label entry
* @mode: the access requested, in "MAY" format
* @a : common audit data
*
......@@ -203,24 +214,25 @@ int smk_access(struct smack_known *subject_known, char *object_label,
* non zero otherwise. It allows that the task may have the capability
* to override the rules.
*/
int smk_tskacc(struct task_smack *subject, char *obj_label,
int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known,
u32 mode, struct smk_audit_info *a)
{
struct smack_known *skp = smk_of_task(subject);
struct smack_known *sbj_known = smk_of_task(tsp);
int may;
int rc;
/*
* Check the global rule list
*/
rc = smk_access(skp, obj_label, mode, NULL);
if (rc == 0) {
rc = smk_access(sbj_known, obj_known, mode, NULL);
if (rc >= 0) {
/*
* If there is an entry in the task's rule list
* it can further restrict access.
*/
may = smk_access_entry(skp->smk_known, obj_label,
&subject->smk_rules);
may = smk_access_entry(sbj_known->smk_known,
obj_known->smk_known,
&tsp->smk_rules);
if (may < 0)
goto out_audit;
if ((mode & may) == mode)
......@@ -237,14 +249,15 @@ int smk_tskacc(struct task_smack *subject, char *obj_label,
out_audit:
#ifdef CONFIG_AUDIT
if (a)
smack_log(skp->smk_known, obj_label, mode, rc, a);
smack_log(sbj_known->smk_known, obj_known->smk_known,
mode, rc, a);
#endif
return rc;
}
/**
* smk_curacc - determine if current has a specific access to an object
* @obj_label: a pointer to the object's Smack label
* @obj_known: a pointer to the object's Smack label entry
* @mode: the access requested, in "MAY" format
* @a : common audit data
*
......@@ -253,11 +266,12 @@ int smk_tskacc(struct task_smack *subject, char *obj_label,
* non zero otherwise. It allows that current may have the capability
* to override the rules.
*/
int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
int smk_curacc(struct smack_known *obj_known,
u32 mode, struct smk_audit_info *a)
{
struct task_smack *tsp = current_security();
return smk_tskacc(tsp, obj_label, mode, a);
return smk_tskacc(tsp, obj_known, mode, a);
}
#ifdef CONFIG_AUDIT
......@@ -328,6 +342,13 @@ void smack_log(char *subject_label, char *object_label, int request,
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)
return;
......@@ -543,27 +564,6 @@ struct smack_known *smk_import_entry(const char *string, int len)
return skp;
}
/**
* smk_import - import a smack label
* @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 label in the label list that
* matches the passed string, adding it if necessary.
*/
char *smk_import(const char *string, int len)
{
struct smack_known *skp;
/* labels cannot begin with a '-' */
if (string[0] == '-')
return NULL;
skp = smk_import_entry(string, len);
if (skp == NULL)
return NULL;
return skp->smk_known;
}
/**
* smack_from_secid - find the Smack label associated with a secid
* @secid: an integer that might be associated with a Smack label
......@@ -590,19 +590,3 @@ struct smack_known *smack_from_secid(const u32 secid)
rcu_read_unlock();
return &smack_known_invalid;
}
/**
* smack_to_secid - find the secid associated with a Smack label
* @smack: the Smack label
*
* Returns the appropriate secid if there is one,
* otherwise 0
*/
u32 smack_to_secid(const char *smack)
{
struct smack_known *skp = smk_find_entry(smack);
if (skp == NULL)
return 0;
return skp->smk_secid;
}
......@@ -54,6 +54,151 @@
LIST_HEAD(smk_ipv6_port_list);
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static void smk_bu_mode(int mode, char *s)
{
int i = 0;
if (mode & MAY_READ)
s[i++] = 'r';
if (mode & MAY_WRITE)
s[i++] = 'w';
if (mode & MAY_EXEC)
s[i++] = 'x';
if (mode & MAY_APPEND)
s[i++] = 'a';
if (mode & MAY_TRANSMUTE)
s[i++] = 't';
if (mode & MAY_LOCK)
s[i++] = 'l';
if (i == 0)
s[i++] = '-';
s[i] = '\0';
}
#endif
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static int smk_bu_note(char *note, struct smack_known *sskp,
struct smack_known *oskp, int mode, int rc)
{
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (rc <= 0)
return rc;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) %s\n",
sskp->smk_known, oskp->smk_known, acc, note);
return 0;
}
#else
#define smk_bu_note(note, sskp, oskp, mode, RC) (RC)
#endif
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static int smk_bu_current(char *note, struct smack_known *oskp,
int mode, int rc)
{
struct task_smack *tsp = current_security();
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (rc <= 0)
return rc;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) %s %s\n",
tsp->smk_task->smk_known, oskp->smk_known,
acc, current->comm, note);
return 0;
}
#else
#define smk_bu_current(note, oskp, mode, RC) (RC)
#endif
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static int smk_bu_task(struct task_struct *otp, int mode, int rc)
{
struct task_smack *tsp = current_security();
struct task_smack *otsp = task_security(otp);
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (rc <= 0)
return rc;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) %s to %s\n",
tsp->smk_task->smk_known, otsp->smk_task->smk_known, acc,
current->comm, otp->comm);
return 0;
}
#else
#define smk_bu_task(otp, mode, RC) (RC)
#endif
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static int smk_bu_inode(struct inode *inode, int mode, int rc)
{
struct task_smack *tsp = current_security();
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (rc <= 0)
return rc;
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,
inode->i_sb->s_id, inode->i_ino, current->comm);
return 0;
}
#else
#define smk_bu_inode(inode, mode, RC) (RC)
#endif
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
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->f_inode;
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (rc <= 0)
return rc;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n",
sskp->smk_known, (char *)file->f_security, acc,
inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name,
current->comm);
return 0;
}
#else
#define smk_bu_file(file, mode, RC) (RC)
#endif
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static int smk_bu_credfile(const struct cred *cred, struct file *file,
int mode, int rc)
{
struct task_smack *tsp = cred->security;
struct smack_known *sskp = tsp->smk_task;
struct inode *inode = file->f_inode;
char acc[SMK_NUM_ACCESS_TYPE + 1];
if (rc <= 0)
return rc;
smk_bu_mode(mode, acc);
pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n",
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name,
current->comm);
return 0;
}
#else
#define smk_bu_credfile(cred, file, mode, RC) (RC)
#endif
/**
* smk_fetch - Fetch the smack label from a file.
* @ip: a pointer to the inode
......@@ -87,11 +232,11 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
/**
* new_inode_smack - allocate an inode security blob
* @smack: a pointer to the Smack label to use in the blob
* @skp: a pointer to the Smack label entry to use in the blob
*
* Returns the new blob or NULL if there's no memory available
*/
struct inode_smack *new_inode_smack(char *smack)
struct inode_smack *new_inode_smack(struct smack_known *skp)
{
struct inode_smack *isp;
......@@ -99,7 +244,7 @@ struct inode_smack *new_inode_smack(char *smack)
if (isp == NULL)
return NULL;
isp->smk_inode = smack;
isp->smk_inode = skp;
isp->smk_flags = 0;
mutex_init(&isp->smk_lock);
......@@ -178,20 +323,20 @@ static inline unsigned int smk_ptrace_mode(unsigned int mode)
/**
* smk_ptrace_rule_check - helper for ptrace access
* @tracer: tracer process
* @tracee_label: label of the process that's about to be traced,
* the pointer must originate from smack structures
* @tracee_known: label entry of the process that's about to be traced
* @mode: ptrace attachment mode (PTRACE_MODE_*)
* @func: name of the function that called us, used for audit
*
* Returns 0 on access granted, -error on error
*/
static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label,
static int smk_ptrace_rule_check(struct task_struct *tracer,
struct smack_known *tracee_known,
unsigned int mode, const char *func)
{
int rc;
struct smk_audit_info ad, *saip = NULL;
struct task_smack *tsp;
struct smack_known *skp;
struct smack_known *tracer_known;
if ((mode & PTRACE_MODE_NOAUDIT) == 0) {
smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK);
......@@ -200,12 +345,12 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label,
}
tsp = task_security(tracer);
skp = smk_of_task(tsp);
tracer_known = smk_of_task(tsp);
if ((mode & PTRACE_MODE_ATTACH) &&
(smack_ptrace_rule == SMACK_PTRACE_EXACT ||
smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) {
if (skp->smk_known == tracee_label)
if (tracer_known->smk_known == tracee_known->smk_known)
rc = 0;
else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)
rc = -EACCES;
......@@ -215,13 +360,15 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label,
rc = -EACCES;
if (saip)
smack_log(skp->smk_known, tracee_label, 0, rc, saip);
smack_log(tracer_known->smk_known,
tracee_known->smk_known,
0, rc, saip);
return rc;
}
/* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */
rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip);
rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip);
return rc;
}
......@@ -250,7 +397,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
skp = smk_of_task(task_security(ctp));
rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__);
rc = smk_ptrace_rule_check(current, skp, mode, __func__);
return rc;
}
......@@ -273,8 +420,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
skp = smk_of_task(current_security());
rc = smk_ptrace_rule_check(ptp, skp->smk_known,
PTRACE_MODE_ATTACH, __func__);
rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
return rc;
}
......@@ -318,10 +464,10 @@ static int smack_sb_alloc_security(struct super_block *sb)
if (sbsp == NULL)
return -ENOMEM;
sbsp->smk_root = smack_known_floor.smk_known;
sbsp->smk_default = smack_known_floor.smk_known;
sbsp->smk_floor = smack_known_floor.smk_known;
sbsp->smk_hat = smack_known_hat.smk_known;
sbsp->smk_root = &smack_known_floor;
sbsp->smk_default = &smack_known_floor;
sbsp->smk_floor = &smack_known_floor;
sbsp->smk_hat = &smack_known_hat;
/*
* smk_initialized will be zero from kzalloc.
*/
......@@ -405,7 +551,6 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
struct smack_known *skp;
char *op;
char *commap;
char *nsp;
int transmute = 0;
int specified = 0;
......@@ -421,38 +566,38 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
op += strlen(SMK_FSHAT);
nsp = smk_import(op, 0);
if (nsp != NULL) {
sp->smk_hat = nsp;
skp = smk_import_entry(op, 0);
if (skp != NULL) {
sp->smk_hat = skp;
specified = 1;
}
} else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
op += strlen(SMK_FSFLOOR);
nsp = smk_import(op, 0);
if (nsp != NULL) {
sp->smk_floor = nsp;
skp = smk_import_entry(op, 0);
if (skp != NULL) {
sp->smk_floor = skp;
specified = 1;
}
} else if (strncmp(op, SMK_FSDEFAULT,
strlen(SMK_FSDEFAULT)) == 0) {
op += strlen(SMK_FSDEFAULT);
nsp = smk_import(op, 0);
if (nsp != NULL) {
sp->smk_default = nsp;
skp = smk_import_entry(op, 0);
if (skp != NULL) {
sp->smk_default = skp;
specified = 1;
}
} else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
op += strlen(SMK_FSROOT);
nsp = smk_import(op, 0);
if (nsp != NULL) {
sp->smk_root = nsp;
skp = smk_import_entry(op, 0);
if (skp != NULL) {
sp->smk_root = skp;
specified = 1;
}
} else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) {
op += strlen(SMK_FSTRANS);
nsp = smk_import(op, 0);
if (nsp != NULL) {
sp->smk_root = nsp;
skp = smk_import_entry(op, 0);
if (skp != NULL) {
sp->smk_root = skp;
transmute = 1;
specified = 1;
}
......@@ -469,8 +614,8 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
* Unprivileged mounts get root and default from the caller.
*/
skp = smk_of_current();
sp->smk_root = skp->smk_known;
sp->smk_default = skp->smk_known;
sp->smk_root = skp;
sp->smk_default = skp;
}
/*
* Initialize the root inode.
......@@ -507,6 +652,7 @@ static int smack_sb_statfs(struct dentry *dentry)
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad);
rc = smk_bu_current("statfs", sbp->smk_floor, MAY_READ, rc);
return rc;
}
......@@ -546,7 +692,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
tracer = ptrace_parent(current);
if (likely(tracer != NULL))
rc = smk_ptrace_rule_check(tracer,
isp->smk_task->smk_known,
isp->smk_task,
PTRACE_MODE_ATTACH,
__func__);
rcu_read_unlock();
......@@ -607,7 +753,7 @@ static int smack_inode_alloc_security(struct inode *inode)
{
struct smack_known *skp = smk_of_current();
inode->i_security = new_inode_smack(skp->smk_known);
inode->i_security = new_inode_smack(skp);
if (inode->i_security == NULL)
return -ENOMEM;
return 0;
......@@ -627,8 +773,8 @@ static void smack_inode_free_security(struct inode *inode)
/**
* smack_inode_init_security - copy out the smack from an inode
* @inode: the inode
* @dir: unused
* @inode: the newly created inode
* @dir: containing directory object
* @qstr: unused
* @name: where to put the attribute name
* @value: where to put the attribute value
......@@ -642,8 +788,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
{
struct inode_smack *issp = inode->i_security;
struct smack_known *skp = smk_of_current();
char *isp = smk_of_inode(inode);
char *dsp = smk_of_inode(dir);
struct smack_known *isp = smk_of_inode(inode);
struct smack_known *dsp = smk_of_inode(dir);
int may;
if (name)
......@@ -651,7 +797,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
if (value) {
rcu_read_lock();
may = smk_access_entry(skp->smk_known, dsp, &skp->smk_rules);
may = smk_access_entry(skp->smk_known, dsp->smk_known,
&skp->smk_rules);
rcu_read_unlock();
/*
......@@ -666,13 +813,13 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
issp->smk_flags |= SMK_INODE_CHANGED;
}
*value = kstrdup(isp, GFP_NOFS);
*value = kstrdup(isp->smk_known, GFP_NOFS);
if (*value == NULL)
return -ENOMEM;
}
if (len)
*len = strlen(isp) + 1;
*len = strlen(isp->smk_known);
return 0;
}
......@@ -688,7 +835,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
char *isp;
struct smack_known *isp;
struct smk_audit_info ad;
int rc;
......@@ -697,11 +844,13 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
isp = smk_of_inode(old_dentry->d_inode);
rc = smk_curacc(isp, MAY_WRITE, &ad);
rc = smk_bu_inode(old_dentry->d_inode, MAY_WRITE, rc);
if (rc == 0 && new_dentry->d_inode != NULL) {
isp = smk_of_inode(new_dentry->d_inode);
smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
rc = smk_curacc(isp, MAY_WRITE, &ad);
rc = smk_bu_inode(new_dentry->d_inode, MAY_WRITE, rc);
}
return rc;
......@@ -728,6 +877,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
* You need write access to the thing you're unlinking
*/
rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad);
rc = smk_bu_inode(ip, MAY_WRITE, rc);
if (rc == 0) {
/*
* You also need write access to the containing directory
......@@ -735,6 +885,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
smk_ad_setfield_u_fs_inode(&ad, dir);
rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
rc = smk_bu_inode(dir, MAY_WRITE, rc);
}
return rc;
}
......@@ -759,6 +910,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
* You need write access to the thing you're removing
*/
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
if (rc == 0) {
/*
* You also need write access to the containing directory
......@@ -766,6 +918,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
smk_ad_setfield_u_fs_inode(&ad, dir);
rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
rc = smk_bu_inode(dir, MAY_WRITE, rc);
}
return rc;
......@@ -773,10 +926,10 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
/**
* smack_inode_rename - Smack check on rename
* @old_inode: the old directory
* @old_dentry: unused
* @new_inode: the new directory
* @new_dentry: unused
* @old_inode: unused
* @old_dentry: the old object
* @new_inode: unused
* @new_dentry: the new object
*
* Read and write access is required on both the old and
* new directories.
......@@ -789,7 +942,7 @@ static int smack_inode_rename(struct inode *old_inode,
struct dentry *new_dentry)
{
int rc;
char *isp;
struct smack_known *isp;
struct smk_audit_info ad;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
......@@ -797,11 +950,13 @@ static int smack_inode_rename(struct inode *old_inode,
isp = smk_of_inode(old_dentry->d_inode);
rc = smk_curacc(isp, MAY_READWRITE, &ad);
rc = smk_bu_inode(old_dentry->d_inode, MAY_READWRITE, rc);
if (rc == 0 && new_dentry->d_inode != NULL) {
isp = smk_of_inode(new_dentry->d_inode);
smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
rc = smk_curacc(isp, MAY_READWRITE, &ad);
rc = smk_bu_inode(new_dentry->d_inode, MAY_READWRITE, rc);
}
return rc;
}
......@@ -819,6 +974,7 @@ static int smack_inode_permission(struct inode *inode, int mask)
{
struct smk_audit_info ad;
int no_block = mask & MAY_NOT_BLOCK;
int rc;
mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
/*
......@@ -832,7 +988,9 @@ static int smack_inode_permission(struct inode *inode, int mask)
return -ECHILD;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
smk_ad_setfield_u_fs_inode(&ad, inode);
return smk_curacc(smk_of_inode(inode), mask, &ad);
rc = smk_curacc(smk_of_inode(inode), mask, &ad);
rc = smk_bu_inode(inode, mask, rc);
return rc;
}
/**
......@@ -845,6 +1003,8 @@ static int smack_inode_permission(struct inode *inode, int mask)
static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
{
struct smk_audit_info ad;
int rc;
/*
* Need to allow for clearing the setuid bit.
*/
......@@ -853,12 +1013,14 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
return rc;
}
/**
* smack_inode_getattr - Smack check for getting attributes
* @mnt: unused
* @mnt: vfsmount of the object
* @dentry: the object
*
* Returns 0 if access is permitted, an error code otherwise
......@@ -867,21 +1029,24 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
struct smk_audit_info ad;
struct path path;
int rc;
path.dentry = dentry;
path.mnt = mnt;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, path);
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
return rc;
}
/**
* smack_inode_setxattr - Smack check for setting xattrs
* @dentry: the object
* @name: name of the attribute
* @value: unused
* @size: unused
* @value: value of the attribute
* @size: size of the value
* @flags: unused
*
* This protects the Smack attribute explicitly.
......@@ -923,7 +1088,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
rc = -EPERM;
if (rc == 0 && check_import) {
skp = smk_import_entry(value, size);
skp = size ? smk_import_entry(value, size) : NULL;
if (skp == NULL || (check_star &&
(skp == &smack_known_star || skp == &smack_known_web)))
rc = -EINVAL;
......@@ -932,8 +1097,10 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
if (rc == 0)
if (rc == 0) {
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
}
return rc;
}
......@@ -963,9 +1130,9 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
if (strcmp(name, XATTR_NAME_SMACK) == 0) {
skp = smk_import_entry(value, size);
if (skp != NULL)
isp->smk_inode = skp->smk_known;
isp->smk_inode = skp;
else
isp->smk_inode = smack_known_invalid.smk_known;
isp->smk_inode = &smack_known_invalid;
} else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
skp = smk_import_entry(value, size);
if (skp != NULL)
......@@ -993,11 +1160,14 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
static int smack_inode_getxattr(struct dentry *dentry, const char *name)
{
struct smk_audit_info ad;
int rc;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
return rc;
}
/**
......@@ -1033,6 +1203,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
if (rc != 0)
return rc;
......@@ -1070,14 +1241,14 @@ static int smack_inode_getsecurity(const struct inode *inode,
struct socket *sock;
struct super_block *sbp;
struct inode *ip = (struct inode *)inode;
char *isp;
struct smack_known *isp;
int ilen;
int rc = 0;
if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
isp = smk_of_inode(inode);
ilen = strlen(isp) + 1;
*buffer = isp;
ilen = strlen(isp->smk_known);
*buffer = isp->smk_known;
return ilen;
}
......@@ -1095,15 +1266,15 @@ static int smack_inode_getsecurity(const struct inode *inode,
ssp = sock->sk->sk_security;
if (strcmp(name, XATTR_SMACK_IPIN) == 0)
isp = ssp->smk_in->smk_known;
isp = ssp->smk_in;
else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
isp = ssp->smk_out->smk_known;
isp = ssp->smk_out;
else
return -EOPNOTSUPP;
ilen = strlen(isp) + 1;
ilen = strlen(isp->smk_known);
if (rc == 0) {
*buffer = isp;
*buffer = isp->smk_known;
rc = ilen;
}
......@@ -1122,13 +1293,12 @@ static int smack_inode_getsecurity(const struct inode *inode,
static int smack_inode_listsecurity(struct inode *inode, char *buffer,
size_t buffer_size)
{
int len = strlen(XATTR_NAME_SMACK);
int len = sizeof(XATTR_NAME_SMACK);
if (buffer != NULL && len <= buffer_size) {
if (buffer != NULL && len <= buffer_size)
memcpy(buffer, XATTR_NAME_SMACK, len);
return len;
}
return -EINVAL;
}
/**
......@@ -1140,7 +1310,7 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
{
struct inode_smack *isp = inode->i_security;
*secid = smack_to_secid(isp->smk_inode);
*secid = isp->smk_inode->smk_secid;
}
/*
......@@ -1179,7 +1349,7 @@ static int smack_file_alloc_security(struct file *file)
{
struct smack_known *skp = smk_of_current();
file->f_security = skp->smk_known;
file->f_security = skp;
return 0;
}
......@@ -1214,11 +1384,15 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path);
if (_IOC_DIR(cmd) & _IOC_WRITE)
if (_IOC_DIR(cmd) & _IOC_WRITE) {
rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
rc = smk_bu_file(file, MAY_WRITE, rc);
}
if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ))
if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) {
rc = smk_curacc(file->f_security, MAY_READ, &ad);
rc = smk_bu_file(file, MAY_READ, rc);
}
return rc;
}
......@@ -1233,10 +1407,13 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
static int smack_file_lock(struct file *file, unsigned int cmd)
{
struct smk_audit_info ad;
int rc;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path);
return smk_curacc(file->f_security, MAY_LOCK, &ad);
rc = smk_curacc(file->f_security, MAY_LOCK, &ad);
rc = smk_bu_file(file, MAY_LOCK, rc);
return rc;
}
/**
......@@ -1266,12 +1443,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path);
rc = smk_curacc(file->f_security, MAY_LOCK, &ad);
rc = smk_bu_file(file, MAY_LOCK, rc);
break;
case F_SETOWN:
case F_SETSIG:
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path);
rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
rc = smk_bu_file(file, MAY_WRITE, rc);
break;
default:
break;
......@@ -1298,7 +1477,7 @@ static int smack_mmap_file(struct file *file,
struct smack_known *mkp;
struct smack_rule *srp;
struct task_smack *tsp;
char *osmack;
struct smack_known *okp;
struct inode_smack *isp;
int may;
int mmay;
......@@ -1324,17 +1503,18 @@ static int smack_mmap_file(struct file *file,
* to that rule's object label.
*/
list_for_each_entry_rcu(srp, &skp->smk_rules, list) {
osmack = srp->smk_object;
okp = srp->smk_object;
/*
* Matching labels always allows access.
*/
if (mkp->smk_known == osmack)
if (mkp->smk_known == okp->smk_known)
continue;
/*
* If there is a matching local rule take
* that into account as well.
*/
may = smk_access_entry(srp->smk_subject->smk_known, osmack,
may = smk_access_entry(srp->smk_subject->smk_known,
okp->smk_known,
&tsp->smk_rules);
if (may == -ENOENT)
may = srp->smk_access;
......@@ -1352,7 +1532,7 @@ static int smack_mmap_file(struct file *file,
* If there isn't one a SMACK64MMAP subject
* can't have as much access as current.
*/
mmay = smk_access_entry(mkp->smk_known, osmack,
mmay = smk_access_entry(mkp->smk_known, okp->smk_known,
&mkp->smk_rules);
if (mmay == -ENOENT) {
rc = -EACCES;
......@@ -1362,7 +1542,7 @@ static int smack_mmap_file(struct file *file,
* If there is a local entry it modifies the
* potential access, too.
*/
tmay = smk_access_entry(mkp->smk_known, osmack,
tmay = smk_access_entry(mkp->smk_known, okp->smk_known,
&tsp->smk_rules);
if (tmay != -ENOENT)
mmay &= tmay;
......@@ -1394,7 +1574,7 @@ static int smack_file_set_fowner(struct file *file)
{
struct smack_known *skp = smk_of_current();
file->f_security = skp->smk_known;
file->f_security = skp;
return 0;
}
......@@ -1424,14 +1604,15 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
file = container_of(fown, struct file, f_owner);
/* we don't log here as rc can be overriden */
skp = smk_find_entry(file->f_security);
rc = smk_access(skp, tkp->smk_known, MAY_WRITE, NULL);
skp = file->f_security;
rc = smk_access(skp, tkp, MAY_WRITE, NULL);
rc = smk_bu_note("sigiotask", skp, tkp, MAY_WRITE, rc);
if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
rc = 0;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
smk_ad_setfield_u_tsk(&ad, tsk);
smack_log(file->f_security, tkp->smk_known, MAY_WRITE, rc, &ad);
smack_log(skp->smk_known, tkp->smk_known, MAY_WRITE, rc, &ad);
return rc;
}
......@@ -1443,6 +1624,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
*/
static int smack_file_receive(struct file *file)
{
int rc;
int may = 0;
struct smk_audit_info ad;
......@@ -1456,7 +1638,9 @@ static int smack_file_receive(struct file *file)
if (file->f_mode & FMODE_WRITE)
may |= MAY_WRITE;
return smk_curacc(file->f_security, may, &ad);
rc = smk_curacc(file->f_security, may, &ad);
rc = smk_bu_file(file, may, rc);
return rc;
}
/**
......@@ -1478,12 +1662,15 @@ static int smack_file_open(struct file *file, const struct cred *cred)
struct smk_audit_info ad;
int rc;
if (smack_privileged(CAP_MAC_OVERRIDE))
if (smack_privileged(CAP_MAC_OVERRIDE)) {
file->f_security = isp->smk_inode;
return 0;
}
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, file->f_path);
rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad);
rc = smk_bu_credfile(cred, file, MAY_READ, rc);
if (rc == 0)
file->f_security = isp->smk_inode;
......@@ -1622,7 +1809,7 @@ static int smack_kernel_create_files_as(struct cred *new,
struct inode_smack *isp = inode->i_security;
struct task_smack *tsp = new->security;
tsp->smk_forked = smk_find_entry(isp->smk_inode);
tsp->smk_forked = isp->smk_inode;
tsp->smk_task = tsp->smk_forked;
return 0;
}
......@@ -1640,10 +1827,13 @@ static int smk_curacc_on_task(struct task_struct *p, int access,
{
struct smk_audit_info ad;
struct smack_known *skp = smk_of_task(task_security(p));
int rc;
smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK);
smk_ad_setfield_u_tsk(&ad, p);
return smk_curacc(skp->smk_known, access, &ad);
rc = smk_curacc(skp, access, &ad);
rc = smk_bu_task(p, access, rc);
return rc;
}
/**
......@@ -1797,6 +1987,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
struct smk_audit_info ad;
struct smack_known *skp;
struct smack_known *tkp = smk_of_task(task_security(p));
int rc;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
smk_ad_setfield_u_tsk(&ad, p);
......@@ -1804,15 +1995,20 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
* Sending a signal requires that the sender
* can write the receiver.
*/
if (secid == 0)
return smk_curacc(tkp->smk_known, MAY_WRITE, &ad);
if (secid == 0) {
rc = smk_curacc(tkp, MAY_WRITE, &ad);
rc = smk_bu_task(p, MAY_WRITE, rc);
return rc;
}
/*
* If the secid isn't 0 we're dealing with some USB IO
* specific behavior. This is not clean. For one thing
* we can't take privilege into account.
*/
skp = smack_from_secid(secid);
return smk_access(skp, tkp->smk_known, MAY_WRITE, &ad);
rc = smk_access(skp, tkp, MAY_WRITE, &ad);
rc = smk_bu_note("USB signal", skp, tkp, MAY_WRITE, rc);
return rc;
}
/**
......@@ -1846,7 +2042,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
struct inode_smack *isp = inode->i_security;
struct smack_known *skp = smk_of_task(task_security(p));
isp->smk_inode = skp->smk_known;
isp->smk_inode = skp;
}
/*
......@@ -1904,7 +2100,7 @@ static void smack_sk_free_security(struct sock *sk)
*
* Returns the label of the far end or NULL if it's not special.
*/
static char *smack_host_label(struct sockaddr_in *sip)
static struct smack_known *smack_host_label(struct sockaddr_in *sip)
{
struct smk_netlbladdr *snp;
struct in_addr *siap = &sip->sin_addr;
......@@ -1921,7 +2117,7 @@ static char *smack_host_label(struct sockaddr_in *sip)
if ((&snp->smk_host.sin_addr)->s_addr ==
(siap->s_addr & (&snp->smk_mask)->s_addr)) {
/* we have found the special CIPSO option */
if (snp->smk_label == smack_cipso_option)
if (snp->smk_label == &smack_cipso_option)
return NULL;
return snp->smk_label;
}
......@@ -1986,13 +2182,13 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
struct smack_known *skp;
int rc;
int sk_lbl;
char *hostsp;
struct smack_known *hkp;
struct socket_smack *ssp = sk->sk_security;
struct smk_audit_info ad;
rcu_read_lock();
hostsp = smack_host_label(sap);
if (hostsp != NULL) {
hkp = smack_host_label(sap);
if (hkp != NULL) {
#ifdef CONFIG_AUDIT
struct lsm_network_audit net;
......@@ -2003,7 +2199,8 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
#endif
sk_lbl = SMACK_UNLABELED_SOCKET;
skp = ssp->smk_out;
rc = smk_access(skp, hostsp, MAY_WRITE, &ad);
rc = smk_access(skp, hkp, MAY_WRITE, &ad);
rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc);
} else {
sk_lbl = SMACK_CIPSO_SOCKET;
rc = 0;
......@@ -2104,18 +2301,19 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
struct socket_smack *ssp = sk->sk_security;
struct smack_known *skp;
unsigned short port = 0;
char *object;
struct smack_known *object;
struct smk_audit_info ad;
int rc;
#ifdef CONFIG_AUDIT
struct lsm_network_audit net;
#endif
if (act == SMK_RECEIVING) {
skp = smack_net_ambient;
object = ssp->smk_in->smk_known;
object = ssp->smk_in;
} else {
skp = ssp->smk_out;
object = smack_net_ambient->smk_known;
object = smack_net_ambient;
}
/*
......@@ -2142,7 +2340,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
if (spp->smk_port != port)
continue;
object = spp->smk_in->smk_known;
object = spp->smk_in;
if (act == SMK_CONNECTING)
ssp->smk_packet = spp->smk_out;
break;
......@@ -2159,7 +2357,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
else
ad.a.u.net->v6info.daddr = address->sin6_addr;
#endif
return smk_access(skp, object, MAY_WRITE, &ad);
rc = smk_access(skp, object, MAY_WRITE, &ad);
rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
return rc;
}
/**
......@@ -2191,7 +2391,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
return -EINVAL;
if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
nsp->smk_inode = skp->smk_known;
nsp->smk_inode = skp;
nsp->smk_flags |= SMK_INODE_INSTANT;
return 0;
}
......@@ -2333,7 +2533,7 @@ static int smack_msg_msg_alloc_security(struct msg_msg *msg)
{
struct smack_known *skp = smk_of_current();
msg->security = skp->smk_known;
msg->security = skp;
return 0;
}
......@@ -2354,9 +2554,9 @@ static void smack_msg_msg_free_security(struct msg_msg *msg)
*
* Returns a pointer to the smack value
*/
static char *smack_of_shm(struct shmid_kernel *shp)
static struct smack_known *smack_of_shm(struct shmid_kernel *shp)
{
return (char *)shp->shm_perm.security;
return (struct smack_known *)shp->shm_perm.security;
}
/**
......@@ -2370,7 +2570,7 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp)
struct kern_ipc_perm *isp = &shp->shm_perm;
struct smack_known *skp = smk_of_current();
isp->security = skp->smk_known;
isp->security = skp;
return 0;
}
......@@ -2396,14 +2596,17 @@ static void smack_shm_free_security(struct shmid_kernel *shp)
*/
static int smk_curacc_shm(struct shmid_kernel *shp, int access)
{
char *ssp = smack_of_shm(shp);
struct smack_known *ssp = smack_of_shm(shp);
struct smk_audit_info ad;
int rc;
#ifdef CONFIG_AUDIT
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
ad.a.u.ipc_id = shp->shm_perm.id;
#endif
return smk_curacc(ssp, access, &ad);
rc = smk_curacc(ssp, access, &ad);
rc = smk_bu_current("shm", ssp, access, rc);
return rc;
}
/**
......@@ -2478,9 +2681,9 @@ static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
*
* Returns a pointer to the smack value
*/
static char *smack_of_sem(struct sem_array *sma)
static struct smack_known *smack_of_sem(struct sem_array *sma)
{
return (char *)sma->sem_perm.security;
return (struct smack_known *)sma->sem_perm.security;
}
/**
......@@ -2494,7 +2697,7 @@ static int smack_sem_alloc_security(struct sem_array *sma)
struct kern_ipc_perm *isp = &sma->sem_perm;
struct smack_known *skp = smk_of_current();
isp->security = skp->smk_known;
isp->security = skp;
return 0;
}
......@@ -2520,14 +2723,17 @@ static void smack_sem_free_security(struct sem_array *sma)
*/
static int smk_curacc_sem(struct sem_array *sma, int access)
{
char *ssp = smack_of_sem(sma);
struct smack_known *ssp = smack_of_sem(sma);
struct smk_audit_info ad;
int rc;
#ifdef CONFIG_AUDIT
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
ad.a.u.ipc_id = sma->sem_perm.id;
#endif
return smk_curacc(ssp, access, &ad);
rc = smk_curacc(ssp, access, &ad);
rc = smk_bu_current("sem", ssp, access, rc);
return rc;
}
/**
......@@ -2613,7 +2819,7 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq)
struct kern_ipc_perm *kisp = &msq->q_perm;
struct smack_known *skp = smk_of_current();
kisp->security = skp->smk_known;
kisp->security = skp;
return 0;
}
......@@ -2634,11 +2840,11 @@ static void smack_msg_queue_free_security(struct msg_queue *msq)
* smack_of_msq - the smack pointer for the msq
* @msq: the object
*
* Returns a pointer to the smack value
* Returns a pointer to the smack label entry
*/
static char *smack_of_msq(struct msg_queue *msq)
static struct smack_known *smack_of_msq(struct msg_queue *msq)
{
return (char *)msq->q_perm.security;
return (struct smack_known *)msq->q_perm.security;
}
/**
......@@ -2650,14 +2856,17 @@ static char *smack_of_msq(struct msg_queue *msq)
*/
static int smk_curacc_msq(struct msg_queue *msq, int access)
{
char *msp = smack_of_msq(msq);
struct smack_known *msp = smack_of_msq(msq);
struct smk_audit_info ad;
int rc;
#ifdef CONFIG_AUDIT
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
ad.a.u.ipc_id = msq->q_perm.id;
#endif
return smk_curacc(msp, access, &ad);
rc = smk_curacc(msp, access, &ad);
rc = smk_bu_current("msq", msp, access, rc);
return rc;
}
/**
......@@ -2750,15 +2959,18 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
*/
static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
{
char *isp = ipp->security;
struct smack_known *iskp = ipp->security;
int may = smack_flags_to_may(flag);
struct smk_audit_info ad;
int rc;
#ifdef CONFIG_AUDIT
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
ad.a.u.ipc_id = ipp->id;
#endif
return smk_curacc(isp, may, &ad);
rc = smk_curacc(iskp, may, &ad);
rc = smk_bu_current("svipc", iskp, may, rc);
return rc;
}
/**
......@@ -2768,9 +2980,9 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
*/
static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
{
char *smack = ipp->security;
struct smack_known *iskp = ipp->security;
*secid = smack_to_secid(smack);
*secid = iskp->smk_secid;
}
/**
......@@ -2787,7 +2999,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
struct inode_smack *isp;
struct smack_known *skp;
struct smack_known *ckp = smk_of_current();
char *final;
struct smack_known *final;
char trattr[TRANS_TRUE_SIZE];
int transflag = 0;
int rc;
......@@ -2827,8 +3039,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* so there's no opportunity to set the mount
* options.
*/
sbsp->smk_root = smack_known_star.smk_known;
sbsp->smk_default = smack_known_star.smk_known;
sbsp->smk_root = &smack_known_star;
sbsp->smk_default = &smack_known_star;
}
isp->smk_inode = sbsp->smk_root;
isp->smk_flags |= SMK_INODE_INSTANT;
......@@ -2858,7 +3070,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*
* Cgroupfs is special
*/
final = smack_known_star.smk_known;
final = &smack_known_star;
break;
case DEVPTS_SUPER_MAGIC:
/*
......@@ -2866,7 +3078,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* Programs that change smack have to treat the
* pty with respect.
*/
final = ckp->smk_known;
final = ckp;
break;
case PROC_SUPER_MAGIC:
/*
......@@ -2880,7 +3092,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* but watch out, because they're volitile,
* getting recreated on every reboot.
*/
final = smack_known_star.smk_known;
final = &smack_known_star;
/*
* No break.
*
......@@ -2899,7 +3111,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* UNIX domain sockets use lower level socket data.
*/
if (S_ISSOCK(inode->i_mode)) {
final = smack_known_star.smk_known;
final = &smack_known_star;
break;
}
/*
......@@ -2916,7 +3128,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
dp = dget(opt_dentry);
skp = smk_fetch(XATTR_NAME_SMACK, inode, dp);
if (skp != NULL)
final = skp->smk_known;
final = skp;
/*
* Transmuting directory
......@@ -2965,7 +3177,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
}
if (final == NULL)
isp->smk_inode = ckp->smk_known;
isp->smk_inode = ckp;
else
isp->smk_inode = final;
......@@ -3090,9 +3302,13 @@ static int smack_unix_stream_connect(struct sock *sock,
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
smk_ad_setfield_u_net_sk(&ad, other);
#endif
rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad);
if (rc == 0)
rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL);
rc = smk_access(skp, okp, MAY_WRITE, &ad);
rc = smk_bu_note("UDS connect", skp, okp, MAY_WRITE, rc);
if (rc == 0) {
rc = smk_access(okp, skp, MAY_WRITE, NULL);
rc = smk_bu_note("UDS connect", okp, skp,
MAY_WRITE, rc);
}
}
/*
......@@ -3118,8 +3334,8 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
{
struct socket_smack *ssp = sock->sk->sk_security;
struct socket_smack *osp = other->sk->sk_security;
struct smack_known *skp;
struct smk_audit_info ad;
int rc;
#ifdef CONFIG_AUDIT
struct lsm_network_audit net;
......@@ -3131,8 +3347,9 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
if (smack_privileged(CAP_MAC_OVERRIDE))
return 0;
skp = ssp->smk_out;
return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad);
rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
rc = smk_bu_note("UDS send", ssp->smk_out, osp->smk_in, MAY_WRITE, rc);
return rc;
}
/**
......@@ -3346,7 +3563,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
* This is the simplist possible security model
* for networking.
*/
rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in,
MAY_WRITE, rc);
if (rc != 0)
netlbl_skbuff_err(skb, rc, 0);
break;
......@@ -3489,7 +3708,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct netlbl_lsm_secattr secattr;
struct sockaddr_in addr;
struct iphdr *hdr;
char *hsp;
struct smack_known *hskp;
int rc;
struct smk_audit_info ad;
#ifdef CONFIG_AUDIT
......@@ -3526,7 +3745,8 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
* Receiving a packet requires that the other end be able to write
* here. Read access is not required.
*/
rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
rc = smk_bu_note("IPv4 connect", skp, ssp->smk_in, MAY_WRITE, rc);
if (rc != 0)
return rc;
......@@ -3544,10 +3764,10 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
hdr = ip_hdr(skb);
addr.sin_addr.s_addr = hdr->saddr;
rcu_read_lock();
hsp = smack_host_label(&addr);
hskp = smack_host_label(&addr);
rcu_read_unlock();
if (hsp == NULL)
if (hskp == NULL)
rc = netlbl_req_setattr(req, &skp->smk_netlabel);
else
netlbl_req_delattr(req);
......@@ -3599,7 +3819,7 @@ static int smack_key_alloc(struct key *key, const struct cred *cred,
{
struct smack_known *skp = smk_of_task(cred->security);
key->security = skp->smk_known;
key->security = skp;
return 0;
}
......@@ -3630,6 +3850,7 @@ static int smack_key_permission(key_ref_t key_ref,
struct smk_audit_info ad;
struct smack_known *tkp = smk_of_task(cred->security);
int request = 0;
int rc;
keyp = key_ref_to_ptr(key_ref);
if (keyp == NULL)
......@@ -3654,7 +3875,9 @@ static int smack_key_permission(key_ref_t key_ref,
request = MAY_READ;
if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR))
request = MAY_WRITE;
return smk_access(tkp, keyp->security, request, &ad);
rc = smk_access(tkp, keyp->security, request, &ad);
rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
return rc;
}
#endif /* CONFIG_KEYS */
......@@ -3685,6 +3908,7 @@ static int smack_key_permission(key_ref_t key_ref,
*/
static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
{
struct smack_known *skp;
char **rule = (char **)vrule;
*rule = NULL;
......@@ -3694,7 +3918,9 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
if (op != Audit_equal && op != Audit_not_equal)
return -EINVAL;
*rule = smk_import(rulestr, 0);
skp = smk_import_entry(rulestr, 0);
if (skp)
*rule = skp->smk_known;
return 0;
}
......@@ -3813,7 +4039,12 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
*/
static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
*secid = smack_to_secid(secdata);
struct smack_known *skp = smk_find_entry(secdata);
if (skp)
*secid = skp->smk_secid;
else
*secid = 0;
return 0;
}
......
......@@ -131,14 +131,17 @@ LIST_HEAD(smack_rule_list);
struct smack_parsed_rule {
struct smack_known *smk_subject;
char *smk_object;
struct smack_known *smk_object;
int smk_access1;
int smk_access2;
};
static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
const char *smack_cipso_option = SMACK_CIPSO_OPTION;
struct smack_known smack_cipso_option = {
.smk_known = SMACK_CIPSO_OPTION,
.smk_secid = 0,
};
/*
* Values for parsing cipso rules
......@@ -304,6 +307,10 @@ static int smk_perm_from_str(const char *string)
case 'L':
perm |= MAY_LOCK;
break;
case 'b':
case 'B':
perm |= MAY_BRINGUP;
break;
default:
return perm;
}
......@@ -335,7 +342,7 @@ static int smk_fill_rule(const char *subject, const char *object,
if (rule->smk_subject == NULL)
return -EINVAL;
rule->smk_object = smk_import(object, len);
rule->smk_object = smk_import_entry(object, len);
if (rule->smk_object == NULL)
return -EINVAL;
} else {
......@@ -355,7 +362,7 @@ static int smk_fill_rule(const char *subject, const char *object,
kfree(cp);
if (skp == NULL)
return -ENOENT;
rule->smk_object = skp->smk_known;
rule->smk_object = skp;
}
rule->smk_access1 = smk_perm_from_str(access1);
......@@ -594,13 +601,15 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
* anything you read back.
*/
if (strlen(srp->smk_subject->smk_known) >= max ||
strlen(srp->smk_object) >= max)
strlen(srp->smk_object->smk_known) >= max)
return;
if (srp->smk_access == 0)
return;
seq_printf(s, "%s %s", srp->smk_subject->smk_known, srp->smk_object);
seq_printf(s, "%s %s",
srp->smk_subject->smk_known,
srp->smk_object->smk_known);
seq_putc(s, ' ');
......@@ -616,6 +625,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
seq_putc(s, 't');
if (srp->smk_access & MAY_LOCK)
seq_putc(s, 'l');
if (srp->smk_access & MAY_BRINGUP)
seq_putc(s, 'b');
seq_putc(s, '\n');
}
......@@ -1067,7 +1078,7 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
seq_printf(s, "%u.%u.%u.%u/%d %s\n",
hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label->smk_known);
return 0;
}
......@@ -1147,10 +1158,10 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct smk_netlbladdr *skp;
struct smk_netlbladdr *snp;
struct sockaddr_in newname;
char *smack;
char *sp;
struct smack_known *skp;
char *data;
char *host = (char *)&newname.sin_addr.s_addr;
int rc;
......@@ -1213,15 +1224,15 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
* If smack begins with '-', it is an option, don't import it
*/
if (smack[0] != '-') {
sp = smk_import(smack, 0);
if (sp == NULL) {
skp = smk_import_entry(smack, 0);
if (skp == NULL) {
rc = -EINVAL;
goto free_out;
}
} else {
/* check known options */
if (strcmp(smack, smack_cipso_option) == 0)
sp = (char *)smack_cipso_option;
if (strcmp(smack, smack_cipso_option.smk_known) == 0)
skp = &smack_cipso_option;
else {
rc = -EINVAL;
goto free_out;
......@@ -1244,9 +1255,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
nsa = newname.sin_addr.s_addr;
/* try to find if the prefix is already in the list */
found = 0;
list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
if (skp->smk_host.sin_addr.s_addr == nsa &&
skp->smk_mask.s_addr == mask.s_addr) {
list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) {
if (snp->smk_host.sin_addr.s_addr == nsa &&
snp->smk_mask.s_addr == mask.s_addr) {
found = 1;
break;
}
......@@ -1254,26 +1265,26 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
smk_netlabel_audit_set(&audit_info);
if (found == 0) {
skp = kzalloc(sizeof(*skp), GFP_KERNEL);
if (skp == NULL)
snp = kzalloc(sizeof(*snp), GFP_KERNEL);
if (snp == NULL)
rc = -ENOMEM;
else {
rc = 0;
skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
skp->smk_mask.s_addr = mask.s_addr;
skp->smk_label = sp;
smk_netlbladdr_insert(skp);
snp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
snp->smk_mask.s_addr = mask.s_addr;
snp->smk_label = skp;
smk_netlbladdr_insert(snp);
}
} else {
/* we delete the unlabeled entry, only if the previous label
* wasn't the special CIPSO option */
if (skp->smk_label != smack_cipso_option)
if (snp->smk_label != &smack_cipso_option)
rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
&skp->smk_host.sin_addr, &skp->smk_mask,
&snp->smk_host.sin_addr, &snp->smk_mask,
PF_INET, &audit_info);
else
rc = 0;
skp->smk_label = sp;
snp->smk_label = skp;
}
/*
......@@ -1281,10 +1292,10 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
* this host so that incoming packets get labeled.
* but only if we didn't get the special CIPSO option
*/
if (rc == 0 && sp != smack_cipso_option)
if (rc == 0 && skp != &smack_cipso_option)
rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
&skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
smack_to_secid(skp->smk_label), &audit_info);
&snp->smk_host.sin_addr, &snp->smk_mask, PF_INET,
snp->smk_label->smk_secid, &audit_info);
if (rc == 0)
rc = count;
......@@ -1677,7 +1688,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
if (smack_onlycap != NULL && smack_onlycap != skp)
return -EPERM;
data = kzalloc(count, GFP_KERNEL);
data = kzalloc(count + 1, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
......@@ -1880,7 +1891,10 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
else if (res != -ENOENT)
return -EINVAL;
data[0] = res == 0 ? '1' : '0';
/*
* smk_access() can return a value > 0 in the "bringup" case.
*/
data[0] = res >= 0 ? '1' : '0';
data[1] = '\0';
simple_transaction_set(file, 2);
......@@ -2228,7 +2242,7 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
data = kzalloc(count, GFP_KERNEL);
data = kzalloc(count + 1, GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
......
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