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