You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (30 commits) MAINTAINERS: Add tomoyo-dev-en ML. SELinux: define permissions for DCB netlink messages encrypted-keys: style and other cleanup encrypted-keys: verify datablob size before converting to binary trusted-keys: kzalloc and other cleanup trusted-keys: additional TSS return code and other error handling syslog: check cap_syslog when dmesg_restrict Smack: Transmute labels on specified directories selinux: cache sidtab_context_to_sid results SELinux: do not compute transition labels on mountpoint labeled filesystems This patch adds a new security attribute to Smack called SMACK64EXEC. It defines label that is used while task is running. SELinux: merge policydb_index_classes and policydb_index_others selinux: convert part of the sym_val_to_name array to use flex_array selinux: convert type_val_to_struct to flex_array flex_array: fix flex_array_put_ptr macro to be valid C SELinux: do not set automatic i_ino in selinuxfs selinux: rework security_netlbl_secattr_to_sid SELinux: standardize return code handling in selinuxfs.c SELinux: standardize return code handling in selinuxfs.c SELinux: standardize return code handling in policydb.c ...
This commit is contained in:
@@ -21,6 +21,37 @@ config KEYS
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
config TRUSTED_KEYS
|
||||
tristate "TRUSTED KEYS"
|
||||
depends on KEYS && TCG_TPM
|
||||
select CRYPTO
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_SHA1
|
||||
help
|
||||
This option provides support for creating, sealing, and unsealing
|
||||
keys in the kernel. Trusted keys are random number symmetric keys,
|
||||
generated and RSA-sealed by the TPM. The TPM only unseals the keys,
|
||||
if the boot PCRs and other criteria match. Userspace will only ever
|
||||
see encrypted blobs.
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
config ENCRYPTED_KEYS
|
||||
tristate "ENCRYPTED KEYS"
|
||||
depends on KEYS && TRUSTED_KEYS
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_CBC
|
||||
select CRYPTO_SHA256
|
||||
select CRYPTO_RNG
|
||||
help
|
||||
This option provides support for create/encrypting/decrypting keys
|
||||
in the kernel. Encrypted keys are kernel generated random numbers,
|
||||
which are encrypted/decrypted with a 'master' symmetric key. The
|
||||
'master' key can be either a trusted-key or user-key type.
|
||||
Userspace only ever sees/stores encrypted blobs.
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
config KEYS_DEBUG_PROC_KEYS
|
||||
bool "Enable the /proc/keys file by which keys may be viewed"
|
||||
depends on KEYS
|
||||
|
||||
@@ -13,6 +13,8 @@ obj-y := \
|
||||
request_key_auth.o \
|
||||
user_defined.o
|
||||
|
||||
obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
|
||||
obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted_defined.o
|
||||
obj-$(CONFIG_KEYS_COMPAT) += compat.o
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
obj-$(CONFIG_SYSCTL) += sysctl.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
#ifndef __ENCRYPTED_KEY_H
|
||||
#define __ENCRYPTED_KEY_H
|
||||
|
||||
#define ENCRYPTED_DEBUG 0
|
||||
|
||||
#if ENCRYPTED_DEBUG
|
||||
static inline void dump_master_key(const u8 *master_key, size_t master_keylen)
|
||||
{
|
||||
print_hex_dump(KERN_ERR, "master key: ", DUMP_PREFIX_NONE, 32, 1,
|
||||
master_key, master_keylen, 0);
|
||||
}
|
||||
|
||||
static inline void dump_decrypted_data(struct encrypted_key_payload *epayload)
|
||||
{
|
||||
print_hex_dump(KERN_ERR, "decrypted data: ", DUMP_PREFIX_NONE, 32, 1,
|
||||
epayload->decrypted_data,
|
||||
epayload->decrypted_datalen, 0);
|
||||
}
|
||||
|
||||
static inline void dump_encrypted_data(struct encrypted_key_payload *epayload,
|
||||
unsigned int encrypted_datalen)
|
||||
{
|
||||
print_hex_dump(KERN_ERR, "encrypted data: ", DUMP_PREFIX_NONE, 32, 1,
|
||||
epayload->encrypted_data, encrypted_datalen, 0);
|
||||
}
|
||||
|
||||
static inline void dump_hmac(const char *str, const u8 *digest,
|
||||
unsigned int hmac_size)
|
||||
{
|
||||
if (str)
|
||||
pr_info("encrypted_key: %s", str);
|
||||
print_hex_dump(KERN_ERR, "hmac: ", DUMP_PREFIX_NONE, 32, 1, digest,
|
||||
hmac_size, 0);
|
||||
}
|
||||
#else
|
||||
static inline void dump_master_key(const u8 *master_key, size_t master_keylen)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_decrypted_data(struct encrypted_key_payload *epayload)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_encrypted_data(struct encrypted_key_payload *epayload,
|
||||
unsigned int encrypted_datalen)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_hmac(const char *str, const u8 *digest,
|
||||
unsigned int hmac_size)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
#ifndef __TRUSTED_KEY_H
|
||||
#define __TRUSTED_KEY_H
|
||||
|
||||
/* implementation specific TPM constants */
|
||||
#define MAX_PCRINFO_SIZE 64
|
||||
#define MAX_BUF_SIZE 512
|
||||
#define TPM_GETRANDOM_SIZE 14
|
||||
#define TPM_OSAP_SIZE 36
|
||||
#define TPM_OIAP_SIZE 10
|
||||
#define TPM_SEAL_SIZE 87
|
||||
#define TPM_UNSEAL_SIZE 104
|
||||
#define TPM_SIZE_OFFSET 2
|
||||
#define TPM_RETURN_OFFSET 6
|
||||
#define TPM_DATA_OFFSET 10
|
||||
|
||||
#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset]))
|
||||
#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset])
|
||||
#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset]))
|
||||
|
||||
struct tpm_buf {
|
||||
int len;
|
||||
unsigned char data[MAX_BUF_SIZE];
|
||||
};
|
||||
|
||||
#define INIT_BUF(tb) (tb->len = 0)
|
||||
|
||||
struct osapsess {
|
||||
uint32_t handle;
|
||||
unsigned char secret[SHA1_DIGEST_SIZE];
|
||||
unsigned char enonce[TPM_NONCE_SIZE];
|
||||
};
|
||||
|
||||
/* discrete values, but have to store in uint16_t for TPM use */
|
||||
enum {
|
||||
SEAL_keytype = 1,
|
||||
SRK_keytype = 4
|
||||
};
|
||||
|
||||
struct trusted_key_options {
|
||||
uint16_t keytype;
|
||||
uint32_t keyhandle;
|
||||
unsigned char keyauth[SHA1_DIGEST_SIZE];
|
||||
unsigned char blobauth[SHA1_DIGEST_SIZE];
|
||||
uint32_t pcrinfo_len;
|
||||
unsigned char pcrinfo[MAX_PCRINFO_SIZE];
|
||||
int pcrlock;
|
||||
};
|
||||
|
||||
#define TPM_DEBUG 0
|
||||
|
||||
#if TPM_DEBUG
|
||||
static inline void dump_options(struct trusted_key_options *o)
|
||||
{
|
||||
pr_info("trusted_key: sealing key type %d\n", o->keytype);
|
||||
pr_info("trusted_key: sealing key handle %0X\n", o->keyhandle);
|
||||
pr_info("trusted_key: pcrlock %d\n", o->pcrlock);
|
||||
pr_info("trusted_key: pcrinfo %d\n", o->pcrinfo_len);
|
||||
print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
|
||||
16, 1, o->pcrinfo, o->pcrinfo_len, 0);
|
||||
}
|
||||
|
||||
static inline void dump_payload(struct trusted_key_payload *p)
|
||||
{
|
||||
pr_info("trusted_key: key_len %d\n", p->key_len);
|
||||
print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE,
|
||||
16, 1, p->key, p->key_len, 0);
|
||||
pr_info("trusted_key: bloblen %d\n", p->blob_len);
|
||||
print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE,
|
||||
16, 1, p->blob, p->blob_len, 0);
|
||||
pr_info("trusted_key: migratable %d\n", p->migratable);
|
||||
}
|
||||
|
||||
static inline void dump_sess(struct osapsess *s)
|
||||
{
|
||||
print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->handle, 4, 0);
|
||||
pr_info("trusted-key: secret:\n");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
|
||||
pr_info("trusted-key: enonce:\n");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
|
||||
16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
|
||||
}
|
||||
|
||||
static inline void dump_tpm_buf(unsigned char *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
pr_info("\ntrusted-key: tpm buffer\n");
|
||||
len = LOAD32(buf, TPM_SIZE_OFFSET);
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
|
||||
}
|
||||
#else
|
||||
static inline void dump_options(struct trusted_key_options *o)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_payload(struct trusted_key_payload *p)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_sess(struct osapsess *s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void dump_tpm_buf(unsigned char *buf)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void store8(struct tpm_buf *buf, const unsigned char value)
|
||||
{
|
||||
buf->data[buf->len++] = value;
|
||||
}
|
||||
|
||||
static inline void store16(struct tpm_buf *buf, const uint16_t value)
|
||||
{
|
||||
*(uint16_t *) & buf->data[buf->len] = htons(value);
|
||||
buf->len += sizeof value;
|
||||
}
|
||||
|
||||
static inline void store32(struct tpm_buf *buf, const uint32_t value)
|
||||
{
|
||||
*(uint32_t *) & buf->data[buf->len] = htonl(value);
|
||||
buf->len += sizeof value;
|
||||
}
|
||||
|
||||
static inline void storebytes(struct tpm_buf *buf, const unsigned char *in,
|
||||
const int len)
|
||||
{
|
||||
memcpy(buf->data + buf->len, in, len);
|
||||
buf->len += len;
|
||||
}
|
||||
#endif
|
||||
@@ -2525,7 +2525,10 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
|
||||
sid = tsec->sid;
|
||||
newsid = tsec->create_sid;
|
||||
|
||||
if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
|
||||
if ((sbsec->flags & SE_SBINITIALIZED) &&
|
||||
(sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
|
||||
newsid = sbsec->mntpoint_sid;
|
||||
else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
|
||||
rc = security_transition_sid(sid, dsec->sid,
|
||||
inode_mode_to_security_class(inode->i_mode),
|
||||
&newsid);
|
||||
|
||||
@@ -142,7 +142,7 @@ struct security_class_mapping secclass_map[] = {
|
||||
"node_bind", "name_connect", NULL } },
|
||||
{ "memprotect", { "mmap_zero", NULL } },
|
||||
{ "peer", { "recv", NULL } },
|
||||
{ "capability2", { "mac_override", "mac_admin", NULL } },
|
||||
{ "capability2", { "mac_override", "mac_admin", "syslog", NULL } },
|
||||
{ "kernel_service", { "use_as_override", "create_files_as", NULL } },
|
||||
{ "tun_socket",
|
||||
{ COMMON_SOCK_PERMS, NULL } },
|
||||
|
||||
@@ -65,6 +65,8 @@ static struct nlmsg_perm nlmsg_route_perms[] =
|
||||
{ RTM_NEWADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_GETDCB, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
};
|
||||
|
||||
static struct nlmsg_perm nlmsg_firewall_perms[] =
|
||||
|
||||
+317
-344
File diff suppressed because it is too large
Load Diff
@@ -193,6 +193,7 @@ int cond_index_bool(void *key, void *datum, void *datap)
|
||||
{
|
||||
struct policydb *p;
|
||||
struct cond_bool_datum *booldatum;
|
||||
struct flex_array *fa;
|
||||
|
||||
booldatum = datum;
|
||||
p = datap;
|
||||
@@ -200,7 +201,10 @@ int cond_index_bool(void *key, void *datum, void *datap)
|
||||
if (!booldatum->value || booldatum->value > p->p_bools.nprim)
|
||||
return -EINVAL;
|
||||
|
||||
p->p_bool_val_to_name[booldatum->value - 1] = key;
|
||||
fa = p->sym_val_to_name[SYM_BOOLS];
|
||||
if (flex_array_put_ptr(fa, booldatum->value - 1, key,
|
||||
GFP_KERNEL | __GFP_ZERO))
|
||||
BUG();
|
||||
p->bool_val_to_struct[booldatum->value - 1] = booldatum;
|
||||
|
||||
return 0;
|
||||
|
||||
+13
-12
@@ -45,7 +45,7 @@ int mls_compute_context_len(struct context *context)
|
||||
len = 1; /* for the beginning ":" */
|
||||
for (l = 0; l < 2; l++) {
|
||||
int index_sens = context->range.level[l].sens;
|
||||
len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
|
||||
len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
|
||||
|
||||
/* categories */
|
||||
head = -2;
|
||||
@@ -55,17 +55,17 @@ int mls_compute_context_len(struct context *context)
|
||||
if (i - prev > 1) {
|
||||
/* one or more negative bits are skipped */
|
||||
if (head != prev) {
|
||||
nm = policydb.p_cat_val_to_name[prev];
|
||||
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||
len += strlen(nm) + 1;
|
||||
}
|
||||
nm = policydb.p_cat_val_to_name[i];
|
||||
nm = sym_name(&policydb, SYM_CATS, i);
|
||||
len += strlen(nm) + 1;
|
||||
head = i;
|
||||
}
|
||||
prev = i;
|
||||
}
|
||||
if (prev != head) {
|
||||
nm = policydb.p_cat_val_to_name[prev];
|
||||
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||
len += strlen(nm) + 1;
|
||||
}
|
||||
if (l == 0) {
|
||||
@@ -102,8 +102,8 @@ void mls_sid_to_context(struct context *context,
|
||||
scontextp++;
|
||||
|
||||
for (l = 0; l < 2; l++) {
|
||||
strcpy(scontextp,
|
||||
policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
|
||||
strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
|
||||
context->range.level[l].sens - 1));
|
||||
scontextp += strlen(scontextp);
|
||||
|
||||
/* categories */
|
||||
@@ -118,7 +118,7 @@ void mls_sid_to_context(struct context *context,
|
||||
*scontextp++ = '.';
|
||||
else
|
||||
*scontextp++ = ',';
|
||||
nm = policydb.p_cat_val_to_name[prev];
|
||||
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||
strcpy(scontextp, nm);
|
||||
scontextp += strlen(nm);
|
||||
}
|
||||
@@ -126,7 +126,7 @@ void mls_sid_to_context(struct context *context,
|
||||
*scontextp++ = ':';
|
||||
else
|
||||
*scontextp++ = ',';
|
||||
nm = policydb.p_cat_val_to_name[i];
|
||||
nm = sym_name(&policydb, SYM_CATS, i);
|
||||
strcpy(scontextp, nm);
|
||||
scontextp += strlen(nm);
|
||||
head = i;
|
||||
@@ -139,7 +139,7 @@ void mls_sid_to_context(struct context *context,
|
||||
*scontextp++ = '.';
|
||||
else
|
||||
*scontextp++ = ',';
|
||||
nm = policydb.p_cat_val_to_name[prev];
|
||||
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||
strcpy(scontextp, nm);
|
||||
scontextp += strlen(nm);
|
||||
}
|
||||
@@ -166,7 +166,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
|
||||
if (!l->sens || l->sens > p->p_levels.nprim)
|
||||
return 0;
|
||||
levdatum = hashtab_search(p->p_levels.table,
|
||||
p->p_sens_val_to_name[l->sens - 1]);
|
||||
sym_name(p, SYM_LEVELS, l->sens - 1));
|
||||
if (!levdatum)
|
||||
return 0;
|
||||
|
||||
@@ -482,7 +482,8 @@ int mls_convert_context(struct policydb *oldp,
|
||||
|
||||
for (l = 0; l < 2; l++) {
|
||||
levdatum = hashtab_search(newp->p_levels.table,
|
||||
oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
|
||||
sym_name(oldp, SYM_LEVELS,
|
||||
c->range.level[l].sens - 1));
|
||||
|
||||
if (!levdatum)
|
||||
return -EINVAL;
|
||||
@@ -493,7 +494,7 @@ int mls_convert_context(struct policydb *oldp,
|
||||
int rc;
|
||||
|
||||
catdatum = hashtab_search(newp->p_cats.table,
|
||||
oldp->p_cat_val_to_name[i]);
|
||||
sym_name(oldp, SYM_CATS, i));
|
||||
if (!catdatum)
|
||||
return -EINVAL;
|
||||
rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
|
||||
|
||||
+350
-349
File diff suppressed because it is too large
Load Diff
@@ -203,21 +203,13 @@ struct policydb {
|
||||
#define p_cats symtab[SYM_CATS]
|
||||
|
||||
/* symbol names indexed by (value - 1) */
|
||||
char **sym_val_to_name[SYM_NUM];
|
||||
#define p_common_val_to_name sym_val_to_name[SYM_COMMONS]
|
||||
#define p_class_val_to_name sym_val_to_name[SYM_CLASSES]
|
||||
#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
|
||||
#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
|
||||
#define p_user_val_to_name sym_val_to_name[SYM_USERS]
|
||||
#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
|
||||
#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
|
||||
#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
|
||||
struct flex_array *sym_val_to_name[SYM_NUM];
|
||||
|
||||
/* class, role, and user attributes indexed by (value - 1) */
|
||||
struct class_datum **class_val_to_struct;
|
||||
struct role_datum **role_val_to_struct;
|
||||
struct user_datum **user_val_to_struct;
|
||||
struct type_datum **type_val_to_struct;
|
||||
struct flex_array *type_val_to_struct_array;
|
||||
|
||||
/* type enforcement access vectors and transitions */
|
||||
struct avtab te_avtab;
|
||||
@@ -321,6 +313,13 @@ static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned int element_nr)
|
||||
{
|
||||
struct flex_array *fa = p->sym_val_to_name[sym_num];
|
||||
|
||||
return flex_array_get_ptr(fa, element_nr);
|
||||
}
|
||||
|
||||
extern u16 string_to_security_class(struct policydb *p, const char *name);
|
||||
extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
|
||||
|
||||
|
||||
+208
-215
File diff suppressed because it is too large
Load Diff
@@ -147,6 +147,17 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void sidtab_update_cache(struct sidtab *s, struct sidtab_node *n, int loc)
|
||||
{
|
||||
BUG_ON(loc >= SIDTAB_CACHE_LEN);
|
||||
|
||||
while (loc > 0) {
|
||||
s->cache[loc] = s->cache[loc - 1];
|
||||
loc--;
|
||||
}
|
||||
s->cache[0] = n;
|
||||
}
|
||||
|
||||
static inline u32 sidtab_search_context(struct sidtab *s,
|
||||
struct context *context)
|
||||
{
|
||||
@@ -156,14 +167,33 @@ static inline u32 sidtab_search_context(struct sidtab *s,
|
||||
for (i = 0; i < SIDTAB_SIZE; i++) {
|
||||
cur = s->htable[i];
|
||||
while (cur) {
|
||||
if (context_cmp(&cur->context, context))
|
||||
if (context_cmp(&cur->context, context)) {
|
||||
sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1);
|
||||
return cur->sid;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context)
|
||||
{
|
||||
int i;
|
||||
struct sidtab_node *node;
|
||||
|
||||
for (i = 0; i < SIDTAB_CACHE_LEN; i++) {
|
||||
node = s->cache[i];
|
||||
if (unlikely(!node))
|
||||
return 0;
|
||||
if (context_cmp(&node->context, context)) {
|
||||
sidtab_update_cache(s, node, i);
|
||||
return node->sid;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sidtab_context_to_sid(struct sidtab *s,
|
||||
struct context *context,
|
||||
u32 *out_sid)
|
||||
@@ -174,7 +204,9 @@ int sidtab_context_to_sid(struct sidtab *s,
|
||||
|
||||
*out_sid = SECSID_NULL;
|
||||
|
||||
sid = sidtab_search_context(s, context);
|
||||
sid = sidtab_search_cache(s, context);
|
||||
if (!sid)
|
||||
sid = sidtab_search_context(s, context);
|
||||
if (!sid) {
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
/* Rescan now that we hold the lock. */
|
||||
@@ -259,12 +291,15 @@ void sidtab_destroy(struct sidtab *s)
|
||||
void sidtab_set(struct sidtab *dst, struct sidtab *src)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&src->lock, flags);
|
||||
dst->htable = src->htable;
|
||||
dst->nel = src->nel;
|
||||
dst->next_sid = src->next_sid;
|
||||
dst->shutdown = 0;
|
||||
for (i = 0; i < SIDTAB_CACHE_LEN; i++)
|
||||
dst->cache[i] = NULL;
|
||||
spin_unlock_irqrestore(&src->lock, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ struct sidtab {
|
||||
unsigned int nel; /* number of elements */
|
||||
unsigned int next_sid; /* next SID to allocate */
|
||||
unsigned char shutdown;
|
||||
#define SIDTAB_CACHE_LEN 3
|
||||
struct sidtab_node *cache[SIDTAB_CACHE_LEN];
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
|
||||
@@ -51,11 +51,18 @@ struct socket_smack {
|
||||
*/
|
||||
struct inode_smack {
|
||||
char *smk_inode; /* label of the fso */
|
||||
char *smk_task; /* label of the task */
|
||||
struct mutex smk_lock; /* initialization lock */
|
||||
int smk_flags; /* smack inode flags */
|
||||
};
|
||||
|
||||
struct task_smack {
|
||||
char *smk_task; /* label used for access control */
|
||||
char *smk_forked; /* label when forked */
|
||||
};
|
||||
|
||||
#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
|
||||
#define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */
|
||||
|
||||
/*
|
||||
* A label access rule.
|
||||
@@ -160,6 +167,10 @@ struct smack_known {
|
||||
#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
|
||||
#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */
|
||||
|
||||
/*
|
||||
* Flag for transmute access
|
||||
*/
|
||||
#define MAY_TRANSMUTE 64
|
||||
/*
|
||||
* Just to make the common cases easier to deal with
|
||||
*/
|
||||
@@ -191,6 +202,7 @@ struct inode_smack *new_inode_smack(char *);
|
||||
/*
|
||||
* These functions are in smack_access.c
|
||||
*/
|
||||
int smk_access_entry(char *, char *);
|
||||
int smk_access(char *, char *, int, struct smk_audit_info *);
|
||||
int smk_curacc(char *, u32, struct smk_audit_info *);
|
||||
int smack_to_cipso(const char *, struct smack_cipso *);
|
||||
@@ -233,6 +245,15 @@ static inline void smack_catset_bit(int cat, char *catsetp)
|
||||
catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the directory transmuting?
|
||||
*/
|
||||
static inline int smk_inode_transmutable(const struct inode *isp)
|
||||
{
|
||||
struct inode_smack *sip = isp->i_security;
|
||||
return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Present a pointer to the smack label in an inode blob.
|
||||
*/
|
||||
@@ -242,6 +263,30 @@ static inline char *smk_of_inode(const struct inode *isp)
|
||||
return sip->smk_inode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Present a pointer to the smack label in an task blob.
|
||||
*/
|
||||
static inline char *smk_of_task(const struct task_smack *tsp)
|
||||
{
|
||||
return tsp->smk_task;
|
||||
}
|
||||
|
||||
/*
|
||||
* Present a pointer to the forked smack label in an task blob.
|
||||
*/
|
||||
static inline char *smk_of_forked(const struct task_smack *tsp)
|
||||
{
|
||||
return tsp->smk_forked;
|
||||
}
|
||||
|
||||
/*
|
||||
* Present a pointer to the smack label in the current task blob.
|
||||
*/
|
||||
static inline char *smk_of_current(void)
|
||||
{
|
||||
return smk_of_task(current_security());
|
||||
}
|
||||
|
||||
/*
|
||||
* logging functions
|
||||
*/
|
||||
|
||||
@@ -66,6 +66,46 @@ static u32 smack_next_secid = 10;
|
||||
*/
|
||||
int log_policy = SMACK_AUDIT_DENIED;
|
||||
|
||||
/**
|
||||
* smk_access_entry - look up matching access rule
|
||||
* @subject_label: a pointer to the subject's Smack label
|
||||
* @object_label: a pointer to the object's Smack label
|
||||
*
|
||||
* This function looks up the subject/object pair in the
|
||||
* access rule list and returns pointer to the matching rule if found,
|
||||
* NULL otherwise.
|
||||
*
|
||||
* NOTE:
|
||||
* Even though Smack labels are usually shared on smack_list
|
||||
* labels that come in off the network can't be imported
|
||||
* and added to the list for locking reasons.
|
||||
*
|
||||
* Therefore, it is necessary to check the contents of the labels,
|
||||
* not just the pointer values. Of course, in most cases the labels
|
||||
* will be on the list, so checking the pointers may be a worthwhile
|
||||
* optimization.
|
||||
*/
|
||||
int smk_access_entry(char *subject_label, char *object_label)
|
||||
{
|
||||
u32 may = MAY_NOT;
|
||||
struct smack_rule *srp;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(srp, &smack_rule_list, list) {
|
||||
if (srp->smk_subject == subject_label ||
|
||||
strcmp(srp->smk_subject, subject_label) == 0) {
|
||||
if (srp->smk_object == object_label ||
|
||||
strcmp(srp->smk_object, object_label) == 0) {
|
||||
may = srp->smk_access;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return may;
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_access - determine if a subject has a specific access to an object
|
||||
* @subject_label: a pointer to the subject's Smack label
|
||||
@@ -90,7 +130,6 @@ int smk_access(char *subject_label, char *object_label, int request,
|
||||
struct smk_audit_info *a)
|
||||
{
|
||||
u32 may = MAY_NOT;
|
||||
struct smack_rule *srp;
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
@@ -144,18 +183,7 @@ int smk_access(char *subject_label, char *object_label, int request,
|
||||
* access (e.g. read is included in readwrite) it's
|
||||
* good.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(srp, &smack_rule_list, list) {
|
||||
if (srp->smk_subject == subject_label ||
|
||||
strcmp(srp->smk_subject, subject_label) == 0) {
|
||||
if (srp->smk_object == object_label ||
|
||||
strcmp(srp->smk_object, object_label) == 0) {
|
||||
may = srp->smk_access;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
may = smk_access_entry(subject_label, object_label);
|
||||
/*
|
||||
* This is a bit map operation.
|
||||
*/
|
||||
@@ -185,7 +213,7 @@ out_audit:
|
||||
int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
|
||||
{
|
||||
int rc;
|
||||
char *sp = current_security();
|
||||
char *sp = smk_of_current();
|
||||
|
||||
rc = smk_access(sp, obj_label, mode, NULL);
|
||||
if (rc == 0)
|
||||
@@ -196,7 +224,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
|
||||
* only one that gets privilege and current does not
|
||||
* have that label.
|
||||
*/
|
||||
if (smack_onlycap != NULL && smack_onlycap != current->cred->security)
|
||||
if (smack_onlycap != NULL && smack_onlycap != sp)
|
||||
goto out_audit;
|
||||
|
||||
if (capable(CAP_MAC_OVERRIDE))
|
||||
|
||||
+246
-108
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user