Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights for this window: - improved AVC hashing for SELinux by John Brooks and Stephen Smalley - addition of an unconfined label to Smack - Smack documentation update - TPM driver updates" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (28 commits) lsm: copy comm before calling audit_log to avoid race in string printing tomoyo: Do not generate empty policy files tomoyo: Use if_changed when generating builtin-policy.h tomoyo: Use bin2c to generate builtin-policy.h selinux: increase avtab max buckets selinux: Use a better hash function for avtab selinux: convert avtab hash table to flex_array selinux: reconcile security_netlbl_secattr_to_sid() and mls_import_netlbl_cat() selinux: remove unnecessary pointer reassignment Smack: Updates for Smack documentation tpm/st33zp24/spi: Add missing device table for spi phy. tpm/st33zp24: Add proper wait for ordinal duration in case of irq mode smack: Fix gcc warning from unused smack_syslog_lock mutex in smackfs.c Smack: Allow an unconfined label in bringup mode Smack: getting the Smack security context of keys Smack: Assign smack_known_web as default smk_in label for kernel thread's socket tpm/tpm_infineon: Use struct dev_pm_ops for power management MAINTAINERS: Add Jason as designated reviewer for TPM tpm: Update KConfig text to include TPM2.0 FIFO chips tpm/st33zp24/dts/st33zp24-spi: Add dts documentation for st33zp24 spi phy ...
This commit is contained in:
@@ -211,7 +211,7 @@ static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
|
||||
static void dump_common_audit_data(struct audit_buffer *ab,
|
||||
struct common_audit_data *a)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
char comm[sizeof(current->comm)];
|
||||
|
||||
/*
|
||||
* To keep stack sizes in check force programers to notice if they
|
||||
@@ -220,8 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
|
||||
*/
|
||||
BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
|
||||
|
||||
audit_log_format(ab, " pid=%d comm=", task_pid_nr(tsk));
|
||||
audit_log_untrustedstring(ab, tsk->comm);
|
||||
audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
|
||||
audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm)));
|
||||
|
||||
switch (a->type) {
|
||||
case LSM_AUDIT_DATA_NONE:
|
||||
@@ -276,16 +276,19 @@ static void dump_common_audit_data(struct audit_buffer *ab,
|
||||
audit_log_format(ab, " ino=%lu", inode->i_ino);
|
||||
break;
|
||||
}
|
||||
case LSM_AUDIT_DATA_TASK:
|
||||
tsk = a->u.tsk;
|
||||
case LSM_AUDIT_DATA_TASK: {
|
||||
struct task_struct *tsk = a->u.tsk;
|
||||
if (tsk) {
|
||||
pid_t pid = task_pid_nr(tsk);
|
||||
if (pid) {
|
||||
char comm[sizeof(tsk->comm)];
|
||||
audit_log_format(ab, " pid=%d comm=", pid);
|
||||
audit_log_untrustedstring(ab, tsk->comm);
|
||||
audit_log_untrustedstring(ab,
|
||||
memcpy(comm, tsk->comm, sizeof(comm)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LSM_AUDIT_DATA_NET:
|
||||
if (a->u.net->sk) {
|
||||
struct sock *sk = a->u.net->sk;
|
||||
|
||||
@@ -724,12 +724,10 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
||||
rcu_read_lock();
|
||||
|
||||
node = avc_lookup(ssid, tsid, tclass);
|
||||
if (unlikely(!node)) {
|
||||
if (unlikely(!node))
|
||||
node = avc_compute_av(ssid, tsid, tclass, avd);
|
||||
} else {
|
||||
else
|
||||
memcpy(avd, &node->ae.avd, sizeof(*avd));
|
||||
avd = &node->ae.avd;
|
||||
}
|
||||
|
||||
denied = requested & ~(avd->allowed);
|
||||
if (unlikely(denied))
|
||||
|
||||
+56
-16
@@ -25,10 +25,43 @@
|
||||
|
||||
static struct kmem_cache *avtab_node_cachep;
|
||||
|
||||
static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
|
||||
/* Based on MurmurHash3, written by Austin Appleby and placed in the
|
||||
* public domain.
|
||||
*/
|
||||
static inline int avtab_hash(struct avtab_key *keyp, u32 mask)
|
||||
{
|
||||
return ((keyp->target_class + (keyp->target_type << 2) +
|
||||
(keyp->source_type << 9)) & mask);
|
||||
static const u32 c1 = 0xcc9e2d51;
|
||||
static const u32 c2 = 0x1b873593;
|
||||
static const u32 r1 = 15;
|
||||
static const u32 r2 = 13;
|
||||
static const u32 m = 5;
|
||||
static const u32 n = 0xe6546b64;
|
||||
|
||||
u32 hash = 0;
|
||||
|
||||
#define mix(input) { \
|
||||
u32 v = input; \
|
||||
v *= c1; \
|
||||
v = (v << r1) | (v >> (32 - r1)); \
|
||||
v *= c2; \
|
||||
hash ^= v; \
|
||||
hash = (hash << r2) | (hash >> (32 - r2)); \
|
||||
hash = hash * m + n; \
|
||||
}
|
||||
|
||||
mix(keyp->target_class);
|
||||
mix(keyp->target_type);
|
||||
mix(keyp->source_type);
|
||||
|
||||
#undef mix
|
||||
|
||||
hash ^= hash >> 16;
|
||||
hash *= 0x85ebca6b;
|
||||
hash ^= hash >> 13;
|
||||
hash *= 0xc2b2ae35;
|
||||
hash ^= hash >> 16;
|
||||
|
||||
return hash & mask;
|
||||
}
|
||||
|
||||
static struct avtab_node*
|
||||
@@ -46,8 +79,12 @@ avtab_insert_node(struct avtab *h, int hvalue,
|
||||
newnode->next = prev->next;
|
||||
prev->next = newnode;
|
||||
} else {
|
||||
newnode->next = h->htable[hvalue];
|
||||
h->htable[hvalue] = newnode;
|
||||
newnode->next = flex_array_get_ptr(h->htable, hvalue);
|
||||
if (flex_array_put_ptr(h->htable, hvalue, newnode,
|
||||
GFP_KERNEL|__GFP_ZERO)) {
|
||||
kmem_cache_free(avtab_node_cachep, newnode);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
h->nel++;
|
||||
@@ -64,7 +101,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
|
||||
return -EINVAL;
|
||||
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
for (prev = NULL, cur = h->htable[hvalue];
|
||||
for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
|
||||
cur;
|
||||
prev = cur, cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
@@ -104,7 +141,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
|
||||
if (!h || !h->htable)
|
||||
return NULL;
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
for (prev = NULL, cur = h->htable[hvalue];
|
||||
for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
|
||||
cur;
|
||||
prev = cur, cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
@@ -135,7 +172,8 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
|
||||
return NULL;
|
||||
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
for (cur = h->htable[hvalue]; cur; cur = cur->next) {
|
||||
for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
|
||||
cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class == cur->key.target_class &&
|
||||
@@ -170,7 +208,8 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
|
||||
return NULL;
|
||||
|
||||
hvalue = avtab_hash(key, h->mask);
|
||||
for (cur = h->htable[hvalue]; cur; cur = cur->next) {
|
||||
for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
|
||||
cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class == cur->key.target_class &&
|
||||
@@ -228,15 +267,14 @@ void avtab_destroy(struct avtab *h)
|
||||
return;
|
||||
|
||||
for (i = 0; i < h->nslot; i++) {
|
||||
cur = h->htable[i];
|
||||
cur = flex_array_get_ptr(h->htable, i);
|
||||
while (cur) {
|
||||
temp = cur;
|
||||
cur = cur->next;
|
||||
kmem_cache_free(avtab_node_cachep, temp);
|
||||
}
|
||||
h->htable[i] = NULL;
|
||||
}
|
||||
kfree(h->htable);
|
||||
flex_array_free(h->htable);
|
||||
h->htable = NULL;
|
||||
h->nslot = 0;
|
||||
h->mask = 0;
|
||||
@@ -251,7 +289,7 @@ int avtab_init(struct avtab *h)
|
||||
|
||||
int avtab_alloc(struct avtab *h, u32 nrules)
|
||||
{
|
||||
u16 mask = 0;
|
||||
u32 mask = 0;
|
||||
u32 shift = 0;
|
||||
u32 work = nrules;
|
||||
u32 nslot = 0;
|
||||
@@ -270,7 +308,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
|
||||
nslot = MAX_AVTAB_HASH_BUCKETS;
|
||||
mask = nslot - 1;
|
||||
|
||||
h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL);
|
||||
h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot,
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!h->htable)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -293,7 +332,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
|
||||
max_chain_len = 0;
|
||||
chain2_len_sum = 0;
|
||||
for (i = 0; i < h->nslot; i++) {
|
||||
cur = h->htable[i];
|
||||
cur = flex_array_get_ptr(h->htable, i);
|
||||
if (cur) {
|
||||
slots_used++;
|
||||
chain_len = 0;
|
||||
@@ -534,7 +573,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < a->nslot; i++) {
|
||||
for (cur = a->htable[i]; cur; cur = cur->next) {
|
||||
for (cur = flex_array_get_ptr(a->htable, i); cur;
|
||||
cur = cur->next) {
|
||||
rc = avtab_write_item(p, cur, fp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#ifndef _SS_AVTAB_H_
|
||||
#define _SS_AVTAB_H_
|
||||
|
||||
#include <linux/flex_array.h>
|
||||
|
||||
struct avtab_key {
|
||||
u16 source_type; /* source type */
|
||||
u16 target_type; /* target type */
|
||||
@@ -51,10 +53,10 @@ struct avtab_node {
|
||||
};
|
||||
|
||||
struct avtab {
|
||||
struct avtab_node **htable;
|
||||
struct flex_array *htable;
|
||||
u32 nel; /* number of elements */
|
||||
u32 nslot; /* number of hash slots */
|
||||
u16 mask; /* mask to compute hash func */
|
||||
u32 mask; /* mask to compute hash func */
|
||||
|
||||
};
|
||||
|
||||
@@ -84,7 +86,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified
|
||||
void avtab_cache_init(void);
|
||||
void avtab_cache_destroy(void);
|
||||
|
||||
#define MAX_AVTAB_HASH_BITS 11
|
||||
#define MAX_AVTAB_HASH_BITS 16
|
||||
#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
|
||||
|
||||
#endif /* _SS_AVTAB_H_ */
|
||||
|
||||
@@ -654,19 +654,15 @@ int mls_import_netlbl_cat(struct context *context,
|
||||
|
||||
rc = ebitmap_netlbl_import(&context->range.level[0].cat,
|
||||
secattr->attr.mls.cat);
|
||||
if (rc != 0)
|
||||
goto import_netlbl_cat_failure;
|
||||
|
||||
rc = ebitmap_cpy(&context->range.level[1].cat,
|
||||
&context->range.level[0].cat);
|
||||
if (rc != 0)
|
||||
if (rc)
|
||||
goto import_netlbl_cat_failure;
|
||||
memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
|
||||
sizeof(context->range.level[0].cat));
|
||||
|
||||
return 0;
|
||||
|
||||
import_netlbl_cat_failure:
|
||||
ebitmap_destroy(&context->range.level[0].cat);
|
||||
ebitmap_destroy(&context->range.level[1].cat);
|
||||
return rc;
|
||||
}
|
||||
#endif /* CONFIG_NETLABEL */
|
||||
|
||||
@@ -3179,13 +3179,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
||||
ctx_new.type = ctx->type;
|
||||
mls_import_netlbl_lvl(&ctx_new, secattr);
|
||||
if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
|
||||
rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
|
||||
secattr->attr.mls.cat);
|
||||
rc = mls_import_netlbl_cat(&ctx_new, secattr);
|
||||
if (rc)
|
||||
goto out;
|
||||
memcpy(&ctx_new.range.level[1].cat,
|
||||
&ctx_new.range.level[0].cat,
|
||||
sizeof(ctx_new.range.level[0].cat));
|
||||
}
|
||||
rc = -EIDRM;
|
||||
if (!mls_context_isvalid(&policydb, &ctx_new))
|
||||
|
||||
@@ -105,6 +105,7 @@ struct task_smack {
|
||||
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
|
||||
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
|
||||
#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */
|
||||
#define SMK_INODE_IMPURE 0x08 /* involved in an impure transaction */
|
||||
|
||||
/*
|
||||
* A label access rule.
|
||||
@@ -193,6 +194,10 @@ struct smk_port_label {
|
||||
#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */
|
||||
#define MAY_BRINGUP 0x00004000 /* Report use of this rule */
|
||||
|
||||
#define SMACK_BRINGUP_ALLOW 1 /* Allow bringup mode */
|
||||
#define SMACK_UNCONFINED_SUBJECT 2 /* Allow unconfined label */
|
||||
#define SMACK_UNCONFINED_OBJECT 3 /* Allow unconfined label */
|
||||
|
||||
/*
|
||||
* Just to make the common cases easier to deal with
|
||||
*/
|
||||
@@ -254,6 +259,9 @@ extern int smack_cipso_mapped;
|
||||
extern struct smack_known *smack_net_ambient;
|
||||
extern struct smack_known *smack_onlycap;
|
||||
extern struct smack_known *smack_syslog_label;
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
extern struct smack_known *smack_unconfined;
|
||||
#endif
|
||||
extern struct smack_known smack_cipso_option;
|
||||
extern int smack_ptrace_rule;
|
||||
|
||||
|
||||
@@ -130,7 +130,8 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
|
||||
|
||||
/*
|
||||
* Hardcoded comparisons.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* A star subject can't access any object.
|
||||
*/
|
||||
if (subject == &smack_known_star) {
|
||||
@@ -189,10 +190,20 @@ int smk_access(struct smack_known *subject, struct smack_known *object,
|
||||
* succeed because of "b" rules.
|
||||
*/
|
||||
if (may & MAY_BRINGUP)
|
||||
rc = MAY_BRINGUP;
|
||||
rc = SMACK_BRINGUP_ALLOW;
|
||||
#endif
|
||||
|
||||
out_audit:
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
if (rc < 0) {
|
||||
if (object == smack_unconfined)
|
||||
rc = SMACK_UNCONFINED_OBJECT;
|
||||
if (subject == smack_unconfined)
|
||||
rc = SMACK_UNCONFINED_SUBJECT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIT
|
||||
if (a)
|
||||
smack_log(subject->smk_known, object->smk_known,
|
||||
@@ -338,19 +349,16 @@ static void smack_log_callback(struct audit_buffer *ab, void *a)
|
||||
void smack_log(char *subject_label, char *object_label, int request,
|
||||
int result, struct smk_audit_info *ad)
|
||||
{
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
|
||||
#else
|
||||
char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
|
||||
#endif
|
||||
struct smack_audit_data *sad;
|
||||
struct common_audit_data *a = &ad->a;
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
/*
|
||||
* The result may be positive in bringup mode.
|
||||
*/
|
||||
if (result > 0)
|
||||
result = 0;
|
||||
#endif
|
||||
/* check if we have to log the current event */
|
||||
if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
|
||||
if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
|
||||
return;
|
||||
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
|
||||
return;
|
||||
@@ -364,6 +372,21 @@ void smack_log(char *subject_label, char *object_label, int request,
|
||||
smack_str_from_perm(request_buffer, request);
|
||||
sad->subject = subject_label;
|
||||
sad->object = object_label;
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
/*
|
||||
* The result may be positive in bringup mode.
|
||||
* A positive result is an allow, but not for normal reasons.
|
||||
* Mark it as successful, but don't filter it out even if
|
||||
* the logging policy says to do so.
|
||||
*/
|
||||
if (result == SMACK_UNCONFINED_SUBJECT)
|
||||
strcat(request_buffer, "(US)");
|
||||
else if (result == SMACK_UNCONFINED_OBJECT)
|
||||
strcat(request_buffer, "(UO)");
|
||||
|
||||
if (result > 0)
|
||||
result = 0;
|
||||
#endif
|
||||
sad->request = request_buffer;
|
||||
sad->result = result;
|
||||
|
||||
|
||||
@@ -57,6 +57,13 @@ static struct kmem_cache *smack_inode_cache;
|
||||
int smack_enabled;
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
static char *smk_bu_mess[] = {
|
||||
"Bringup Error", /* Unused */
|
||||
"Bringup", /* SMACK_BRINGUP_ALLOW */
|
||||
"Unconfined Subject", /* SMACK_UNCONFINED_SUBJECT */
|
||||
"Unconfined Object", /* SMACK_UNCONFINED_OBJECT */
|
||||
};
|
||||
|
||||
static void smk_bu_mode(int mode, char *s)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -87,9 +94,11 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
if (rc > SMACK_UNCONFINED_OBJECT)
|
||||
rc = 0;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
pr_info("Smack Bringup: (%s %s %s) %s\n",
|
||||
pr_info("Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc],
|
||||
sskp->smk_known, oskp->smk_known, acc, note);
|
||||
return 0;
|
||||
}
|
||||
@@ -106,9 +115,11 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
if (rc > SMACK_UNCONFINED_OBJECT)
|
||||
rc = 0;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
pr_info("Smack Bringup: (%s %s %s) %s %s\n",
|
||||
pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
|
||||
tsp->smk_task->smk_known, oskp->smk_known,
|
||||
acc, current->comm, note);
|
||||
return 0;
|
||||
@@ -126,9 +137,11 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
if (rc > SMACK_UNCONFINED_OBJECT)
|
||||
rc = 0;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
pr_info("Smack Bringup: (%s %s %s) %s to %s\n",
|
||||
pr_info("Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc],
|
||||
tsp->smk_task->smk_known, smk_task->smk_known, acc,
|
||||
current->comm, otp->comm);
|
||||
return 0;
|
||||
@@ -141,14 +154,25 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
|
||||
static int smk_bu_inode(struct inode *inode, int mode, int rc)
|
||||
{
|
||||
struct task_smack *tsp = current_security();
|
||||
struct inode_smack *isp = inode->i_security;
|
||||
char acc[SMK_NUM_ACCESS_TYPE + 1];
|
||||
|
||||
if (isp->smk_flags & SMK_INODE_IMPURE)
|
||||
pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
|
||||
inode->i_sb->s_id, inode->i_ino, current->comm);
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
if (rc > SMACK_UNCONFINED_OBJECT)
|
||||
rc = 0;
|
||||
if (rc == SMACK_UNCONFINED_SUBJECT &&
|
||||
(mode & (MAY_WRITE | MAY_APPEND)))
|
||||
isp->smk_flags |= SMK_INODE_IMPURE;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n",
|
||||
tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc,
|
||||
|
||||
pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
|
||||
tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,
|
||||
inode->i_sb->s_id, inode->i_ino, current->comm);
|
||||
return 0;
|
||||
}
|
||||
@@ -162,13 +186,20 @@ static int smk_bu_file(struct file *file, int mode, int rc)
|
||||
struct task_smack *tsp = current_security();
|
||||
struct smack_known *sskp = tsp->smk_task;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct inode_smack *isp = inode->i_security;
|
||||
char acc[SMK_NUM_ACCESS_TYPE + 1];
|
||||
|
||||
if (isp->smk_flags & SMK_INODE_IMPURE)
|
||||
pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
|
||||
inode->i_sb->s_id, inode->i_ino, current->comm);
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
if (rc > SMACK_UNCONFINED_OBJECT)
|
||||
rc = 0;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
|
||||
pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
|
||||
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
|
||||
inode->i_sb->s_id, inode->i_ino, file,
|
||||
current->comm);
|
||||
@@ -185,13 +216,20 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
|
||||
struct task_smack *tsp = cred->security;
|
||||
struct smack_known *sskp = tsp->smk_task;
|
||||
struct inode *inode = file->f_inode;
|
||||
struct inode_smack *isp = inode->i_security;
|
||||
char acc[SMK_NUM_ACCESS_TYPE + 1];
|
||||
|
||||
if (isp->smk_flags & SMK_INODE_IMPURE)
|
||||
pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
|
||||
inode->i_sb->s_id, inode->i_ino, current->comm);
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
if (rc > SMACK_UNCONFINED_OBJECT)
|
||||
rc = 0;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
|
||||
pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
|
||||
sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
|
||||
inode->i_sb->s_id, inode->i_ino, file,
|
||||
current->comm);
|
||||
@@ -2449,7 +2487,21 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
|
||||
static int smack_socket_post_create(struct socket *sock, int family,
|
||||
int type, int protocol, int kern)
|
||||
{
|
||||
if (family != PF_INET || sock->sk == NULL)
|
||||
struct socket_smack *ssp;
|
||||
|
||||
if (sock->sk == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Sockets created by kernel threads receive web label.
|
||||
*/
|
||||
if (unlikely(current->flags & PF_KTHREAD)) {
|
||||
ssp = sock->sk->sk_security;
|
||||
ssp->smk_in = &smack_known_web;
|
||||
ssp->smk_out = &smack_known_web;
|
||||
}
|
||||
|
||||
if (family != PF_INET)
|
||||
return 0;
|
||||
/*
|
||||
* Set the outbound netlbl.
|
||||
@@ -3983,6 +4035,36 @@ static int smack_key_permission(key_ref_t key_ref,
|
||||
rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* smack_key_getsecurity - Smack label tagging the key
|
||||
* @key points to the key to be queried
|
||||
* @_buffer points to a pointer that should be set to point to the
|
||||
* resulting string (if no label or an error occurs).
|
||||
* Return the length of the string (including terminating NUL) or -ve if
|
||||
* an error.
|
||||
* May also return 0 (and a NULL buffer pointer) if there is no label.
|
||||
*/
|
||||
static int smack_key_getsecurity(struct key *key, char **_buffer)
|
||||
{
|
||||
struct smack_known *skp = key->security;
|
||||
size_t length;
|
||||
char *copy;
|
||||
|
||||
if (key->security == NULL) {
|
||||
*_buffer = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
copy = kstrdup(skp->smk_known, GFP_KERNEL);
|
||||
if (copy == NULL)
|
||||
return -ENOMEM;
|
||||
length = strlen(copy) + 1;
|
||||
|
||||
*_buffer = copy;
|
||||
return length;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
/*
|
||||
@@ -4307,6 +4389,7 @@ struct security_operations smack_ops = {
|
||||
.key_alloc = smack_key_alloc,
|
||||
.key_free = smack_key_free,
|
||||
.key_permission = smack_key_permission,
|
||||
.key_getsecurity = smack_key_getsecurity,
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
/* Audit hooks */
|
||||
|
||||
@@ -54,6 +54,9 @@ enum smk_inos {
|
||||
SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
|
||||
SMK_SYSLOG = 20, /* change syslog label) */
|
||||
SMK_PTRACE = 21, /* set ptrace rule */
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
SMK_UNCONFINED = 22, /* define an unconfined label */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -61,7 +64,6 @@ enum smk_inos {
|
||||
*/
|
||||
static DEFINE_MUTEX(smack_cipso_lock);
|
||||
static DEFINE_MUTEX(smack_ambient_lock);
|
||||
static DEFINE_MUTEX(smack_syslog_lock);
|
||||
static DEFINE_MUTEX(smk_netlbladdr_lock);
|
||||
|
||||
/*
|
||||
@@ -95,6 +97,16 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
|
||||
*/
|
||||
struct smack_known *smack_onlycap;
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
/*
|
||||
* Allow one label to be unconfined. This is for
|
||||
* debugging and application bring-up purposes only.
|
||||
* It is bad and wrong, but everyone seems to expect
|
||||
* to have it.
|
||||
*/
|
||||
struct smack_known *smack_unconfined;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this value is set restrict syslog use to the label specified.
|
||||
* It can be reset via smackfs/syslog
|
||||
@@ -1717,6 +1729,85 @@ static const struct file_operations smk_onlycap_ops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
/**
|
||||
* smk_read_unconfined - read() for smackfs/unconfined
|
||||
* @filp: file pointer, not actually used
|
||||
* @buf: where to put the result
|
||||
* @cn: maximum to send along
|
||||
* @ppos: where to start
|
||||
*
|
||||
* Returns number of bytes read or error code, as appropriate
|
||||
*/
|
||||
static ssize_t smk_read_unconfined(struct file *filp, char __user *buf,
|
||||
size_t cn, loff_t *ppos)
|
||||
{
|
||||
char *smack = "";
|
||||
ssize_t rc = -EINVAL;
|
||||
int asize;
|
||||
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
|
||||
if (smack_unconfined != NULL)
|
||||
smack = smack_unconfined->smk_known;
|
||||
|
||||
asize = strlen(smack) + 1;
|
||||
|
||||
if (cn >= asize)
|
||||
rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_write_unconfined - write() for smackfs/unconfined
|
||||
* @file: file pointer, not actually used
|
||||
* @buf: where to get the data from
|
||||
* @count: bytes sent
|
||||
* @ppos: where to start
|
||||
*
|
||||
* Returns number of bytes written or error code, as appropriate
|
||||
*/
|
||||
static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *data;
|
||||
int rc = count;
|
||||
|
||||
if (!smack_privileged(CAP_MAC_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
data = kzalloc(count + 1, GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Should the null string be passed in unset the unconfined value.
|
||||
* This seems like something to be careful with as usually
|
||||
* smk_import only expects to return NULL for errors. It
|
||||
* is usually the case that a nullstring or "\n" would be
|
||||
* bad to pass to smk_import but in fact this is useful here.
|
||||
*
|
||||
* smk_import will also reject a label beginning with '-',
|
||||
* so "-confine" will also work.
|
||||
*/
|
||||
if (copy_from_user(data, buf, count) != 0)
|
||||
rc = -EFAULT;
|
||||
else
|
||||
smack_unconfined = smk_import_entry(data, count);
|
||||
|
||||
kfree(data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations smk_unconfined_ops = {
|
||||
.read = smk_read_unconfined,
|
||||
.write = smk_write_unconfined,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
|
||||
|
||||
/**
|
||||
* smk_read_logging - read() for /smack/logging
|
||||
* @filp: file pointer, not actually used
|
||||
@@ -2384,6 +2475,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
|
||||
"syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
|
||||
[SMK_PTRACE] = {
|
||||
"ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
[SMK_UNCONFINED] = {
|
||||
"unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
|
||||
#endif
|
||||
/* last one */
|
||||
{""}
|
||||
};
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
builtin-policy.h
|
||||
policy/
|
||||
policy/*.conf
|
||||
|
||||
@@ -6,6 +6,7 @@ config SECURITY_TOMOYO
|
||||
select SECURITY_PATH
|
||||
select SECURITY_NETWORK
|
||||
select SRCU
|
||||
select BUILD_BIN2C
|
||||
default n
|
||||
help
|
||||
This selects TOMOYO Linux, pathname-based access control.
|
||||
|
||||
+10
-43
@@ -1,48 +1,15 @@
|
||||
obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o
|
||||
|
||||
$(obj)/policy/profile.conf:
|
||||
@mkdir -p $(obj)/policy/
|
||||
@echo Creating an empty policy/profile.conf
|
||||
@touch $@
|
||||
targets += builtin-policy.h
|
||||
define do_policy
|
||||
echo "static char tomoyo_builtin_$(1)[] __initdata ="; \
|
||||
$(objtree)/scripts/basic/bin2c <$(firstword $(wildcard $(obj)/policy/$(1).conf $(srctree)/$(src)/policy/$(1).conf.default) /dev/null); \
|
||||
echo ";"
|
||||
endef
|
||||
quiet_cmd_policy = POLICY $@
|
||||
cmd_policy = ($(call do_policy,profile); $(call do_policy,exception_policy); $(call do_policy,domain_policy); $(call do_policy,manager); $(call do_policy,stat)) >$@
|
||||
|
||||
$(obj)/policy/exception_policy.conf:
|
||||
@mkdir -p $(obj)/policy/
|
||||
@echo Creating a default policy/exception_policy.conf
|
||||
@echo initialize_domain /sbin/modprobe from any >> $@
|
||||
@echo initialize_domain /sbin/hotplug from any >> $@
|
||||
|
||||
$(obj)/policy/domain_policy.conf:
|
||||
@mkdir -p $(obj)/policy/
|
||||
@echo Creating an empty policy/domain_policy.conf
|
||||
@touch $@
|
||||
|
||||
$(obj)/policy/manager.conf:
|
||||
@mkdir -p $(obj)/policy/
|
||||
@echo Creating an empty policy/manager.conf
|
||||
@touch $@
|
||||
|
||||
$(obj)/policy/stat.conf:
|
||||
@mkdir -p $(obj)/policy/
|
||||
@echo Creating an empty policy/stat.conf
|
||||
@touch $@
|
||||
|
||||
$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf
|
||||
@echo Generating built-in policy for TOMOYO 2.5.x.
|
||||
@echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp
|
||||
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp
|
||||
@echo "\"\";" >> $@.tmp
|
||||
@echo "static char tomoyo_builtin_exception_policy[] __initdata =" >> $@.tmp
|
||||
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp
|
||||
@echo "\"\";" >> $@.tmp
|
||||
@echo "static char tomoyo_builtin_domain_policy[] __initdata =" >> $@.tmp
|
||||
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp
|
||||
@echo "\"\";" >> $@.tmp
|
||||
@echo "static char tomoyo_builtin_manager[] __initdata =" >> $@.tmp
|
||||
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp
|
||||
@echo "\"\";" >> $@.tmp
|
||||
@echo "static char tomoyo_builtin_stat[] __initdata =" >> $@.tmp
|
||||
@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp
|
||||
@echo "\"\";" >> $@.tmp
|
||||
@mv $@.tmp $@
|
||||
$(obj)/builtin-policy.h: $(wildcard $(obj)/policy/*.conf $(src)/policy/*.conf.default) FORCE
|
||||
$(call if_changed,policy)
|
||||
|
||||
$(obj)/common.o: $(obj)/builtin-policy.h
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
initialize_domain /sbin/modprobe from any
|
||||
initialize_domain /sbin/hotplug from any
|
||||
@@ -1,8 +1,6 @@
|
||||
config SECURITY_YAMA
|
||||
bool "Yama support"
|
||||
depends on SECURITY
|
||||
select SECURITYFS
|
||||
select SECURITY_PATH
|
||||
default n
|
||||
help
|
||||
This selects Yama, which extends DAC support with additional
|
||||
|
||||
@@ -379,20 +379,17 @@ static struct security_operations yama_ops = {
|
||||
static int yama_dointvec_minmax(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int rc;
|
||||
struct ctl_table table_copy;
|
||||
|
||||
if (write && !capable(CAP_SYS_PTRACE))
|
||||
return -EPERM;
|
||||
|
||||
rc = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Lock the max value if it ever gets set. */
|
||||
if (write && *(int *)table->data == *(int *)table->extra2)
|
||||
table->extra1 = table->extra2;
|
||||
table_copy = *table;
|
||||
if (*(int *)table_copy.data == *(int *)table_copy.extra2)
|
||||
table_copy.extra1 = table_copy.extra2;
|
||||
|
||||
return rc;
|
||||
return proc_dointvec_minmax(&table_copy, write, buffer, lenp, ppos);
|
||||
}
|
||||
|
||||
static int zero;
|
||||
|
||||
Reference in New Issue
Block a user