Merge to v3.13-rc7 for prerequisite changes in the Xen code for TPM

This commit is contained in:
James Morris
2014-01-06 22:23:01 +11:00
9978 changed files with 406090 additions and 204482 deletions

View File

@@ -580,15 +580,13 @@ static struct aa_namespace *__next_namespace(struct aa_namespace *root,
/* check if the next ns is a sibling, parent, gp, .. */
parent = ns->parent;
while (parent) {
while (ns != root) {
mutex_unlock(&ns->lock);
next = list_entry_next(ns, base.list);
if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
mutex_lock(&next->lock);
return next;
}
if (parent == root)
return NULL;
ns = parent;
parent = parent->parent;
}

View File

@@ -15,14 +15,14 @@
* it should be.
*/
#include <linux/crypto.h>
#include <crypto/hash.h>
#include "include/apparmor.h"
#include "include/crypto.h"
static unsigned int apparmor_hash_size;
static struct crypto_hash *apparmor_tfm;
static struct crypto_shash *apparmor_tfm;
unsigned int aa_hash_size(void)
{
@@ -32,35 +32,33 @@ unsigned int aa_hash_size(void)
int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
size_t len)
{
struct scatterlist sg[2];
struct hash_desc desc = {
.tfm = apparmor_tfm,
.flags = 0
};
struct {
struct shash_desc shash;
char ctx[crypto_shash_descsize(apparmor_tfm)];
} desc;
int error = -ENOMEM;
u32 le32_version = cpu_to_le32(version);
if (!apparmor_tfm)
return 0;
sg_init_table(sg, 2);
sg_set_buf(&sg[0], &le32_version, 4);
sg_set_buf(&sg[1], (u8 *) start, len);
profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL);
if (!profile->hash)
goto fail;
error = crypto_hash_init(&desc);
desc.shash.tfm = apparmor_tfm;
desc.shash.flags = 0;
error = crypto_shash_init(&desc.shash);
if (error)
goto fail;
error = crypto_hash_update(&desc, &sg[0], 4);
error = crypto_shash_update(&desc.shash, (u8 *) &le32_version, 4);
if (error)
goto fail;
error = crypto_hash_update(&desc, &sg[1], len);
error = crypto_shash_update(&desc.shash, (u8 *) start, len);
if (error)
goto fail;
error = crypto_hash_final(&desc, profile->hash);
error = crypto_shash_final(&desc.shash, profile->hash);
if (error)
goto fail;
@@ -75,19 +73,19 @@ int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
static int __init init_profile_hash(void)
{
struct crypto_hash *tfm;
struct crypto_shash *tfm;
if (!apparmor_initialized)
return 0;
tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
tfm = crypto_alloc_shash("sha1", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
int error = PTR_ERR(tfm);
AA_ERROR("failed to setup profile sha1 hashing: %d\n", error);
return error;
}
apparmor_tfm = tfm;
apparmor_hash_size = crypto_hash_digestsize(apparmor_tfm);
apparmor_hash_size = crypto_shash_digestsize(apparmor_tfm);
aa_info_message("AppArmor sha1 policy hashing enabled");

View File

@@ -360,7 +360,9 @@ static inline void aa_put_replacedby(struct aa_replacedby *p)
static inline void __aa_update_replacedby(struct aa_profile *orig,
struct aa_profile *new)
{
struct aa_profile *tmp = rcu_dereference(orig->replacedby->profile);
struct aa_profile *tmp;
tmp = rcu_dereference_protected(orig->replacedby->profile,
mutex_is_locked(&orig->ns->lock));
rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new));
orig->flags |= PFLAG_INVALID;
aa_put_profile(tmp);

View File

@@ -563,7 +563,8 @@ void __init aa_free_root_ns(void)
static void free_replacedby(struct aa_replacedby *r)
{
if (r) {
aa_put_profile(rcu_dereference(r->profile));
/* r->profile will not be updated any more as r is dead */
aa_put_profile(rcu_dereference_protected(r->profile, true));
kzfree(r);
}
}
@@ -609,6 +610,7 @@ void aa_free_profile(struct aa_profile *profile)
aa_put_dfa(profile->policy.dfa);
aa_put_replacedby(profile->replacedby);
kzfree(profile->hash);
kzfree(profile);
}

View File

@@ -63,16 +63,6 @@ static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
struct cgroup_subsys devices_subsys;
static int devcgroup_can_attach(struct cgroup_subsys_state *new_css,
struct cgroup_taskset *set)
{
struct task_struct *task = cgroup_taskset_first(set);
if (current != task && !capable(CAP_SYS_ADMIN))
return -EPERM;
return 0;
}
/*
* called under devcgroup_mutex
*/
@@ -697,7 +687,6 @@ static struct cftype dev_cgroup_files[] = {
struct cgroup_subsys devices_subsys = {
.name = "devices",
.can_attach = devcgroup_can_attach,
.css_alloc = devcgroup_css_alloc,
.css_free = devcgroup_css_free,
.css_online = devcgroup_online,

View File

@@ -13,9 +13,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/rbtree.h>
#include <linux/cred.h>
#include <linux/key-type.h>
#include <linux/digsig.h>
@@ -23,19 +21,11 @@
static struct key *keyring[INTEGRITY_KEYRING_MAX];
#ifdef CONFIG_IMA_TRUSTED_KEYRING
static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
".evm",
".module",
".ima",
};
#else
static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
"_evm",
"_module",
"_ima",
};
#endif
int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
const char *digest, int digestlen)
@@ -45,7 +35,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
if (!keyring[id]) {
keyring[id] =
request_key(&key_type_keyring, keyring_name[id], NULL);
request_key(&key_type_keyring, keyring_name[id], NULL);
if (IS_ERR(keyring[id])) {
int err = PTR_ERR(keyring[id]);
pr_err("no %s keyring: %d\n", keyring_name[id], err);
@@ -66,21 +56,3 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
return -EOPNOTSUPP;
}
int integrity_init_keyring(const unsigned int id)
{
const struct cred *cred = current_cred();
const struct user_struct *user = cred->user;
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
KGIDT_INIT(0), cred,
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ),
KEY_ALLOC_NOT_IN_QUOTA, user->uid_keyring);
if (!IS_ERR(keyring[id]))
set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags);
else
pr_info("Can't allocate %s keyring (%ld)\n",
keyring_name[id], PTR_ERR(keyring[id]));
return 0;
}

View File

@@ -123,11 +123,3 @@ config IMA_APPRAISE
For more information on integrity appraisal refer to:
<http://linux-ima.sourceforge.net>
If unsure, say N.
config IMA_TRUSTED_KEYRING
bool "Require all keys on the _ima keyring be signed"
depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
default y
help
This option requires that all keys added to the _ima
keyring be signed by a key on the system trusted keyring.

View File

@@ -26,7 +26,8 @@
#include "../integrity.h"
enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII };
enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
IMA_SHOW_ASCII };
enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
/* digest size for IMA, fits SHA1 or MD5 */
@@ -97,7 +98,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
const char *op, struct inode *inode,
const unsigned char *filename);
int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
int ima_calc_field_array_hash(struct ima_field_data *field_data,
struct ima_template_desc *desc, int num_fields,
struct ima_digest_data *hash);
int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
void ima_add_violation(struct file *file, const unsigned char *filename,
@@ -146,6 +148,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
int xattr_len, struct ima_template_entry **entry);
int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode, const unsigned char *filename);
void ima_free_template_entry(struct ima_template_entry *entry);
const char *ima_d_path(struct path *path, char **pathbuf);
/* rbtree tree calls to lookup, insert, delete

View File

@@ -21,6 +21,19 @@
#include <crypto/hash_info.h>
#include "ima.h"
/*
* ima_free_template_entry - free an existing template entry
*/
void ima_free_template_entry(struct ima_template_entry *entry)
{
int i;
for (i = 0; i < entry->template_desc->num_fields; i++)
kfree(entry->template_data[i].data);
kfree(entry);
}
/*
* ima_alloc_init_template - create and initialize a new template entry
*/
@@ -37,6 +50,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
if (!*entry)
return -ENOMEM;
(*entry)->template_desc = template_desc;
for (i = 0; i < template_desc->num_fields; i++) {
struct ima_template_field *field = template_desc->fields[i];
u32 len;
@@ -51,10 +65,9 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
(*entry)->template_data_len += sizeof(len);
(*entry)->template_data_len += len;
}
(*entry)->template_desc = template_desc;
return 0;
out:
kfree(*entry);
ima_free_template_entry(*entry);
*entry = NULL;
return result;
}
@@ -94,6 +107,7 @@ int ima_store_template(struct ima_template_entry *entry,
/* this function uses default algo */
hash.hdr.algo = HASH_ALGO_SHA1;
result = ima_calc_field_array_hash(&entry->template_data[0],
entry->template_desc,
num_fields, &hash.hdr);
if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
@@ -133,7 +147,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
}
result = ima_store_template(entry, violation, inode, filename);
if (result < 0)
kfree(entry);
ima_free_template_entry(entry);
err_out:
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
op, cause, result, 0);
@@ -268,7 +282,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
if (!result || result == -EEXIST)
iint->flags |= IMA_MEASURED;
if (result < 0)
kfree(entry);
ima_free_template_entry(entry);
}
void ima_audit_measurement(struct integrity_iint_cache *iint,

View File

@@ -381,14 +381,3 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
}
return result;
}
#ifdef CONFIG_IMA_TRUSTED_KEYRING
static int __init init_ima_keyring(void)
{
int ret;
ret = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
return 0;
}
late_initcall(init_ima_keyring);
#endif

View File

@@ -140,6 +140,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
* Calculate the hash of template data
*/
static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
struct ima_template_desc *td,
int num_fields,
struct ima_digest_data *hash,
struct crypto_shash *tfm)
@@ -160,9 +161,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
return rc;
for (i = 0; i < num_fields; i++) {
rc = crypto_shash_update(&desc.shash,
(const u8 *) &field_data[i].len,
sizeof(field_data[i].len));
if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
rc = crypto_shash_update(&desc.shash,
(const u8 *) &field_data[i].len,
sizeof(field_data[i].len));
if (rc)
break;
}
rc = crypto_shash_update(&desc.shash, field_data[i].data,
field_data[i].len);
if (rc)
@@ -175,7 +180,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
return rc;
}
int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
int ima_calc_field_array_hash(struct ima_field_data *field_data,
struct ima_template_desc *desc, int num_fields,
struct ima_digest_data *hash)
{
struct crypto_shash *tfm;
@@ -185,7 +191,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
if (IS_ERR(tfm))
return PTR_ERR(tfm);
rc = ima_calc_field_array_hash_tfm(field_data, num_fields, hash, tfm);
rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields,
hash, tfm);
ima_free_tfm(tfm);

View File

@@ -120,6 +120,7 @@ static int ima_measurements_show(struct seq_file *m, void *v)
struct ima_template_entry *e;
int namelen;
u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
bool is_ima_template = false;
int i;
/* get entry */
@@ -145,14 +146,21 @@ static int ima_measurements_show(struct seq_file *m, void *v)
ima_putc(m, e->template_desc->name, namelen);
/* 5th: template length (except for 'ima' template) */
if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0)
is_ima_template = true;
if (!is_ima_template)
ima_putc(m, &e->template_data_len,
sizeof(e->template_data_len));
/* 6th: template specific data */
for (i = 0; i < e->template_desc->num_fields; i++) {
e->template_desc->fields[i]->field_show(m, IMA_SHOW_BINARY,
&e->template_data[i]);
enum ima_show_type show = IMA_SHOW_BINARY;
struct ima_template_field *field = e->template_desc->fields[i];
if (is_ima_template && strcmp(field->field_id, "d") == 0)
show = IMA_SHOW_BINARY_NO_FIELD_LEN;
field->field_show(m, show, &e->template_data[i]);
}
return 0;
}

View File

@@ -63,7 +63,6 @@ static void __init ima_add_boot_aggregate(void)
result = ima_calc_boot_aggregate(&hash.hdr);
if (result < 0) {
audit_cause = "hashing_error";
kfree(entry);
goto err_out;
}
}
@@ -76,7 +75,7 @@ static void __init ima_add_boot_aggregate(void)
result = ima_store_template(entry, violation, NULL,
boot_aggregate_name);
if (result < 0)
kfree(entry);
ima_free_template_entry(entry);
return;
err_out:
integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,

View File

@@ -90,7 +90,7 @@ static struct ima_template_field *lookup_template_field(const char *field_id)
return NULL;
}
static int template_fmt_size(char *template_fmt)
static int template_fmt_size(const char *template_fmt)
{
char c;
int template_fmt_len = strlen(template_fmt);
@@ -106,22 +106,29 @@ static int template_fmt_size(char *template_fmt)
return j + 1;
}
static int template_desc_init_fields(char *template_fmt,
static int template_desc_init_fields(const char *template_fmt,
struct ima_template_field ***fields,
int *num_fields)
{
char *c, *template_fmt_ptr = template_fmt;
char *c, *template_fmt_copy, *template_fmt_ptr;
int template_num_fields = template_fmt_size(template_fmt);
int i, result = 0;
if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX)
return -EINVAL;
/* copying is needed as strsep() modifies the original buffer */
template_fmt_copy = kstrdup(template_fmt, GFP_KERNEL);
if (template_fmt_copy == NULL)
return -ENOMEM;
*fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL);
if (*fields == NULL) {
result = -ENOMEM;
goto out;
}
template_fmt_ptr = template_fmt_copy;
for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL &&
i < template_num_fields; i++) {
struct ima_template_field *f = lookup_template_field(c);
@@ -133,10 +140,12 @@ static int template_desc_init_fields(char *template_fmt,
(*fields)[i] = f;
}
*num_fields = i;
return 0;
out:
kfree(*fields);
*fields = NULL;
if (result < 0) {
kfree(*fields);
*fields = NULL;
}
kfree(template_fmt_copy);
return result;
}

View File

@@ -109,9 +109,12 @@ static void ima_show_template_data_binary(struct seq_file *m,
enum data_formats datafmt,
struct ima_field_data *field_data)
{
ima_putc(m, &field_data->len, sizeof(u32));
if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
ima_putc(m, &field_data->len, sizeof(u32));
if (!field_data->len)
return;
ima_putc(m, field_data->data, field_data->len);
}
@@ -125,6 +128,7 @@ static void ima_show_template_field_data(struct seq_file *m,
ima_show_template_data_ascii(m, show, datafmt, field_data);
break;
case IMA_SHOW_BINARY:
case IMA_SHOW_BINARY_NO_FIELD_LEN:
ima_show_template_data_binary(m, show, datafmt, field_data);
break;
default:

View File

@@ -137,19 +137,12 @@ static inline int integrity_digsig_verify(const unsigned int id,
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
int asymmetric_verify(struct key *keyring, const char *sig,
int siglen, const char *data, int datalen);
int integrity_init_keyring(const unsigned int id);
#else
static inline int asymmetric_verify(struct key *keyring, const char *sig,
int siglen, const char *data, int datalen)
{
return -EOPNOTSUPP;
}
static int integrity_init_keyring(const unsigned int id)
{
return 0;
}
#endif
#ifdef CONFIG_INTEGRITY_AUDIT

View File

@@ -70,7 +70,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
*
* TODO: Encrypt the stored data with a temporary key.
*/
file = shmem_file_setup("", datalen, 0);
file = shmem_kernel_file_setup("", datalen, 0);
if (IS_ERR(file)) {
ret = PTR_ERR(file);
goto err_quota;
@@ -78,6 +78,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
written = kernel_write(file, prep->data, prep->datalen, 0);
if (written != datalen) {
ret = written;
if (written >= 0)
ret = -ENOMEM;
goto err_fput;

View File

@@ -130,46 +130,6 @@ void key_gc_keytype(struct key_type *ktype)
kleave("");
}
static int key_gc_keyring_func(const void *object, void *iterator_data)
{
const struct key *key = object;
time_t *limit = iterator_data;
return key_is_dead(key, *limit);
}
/*
* Garbage collect pointers from a keyring.
*
* Not called with any locks held. The keyring's key struct will not be
* deallocated under us as only our caller may deallocate it.
*/
static void key_gc_keyring(struct key *keyring, time_t limit)
{
int result;
kenter("%x{%s}", keyring->serial, keyring->description ?: "");
if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED)))
goto dont_gc;
/* scan the keyring looking for dead keys */
rcu_read_lock();
result = assoc_array_iterate(&keyring->keys,
key_gc_keyring_func, &limit);
rcu_read_unlock();
if (result == true)
goto do_gc;
dont_gc:
kleave(" [no gc]");
return;
do_gc:
keyring_gc(keyring, limit);
kleave(" [gc]");
}
/*
* Garbage collect a list of unreferenced, detached keys
*/
@@ -388,7 +348,7 @@ static void key_garbage_collector(struct work_struct *work)
*/
found_keyring:
spin_unlock(&key_serial_lock);
key_gc_keyring(key, limit);
keyring_gc(key, limit);
goto maybe_resched;
/* We found a dead key that is still referenced. Reset its type and

View File

@@ -272,7 +272,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
}
/* allocate and initialise the key and its description */
key = kmem_cache_alloc(key_jar, GFP_KERNEL);
key = kmem_cache_zalloc(key_jar, GFP_KERNEL);
if (!key)
goto no_memory_2;
@@ -293,18 +293,12 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->uid = uid;
key->gid = gid;
key->perm = perm;
key->flags = 0;
key->expiry = 0;
key->payload.data = NULL;
key->security = NULL;
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
if (flags & KEY_ALLOC_TRUSTED)
key->flags |= 1 << KEY_FLAG_TRUSTED;
memset(&key->type_data, 0, sizeof(key->type_data));
#ifdef KEY_DEBUGGING
key->magic = KEY_DEBUG_MAGIC;
#endif

View File

@@ -160,7 +160,7 @@ static u64 mult_64x32_and_fold(u64 x, u32 y)
static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key)
{
const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP;
const unsigned long level_mask = ASSOC_ARRAY_LEVEL_STEP_MASK;
const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK;
const char *description = index_key->description;
unsigned long hash, type;
u32 piece;
@@ -194,10 +194,10 @@ static unsigned long hash_key_type_and_desc(const struct keyring_index_key *inde
* ordinary keys by making sure the lowest level segment in the hash is
* zero for keyrings and non-zero otherwise.
*/
if (index_key->type != &key_type_keyring && (hash & level_mask) == 0)
if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0)
return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1;
if (index_key->type == &key_type_keyring && (hash & level_mask) != 0)
return (hash + (hash << level_shift)) & ~level_mask;
if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0)
return (hash + (hash << level_shift)) & ~fan_mask;
return hash;
}
@@ -279,12 +279,11 @@ static bool keyring_compare_object(const void *object, const void *data)
* Compare the index keys of a pair of objects and determine the bit position
* at which they differ - if they differ.
*/
static int keyring_diff_objects(const void *_a, const void *_b)
static int keyring_diff_objects(const void *object, const void *data)
{
const struct key *key_a = keyring_ptr_to_key(_a);
const struct key *key_b = keyring_ptr_to_key(_b);
const struct key *key_a = keyring_ptr_to_key(object);
const struct keyring_index_key *a = &key_a->index_key;
const struct keyring_index_key *b = &key_b->index_key;
const struct keyring_index_key *b = data;
unsigned long seg_a, seg_b;
int level, i;
@@ -691,8 +690,8 @@ static bool search_nested_keyrings(struct key *keyring,
smp_read_barrier_depends();
ptr = ACCESS_ONCE(shortcut->next_node);
BUG_ON(!assoc_array_ptr_is_node(ptr));
node = assoc_array_ptr_to_node(ptr);
}
node = assoc_array_ptr_to_node(ptr);
begin_node:
kdebug("begin_node");
@@ -1304,7 +1303,7 @@ static void keyring_revoke(struct key *keyring)
}
}
static bool gc_iterator(void *object, void *iterator_data)
static bool keyring_gc_select_iterator(void *object, void *iterator_data)
{
struct key *key = keyring_ptr_to_key(object);
time_t *limit = iterator_data;
@@ -1315,22 +1314,47 @@ static bool gc_iterator(void *object, void *iterator_data)
return true;
}
static int keyring_gc_check_iterator(const void *object, void *iterator_data)
{
const struct key *key = keyring_ptr_to_key(object);
time_t *limit = iterator_data;
key_check(key);
return key_is_dead(key, *limit);
}
/*
* Collect garbage from the contents of a keyring, replacing the old list with
* a new one with the pointers all shuffled down.
* Garbage collect pointers from a keyring.
*
* Dead keys are classed as oned that are flagged as being dead or are revoked,
* expired or negative keys that were revoked or expired before the specified
* limit.
* Not called with any locks held. The keyring's key struct will not be
* deallocated under us as only our caller may deallocate it.
*/
void keyring_gc(struct key *keyring, time_t limit)
{
kenter("{%x,%s}", key_serial(keyring), keyring->description);
int result;
kenter("%x{%s}", keyring->serial, keyring->description ?: "");
if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED)))
goto dont_gc;
/* scan the keyring looking for dead keys */
rcu_read_lock();
result = assoc_array_iterate(&keyring->keys,
keyring_gc_check_iterator, &limit);
rcu_read_unlock();
if (result == true)
goto do_gc;
dont_gc:
kleave(" [no gc]");
return;
do_gc:
down_write(&keyring->sem);
assoc_array_gc(&keyring->keys, &keyring_assoc_array_ops,
gc_iterator, &limit);
keyring_gc_select_iterator, &limit);
up_write(&keyring->sem);
kleave("");
kleave(" [gc]");
}

View File

@@ -144,10 +144,8 @@ long keyctl_get_persistent(uid_t _uid, key_serial_t destid)
/* You can only see your own persistent cache if you're not
* sufficiently privileged.
*/
if (uid_eq(uid, current_uid()) &&
uid_eq(uid, current_suid()) &&
uid_eq(uid, current_euid()) &&
uid_eq(uid, current_fsuid()) &&
if (!uid_eq(uid, current_uid()) &&
!uid_eq(uid, current_euid()) &&
!ns_capable(ns, CAP_SETUID))
return -EPERM;
}

View File

@@ -302,18 +302,19 @@ static void dump_common_audit_data(struct audit_buffer *ab,
"faddr", "fport");
break;
}
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6: {
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *inet6 = inet6_sk(sk);
print_ipv6_addr(ab, &inet6->rcv_saddr,
print_ipv6_addr(ab, &sk->sk_v6_rcv_saddr,
inet->inet_sport,
"laddr", "lport");
print_ipv6_addr(ab, &inet6->daddr,
print_ipv6_addr(ab, &sk->sk_v6_daddr,
inet->inet_dport,
"faddr", "fport");
break;
}
#endif
case AF_UNIX:
u = unix_sk(sk);
if (u->path.dentry) {
@@ -396,7 +397,8 @@ void common_lsm_audit(struct common_audit_data *a,
if (a == NULL)
return;
/* we use GFP_ATOMIC so we won't sleep */
ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
ab = audit_log_start(current->audit_context, GFP_ATOMIC | __GFP_NOWARN,
AUDIT_AVC);
if (ab == NULL)
return;

View File

@@ -746,7 +746,6 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
* @tclass: target security class
* @requested: requested permissions, interpreted based on @tclass
* @auditdata: auxiliary audit data
* @flags: VFS walk flags
*
* Check the AVC to determine whether the @requested permissions are granted
* for the SID pair (@ssid, @tsid), interpreting the permissions
@@ -756,17 +755,15 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
* permissions are granted, -%EACCES if any permissions are denied, or
* another -errno upon other errors.
*/
int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct common_audit_data *auditdata,
unsigned flags)
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct common_audit_data *auditdata)
{
struct av_decision avd;
int rc, rc2;
rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata,
flags);
rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
if (rc2)
return rc2;
return rc;

View File

@@ -53,6 +53,7 @@
#include <net/ip.h> /* for local_port_range[] */
#include <net/sock.h>
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
#include <net/inet_connection_sock.h>
#include <net/net_namespace.h>
#include <net/netlabel.h>
#include <linux/uaccess.h>
@@ -95,10 +96,6 @@
#include "audit.h"
#include "avc_ss.h"
#define SB_TYPE_FMT "%s%s%s"
#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
extern struct security_operations *security_ops;
/* SECMARK reference count */
@@ -413,8 +410,8 @@ static int sb_finish_set_opts(struct super_block *sb)
the first boot of the SELinux kernel before we have
assigned xattr values to the filesystem. */
if (!root_inode->i_op->getxattr) {
printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
"xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
"xattr support\n", sb->s_id, sb->s_type->name);
rc = -EOPNOTSUPP;
goto out;
}
@@ -422,22 +419,22 @@ static int sb_finish_set_opts(struct super_block *sb)
if (rc < 0 && rc != -ENODATA) {
if (rc == -EOPNOTSUPP)
printk(KERN_WARNING "SELinux: (dev %s, type "
SB_TYPE_FMT") has no security xattr handler\n",
sb->s_id, SB_TYPE_ARGS(sb));
"%s) has no security xattr handler\n",
sb->s_id, sb->s_type->name);
else
printk(KERN_WARNING "SELinux: (dev %s, type "
SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
SB_TYPE_ARGS(sb), -rc);
"%s) getxattr errno %d\n", sb->s_id,
sb->s_type->name, -rc);
goto out;
}
}
if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
sb->s_id, SB_TYPE_ARGS(sb));
printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
sb->s_id, sb->s_type->name);
else
printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
sb->s_id, SB_TYPE_ARGS(sb),
printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
sb->s_id, sb->s_type->name,
labeling_behaviors[sbsec->behavior-1]);
sbsec->flags |= SE_SBINITIALIZED;
@@ -600,6 +597,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
const struct cred *cred = current_cred();
int rc = 0, i;
struct superblock_security_struct *sbsec = sb->s_security;
const char *name = sb->s_type->name;
struct inode *inode = sbsec->sb->s_root->d_inode;
struct inode_security_struct *root_isec = inode->i_security;
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
@@ -658,8 +656,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
strlen(mount_options[i]), &sid);
if (rc) {
printk(KERN_WARNING "SELinux: security_context_to_sid"
"(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
"(%s) failed for (dev %s, type %s) errno=%d\n",
mount_options[i], sb->s_id, name, rc);
goto out;
}
switch (flags[i]) {
@@ -806,8 +804,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
out_double_mount:
rc = -EINVAL;
printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
"security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
SB_TYPE_ARGS(sb));
"security settings for (dev %s, type %s)\n", sb->s_id, name);
goto out;
}
@@ -1539,7 +1536,7 @@ static int cred_has_capability(const struct cred *cred,
rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
if (audit == SECURITY_CAP_AUDIT) {
int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
if (rc2)
return rc2;
}
@@ -1562,8 +1559,7 @@ static int task_has_system(struct task_struct *tsk,
static int inode_has_perm(const struct cred *cred,
struct inode *inode,
u32 perms,
struct common_audit_data *adp,
unsigned flags)
struct common_audit_data *adp)
{
struct inode_security_struct *isec;
u32 sid;
@@ -1576,7 +1572,7 @@ static int inode_has_perm(const struct cred *cred,
sid = cred_sid(cred);
isec = inode->i_security;
return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
}
/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1591,7 +1587,7 @@ static inline int dentry_has_perm(const struct cred *cred,
ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
return inode_has_perm(cred, inode, av, &ad, 0);
return inode_has_perm(cred, inode, av, &ad);
}
/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1606,7 +1602,7 @@ static inline int path_has_perm(const struct cred *cred,
ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = *path;
return inode_has_perm(cred, inode, av, &ad, 0);
return inode_has_perm(cred, inode, av, &ad);
}
/* Same as path_has_perm, but uses the inode from the file struct. */
@@ -1618,7 +1614,7 @@ static inline int file_path_has_perm(const struct cred *cred,
ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = file->f_path;
return inode_has_perm(cred, file_inode(file), av, &ad, 0);
return inode_has_perm(cred, file_inode(file), av, &ad);
}
/* Check whether a task can use an open file descriptor to
@@ -1654,7 +1650,7 @@ static int file_has_perm(const struct cred *cred,
/* av is zero if only checking access to the descriptor. */
rc = 0;
if (av)
rc = inode_has_perm(cred, inode, av, &ad, 0);
rc = inode_has_perm(cred, inode, av, &ad);
out:
return rc;
@@ -2481,8 +2477,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
rc = security_context_to_sid(mount_options[i], len, &sid);
if (rc) {
printk(KERN_WARNING "SELinux: security_context_to_sid"
"(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
"(%s) failed for (dev %s, type %s) errno=%d\n",
mount_options[i], sb->s_id, sb->s_type->name, rc);
goto out_free_opts;
}
rc = -EINVAL;
@@ -2520,8 +2516,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
return rc;
out_bad_option:
printk(KERN_WARNING "SELinux: unable to change security options "
"during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
SB_TYPE_ARGS(sb));
"during remount (dev %s, type=%s)\n", sb->s_id,
sb->s_type->name);
goto out_free_opts;
}
@@ -3829,7 +3825,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
u32 nlbl_sid;
u32 nlbl_type;
err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
if (unlikely(err))
return -EACCES;
err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
@@ -3847,6 +3843,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
return 0;
}
/**
* selinux_conn_sid - Determine the child socket label for a connection
* @sk_sid: the parent socket's SID
* @skb_sid: the packet's SID
* @conn_sid: the resulting connection SID
*
* If @skb_sid is valid then the user:role:type information from @sk_sid is
* combined with the MLS information from @skb_sid in order to create
* @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
* of @sk_sid. Returns zero on success, negative values on failure.
*
*/
static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
{
int err = 0;
if (skb_sid != SECSID_NULL)
err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
else
*conn_sid = sk_sid;
return err;
}
/* socket security operations */
static int socket_sockcreate_sid(const struct task_security_struct *tsec,
@@ -3970,7 +3990,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (snum) {
int low, high;
inet_get_local_port_range(&low, &high);
inet_get_local_port_range(sock_net(sk), &low, &high);
if (snum < max(PROT_SOCK, low) || snum > high) {
err = sel_netport_sid(sk->sk_protocol,
@@ -4314,8 +4334,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
}
err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
PEER__RECV, &ad);
if (err)
if (err) {
selinux_netlbl_err(skb, err, 0);
return err;
}
}
if (secmark_active) {
@@ -4453,7 +4475,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct sk_security_struct *sksec = sk->sk_security;
int err;
u16 family = sk->sk_family;
u32 newsid;
u32 connsid;
u32 peersid;
/* handle mapped IPv4 packets arriving via IPv6 sockets */
@@ -4463,16 +4485,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
err = selinux_skb_peerlbl_sid(skb, family, &peersid);
if (err)
return err;
if (peersid == SECSID_NULL) {
req->secid = sksec->sid;
req->peer_secid = SECSID_NULL;
} else {
err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
if (err)
return err;
req->secid = newsid;
req->peer_secid = peersid;
}
err = selinux_conn_sid(sksec->sid, peersid, &connsid);
if (err)
return err;
req->secid = connsid;
req->peer_secid = peersid;
return selinux_netlbl_inet_conn_request(req, family);
}
@@ -4709,7 +4726,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
return NF_ACCEPT;
}
static unsigned int selinux_ipv4_forward(unsigned int hooknum,
static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -4719,7 +4736,7 @@ static unsigned int selinux_ipv4_forward(unsigned int hooknum,
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static unsigned int selinux_ipv6_forward(unsigned int hooknum,
static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -4732,6 +4749,7 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
static unsigned int selinux_ip_output(struct sk_buff *skb,
u16 family)
{
struct sock *sk;
u32 sid;
if (!netlbl_enabled())
@@ -4740,8 +4758,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
* because we want to make sure we apply the necessary labeling
* before IPsec is applied so we can leverage AH protection */
if (skb->sk) {
struct sk_security_struct *sksec = skb->sk->sk_security;
sk = skb->sk;
if (sk) {
struct sk_security_struct *sksec;
if (sk->sk_state == TCP_LISTEN)
/* if the socket is the listening state then this
* packet is a SYN-ACK packet which means it needs to
* be labeled based on the connection/request_sock and
* not the parent socket. unfortunately, we can't
* lookup the request_sock yet as it isn't queued on
* the parent socket until after the SYN-ACK is sent.
* the "solution" is to simply pass the packet as-is
* as any IP option based labeling should be copied
* from the initial connection request (in the IP
* layer). it is far from ideal, but until we get a
* security label in the packet itself this is the
* best we can do. */
return NF_ACCEPT;
/* standard practice, label using the parent socket */
sksec = sk->sk_security;
sid = sksec->sid;
} else
sid = SECINITSID_KERNEL;
@@ -4751,7 +4788,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
return NF_ACCEPT;
}
static unsigned int selinux_ipv4_output(unsigned int hooknum,
static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -4811,27 +4848,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
* as fast and as clean as possible. */
if (!selinux_policycap_netpeer)
return selinux_ip_postroute_compat(skb, ifindex, family);
secmark_active = selinux_secmark_enabled();
peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active)
return NF_ACCEPT;
sk = skb->sk;
#ifdef CONFIG_XFRM
/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
* packet transformation so allow the packet to pass without any checks
* since we'll have another chance to perform access control checks
* when the packet is on it's final way out.
* NOTE: there appear to be some IPv6 multicast cases where skb->dst
* is NULL, in this case go ahead and apply access control. */
if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
* is NULL, in this case go ahead and apply access control.
* NOTE: if this is a local socket (skb->sk != NULL) that is in the
* TCP listening state we cannot wait until the XFRM processing
* is done as we will miss out on the SA label if we do;
* unfortunately, this means more work, but it is only once per
* connection. */
if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
!(sk != NULL && sk->sk_state == TCP_LISTEN))
return NF_ACCEPT;
#endif
secmark_active = selinux_secmark_enabled();
peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active)
return NF_ACCEPT;
/* if the packet is being forwarded then get the peer label from the
* packet itself; otherwise check to see if it is from a local
* application or the kernel, if from an application get the peer label
* from the sending socket, otherwise use the kernel's sid */
sk = skb->sk;
if (sk == NULL) {
/* Without an associated socket the packet is either coming
* from the kernel or it is being forwarded; check the packet
* to determine which and if the packet is being forwarded
* query the packet directly to determine the security label. */
if (skb->skb_iif) {
secmark_perm = PACKET__FORWARD_OUT;
if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
@@ -4840,7 +4886,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
secmark_perm = PACKET__SEND;
peer_sid = SECINITSID_KERNEL;
}
} else if (sk->sk_state == TCP_LISTEN) {
/* Locally generated packet but the associated socket is in the
* listening state which means this is a SYN-ACK packet. In
* this particular case the correct security label is assigned
* to the connection/request_sock but unfortunately we can't
* query the request_sock as it isn't queued on the parent
* socket until after the SYN-ACK packet is sent; the only
* viable choice is to regenerate the label like we do in
* selinux_inet_conn_request(). See also selinux_ip_output()
* for similar problems. */
u32 skb_sid;
struct sk_security_struct *sksec = sk->sk_security;
if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
return NF_DROP;
/* At this point, if the returned skb peerlbl is SECSID_NULL
* and the packet has been through at least one XFRM
* transformation then we must be dealing with the "final"
* form of labeled IPsec packet; since we've already applied
* all of our access controls on this packet we can safely
* pass the packet. */
if (skb_sid == SECSID_NULL) {
switch (family) {
case PF_INET:
if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
return NF_ACCEPT;
break;
case PF_INET6:
if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
return NF_ACCEPT;
default:
return NF_DROP_ERR(-ECONNREFUSED);
}
}
if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
return NF_DROP;
secmark_perm = PACKET__SEND;
} else {
/* Locally generated packet, fetch the security label from the
* associated socket. */
struct sk_security_struct *sksec = sk->sk_security;
peer_sid = sksec->sid;
secmark_perm = PACKET__SEND;
@@ -4878,7 +4962,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
return NF_ACCEPT;
}
static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -4888,7 +4972,7 @@ static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -5504,11 +5588,11 @@ static int selinux_setprocattr(struct task_struct *p,
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and fail. */
ptsid = 0;
task_lock(p);
rcu_read_lock();
tracer = ptrace_parent(p);
if (tracer)
ptsid = task_sid(tracer);
task_unlock(p);
rcu_read_unlock();
if (tracer) {
error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,

View File

@@ -130,7 +130,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd,
int result,
struct common_audit_data *a, unsigned flags)
struct common_audit_data *a)
{
u32 audited, denied;
audited = avc_audit_required(requested, avd, result, 0, &denied);
@@ -138,7 +138,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
return 0;
return slow_avc_audit(ssid, tsid, tclass,
requested, audited, denied,
a, flags);
a, 0);
}
#define AVC_STRICT 1 /* Ignore permissive mode. */
@@ -147,17 +147,9 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
unsigned flags,
struct av_decision *avd);
int avc_has_perm_flags(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct common_audit_data *auditdata,
unsigned);
static inline int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct common_audit_data *auditdata)
{
return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0);
}
int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct common_audit_data *auditdata);
u32 avc_policy_seqno(void);

View File

@@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
struct common_audit_data *ad, u8 proto);
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid);
static inline void selinux_xfrm_notify_policyload(void)
{
@@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
static inline void selinux_xfrm_notify_policyload(void)
{
}
static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
{
*sid = SECSID_NULL;
return 0;
}
#endif
static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
{
return selinux_xfrm_decode_session(skb, sid, 0);
}
#endif /* _SELINUX_XFRM_H_ */

View File

@@ -116,6 +116,8 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
{ AUDIT_MAKE_EQUIV, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ },
{ AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT },
{ AUDIT_GET_FEATURE, NETLINK_AUDIT_SOCKET__NLMSG_READ },
{ AUDIT_SET_FEATURE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
};

View File

@@ -2334,50 +2334,16 @@ int security_fs_use(struct super_block *sb)
struct ocontext *c;
struct superblock_security_struct *sbsec = sb->s_security;
const char *fstype = sb->s_type->name;
const char *subtype = (sb->s_subtype && sb->s_subtype[0]) ? sb->s_subtype : NULL;
struct ocontext *base = NULL;
read_lock(&policy_rwlock);
for (c = policydb.ocontexts[OCON_FSUSE]; c; c = c->next) {
char *sub;
int baselen;
baselen = strlen(fstype);
/* if base does not match, this is not the one */
if (strncmp(fstype, c->u.name, baselen))
continue;
/* if there is no subtype, this is the one! */
if (!subtype)
break;
/* skip past the base in this entry */
sub = c->u.name + baselen;
/* entry is only a base. save it. keep looking for subtype */
if (sub[0] == '\0') {
base = c;
continue;
}
/* entry is not followed by a subtype, so it is not a match */
if (sub[0] != '.')
continue;
/* whew, we found a subtype of this fstype */
sub++; /* move past '.' */
/* exact match of fstype AND subtype */
if (!strcmp(subtype, sub))
c = policydb.ocontexts[OCON_FSUSE];
while (c) {
if (strcmp(fstype, c->u.name) == 0)
break;
c = c->next;
}
/* in case we had found an fstype match but no subtype match */
if (!c)
c = base;
if (c) {
sbsec->behavior = c->v.behavior;
if (!c->sid[0]) {

View File

@@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
NULL) ? 0 : 1);
}
/*
* LSM hook implementation that checks and/or returns the xfrm sid for the
* incoming packet.
*/
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct xfrm_state *x;
if (dst == NULL)
return SECSID_NULL;
x = dst->xfrm;
if (x == NULL || !selinux_authorizable_xfrm(x))
return SECSID_NULL;
return x->security->ctx_sid;
}
static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb,
u32 *sid, int ckall)
{
u32 sid_session = SECSID_NULL;
struct sec_path *sp;
struct sec_path *sp = skb->sp;
if (skb == NULL)
goto out;
sp = skb->sp;
if (sp) {
int i;
@@ -247,6 +254,30 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
return 0;
}
/*
* LSM hook implementation that checks and/or returns the xfrm sid for the
* incoming packet.
*/
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
{
if (skb == NULL) {
*sid = SECSID_NULL;
return 0;
}
return selinux_xfrm_skb_sid_ingress(skb, sid, ckall);
}
int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
{
int rc;
rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0);
if (rc == 0 && *sid == SECSID_NULL)
*sid = selinux_xfrm_skb_sid_egress(skb);
return rc;
}
/*
* LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
*/
@@ -327,19 +358,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
return rc;
ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
if (!ctx)
return -ENOMEM;
if (!ctx) {
rc = -ENOMEM;
goto out;
}
ctx->ctx_doi = XFRM_SC_DOI_LSM;
ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
ctx->ctx_sid = secid;
ctx->ctx_len = str_len;
memcpy(ctx->ctx_str, ctx_str, str_len);
kfree(ctx_str);
x->security = ctx;
atomic_inc(&selinux_xfrm_refcount);
return 0;
out:
kfree(ctx_str);
return rc;
}
/*