Commit ca661c5e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'selinux-pr-20240312' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux

Pull selinux updates from Paul Moore:
 "Really only a few notable changes:

   - Continue the coding style/formatting fixup work

     This is the bulk of the diffstat in this pull request, with the
     focus this time around being the security/selinux/ss directory.

     We've only got a couple of files left to cleanup and once we're
     done with that we can start enabling some automatic style
     verfication and introduce tooling to help new folks format their
     code correctly.

   - Don't restrict xattr copy-up when SELinux policy is not loaded

     This helps systems that use overlayfs, or similar filesystems,
     preserve their SELinux labels during early boot when the SELinux
     policy has yet to be loaded.

   - Reduce the work we do during inode initialization time

     This isn't likely to show up in any benchmark results, but we
     removed an unnecessary SELinux object class lookup/calculation
     during inode initialization.

   - Correct the return values in selinux_socket_getpeersec_dgram()

     We had some inconsistencies with respect to our return values
     across selinux_socket_getpeersec_dgram() and
     selinux_socket_getpeersec_stream().

     This provides a more uniform set of error codes across the two
     functions and should help make it easier for users to identify
     the source of a failure"

* tag 'selinux-pr-20240312' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: (24 commits)
  selinux: fix style issues in security/selinux/ss/symtab.c
  selinux: fix style issues in security/selinux/ss/symtab.h
  selinux: fix style issues in security/selinux/ss/sidtab.c
  selinux: fix style issues in security/selinux/ss/sidtab.h
  selinux: fix style issues in security/selinux/ss/services.h
  selinux: fix style issues in security/selinux/ss/policydb.c
  selinux: fix style issues in security/selinux/ss/policydb.h
  selinux: fix style issues in security/selinux/ss/mls_types.h
  selinux: fix style issues in security/selinux/ss/mls.c
  selinux: fix style issues in security/selinux/ss/mls.h
  selinux: fix style issues in security/selinux/ss/hashtab.c
  selinux: fix style issues in security/selinux/ss/hashtab.h
  selinux: fix style issues in security/selinux/ss/ebitmap.c
  selinux: fix style issues in security/selinux/ss/ebitmap.h
  selinux: fix style issues in security/selinux/ss/context.h
  selinux: fix style issues in security/selinux/ss/context.h
  selinux: fix style issues in security/selinux/ss/constraint.h
  selinux: fix style issues in security/selinux/ss/conditional.c
  selinux: fix style issues in security/selinux/ss/conditional.h
  selinux: fix style issues in security/selinux/ss/avtab.c
  ...
parents 9187210e a1fc7934
...@@ -2920,23 +2920,22 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, ...@@ -2920,23 +2920,22 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count); struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
u32 newsid, clen; u32 newsid, clen;
u16 newsclass;
int rc; int rc;
char *context; char *context;
sbsec = selinux_superblock(dir->i_sb); sbsec = selinux_superblock(dir->i_sb);
newsid = tsec->create_sid; newsid = tsec->create_sid;
newsclass = inode_mode_to_security_class(inode->i_mode);
rc = selinux_determine_inode_label(tsec, dir, qstr, rc = selinux_determine_inode_label(tsec, dir, qstr, newsclass, &newsid);
inode_mode_to_security_class(inode->i_mode),
&newsid);
if (rc) if (rc)
return rc; return rc;
/* Possibly defer initialization to selinux_complete_init. */ /* Possibly defer initialization to selinux_complete_init. */
if (sbsec->flags & SE_SBINITIALIZED) { if (sbsec->flags & SE_SBINITIALIZED) {
struct inode_security_struct *isec = selinux_inode(inode); struct inode_security_struct *isec = selinux_inode(inode);
isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sclass = newsclass;
isec->sid = newsid; isec->sid = newsid;
isec->initialized = LABEL_INITIALIZED; isec->initialized = LABEL_INITIALIZED;
} }
...@@ -3534,9 +3533,10 @@ static int selinux_inode_copy_up_xattr(const char *name) ...@@ -3534,9 +3533,10 @@ static int selinux_inode_copy_up_xattr(const char *name)
{ {
/* The copy_up hook above sets the initial context on an inode, but we /* The copy_up hook above sets the initial context on an inode, but we
* don't then want to overwrite it by blindly copying all the lower * don't then want to overwrite it by blindly copying all the lower
* xattrs up. Instead, we have to filter out SELinux-related xattrs. * xattrs up. Instead, filter out SELinux-related xattrs following
* policy load.
*/ */
if (strcmp(name, XATTR_NAME_SELINUX) == 0) if (selinux_initialized() && strcmp(name, XATTR_NAME_SELINUX) == 0)
return 1; /* Discard */ return 1; /* Discard */
/* /*
* Any other attribute apart from SELINUX is not claimed, supported * Any other attribute apart from SELINUX is not claimed, supported
...@@ -5194,11 +5194,11 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, ...@@ -5194,11 +5194,11 @@ static int selinux_socket_getpeersec_stream(struct socket *sock,
return err; return err;
} }
static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) static int selinux_socket_getpeersec_dgram(struct socket *sock,
struct sk_buff *skb, u32 *secid)
{ {
u32 peer_secid = SECSID_NULL; u32 peer_secid = SECSID_NULL;
u16 family; u16 family;
struct inode_security_struct *isec;
if (skb && skb->protocol == htons(ETH_P_IP)) if (skb && skb->protocol == htons(ETH_P_IP))
family = PF_INET; family = PF_INET;
...@@ -5206,19 +5206,21 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * ...@@ -5206,19 +5206,21 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
family = PF_INET6; family = PF_INET6;
else if (sock) else if (sock)
family = sock->sk->sk_family; family = sock->sk->sk_family;
else else {
goto out; *secid = SECSID_NULL;
return -EINVAL;
}
if (sock && family == PF_UNIX) { if (sock && family == PF_UNIX) {
struct inode_security_struct *isec;
isec = inode_security_novalidate(SOCK_INODE(sock)); isec = inode_security_novalidate(SOCK_INODE(sock));
peer_secid = isec->sid; peer_secid = isec->sid;
} else if (skb) } else if (skb)
selinux_skb_peerlbl_sid(skb, family, &peer_secid); selinux_skb_peerlbl_sid(skb, family, &peer_secid);
out:
*secid = peer_secid; *secid = peer_secid;
if (peer_secid == SECSID_NULL) if (peer_secid == SECSID_NULL)
return -EINVAL; return -ENOPROTOOPT;
return 0; return 0;
} }
......
/* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Implementation of the access vector table type. * Implementation of the access vector table type.
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> /* Updated: Frank Mayer <mayerf@tresys.com> and
* * Karl MacMillan <kmacmillan@tresys.com>
* Added conditional policy language extensions * Added conditional policy language extensions
* * Copyright (C) 2003 Tresys Technology, LLC
* Copyright (C) 2003 Tresys Technology, LLC
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
* *
* Updated: Yuichi Nakamura <ynakam@hitachisoft.jp> * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
* Tuned number of hash slots for avtab to reduce memory usage * Tuned number of hash slots for avtab to reduce memory usage
*/ */
#include <linux/bitops.h> #include <linux/bitops.h>
...@@ -36,19 +33,20 @@ static inline u32 avtab_hash(const struct avtab_key *keyp, u32 mask) ...@@ -36,19 +33,20 @@ static inline u32 avtab_hash(const struct avtab_key *keyp, u32 mask)
static const u32 c2 = 0x1b873593; static const u32 c2 = 0x1b873593;
static const u32 r1 = 15; static const u32 r1 = 15;
static const u32 r2 = 13; static const u32 r2 = 13;
static const u32 m = 5; static const u32 m = 5;
static const u32 n = 0xe6546b64; static const u32 n = 0xe6546b64;
u32 hash = 0; u32 hash = 0;
#define mix(input) do { \ #define mix(input) \
u32 v = input; \ do { \
v *= c1; \ u32 v = input; \
v = (v << r1) | (v >> (32 - r1)); \ v *= c1; \
v *= c2; \ v = (v << r1) | (v >> (32 - r1)); \
hash ^= v; \ v *= c2; \
hash ^= v; \
hash = (hash << r2) | (hash >> (32 - r2)); \ hash = (hash << r2) | (hash >> (32 - r2)); \
hash = hash * m + n; \ hash = hash * m + n; \
} while (0) } while (0)
mix(keyp->target_class); mix(keyp->target_class);
...@@ -66,9 +64,10 @@ static inline u32 avtab_hash(const struct avtab_key *keyp, u32 mask) ...@@ -66,9 +64,10 @@ static inline u32 avtab_hash(const struct avtab_key *keyp, u32 mask)
return hash & mask; return hash & mask;
} }
static struct avtab_node* static struct avtab_node *avtab_insert_node(struct avtab *h,
avtab_insert_node(struct avtab *h, struct avtab_node **dst, struct avtab_node **dst,
const struct avtab_key *key, const struct avtab_datum *datum) const struct avtab_key *key,
const struct avtab_datum *datum)
{ {
struct avtab_node *newnode; struct avtab_node *newnode;
struct avtab_extended_perms *xperms; struct avtab_extended_perms *xperms;
...@@ -99,7 +98,7 @@ avtab_insert_node(struct avtab *h, struct avtab_node **dst, ...@@ -99,7 +98,7 @@ avtab_insert_node(struct avtab *h, struct avtab_node **dst,
static int avtab_node_cmp(const struct avtab_key *key1, static int avtab_node_cmp(const struct avtab_key *key1,
const struct avtab_key *key2) const struct avtab_key *key2)
{ {
u16 specified = key1->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); u16 specified = key1->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
if (key1->source_type == key2->source_type && if (key1->source_type == key2->source_type &&
key1->target_type == key2->target_type && key1->target_type == key2->target_type &&
...@@ -129,8 +128,7 @@ static int avtab_insert(struct avtab *h, const struct avtab_key *key, ...@@ -129,8 +128,7 @@ static int avtab_insert(struct avtab *h, const struct avtab_key *key,
return -EINVAL; return -EINVAL;
hvalue = avtab_hash(key, h->mask); hvalue = avtab_hash(key, h->mask);
for (prev = NULL, cur = h->htable[hvalue]; for (prev = NULL, cur = h->htable[hvalue]; cur;
cur;
prev = cur, cur = cur->next) { prev = cur, cur = cur->next) {
cmp = avtab_node_cmp(key, &cur->key); cmp = avtab_node_cmp(key, &cur->key);
/* extended perms may not be unique */ /* extended perms may not be unique */
...@@ -163,8 +161,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, ...@@ -163,8 +161,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h,
if (!h || !h->nslot || h->nel == U32_MAX) if (!h || !h->nslot || h->nel == U32_MAX)
return NULL; return NULL;
hvalue = avtab_hash(key, h->mask); hvalue = avtab_hash(key, h->mask);
for (prev = NULL, cur = h->htable[hvalue]; for (prev = NULL, cur = h->htable[hvalue]; cur;
cur;
prev = cur, cur = cur->next) { prev = cur, cur = cur->next) {
cmp = avtab_node_cmp(key, &cur->key); cmp = avtab_node_cmp(key, &cur->key);
if (cmp <= 0) if (cmp <= 0)
...@@ -188,8 +185,7 @@ struct avtab_node *avtab_search_node(struct avtab *h, ...@@ -188,8 +185,7 @@ struct avtab_node *avtab_search_node(struct avtab *h,
return NULL; return NULL;
hvalue = avtab_hash(key, h->mask); hvalue = avtab_hash(key, h->mask);
for (cur = h->htable[hvalue]; cur; for (cur = h->htable[hvalue]; cur; cur = cur->next) {
cur = cur->next) {
cmp = avtab_node_cmp(key, &cur->key); cmp = avtab_node_cmp(key, &cur->key);
if (cmp == 0) if (cmp == 0)
return cur; return cur;
...@@ -199,8 +195,8 @@ struct avtab_node *avtab_search_node(struct avtab *h, ...@@ -199,8 +195,8 @@ struct avtab_node *avtab_search_node(struct avtab *h,
return NULL; return NULL;
} }
struct avtab_node* struct avtab_node *avtab_search_node_next(struct avtab_node *node,
avtab_search_node_next(struct avtab_node *node, u16 specified) u16 specified)
{ {
struct avtab_key tmp_key; struct avtab_key tmp_key;
struct avtab_node *cur; struct avtab_node *cur;
...@@ -314,17 +310,19 @@ void avtab_hash_eval(struct avtab *h, const char *tag) ...@@ -314,17 +310,19 @@ void avtab_hash_eval(struct avtab *h, const char *tag)
if (chain_len > max_chain_len) if (chain_len > max_chain_len)
max_chain_len = chain_len; max_chain_len = chain_len;
chain2_len_sum += (unsigned long long)chain_len * chain_len; chain2_len_sum +=
(unsigned long long)chain_len * chain_len;
} }
} }
pr_debug("SELinux: %s: %d entries and %d/%d buckets used, " pr_debug("SELinux: %s: %d entries and %d/%d buckets used, "
"longest chain length %d, sum of chain length^2 %llu\n", "longest chain length %d, sum of chain length^2 %llu\n",
tag, h->nel, slots_used, h->nslot, max_chain_len, tag, h->nel, slots_used, h->nslot, max_chain_len,
chain2_len_sum); chain2_len_sum);
} }
#endif /* CONFIG_SECURITY_SELINUX_DEBUG */ #endif /* CONFIG_SECURITY_SELINUX_DEBUG */
/* clang-format off */
static const uint16_t spec_order[] = { static const uint16_t spec_order[] = {
AVTAB_ALLOWED, AVTAB_ALLOWED,
AVTAB_AUDITDENY, AVTAB_AUDITDENY,
...@@ -336,6 +334,7 @@ static const uint16_t spec_order[] = { ...@@ -336,6 +334,7 @@ static const uint16_t spec_order[] = {
AVTAB_XPERMS_AUDITALLOW, AVTAB_XPERMS_AUDITALLOW,
AVTAB_XPERMS_DONTAUDIT AVTAB_XPERMS_DONTAUDIT
}; };
/* clang-format on */
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
int (*insertf)(struct avtab *a, const struct avtab_key *k, int (*insertf)(struct avtab *a, const struct avtab_key *k,
...@@ -365,9 +364,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -365,9 +364,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
if (items2 > ARRAY_SIZE(buf32)) { if (items2 > ARRAY_SIZE(buf32)) {
pr_err("SELinux: avtab: entry overflow\n"); pr_err("SELinux: avtab: entry overflow\n");
return -EINVAL; return -EINVAL;
} }
rc = next_entry(buf32, fp, sizeof(u32)*items2); rc = next_entry(buf32, fp, sizeof(u32) * items2);
if (rc) { if (rc) {
pr_err("SELinux: avtab: truncated entry\n"); pr_err("SELinux: avtab: truncated entry\n");
return rc; return rc;
...@@ -400,8 +398,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -400,8 +398,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
pr_err("SELinux: avtab: null entry\n"); pr_err("SELinux: avtab: null entry\n");
return -EINVAL; return -EINVAL;
} }
if ((val & AVTAB_AV) && if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) {
(val & AVTAB_TYPE)) {
pr_err("SELinux: avtab: entry has both access vectors and types\n"); pr_err("SELinux: avtab: entry has both access vectors and types\n");
return -EINVAL; return -EINVAL;
} }
...@@ -428,7 +425,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -428,7 +425,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
return 0; return 0;
} }
rc = next_entry(buf16, fp, sizeof(u16)*4); rc = next_entry(buf16, fp, sizeof(u16) * 4);
if (rc) { if (rc) {
pr_err("SELinux: avtab: truncated entry\n"); pr_err("SELinux: avtab: truncated entry\n");
return rc; return rc;
...@@ -454,10 +451,11 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -454,10 +451,11 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
} }
if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) && if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) &&
(key.specified & AVTAB_XPERMS)) { (key.specified & AVTAB_XPERMS)) {
pr_err("SELinux: avtab: policy version %u does not " pr_err("SELinux: avtab: policy version %u does not "
"support extended permissions rules and one " "support extended permissions rules and one "
"was specified\n", vers); "was specified\n",
vers);
return -EINVAL; return -EINVAL;
} else if (key.specified & AVTAB_XPERMS) { } else if (key.specified & AVTAB_XPERMS) {
memset(&xperms, 0, sizeof(struct avtab_extended_perms)); memset(&xperms, 0, sizeof(struct avtab_extended_perms));
...@@ -471,7 +469,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -471,7 +469,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
pr_err("SELinux: avtab: truncated entry\n"); pr_err("SELinux: avtab: truncated entry\n");
return rc; return rc;
} }
rc = next_entry(buf32, fp, sizeof(u32)*ARRAY_SIZE(xperms.perms.p)); rc = next_entry(buf32, fp,
sizeof(u32) * ARRAY_SIZE(xperms.perms.p));
if (rc) { if (rc) {
pr_err("SELinux: avtab: truncated entry\n"); pr_err("SELinux: avtab: truncated entry\n");
return rc; return rc;
...@@ -507,7 +506,6 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) ...@@ -507,7 +506,6 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
__le32 buf[1]; __le32 buf[1];
u32 nel, i; u32 nel, i;
rc = next_entry(buf, fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (rc < 0) { if (rc < 0) {
pr_err("SELinux: avtab: truncated table\n"); pr_err("SELinux: avtab: truncated table\n");
...@@ -561,7 +559,8 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp) ...@@ -561,7 +559,8 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp)
return rc; return rc;
if (cur->key.specified & AVTAB_XPERMS) { if (cur->key.specified & AVTAB_XPERMS) {
rc = put_entry(&cur->datum.u.xperms->specified, sizeof(u8), 1, fp); rc = put_entry(&cur->datum.u.xperms->specified, sizeof(u8), 1,
fp);
if (rc) if (rc)
return rc; return rc;
rc = put_entry(&cur->datum.u.xperms->driver, sizeof(u8), 1, fp); rc = put_entry(&cur->datum.u.xperms->driver, sizeof(u8), 1, fp);
...@@ -570,7 +569,7 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp) ...@@ -570,7 +569,7 @@ int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp)
for (i = 0; i < ARRAY_SIZE(cur->datum.u.xperms->perms.p); i++) for (i = 0; i < ARRAY_SIZE(cur->datum.u.xperms->perms.p); i++)
buf32[i] = cpu_to_le32(cur->datum.u.xperms->perms.p[i]); buf32[i] = cpu_to_le32(cur->datum.u.xperms->perms.p[i]);
rc = put_entry(buf32, sizeof(u32), rc = put_entry(buf32, sizeof(u32),
ARRAY_SIZE(cur->datum.u.xperms->perms.p), fp); ARRAY_SIZE(cur->datum.u.xperms->perms.p), fp);
} else { } else {
buf32[0] = cpu_to_le32(cur->datum.u.data); buf32[0] = cpu_to_le32(cur->datum.u.data);
rc = put_entry(buf32, sizeof(u32), 1, fp); rc = put_entry(buf32, sizeof(u32), 1, fp);
...@@ -593,8 +592,7 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) ...@@ -593,8 +592,7 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
return rc; return rc;
for (i = 0; i < a->nslot; i++) { for (i = 0; i < a->nslot; i++) {
for (cur = a->htable[i]; cur; for (cur = a->htable[i]; cur; cur = cur->next) {
cur = cur->next) {
rc = avtab_write_item(p, cur, fp); rc = avtab_write_item(p, cur, fp);
if (rc) if (rc)
return rc; return rc;
...@@ -606,10 +604,9 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) ...@@ -606,10 +604,9 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
void __init avtab_cache_init(void) void __init avtab_cache_init(void)
{ {
avtab_node_cachep = kmem_cache_create("avtab_node", avtab_node_cachep = kmem_cache_create(
sizeof(struct avtab_node), "avtab_node", sizeof(struct avtab_node), 0, SLAB_PANIC, NULL);
0, SLAB_PANIC, NULL); avtab_xperms_cachep = kmem_cache_create(
avtab_xperms_cachep = kmem_cache_create("avtab_extended_perms", "avtab_extended_perms", sizeof(struct avtab_extended_perms), 0,
sizeof(struct avtab_extended_perms), SLAB_PANIC, NULL);
0, SLAB_PANIC, NULL);
} }
...@@ -9,42 +9,42 @@ ...@@ -9,42 +9,42 @@
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> /* Updated: Frank Mayer <mayerf@tresys.com> and
* * Karl MacMillan <kmacmillan@tresys.com>
* Added conditional policy language extensions * Added conditional policy language extensions
* * Copyright (C) 2003 Tresys Technology, LLC
* Copyright (C) 2003 Tresys Technology, LLC
* *
* Updated: Yuichi Nakamura <ynakam@hitachisoft.jp> * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
* Tuned number of hash slots for avtab to reduce memory usage * Tuned number of hash slots for avtab to reduce memory usage
*/ */
#ifndef _SS_AVTAB_H_ #ifndef _SS_AVTAB_H_
#define _SS_AVTAB_H_ #define _SS_AVTAB_H_
#include "security.h" #include "security.h"
struct avtab_key { struct avtab_key {
u16 source_type; /* source type */ u16 source_type; /* source type */
u16 target_type; /* target type */ u16 target_type; /* target type */
u16 target_class; /* target object class */ u16 target_class; /* target object class */
#define AVTAB_ALLOWED 0x0001 #define AVTAB_ALLOWED 0x0001
#define AVTAB_AUDITALLOW 0x0002 #define AVTAB_AUDITALLOW 0x0002
#define AVTAB_AUDITDENY 0x0004 #define AVTAB_AUDITDENY 0x0004
#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) #define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
#define AVTAB_TRANSITION 0x0010 #define AVTAB_TRANSITION 0x0010
#define AVTAB_MEMBER 0x0020 #define AVTAB_MEMBER 0x0020
#define AVTAB_CHANGE 0x0040 #define AVTAB_CHANGE 0x0040
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
/* extended permissions */ /* extended permissions */
#define AVTAB_XPERMS_ALLOWED 0x0100 #define AVTAB_XPERMS_ALLOWED 0x0100
#define AVTAB_XPERMS_AUDITALLOW 0x0200 #define AVTAB_XPERMS_AUDITALLOW 0x0200
#define AVTAB_XPERMS_DONTAUDIT 0x0400 #define AVTAB_XPERMS_DONTAUDIT 0x0400
#define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | \ #define AVTAB_XPERMS \
AVTAB_XPERMS_AUDITALLOW | \ (AVTAB_XPERMS_ALLOWED | AVTAB_XPERMS_AUDITALLOW | \
AVTAB_XPERMS_DONTAUDIT) AVTAB_XPERMS_DONTAUDIT)
#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ #define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
u16 specified; /* what field is specified */ u16 specified; /* what field is specified */
}; };
/* /*
...@@ -53,8 +53,8 @@ struct avtab_key { ...@@ -53,8 +53,8 @@ struct avtab_key {
*/ */
struct avtab_extended_perms { struct avtab_extended_perms {
/* These are not flags. All 256 values may be used */ /* These are not flags. All 256 values may be used */
#define AVTAB_XPERMS_IOCTLFUNCTION 0x01 #define AVTAB_XPERMS_IOCTLFUNCTION 0x01
#define AVTAB_XPERMS_IOCTLDRIVER 0x02 #define AVTAB_XPERMS_IOCTLDRIVER 0x02
/* extension of the avtab_key specified */ /* extension of the avtab_key specified */
u8 specified; /* ioctl, netfilter, ... */ u8 specified; /* ioctl, netfilter, ... */
/* /*
...@@ -82,9 +82,9 @@ struct avtab_node { ...@@ -82,9 +82,9 @@ struct avtab_node {
struct avtab { struct avtab {
struct avtab_node **htable; struct avtab_node **htable;
u32 nel; /* number of elements */ u32 nel; /* number of elements */
u32 nslot; /* number of hash slots */ u32 nslot; /* number of hash slots */
u32 mask; /* mask to compute hash func */ u32 mask; /* mask to compute hash func */
}; };
void avtab_init(struct avtab *h); void avtab_init(struct avtab *h);
...@@ -92,6 +92,9 @@ int avtab_alloc(struct avtab *, u32); ...@@ -92,6 +92,9 @@ int avtab_alloc(struct avtab *, u32);
int avtab_alloc_dup(struct avtab *new, const struct avtab *orig); int avtab_alloc_dup(struct avtab *new, const struct avtab *orig);
void avtab_destroy(struct avtab *h); void avtab_destroy(struct avtab *h);
#define MAX_AVTAB_HASH_BITS 16
#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
#ifdef CONFIG_SECURITY_SELINUX_DEBUG #ifdef CONFIG_SECURITY_SELINUX_DEBUG
void avtab_hash_eval(struct avtab *h, const char *tag); void avtab_hash_eval(struct avtab *h, const char *tag);
#else #else
...@@ -107,7 +110,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, ...@@ -107,7 +110,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
void *p); void *p);
int avtab_read(struct avtab *a, void *fp, struct policydb *pol); int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp); int avtab_write_item(struct policydb *p, const struct avtab_node *cur,
void *fp);
int avtab_write(struct policydb *p, struct avtab *a, void *fp); int avtab_write(struct policydb *p, struct avtab *a, void *fp);
struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_node *avtab_insert_nonunique(struct avtab *h,
...@@ -116,11 +120,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h, ...@@ -116,11 +120,7 @@ struct avtab_node *avtab_insert_nonunique(struct avtab *h,
struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_node *avtab_search_node(struct avtab *h,
const struct avtab_key *key); const struct avtab_key *key);
struct avtab_node *avtab_search_node_next(struct avtab_node *node,
u16 specified);
struct avtab_node *avtab_search_node_next(struct avtab_node *node, u16 specified); #endif /* _SS_AVTAB_H_ */
#define MAX_AVTAB_HASH_BITS 16
#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
#endif /* _SS_AVTAB_H_ */
// SPDX-License-Identifier: GPL-2.0-only /* SPDX-License-Identifier: GPL-2.0-only */
/* Authors: Karl MacMillan <kmacmillan@tresys.com> /* Authors: Karl MacMillan <kmacmillan@tresys.com>
* Frank Mayer <mayerf@tresys.com> * Frank Mayer <mayerf@tresys.com>
* * Copyright (C) 2003 - 2004 Tresys Technology, LLC
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -166,9 +165,8 @@ void cond_policydb_destroy(struct policydb *p) ...@@ -166,9 +165,8 @@ void cond_policydb_destroy(struct policydb *p)
int cond_init_bool_indexes(struct policydb *p) int cond_init_bool_indexes(struct policydb *p)
{ {
kfree(p->bool_val_to_struct); kfree(p->bool_val_to_struct);
p->bool_val_to_struct = kmalloc_array(p->p_bools.nprim, p->bool_val_to_struct = kmalloc_array(
sizeof(*p->bool_val_to_struct), p->p_bools.nprim, sizeof(*p->bool_val_to_struct), GFP_KERNEL);
GFP_KERNEL);
if (!p->bool_val_to_struct) if (!p->bool_val_to_struct)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
...@@ -287,7 +285,8 @@ static int cond_insertf(struct avtab *a, const struct avtab_key *k, ...@@ -287,7 +285,8 @@ static int cond_insertf(struct avtab *a, const struct avtab_key *k,
if (other) { if (other) {
node_ptr = avtab_search_node(&p->te_cond_avtab, k); node_ptr = avtab_search_node(&p->te_cond_avtab, k);
if (node_ptr) { if (node_ptr) {
if (avtab_search_node_next(node_ptr, k->specified)) { if (avtab_search_node_next(node_ptr,
k->specified)) {
pr_err("SELinux: too many conflicting type rules.\n"); pr_err("SELinux: too many conflicting type rules.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -478,8 +477,8 @@ int cond_write_bool(void *vkey, void *datum, void *ptr) ...@@ -478,8 +477,8 @@ int cond_write_bool(void *vkey, void *datum, void *ptr)
* the conditional. This means that the avtab with the conditional * the conditional. This means that the avtab with the conditional
* rules will not be saved but will be rebuilt on policy load. * rules will not be saved but will be rebuilt on policy load.
*/ */
static int cond_write_av_list(struct policydb *p, static int cond_write_av_list(struct policydb *p, struct cond_av_list *list,
struct cond_av_list *list, struct policy_file *fp) struct policy_file *fp)
{ {
__le32 buf[1]; __le32 buf[1];
u32 i; u32 i;
...@@ -500,7 +499,7 @@ static int cond_write_av_list(struct policydb *p, ...@@ -500,7 +499,7 @@ static int cond_write_av_list(struct policydb *p,
} }
static int cond_write_node(struct policydb *p, struct cond_node *node, static int cond_write_node(struct policydb *p, struct cond_node *node,
struct policy_file *fp) struct policy_file *fp)
{ {
__le32 buf[2]; __le32 buf[2];
int rc; int rc;
...@@ -555,7 +554,7 @@ int cond_write_list(struct policydb *p, void *fp) ...@@ -555,7 +554,7 @@ int cond_write_list(struct policydb *p, void *fp)
} }
void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
struct extended_perms_decision *xpermd) struct extended_perms_decision *xpermd)
{ {
struct avtab_node *node; struct avtab_node *node;
...@@ -563,7 +562,7 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, ...@@ -563,7 +562,7 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
return; return;
for (node = avtab_search_node(ctab, key); node; for (node = avtab_search_node(ctab, key); node;
node = avtab_search_node_next(node, key->specified)) { node = avtab_search_node_next(node, key->specified)) {
if (node->key.specified & AVTAB_ENABLED) if (node->key.specified & AVTAB_ENABLED)
services_compute_xperms_decision(xpermd, node); services_compute_xperms_decision(xpermd, node);
} }
...@@ -572,7 +571,7 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, ...@@ -572,7 +571,7 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
* av table, and if so, add them to the result * av table, and if so, add them to the result
*/ */
void cond_compute_av(struct avtab *ctab, struct avtab_key *key, void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
struct av_decision *avd, struct extended_perms *xperms) struct av_decision *avd, struct extended_perms *xperms)
{ {
struct avtab_node *node; struct avtab_node *node;
...@@ -580,30 +579,29 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, ...@@ -580,30 +579,29 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
return; return;
for (node = avtab_search_node(ctab, key); node; for (node = avtab_search_node(ctab, key); node;
node = avtab_search_node_next(node, key->specified)) { node = avtab_search_node_next(node, key->specified)) {
if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == if ((u16)(AVTAB_ALLOWED | AVTAB_ENABLED) ==
(node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED)))
avd->allowed |= node->datum.u.data; avd->allowed |= node->datum.u.data;
if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) == if ((u16)(AVTAB_AUDITDENY | AVTAB_ENABLED) ==
(node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED)))
/* Since a '0' in an auditdeny mask represents a /* Since a '0' in an auditdeny mask represents a
* permission we do NOT want to audit (dontaudit), we use * permission we do NOT want to audit (dontaudit), we use
* the '&' operand to ensure that all '0's in the mask * the '&' operand to ensure that all '0's in the mask
* are retained (much unlike the allow and auditallow cases). * are retained (much unlike the allow and auditallow cases).
*/ */
avd->auditdeny &= node->datum.u.data; avd->auditdeny &= node->datum.u.data;
if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) == if ((u16)(AVTAB_AUDITALLOW | AVTAB_ENABLED) ==
(node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED)))
avd->auditallow |= node->datum.u.data; avd->auditallow |= node->datum.u.data;
if (xperms && (node->key.specified & AVTAB_ENABLED) && if (xperms && (node->key.specified & AVTAB_ENABLED) &&
(node->key.specified & AVTAB_XPERMS)) (node->key.specified & AVTAB_XPERMS))
services_compute_xperms_drivers(xperms, node); services_compute_xperms_drivers(xperms, node);
} }
} }
static int cond_dup_av_list(struct cond_av_list *new, static int cond_dup_av_list(struct cond_av_list *new, struct cond_av_list *orig,
struct cond_av_list *orig, struct avtab *avtab)
struct avtab *avtab)
{ {
u32 i; u32 i;
...@@ -614,9 +612,8 @@ static int cond_dup_av_list(struct cond_av_list *new, ...@@ -614,9 +612,8 @@ static int cond_dup_av_list(struct cond_av_list *new,
return -ENOMEM; return -ENOMEM;
for (i = 0; i < orig->len; i++) { for (i = 0; i < orig->len; i++) {
new->nodes[i] = avtab_insert_nonunique(avtab, new->nodes[i] = avtab_insert_nonunique(
&orig->nodes[i]->key, avtab, &orig->nodes[i]->key, &orig->nodes[i]->datum);
&orig->nodes[i]->datum);
if (!new->nodes[i]) if (!new->nodes[i])
return -ENOMEM; return -ENOMEM;
new->len++; new->len++;
...@@ -637,8 +634,7 @@ static int duplicate_policydb_cond_list(struct policydb *newp, ...@@ -637,8 +634,7 @@ static int duplicate_policydb_cond_list(struct policydb *newp,
newp->cond_list_len = 0; newp->cond_list_len = 0;
newp->cond_list = kcalloc(origp->cond_list_len, newp->cond_list = kcalloc(origp->cond_list_len,
sizeof(*newp->cond_list), sizeof(*newp->cond_list), GFP_KERNEL);
GFP_KERNEL);
if (!newp->cond_list) if (!newp->cond_list)
goto error; goto error;
...@@ -649,7 +645,8 @@ static int duplicate_policydb_cond_list(struct policydb *newp, ...@@ -649,7 +645,8 @@ static int duplicate_policydb_cond_list(struct policydb *newp,
newp->cond_list_len++; newp->cond_list_len++;
newn->cur_state = orign->cur_state; newn->cur_state = orign->cur_state;
newn->expr.nodes = kmemdup(orign->expr.nodes, newn->expr.nodes =
kmemdup(orign->expr.nodes,
orign->expr.len * sizeof(*orign->expr.nodes), orign->expr.len * sizeof(*orign->expr.nodes),
GFP_KERNEL); GFP_KERNEL);
if (!newn->expr.nodes) if (!newn->expr.nodes)
...@@ -658,12 +655,12 @@ static int duplicate_policydb_cond_list(struct policydb *newp, ...@@ -658,12 +655,12 @@ static int duplicate_policydb_cond_list(struct policydb *newp,
newn->expr.len = orign->expr.len; newn->expr.len = orign->expr.len;
rc = cond_dup_av_list(&newn->true_list, &orign->true_list, rc = cond_dup_av_list(&newn->true_list, &orign->true_list,
&newp->te_cond_avtab); &newp->te_cond_avtab);
if (rc) if (rc)
goto error; goto error;
rc = cond_dup_av_list(&newn->false_list, &orign->false_list, rc = cond_dup_av_list(&newn->false_list, &orign->false_list,
&newp->te_cond_avtab); &newp->te_cond_avtab);
if (rc) if (rc)
goto error; goto error;
} }
...@@ -683,7 +680,8 @@ static int cond_bools_destroy(void *key, void *datum, void *args) ...@@ -683,7 +680,8 @@ static int cond_bools_destroy(void *key, void *datum, void *args)
return 0; return 0;
} }
static int cond_bools_copy(struct hashtab_node *new, struct hashtab_node *orig, void *args) static int cond_bools_copy(struct hashtab_node *new, struct hashtab_node *orig,
void *args)
{ {
struct cond_bool_datum *datum; struct cond_bool_datum *datum;
...@@ -709,7 +707,7 @@ static int cond_bools_index(void *key, void *datum, void *args) ...@@ -709,7 +707,7 @@ static int cond_bools_index(void *key, void *datum, void *args)
} }
static int duplicate_policydb_bools(struct policydb *newdb, static int duplicate_policydb_bools(struct policydb *newdb,
struct policydb *orig) struct policydb *orig)
{ {
struct cond_bool_datum **cond_bool_array; struct cond_bool_datum **cond_bool_array;
int rc; int rc;
...@@ -721,7 +719,7 @@ static int duplicate_policydb_bools(struct policydb *newdb, ...@@ -721,7 +719,7 @@ static int duplicate_policydb_bools(struct policydb *newdb,
return -ENOMEM; return -ENOMEM;
rc = hashtab_duplicate(&newdb->p_bools.table, &orig->p_bools.table, rc = hashtab_duplicate(&newdb->p_bools.table, &orig->p_bools.table,
cond_bools_copy, cond_bools_destroy, NULL); cond_bools_copy, cond_bools_destroy, NULL);
if (rc) { if (rc) {
kfree(cond_bool_array); kfree(cond_bool_array);
return -ENOMEM; return -ENOMEM;
......
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* Authors: Karl MacMillan <kmacmillan@tresys.com> /* Authors: Karl MacMillan <kmacmillan@tresys.com>
* Frank Mayer <mayerf@tresys.com> * Frank Mayer <mayerf@tresys.com>
* * Copyright (C) 2003 - 2004 Tresys Technology, LLC
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
*/ */
#ifndef _CONDITIONAL_H_ #ifndef _CONDITIONAL_H_
...@@ -20,14 +19,14 @@ ...@@ -20,14 +19,14 @@
* in reverse polish notation. * in reverse polish notation.
*/ */
struct cond_expr_node { struct cond_expr_node {
#define COND_BOOL 1 /* plain bool */ #define COND_BOOL 1 /* plain bool */
#define COND_NOT 2 /* !bool */ #define COND_NOT 2 /* !bool */
#define COND_OR 3 /* bool || bool */ #define COND_OR 3 /* bool || bool */
#define COND_AND 4 /* bool && bool */ #define COND_AND 4 /* bool && bool */
#define COND_XOR 5 /* bool ^ bool */ #define COND_XOR 5 /* bool ^ bool */
#define COND_EQ 6 /* bool == bool */ #define COND_EQ 6 /* bool == bool */
#define COND_NEQ 7 /* bool != bool */ #define COND_NEQ 7 /* bool != bool */
#define COND_LAST COND_NEQ #define COND_LAST COND_NEQ
u32 expr_type; u32 expr_type;
u32 boolean; u32 boolean;
}; };
...@@ -75,9 +74,9 @@ int cond_write_bool(void *key, void *datum, void *ptr); ...@@ -75,9 +74,9 @@ int cond_write_bool(void *key, void *datum, void *ptr);
int cond_write_list(struct policydb *p, void *fp); int cond_write_list(struct policydb *p, void *fp);
void cond_compute_av(struct avtab *ctab, struct avtab_key *key, void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
struct av_decision *avd, struct extended_perms *xperms); struct av_decision *avd, struct extended_perms *xperms);
void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
struct extended_perms_decision *xpermd); struct extended_perms_decision *xpermd);
void evaluate_cond_nodes(struct policydb *p); void evaluate_cond_nodes(struct policydb *p);
void cond_policydb_destroy_dup(struct policydb *p); void cond_policydb_destroy_dup(struct policydb *p);
int cond_policydb_dup(struct policydb *new, struct policydb *orig); int cond_policydb_dup(struct policydb *new, struct policydb *orig);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#ifndef _SS_CONSTRAINT_H_ #ifndef _SS_CONSTRAINT_H_
#define _SS_CONSTRAINT_H_ #define _SS_CONSTRAINT_H_
...@@ -21,43 +22,43 @@ ...@@ -21,43 +22,43 @@
#define CEXPR_MAXDEPTH 5 #define CEXPR_MAXDEPTH 5
struct constraint_expr { struct constraint_expr {
#define CEXPR_NOT 1 /* not expr */ #define CEXPR_NOT 1 /* not expr */
#define CEXPR_AND 2 /* expr and expr */ #define CEXPR_AND 2 /* expr and expr */
#define CEXPR_OR 3 /* expr or expr */ #define CEXPR_OR 3 /* expr or expr */
#define CEXPR_ATTR 4 /* attr op attr */ #define CEXPR_ATTR 4 /* attr op attr */
#define CEXPR_NAMES 5 /* attr op names */ #define CEXPR_NAMES 5 /* attr op names */
u32 expr_type; /* expression type */ u32 expr_type; /* expression type */
#define CEXPR_USER 1 /* user */ #define CEXPR_USER 1 /* user */
#define CEXPR_ROLE 2 /* role */ #define CEXPR_ROLE 2 /* role */
#define CEXPR_TYPE 4 /* type */ #define CEXPR_TYPE 4 /* type */
#define CEXPR_TARGET 8 /* target if set, source otherwise */ #define CEXPR_TARGET 8 /* target if set, source otherwise */
#define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */ #define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */
#define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */ #define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */
#define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */ #define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */
#define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */ #define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */
#define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */ #define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */
#define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */ #define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */
#define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */ #define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */
u32 attr; /* attribute */ u32 attr; /* attribute */
#define CEXPR_EQ 1 /* == or eq */ #define CEXPR_EQ 1 /* == or eq */
#define CEXPR_NEQ 2 /* != */ #define CEXPR_NEQ 2 /* != */
#define CEXPR_DOM 3 /* dom */ #define CEXPR_DOM 3 /* dom */
#define CEXPR_DOMBY 4 /* domby */ #define CEXPR_DOMBY 4 /* domby */
#define CEXPR_INCOMP 5 /* incomp */ #define CEXPR_INCOMP 5 /* incomp */
u32 op; /* operator */ u32 op; /* operator */
struct ebitmap names; /* names */ struct ebitmap names; /* names */
struct type_set *type_names; struct type_set *type_names;
struct constraint_expr *next; /* next expression */ struct constraint_expr *next; /* next expression */
}; };
struct constraint_node { struct constraint_node {
u32 permissions; /* constrained permissions */ u32 permissions; /* constrained permissions */
struct constraint_expr *expr; /* constraint on permissions */ struct constraint_expr *expr; /* constraint on permissions */
struct constraint_node *next; /* next constraint */ struct constraint_node *next; /* next constraint */
}; };
#endif /* _SS_CONSTRAINT_H_ */ #endif /* _SS_CONSTRAINT_H_ */
// SPDX-License-Identifier: GPL-2.0 /* SPDX-License-Identifier: GPL-2.0 */
/* /*
* Implementations of the security context functions. * Implementations of the security context functions.
* *
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#ifndef _SS_CONTEXT_H_ #ifndef _SS_CONTEXT_H_
#define _SS_CONTEXT_H_ #define _SS_CONTEXT_H_
...@@ -28,9 +29,9 @@ struct context { ...@@ -28,9 +29,9 @@ struct context {
u32 user; u32 user;
u32 role; u32 role;
u32 type; u32 type;
u32 len; /* length of string in bytes */ u32 len; /* length of string in bytes */
struct mls_range range; struct mls_range range;
char *str; /* string representation if context cannot be mapped. */ char *str; /* string representation if context cannot be mapped. */
}; };
static inline void mls_context_init(struct context *c) static inline void mls_context_init(struct context *c)
...@@ -38,7 +39,8 @@ static inline void mls_context_init(struct context *c) ...@@ -38,7 +39,8 @@ static inline void mls_context_init(struct context *c)
memset(&c->range, 0, sizeof(c->range)); memset(&c->range, 0, sizeof(c->range));
} }
static inline int mls_context_cpy(struct context *dst, const struct context *src) static inline int mls_context_cpy(struct context *dst,
const struct context *src)
{ {
int rc; int rc;
...@@ -58,7 +60,8 @@ static inline int mls_context_cpy(struct context *dst, const struct context *src ...@@ -58,7 +60,8 @@ static inline int mls_context_cpy(struct context *dst, const struct context *src
/* /*
* Sets both levels in the MLS range of 'dst' to the low level of 'src'. * Sets both levels in the MLS range of 'dst' to the low level of 'src'.
*/ */
static inline int mls_context_cpy_low(struct context *dst, const struct context *src) static inline int mls_context_cpy_low(struct context *dst,
const struct context *src)
{ {
int rc; int rc;
...@@ -78,7 +81,8 @@ static inline int mls_context_cpy_low(struct context *dst, const struct context ...@@ -78,7 +81,8 @@ static inline int mls_context_cpy_low(struct context *dst, const struct context
/* /*
* Sets both levels in the MLS range of 'dst' to the high level of 'src'. * Sets both levels in the MLS range of 'dst' to the high level of 'src'.
*/ */
static inline int mls_context_cpy_high(struct context *dst, const struct context *src) static inline int mls_context_cpy_high(struct context *dst,
const struct context *src)
{ {
int rc; int rc;
...@@ -95,9 +99,9 @@ static inline int mls_context_cpy_high(struct context *dst, const struct context ...@@ -95,9 +99,9 @@ static inline int mls_context_cpy_high(struct context *dst, const struct context
return rc; return rc;
} }
static inline int mls_context_glblub(struct context *dst, static inline int mls_context_glblub(struct context *dst,
const struct context *c1, const struct context *c2) const struct context *c1,
const struct context *c2)
{ {
struct mls_range *dr = &dst->range; struct mls_range *dr = &dst->range;
const struct mls_range *r1 = &c1->range, *r2 = &c2->range; const struct mls_range *r1 = &c1->range, *r2 = &c2->range;
...@@ -114,13 +118,13 @@ static inline int mls_context_glblub(struct context *dst, ...@@ -114,13 +118,13 @@ static inline int mls_context_glblub(struct context *dst,
/* Take the least of the high */ /* Take the least of the high */
dr->level[1].sens = min(r1->level[1].sens, r2->level[1].sens); dr->level[1].sens = min(r1->level[1].sens, r2->level[1].sens);
rc = ebitmap_and(&dr->level[0].cat, rc = ebitmap_and(&dr->level[0].cat, &r1->level[0].cat,
&r1->level[0].cat, &r2->level[0].cat); &r2->level[0].cat);
if (rc) if (rc)
goto out; goto out;
rc = ebitmap_and(&dr->level[1].cat, rc = ebitmap_and(&dr->level[1].cat, &r1->level[1].cat,
&r1->level[1].cat, &r2->level[1].cat); &r2->level[1].cat);
if (rc) if (rc)
goto out; goto out;
...@@ -128,7 +132,8 @@ static inline int mls_context_glblub(struct context *dst, ...@@ -128,7 +132,8 @@ static inline int mls_context_glblub(struct context *dst,
return rc; return rc;
} }
static inline int mls_context_cmp(const struct context *c1, const struct context *c2) static inline int mls_context_cmp(const struct context *c1,
const struct context *c2)
{ {
return ((c1->range.level[0].sens == c2->range.level[0].sens) && return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
...@@ -183,19 +188,17 @@ static inline void context_destroy(struct context *c) ...@@ -183,19 +188,17 @@ static inline void context_destroy(struct context *c)
mls_context_destroy(c); mls_context_destroy(c);
} }
static inline int context_cmp(const struct context *c1, const struct context *c2) static inline int context_cmp(const struct context *c1,
const struct context *c2)
{ {
if (c1->len && c2->len) if (c1->len && c2->len)
return (c1->len == c2->len && !strcmp(c1->str, c2->str)); return (c1->len == c2->len && !strcmp(c1->str, c2->str));
if (c1->len || c2->len) if (c1->len || c2->len)
return 0; return 0;
return ((c1->user == c2->user) && return ((c1->user == c2->user) && (c1->role == c2->role) &&
(c1->role == c2->role) && (c1->type == c2->type) && mls_context_cmp(c1, c2));
(c1->type == c2->type) &&
mls_context_cmp(c1, c2));
} }
u32 context_compute_hash(const struct context *c); u32 context_compute_hash(const struct context *c);
#endif /* _SS_CONTEXT_H_ */ #endif /* _SS_CONTEXT_H_ */
// SPDX-License-Identifier: GPL-2.0 /* SPDX-License-Identifier: GPL-2.0 */
/* /*
* Implementation of the extensible bitmap type. * Implementation of the extensible bitmap type.
* *
...@@ -6,14 +6,11 @@ ...@@ -6,14 +6,11 @@
*/ */
/* /*
* Updated: Hewlett-Packard <paul@paul-moore.com> * Updated: Hewlett-Packard <paul@paul-moore.com>
* Added support to import/export the NetLabel category bitmap
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
* *
* Added support to import/export the NetLabel category bitmap
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
/*
* Updated: KaiGai Kohei <kaigai@ak.jp.nec.com> * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
* Applied standard bit operations to improve bitmap scanning. * Applied standard bit operations to improve bitmap scanning.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -24,7 +21,7 @@ ...@@ -24,7 +21,7 @@
#include "ebitmap.h" #include "ebitmap.h"
#include "policydb.h" #include "policydb.h"
#define BITS_PER_U64 (sizeof(u64) * 8) #define BITS_PER_U64 (sizeof(u64) * 8)
static struct kmem_cache *ebitmap_node_cachep __ro_after_init; static struct kmem_cache *ebitmap_node_cachep __ro_after_init;
...@@ -37,8 +34,7 @@ int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2) ...@@ -37,8 +34,7 @@ int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2)
n1 = e1->node; n1 = e1->node;
n2 = e2->node; n2 = e2->node;
while (n1 && n2 && while (n1 && n2 && (n1->startbit == n2->startbit) &&
(n1->startbit == n2->startbit) &&
!memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8)) { !memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8)) {
n1 = n1->next; n1 = n1->next;
n2 = n2->next; n2 = n2->next;
...@@ -79,14 +75,16 @@ int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src) ...@@ -79,14 +75,16 @@ int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src)
return 0; return 0;
} }
int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2) int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1,
const struct ebitmap *e2)
{ {
struct ebitmap_node *n; struct ebitmap_node *n;
int bit, rc; int bit, rc;
ebitmap_init(dst); ebitmap_init(dst);
ebitmap_for_each_positive_bit(e1, n, bit) { ebitmap_for_each_positive_bit(e1, n, bit)
{
if (ebitmap_get_bit(e2, bit)) { if (ebitmap_get_bit(e2, bit)) {
rc = ebitmap_set_bit(dst, bit, 1); rc = ebitmap_set_bit(dst, bit, 1);
if (rc < 0) if (rc < 0)
...@@ -96,7 +94,6 @@ int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebit ...@@ -96,7 +94,6 @@ int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebit
return 0; return 0;
} }
#ifdef CONFIG_NETLABEL #ifdef CONFIG_NETLABEL
/** /**
* ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
...@@ -131,10 +128,8 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, ...@@ -131,10 +128,8 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
for (iter = 0; iter < EBITMAP_UNIT_NUMS; iter++) { for (iter = 0; iter < EBITMAP_UNIT_NUMS; iter++) {
e_map = e_iter->maps[iter]; e_map = e_iter->maps[iter];
if (e_map != 0) { if (e_map != 0) {
rc = netlbl_catmap_setlong(catmap, rc = netlbl_catmap_setlong(catmap, offset,
offset, e_map, GFP_ATOMIC);
e_map,
GFP_ATOMIC);
if (rc != 0) if (rc != 0)
goto netlbl_export_failure; goto netlbl_export_failure;
} }
...@@ -185,7 +180,8 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, ...@@ -185,7 +180,8 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
if (e_iter == NULL || if (e_iter == NULL ||
offset >= e_iter->startbit + EBITMAP_SIZE) { offset >= e_iter->startbit + EBITMAP_SIZE) {
e_prev = e_iter; e_prev = e_iter;
e_iter = kmem_cache_zalloc(ebitmap_node_cachep, GFP_ATOMIC); e_iter = kmem_cache_zalloc(ebitmap_node_cachep,
GFP_ATOMIC);
if (e_iter == NULL) if (e_iter == NULL)
goto netlbl_import_failure; goto netlbl_import_failure;
e_iter->startbit = offset - (offset % EBITMAP_SIZE); e_iter->startbit = offset - (offset % EBITMAP_SIZE);
...@@ -218,7 +214,8 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, ...@@ -218,7 +214,8 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
* if last_e2bit is non-zero, the highest set bit in e2 cannot exceed * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
* last_e2bit. * last_e2bit.
*/ */
int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit) int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2,
u32 last_e2bit)
{ {
const struct ebitmap_node *n1, *n2; const struct ebitmap_node *n1, *n2;
int i; int i;
...@@ -234,8 +231,8 @@ int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 las ...@@ -234,8 +231,8 @@ int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 las
n1 = n1->next; n1 = n1->next;
continue; continue;
} }
for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i]; ) for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i];)
i--; /* Skip trailing NULL map entries */ i--; /* Skip trailing NULL map entries */
if (last_e2bit && (i >= 0)) { if (last_e2bit && (i >= 0)) {
u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE + u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE +
__fls(n2->maps[i]); __fls(n2->maps[i]);
...@@ -302,8 +299,8 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value) ...@@ -302,8 +299,8 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
* within the bitmap * within the bitmap
*/ */
if (prev) if (prev)
e->highbit = prev->startbit e->highbit = prev->startbit +
+ EBITMAP_SIZE; EBITMAP_SIZE;
else else
e->highbit = 0; e->highbit = 0;
} }
...@@ -424,7 +421,8 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -424,7 +421,8 @@ int ebitmap_read(struct ebitmap *e, void *fp)
if (!n || startbit >= n->startbit + EBITMAP_SIZE) { if (!n || startbit >= n->startbit + EBITMAP_SIZE) {
struct ebitmap_node *tmp; struct ebitmap_node *tmp;
tmp = kmem_cache_zalloc(ebitmap_node_cachep, GFP_KERNEL); tmp = kmem_cache_zalloc(ebitmap_node_cachep,
GFP_KERNEL);
if (!tmp) { if (!tmp) {
pr_err("SELinux: ebitmap: out of memory\n"); pr_err("SELinux: ebitmap: out of memory\n");
rc = -ENOMEM; rc = -ENOMEM;
...@@ -481,7 +479,8 @@ int ebitmap_write(const struct ebitmap *e, void *fp) ...@@ -481,7 +479,8 @@ int ebitmap_write(const struct ebitmap *e, void *fp)
count = 0; count = 0;
last_bit = 0; last_bit = 0;
last_startbit = -1; last_startbit = -1;
ebitmap_for_each_positive_bit(e, n, bit) { ebitmap_for_each_positive_bit(e, n, bit)
{
if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) { if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
count++; count++;
last_startbit = rounddown(bit, BITS_PER_U64); last_startbit = rounddown(bit, BITS_PER_U64);
...@@ -497,7 +496,8 @@ int ebitmap_write(const struct ebitmap *e, void *fp) ...@@ -497,7 +496,8 @@ int ebitmap_write(const struct ebitmap *e, void *fp)
map = 0; map = 0;
last_startbit = INT_MIN; last_startbit = INT_MIN;
ebitmap_for_each_positive_bit(e, n, bit) { ebitmap_for_each_positive_bit(e, n, bit)
{
if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) { if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
__le64 buf64[1]; __le64 buf64[1];
...@@ -559,6 +559,6 @@ u32 ebitmap_hash(const struct ebitmap *e, u32 hash) ...@@ -559,6 +559,6 @@ u32 ebitmap_hash(const struct ebitmap *e, u32 hash)
void __init ebitmap_cache_init(void) void __init ebitmap_cache_init(void)
{ {
ebitmap_node_cachep = kmem_cache_create("ebitmap_node", ebitmap_node_cachep = kmem_cache_create("ebitmap_node",
sizeof(struct ebitmap_node), sizeof(struct ebitmap_node), 0,
0, SLAB_PANIC, NULL); SLAB_PANIC, NULL);
} }
...@@ -12,23 +12,25 @@ ...@@ -12,23 +12,25 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#ifndef _SS_EBITMAP_H_ #ifndef _SS_EBITMAP_H_
#define _SS_EBITMAP_H_ #define _SS_EBITMAP_H_
#include <net/netlabel.h> #include <net/netlabel.h>
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#define EBITMAP_NODE_SIZE 64 #define EBITMAP_NODE_SIZE 64
#else #else
#define EBITMAP_NODE_SIZE 32 #define EBITMAP_NODE_SIZE 32
#endif #endif
#define EBITMAP_UNIT_NUMS ((EBITMAP_NODE_SIZE-sizeof(void *)-sizeof(u32))\ #define EBITMAP_UNIT_NUMS \
/ sizeof(unsigned long)) ((EBITMAP_NODE_SIZE - sizeof(void *) - sizeof(u32)) / \
#define EBITMAP_UNIT_SIZE BITS_PER_LONG sizeof(unsigned long))
#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE) #define EBITMAP_UNIT_SIZE BITS_PER_LONG
#define EBITMAP_BIT 1ULL #define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
#define EBITMAP_SHIFT_UNIT_SIZE(x) \ #define EBITMAP_BIT 1ULL
#define EBITMAP_SHIFT_UNIT_SIZE(x) \
(((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2) (((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2)
struct ebitmap_node { struct ebitmap_node {
...@@ -38,8 +40,8 @@ struct ebitmap_node { ...@@ -38,8 +40,8 @@ struct ebitmap_node {
}; };
struct ebitmap { struct ebitmap {
struct ebitmap_node *node; /* first node in the bitmap */ struct ebitmap_node *node; /* first node in the bitmap */
u32 highbit; /* highest position in the total bitmap */ u32 highbit; /* highest position in the total bitmap */
}; };
#define ebitmap_length(e) ((e)->highbit) #define ebitmap_length(e) ((e)->highbit)
...@@ -80,9 +82,9 @@ static inline unsigned int ebitmap_next_positive(const struct ebitmap *e, ...@@ -80,9 +82,9 @@ static inline unsigned int ebitmap_next_positive(const struct ebitmap *e,
return ebitmap_length(e); return ebitmap_length(e);
} }
#define EBITMAP_NODE_INDEX(node, bit) \ #define EBITMAP_NODE_INDEX(node, bit) \
(((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE) (((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE)
#define EBITMAP_NODE_OFFSET(node, bit) \ #define EBITMAP_NODE_OFFSET(node, bit) \
(((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE) (((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
static inline int ebitmap_node_get_bit(const struct ebitmap_node *n, static inline int ebitmap_node_get_bit(const struct ebitmap_node *n,
...@@ -117,15 +119,17 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n, ...@@ -117,15 +119,17 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
n->maps[index] &= ~(EBITMAP_BIT << ofs); n->maps[index] &= ~(EBITMAP_BIT << ofs);
} }
#define ebitmap_for_each_positive_bit(e, n, bit) \ #define ebitmap_for_each_positive_bit(e, n, bit) \
for ((bit) = ebitmap_start_positive(e, &(n)); \ for ((bit) = ebitmap_start_positive(e, &(n)); \
(bit) < ebitmap_length(e); \ (bit) < ebitmap_length(e); \
(bit) = ebitmap_next_positive(e, &(n), bit)) \ (bit) = ebitmap_next_positive(e, &(n), bit))
int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2); int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src); int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src);
int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2); int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1,
int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit); const struct ebitmap *e2);
int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2,
u32 last_e2bit);
int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit); int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit);
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
void ebitmap_destroy(struct ebitmap *e); void ebitmap_destroy(struct ebitmap *e);
...@@ -151,4 +155,4 @@ static inline int ebitmap_netlbl_import(struct ebitmap *ebmap, ...@@ -151,4 +155,4 @@ static inline int ebitmap_netlbl_import(struct ebitmap *ebmap,
} }
#endif #endif
#endif /* _SS_EBITMAP_H_ */ #endif /* _SS_EBITMAP_H_ */
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -47,8 +48,8 @@ int hashtab_init(struct hashtab *h, u32 nel_hint) ...@@ -47,8 +48,8 @@ int hashtab_init(struct hashtab *h, u32 nel_hint)
return 0; return 0;
} }
int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, void *key,
void *key, void *datum) void *datum)
{ {
struct hashtab_node *newnode; struct hashtab_node *newnode;
...@@ -83,8 +84,7 @@ void hashtab_destroy(struct hashtab *h) ...@@ -83,8 +84,7 @@ void hashtab_destroy(struct hashtab *h)
h->htable = NULL; h->htable = NULL;
} }
int hashtab_map(struct hashtab *h, int hashtab_map(struct hashtab *h, int (*apply)(void *k, void *d, void *args),
int (*apply)(void *k, void *d, void *args),
void *args) void *args)
{ {
u32 i; u32 i;
...@@ -137,10 +137,9 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info) ...@@ -137,10 +137,9 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
#endif /* CONFIG_SECURITY_SELINUX_DEBUG */ #endif /* CONFIG_SECURITY_SELINUX_DEBUG */
int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
int (*copy)(struct hashtab_node *new, int (*copy)(struct hashtab_node *new,
struct hashtab_node *orig, void *args), struct hashtab_node *orig, void *args),
int (*destroy)(void *k, void *d, void *args), int (*destroy)(void *k, void *d, void *args), void *args)
void *args)
{ {
struct hashtab_node *cur, *tmp, *tail; struct hashtab_node *cur, *tmp, *tail;
u32 i; u32 i;
...@@ -178,7 +177,7 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, ...@@ -178,7 +177,7 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
return 0; return 0;
error: error:
for (i = 0; i < new->size; i++) { for (i = 0; i < new->size; i++) {
for (cur = new->htable[i]; cur; cur = tmp) { for (cur = new->htable[i]; cur; cur = tmp) {
tmp = cur->next; tmp = cur->next;
...@@ -193,7 +192,7 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, ...@@ -193,7 +192,7 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
void __init hashtab_cache_init(void) void __init hashtab_cache_init(void)
{ {
hashtab_node_cachep = kmem_cache_create("hashtab_node", hashtab_node_cachep = kmem_cache_create("hashtab_node",
sizeof(struct hashtab_node), sizeof(struct hashtab_node), 0,
0, SLAB_PANIC, NULL); SLAB_PANIC, NULL);
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#ifndef _SS_HASHTAB_H_ #ifndef _SS_HASHTAB_H_
#define _SS_HASHTAB_H_ #define _SS_HASHTAB_H_
...@@ -15,12 +16,11 @@ ...@@ -15,12 +16,11 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#define HASHTAB_MAX_NODES U32_MAX #define HASHTAB_MAX_NODES U32_MAX
struct hashtab_key_params { struct hashtab_key_params {
u32 (*hash)(const void *key); /* hash function */ u32 (*hash)(const void *key); /* hash func */
int (*cmp)(const void *key1, const void *key2); int (*cmp)(const void *key1, const void *key2); /* comparison func */
/* key comparison function */
}; };
struct hashtab_node { struct hashtab_node {
...@@ -30,9 +30,9 @@ struct hashtab_node { ...@@ -30,9 +30,9 @@ struct hashtab_node {
}; };
struct hashtab { struct hashtab {
struct hashtab_node **htable; /* hash table */ struct hashtab_node **htable; /* hash table */
u32 size; /* number of slots in hash table */ u32 size; /* number of slots in hash table */
u32 nel; /* number of elements in hash table */ u32 nel; /* number of elements in hash table */
}; };
struct hashtab_info { struct hashtab_info {
...@@ -48,8 +48,8 @@ struct hashtab_info { ...@@ -48,8 +48,8 @@ struct hashtab_info {
*/ */
int hashtab_init(struct hashtab *h, u32 nel_hint); int hashtab_init(struct hashtab *h, u32 nel_hint);
int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, void *key,
void *key, void *datum); void *datum);
/* /*
* Inserts the specified (key, datum) pair into the specified hash table. * Inserts the specified (key, datum) pair into the specified hash table.
...@@ -84,8 +84,8 @@ static inline int hashtab_insert(struct hashtab *h, void *key, void *datum, ...@@ -84,8 +84,8 @@ static inline int hashtab_insert(struct hashtab *h, void *key, void *datum,
cur = cur->next; cur = cur->next;
} }
return __hashtab_insert(h, prev ? &prev->next : &h->htable[hvalue], return __hashtab_insert(h, prev ? &prev->next : &h->htable[hvalue], key,
key, datum); datum);
} }
/* /*
...@@ -133,15 +133,13 @@ void hashtab_destroy(struct hashtab *h); ...@@ -133,15 +133,13 @@ void hashtab_destroy(struct hashtab *h);
* iterating through the hash table and will propagate the error * iterating through the hash table and will propagate the error
* return to its caller. * return to its caller.
*/ */
int hashtab_map(struct hashtab *h, int hashtab_map(struct hashtab *h, int (*apply)(void *k, void *d, void *args),
int (*apply)(void *k, void *d, void *args),
void *args); void *args);
int hashtab_duplicate(struct hashtab *new, struct hashtab *orig, int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
int (*copy)(struct hashtab_node *new, int (*copy)(struct hashtab_node *new,
struct hashtab_node *orig, void *args), struct hashtab_node *orig, void *args),
int (*destroy)(void *k, void *d, void *args), int (*destroy)(void *k, void *d, void *args), void *args);
void *args);
#ifdef CONFIG_SECURITY_SELINUX_DEBUG #ifdef CONFIG_SECURITY_SELINUX_DEBUG
/* Fill info with some hash table statistics */ /* Fill info with some hash table statistics */
...@@ -149,7 +147,8 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info); ...@@ -149,7 +147,8 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
#else #else
static inline void hashtab_stat(struct hashtab *h, struct hashtab_info *info) static inline void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
{ {
return;
} }
#endif #endif
#endif /* _SS_HASHTAB_H */ #endif /* _SS_HASHTAB_H */
...@@ -4,19 +4,15 @@ ...@@ -4,19 +4,15 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
/* /*
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
* Support for enhanced MLS infrastructure.
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
* *
* Support for enhanced MLS infrastructure.
*
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
*/
/*
* Updated: Hewlett-Packard <paul@paul-moore.com> * Updated: Hewlett-Packard <paul@paul-moore.com>
* * Added support to import/export the MLS label from NetLabel
* Added support to import/export the MLS label from NetLabel * Copyright (C) Hewlett-Packard Development Company, L.P., 2006
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -52,7 +48,8 @@ int mls_compute_context_len(struct policydb *p, struct context *context) ...@@ -52,7 +48,8 @@ int mls_compute_context_len(struct policydb *p, struct context *context)
head = -2; head = -2;
prev = -2; prev = -2;
e = &context->range.level[l].cat; e = &context->range.level[l].cat;
ebitmap_for_each_positive_bit(e, node, i) { ebitmap_for_each_positive_bit(e, node, i)
{
if (i - prev > 1) { if (i - prev > 1) {
/* one or more negative bits are skipped */ /* one or more negative bits are skipped */
if (head != prev) { if (head != prev) {
...@@ -86,8 +83,7 @@ int mls_compute_context_len(struct policydb *p, struct context *context) ...@@ -86,8 +83,7 @@ int mls_compute_context_len(struct policydb *p, struct context *context)
* the MLS fields of `context' into the string `*scontext'. * the MLS fields of `context' into the string `*scontext'.
* Update `*scontext' to point to the end of the MLS fields. * Update `*scontext' to point to the end of the MLS fields.
*/ */
void mls_sid_to_context(struct policydb *p, void mls_sid_to_context(struct policydb *p, struct context *context,
struct context *context,
char **scontext) char **scontext)
{ {
char *scontextp, *nm; char *scontextp, *nm;
...@@ -112,7 +108,8 @@ void mls_sid_to_context(struct policydb *p, ...@@ -112,7 +108,8 @@ void mls_sid_to_context(struct policydb *p,
head = -2; head = -2;
prev = -2; prev = -2;
e = &context->range.level[l].cat; e = &context->range.level[l].cat;
ebitmap_for_each_positive_bit(e, node, i) { ebitmap_for_each_positive_bit(e, node, i)
{
if (i - prev > 1) { if (i - prev > 1) {
/* one or more negative bits are skipped */ /* one or more negative bits are skipped */
if (prev != head) { if (prev != head) {
...@@ -230,12 +227,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c) ...@@ -230,12 +227,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
* Policy read-lock must be held for sidtab lookup. * Policy read-lock must be held for sidtab lookup.
* *
*/ */
int mls_context_to_sid(struct policydb *pol, int mls_context_to_sid(struct policydb *pol, char oldc, char *scontext,
char oldc, struct context *context, struct sidtab *s, u32 def_sid)
char *scontext,
struct context *context,
struct sidtab *s,
u32 def_sid)
{ {
char *sensitivity, *cur_cat, *next_cat, *rngptr; char *sensitivity, *cur_cat, *next_cat, *rngptr;
struct level_datum *levdatum; struct level_datum *levdatum;
...@@ -333,7 +326,8 @@ int mls_context_to_sid(struct policydb *pol, ...@@ -333,7 +326,8 @@ int mls_context_to_sid(struct policydb *pol,
return -EINVAL; return -EINVAL;
for (i = catdatum->value; i < rngdatum->value; i++) { for (i = catdatum->value; i < rngdatum->value; i++) {
rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1); rc = ebitmap_set_bit(
&context->range.level[l].cat, i, 1);
if (rc) if (rc)
return rc; return rc;
} }
...@@ -371,8 +365,8 @@ int mls_from_string(struct policydb *p, char *str, struct context *context, ...@@ -371,8 +365,8 @@ int mls_from_string(struct policydb *p, char *str, struct context *context,
if (!tmpstr) { if (!tmpstr) {
rc = -ENOMEM; rc = -ENOMEM;
} else { } else {
rc = mls_context_to_sid(p, ':', tmpstr, context, rc = mls_context_to_sid(p, ':', tmpstr, context, NULL,
NULL, SECSID_NULL); SECSID_NULL);
kfree(tmpstr); kfree(tmpstr);
} }
...@@ -382,8 +376,7 @@ int mls_from_string(struct policydb *p, char *str, struct context *context, ...@@ -382,8 +376,7 @@ int mls_from_string(struct policydb *p, char *str, struct context *context,
/* /*
* Copies the MLS range `range' into `context'. * Copies the MLS range `range' into `context'.
*/ */
int mls_range_set(struct context *context, int mls_range_set(struct context *context, struct mls_range *range)
struct mls_range *range)
{ {
int l, rc = 0; int l, rc = 0;
...@@ -399,9 +392,8 @@ int mls_range_set(struct context *context, ...@@ -399,9 +392,8 @@ int mls_range_set(struct context *context,
return rc; return rc;
} }
int mls_setup_user_range(struct policydb *p, int mls_setup_user_range(struct policydb *p, struct context *fromcon,
struct context *fromcon, struct user_datum *user, struct user_datum *user, struct context *usercon)
struct context *usercon)
{ {
if (p->mls_enabled) { if (p->mls_enabled) {
struct mls_level *fromcon_sen = &(fromcon->range.level[0]); struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
...@@ -444,10 +436,8 @@ int mls_setup_user_range(struct policydb *p, ...@@ -444,10 +436,8 @@ int mls_setup_user_range(struct policydb *p,
* policy `oldp' to the values specified in the policy `newp', * policy `oldp' to the values specified in the policy `newp',
* storing the resulting context in `newc'. * storing the resulting context in `newc'.
*/ */
int mls_convert_context(struct policydb *oldp, int mls_convert_context(struct policydb *oldp, struct policydb *newp,
struct policydb *newp, struct context *oldc, struct context *newc)
struct context *oldc,
struct context *newc)
{ {
struct level_datum *levdatum; struct level_datum *levdatum;
struct cat_datum *catdatum; struct cat_datum *catdatum;
...@@ -468,8 +458,9 @@ int mls_convert_context(struct policydb *oldp, ...@@ -468,8 +458,9 @@ int mls_convert_context(struct policydb *oldp,
return -EINVAL; return -EINVAL;
newc->range.level[l].sens = levdatum->level->sens; newc->range.level[l].sens = levdatum->level->sens;
ebitmap_for_each_positive_bit(&oldc->range.level[l].cat, ebitmap_for_each_positive_bit(&oldc->range.level[l].cat, node,
node, i) { i)
{
int rc; int rc;
catdatum = symtab_search(&newp->p_cats, catdatum = symtab_search(&newp->p_cats,
...@@ -486,13 +477,9 @@ int mls_convert_context(struct policydb *oldp, ...@@ -486,13 +477,9 @@ int mls_convert_context(struct policydb *oldp,
return 0; return 0;
} }
int mls_compute_sid(struct policydb *p, int mls_compute_sid(struct policydb *p, struct context *scontext,
struct context *scontext, struct context *tcontext, u16 tclass, u32 specified,
struct context *tcontext, struct context *newcontext, bool sock)
u16 tclass,
u32 specified,
struct context *newcontext,
bool sock)
{ {
struct range_trans rtr; struct range_trans rtr;
struct mls_range *r; struct mls_range *r;
...@@ -532,8 +519,8 @@ int mls_compute_sid(struct policydb *p, ...@@ -532,8 +519,8 @@ int mls_compute_sid(struct policydb *p,
case DEFAULT_TARGET_LOW_HIGH: case DEFAULT_TARGET_LOW_HIGH:
return mls_context_cpy(newcontext, tcontext); return mls_context_cpy(newcontext, tcontext);
case DEFAULT_GLBLUB: case DEFAULT_GLBLUB:
return mls_context_glblub(newcontext, return mls_context_glblub(newcontext, scontext,
scontext, tcontext); tcontext);
} }
fallthrough; fallthrough;
...@@ -563,8 +550,7 @@ int mls_compute_sid(struct policydb *p, ...@@ -563,8 +550,7 @@ int mls_compute_sid(struct policydb *p,
* NetLabel MLS sensitivity level field. * NetLabel MLS sensitivity level field.
* *
*/ */
void mls_export_netlbl_lvl(struct policydb *p, void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr) struct netlbl_lsm_secattr *secattr)
{ {
if (!p->mls_enabled) if (!p->mls_enabled)
...@@ -585,8 +571,7 @@ void mls_export_netlbl_lvl(struct policydb *p, ...@@ -585,8 +571,7 @@ void mls_export_netlbl_lvl(struct policydb *p,
* NetLabel MLS sensitivity level into the context. * NetLabel MLS sensitivity level into the context.
* *
*/ */
void mls_import_netlbl_lvl(struct policydb *p, void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr) struct netlbl_lsm_secattr *secattr)
{ {
if (!p->mls_enabled) if (!p->mls_enabled)
...@@ -607,8 +592,7 @@ void mls_import_netlbl_lvl(struct policydb *p, ...@@ -607,8 +592,7 @@ void mls_import_netlbl_lvl(struct policydb *p,
* MLS category field. Returns zero on success, negative values on failure. * MLS category field. Returns zero on success, negative values on failure.
* *
*/ */
int mls_export_netlbl_cat(struct policydb *p, int mls_export_netlbl_cat(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr) struct netlbl_lsm_secattr *secattr)
{ {
int rc; int rc;
...@@ -637,8 +621,7 @@ int mls_export_netlbl_cat(struct policydb *p, ...@@ -637,8 +621,7 @@ int mls_export_netlbl_cat(struct policydb *p,
* negative values on failure. * negative values on failure.
* *
*/ */
int mls_import_netlbl_cat(struct policydb *p, int mls_import_netlbl_cat(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr) struct netlbl_lsm_secattr *secattr)
{ {
int rc; int rc;
......
...@@ -4,19 +4,15 @@ ...@@ -4,19 +4,15 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
/* /*
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
* Support for enhanced MLS infrastructure.
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
* *
* Support for enhanced MLS infrastructure.
*
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
*/
/*
* Updated: Hewlett-Packard <paul@paul-moore.com> * Updated: Hewlett-Packard <paul@paul-moore.com>
* * Added support to import/export the MLS label from NetLabel
* Added support to import/export the MLS label from NetLabel * Copyright (X) Hewlett-Packard Development Company, L.P., 2006
*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/ */
#ifndef _SS_MLS_H_ #ifndef _SS_MLS_H_
...@@ -35,47 +31,32 @@ int mls_context_isvalid(struct policydb *p, struct context *c); ...@@ -35,47 +31,32 @@ int mls_context_isvalid(struct policydb *p, struct context *c);
int mls_range_isvalid(struct policydb *p, struct mls_range *r); int mls_range_isvalid(struct policydb *p, struct mls_range *r);
int mls_level_isvalid(struct policydb *p, struct mls_level *l); int mls_level_isvalid(struct policydb *p, struct mls_level *l);
int mls_context_to_sid(struct policydb *p, int mls_context_to_sid(struct policydb *p, char oldc, char *scontext,
char oldc, struct context *context, struct sidtab *s, u32 def_sid);
char *scontext,
struct context *context,
struct sidtab *s,
u32 def_sid);
int mls_from_string(struct policydb *p, char *str, struct context *context, int mls_from_string(struct policydb *p, char *str, struct context *context,
gfp_t gfp_mask); gfp_t gfp_mask);
int mls_range_set(struct context *context, struct mls_range *range); int mls_range_set(struct context *context, struct mls_range *range);
int mls_convert_context(struct policydb *oldp, int mls_convert_context(struct policydb *oldp, struct policydb *newp,
struct policydb *newp, struct context *oldc, struct context *newc);
struct context *oldc,
struct context *newc);
int mls_compute_sid(struct policydb *p, int mls_compute_sid(struct policydb *p, struct context *scontext,
struct context *scontext, struct context *tcontext, u16 tclass, u32 specified,
struct context *tcontext, struct context *newcontext, bool sock);
u16 tclass,
u32 specified,
struct context *newcontext,
bool sock);
int mls_setup_user_range(struct policydb *p, int mls_setup_user_range(struct policydb *p, struct context *fromcon,
struct context *fromcon, struct user_datum *user, struct user_datum *user, struct context *usercon);
struct context *usercon);
#ifdef CONFIG_NETLABEL #ifdef CONFIG_NETLABEL
void mls_export_netlbl_lvl(struct policydb *p, void mls_export_netlbl_lvl(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr); struct netlbl_lsm_secattr *secattr);
void mls_import_netlbl_lvl(struct policydb *p, void mls_import_netlbl_lvl(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr); struct netlbl_lsm_secattr *secattr);
int mls_export_netlbl_cat(struct policydb *p, int mls_export_netlbl_cat(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr); struct netlbl_lsm_secattr *secattr);
int mls_import_netlbl_cat(struct policydb *p, int mls_import_netlbl_cat(struct policydb *p, struct context *context,
struct context *context,
struct netlbl_lsm_secattr *secattr); struct netlbl_lsm_secattr *secattr);
#else #else
static inline void mls_export_netlbl_lvl(struct policydb *p, static inline void mls_export_netlbl_lvl(struct policydb *p,
...@@ -112,5 +93,4 @@ static inline u32 mls_range_hash(const struct mls_range *r, u32 hash) ...@@ -112,5 +93,4 @@ static inline u32 mls_range_hash(const struct mls_range *r, u32 hash)
return hash; return hash;
} }
#endif /* _SS_MLS_H */ #endif /* _SS_MLS_H */
...@@ -4,12 +4,11 @@ ...@@ -4,12 +4,11 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
/* /*
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
* * Support for enhanced MLS infrastructure.
* Support for enhanced MLS infrastructure. * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
*
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
*/ */
#ifndef _SS_MLS_TYPES_H_ #ifndef _SS_MLS_TYPES_H_
...@@ -19,34 +18,35 @@ ...@@ -19,34 +18,35 @@
#include "ebitmap.h" #include "ebitmap.h"
struct mls_level { struct mls_level {
u32 sens; /* sensitivity */ u32 sens; /* sensitivity */
struct ebitmap cat; /* category set */ struct ebitmap cat; /* category set */
}; };
struct mls_range { struct mls_range {
struct mls_level level[2]; /* low == level[0], high == level[1] */ struct mls_level level[2]; /* low == level[0], high == level[1] */
}; };
static inline int mls_level_eq(const struct mls_level *l1, const struct mls_level *l2) static inline int mls_level_eq(const struct mls_level *l1,
const struct mls_level *l2)
{ {
return ((l1->sens == l2->sens) && return ((l1->sens == l2->sens) && ebitmap_cmp(&l1->cat, &l2->cat));
ebitmap_cmp(&l1->cat, &l2->cat));
} }
static inline int mls_level_dom(const struct mls_level *l1, const struct mls_level *l2) static inline int mls_level_dom(const struct mls_level *l1,
const struct mls_level *l2)
{ {
return ((l1->sens >= l2->sens) && return ((l1->sens >= l2->sens) &&
ebitmap_contains(&l1->cat, &l2->cat, 0)); ebitmap_contains(&l1->cat, &l2->cat, 0));
} }
#define mls_level_incomp(l1, l2) \ #define mls_level_incomp(l1, l2) \
(!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1))) (!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1)))
#define mls_level_between(l1, l2, l3) \ #define mls_level_between(l1, l2, l3) \
(mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1))) (mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1)))
#define mls_range_contains(r1, r2) \ #define mls_range_contains(r1, r2) \
(mls_level_dom(&(r2).level[0], &(r1).level[0]) && \ (mls_level_dom(&(r2).level[0], &(r1).level[0]) && \
mls_level_dom(&(r1).level[1], &(r2).level[1])) mls_level_dom(&(r1).level[1], &(r2).level[1]))
#endif /* _SS_MLS_TYPES_H_ */ #endif /* _SS_MLS_TYPES_H_ */
This diff is collapsed.
This diff is collapsed.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#ifndef _SS_SERVICES_H_ #ifndef _SS_SERVICES_H_
#define _SS_SERVICES_H_ #define _SS_SERVICES_H_
...@@ -43,4 +44,4 @@ int services_convert_context(struct convert_context_args *args, ...@@ -43,4 +44,4 @@ int services_convert_context(struct convert_context_args *args,
struct context *oldc, struct context *newc, struct context *oldc, struct context *newc,
gfp_t gfp_flags); gfp_t gfp_flags);
#endif /* _SS_SERVICES_H_ */ #endif /* _SS_SERVICES_H_ */
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* *
* Copyright (C) 2018 Red Hat, Inc. * Copyright (C) 2018 Red Hat, Inc.
*/ */
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -29,7 +30,7 @@ struct sidtab_str_cache { ...@@ -29,7 +30,7 @@ struct sidtab_str_cache {
}; };
#define index_to_sid(index) ((index) + SECINITSID_NUM + 1) #define index_to_sid(index) ((index) + SECINITSID_NUM + 1)
#define sid_to_index(sid) ((sid) - (SECINITSID_NUM + 1)) #define sid_to_index(sid) ((sid) - (SECINITSID_NUM + 1))
int sidtab_init(struct sidtab *s) int sidtab_init(struct sidtab *s)
{ {
...@@ -140,9 +141,11 @@ int sidtab_hash_stats(struct sidtab *sidtab, char *page) ...@@ -140,9 +141,11 @@ int sidtab_hash_stats(struct sidtab *sidtab, char *page)
if (chain_len > max_chain_len) if (chain_len > max_chain_len)
max_chain_len = chain_len; max_chain_len = chain_len;
return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n" return scnprintf(page, PAGE_SIZE,
"longest chain: %d\n", entries, "entries: %d\nbuckets used: %d/%d\n"
slots_used, SIDTAB_HASH_BUCKETS, max_chain_len); "longest chain: %d\n",
entries, slots_used, SIDTAB_HASH_BUCKETS,
max_chain_len);
} }
static u32 sidtab_level_from_count(u32 count) static u32 sidtab_level_from_count(u32 count)
...@@ -162,15 +165,15 @@ static int sidtab_alloc_roots(struct sidtab *s, u32 level) ...@@ -162,15 +165,15 @@ static int sidtab_alloc_roots(struct sidtab *s, u32 level)
u32 l; u32 l;
if (!s->roots[0].ptr_leaf) { if (!s->roots[0].ptr_leaf) {
s->roots[0].ptr_leaf = kzalloc(SIDTAB_NODE_ALLOC_SIZE, s->roots[0].ptr_leaf =
GFP_ATOMIC); kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC);
if (!s->roots[0].ptr_leaf) if (!s->roots[0].ptr_leaf)
return -ENOMEM; return -ENOMEM;
} }
for (l = 1; l <= level; ++l) for (l = 1; l <= level; ++l)
if (!s->roots[l].ptr_inner) { if (!s->roots[l].ptr_inner) {
s->roots[l].ptr_inner = kzalloc(SIDTAB_NODE_ALLOC_SIZE, s->roots[l].ptr_inner =
GFP_ATOMIC); kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC);
if (!s->roots[l].ptr_inner) if (!s->roots[l].ptr_inner)
return -ENOMEM; return -ENOMEM;
s->roots[l].ptr_inner->entries[0] = s->roots[l - 1]; s->roots[l].ptr_inner->entries[0] = s->roots[l - 1];
...@@ -203,16 +206,16 @@ static struct sidtab_entry *sidtab_do_lookup(struct sidtab *s, u32 index, ...@@ -203,16 +206,16 @@ static struct sidtab_entry *sidtab_do_lookup(struct sidtab *s, u32 index,
if (!entry->ptr_inner) { if (!entry->ptr_inner) {
if (alloc) if (alloc)
entry->ptr_inner = kzalloc(SIDTAB_NODE_ALLOC_SIZE, entry->ptr_inner = kzalloc(
GFP_ATOMIC); SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC);
if (!entry->ptr_inner) if (!entry->ptr_inner)
return NULL; return NULL;
} }
} }
if (!entry->ptr_leaf) { if (!entry->ptr_leaf) {
if (alloc) if (alloc)
entry->ptr_leaf = kzalloc(SIDTAB_NODE_ALLOC_SIZE, entry->ptr_leaf =
GFP_ATOMIC); kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_ATOMIC);
if (!entry->ptr_leaf) if (!entry->ptr_leaf)
return NULL; return NULL;
} }
...@@ -262,8 +265,7 @@ struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid) ...@@ -262,8 +265,7 @@ struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid)
return sidtab_search_core(s, sid, 1); return sidtab_search_core(s, sid, 1);
} }
int sidtab_context_to_sid(struct sidtab *s, struct context *context, int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid)
u32 *sid)
{ {
unsigned long flags; unsigned long flags;
u32 count, hash = context_compute_hash(context); u32 count, hash = context_compute_hash(context);
...@@ -327,8 +329,8 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, ...@@ -327,8 +329,8 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
goto out_unlock; goto out_unlock;
} }
rc = services_convert_context(convert->args, rc = services_convert_context(convert->args, context,
context, &dst_convert->context, &dst_convert->context,
GFP_ATOMIC); GFP_ATOMIC);
if (rc) { if (rc) {
context_destroy(&dst->context); context_destroy(&dst->context);
...@@ -338,8 +340,8 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, ...@@ -338,8 +340,8 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
dst_convert->hash = context_compute_hash(&dst_convert->context); dst_convert->hash = context_compute_hash(&dst_convert->context);
target->count = count + 1; target->count = count + 1;
hash_add_rcu(target->context_to_sid, hash_add_rcu(target->context_to_sid, &dst_convert->list,
&dst_convert->list, dst_convert->hash); dst_convert->hash);
} }
if (context->len) if (context->len)
...@@ -373,8 +375,8 @@ static void sidtab_convert_hashtable(struct sidtab *s, u32 count) ...@@ -373,8 +375,8 @@ static void sidtab_convert_hashtable(struct sidtab *s, u32 count)
} }
static int sidtab_convert_tree(union sidtab_entry_inner *edst, static int sidtab_convert_tree(union sidtab_entry_inner *edst,
union sidtab_entry_inner *esrc, union sidtab_entry_inner *esrc, u32 *pos,
u32 *pos, u32 count, u32 level, u32 count, u32 level,
struct sidtab_convert_params *convert) struct sidtab_convert_params *convert)
{ {
int rc; int rc;
...@@ -382,8 +384,8 @@ static int sidtab_convert_tree(union sidtab_entry_inner *edst, ...@@ -382,8 +384,8 @@ static int sidtab_convert_tree(union sidtab_entry_inner *edst,
if (level != 0) { if (level != 0) {
if (!edst->ptr_inner) { if (!edst->ptr_inner) {
edst->ptr_inner = kzalloc(SIDTAB_NODE_ALLOC_SIZE, edst->ptr_inner =
GFP_KERNEL); kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_KERNEL);
if (!edst->ptr_inner) if (!edst->ptr_inner)
return -ENOMEM; return -ENOMEM;
} }
...@@ -399,17 +401,18 @@ static int sidtab_convert_tree(union sidtab_entry_inner *edst, ...@@ -399,17 +401,18 @@ static int sidtab_convert_tree(union sidtab_entry_inner *edst,
} }
} else { } else {
if (!edst->ptr_leaf) { if (!edst->ptr_leaf) {
edst->ptr_leaf = kzalloc(SIDTAB_NODE_ALLOC_SIZE, edst->ptr_leaf =
GFP_KERNEL); kzalloc(SIDTAB_NODE_ALLOC_SIZE, GFP_KERNEL);
if (!edst->ptr_leaf) if (!edst->ptr_leaf)
return -ENOMEM; return -ENOMEM;
} }
i = 0; i = 0;
while (i < SIDTAB_LEAF_ENTRIES && *pos < count) { while (i < SIDTAB_LEAF_ENTRIES && *pos < count) {
rc = services_convert_context(convert->args, rc = services_convert_context(
&esrc->ptr_leaf->entries[i].context, convert->args,
&edst->ptr_leaf->entries[i].context, &esrc->ptr_leaf->entries[i].context,
GFP_KERNEL); &edst->ptr_leaf->entries[i].context,
GFP_KERNEL);
if (rc) if (rc)
return rc; return rc;
(*pos)++; (*pos)++;
...@@ -489,13 +492,15 @@ void sidtab_cancel_convert(struct sidtab *s) ...@@ -489,13 +492,15 @@ void sidtab_cancel_convert(struct sidtab *s)
spin_unlock_irqrestore(&s->lock, flags); spin_unlock_irqrestore(&s->lock, flags);
} }
void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock) void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags)
__acquires(&s->lock)
{ {
spin_lock_irqsave(&s->lock, *flags); spin_lock_irqsave(&s->lock, *flags);
s->frozen = true; s->frozen = true;
s->convert = NULL; s->convert = NULL;
} }
void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock) void sidtab_freeze_end(struct sidtab *s, unsigned long *flags)
__releases(&s->lock)
{ {
spin_unlock_irqrestore(&s->lock, *flags); spin_unlock_irqrestore(&s->lock, *flags);
} }
...@@ -600,8 +605,8 @@ void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, ...@@ -600,8 +605,8 @@ void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry,
kfree_rcu(victim, rcu_member); kfree_rcu(victim, rcu_member);
} }
int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, char **out,
char **out, u32 *out_len) u32 *out_len)
{ {
struct sidtab_str_cache *cache; struct sidtab_str_cache *cache;
int rc = 0; int rc = 0;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* *
* Copyright (C) 2018 Red Hat, Inc. * Copyright (C) 2018 Red Hat, Inc.
*/ */
#ifndef _SS_SIDTAB_H_ #ifndef _SS_SIDTAB_H_
#define _SS_SIDTAB_H_ #define _SS_SIDTAB_H_
...@@ -29,25 +30,26 @@ struct sidtab_entry { ...@@ -29,25 +30,26 @@ struct sidtab_entry {
union sidtab_entry_inner { union sidtab_entry_inner {
struct sidtab_node_inner *ptr_inner; struct sidtab_node_inner *ptr_inner;
struct sidtab_node_leaf *ptr_leaf; struct sidtab_node_leaf *ptr_leaf;
}; };
/* align node size to page boundary */ /* align node size to page boundary */
#define SIDTAB_NODE_ALLOC_SHIFT PAGE_SHIFT #define SIDTAB_NODE_ALLOC_SHIFT PAGE_SHIFT
#define SIDTAB_NODE_ALLOC_SIZE PAGE_SIZE #define SIDTAB_NODE_ALLOC_SIZE PAGE_SIZE
#define size_to_shift(size) ((size) == 1 ? 1 : (const_ilog2((size) - 1) + 1)) #define size_to_shift(size) ((size) == 1 ? 1 : (const_ilog2((size)-1) + 1))
#define SIDTAB_INNER_SHIFT \ #define SIDTAB_INNER_SHIFT \
(SIDTAB_NODE_ALLOC_SHIFT - size_to_shift(sizeof(union sidtab_entry_inner))) (SIDTAB_NODE_ALLOC_SHIFT - \
size_to_shift(sizeof(union sidtab_entry_inner)))
#define SIDTAB_INNER_ENTRIES ((size_t)1 << SIDTAB_INNER_SHIFT) #define SIDTAB_INNER_ENTRIES ((size_t)1 << SIDTAB_INNER_SHIFT)
#define SIDTAB_LEAF_ENTRIES \ #define SIDTAB_LEAF_ENTRIES \
(SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry)) (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry))
#define SIDTAB_MAX_BITS 32 #define SIDTAB_MAX_BITS 32
#define SIDTAB_MAX U32_MAX #define SIDTAB_MAX U32_MAX
/* ensure enough tree levels for SIDTAB_MAX entries */ /* ensure enough tree levels for SIDTAB_MAX entries */
#define SIDTAB_MAX_LEVEL \ #define SIDTAB_MAX_LEVEL \
DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \ DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \
SIDTAB_INNER_SHIFT) SIDTAB_INNER_SHIFT)
...@@ -69,7 +71,7 @@ struct sidtab_convert_params { ...@@ -69,7 +71,7 @@ struct sidtab_convert_params {
struct sidtab *target; struct sidtab *target;
}; };
#define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS #define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS
#define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS)
struct sidtab { struct sidtab {
...@@ -125,8 +127,10 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params); ...@@ -125,8 +127,10 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params);
void sidtab_cancel_convert(struct sidtab *s); void sidtab_cancel_convert(struct sidtab *s);
void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock); void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags)
void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock); __acquires(&s->lock);
void sidtab_freeze_end(struct sidtab *s, unsigned long *flags)
__releases(&s->lock);
int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid);
...@@ -137,8 +141,8 @@ int sidtab_hash_stats(struct sidtab *sidtab, char *page); ...@@ -137,8 +141,8 @@ int sidtab_hash_stats(struct sidtab *sidtab, char *page);
#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0
void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry,
const char *str, u32 str_len); const char *str, u32 str_len);
int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, char **out,
char **out, u32 *out_len); u32 *out_len);
#else #else
static inline void sidtab_sid2str_put(struct sidtab *s, static inline void sidtab_sid2str_put(struct sidtab *s,
struct sidtab_entry *entry, struct sidtab_entry *entry,
...@@ -146,13 +150,11 @@ static inline void sidtab_sid2str_put(struct sidtab *s, ...@@ -146,13 +150,11 @@ static inline void sidtab_sid2str_put(struct sidtab *s,
{ {
} }
static inline int sidtab_sid2str_get(struct sidtab *s, static inline int sidtab_sid2str_get(struct sidtab *s,
struct sidtab_entry *entry, struct sidtab_entry *entry, char **out,
char **out, u32 *out_len) u32 *out_len)
{ {
return -ENOENT; return -ENOENT;
} }
#endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */ #endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */
#endif /* _SS_SIDTAB_H_ */ #endif /* _SS_SIDTAB_H_ */
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -19,7 +20,8 @@ static unsigned int symhash(const void *key) ...@@ -19,7 +20,8 @@ static unsigned int symhash(const void *key)
keyp = key; keyp = key;
size = strlen(keyp); size = strlen(keyp);
for (p = keyp; (p - keyp) < size; p++) for (p = keyp; (p - keyp) < size; p++)
val = (val << 4 | (val >> (8*sizeof(unsigned int)-4))) ^ (*p); val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^
(*p);
return val; return val;
} }
......
...@@ -7,14 +7,15 @@ ...@@ -7,14 +7,15 @@
* *
* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/ */
#ifndef _SS_SYMTAB_H_ #ifndef _SS_SYMTAB_H_
#define _SS_SYMTAB_H_ #define _SS_SYMTAB_H_
#include "hashtab.h" #include "hashtab.h"
struct symtab { struct symtab {
struct hashtab table; /* hash table (keyed on a string) */ struct hashtab table; /* hash table (keyed on a string) */
u32 nprim; /* number of primary names in table */ u32 nprim; /* number of primary names in table */
}; };
int symtab_init(struct symtab *s, u32 size); int symtab_init(struct symtab *s, u32 size);
...@@ -22,6 +23,4 @@ int symtab_init(struct symtab *s, u32 size); ...@@ -22,6 +23,4 @@ int symtab_init(struct symtab *s, u32 size);
int symtab_insert(struct symtab *s, char *name, void *datum); int symtab_insert(struct symtab *s, char *name, void *datum);
void *symtab_search(struct symtab *s, const char *name); void *symtab_search(struct symtab *s, const char *name);
#endif /* _SS_SYMTAB_H_ */ #endif /* _SS_SYMTAB_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment