selinux/stable-6.10 PR 20240513
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmZCWd4UHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXMFMQ/8DlQhbe+NzeAjBg2O7RqNKoE/UU2l JAkzgQ7h35/sgsfDIEhPv0VOzq2cwLSaw5/qSGGrQDWR4AKz55HvBSJQDElgzPo2 wtL2lozjJ03+P391aeXEHdkqzgp2F3c6oNthIcFvRmi3EVcWr7eqnjWU+bJzFtMA z4IgX01yiUF6EMdTJcWjSLclk3dOqHWPV657RadYyp2pr3u9rc9gqgxichs0dQW0 X/vexUBg81TdSeHS+u9Jgrz+TCsQdP3CHSFibXDv1rX89bqCbG9wYNTyTBHH9f0j LPpV2bKaesxIZV6dZyIKKSqCtHGBcjcJEjUbl7JFkQOS/a8NPMDH2ZYkHqbyq4BH SX+kRhthmXZiZ2IWhMRikaE4FBIWI7JAC4riKB2Dd0RzJrNEgaawU0wM+evKai9F s3GCk/P7wnTT4GlDHSkYEiiRF9c3DNkfVb9mqG78PRMR4X+z/0dsX5iaJTwlyMxo 69JSoTNzMxVdDtvD+K89V7GCm8NmGFjLwQUqb282L/6ibzC/5CCUQXn8ZWvNRPql IUoQhKbveCWR3m9vAMeGpE61oNgFp0mHj3Zb/vE5Yu7HxOn2y1lFv2XGxR6bGyTF T53AaHM15uFomhqhG+iM3b4FDhNIJpbUc4MJsq3iMgFC941n1ceXyeBEgf31+Z2x k1ZlxqLAWn05auA= =2Wbi -----END PGP SIGNATURE----- Merge tag 'selinux-pr-20240513' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux Pull selinux updates from Paul Moore: - Attempt to pre-allocate the SELinux status page so it doesn't appear to userspace that we are skipping SELinux policy sequence numbers - Reject invalid SELinux policy bitmaps with an error at policy load time - Consistently use the same type, u32, for ebitmap offsets - Improve the "symhash" hash function for better distribution on common policies - Correct a number of printk format specifiers in the ebitmap code - Improved error checking in sel_write_load() - Ensure we have a proper return code in the filename_trans_read_helper_compat() function - Make better use of the current_sid() helper function - Allow for more hash table statistics when debugging is enabled - Migrate from printk_ratelimit() to pr_warn_ratelimited() - Miscellaneous cleanups and tweaks to selinux_lsm_getattr() - More consitification work in the conditional policy space * tag 'selinux-pr-20240513' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: constify source policy in cond_policydb_dup() selinux: avoid printk_ratelimit() selinux: pre-allocate the status page selinux: clarify return code in filename_trans_read_helper_compat() selinux: use u32 as bit position type in ebitmap code selinux: improve symtab string hashing selinux: dump statistics for more hash tables selinux: make more use of current_sid() selinux: update numeric format specifiers for ebitmaps selinux: improve error checking in sel_write_load() selinux: cleanup selinux_lsm_getattr() selinux: reject invalid ebitmaps
This commit is contained in:
commit
ccae19c623
@ -2961,7 +2961,7 @@ static int selinux_inode_init_security_anon(struct inode *inode,
|
||||
const struct qstr *name,
|
||||
const struct inode *context_inode)
|
||||
{
|
||||
const struct task_security_struct *tsec = selinux_cred(current_cred());
|
||||
u32 sid = current_sid();
|
||||
struct common_audit_data ad;
|
||||
struct inode_security_struct *isec;
|
||||
int rc;
|
||||
@ -2990,7 +2990,7 @@ static int selinux_inode_init_security_anon(struct inode *inode,
|
||||
} else {
|
||||
isec->sclass = SECCLASS_ANON_INODE;
|
||||
rc = security_transition_sid(
|
||||
tsec->sid, tsec->sid,
|
||||
sid, sid,
|
||||
isec->sclass, name, &isec->sid);
|
||||
if (rc)
|
||||
return rc;
|
||||
@ -3005,7 +3005,7 @@ static int selinux_inode_init_security_anon(struct inode *inode,
|
||||
ad.type = LSM_AUDIT_DATA_ANONINODE;
|
||||
ad.u.anonclass = name ? (const char *)name->name : "?";
|
||||
|
||||
return avc_has_perm(tsec->sid,
|
||||
return avc_has_perm(sid,
|
||||
isec->sid,
|
||||
isec->sclass,
|
||||
FILE__CREATE,
|
||||
@ -3063,14 +3063,12 @@ static int selinux_inode_readlink(struct dentry *dentry)
|
||||
static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
|
||||
bool rcu)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
struct common_audit_data ad;
|
||||
struct inode_security_struct *isec;
|
||||
u32 sid;
|
||||
u32 sid = current_sid();
|
||||
|
||||
ad.type = LSM_AUDIT_DATA_DENTRY;
|
||||
ad.u.dentry = dentry;
|
||||
sid = cred_sid(cred);
|
||||
isec = inode_security_rcu(inode, rcu);
|
||||
if (IS_ERR(isec))
|
||||
return PTR_ERR(isec);
|
||||
@ -3094,12 +3092,11 @@ static noinline int audit_inode_permission(struct inode *inode,
|
||||
|
||||
static int selinux_inode_permission(struct inode *inode, int mask)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
u32 perms;
|
||||
bool from_access;
|
||||
bool no_block = mask & MAY_NOT_BLOCK;
|
||||
struct inode_security_struct *isec;
|
||||
u32 sid;
|
||||
u32 sid = current_sid();
|
||||
struct av_decision avd;
|
||||
int rc, rc2;
|
||||
u32 audited, denied;
|
||||
@ -3116,7 +3113,6 @@ static int selinux_inode_permission(struct inode *inode, int mask)
|
||||
|
||||
perms = file_mask_to_av(inode->i_mode, mask);
|
||||
|
||||
sid = cred_sid(cred);
|
||||
isec = inode_security_rcu(inode, no_block);
|
||||
if (IS_ERR(isec))
|
||||
return PTR_ERR(isec);
|
||||
@ -5564,13 +5560,7 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
static int selinux_secmark_relabel_packet(u32 sid)
|
||||
{
|
||||
const struct task_security_struct *tsec;
|
||||
u32 tsid;
|
||||
|
||||
tsec = selinux_cred(current_cred());
|
||||
tsid = tsec->sid;
|
||||
|
||||
return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
|
||||
return avc_has_perm(current_sid(), sid, SECCLASS_PACKET, PACKET__RELABELTO,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@ -6348,55 +6338,55 @@ static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
|
||||
static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p,
|
||||
char **value)
|
||||
{
|
||||
const struct task_security_struct *__tsec;
|
||||
u32 sid;
|
||||
const struct task_security_struct *tsec;
|
||||
int error;
|
||||
unsigned len;
|
||||
u32 sid;
|
||||
u32 len;
|
||||
|
||||
rcu_read_lock();
|
||||
__tsec = selinux_cred(__task_cred(p));
|
||||
|
||||
if (current != p) {
|
||||
error = avc_has_perm(current_sid(), __tsec->sid,
|
||||
tsec = selinux_cred(__task_cred(p));
|
||||
if (p != current) {
|
||||
error = avc_has_perm(current_sid(), tsec->sid,
|
||||
SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
|
||||
if (error)
|
||||
goto bad;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
switch (attr) {
|
||||
case LSM_ATTR_CURRENT:
|
||||
sid = __tsec->sid;
|
||||
sid = tsec->sid;
|
||||
break;
|
||||
case LSM_ATTR_PREV:
|
||||
sid = __tsec->osid;
|
||||
sid = tsec->osid;
|
||||
break;
|
||||
case LSM_ATTR_EXEC:
|
||||
sid = __tsec->exec_sid;
|
||||
sid = tsec->exec_sid;
|
||||
break;
|
||||
case LSM_ATTR_FSCREATE:
|
||||
sid = __tsec->create_sid;
|
||||
sid = tsec->create_sid;
|
||||
break;
|
||||
case LSM_ATTR_KEYCREATE:
|
||||
sid = __tsec->keycreate_sid;
|
||||
sid = tsec->keycreate_sid;
|
||||
break;
|
||||
case LSM_ATTR_SOCKCREATE:
|
||||
sid = __tsec->sockcreate_sid;
|
||||
sid = tsec->sockcreate_sid;
|
||||
break;
|
||||
default:
|
||||
error = -EOPNOTSUPP;
|
||||
goto bad;
|
||||
goto err_unlock;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!sid)
|
||||
if (sid == SECSID_NULL) {
|
||||
*value = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = security_sid_to_context(sid, value, &len);
|
||||
if (error)
|
||||
return error;
|
||||
return len;
|
||||
|
||||
bad:
|
||||
err_unlock:
|
||||
rcu_read_unlock();
|
||||
return error;
|
||||
}
|
||||
|
@ -571,11 +571,18 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_fs_info *fsi;
|
||||
struct selinux_load_state load_state;
|
||||
ssize_t length;
|
||||
void *data = NULL;
|
||||
|
||||
/* no partial writes */
|
||||
if (*ppos)
|
||||
return -EINVAL;
|
||||
/* no empty policies */
|
||||
if (!count)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&selinux_state.policy_mutex);
|
||||
|
||||
length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
|
||||
@ -583,26 +590,22 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
/* No partial writes. */
|
||||
length = -EINVAL;
|
||||
if (*ppos != 0)
|
||||
goto out;
|
||||
|
||||
length = -ENOMEM;
|
||||
data = vmalloc(count);
|
||||
if (!data)
|
||||
if (!data) {
|
||||
length = -ENOMEM;
|
||||
goto out;
|
||||
|
||||
length = -EFAULT;
|
||||
if (copy_from_user(data, buf, count) != 0)
|
||||
}
|
||||
if (copy_from_user(data, buf, count) != 0) {
|
||||
length = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
length = security_load_policy(data, count, &load_state);
|
||||
if (length) {
|
||||
pr_warn_ratelimited("SELinux: failed to load policy\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
length = sel_make_policy_nodes(fsi, load_state.policy);
|
||||
if (length) {
|
||||
pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n");
|
||||
@ -611,13 +614,12 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
}
|
||||
|
||||
selinux_policy_commit(&load_state);
|
||||
|
||||
length = count;
|
||||
|
||||
audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
|
||||
"auid=%u ses=%u lsm=selinux res=1",
|
||||
from_kuid(&init_user_ns, audit_get_loginuid(current)),
|
||||
audit_get_sessionid(current));
|
||||
|
||||
out:
|
||||
mutex_unlock(&selinux_state.policy_mutex);
|
||||
vfree(data);
|
||||
@ -2161,6 +2163,12 @@ static int __init init_sel_fs(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to pre-allocate the status page, so the sequence number of the
|
||||
* initial policy load can be stored.
|
||||
*/
|
||||
(void) selinux_kernel_status_page();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,9 @@ int cond_init_bool_indexes(struct policydb *p)
|
||||
p->p_bools.nprim, sizeof(*p->bool_val_to_struct), GFP_KERNEL);
|
||||
if (!p->bool_val_to_struct)
|
||||
return -ENOMEM;
|
||||
|
||||
avtab_hash_eval(&p->te_cond_avtab, "conditional_rules");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -600,7 +603,8 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
|
||||
}
|
||||
}
|
||||
|
||||
static int cond_dup_av_list(struct cond_av_list *new, struct cond_av_list *orig,
|
||||
static int cond_dup_av_list(struct cond_av_list *new,
|
||||
const struct cond_av_list *orig,
|
||||
struct avtab *avtab)
|
||||
{
|
||||
u32 i;
|
||||
@ -623,7 +627,7 @@ static int cond_dup_av_list(struct cond_av_list *new, struct cond_av_list *orig,
|
||||
}
|
||||
|
||||
static int duplicate_policydb_cond_list(struct policydb *newp,
|
||||
struct policydb *origp)
|
||||
const struct policydb *origp)
|
||||
{
|
||||
int rc;
|
||||
u32 i;
|
||||
@ -640,7 +644,7 @@ static int duplicate_policydb_cond_list(struct policydb *newp,
|
||||
|
||||
for (i = 0; i < origp->cond_list_len; i++) {
|
||||
struct cond_node *newn = &newp->cond_list[i];
|
||||
struct cond_node *orign = &origp->cond_list[i];
|
||||
const struct cond_node *orign = &origp->cond_list[i];
|
||||
|
||||
newp->cond_list_len++;
|
||||
|
||||
@ -680,8 +684,8 @@ static int cond_bools_destroy(void *key, void *datum, void *args)
|
||||
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,
|
||||
const struct hashtab_node *orig, void *args)
|
||||
{
|
||||
struct cond_bool_datum *datum;
|
||||
|
||||
@ -707,7 +711,7 @@ static int cond_bools_index(void *key, void *datum, void *args)
|
||||
}
|
||||
|
||||
static int duplicate_policydb_bools(struct policydb *newdb,
|
||||
struct policydb *orig)
|
||||
const struct policydb *orig)
|
||||
{
|
||||
struct cond_bool_datum **cond_bool_array;
|
||||
int rc;
|
||||
@ -740,7 +744,7 @@ void cond_policydb_destroy_dup(struct policydb *p)
|
||||
cond_policydb_destroy(p);
|
||||
}
|
||||
|
||||
int cond_policydb_dup(struct policydb *new, struct policydb *orig)
|
||||
int cond_policydb_dup(struct policydb *new, const struct policydb *orig)
|
||||
{
|
||||
cond_policydb_init(new);
|
||||
|
||||
|
@ -79,6 +79,6 @@ void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
|
||||
struct extended_perms_decision *xpermd);
|
||||
void evaluate_cond_nodes(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, const struct policydb *orig);
|
||||
|
||||
#endif /* _CONDITIONAL_H_ */
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "ebitmap.h"
|
||||
#include "policydb.h"
|
||||
|
||||
#define BITS_PER_U64 (sizeof(u64) * 8)
|
||||
#define BITS_PER_U64 ((u32)(sizeof(u64) * 8))
|
||||
|
||||
static struct kmem_cache *ebitmap_node_cachep __ro_after_init;
|
||||
|
||||
@ -79,7 +79,8 @@ int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1,
|
||||
const struct ebitmap *e2)
|
||||
{
|
||||
struct ebitmap_node *n;
|
||||
int bit, rc;
|
||||
u32 bit;
|
||||
int rc;
|
||||
|
||||
ebitmap_init(dst);
|
||||
|
||||
@ -256,7 +257,7 @@ int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit)
|
||||
int ebitmap_get_bit(const struct ebitmap *e, u32 bit)
|
||||
{
|
||||
const struct ebitmap_node *n;
|
||||
|
||||
@ -273,7 +274,7 @@ int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
|
||||
int ebitmap_set_bit(struct ebitmap *e, u32 bit, int value)
|
||||
{
|
||||
struct ebitmap_node *n, *prev, *new;
|
||||
|
||||
@ -284,7 +285,7 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
|
||||
if (value) {
|
||||
ebitmap_node_set_bit(n, bit);
|
||||
} else {
|
||||
unsigned int s;
|
||||
u32 s;
|
||||
|
||||
ebitmap_node_clr_bit(n, bit);
|
||||
|
||||
@ -362,12 +363,12 @@ void ebitmap_destroy(struct ebitmap *e)
|
||||
int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
{
|
||||
struct ebitmap_node *n = NULL;
|
||||
u32 mapunit, count, startbit, index;
|
||||
u32 mapunit, count, startbit, index, i;
|
||||
__le32 ebitmap_start;
|
||||
u64 map;
|
||||
__le64 mapbits;
|
||||
__le32 buf[3];
|
||||
int rc, i;
|
||||
int rc;
|
||||
|
||||
ebitmap_init(e);
|
||||
|
||||
@ -381,7 +382,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
|
||||
if (mapunit != BITS_PER_U64) {
|
||||
pr_err("SELinux: ebitmap: map size %u does not "
|
||||
"match my size %zd (high bit was %d)\n",
|
||||
"match my size %u (high bit was %u)\n",
|
||||
mapunit, BITS_PER_U64, e->highbit);
|
||||
goto bad;
|
||||
}
|
||||
@ -407,13 +408,13 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
startbit = le32_to_cpu(ebitmap_start);
|
||||
|
||||
if (startbit & (mapunit - 1)) {
|
||||
pr_err("SELinux: ebitmap start bit (%d) is "
|
||||
pr_err("SELinux: ebitmap start bit (%u) is "
|
||||
"not a multiple of the map unit size (%u)\n",
|
||||
startbit, mapunit);
|
||||
goto bad;
|
||||
}
|
||||
if (startbit > e->highbit - mapunit) {
|
||||
pr_err("SELinux: ebitmap start bit (%d) is "
|
||||
pr_err("SELinux: ebitmap start bit (%u) is "
|
||||
"beyond the end of the bitmap (%u)\n",
|
||||
startbit, (e->highbit - mapunit));
|
||||
goto bad;
|
||||
@ -436,8 +437,8 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
e->node = tmp;
|
||||
n = tmp;
|
||||
} else if (startbit <= n->startbit) {
|
||||
pr_err("SELinux: ebitmap: start bit %d"
|
||||
" comes after start bit %d\n",
|
||||
pr_err("SELinux: ebitmap: start bit %u"
|
||||
" comes after start bit %u\n",
|
||||
startbit, n->startbit);
|
||||
goto bad;
|
||||
}
|
||||
@ -448,6 +449,10 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
goto bad;
|
||||
}
|
||||
map = le64_to_cpu(mapbits);
|
||||
if (!map) {
|
||||
pr_err("SELinux: ebitmap: empty map\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE;
|
||||
while (map) {
|
||||
@ -455,6 +460,13 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
map = EBITMAP_SHIFT_UNIT_SIZE(map);
|
||||
}
|
||||
}
|
||||
|
||||
if (n && n->startbit + EBITMAP_SIZE != e->highbit) {
|
||||
pr_err("SELinux: ebitmap: high bit %u is not equal to the expected value %zu\n",
|
||||
e->highbit, n->startbit + EBITMAP_SIZE);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ok:
|
||||
rc = 0;
|
||||
out:
|
||||
@ -469,19 +481,20 @@ bad:
|
||||
int ebitmap_write(const struct ebitmap *e, void *fp)
|
||||
{
|
||||
struct ebitmap_node *n;
|
||||
u32 count;
|
||||
u32 bit, count, last_bit, last_startbit;
|
||||
__le32 buf[3];
|
||||
u64 map;
|
||||
int bit, last_bit, last_startbit, rc;
|
||||
int rc;
|
||||
|
||||
buf[0] = cpu_to_le32(BITS_PER_U64);
|
||||
|
||||
count = 0;
|
||||
last_bit = 0;
|
||||
last_startbit = -1;
|
||||
last_startbit = U32_MAX;
|
||||
ebitmap_for_each_positive_bit(e, n, bit)
|
||||
{
|
||||
if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
|
||||
if (last_startbit == U32_MAX ||
|
||||
rounddown(bit, BITS_PER_U64) > last_startbit) {
|
||||
count++;
|
||||
last_startbit = rounddown(bit, BITS_PER_U64);
|
||||
}
|
||||
@ -495,10 +508,11 @@ int ebitmap_write(const struct ebitmap *e, void *fp)
|
||||
return rc;
|
||||
|
||||
map = 0;
|
||||
last_startbit = INT_MIN;
|
||||
last_startbit = U32_MAX;
|
||||
ebitmap_for_each_positive_bit(e, n, bit)
|
||||
{
|
||||
if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
|
||||
if (last_startbit == U32_MAX ||
|
||||
rounddown(bit, BITS_PER_U64) > last_startbit) {
|
||||
__le64 buf64[1];
|
||||
|
||||
/* this is the very first bit */
|
||||
|
@ -46,10 +46,10 @@ struct ebitmap {
|
||||
|
||||
#define ebitmap_length(e) ((e)->highbit)
|
||||
|
||||
static inline unsigned int ebitmap_start_positive(const struct ebitmap *e,
|
||||
struct ebitmap_node **n)
|
||||
static inline u32 ebitmap_start_positive(const struct ebitmap *e,
|
||||
struct ebitmap_node **n)
|
||||
{
|
||||
unsigned int ofs;
|
||||
u32 ofs;
|
||||
|
||||
for (*n = e->node; *n; *n = (*n)->next) {
|
||||
ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
|
||||
@ -64,11 +64,10 @@ static inline void ebitmap_init(struct ebitmap *e)
|
||||
memset(e, 0, sizeof(*e));
|
||||
}
|
||||
|
||||
static inline unsigned int ebitmap_next_positive(const struct ebitmap *e,
|
||||
struct ebitmap_node **n,
|
||||
unsigned int bit)
|
||||
static inline u32 ebitmap_next_positive(const struct ebitmap *e,
|
||||
struct ebitmap_node **n, u32 bit)
|
||||
{
|
||||
unsigned int ofs;
|
||||
u32 ofs;
|
||||
|
||||
ofs = find_next_bit((*n)->maps, EBITMAP_SIZE, bit - (*n)->startbit + 1);
|
||||
if (ofs < EBITMAP_SIZE)
|
||||
@ -87,11 +86,10 @@ static inline unsigned int ebitmap_next_positive(const struct ebitmap *e,
|
||||
#define EBITMAP_NODE_OFFSET(node, bit) \
|
||||
(((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
|
||||
|
||||
static inline int ebitmap_node_get_bit(const struct ebitmap_node *n,
|
||||
unsigned int bit)
|
||||
static inline int ebitmap_node_get_bit(const struct ebitmap_node *n, u32 bit)
|
||||
{
|
||||
unsigned int index = EBITMAP_NODE_INDEX(n, bit);
|
||||
unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
|
||||
u32 index = EBITMAP_NODE_INDEX(n, bit);
|
||||
u32 ofs = EBITMAP_NODE_OFFSET(n, bit);
|
||||
|
||||
BUG_ON(index >= EBITMAP_UNIT_NUMS);
|
||||
if ((n->maps[index] & (EBITMAP_BIT << ofs)))
|
||||
@ -99,21 +97,19 @@ static inline int ebitmap_node_get_bit(const struct ebitmap_node *n,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ebitmap_node_set_bit(struct ebitmap_node *n,
|
||||
unsigned int bit)
|
||||
static inline void ebitmap_node_set_bit(struct ebitmap_node *n, u32 bit)
|
||||
{
|
||||
unsigned int index = EBITMAP_NODE_INDEX(n, bit);
|
||||
unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
|
||||
u32 index = EBITMAP_NODE_INDEX(n, bit);
|
||||
u32 ofs = EBITMAP_NODE_OFFSET(n, bit);
|
||||
|
||||
BUG_ON(index >= EBITMAP_UNIT_NUMS);
|
||||
n->maps[index] |= (EBITMAP_BIT << ofs);
|
||||
}
|
||||
|
||||
static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
|
||||
unsigned int bit)
|
||||
static inline void ebitmap_node_clr_bit(struct ebitmap_node *n, u32 bit)
|
||||
{
|
||||
unsigned int index = EBITMAP_NODE_INDEX(n, bit);
|
||||
unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
|
||||
u32 index = EBITMAP_NODE_INDEX(n, bit);
|
||||
u32 ofs = EBITMAP_NODE_OFFSET(n, bit);
|
||||
|
||||
BUG_ON(index >= EBITMAP_UNIT_NUMS);
|
||||
n->maps[index] &= ~(EBITMAP_BIT << ofs);
|
||||
@ -130,8 +126,8 @@ int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1,
|
||||
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_set_bit(struct ebitmap *e, unsigned long bit, int value);
|
||||
int ebitmap_get_bit(const struct ebitmap *e, u32 bit);
|
||||
int ebitmap_set_bit(struct ebitmap *e, u32 bit, int value);
|
||||
void ebitmap_destroy(struct ebitmap *e);
|
||||
int ebitmap_read(struct ebitmap *e, void *fp);
|
||||
int ebitmap_write(const struct ebitmap *e, void *fp);
|
||||
|
@ -136,11 +136,12 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
|
||||
}
|
||||
#endif /* CONFIG_SECURITY_SELINUX_DEBUG */
|
||||
|
||||
int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
|
||||
int hashtab_duplicate(struct hashtab *new, const struct hashtab *orig,
|
||||
int (*copy)(struct hashtab_node *new,
|
||||
struct hashtab_node *orig, void *args),
|
||||
const struct hashtab_node *orig, void *args),
|
||||
int (*destroy)(void *k, void *d, void *args), void *args)
|
||||
{
|
||||
const struct hashtab_node *orig_cur;
|
||||
struct hashtab_node *cur, *tmp, *tail;
|
||||
u32 i;
|
||||
int rc;
|
||||
@ -155,12 +156,13 @@ int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
|
||||
|
||||
for (i = 0; i < orig->size; i++) {
|
||||
tail = NULL;
|
||||
for (cur = orig->htable[i]; cur; cur = cur->next) {
|
||||
for (orig_cur = orig->htable[i]; orig_cur;
|
||||
orig_cur = orig_cur->next) {
|
||||
tmp = kmem_cache_zalloc(hashtab_node_cachep,
|
||||
GFP_KERNEL);
|
||||
if (!tmp)
|
||||
goto error;
|
||||
rc = copy(tmp, cur, args);
|
||||
rc = copy(tmp, orig_cur, args);
|
||||
if (rc) {
|
||||
kmem_cache_free(hashtab_node_cachep, tmp);
|
||||
goto error;
|
||||
|
@ -136,9 +136,9 @@ void hashtab_destroy(struct hashtab *h);
|
||||
int hashtab_map(struct hashtab *h, int (*apply)(void *k, void *d, void *args),
|
||||
void *args);
|
||||
|
||||
int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
|
||||
int hashtab_duplicate(struct hashtab *new, const struct hashtab *orig,
|
||||
int (*copy)(struct hashtab_node *new,
|
||||
struct hashtab_node *orig, void *args),
|
||||
const struct hashtab_node *orig, void *args),
|
||||
int (*destroy)(void *k, void *d, void *args), void *args);
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEBUG
|
||||
|
@ -672,14 +672,16 @@ static int (*const index_f[SYM_NUM])(void *key, void *datum, void *datap) = {
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEBUG
|
||||
static void hash_eval(struct hashtab *h, const char *hash_name)
|
||||
static void hash_eval(struct hashtab *h, const char *hash_name,
|
||||
const char *hash_details)
|
||||
{
|
||||
struct hashtab_info info;
|
||||
|
||||
hashtab_stat(h, &info);
|
||||
pr_debug(
|
||||
"SELinux: %s: %d entries and %d/%d buckets used, longest chain length %d, sum of chain length^2 %llu\n",
|
||||
hash_name, h->nel, info.slots_used, h->size, info.max_chain_len,
|
||||
"SELinux: %s%s%s: %d entries and %d/%d buckets used, longest chain length %d, sum of chain length^2 %llu\n",
|
||||
hash_name, hash_details ? "@" : "", hash_details ?: "", h->nel,
|
||||
info.slots_used, h->size, info.max_chain_len,
|
||||
info.chain2_len_sum);
|
||||
}
|
||||
|
||||
@ -688,11 +690,12 @@ static void symtab_hash_eval(struct symtab *s)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SYM_NUM; i++)
|
||||
hash_eval(&s[i].table, symtab_name[i]);
|
||||
hash_eval(&s[i].table, symtab_name[i], NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void hash_eval(struct hashtab *h, const char *hash_name)
|
||||
static inline void hash_eval(struct hashtab *h, const char *hash_name,
|
||||
const char *hash_details)
|
||||
{
|
||||
}
|
||||
static inline void symtab_hash_eval(struct symtab *s)
|
||||
@ -1178,6 +1181,8 @@ static int common_read(struct policydb *p, struct symtab *s, void *fp)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
hash_eval(&comdatum->permissions.table, "common_permissions", key);
|
||||
|
||||
rc = symtab_insert(s, key, comdatum);
|
||||
if (rc)
|
||||
goto bad;
|
||||
@ -1358,6 +1363,8 @@ static int class_read(struct policydb *p, struct symtab *s, void *fp)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
hash_eval(&cladatum->permissions.table, "class_permissions", key);
|
||||
|
||||
rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);
|
||||
if (rc)
|
||||
goto bad;
|
||||
@ -1898,7 +1905,7 @@ static int range_read(struct policydb *p, void *fp)
|
||||
rt = NULL;
|
||||
r = NULL;
|
||||
}
|
||||
hash_eval(&p->range_tr, "rangetr");
|
||||
hash_eval(&p->range_tr, "rangetr", NULL);
|
||||
rc = 0;
|
||||
out:
|
||||
kfree(rt);
|
||||
@ -1943,6 +1950,7 @@ static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
|
||||
if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
|
||||
/* conflicting/duplicate rules are ignored */
|
||||
datum = NULL;
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
if (likely(datum->otype == otype))
|
||||
@ -2116,7 +2124,7 @@ static int filename_trans_read(struct policydb *p, void *fp)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
hash_eval(&p->filename_trans, "filenametr");
|
||||
hash_eval(&p->filename_trans, "filenametr", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2649,6 +2657,8 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
rtd = NULL;
|
||||
}
|
||||
|
||||
hash_eval(&p->role_tr, "roletr", NULL);
|
||||
|
||||
rc = next_entry(buf, fp, sizeof(u32));
|
||||
if (rc)
|
||||
goto bad;
|
||||
|
@ -633,8 +633,7 @@ static void context_struct_compute_av(struct policydb *policydb,
|
||||
}
|
||||
|
||||
if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) {
|
||||
if (printk_ratelimit())
|
||||
pr_warn("SELinux: Invalid class %hu\n", tclass);
|
||||
pr_warn_ratelimited("SELinux: Invalid class %u\n", tclass);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -12,17 +12,17 @@
|
||||
|
||||
static unsigned int symhash(const void *key)
|
||||
{
|
||||
const char *p, *keyp;
|
||||
unsigned int size;
|
||||
unsigned int val;
|
||||
/*
|
||||
* djb2a
|
||||
* Public domain from cdb v0.75
|
||||
*/
|
||||
unsigned int hash = 5381;
|
||||
unsigned char c;
|
||||
|
||||
val = 0;
|
||||
keyp = key;
|
||||
size = strlen(keyp);
|
||||
for (p = keyp; (p - keyp) < size; p++)
|
||||
val = (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^
|
||||
(*p);
|
||||
return val;
|
||||
while ((c = *(const unsigned char *)key++))
|
||||
hash = ((hash << 5) + hash) ^ c;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static int symcmp(const void *key1, const void *key2)
|
||||
|
@ -76,7 +76,6 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
|
||||
gfp_t gfp)
|
||||
{
|
||||
int rc;
|
||||
const struct task_security_struct *tsec = selinux_cred(current_cred());
|
||||
struct xfrm_sec_ctx *ctx = NULL;
|
||||
u32 str_len;
|
||||
|
||||
@ -103,7 +102,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
|
||||
rc = avc_has_perm(current_sid(), ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
|
||||
if (rc)
|
||||
goto err;
|
||||
@ -134,12 +133,10 @@ static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
|
||||
*/
|
||||
static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
|
||||
{
|
||||
const struct task_security_struct *tsec = selinux_cred(current_cred());
|
||||
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
return avc_has_perm(tsec->sid, ctx->ctx_sid,
|
||||
return avc_has_perm(current_sid(), ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
|
||||
NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user