#include "audit.h"
#include "avc_ss.h"
+struct selinux_state selinux_state;
+
/* SECMARK reference count */
static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
-int selinux_enforcing;
+static int selinux_enforcing_boot;
static int __init enforcing_setup(char *str)
{
unsigned long enforcing;
if (!kstrtoul(str, 0, &enforcing))
- selinux_enforcing = enforcing ? 1 : 0;
+ selinux_enforcing_boot = enforcing ? 1 : 0;
return 1;
}
__setup("enforcing=", enforcing_setup);
+#else
+#define selinux_enforcing_boot 1
#endif
#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
int selinux_enabled = 1;
#endif
+static unsigned int selinux_checkreqprot_boot =
+ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
+
+static int __init checkreqprot_setup(char *str)
+{
+ unsigned long checkreqprot;
+
+ if (!kstrtoul(str, 0, &checkreqprot))
+ selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
+ return 1;
+}
+__setup("checkreqprot=", checkreqprot_setup);
+
static struct kmem_cache *sel_inode_cache;
static struct kmem_cache *file_security_cache;
*/
static int selinux_secmark_enabled(void)
{
- return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
+ return (selinux_policycap_alwaysnetwork() ||
+ atomic_read(&selinux_secmark_refcount));
}
/**
*/
static int selinux_peerlbl_enabled(void)
{
- return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
+ return (selinux_policycap_alwaysnetwork() ||
+ netlbl_enabled() || selinux_xfrm_enabled());
}
static int selinux_netcache_avc_callback(u32 event)
might_sleep_if(may_sleep);
- if (ss_initialized && isec->initialized != LABEL_INITIALIZED) {
+ if (selinux_state.initialized &&
+ isec->initialized != LABEL_INITIALIZED) {
if (!may_sleep)
return -ECHILD;
!strcmp(sb->s_type->name, "debugfs") ||
!strcmp(sb->s_type->name, "tracefs") ||
!strcmp(sb->s_type->name, "rootfs") ||
- (selinux_policycap_cgroupseclabel &&
+ (selinux_policycap_cgroupseclabel() &&
(!strcmp(sb->s_type->name, "cgroup") ||
!strcmp(sb->s_type->name, "cgroup2")));
}
if (!(sbsec->flags & SE_SBINITIALIZED))
return -EINVAL;
- if (!ss_initialized)
+ if (!selinux_state.initialized)
return -EINVAL;
/* make sure we always check enough bits to cover the mask */
i = 0;
if (sbsec->flags & FSCONTEXT_MNT) {
- rc = security_sid_to_context(sbsec->sid, &context, &len);
+ rc = security_sid_to_context(&selinux_state, sbsec->sid,
+ &context, &len);
if (rc)
goto out_free;
opts->mnt_opts[i] = context;
opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
}
if (sbsec->flags & CONTEXT_MNT) {
- rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
+ rc = security_sid_to_context(&selinux_state,
+ sbsec->mntpoint_sid,
+ &context, &len);
if (rc)
goto out_free;
opts->mnt_opts[i] = context;
opts->mnt_opts_flags[i++] = CONTEXT_MNT;
}
if (sbsec->flags & DEFCONTEXT_MNT) {
- rc = security_sid_to_context(sbsec->def_sid, &context, &len);
+ rc = security_sid_to_context(&selinux_state, sbsec->def_sid,
+ &context, &len);
if (rc)
goto out_free;
opts->mnt_opts[i] = context;
struct dentry *root = sbsec->sb->s_root;
struct inode_security_struct *isec = backing_inode_security(root);
- rc = security_sid_to_context(isec->sid, &context, &len);
+ rc = security_sid_to_context(&selinux_state, isec->sid,
+ &context, &len);
if (rc)
goto out_free;
opts->mnt_opts[i] = context;
mutex_lock(&sbsec->lock);
- if (!ss_initialized) {
+ if (!selinux_state.initialized) {
if (!num_opts) {
/* Defer initialization until selinux_complete_init,
after the initial policy is loaded and the security
if (flags[i] == SBLABEL_MNT)
continue;
- rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
+ rc = security_context_str_to_sid(&selinux_state,
+ mount_options[i], &sid,
+ GFP_KERNEL);
if (rc) {
printk(KERN_WARNING "SELinux: security_context_str_to_sid"
"(%s) failed for (dev %s, type %s) errno=%d\n",
* Determine the labeling behavior to use for this
* filesystem type.
*/
- rc = security_fs_use(sb);
+ rc = security_fs_use(&selinux_state, sb);
if (rc) {
printk(KERN_WARNING
"%s: security_fs_use(%s) returned %d\n",
}
if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
- rc = security_transition_sid(current_sid(), current_sid(),
+ rc = security_transition_sid(&selinux_state,
+ current_sid(),
+ current_sid(),
SECCLASS_FILE, NULL,
&sbsec->mntpoint_sid);
if (rc)
* if the parent was able to be mounted it clearly had no special lsm
* mount options. thus we can safely deal with this superblock later
*/
- if (!ss_initialized)
+ if (!selinux_state.initialized)
return 0;
/*
if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
!(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
- rc = security_fs_use(newsb);
+ rc = security_fs_use(&selinux_state, newsb);
if (rc)
goto out;
}
static inline u16 socket_type_to_security_class(int family, int type, int protocol)
{
- int extsockclass = selinux_policycap_extsockclass;
+ int extsockclass = selinux_policycap_extsockclass();
switch (family) {
case PF_UNIX:
path++;
}
}
- rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
+ rc = security_genfs_sid(&selinux_state, sb->s_type->name,
+ path, tclass, sid);
}
free_page((unsigned long)buffer);
return rc;
sid = sbsec->def_sid;
rc = 0;
} else {
- rc = security_context_to_sid_default(context, rc, &sid,
+ rc = security_context_to_sid_default(&selinux_state,
+ context, rc, &sid,
sbsec->def_sid,
GFP_NOFS);
if (rc) {
sid = sbsec->sid;
/* Try to obtain a transition SID. */
- rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid);
+ rc = security_transition_sid(&selinux_state, task_sid, sid,
+ sclass, NULL, &sid);
if (rc)
goto out;
break;
*_new_isid = tsec->create_sid;
} else {
const struct inode_security_struct *dsec = inode_security(dir);
- return security_transition_sid(tsec->sid, dsec->sid, tclass,
+ return security_transition_sid(&selinux_state, tsec->sid,
+ dsec->sid, tclass,
name, _new_isid);
}
u32 av = file_to_av(file);
struct inode *inode = file_inode(file);
- if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
+ if (selinux_policycap_openperm() &&
+ inode->i_sb->s_magic != SOCKFS_MAGIC)
av |= FILE__OPEN;
return av;
* policy allows the corresponding permission between
* the old and new contexts.
*/
- if (selinux_policycap_nnp_nosuid_transition) {
+ if (selinux_policycap_nnp_nosuid_transition()) {
av = 0;
if (nnp)
av |= PROCESS2__NNP_TRANSITION;
* i.e. SIDs that are guaranteed to only be allowed a subset
* of the permissions of the current SID.
*/
- rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
+ rc = security_bounded_transition(&selinux_state, old_tsec->sid,
+ new_tsec->sid);
if (!rc)
return 0;
return rc;
} else {
/* Check for a default transition on this program. */
- rc = security_transition_sid(old_tsec->sid, isec->sid,
- SECCLASS_PROCESS, NULL,
+ rc = security_transition_sid(&selinux_state, old_tsec->sid,
+ isec->sid, SECCLASS_PROCESS, NULL,
&new_tsec->sid);
if (rc)
return rc;
if (flags[i] == SBLABEL_MNT)
continue;
- rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
+ rc = security_context_str_to_sid(&selinux_state,
+ mount_options[i], &sid,
+ GFP_KERNEL);
if (rc) {
printk(KERN_WARNING "SELinux: security_context_str_to_sid"
"(%s) failed for (dev %s, type %s) errno=%d\n",
if (rc)
return rc;
- return security_sid_to_context(newsid, (char **)ctx, ctxlen);
+ return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
+ ctxlen);
}
static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
isec->initialized = LABEL_INITIALIZED;
}
- if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
+ if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))
return -EOPNOTSUPP;
if (name)
*name = XATTR_SELINUX_SUFFIX;
if (value && len) {
- rc = security_sid_to_context_force(newsid, &context, &clen);
+ rc = security_sid_to_context_force(&selinux_state, newsid,
+ &context, &clen);
if (rc)
return rc;
*value = context;
ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
return dentry_has_perm(cred, dentry, FILE__SETATTR);
- if (selinux_policycap_openperm &&
+ if (selinux_policycap_openperm() &&
inode->i_sb->s_magic != SOCKFS_MAGIC &&
(ia_valid & ATTR_SIZE) &&
!(ia_valid & ATTR_FILE))
if (rc)
return rc;
- rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
+ rc = security_context_to_sid(&selinux_state, value, size, &newsid,
+ GFP_KERNEL);
if (rc == -EINVAL) {
if (!has_cap_mac_admin(true)) {
struct audit_buffer *ab;
return rc;
}
- rc = security_context_to_sid_force(value, size, &newsid);
+ rc = security_context_to_sid_force(&selinux_state, value,
+ size, &newsid);
}
if (rc)
return rc;
if (rc)
return rc;
- rc = security_validate_transition(isec->sid, newsid, sid,
- isec->sclass);
+ rc = security_validate_transition(&selinux_state, isec->sid, newsid,
+ sid, isec->sclass);
if (rc)
return rc;
return;
}
- rc = security_context_to_sid_force(value, size, &newsid);
+ rc = security_context_to_sid_force(&selinux_state, value, size,
+ &newsid);
if (rc) {
printk(KERN_ERR "SELinux: unable to map context to SID"
"for (%s, %lu), rc=%d\n",
*/
isec = inode_security(inode);
if (has_cap_mac_admin(false))
- error = security_sid_to_context_force(isec->sid, &context,
+ error = security_sid_to_context_force(&selinux_state,
+ isec->sid, &context,
&size);
else
- error = security_sid_to_context(isec->sid, &context, &size);
+ error = security_sid_to_context(&selinux_state, isec->sid,
+ &context, &size);
if (error)
return error;
error = size;
if (!value || !size)
return -EACCES;
- rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
+ rc = security_context_to_sid(&selinux_state, value, size, &newsid,
+ GFP_KERNEL);
if (rc)
return rc;
return rc;
}
- if (selinux_checkreqprot)
+ if (selinux_state.checkreqprot)
prot = reqprot;
return file_map_prot_check(file, prot,
const struct cred *cred = current_cred();
u32 sid = cred_sid(cred);
- if (selinux_checkreqprot)
+ if (selinux_state.checkreqprot)
prot = reqprot;
if (default_noexec &&
if (unlikely(err))
return -EACCES;
- err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
+ err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
+ nlbl_type, xfrm_sid, sid);
if (unlikely(err)) {
printk(KERN_WARNING
"SELinux: failure in selinux_skb_peerlbl_sid(),"
int err = 0;
if (skb_sid != SECSID_NULL)
- err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
+ err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
+ conn_sid);
else
*conn_sid = sk_sid;
return 0;
}
- return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
- socksid);
+ return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
+ secclass, NULL, socksid);
}
static int sock_has_perm(struct sock *sk, u32 perms)
/* server child socket */
sksec_new->peer_sid = sksec_sock->sid;
- err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
- &sksec_new->sid);
+ err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
+ sksec_sock->sid, &sksec_new->sid);
if (err)
return err;
* to the selinux_sock_rcv_skb_compat() function to deal with the
* special handling. We do this in an attempt to keep this function
* as fast and as clean as possible. */
- if (!selinux_policycap_netpeer)
+ if (!selinux_policycap_netpeer())
return selinux_sock_rcv_skb_compat(sk, skb, family);
secmark_active = selinux_secmark_enabled();
if (peer_sid == SECSID_NULL)
return -ENOPROTOOPT;
- err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
+ err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
+ &scontext_len);
if (err)
return err;
u32 conn_sid;
int err = 0;
- if (!selinux_policycap_extsockclass)
+ if (!selinux_policycap_extsockclass())
return 0;
peerlbl_active = selinux_peerlbl_enabled();
struct sockaddr *addr;
struct socket *sock;
- if (!selinux_policycap_extsockclass)
+ if (!selinux_policycap_extsockclass())
return 0;
/* Process one or more addresses that may be IPv4 or IPv6 */
/* If policy does not support SECCLASS_SCTP_SOCKET then call
* the non-sctp clone version.
*/
- if (!selinux_policycap_extsockclass)
+ if (!selinux_policycap_extsockclass())
return selinux_sk_clone_security(sk, newsk);
newsksec->sid = ep->secid;
sk->sk_protocol, nlh->nlmsg_type,
secclass_map[sksec->sclass - 1].name,
task_pid_nr(current), current->comm);
- if (!selinux_enforcing || security_get_allow_unknown())
+ if (!is_enforcing(&selinux_state) ||
+ security_get_allow_unknown(&selinux_state))
err = 0;
}
u8 netlbl_active;
u8 peerlbl_active;
- if (!selinux_policycap_netpeer)
+ if (!selinux_policycap_netpeer())
return NF_ACCEPT;
secmark_active = selinux_secmark_enabled();
* to the selinux_ip_postroute_compat() function to deal with the
* special handling. We do this in an attempt to keep this function
* as fast and as clean as possible. */
- if (!selinux_policycap_netpeer)
+ if (!selinux_policycap_netpeer())
return selinux_ip_postroute_compat(skb, ifindex, family);
secmark_active = selinux_secmark_enabled();
* Compute new sid based on current process and
* message queue this message will be stored in
*/
- rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
- NULL, &msec->sid);
+ rc = security_transition_sid(&selinux_state, sid, isec->sid,
+ SECCLASS_MSG, NULL, &msec->sid);
if (rc)
return rc;
}
if (!sid)
return 0;
- error = security_sid_to_context(sid, value, &len);
+ error = security_sid_to_context(&selinux_state, sid, value, &len);
if (error)
return error;
return len;
str[size-1] = 0;
size--;
}
- error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
+ error = security_context_to_sid(&selinux_state, value, size,
+ &sid, GFP_KERNEL);
if (error == -EINVAL && !strcmp(name, "fscreate")) {
if (!has_cap_mac_admin(true)) {
struct audit_buffer *ab;
return error;
}
- error = security_context_to_sid_force(value, size,
- &sid);
+ error = security_context_to_sid_force(
+ &selinux_state,
+ value, size, &sid);
}
if (error)
return error;
/* Only allow single threaded processes to change context */
error = -EPERM;
if (!current_is_single_threaded()) {
- error = security_bounded_transition(tsec->sid, sid);
+ error = security_bounded_transition(&selinux_state,
+ tsec->sid, sid);
if (error)
goto abort_change;
}
static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
{
- return security_sid_to_context(secid, secdata, seclen);
+ return security_sid_to_context(&selinux_state, secid,
+ secdata, seclen);
}
static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
- return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
+ return security_context_to_sid(&selinux_state, secdata, seclen,
+ secid, GFP_KERNEL);
}
static void selinux_release_secctx(char *secdata, u32 seclen)
unsigned len;
int rc;
- rc = security_sid_to_context(ksec->sid, &context, &len);
+ rc = security_sid_to_context(&selinux_state, ksec->sid,
+ &context, &len);
if (!rc)
rc = len;
*_buffer = context;
struct ib_security_struct *sec = ib_sec;
struct lsm_ibendport_audit ibendport;
- err = security_ib_endport_sid(dev_name, port_num, &sid);
+ err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
+ &sid);
if (err)
return err;
printk(KERN_INFO "SELinux: Initializing.\n");
+ memset(&selinux_state, 0, sizeof(selinux_state));
+ set_enforcing(&selinux_state, selinux_enforcing_boot);
+ selinux_state.checkreqprot = selinux_checkreqprot_boot;
+ selinux_ss_init(&selinux_state.ss);
+
/* Set the security state for the initial task. */
cred_init_security();
0, SLAB_PANIC, NULL);
avc_init();
+ avtab_cache_init();
+
+ ebitmap_cache_init();
+
+ hashtab_cache_init();
+
security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
panic("SELinux: Unable to register AVC LSM notifier callback\n");
- if (selinux_enforcing)
+ if (selinux_enforcing_boot)
printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
else
printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
#endif /* CONFIG_NETFILTER */
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-static int selinux_disabled;
-
-int selinux_disable(void)
+int selinux_disable(struct selinux_state *state)
{
- if (ss_initialized) {
+ if (state->initialized) {
/* Not permitted after initial policy load. */
return -EINVAL;
}
- if (selinux_disabled) {
+ if (state->disabled) {
/* Only do this once. */
return -EINVAL;
}
+ state->disabled = 1;
+
printk(KERN_INFO "SELinux: Disabled at runtime.\n");
- selinux_disabled = 1;
selinux_enabled = 0;
security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
"nnp_nosuid_transition"
};
-int selinux_policycap_netpeer;
-int selinux_policycap_openperm;
-int selinux_policycap_extsockclass;
-int selinux_policycap_alwaysnetwork;
-int selinux_policycap_cgroupseclabel;
-int selinux_policycap_nnp_nosuid_transition;
+static struct selinux_ss selinux_ss;
-static DEFINE_RWLOCK(policy_rwlock);
-
-static struct sidtab sidtab;
-struct policydb policydb;
-int ss_initialized;
-
-/*
- * The largest sequence number that has been used when
- * providing an access decision to the access vector cache.
- * The sequence number only changes when a policy change
- * occurs.
- */
-static u32 latest_granting;
+void selinux_ss_init(struct selinux_ss **ss)
+{
+ rwlock_init(&selinux_ss.policy_rwlock);
+ mutex_init(&selinux_ss.status_lock);
+ *ss = &selinux_ss;
+}
/* Forward declaration. */
-static int context_struct_to_string(struct context *context, char **scontext,
+static int context_struct_to_string(struct policydb *policydb,
+ struct context *context,
+ char **scontext,
u32 *scontext_len);
-static void context_struct_compute_av(struct context *scontext,
- struct context *tcontext,
- u16 tclass,
- struct av_decision *avd,
- struct extended_perms *xperms);
-
-struct selinux_mapping {
- u16 value; /* policy value */
- unsigned num_perms;
- u32 perms[sizeof(u32) * 8];
-};
-
-static struct selinux_mapping *current_mapping;
-static u16 current_mapping_size;
+static void context_struct_compute_av(struct policydb *policydb,
+ struct context *scontext,
+ struct context *tcontext,
+ u16 tclass,
+ struct av_decision *avd,
+ struct extended_perms *xperms);
static int selinux_set_mapping(struct policydb *pol,
struct security_class_mapping *map,
- struct selinux_mapping **out_map_p,
- u16 *out_map_size)
+ struct selinux_map *out_map)
{
- struct selinux_mapping *out_map = NULL;
- size_t size = sizeof(struct selinux_mapping);
u16 i, j;
unsigned k;
bool print_unknown_handle = false;
i++;
/* Allocate space for the class records, plus one for class zero */
- out_map = kcalloc(++i, size, GFP_ATOMIC);
- if (!out_map)
+ out_map->mapping = kcalloc(++i, sizeof(*out_map->mapping), GFP_ATOMIC);
+ if (!out_map->mapping)
return -ENOMEM;
/* Store the raw class and permission values */
j = 0;
while (map[j].name) {
struct security_class_mapping *p_in = map + (j++);
- struct selinux_mapping *p_out = out_map + j;
+ struct selinux_mapping *p_out = out_map->mapping + j;
/* An empty class string skips ahead */
if (!strcmp(p_in->name, "")) {
printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n",
pol->allow_unknown ? "allowed" : "denied");
- *out_map_p = out_map;
- *out_map_size = i;
+ out_map->size = i;
return 0;
err:
- kfree(out_map);
+ kfree(out_map->mapping);
+ out_map->mapping = NULL;
return -EINVAL;
}
* Get real, policy values from mapped values
*/
-static u16 unmap_class(u16 tclass)
+static u16 unmap_class(struct selinux_map *map, u16 tclass)
{
- if (tclass < current_mapping_size)
- return current_mapping[tclass].value;
+ if (tclass < map->size)
+ return map->mapping[tclass].value;
return tclass;
}
/*
* Get kernel value for class from its policy value
*/
-static u16 map_class(u16 pol_value)
+static u16 map_class(struct selinux_map *map, u16 pol_value)
{
u16 i;
- for (i = 1; i < current_mapping_size; i++) {
- if (current_mapping[i].value == pol_value)
+ for (i = 1; i < map->size; i++) {
+ if (map->mapping[i].value == pol_value)
return i;
}
return SECCLASS_NULL;
}
-static void map_decision(u16 tclass, struct av_decision *avd,
+static void map_decision(struct selinux_map *map,
+ u16 tclass, struct av_decision *avd,
int allow_unknown)
{
- if (tclass < current_mapping_size) {
- unsigned i, n = current_mapping[tclass].num_perms;
+ if (tclass < map->size) {
+ struct selinux_mapping *mapping = &map->mapping[tclass];
+ unsigned int i, n = mapping->num_perms;
u32 result;
for (i = 0, result = 0; i < n; i++) {
- if (avd->allowed & current_mapping[tclass].perms[i])
+ if (avd->allowed & mapping->perms[i])
result |= 1<<i;
- if (allow_unknown && !current_mapping[tclass].perms[i])
+ if (allow_unknown && !mapping->perms[i])
result |= 1<<i;
}
avd->allowed = result;
for (i = 0, result = 0; i < n; i++)
- if (avd->auditallow & current_mapping[tclass].perms[i])
+ if (avd->auditallow & mapping->perms[i])
result |= 1<<i;
avd->auditallow = result;
for (i = 0, result = 0; i < n; i++) {
- if (avd->auditdeny & current_mapping[tclass].perms[i])
+ if (avd->auditdeny & mapping->perms[i])
result |= 1<<i;
- if (!allow_unknown && !current_mapping[tclass].perms[i])
+ if (!allow_unknown && !mapping->perms[i])
result |= 1<<i;
}
/*
}
}
-int security_mls_enabled(void)
+int security_mls_enabled(struct selinux_state *state)
{
- return policydb.mls_enabled;
+ struct policydb *p = &state->ss->policydb;
+
+ return p->mls_enabled;
}
/*
* of the process performing the transition. All other callers of
* constraint_expr_eval should pass in NULL for xcontext.
*/
-static int constraint_expr_eval(struct context *scontext,
+static int constraint_expr_eval(struct policydb *policydb,
+ struct context *scontext,
struct context *tcontext,
struct context *xcontext,
struct constraint_expr *cexpr)
case CEXPR_ROLE:
val1 = scontext->role;
val2 = tcontext->role;
- r1 = policydb.role_val_to_struct[val1 - 1];
- r2 = policydb.role_val_to_struct[val2 - 1];
+ r1 = policydb->role_val_to_struct[val1 - 1];
+ r2 = policydb->role_val_to_struct[val2 - 1];
switch (e->op) {
case CEXPR_DOM:
s[++sp] = ebitmap_get_bit(&r1->dominates,
return 0;
}
-static void security_dump_masked_av(struct context *scontext,
+static void security_dump_masked_av(struct policydb *policydb,
+ struct context *scontext,
struct context *tcontext,
u16 tclass,
u32 permissions,
if (!permissions)
return;
- tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1);
- tclass_dat = policydb.class_val_to_struct[tclass - 1];
+ tclass_name = sym_name(policydb, SYM_CLASSES, tclass - 1);
+ tclass_dat = policydb->class_val_to_struct[tclass - 1];
common_dat = tclass_dat->comdatum;
/* init permission_names */
goto out;
/* get scontext/tcontext in text form */
- if (context_struct_to_string(scontext,
+ if (context_struct_to_string(policydb, scontext,
&scontext_name, &length) < 0)
goto out;
- if (context_struct_to_string(tcontext,
+ if (context_struct_to_string(policydb, tcontext,
&tcontext_name, &length) < 0)
goto out;
* security_boundary_permission - drops violated permissions
* on boundary constraint.
*/
-static void type_attribute_bounds_av(struct context *scontext,
+static void type_attribute_bounds_av(struct policydb *policydb,
+ struct context *scontext,
struct context *tcontext,
u16 tclass,
struct av_decision *avd)
struct type_datum *target;
u32 masked = 0;
- source = flex_array_get_ptr(policydb.type_val_to_struct_array,
+ source = flex_array_get_ptr(policydb->type_val_to_struct_array,
scontext->type - 1);
BUG_ON(!source);
if (!source->bounds)
return;
- target = flex_array_get_ptr(policydb.type_val_to_struct_array,
+ target = flex_array_get_ptr(policydb->type_val_to_struct_array,
tcontext->type - 1);
BUG_ON(!target);
tcontextp = &lo_tcontext;
}
- context_struct_compute_av(&lo_scontext,
+ context_struct_compute_av(policydb, &lo_scontext,
tcontextp,
tclass,
&lo_avd,
avd->allowed &= ~masked;
/* audit masked permissions */
- security_dump_masked_av(scontext, tcontext,
+ security_dump_masked_av(policydb, scontext, tcontext,
tclass, masked, "bounds");
}
* Compute access vectors and extended permissions based on a context
* structure pair for the permissions in a particular class.
*/
-static void context_struct_compute_av(struct context *scontext,
- struct context *tcontext,
- u16 tclass,
- struct av_decision *avd,
- struct extended_perms *xperms)
+static void context_struct_compute_av(struct policydb *policydb,
+ struct context *scontext,
+ struct context *tcontext,
+ u16 tclass,
+ struct av_decision *avd,
+ struct extended_perms *xperms)
{
struct constraint_node *constraint;
struct role_allow *ra;
xperms->len = 0;
}
- if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+ if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) {
if (printk_ratelimit())
printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass);
return;
}
- tclass_datum = policydb.class_val_to_struct[tclass - 1];
+ tclass_datum = policydb->class_val_to_struct[tclass - 1];
/*
* If a specific type enforcement rule was defined for
*/
avkey.target_class = tclass;
avkey.specified = AVTAB_AV | AVTAB_XPERMS;
- sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1);
+ sattr = flex_array_get(policydb->type_attr_map_array,
+ scontext->type - 1);
BUG_ON(!sattr);
- tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1);
+ tattr = flex_array_get(policydb->type_attr_map_array,
+ tcontext->type - 1);
BUG_ON(!tattr);
ebitmap_for_each_positive_bit(sattr, snode, i) {
ebitmap_for_each_positive_bit(tattr, tnode, j) {
avkey.source_type = i + 1;
avkey.target_type = j + 1;
- for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+ for (node = avtab_search_node(&policydb->te_avtab,
+ &avkey);
node;
node = avtab_search_node_next(node, avkey.specified)) {
if (node->key.specified == AVTAB_ALLOWED)
}
/* Check conditional av table for additional permissions */
- cond_compute_av(&policydb.te_cond_avtab, &avkey,
+ cond_compute_av(&policydb->te_cond_avtab, &avkey,
avd, xperms);
}
constraint = tclass_datum->constraints;
while (constraint) {
if ((constraint->permissions & (avd->allowed)) &&
- !constraint_expr_eval(scontext, tcontext, NULL,
+ !constraint_expr_eval(policydb, scontext, tcontext, NULL,
constraint->expr)) {
avd->allowed &= ~(constraint->permissions);
}
* role is changing, then check the (current_role, new_role)
* pair.
*/
- if (tclass == policydb.process_class &&
- (avd->allowed & policydb.process_trans_perms) &&
+ if (tclass == policydb->process_class &&
+ (avd->allowed & policydb->process_trans_perms) &&
scontext->role != tcontext->role) {
- for (ra = policydb.role_allow; ra; ra = ra->next) {
+ for (ra = policydb->role_allow; ra; ra = ra->next) {
if (scontext->role == ra->role &&
tcontext->role == ra->new_role)
break;
}
if (!ra)
- avd->allowed &= ~policydb.process_trans_perms;
+ avd->allowed &= ~policydb->process_trans_perms;
}
/*
* constraint, lazy checks have to mask any violated
* permission and notice it to userspace via audit.
*/
- type_attribute_bounds_av(scontext, tcontext,
+ type_attribute_bounds_av(policydb, scontext, tcontext,
tclass, avd);
}
-static int security_validtrans_handle_fail(struct context *ocontext,
+static int security_validtrans_handle_fail(struct selinux_state *state,
+ struct context *ocontext,
struct context *ncontext,
struct context *tcontext,
u16 tclass)
{
+ struct policydb *p = &state->ss->policydb;
char *o = NULL, *n = NULL, *t = NULL;
u32 olen, nlen, tlen;
- if (context_struct_to_string(ocontext, &o, &olen))
+ if (context_struct_to_string(p, ocontext, &o, &olen))
goto out;
- if (context_struct_to_string(ncontext, &n, &nlen))
+ if (context_struct_to_string(p, ncontext, &n, &nlen))
goto out;
- if (context_struct_to_string(tcontext, &t, &tlen))
+ if (context_struct_to_string(p, tcontext, &t, &tlen))
goto out;
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
"op=security_validate_transition seresult=denied"
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
- o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+ o, n, t, sym_name(p, SYM_CLASSES, tclass-1));
out:
kfree(o);
kfree(n);
kfree(t);
- if (!selinux_enforcing)
+ if (!is_enforcing(state))
return 0;
return -EPERM;
}
-static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
+static int security_compute_validatetrans(struct selinux_state *state,
+ u32 oldsid, u32 newsid, u32 tasksid,
u16 orig_tclass, bool user)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct context *ocontext;
struct context *ncontext;
struct context *tcontext;
u16 tclass;
int rc = 0;
- if (!ss_initialized)
+
+ if (!state->initialized)
return 0;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
if (!user)
- tclass = unmap_class(orig_tclass);
+ tclass = unmap_class(&state->ss->map, orig_tclass);
else
tclass = orig_tclass;
- if (!tclass || tclass > policydb.p_classes.nprim) {
+ if (!tclass || tclass > policydb->p_classes.nprim) {
rc = -EINVAL;
goto out;
}
- tclass_datum = policydb.class_val_to_struct[tclass - 1];
+ tclass_datum = policydb->class_val_to_struct[tclass - 1];
- ocontext = sidtab_search(&sidtab, oldsid);
+ ocontext = sidtab_search(sidtab, oldsid);
if (!ocontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, oldsid);
goto out;
}
- ncontext = sidtab_search(&sidtab, newsid);
+ ncontext = sidtab_search(sidtab, newsid);
if (!ncontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, newsid);
goto out;
}
- tcontext = sidtab_search(&sidtab, tasksid);
+ tcontext = sidtab_search(sidtab, tasksid);
if (!tcontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, tasksid);
constraint = tclass_datum->validatetrans;
while (constraint) {
- if (!constraint_expr_eval(ocontext, ncontext, tcontext,
- constraint->expr)) {
+ if (!constraint_expr_eval(policydb, ocontext, ncontext,
+ tcontext, constraint->expr)) {
if (user)
rc = -EPERM;
else
- rc = security_validtrans_handle_fail(ocontext,
+ rc = security_validtrans_handle_fail(state,
+ ocontext,
ncontext,
tcontext,
tclass);
}
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
-int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid,
- u16 tclass)
+int security_validate_transition_user(struct selinux_state *state,
+ u32 oldsid, u32 newsid, u32 tasksid,
+ u16 tclass)
{
- return security_compute_validatetrans(oldsid, newsid, tasksid,
- tclass, true);
+ return security_compute_validatetrans(state, oldsid, newsid, tasksid,
+ tclass, true);
}
-int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+int security_validate_transition(struct selinux_state *state,
+ u32 oldsid, u32 newsid, u32 tasksid,
u16 orig_tclass)
{
- return security_compute_validatetrans(oldsid, newsid, tasksid,
- orig_tclass, false);
+ return security_compute_validatetrans(state, oldsid, newsid, tasksid,
+ orig_tclass, false);
}
/*
* @oldsid : current security identifier
* @newsid : destinated security identifier
*/
-int security_bounded_transition(u32 old_sid, u32 new_sid)
+int security_bounded_transition(struct selinux_state *state,
+ u32 old_sid, u32 new_sid)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct context *old_context, *new_context;
struct type_datum *type;
int index;
int rc;
- if (!ss_initialized)
+ if (!state->initialized)
return 0;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
rc = -EINVAL;
- old_context = sidtab_search(&sidtab, old_sid);
+ old_context = sidtab_search(sidtab, old_sid);
if (!old_context) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
__func__, old_sid);
}
rc = -EINVAL;
- new_context = sidtab_search(&sidtab, new_sid);
+ new_context = sidtab_search(sidtab, new_sid);
if (!new_context) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
__func__, new_sid);
index = new_context->type;
while (true) {
- type = flex_array_get_ptr(policydb.type_val_to_struct_array,
+ type = flex_array_get_ptr(policydb->type_val_to_struct_array,
index - 1);
BUG_ON(!type);
char *new_name = NULL;
u32 length;
- if (!context_struct_to_string(old_context,
+ if (!context_struct_to_string(policydb, old_context,
&old_name, &length) &&
- !context_struct_to_string(new_context,
+ !context_struct_to_string(policydb, new_context,
&new_name, &length)) {
audit_log(current->audit_context,
GFP_ATOMIC, AUDIT_SELINUX_ERR,
kfree(old_name);
}
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
-static void avd_init(struct av_decision *avd)
+static void avd_init(struct selinux_state *state, struct av_decision *avd)
{
avd->allowed = 0;
avd->auditallow = 0;
avd->auditdeny = 0xffffffff;
- avd->seqno = latest_granting;
+ avd->seqno = state->ss->latest_granting;
avd->flags = 0;
}
}
}
-void security_compute_xperms_decision(u32 ssid,
- u32 tsid,
- u16 orig_tclass,
- u8 driver,
- struct extended_perms_decision *xpermd)
+void security_compute_xperms_decision(struct selinux_state *state,
+ u32 ssid,
+ u32 tsid,
+ u16 orig_tclass,
+ u8 driver,
+ struct extended_perms_decision *xpermd)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
u16 tclass;
struct context *scontext, *tcontext;
struct avtab_key avkey;
memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p));
memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
- read_lock(&policy_rwlock);
- if (!ss_initialized)
+ read_lock(&state->ss->policy_rwlock);
+ if (!state->initialized)
goto allow;
- scontext = sidtab_search(&sidtab, ssid);
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
+
+ scontext = sidtab_search(sidtab, ssid);
if (!scontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, ssid);
goto out;
}
- tcontext = sidtab_search(&sidtab, tsid);
+ tcontext = sidtab_search(sidtab, tsid);
if (!tcontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, tsid);
goto out;
}
- tclass = unmap_class(orig_tclass);
+ tclass = unmap_class(&state->ss->map, orig_tclass);
if (unlikely(orig_tclass && !tclass)) {
- if (policydb.allow_unknown)
+ if (policydb->allow_unknown)
goto allow;
goto out;
}
- if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
+ if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) {
pr_warn_ratelimited("SELinux: Invalid class %hu\n", tclass);
goto out;
}
avkey.target_class = tclass;
avkey.specified = AVTAB_XPERMS;
- sattr = flex_array_get(policydb.type_attr_map_array,
+ sattr = flex_array_get(policydb->type_attr_map_array,
scontext->type - 1);
BUG_ON(!sattr);
- tattr = flex_array_get(policydb.type_attr_map_array,
+ tattr = flex_array_get(policydb->type_attr_map_array,
tcontext->type - 1);
BUG_ON(!tattr);
ebitmap_for_each_positive_bit(sattr, snode, i) {
ebitmap_for_each_positive_bit(tattr, tnode, j) {
avkey.source_type = i + 1;
avkey.target_type = j + 1;
- for (node = avtab_search_node(&policydb.te_avtab, &avkey);
+ for (node = avtab_search_node(&policydb->te_avtab,
+ &avkey);
node;
node = avtab_search_node_next(node, avkey.specified))
services_compute_xperms_decision(xpermd, node);
- cond_compute_xperms(&policydb.te_cond_avtab,
+ cond_compute_xperms(&policydb->te_cond_avtab,
&avkey, xpermd);
}
}
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return;
allow:
memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p));
* Compute a set of access vector decisions based on the
* SID pair (@ssid, @tsid) for the permissions in @tclass.
*/
-void security_compute_av(u32 ssid,
+void security_compute_av(struct selinux_state *state,
+ u32 ssid,
u32 tsid,
u16 orig_tclass,
struct av_decision *avd,
struct extended_perms *xperms)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
u16 tclass;
struct context *scontext = NULL, *tcontext = NULL;
- read_lock(&policy_rwlock);
- avd_init(avd);
+ read_lock(&state->ss->policy_rwlock);
+ avd_init(state, avd);
xperms->len = 0;
- if (!ss_initialized)
+ if (!state->initialized)
goto allow;
- scontext = sidtab_search(&sidtab, ssid);
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
+
+ scontext = sidtab_search(sidtab, ssid);
if (!scontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, ssid);
}
/* permissive domain? */
- if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+ if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
avd->flags |= AVD_FLAGS_PERMISSIVE;
- tcontext = sidtab_search(&sidtab, tsid);
+ tcontext = sidtab_search(sidtab, tsid);
if (!tcontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, tsid);
goto out;
}
- tclass = unmap_class(orig_tclass);
+ tclass = unmap_class(&state->ss->map, orig_tclass);
if (unlikely(orig_tclass && !tclass)) {
- if (policydb.allow_unknown)
+ if (policydb->allow_unknown)
goto allow;
goto out;
}
- context_struct_compute_av(scontext, tcontext, tclass, avd, xperms);
- map_decision(orig_tclass, avd, policydb.allow_unknown);
+ context_struct_compute_av(policydb, scontext, tcontext, tclass, avd,
+ xperms);
+ map_decision(&state->ss->map, orig_tclass, avd,
+ policydb->allow_unknown);
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return;
allow:
avd->allowed = 0xffffffff;
goto out;
}
-void security_compute_av_user(u32 ssid,
+void security_compute_av_user(struct selinux_state *state,
+ u32 ssid,
u32 tsid,
u16 tclass,
struct av_decision *avd)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct context *scontext = NULL, *tcontext = NULL;
- read_lock(&policy_rwlock);
- avd_init(avd);
- if (!ss_initialized)
+ read_lock(&state->ss->policy_rwlock);
+ avd_init(state, avd);
+ if (!state->initialized)
goto allow;
- scontext = sidtab_search(&sidtab, ssid);
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
+
+ scontext = sidtab_search(sidtab, ssid);
if (!scontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, ssid);
}
/* permissive domain? */
- if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+ if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
avd->flags |= AVD_FLAGS_PERMISSIVE;
- tcontext = sidtab_search(&sidtab, tsid);
+ tcontext = sidtab_search(sidtab, tsid);
if (!tcontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, tsid);
}
if (unlikely(!tclass)) {
- if (policydb.allow_unknown)
+ if (policydb->allow_unknown)
goto allow;
goto out;
}
- context_struct_compute_av(scontext, tcontext, tclass, avd, NULL);
+ context_struct_compute_av(policydb, scontext, tcontext, tclass, avd,
+ NULL);
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return;
allow:
avd->allowed = 0xffffffff;
* to point to this string and set `*scontext_len' to
* the length of the string.
*/
-static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
+static int context_struct_to_string(struct policydb *p,
+ struct context *context,
+ char **scontext, u32 *scontext_len)
{
char *scontextp;
}
/* Compute the size of the context. */
- *scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
- *scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
- *scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
- *scontext_len += mls_compute_context_len(context);
+ *scontext_len += strlen(sym_name(p, SYM_USERS, context->user - 1)) + 1;
+ *scontext_len += strlen(sym_name(p, SYM_ROLES, context->role - 1)) + 1;
+ *scontext_len += strlen(sym_name(p, SYM_TYPES, context->type - 1)) + 1;
+ *scontext_len += mls_compute_context_len(p, context);
if (!scontext)
return 0;
* Copy the user name, role name and type name into the context.
*/
scontextp += sprintf(scontextp, "%s:%s:%s",
- sym_name(&policydb, SYM_USERS, context->user - 1),
- sym_name(&policydb, SYM_ROLES, context->role - 1),
- sym_name(&policydb, SYM_TYPES, context->type - 1));
+ sym_name(p, SYM_USERS, context->user - 1),
+ sym_name(p, SYM_ROLES, context->role - 1),
+ sym_name(p, SYM_TYPES, context->type - 1));
- mls_sid_to_context(context, &scontextp);
+ mls_sid_to_context(p, context, &scontextp);
*scontextp = 0;
return initial_sid_to_string[sid];
}
-static int security_sid_to_context_core(u32 sid, char **scontext,
+static int security_sid_to_context_core(struct selinux_state *state,
+ u32 sid, char **scontext,
u32 *scontext_len, int force)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct context *context;
int rc = 0;
*scontext = NULL;
*scontext_len = 0;
- if (!ss_initialized) {
+ if (!state->initialized) {
if (sid <= SECINITSID_NUM) {
char *scontextp;
rc = -EINVAL;
goto out;
}
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
if (force)
- context = sidtab_search_force(&sidtab, sid);
+ context = sidtab_search_force(sidtab, sid);
else
- context = sidtab_search(&sidtab, sid);
+ context = sidtab_search(sidtab, sid);
if (!context) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, sid);
rc = -EINVAL;
goto out_unlock;
}
- rc = context_struct_to_string(context, scontext, scontext_len);
+ rc = context_struct_to_string(policydb, context, scontext,
+ scontext_len);
out_unlock:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
out:
return rc;
* into a dynamically allocated string of the correct size. Set @scontext
* to point to this string and set @scontext_len to the length of the string.
*/
-int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+int security_sid_to_context(struct selinux_state *state,
+ u32 sid, char **scontext, u32 *scontext_len)
{
- return security_sid_to_context_core(sid, scontext, scontext_len, 0);
+ return security_sid_to_context_core(state, sid, scontext,
+ scontext_len, 0);
}
-int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len)
+int security_sid_to_context_force(struct selinux_state *state, u32 sid,
+ char **scontext, u32 *scontext_len)
{
- return security_sid_to_context_core(sid, scontext, scontext_len, 1);
+ return security_sid_to_context_core(state, sid, scontext,
+ scontext_len, 1);
}
/*
return rc;
}
-static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
+static int security_context_to_sid_core(struct selinux_state *state,
+ const char *scontext, u32 scontext_len,
u32 *sid, u32 def_sid, gfp_t gfp_flags,
int force)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
char *scontext2, *str = NULL;
struct context context;
int rc = 0;
if (!scontext2)
return -ENOMEM;
- if (!ss_initialized) {
+ if (!state->initialized) {
int i;
for (i = 1; i < SECINITSID_NUM; i++) {
if (!str)
goto out;
}
-
- read_lock(&policy_rwlock);
- rc = string_to_context_struct(&policydb, &sidtab, scontext2,
+ read_lock(&state->ss->policy_rwlock);
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
+ rc = string_to_context_struct(policydb, sidtab, scontext2,
scontext_len, &context, def_sid);
if (rc == -EINVAL && force) {
context.str = str;
str = NULL;
} else if (rc)
goto out_unlock;
- rc = sidtab_context_to_sid(&sidtab, &context, sid);
+ rc = sidtab_context_to_sid(sidtab, &context, sid);
context_destroy(&context);
out_unlock:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
out:
kfree(scontext2);
kfree(str);
* Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
* memory is available, or 0 on success.
*/
-int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid,
+int security_context_to_sid(struct selinux_state *state,
+ const char *scontext, u32 scontext_len, u32 *sid,
gfp_t gfp)
{
- return security_context_to_sid_core(scontext, scontext_len,
+ return security_context_to_sid_core(state, scontext, scontext_len,
sid, SECSID_NULL, gfp, 0);
}
-int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp)
+int security_context_str_to_sid(struct selinux_state *state,
+ const char *scontext, u32 *sid, gfp_t gfp)
{
- return security_context_to_sid(scontext, strlen(scontext), sid, gfp);
+ return security_context_to_sid(state, scontext, strlen(scontext),
+ sid, gfp);
}
/**
* Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
* memory is available, or 0 on success.
*/
-int security_context_to_sid_default(const char *scontext, u32 scontext_len,
+int security_context_to_sid_default(struct selinux_state *state,
+ const char *scontext, u32 scontext_len,
u32 *sid, u32 def_sid, gfp_t gfp_flags)
{
- return security_context_to_sid_core(scontext, scontext_len,
+ return security_context_to_sid_core(state, scontext, scontext_len,
sid, def_sid, gfp_flags, 1);
}
-int security_context_to_sid_force(const char *scontext, u32 scontext_len,
+int security_context_to_sid_force(struct selinux_state *state,
+ const char *scontext, u32 scontext_len,
u32 *sid)
{
- return security_context_to_sid_core(scontext, scontext_len,
+ return security_context_to_sid_core(state, scontext, scontext_len,
sid, SECSID_NULL, GFP_KERNEL, 1);
}
static int compute_sid_handle_invalid_context(
+ struct selinux_state *state,
struct context *scontext,
struct context *tcontext,
u16 tclass,
struct context *newcontext)
{
+ struct policydb *policydb = &state->ss->policydb;
char *s = NULL, *t = NULL, *n = NULL;
u32 slen, tlen, nlen;
- if (context_struct_to_string(scontext, &s, &slen))
+ if (context_struct_to_string(policydb, scontext, &s, &slen))
goto out;
- if (context_struct_to_string(tcontext, &t, &tlen))
+ if (context_struct_to_string(policydb, tcontext, &t, &tlen))
goto out;
- if (context_struct_to_string(newcontext, &n, &nlen))
+ if (context_struct_to_string(policydb, newcontext, &n, &nlen))
goto out;
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
"op=security_compute_sid invalid_context=%s"
" scontext=%s"
" tcontext=%s"
" tclass=%s",
- n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
+ n, s, t, sym_name(policydb, SYM_CLASSES, tclass-1));
out:
kfree(s);
kfree(t);
kfree(n);
- if (!selinux_enforcing)
+ if (!is_enforcing(state))
return 0;
return -EACCES;
}
-static void filename_compute_type(struct policydb *p, struct context *newcontext,
+static void filename_compute_type(struct policydb *policydb,
+ struct context *newcontext,
u32 stype, u32 ttype, u16 tclass,
const char *objname)
{
* like /dev or /var/run. This bitmap will quickly skip rule searches
* if the ttype does not contain any rules.
*/
- if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype))
+ if (!ebitmap_get_bit(&policydb->filename_trans_ttypes, ttype))
return;
ft.stype = stype;
ft.tclass = tclass;
ft.name = objname;
- otype = hashtab_search(p->filename_trans, &ft);
+ otype = hashtab_search(policydb->filename_trans, &ft);
if (otype)
newcontext->type = otype->otype;
}
-static int security_compute_sid(u32 ssid,
+static int security_compute_sid(struct selinux_state *state,
+ u32 ssid,
u32 tsid,
u16 orig_tclass,
u32 specified,
u32 *out_sid,
bool kern)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct class_datum *cladatum = NULL;
struct context *scontext = NULL, *tcontext = NULL, newcontext;
struct role_trans *roletr = NULL;
int rc = 0;
bool sock;
- if (!ss_initialized) {
+ if (!state->initialized) {
switch (orig_tclass) {
case SECCLASS_PROCESS: /* kernel value */
*out_sid = ssid;
context_init(&newcontext);
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
if (kern) {
- tclass = unmap_class(orig_tclass);
+ tclass = unmap_class(&state->ss->map, orig_tclass);
sock = security_is_socket_class(orig_tclass);
} else {
tclass = orig_tclass;
- sock = security_is_socket_class(map_class(tclass));
+ sock = security_is_socket_class(map_class(&state->ss->map,
+ tclass));
}
- scontext = sidtab_search(&sidtab, ssid);
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
+
+ scontext = sidtab_search(sidtab, ssid);
if (!scontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, ssid);
rc = -EINVAL;
goto out_unlock;
}
- tcontext = sidtab_search(&sidtab, tsid);
+ tcontext = sidtab_search(sidtab, tsid);
if (!tcontext) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, tsid);
goto out_unlock;
}
- if (tclass && tclass <= policydb.p_classes.nprim)
- cladatum = policydb.class_val_to_struct[tclass - 1];
+ if (tclass && tclass <= policydb->p_classes.nprim)
+ cladatum = policydb->class_val_to_struct[tclass - 1];
/* Set the user identity. */
switch (specified) {
} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
newcontext.role = tcontext->role;
} else {
- if ((tclass == policydb.process_class) || (sock == true))
+ if ((tclass == policydb->process_class) || (sock == true))
newcontext.role = scontext->role;
else
newcontext.role = OBJECT_R_VAL;
} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
newcontext.type = tcontext->type;
} else {
- if ((tclass == policydb.process_class) || (sock == true)) {
+ if ((tclass == policydb->process_class) || (sock == true)) {
/* Use the type of process. */
newcontext.type = scontext->type;
} else {
avkey.target_type = tcontext->type;
avkey.target_class = tclass;
avkey.specified = specified;
- avdatum = avtab_search(&policydb.te_avtab, &avkey);
+ avdatum = avtab_search(&policydb->te_avtab, &avkey);
/* If no permanent rule, also check for enabled conditional rules */
if (!avdatum) {
- node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
+ node = avtab_search_node(&policydb->te_cond_avtab, &avkey);
for (; node; node = avtab_search_node_next(node, specified)) {
if (node->key.specified & AVTAB_ENABLED) {
avdatum = &node->datum;
/* if we have a objname this is a file trans check so check those rules */
if (objname)
- filename_compute_type(&policydb, &newcontext, scontext->type,
+ filename_compute_type(policydb, &newcontext, scontext->type,
tcontext->type, tclass, objname);
/* Check for class-specific changes. */
if (specified & AVTAB_TRANSITION) {
/* Look for a role transition rule. */
- for (roletr = policydb.role_tr; roletr; roletr = roletr->next) {
+ for (roletr = policydb->role_tr; roletr;
+ roletr = roletr->next) {
if ((roletr->role == scontext->role) &&
(roletr->type == tcontext->type) &&
(roletr->tclass == tclass)) {
/* Set the MLS attributes.
This is done last because it may allocate memory. */
- rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+ rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified,
&newcontext, sock);
if (rc)
goto out_unlock;
/* Check the validity of the context. */
- if (!policydb_context_isvalid(&policydb, &newcontext)) {
- rc = compute_sid_handle_invalid_context(scontext,
+ if (!policydb_context_isvalid(policydb, &newcontext)) {
+ rc = compute_sid_handle_invalid_context(state, scontext,
tcontext,
tclass,
&newcontext);
goto out_unlock;
}
/* Obtain the sid for the context. */
- rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
+ rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
out_unlock:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
context_destroy(&newcontext);
out:
return rc;
* if insufficient memory is available, or %0 if the new SID was
* computed successfully.
*/
-int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
+int security_transition_sid(struct selinux_state *state,
+ u32 ssid, u32 tsid, u16 tclass,
const struct qstr *qstr, u32 *out_sid)
{
- return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
+ return security_compute_sid(state, ssid, tsid, tclass,
+ AVTAB_TRANSITION,
qstr ? qstr->name : NULL, out_sid, true);
}
-int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass,
+int security_transition_sid_user(struct selinux_state *state,
+ u32 ssid, u32 tsid, u16 tclass,
const char *objname, u32 *out_sid)
{
- return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
+ return security_compute_sid(state, ssid, tsid, tclass,
+ AVTAB_TRANSITION,
objname, out_sid, false);
}
* if insufficient memory is available, or %0 if the SID was
* computed successfully.
*/
-int security_member_sid(u32 ssid,
+int security_member_sid(struct selinux_state *state,
+ u32 ssid,
u32 tsid,
u16 tclass,
u32 *out_sid)
{
- return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL,
+ return security_compute_sid(state, ssid, tsid, tclass,
+ AVTAB_MEMBER, NULL,
out_sid, false);
}
* if insufficient memory is available, or %0 if the SID was
* computed successfully.
*/
-int security_change_sid(u32 ssid,
+int security_change_sid(struct selinux_state *state,
+ u32 ssid,
u32 tsid,
u16 tclass,
u32 *out_sid)
{
- return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL,
+ return security_compute_sid(state,
+ ssid, tsid, tclass, AVTAB_CHANGE, NULL,
out_sid, false);
}
return 0;
}
-static inline int convert_context_handle_invalid_context(struct context *context)
+static inline int convert_context_handle_invalid_context(
+ struct selinux_state *state,
+ struct context *context)
{
+ struct policydb *policydb = &state->ss->policydb;
char *s;
u32 len;
- if (selinux_enforcing)
+ if (is_enforcing(state))
return -EINVAL;
- if (!context_struct_to_string(context, &s, &len)) {
+ if (!context_struct_to_string(policydb, context, &s, &len)) {
printk(KERN_WARNING "SELinux: Context %s would be invalid if enforcing\n", s);
kfree(s);
}
}
struct convert_context_args {
+ struct selinux_state *state;
struct policydb *oldp;
struct policydb *newp;
};
/* Check the validity of the new context. */
if (!policydb_context_isvalid(args->newp, c)) {
- rc = convert_context_handle_invalid_context(&oldc);
+ rc = convert_context_handle_invalid_context(args->state,
+ &oldc);
if (rc)
goto bad;
}
return rc;
bad:
/* Map old representation to string and save it. */
- rc = context_struct_to_string(&oldc, &s, &len);
+ rc = context_struct_to_string(args->oldp, &oldc, &s, &len);
if (rc)
return rc;
context_destroy(&oldc);
goto out;
}
-static void security_load_policycaps(void)
+static void security_load_policycaps(struct selinux_state *state)
{
+ struct policydb *p = &state->ss->policydb;
unsigned int i;
struct ebitmap_node *node;
- selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
- POLICYDB_CAPABILITY_NETPEER);
- selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
- POLICYDB_CAPABILITY_OPENPERM);
- selinux_policycap_extsockclass = ebitmap_get_bit(&policydb.policycaps,
- POLICYDB_CAPABILITY_EXTSOCKCLASS);
- selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
- POLICYDB_CAPABILITY_ALWAYSNETWORK);
- selinux_policycap_cgroupseclabel =
- ebitmap_get_bit(&policydb.policycaps,
- POLICYDB_CAPABILITY_CGROUPSECLABEL);
- selinux_policycap_nnp_nosuid_transition =
- ebitmap_get_bit(&policydb.policycaps,
- POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION);
+ for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
+ state->policycap[i] = ebitmap_get_bit(&p->policycaps, i);
for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
pr_info("SELinux: policy capability %s=%d\n",
selinux_policycap_names[i],
- ebitmap_get_bit(&policydb.policycaps, i));
+ ebitmap_get_bit(&p->policycaps, i));
- ebitmap_for_each_positive_bit(&policydb.policycaps, node, i) {
+ ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
if (i >= ARRAY_SIZE(selinux_policycap_names))
pr_info("SELinux: unknown policy capability %u\n",
i);
}
}
-static int security_preserve_bools(struct policydb *p);
+static int security_preserve_bools(struct selinux_state *state,
+ struct policydb *newpolicydb);
/**
* security_load_policy - Load a security policy configuration.
* This function will flush the access vector cache after
* loading the new policy.
*/
-int security_load_policy(void *data, size_t len)
+int security_load_policy(struct selinux_state *state, void *data, size_t len)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct policydb *oldpolicydb, *newpolicydb;
struct sidtab oldsidtab, newsidtab;
- struct selinux_mapping *oldmap, *map = NULL;
+ struct selinux_mapping *oldmapping;
+ struct selinux_map newmap;
struct convert_context_args args;
u32 seqno;
- u16 map_size;
int rc = 0;
struct policy_file file = { data, len }, *fp = &file;
}
newpolicydb = oldpolicydb + 1;
- if (!ss_initialized) {
- avtab_cache_init();
- ebitmap_cache_init();
- hashtab_cache_init();
- rc = policydb_read(&policydb, fp);
- if (rc) {
- avtab_cache_destroy();
- ebitmap_cache_destroy();
- hashtab_cache_destroy();
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
+
+ if (!state->initialized) {
+ rc = policydb_read(policydb, fp);
+ if (rc)
goto out;
- }
- policydb.len = len;
- rc = selinux_set_mapping(&policydb, secclass_map,
- ¤t_mapping,
- ¤t_mapping_size);
+ policydb->len = len;
+ rc = selinux_set_mapping(policydb, secclass_map,
+ &state->ss->map);
if (rc) {
- policydb_destroy(&policydb);
- avtab_cache_destroy();
- ebitmap_cache_destroy();
- hashtab_cache_destroy();
+ policydb_destroy(policydb);
goto out;
}
- rc = policydb_load_isids(&policydb, &sidtab);
+ rc = policydb_load_isids(policydb, sidtab);
if (rc) {
- policydb_destroy(&policydb);
- avtab_cache_destroy();
- ebitmap_cache_destroy();
- hashtab_cache_destroy();
+ policydb_destroy(policydb);
goto out;
}
- security_load_policycaps();
- ss_initialized = 1;
- seqno = ++latest_granting;
+ security_load_policycaps(state);
+ state->initialized = 1;
+ seqno = ++state->ss->latest_granting;
selinux_complete_init();
avc_ss_reset(seqno);
selnl_notify_policyload(seqno);
- selinux_status_update_policyload(seqno);
+ selinux_status_update_policyload(state, seqno);
selinux_netlbl_cache_invalidate();
selinux_xfrm_notify_policyload();
goto out;
}
#if 0
- sidtab_hash_eval(&sidtab, "sids");
+ sidtab_hash_eval(sidtab, "sids");
#endif
rc = policydb_read(newpolicydb, fp);
newpolicydb->len = len;
/* If switching between different policy types, log MLS status */
- if (policydb.mls_enabled && !newpolicydb->mls_enabled)
+ if (policydb->mls_enabled && !newpolicydb->mls_enabled)
printk(KERN_INFO "SELinux: Disabling MLS support...\n");
- else if (!policydb.mls_enabled && newpolicydb->mls_enabled)
+ else if (!policydb->mls_enabled && newpolicydb->mls_enabled)
printk(KERN_INFO "SELinux: Enabling MLS support...\n");
rc = policydb_load_isids(newpolicydb, &newsidtab);
goto out;
}
- rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);
+ rc = selinux_set_mapping(newpolicydb, secclass_map, &newmap);
if (rc)
goto err;
- rc = security_preserve_bools(newpolicydb);
+ rc = security_preserve_bools(state, newpolicydb);
if (rc) {
printk(KERN_ERR "SELinux: unable to preserve booleans\n");
goto err;
}
/* Clone the SID table. */
- sidtab_shutdown(&sidtab);
+ sidtab_shutdown(sidtab);
- rc = sidtab_map(&sidtab, clone_sid, &newsidtab);
+ rc = sidtab_map(sidtab, clone_sid, &newsidtab);
if (rc)
goto err;
* Convert the internal representations of contexts
* in the new SID table.
*/
- args.oldp = &policydb;
+ args.state = state;
+ args.oldp = policydb;
args.newp = newpolicydb;
rc = sidtab_map(&newsidtab, convert_context, &args);
if (rc) {
}
/* Save the old policydb and SID table to free later. */
- memcpy(oldpolicydb, &policydb, sizeof(policydb));
- sidtab_set(&oldsidtab, &sidtab);
+ memcpy(oldpolicydb, policydb, sizeof(*policydb));
+ sidtab_set(&oldsidtab, sidtab);
/* Install the new policydb and SID table. */
- write_lock_irq(&policy_rwlock);
- memcpy(&policydb, newpolicydb, sizeof(policydb));
- sidtab_set(&sidtab, &newsidtab);
- security_load_policycaps();
- oldmap = current_mapping;
- current_mapping = map;
- current_mapping_size = map_size;
- seqno = ++latest_granting;
- write_unlock_irq(&policy_rwlock);
+ write_lock_irq(&state->ss->policy_rwlock);
+ memcpy(policydb, newpolicydb, sizeof(*policydb));
+ sidtab_set(sidtab, &newsidtab);
+ security_load_policycaps(state);
+ oldmapping = state->ss->map.mapping;
+ state->ss->map.mapping = newmap.mapping;
+ state->ss->map.size = newmap.size;
+ seqno = ++state->ss->latest_granting;
+ write_unlock_irq(&state->ss->policy_rwlock);
/* Free the old policydb and SID table. */
policydb_destroy(oldpolicydb);
sidtab_destroy(&oldsidtab);
- kfree(oldmap);
+ kfree(oldmapping);
avc_ss_reset(seqno);
selnl_notify_policyload(seqno);
- selinux_status_update_policyload(seqno);
+ selinux_status_update_policyload(state, seqno);
selinux_netlbl_cache_invalidate();
selinux_xfrm_notify_policyload();
goto out;
err:
- kfree(map);
+ kfree(newmap.mapping);
sidtab_destroy(&newsidtab);
policydb_destroy(newpolicydb);
return rc;
}
-size_t security_policydb_len(void)
+size_t security_policydb_len(struct selinux_state *state)
{
+ struct policydb *p = &state->ss->policydb;
size_t len;
- read_lock(&policy_rwlock);
- len = policydb.len;
- read_unlock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+ len = p->len;
+ read_unlock(&state->ss->policy_rwlock);
return len;
}
* @port: port number
* @out_sid: security identifier
*/
-int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
+int security_port_sid(struct selinux_state *state,
+ u8 protocol, u16 port, u32 *out_sid)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct ocontext *c;
int rc = 0;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
- c = policydb.ocontexts[OCON_PORT];
+ c = policydb->ocontexts[OCON_PORT];
while (c) {
if (c->u.port.protocol == protocol &&
c->u.port.low_port <= port &&
if (c) {
if (!c->sid[0]) {
- rc = sidtab_context_to_sid(&sidtab,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc)
}
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
* @pkey_num: pkey number
* @out_sid: security identifier
*/
-int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
+int security_ib_pkey_sid(struct selinux_state *state,
+ u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct ocontext *c;
int rc = 0;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
- c = policydb.ocontexts[OCON_IBPKEY];
+ c = policydb->ocontexts[OCON_IBPKEY];
while (c) {
if (c->u.ibpkey.low_pkey <= pkey_num &&
c->u.ibpkey.high_pkey >= pkey_num &&
if (c) {
if (!c->sid[0]) {
- rc = sidtab_context_to_sid(&sidtab,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc)
*out_sid = SECINITSID_UNLABELED;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
* @port: port number
* @out_sid: security identifier
*/
-int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
+int security_ib_endport_sid(struct selinux_state *state,
+ const char *dev_name, u8 port_num, u32 *out_sid)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct ocontext *c;
int rc = 0;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
- c = policydb.ocontexts[OCON_IBENDPORT];
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
+
+ c = policydb->ocontexts[OCON_IBENDPORT];
while (c) {
if (c->u.ibendport.port == port_num &&
!strncmp(c->u.ibendport.dev_name,
if (c) {
if (!c->sid[0]) {
- rc = sidtab_context_to_sid(&sidtab,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc)
*out_sid = SECINITSID_UNLABELED;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
* @name: interface name
* @if_sid: interface SID
*/
-int security_netif_sid(char *name, u32 *if_sid)
+int security_netif_sid(struct selinux_state *state,
+ char *name, u32 *if_sid)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
int rc = 0;
struct ocontext *c;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
- c = policydb.ocontexts[OCON_NETIF];
+ c = policydb->ocontexts[OCON_NETIF];
while (c) {
if (strcmp(name, c->u.name) == 0)
break;
if (c) {
if (!c->sid[0] || !c->sid[1]) {
- rc = sidtab_context_to_sid(&sidtab,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc)
goto out;
- rc = sidtab_context_to_sid(&sidtab,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[1],
&c->sid[1]);
if (rc)
*if_sid = SECINITSID_NETIF;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
* @addrlen: address length in bytes
* @out_sid: security identifier
*/
-int security_node_sid(u16 domain,
+int security_node_sid(struct selinux_state *state,
+ u16 domain,
void *addrp,
u32 addrlen,
u32 *out_sid)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
int rc;
struct ocontext *c;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
switch (domain) {
case AF_INET: {
addr = *((u32 *)addrp);
- c = policydb.ocontexts[OCON_NODE];
+ c = policydb->ocontexts[OCON_NODE];
while (c) {
if (c->u.node.addr == (addr & c->u.node.mask))
break;
rc = -EINVAL;
if (addrlen != sizeof(u64) * 2)
goto out;
- c = policydb.ocontexts[OCON_NODE6];
+ c = policydb->ocontexts[OCON_NODE6];
while (c) {
if (match_ipv6_addrmask(addrp, c->u.node6.addr,
c->u.node6.mask))
if (c) {
if (!c->sid[0]) {
- rc = sidtab_context_to_sid(&sidtab,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc)
rc = 0;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
* number of elements in the array.
*/
-int security_get_user_sids(u32 fromsid,
+int security_get_user_sids(struct selinux_state *state,
+ u32 fromsid,
char *username,
u32 **sids,
u32 *nel)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
struct context *fromcon, usercon;
u32 *mysids = NULL, *mysids2, sid;
u32 mynel = 0, maxnel = SIDS_NEL;
*sids = NULL;
*nel = 0;
- if (!ss_initialized)
+ if (!state->initialized)
goto out;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
context_init(&usercon);
rc = -EINVAL;
- fromcon = sidtab_search(&sidtab, fromsid);
+ fromcon = sidtab_search(sidtab, fromsid);
if (!fromcon)
goto out_unlock;
rc = -EINVAL;
- user = hashtab_search(policydb.p_users.table, username);
+ user = hashtab_search(policydb->p_users.table, username);
if (!user)
goto out_unlock;
goto out_unlock;
ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
- role = policydb.role_val_to_struct[i];
+ role = policydb->role_val_to_struct[i];
usercon.role = i + 1;
ebitmap_for_each_positive_bit(&role->types, tnode, j) {
usercon.type = j + 1;
- if (mls_setup_user_range(fromcon, user, &usercon))
+ if (mls_setup_user_range(policydb, fromcon, user,
+ &usercon))
continue;
- rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
+ rc = sidtab_context_to_sid(sidtab, &usercon, &sid);
if (rc)
goto out_unlock;
if (mynel < maxnel) {
}
rc = 0;
out_unlock:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
if (rc || !mynel) {
kfree(mysids);
goto out;
*
* The caller must acquire the policy_rwlock before calling this function.
*/
-static inline int __security_genfs_sid(const char *fstype,
+static inline int __security_genfs_sid(struct selinux_state *state,
+ const char *fstype,
char *path,
u16 orig_sclass,
u32 *sid)
{
+ struct policydb *policydb = &state->ss->policydb;
+ struct sidtab *sidtab = &state->ss->sidtab;
int len;
u16 sclass;
struct genfs *genfs;
while (path[0] == '/' && path[1] == '/')
path++;
- sclass = unmap_class(orig_sclass);
+ sclass = unmap_class(&state->ss->map, orig_sclass);
*sid = SECINITSID_UNLABELED;
- for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
+ for (genfs = policydb->genfs; genfs; genfs = genfs->next) {
cmp = strcmp(fstype, genfs->fstype);
if (cmp <= 0)
break;
goto out;
if (!c->sid[0]) {
- rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
+ rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]);
if (rc)
goto out;
}
* Acquire policy_rwlock before calling __security_genfs_sid() and release
* it afterward.
*/
-int security_genfs_sid(const char *fstype,
+int security_genfs_sid(struct selinux_state *state,
+ const char *fstype,
char *path,
u16 orig_sclass,
u32 *sid)
{
int retval;
- read_lock(&policy_rwlock);
- retval = __security_genfs_sid(fstype, path, orig_sclass, sid);
- read_unlock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+ retval = __security_genfs_sid(state, fstype, path, orig_sclass, sid);
+ read_unlock(&state->ss->policy_rwlock);
return retval;
}
* security_fs_use - Determine how to handle labeling for a filesystem.
* @sb: superblock in question
*/
-int security_fs_use(struct super_block *sb)
+int security_fs_use(struct selinux_state *state, struct super_block *sb)
{
+ struct policydb *policydb;
+ struct sidtab *sidtab;
int rc = 0;
struct ocontext *c;
struct superblock_security_struct *sbsec = sb->s_security;
const char *fstype = sb->s_type->name;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+ sidtab = &state->ss->sidtab;
- c = policydb.ocontexts[OCON_FSUSE];
+ c = policydb->ocontexts[OCON_FSUSE];
while (c) {
if (strcmp(fstype, c->u.name) == 0)
break;
if (c) {
sbsec->behavior = c->v.behavior;
if (!c->sid[0]) {
- rc = sidtab_context_to_sid(&sidtab, &c->context[0],
+ rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc)
goto out;
}
sbsec->sid = c->sid[0];
} else {
- rc = __security_genfs_sid(fstype, "/", SECCLASS_DIR,
+ rc = __security_genfs_sid(state, fstype, "/", SECCLASS_DIR,
&sbsec->sid);
if (rc) {
sbsec->behavior = SECURITY_FS_USE_NONE;
}
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
-int security_get_bools(int *len, char ***names, int **values)
+int security_get_bools(struct selinux_state *state,
+ int *len, char ***names, int **values)
{
+ struct policydb *policydb;
int i, rc;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
+
*names = NULL;
*values = NULL;
rc = 0;
- *len = policydb.p_bools.nprim;
+ *len = policydb->p_bools.nprim;
if (!*len)
goto out;
goto err;
for (i = 0; i < *len; i++) {
- (*values)[i] = policydb.bool_val_to_struct[i]->state;
+ (*values)[i] = policydb->bool_val_to_struct[i]->state;
rc = -ENOMEM;
- (*names)[i] = kstrdup(sym_name(&policydb, SYM_BOOLS, i), GFP_ATOMIC);
+ (*names)[i] = kstrdup(sym_name(policydb, SYM_BOOLS, i),
+ GFP_ATOMIC);
if (!(*names)[i])
goto err;
}
rc = 0;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
err:
if (*names) {
}
-int security_set_bools(int len, int *values)
+int security_set_bools(struct selinux_state *state, int len, int *values)
{
+ struct policydb *policydb;
int i, rc;
int lenp, seqno = 0;
struct cond_node *cur;
- write_lock_irq(&policy_rwlock);
+ write_lock_irq(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
rc = -EFAULT;
- lenp = policydb.p_bools.nprim;
+ lenp = policydb->p_bools.nprim;
if (len != lenp)
goto out;
for (i = 0; i < len; i++) {
- if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
+ if (!!values[i] != policydb->bool_val_to_struct[i]->state) {
audit_log(current->audit_context, GFP_ATOMIC,
AUDIT_MAC_CONFIG_CHANGE,
"bool=%s val=%d old_val=%d auid=%u ses=%u",
- sym_name(&policydb, SYM_BOOLS, i),
+ sym_name(policydb, SYM_BOOLS, i),
!!values[i],
- policydb.bool_val_to_struct[i]->state,
+ policydb->bool_val_to_struct[i]->state,
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
}
if (values[i])
- policydb.bool_val_to_struct[i]->state = 1;
+ policydb->bool_val_to_struct[i]->state = 1;
else
- policydb.bool_val_to_struct[i]->state = 0;
+ policydb->bool_val_to_struct[i]->state = 0;
}
- for (cur = policydb.cond_list; cur; cur = cur->next) {
- rc = evaluate_cond_node(&policydb, cur);
+ for (cur = policydb->cond_list; cur; cur = cur->next) {
+ rc = evaluate_cond_node(policydb, cur);
if (rc)
goto out;
}
- seqno = ++latest_granting;
+ seqno = ++state->ss->latest_granting;
rc = 0;
out:
- write_unlock_irq(&policy_rwlock);
+ write_unlock_irq(&state->ss->policy_rwlock);
if (!rc) {
avc_ss_reset(seqno);
selnl_notify_policyload(seqno);
- selinux_status_update_policyload(seqno);
+ selinux_status_update_policyload(state, seqno);
selinux_xfrm_notify_policyload();
}
return rc;
}
-int security_get_bool_value(int index)
+int security_get_bool_value(struct selinux_state *state,
+ int index)
{
+ struct policydb *policydb;
int rc;
int len;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+
+ policydb = &state->ss->policydb;
rc = -EFAULT;
- len = policydb.p_bools.nprim;
+ len = policydb->p_bools.nprim;
if (index >= len)
goto out;
- rc = policydb.bool_val_to_struct[index]->state;
+ rc = policydb->bool_val_to_struct[index]->state;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
-static int security_preserve_bools(struct policydb *p)
+static int security_preserve_bools(struct selinux_state *state,
+ struct policydb *policydb)
{
int rc, nbools = 0, *bvalues = NULL, i;
char **bnames = NULL;
struct cond_bool_datum *booldatum;
struct cond_node *cur;
- rc = security_get_bools(&nbools, &bnames, &bvalues);
+ rc = security_get_bools(state, &nbools, &bnames, &bvalues);
if (rc)
goto out;
for (i = 0; i < nbools; i++) {
- booldatum = hashtab_search(p->p_bools.table, bnames[i]);
+ booldatum = hashtab_search(policydb->p_bools.table, bnames[i]);
if (booldatum)
booldatum->state = bvalues[i];
}
- for (cur = p->cond_list; cur; cur = cur->next) {
- rc = evaluate_cond_node(p, cur);
+ for (cur = policydb->cond_list; cur; cur = cur->next) {
+ rc = evaluate_cond_node(policydb, cur);
if (rc)
goto out;
}
* security_sid_mls_copy() - computes a new sid based on the given
* sid and the mls portion of mls_sid.
*/
-int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
+int security_sid_mls_copy(struct selinux_state *state,
+ u32 sid, u32 mls_sid, u32 *new_sid)
{
+ struct policydb *policydb = &state->ss->policydb;
+ struct sidtab *sidtab = &state->ss->sidtab;
struct context *context1;
struct context *context2;
struct context newcon;
int rc;
rc = 0;
- if (!ss_initialized || !policydb.mls_enabled) {
+ if (!state->initialized || !policydb->mls_enabled) {
*new_sid = sid;
goto out;
}
context_init(&newcon);
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
rc = -EINVAL;
- context1 = sidtab_search(&sidtab, sid);
+ context1 = sidtab_search(sidtab, sid);
if (!context1) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, sid);
}
rc = -EINVAL;
- context2 = sidtab_search(&sidtab, mls_sid);
+ context2 = sidtab_search(sidtab, mls_sid);
if (!context2) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, mls_sid);
goto out_unlock;
/* Check the validity of the new context. */
- if (!policydb_context_isvalid(&policydb, &newcon)) {
- rc = convert_context_handle_invalid_context(&newcon);
+ if (!policydb_context_isvalid(policydb, &newcon)) {
+ rc = convert_context_handle_invalid_context(state, &newcon);
if (rc) {
- if (!context_struct_to_string(&newcon, &s, &len)) {
+ if (!context_struct_to_string(policydb, &newcon, &s,
+ &len)) {
audit_log(current->audit_context,
GFP_ATOMIC, AUDIT_SELINUX_ERR,
"op=security_sid_mls_copy "
}
}
- rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
+ rc = sidtab_context_to_sid(sidtab, &newcon, new_sid);
out_unlock:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
context_destroy(&newcon);
out:
return rc;
* multiple, inconsistent labels | -<errno> | SECSID_NULL
*
*/
-int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
+int security_net_peersid_resolve(struct selinux_state *state,
+ u32 nlbl_sid, u32 nlbl_type,
u32 xfrm_sid,
u32 *peer_sid)
{
+ struct policydb *policydb = &state->ss->policydb;
+ struct sidtab *sidtab = &state->ss->sidtab;
int rc;
struct context *nlbl_ctx;
struct context *xfrm_ctx;
return 0;
}
- /* we don't need to check ss_initialized here since the only way both
+ /*
+ * We don't need to check initialized here since the only way both
* nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
- * security server was initialized and ss_initialized was true */
- if (!policydb.mls_enabled)
+ * security server was initialized and state->initialized was true.
+ */
+ if (!policydb->mls_enabled)
return 0;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
rc = -EINVAL;
- nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
+ nlbl_ctx = sidtab_search(sidtab, nlbl_sid);
if (!nlbl_ctx) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, nlbl_sid);
goto out;
}
rc = -EINVAL;
- xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
+ xfrm_ctx = sidtab_search(sidtab, xfrm_sid);
if (!xfrm_ctx) {
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
__func__, xfrm_sid);
* expressive */
*peer_sid = xfrm_sid;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
return 0;
}
-int security_get_classes(char ***classes, int *nclasses)
+int security_get_classes(struct selinux_state *state,
+ char ***classes, int *nclasses)
{
+ struct policydb *policydb = &state->ss->policydb;
int rc;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
rc = -ENOMEM;
- *nclasses = policydb.p_classes.nprim;
+ *nclasses = policydb->p_classes.nprim;
*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
if (!*classes)
goto out;
- rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+ rc = hashtab_map(policydb->p_classes.table, get_classes_callback,
*classes);
if (rc) {
int i;
}
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
return 0;
}
-int security_get_permissions(char *class, char ***perms, int *nperms)
+int security_get_permissions(struct selinux_state *state,
+ char *class, char ***perms, int *nperms)
{
+ struct policydb *policydb = &state->ss->policydb;
int rc, i;
struct class_datum *match;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
rc = -EINVAL;
- match = hashtab_search(policydb.p_classes.table, class);
+ match = hashtab_search(policydb->p_classes.table, class);
if (!match) {
printk(KERN_ERR "SELinux: %s: unrecognized class %s\n",
__func__, class);
goto err;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
err:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
for (i = 0; i < *nperms; i++)
kfree((*perms)[i]);
kfree(*perms);
return rc;
}
-int security_get_reject_unknown(void)
+int security_get_reject_unknown(struct selinux_state *state)
{
- return policydb.reject_unknown;
+ return state->ss->policydb.reject_unknown;
}
-int security_get_allow_unknown(void)
+int security_get_allow_unknown(struct selinux_state *state)
{
- return policydb.allow_unknown;
+ return state->ss->policydb.allow_unknown;
}
/**
* supported, false (0) if it isn't supported.
*
*/
-int security_policycap_supported(unsigned int req_cap)
+int security_policycap_supported(struct selinux_state *state,
+ unsigned int req_cap)
{
+ struct policydb *policydb = &state->ss->policydb;
int rc;
- read_lock(&policy_rwlock);
- rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
- read_unlock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+ rc = ebitmap_get_bit(&policydb->policycaps, req_cap);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
{
+ struct selinux_state *state = &selinux_state;
+ struct policydb *policydb = &state->ss->policydb;
struct selinux_audit_rule *tmprule;
struct role_datum *roledatum;
struct type_datum *typedatum;
*rule = NULL;
- if (!ss_initialized)
+ if (!state->initialized)
return -EOPNOTSUPP;
switch (field) {
context_init(&tmprule->au_ctxt);
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
- tmprule->au_seqno = latest_granting;
+ tmprule->au_seqno = state->ss->latest_granting;
switch (field) {
case AUDIT_SUBJ_USER:
case AUDIT_OBJ_USER:
rc = -EINVAL;
- userdatum = hashtab_search(policydb.p_users.table, rulestr);
+ userdatum = hashtab_search(policydb->p_users.table, rulestr);
if (!userdatum)
goto out;
tmprule->au_ctxt.user = userdatum->value;
case AUDIT_SUBJ_ROLE:
case AUDIT_OBJ_ROLE:
rc = -EINVAL;
- roledatum = hashtab_search(policydb.p_roles.table, rulestr);
+ roledatum = hashtab_search(policydb->p_roles.table, rulestr);
if (!roledatum)
goto out;
tmprule->au_ctxt.role = roledatum->value;
case AUDIT_SUBJ_TYPE:
case AUDIT_OBJ_TYPE:
rc = -EINVAL;
- typedatum = hashtab_search(policydb.p_types.table, rulestr);
+ typedatum = hashtab_search(policydb->p_types.table, rulestr);
if (!typedatum)
goto out;
tmprule->au_ctxt.type = typedatum->value;
case AUDIT_SUBJ_CLR:
case AUDIT_OBJ_LEV_LOW:
case AUDIT_OBJ_LEV_HIGH:
- rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
+ rc = mls_from_string(policydb, rulestr, &tmprule->au_ctxt,
+ GFP_ATOMIC);
if (rc)
goto out;
break;
}
rc = 0;
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
if (rc) {
selinux_audit_rule_free(tmprule);
int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
struct audit_context *actx)
{
+ struct selinux_state *state = &selinux_state;
struct context *ctxt;
struct mls_level *level;
struct selinux_audit_rule *rule = vrule;
return -ENOENT;
}
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
- if (rule->au_seqno < latest_granting) {
+ if (rule->au_seqno < state->ss->latest_granting) {
match = -ESTALE;
goto out;
}
- ctxt = sidtab_search(&sidtab, sid);
+ ctxt = sidtab_search(&state->ss->sidtab, sid);
if (unlikely(!ctxt)) {
WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
sid);
}
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return match;
}
* failure.
*
*/
-int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
+int security_netlbl_secattr_to_sid(struct selinux_state *state,
+ struct netlbl_lsm_secattr *secattr,
u32 *sid)
{
+ struct policydb *policydb = &state->ss->policydb;
+ struct sidtab *sidtab = &state->ss->sidtab;
int rc;
struct context *ctx;
struct context ctx_new;
- if (!ss_initialized) {
+ if (!state->initialized) {
*sid = SECSID_NULL;
return 0;
}
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
if (secattr->flags & NETLBL_SECATTR_CACHE)
*sid = *(u32 *)secattr->cache->data;
*sid = secattr->attr.secid;
else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
rc = -EIDRM;
- ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
+ ctx = sidtab_search(sidtab, SECINITSID_NETMSG);
if (ctx == NULL)
goto out;
ctx_new.user = ctx->user;
ctx_new.role = ctx->role;
ctx_new.type = ctx->type;
- mls_import_netlbl_lvl(&ctx_new, secattr);
+ mls_import_netlbl_lvl(policydb, &ctx_new, secattr);
if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
- rc = mls_import_netlbl_cat(&ctx_new, secattr);
+ rc = mls_import_netlbl_cat(policydb, &ctx_new, secattr);
if (rc)
goto out;
}
rc = -EIDRM;
- if (!mls_context_isvalid(&policydb, &ctx_new))
+ if (!mls_context_isvalid(policydb, &ctx_new))
goto out_free;
- rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
+ rc = sidtab_context_to_sid(sidtab, &ctx_new, sid);
if (rc)
goto out_free;
} else
*sid = SECSID_NULL;
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return 0;
out_free:
ebitmap_destroy(&ctx_new.range.level[0].cat);
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
* Returns zero on success, negative values on failure.
*
*/
-int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
+int security_netlbl_sid_to_secattr(struct selinux_state *state,
+ u32 sid, struct netlbl_lsm_secattr *secattr)
{
+ struct policydb *policydb = &state->ss->policydb;
int rc;
struct context *ctx;
- if (!ss_initialized)
+ if (!state->initialized)
return 0;
- read_lock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
rc = -ENOENT;
- ctx = sidtab_search(&sidtab, sid);
+ ctx = sidtab_search(&state->ss->sidtab, sid);
if (ctx == NULL)
goto out;
rc = -ENOMEM;
- secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1),
+ secattr->domain = kstrdup(sym_name(policydb, SYM_TYPES, ctx->type - 1),
GFP_ATOMIC);
if (secattr->domain == NULL)
goto out;
secattr->attr.secid = sid;
secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
- mls_export_netlbl_lvl(ctx, secattr);
- rc = mls_export_netlbl_cat(ctx, secattr);
+ mls_export_netlbl_lvl(policydb, ctx, secattr);
+ rc = mls_export_netlbl_cat(policydb, ctx, secattr);
out:
- read_unlock(&policy_rwlock);
+ read_unlock(&state->ss->policy_rwlock);
return rc;
}
#endif /* CONFIG_NETLABEL */
* @len: length of data in bytes
*
*/
-int security_read_policy(void **data, size_t *len)
+int security_read_policy(struct selinux_state *state,
+ void **data, size_t *len)
{
+ struct policydb *policydb = &state->ss->policydb;
int rc;
struct policy_file fp;
- if (!ss_initialized)
+ if (!state->initialized)
return -EINVAL;
- *len = security_policydb_len();
+ *len = security_policydb_len(state);
*data = vmalloc_user(*len);
if (!*data)
fp.data = *data;
fp.len = *len;
- read_lock(&policy_rwlock);
- rc = policydb_write(&policydb, &fp);
- read_unlock(&policy_rwlock);
+ read_lock(&state->ss->policy_rwlock);
+ rc = policydb_write(policydb, &fp);
+ read_unlock(&state->ss->policy_rwlock);
if (rc)
return rc;