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

Commit 44c3b591 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
  security: compile capabilities by default
  selinux: make selinux_set_mnt_opts() static
  SELinux: Add warning messages on network denial due to error
  SELinux: Add network ingress and egress control permission checks
  NetLabel: Add auditing to the static labeling mechanism
  NetLabel: Introduce static network labels for unlabeled connections
  SELinux: Allow NetLabel to directly cache SIDs
  SELinux: Enable dynamic enable/disable of the network access checks
  SELinux: Better integration between peer labeling subsystems
  SELinux: Add a new peer class and permissions to the Flask definitions
  SELinux: Add a capabilities bitmap to SELinux policy version 22
  SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions
  SELinux: Only store the network interface's ifindex
  SELinux: Convert the netif code to use ifindex values
  NetLabel: Add IP address family information to the netlbl_skbuff_getattr() function
  NetLabel: Add secid token support to the NetLabel secattr struct
  NetLabel: Consolidate the LSM domain mapping/hashing locks
  NetLabel: Cleanup the LSM domain hash functions
  NetLabel: Remove unneeded RCU read locks
parents 3b470ac4 f71ea9dd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@
#define AUDIT_MAC_IPSEC_ADDSPD	1413	/* Not used */
#define AUDIT_MAC_IPSEC_DELSPD	1414	/* Not used */
#define AUDIT_MAC_IPSEC_EVENT	1415	/* Audit an IPSec event */
#define AUDIT_MAC_UNLBL_STCADD	1416	/* NetLabel: add a static label */
#define AUDIT_MAC_UNLBL_STCDEL	1417	/* NetLabel: del a static label */

#define AUDIT_FIRST_KERN_ANOM_MSG   1700
#define AUDIT_LAST_KERN_ANOM_MSG    1799
+37 −8
Original line number Diff line number Diff line
@@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
int selinux_string_to_sid(char *str, u32 *sid);

/**
 *     selinux_relabel_packet_permission - check permission to relabel a packet
 *     @sid: ID value to be applied to network packet (via SECMARK, most likely)
 *     selinux_secmark_relabel_packet_permission - secmark permission check
 *     @sid: SECMARK ID value to be applied to network packet
 *
 *     Returns 0 if the current task is allowed to label packets with the
 *     supplied security ID.  Note that it is implicit that the packet is always
 *     being relabeled from the default unlabled value, and that the access
 *     control decision is made in the AVC.
 *     Returns 0 if the current task is allowed to set the SECMARK label of
 *     packets with the supplied security ID.  Note that it is implicit that
 *     the packet is always being relabeled from the default unlabeled value,
 *     and that the access control decision is made in the AVC.
 */
int selinux_relabel_packet_permission(u32 sid);
int selinux_secmark_relabel_packet_permission(u32 sid);

/**
 *     selinux_secmark_refcount_inc - increments the secmark use counter
 *
 *     SELinux keeps track of the current SECMARK targets in use so it knows
 *     when to apply SECMARK label access checks to network packets.  This
 *     function incements this reference count to indicate that a new SECMARK
 *     target has been configured.
 */
void selinux_secmark_refcount_inc(void);

/**
 *     selinux_secmark_refcount_dec - decrements the secmark use counter
 *
 *     SELinux keeps track of the current SECMARK targets in use so it knows
 *     when to apply SECMARK label access checks to network packets.  This
 *     function decements this reference count to indicate that one of the
 *     existing SECMARK targets has been removed/flushed.
 */
void selinux_secmark_refcount_dec(void);
#else

static inline int selinux_audit_rule_init(u32 field, u32 op,
@@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, u32 *sid)
       return 0;
}

static inline int selinux_relabel_packet_permission(u32 sid)
static inline int selinux_secmark_relabel_packet_permission(u32 sid)
{
	return 0;
}

static inline void selinux_secmark_refcount_inc(void)
{
	return;
}

static inline void selinux_secmark_refcount_dec(void)
{
	return;
}

#endif	/* CONFIG_SECURITY_SELINUX */

#endif /* _LINUX_SELINUX_H */
+80 −19
Original line number Diff line number Diff line
@@ -67,7 +67,11 @@
 * NetLabel NETLINK protocol
 */

#define NETLBL_PROTO_VERSION            1
/* NetLabel NETLINK protocol version
 *  1: initial version
 *  2: added static labels for unlabeled connections
 */
#define NETLBL_PROTO_VERSION            2

/* NetLabel NETLINK types/families */
#define NETLBL_NLTYPE_NONE              0
@@ -105,17 +109,49 @@ struct netlbl_dom_map;
/* Domain mapping operations */
int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);

/* LSM security attributes */
/*
 * LSM security attributes
 */

/**
 * struct netlbl_lsm_cache - NetLabel LSM security attribute cache
 * @refcount: atomic reference counter
 * @free: LSM supplied function to free the cache data
 * @data: LSM supplied cache data
 *
 * Description:
 * This structure is provided for LSMs which wish to make use of the NetLabel
 * caching mechanism to store LSM specific data/attributes in the NetLabel
 * cache.  If the LSM has to perform a lot of translation from the NetLabel
 * security attributes into it's own internal representation then the cache
 * mechanism can provide a way to eliminate some or all of that translation
 * overhead on a cache hit.
 *
 */
struct netlbl_lsm_cache {
	atomic_t refcount;
	void (*free) (const void *data);
	void *data;
};
/* The catmap bitmap field MUST be a power of two in length and large

/**
 * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap
 * @startbit: the value of the lowest order bit in the bitmap
 * @bitmap: the category bitmap
 * @next: pointer to the next bitmap "node" or NULL
 *
 * Description:
 * This structure is used to represent category bitmaps.  Due to the large
 * number of categories supported by most labeling protocols it is not
 * practical to transfer a full bitmap internally so NetLabel adopts a sparse
 * bitmap structure modeled after SELinux's ebitmap structure.
 * The catmap bitmap field MUST be a power of two in length and large
 * enough to hold at least 240 bits.  Special care (i.e. check the code!)
 * should be used when changing these values as the LSM implementation
 * probably has functions which rely on the sizes of these types to speed
 * processing. */
 * processing.
 *
 */
#define NETLBL_CATMAP_MAPTYPE           u64
#define NETLBL_CATMAP_MAPCNT            4
#define NETLBL_CATMAP_MAPSIZE           (sizeof(NETLBL_CATMAP_MAPTYPE) * 8)
@@ -127,22 +163,48 @@ struct netlbl_lsm_secattr_catmap {
	NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT];
	struct netlbl_lsm_secattr_catmap *next;
};

/**
 * struct netlbl_lsm_secattr - NetLabel LSM security attributes
 * @flags: indicate which attributes are contained in this structure
 * @type: indicate the NLTYPE of the attributes
 * @domain: the NetLabel LSM domain
 * @cache: NetLabel LSM specific cache
 * @attr.mls: MLS sensitivity label
 * @attr.mls.cat: MLS category bitmap
 * @attr.mls.lvl: MLS sensitivity level
 * @attr.secid: LSM specific secid token
 *
 * Description:
 * This structure is used to pass security attributes between NetLabel and the
 * LSM modules.  The flags field is used to specify which fields within the
 * struct are valid and valid values can be created by bitwise OR'ing the
 * NETLBL_SECATTR_* defines.  The domain field is typically set by the LSM to
 * specify domain specific configuration settings and is not usually used by
 * NetLabel itself when returning security attributes to the LSM.
 *
 */
#define NETLBL_SECATTR_NONE             0x00000000
#define NETLBL_SECATTR_DOMAIN           0x00000001
#define NETLBL_SECATTR_CACHE            0x00000002
#define NETLBL_SECATTR_MLS_LVL          0x00000004
#define NETLBL_SECATTR_MLS_CAT          0x00000008
#define NETLBL_SECATTR_SECID            0x00000010
#define NETLBL_SECATTR_CACHEABLE        (NETLBL_SECATTR_MLS_LVL | \
					 NETLBL_SECATTR_MLS_CAT)
					 NETLBL_SECATTR_MLS_CAT | \
					 NETLBL_SECATTR_SECID)
struct netlbl_lsm_secattr {
	u32 flags;

	u32 type;
	char *domain;

	u32 mls_lvl;
	struct netlbl_lsm_secattr_catmap *mls_cat;

	struct netlbl_lsm_cache *cache;
	union {
		struct {
			struct netlbl_lsm_secattr_catmap *cat;
			u32 lvl;
		} mls;
		u32 secid;
	} attr;
};

/*
@@ -231,10 +293,7 @@ static inline void netlbl_secattr_catmap_free(
 */
static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
{
	secattr->flags = 0;
	secattr->domain = NULL;
	secattr->mls_cat = NULL;
	secattr->cache = NULL;
	memset(secattr, 0, sizeof(*secattr));
}

/**
@@ -248,11 +307,11 @@ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
 */
static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
{
	if (secattr->cache)
		netlbl_secattr_cache_free(secattr->cache);
	kfree(secattr->domain);
	if (secattr->mls_cat)
		netlbl_secattr_catmap_free(secattr->mls_cat);
	if (secattr->flags & NETLBL_SECATTR_CACHE)
		netlbl_secattr_cache_free(secattr->cache);
	if (secattr->flags & NETLBL_SECATTR_MLS_CAT)
		netlbl_secattr_catmap_free(secattr->attr.mls.cat);
}

/**
@@ -300,7 +359,7 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
				 gfp_t flags);

/*
 * LSM protocol operations
 * LSM protocol operations (NetLabel LSM/kernel API)
 */
int netlbl_enabled(void);
int netlbl_sock_setattr(struct sock *sk,
@@ -308,6 +367,7 @@ int netlbl_sock_setattr(struct sock *sk,
int netlbl_sock_getattr(struct sock *sk,
			struct netlbl_lsm_secattr *secattr);
int netlbl_skbuff_getattr(const struct sk_buff *skb,
			  u16 family,
			  struct netlbl_lsm_secattr *secattr);
void netlbl_skbuff_err(struct sk_buff *skb, int error);

@@ -360,6 +420,7 @@ static inline int netlbl_sock_getattr(struct sock *sk,
	return -ENOSYS;
}
static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
					u16 family,
					struct netlbl_lsm_secattr *secattr)
{
	return -ENOSYS;
+37 −22
Original line number Diff line number Diff line
@@ -348,6 +348,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
			atomic_inc(&entry->lsm_data->refcount);
			secattr->cache = entry->lsm_data;
			secattr->flags |= NETLBL_SECATTR_CACHE;
			secattr->type = NETLBL_NLTYPE_CIPSOV4;
			if (prev_entry == NULL) {
				spin_unlock_bh(&cipso_v4_cache[bkt].lock);
				return 0;
@@ -865,7 +866,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
	}

	for (;;) {
		host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat,
		host_spot = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
						       host_spot + 1);
		if (host_spot < 0)
			break;
@@ -948,7 +949,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
				return -EPERM;
			break;
		}
		ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
		ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
						       host_spot,
						       GFP_ATOMIC);
		if (ret_val != 0)
@@ -1014,7 +1015,8 @@ static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def,
	u32 cat_iter = 0;

	for (;;) {
		cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1);
		cat = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
						 cat + 1);
		if (cat < 0)
			break;
		if ((cat_iter + 2) > net_cat_len)
@@ -1049,7 +1051,7 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
	u32 iter;

	for (iter = 0; iter < net_cat_len; iter += 2) {
		ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
		ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
				ntohs(get_unaligned((__be16 *)&net_cat[iter])),
				GFP_ATOMIC);
		if (ret_val != 0)
@@ -1130,7 +1132,8 @@ static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
		return -ENOSPC;

	for (;;) {
		iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1);
		iter = netlbl_secattr_catmap_walk(secattr->attr.mls.cat,
						  iter + 1);
		if (iter < 0)
			break;
		cat_size += (iter == 0 ? 0 : sizeof(u16));
@@ -1138,7 +1141,8 @@ static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
			return -ENOSPC;
		array[array_cnt++] = iter;

		iter = netlbl_secattr_catmap_walk_rng(secattr->mls_cat, iter);
		iter = netlbl_secattr_catmap_walk_rng(secattr->attr.mls.cat,
						      iter);
		if (iter < 0)
			return -EFAULT;
		cat_size += sizeof(u16);
@@ -1191,7 +1195,7 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
		else
			cat_low = 0;

		ret_val = netlbl_secattr_catmap_setrng(secattr->mls_cat,
		ret_val = netlbl_secattr_catmap_setrng(secattr->attr.mls.cat,
						       cat_low,
						       cat_high,
						       GFP_ATOMIC);
@@ -1251,7 +1255,9 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
	if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
		return -EPERM;

	ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
	ret_val = cipso_v4_map_lvl_hton(doi_def,
					secattr->attr.mls.lvl,
					&level);
	if (ret_val != 0)
		return ret_val;

@@ -1303,12 +1309,13 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
	ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
	if (ret_val != 0)
		return ret_val;
	secattr->mls_lvl = level;
	secattr->attr.mls.lvl = level;
	secattr->flags |= NETLBL_SECATTR_MLS_LVL;

	if (tag_len > 4) {
		secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
		if (secattr->mls_cat == NULL)
		secattr->attr.mls.cat =
		                       netlbl_secattr_catmap_alloc(GFP_ATOMIC);
		if (secattr->attr.mls.cat == NULL)
			return -ENOMEM;

		ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
@@ -1316,7 +1323,7 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
						    tag_len - 4,
						    secattr);
		if (ret_val != 0) {
			netlbl_secattr_catmap_free(secattr->mls_cat);
			netlbl_secattr_catmap_free(secattr->attr.mls.cat);
			return ret_val;
		}

@@ -1350,7 +1357,9 @@ static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
	if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
		return -EPERM;

	ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
	ret_val = cipso_v4_map_lvl_hton(doi_def,
					secattr->attr.mls.lvl,
					&level);
	if (ret_val != 0)
		return ret_val;

@@ -1396,12 +1405,13 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
	ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
	if (ret_val != 0)
		return ret_val;
	secattr->mls_lvl = level;
	secattr->attr.mls.lvl = level;
	secattr->flags |= NETLBL_SECATTR_MLS_LVL;

	if (tag_len > 4) {
		secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
		if (secattr->mls_cat == NULL)
		secattr->attr.mls.cat =
			               netlbl_secattr_catmap_alloc(GFP_ATOMIC);
		if (secattr->attr.mls.cat == NULL)
			return -ENOMEM;

		ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
@@ -1409,7 +1419,7 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
						     tag_len - 4,
						     secattr);
		if (ret_val != 0) {
			netlbl_secattr_catmap_free(secattr->mls_cat);
			netlbl_secattr_catmap_free(secattr->attr.mls.cat);
			return ret_val;
		}

@@ -1443,7 +1453,9 @@ static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
	if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
		return -EPERM;

	ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
	ret_val = cipso_v4_map_lvl_hton(doi_def,
					secattr->attr.mls.lvl,
					&level);
	if (ret_val != 0)
		return ret_val;

@@ -1488,12 +1500,13 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
	ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
	if (ret_val != 0)
		return ret_val;
	secattr->mls_lvl = level;
	secattr->attr.mls.lvl = level;
	secattr->flags |= NETLBL_SECATTR_MLS_LVL;

	if (tag_len > 4) {
		secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
		if (secattr->mls_cat == NULL)
		secattr->attr.mls.cat =
			               netlbl_secattr_catmap_alloc(GFP_ATOMIC);
		if (secattr->attr.mls.cat == NULL)
			return -ENOMEM;

		ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
@@ -1501,7 +1514,7 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
						    tag_len - 4,
						    secattr);
		if (ret_val != 0) {
			netlbl_secattr_catmap_free(secattr->mls_cat);
			netlbl_secattr_catmap_free(secattr->attr.mls.cat);
			return ret_val;
		}

@@ -1850,6 +1863,8 @@ static int cipso_v4_getattr(const unsigned char *cipso,
		ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr);
		break;
	}
	if (ret_val == 0)
		secattr->type = NETLBL_NLTYPE_CIPSOV4;

getattr_return:
	rcu_read_unlock();
+12 −1
Original line number Diff line number Diff line
@@ -72,12 +72,13 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
		return false;
	}

	err = selinux_relabel_packet_permission(sel->selsid);
	err = selinux_secmark_relabel_packet_permission(sel->selsid);
	if (err) {
		printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
		return false;
	}

	selinux_secmark_refcount_inc();
	return true;
}

@@ -110,11 +111,20 @@ secmark_tg_check(const char *tablename, const void *entry,
	return true;
}

void secmark_tg_destroy(const struct xt_target *target, void *targinfo)
{
	switch (mode) {
	case SECMARK_MODE_SEL:
		selinux_secmark_refcount_dec();
	}
}

static struct xt_target secmark_tg_reg[] __read_mostly = {
	{
		.name		= "SECMARK",
		.family		= AF_INET,
		.checkentry	= secmark_tg_check,
		.destroy	= secmark_tg_destroy,
		.target		= secmark_tg,
		.targetsize	= sizeof(struct xt_secmark_target_info),
		.table		= "mangle",
@@ -124,6 +134,7 @@ static struct xt_target secmark_tg_reg[] __read_mostly = {
		.name		= "SECMARK",
		.family		= AF_INET6,
		.checkentry	= secmark_tg_check,
		.destroy	= secmark_tg_destroy,
		.target		= secmark_tg,
		.targetsize	= sizeof(struct xt_secmark_target_info),
		.table		= "mangle",
Loading