Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ca00728 authored by James Morris's avatar James Morris
Browse files

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

parents e2fa3d79 0fcfee61
Loading
Loading
Loading
Loading
+62 −48
Original line number Diff line number Diff line
@@ -28,6 +28,38 @@
#define SMK_LABELLEN	24
#define SMK_LONGLABEL	256

/*
 * This is the repository for labels seen so that it is
 * not necessary to keep allocating tiny chuncks of memory
 * and so that they can be shared.
 *
 * Labels are never modified in place. Anytime a label
 * is imported (e.g. xattrset on a file) the list is checked
 * for it and it is added if it doesn't exist. The address
 * is passed out in either case. Entries are added, but
 * never deleted.
 *
 * Since labels are hanging around anyway it doesn't
 * hurt to maintain a secid for those awkward situations
 * where kernel components that ought to use LSM independent
 * interfaces don't. The secid should go away when all of
 * these components have been repaired.
 *
 * The cipso value associated with the label gets stored here, too.
 *
 * Keep the access rules for this subject label here so that
 * the entire set of rules does not need to be examined every
 * time.
 */
struct smack_known {
	struct list_head		list;
	char				*smk_known;
	u32				smk_secid;
	struct netlbl_lsm_secattr	smk_netlabel;	/* on wire labels */
	struct list_head		smk_rules;	/* access rules */
	struct mutex			smk_rules_lock;	/* lock for rules */
};

/*
 * Maximum number of bytes for the levels in a CIPSO IP option.
 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -46,7 +78,7 @@ struct superblock_smack {
};

struct socket_smack {
	char		*smk_out;	/* outbound label */
	struct smack_known	*smk_out;	/* outbound label */
	char			*smk_in;	/* inbound label */
	char			*smk_packet;	/* TCP peer label */
};
@@ -56,15 +88,15 @@ struct socket_smack {
 */
struct inode_smack {
	char			*smk_inode;	/* label of the fso */
	char		*smk_task;	/* label of the task */
	char		*smk_mmap;	/* label of the mmap domain */
	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 */
	int			smk_flags;	/* smack inode flags */
};

struct task_smack {
	char			*smk_task;	/* label for access control */
	char			*smk_forked;	/* label when forked */
	struct smack_known	*smk_task;	/* label for access control */
	struct smack_known	*smk_forked;	/* label when forked */
	struct list_head	smk_rules;	/* per task access rules */
	struct mutex		smk_rules_lock;	/* lock for the rules */
};
@@ -78,7 +110,7 @@ struct task_smack {
 */
struct smack_rule {
	struct list_head	list;
	char			*smk_subject;
	struct smack_known	*smk_subject;
	char			*smk_object;
	int			smk_access;
};
@@ -94,35 +126,14 @@ struct smk_netlbladdr {
};

/*
 * This is the repository for labels seen so that it is
 * not necessary to keep allocating tiny chuncks of memory
 * and so that they can be shared.
 *
 * Labels are never modified in place. Anytime a label
 * is imported (e.g. xattrset on a file) the list is checked
 * for it and it is added if it doesn't exist. The address
 * is passed out in either case. Entries are added, but
 * never deleted.
 *
 * Since labels are hanging around anyway it doesn't
 * hurt to maintain a secid for those awkward situations
 * where kernel components that ought to use LSM independent
 * interfaces don't. The secid should go away when all of
 * these components have been repaired.
 *
 * The cipso value associated with the label gets stored here, too.
 *
 * Keep the access rules for this subject label here so that
 * the entire set of rules does not need to be examined every
 * time.
 * An entry in the table identifying ports.
 */
struct smack_known {
struct smk_port_label {
	struct list_head	list;
	char				*smk_known;
	u32				smk_secid;
	struct netlbl_lsm_secattr	smk_netlabel;	/* on wire labels */
	struct list_head		smk_rules;	/* access rules */
	struct mutex			smk_rules_lock;	/* lock for rules */
	struct sock		*smk_sock;	/* socket initialized on */
	unsigned short		smk_port;	/* the port number */
	char			*smk_in;	/* incoming label */
	struct smack_known	*smk_out;	/* outgoing label */
};

/*
@@ -132,6 +143,7 @@ struct smack_known {
#define SMK_FSFLOOR	"smackfsfloor="
#define SMK_FSHAT	"smackfshat="
#define SMK_FSROOT	"smackfsroot="
#define SMK_FSTRANS	"smackfstransmute="

#define SMACK_CIPSO_OPTION 	"-CIPSO"

@@ -203,9 +215,9 @@ struct inode_smack *new_inode_smack(char *);
 * These functions are in smack_access.c
 */
int smk_access_entry(char *, char *, struct list_head *);
int smk_access(char *, char *, int, struct smk_audit_info *);
int smk_access(struct smack_known *, char *, int, struct smk_audit_info *);
int smk_curacc(char *, u32, struct smk_audit_info *);
char *smack_from_secid(const u32);
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);
@@ -218,7 +230,7 @@ u32 smack_to_secid(const char *);
 */
extern int smack_cipso_direct;
extern int smack_cipso_mapped;
extern char *smack_net_ambient;
extern struct smack_known *smack_net_ambient;
extern char *smack_onlycap;
extern const char *smack_cipso_option;

@@ -254,17 +266,17 @@ static inline char *smk_of_inode(const struct inode *isp)
}

/*
 * Present a pointer to the smack label in an task blob.
 * Present a pointer to the smack label entry in an task blob.
 */
static inline char *smk_of_task(const struct task_smack *tsp)
static inline struct smack_known *smk_of_task(const struct task_smack *tsp)
{
	return tsp->smk_task;
}

/*
 * Present a pointer to the forked smack label in an task blob.
 * Present a pointer to the forked smack label entry in an task blob.
 */
static inline char *smk_of_forked(const struct task_smack *tsp)
static inline struct smack_known *smk_of_forked(const struct task_smack *tsp)
{
	return tsp->smk_forked;
}
@@ -272,7 +284,7 @@ static inline char *smk_of_forked(const struct task_smack *tsp)
/*
 * Present a pointer to the smack label in the current task blob.
 */
static inline char *smk_of_current(void)
static inline struct smack_known *smk_of_current(void)
{
	return smk_of_task(current_security());
}
@@ -283,9 +295,11 @@ static inline char *smk_of_current(void)
 */
static inline int smack_privileged(int cap)
{
	struct smack_known *skp = smk_of_current();

	if (!capable(cap))
		return 0;
	if (smack_onlycap == NULL || smack_onlycap == smk_of_current())
	if (smack_onlycap == NULL || smack_onlycap == skp->smk_known)
		return 1;
	return 0;
}
+23 −20
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ int smk_access_entry(char *subject_label, char *object_label,

	list_for_each_entry_rcu(srp, rule_list, list) {
		if (srp->smk_object == object_label &&
		    srp->smk_subject == subject_label) {
		    srp->smk_subject->smk_known == subject_label) {
			may = srp->smk_access;
			break;
		}
@@ -104,7 +104,7 @@ int smk_access_entry(char *subject_label, char *object_label,

/**
 * smk_access - determine if a subject has a specific access to an object
 * @subject_label: a pointer to the subject's Smack label
 * @subject_known: a pointer to the subject's Smack label entry
 * @object_label: a pointer to the object's Smack label
 * @request: the access requested, in "MAY" format
 * @a : a pointer to the audit data
@@ -115,10 +115,9 @@ int smk_access_entry(char *subject_label, char *object_label,
 *
 * Smack labels are shared on smack_list
 */
int smk_access(char *subject_label, char *object_label, int request,
	       struct smk_audit_info *a)
int smk_access(struct smack_known *subject_known, char *object_label,
		int request, struct smk_audit_info *a)
{
	struct smack_known *skp;
	int may = MAY_NOT;
	int rc = 0;

@@ -127,7 +126,7 @@ int smk_access(char *subject_label, char *object_label, int request,
	 *
	 * A star subject can't access any object.
	 */
	if (subject_label == smack_known_star.smk_known) {
	if (subject_known == &smack_known_star) {
		rc = -EACCES;
		goto out_audit;
	}
@@ -137,7 +136,7 @@ int smk_access(char *subject_label, char *object_label, int request,
	 * An internet subject can access any object.
	 */
	if (object_label == smack_known_web.smk_known ||
	    subject_label == smack_known_web.smk_known)
	    subject_known == &smack_known_web)
		goto out_audit;
	/*
	 * A star object can be accessed by any subject.
@@ -148,7 +147,7 @@ int smk_access(char *subject_label, char *object_label, int request,
	 * An object can be accessed in any way by a subject
	 * with the same label.
	 */
	if (subject_label == object_label)
	if (subject_known->smk_known == object_label)
		goto out_audit;
	/*
	 * A hat subject can read any object.
@@ -157,7 +156,7 @@ int smk_access(char *subject_label, char *object_label, int request,
	if ((request & MAY_ANYREAD) == request) {
		if (object_label == smack_known_floor.smk_known)
			goto out_audit;
		if (subject_label == smack_known_hat.smk_known)
		if (subject_known == &smack_known_hat)
			goto out_audit;
	}
	/*
@@ -167,9 +166,9 @@ int smk_access(char *subject_label, char *object_label, int request,
	 * good. A negative response from smk_access_entry()
	 * indicates there is no entry for this pair.
	 */
	skp = smk_find_entry(subject_label);
	rcu_read_lock();
	may = smk_access_entry(subject_label, object_label, &skp->smk_rules);
	may = smk_access_entry(subject_known->smk_known, object_label,
				&subject_known->smk_rules);
	rcu_read_unlock();

	if (may > 0 && (request & may) == request)
@@ -179,7 +178,8 @@ int smk_access(char *subject_label, char *object_label, int request,
out_audit:
#ifdef CONFIG_AUDIT
	if (a)
		smack_log(subject_label, object_label, request, rc, a);
		smack_log(subject_known->smk_known, object_label, request,
				rc, a);
#endif
	return rc;
}
@@ -198,20 +198,21 @@ int smk_access(char *subject_label, char *object_label, int request,
int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
{
	struct task_smack *tsp = current_security();
	char *sp = smk_of_task(tsp);
	struct smack_known *skp = smk_of_task(tsp);
	int may;
	int rc;

	/*
	 * Check the global rule list
	 */
	rc = smk_access(sp, obj_label, mode, NULL);
	rc = smk_access(skp, obj_label, 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(sp, obj_label, &tsp->smk_rules);
		may = smk_access_entry(skp->smk_known, obj_label,
					&tsp->smk_rules);
		if (may < 0)
			goto out_audit;
		if ((mode & may) == mode)
@@ -228,7 +229,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
out_audit:
#ifdef CONFIG_AUDIT
	if (a)
		smack_log(sp, obj_label, mode, rc, a);
		smack_log(skp->smk_known, obj_label, mode, rc, a);
#endif
	return rc;
}
@@ -402,6 +403,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
	sap->flags |= NETLBL_SECATTR_MLS_CAT;
	sap->attr.mls.lvl = level;
	sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
	if (!sap->attr.mls.cat)
		return -ENOMEM;
	sap->attr.mls.cat->startbit = 0;

	for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
@@ -513,10 +516,10 @@ char *smk_import(const char *string, int len)
 * smack_from_secid - find the Smack label associated with a secid
 * @secid: an integer that might be associated with a Smack label
 *
 * Returns a pointer to the appropriate Smack label if there is one,
 * Returns a pointer to the appropriate Smack label entry if there is one,
 * otherwise a pointer to the invalid Smack label.
 */
char *smack_from_secid(const u32 secid)
struct smack_known *smack_from_secid(const u32 secid)
{
	struct smack_known *skp;

@@ -524,7 +527,7 @@ char *smack_from_secid(const u32 secid)
	list_for_each_entry_rcu(skp, &smack_known_list, list) {
		if (skp->smk_secid == secid) {
			rcu_read_unlock();
			return skp->smk_known;
			return skp;
		}
	}

@@ -533,7 +536,7 @@ char *smack_from_secid(const u32 secid)
	 * of a secid that is not on the list.
	 */
	rcu_read_unlock();
	return smack_known_invalid.smk_known;
	return &smack_known_invalid;
}

/**
+498 −186

File changed.

Preview size limit exceeded, changes collapsed.

+27 −26
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ static DEFINE_MUTEX(smk_netlbladdr_lock);
 * If it isn't somehow marked, use this.
 * It can be reset via smackfs/ambient
 */
char *smack_net_ambient;
struct smack_known *smack_net_ambient;

/*
 * This is the level in a CIPSO header that indicates a
@@ -112,7 +112,7 @@ struct smack_master_list {
LIST_HEAD(smack_rule_list);

struct smack_parsed_rule {
	char			*smk_subject;
	struct smack_known	*smk_subject;
	char			*smk_object;
	int			smk_access1;
	int			smk_access2;
@@ -163,9 +163,11 @@ static inline void smack_catset_bit(unsigned int cat, char *catsetp)
 */
static void smk_netlabel_audit_set(struct netlbl_audit *nap)
{
	struct smack_known *skp = smk_of_current();

	nap->loginuid = audit_get_loginuid(current);
	nap->sessionid = audit_get_sessionid(current);
	nap->secid = smack_to_secid(smk_of_current());
	nap->secid = skp->smk_secid;
}

/*
@@ -306,7 +308,7 @@ static int smk_fill_rule(const char *subject, const char *object,
	struct smack_known *skp;

	if (import) {
		rule->smk_subject = smk_import(subject, len);
		rule->smk_subject = smk_import_entry(subject, len);
		if (rule->smk_subject == NULL)
			return -1;

@@ -321,7 +323,7 @@ static int smk_fill_rule(const char *subject, const char *object,
		kfree(cp);
		if (skp == NULL)
			return -1;
		rule->smk_subject = skp->smk_known;
		rule->smk_subject = skp;

		cp = smk_parse_smack(object, len);
		if (cp == NULL)
@@ -445,7 +447,6 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
					struct list_head *rule_list,
					struct mutex *rule_lock, int format)
{
	struct smack_known *skp;
	struct smack_parsed_rule *rule;
	char *data;
	int datalen;
@@ -505,12 +506,10 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
			goto out_free_rule;
	}


	if (rule_list == NULL) {
		load = 1;
		skp = smk_find_entry(rule->smk_subject);
		rule_list = &skp->smk_rules;
		rule_lock = &skp->smk_rules_lock;
		rule_list = &rule->smk_subject->smk_rules;
		rule_lock = &rule->smk_subject->smk_rules_lock;
	}

	rc = smk_set_access(rule, rule_list, rule_lock, load);
@@ -579,13 +578,14 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
	 * because you should expect to be able to write
	 * anything you read back.
	 */
	if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max)
	if (strlen(srp->smk_subject->smk_known) >= max ||
	    strlen(srp->smk_object) >= max)
		return;

	if (srp->smk_access == 0)
		return;

	seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object);
	seq_printf(s, "%s %s", srp->smk_subject->smk_known, srp->smk_object);

	seq_putc(s, ' ');

@@ -738,9 +738,9 @@ static void smk_unlbl_ambient(char *oldambient)
			       __func__, __LINE__, rc);
	}
	if (smack_net_ambient == NULL)
		smack_net_ambient = smack_known_floor.smk_known;
		smack_net_ambient = &smack_known_floor;

	rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
	rc = netlbl_cfg_unlbl_map_add(smack_net_ambient->smk_known, PF_INET,
				      NULL, NULL, &nai);
	if (rc != 0)
		printk(KERN_WARNING "%s:%d add rc = %d\n",
@@ -881,7 +881,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
	if (format == SMK_FIXED24_FMT)
		rule += SMK_LABELLEN;
	else
		rule += strlen(skp->smk_known);
		rule += strlen(skp->smk_known) + 1;

	ret = sscanf(rule, "%d", &maplevel);
	if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
@@ -1535,11 +1535,12 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
	 */
	mutex_lock(&smack_ambient_lock);

	asize = strlen(smack_net_ambient) + 1;
	asize = strlen(smack_net_ambient->smk_known) + 1;

	if (cn >= asize)
		rc = simple_read_from_buffer(buf, cn, ppos,
					     smack_net_ambient, asize);
					     smack_net_ambient->smk_known,
					     asize);
	else
		rc = -EINVAL;

@@ -1560,8 +1561,8 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
				 size_t count, loff_t *ppos)
{
	struct smack_known *skp;
	char *oldambient;
	char *smack = NULL;
	char *data;
	int rc = count;

@@ -1577,16 +1578,16 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
		goto out;
	}

	smack = smk_import(data, count);
	if (smack == NULL) {
	skp = smk_import_entry(data, count);
	if (skp == NULL) {
		rc = -EINVAL;
		goto out;
	}

	mutex_lock(&smack_ambient_lock);

	oldambient = smack_net_ambient;
	smack_net_ambient = smack;
	oldambient = smack_net_ambient->smk_known;
	smack_net_ambient = skp;
	smk_unlbl_ambient(oldambient);

	mutex_unlock(&smack_ambient_lock);
@@ -1645,7 +1646,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
				 size_t count, loff_t *ppos)
{
	char *data;
	char *sp = smk_of_task(current->cred->security);
	struct smack_known *skp = smk_of_task(current->cred->security);
	int rc = count;

	if (!smack_privileged(CAP_MAC_ADMIN))
@@ -1656,7 +1657,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
	 * explicitly for clarity. The smk_access() implementation
	 * would use smk_access(smack_onlycap, MAY_WRITE)
	 */
	if (smack_onlycap != NULL && smack_onlycap != sp)
	if (smack_onlycap != NULL && smack_onlycap != skp->smk_known)
		return -EPERM;

	data = kzalloc(count, GFP_KERNEL);
@@ -1866,8 +1867,8 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
	if (res)
		return -EINVAL;

	res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access1,
			  NULL);
	res = smk_access(rule.smk_subject, rule.smk_object,
				rule.smk_access1, NULL);
	data[0] = res == 0 ? '1' : '0';
	data[1] = '\0';