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;
}

/**