Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6: security: enhance DEFAULT_MMAP_MIN_ADDR description SELinux: add netport.[ch] SELinux: Add network port SID cache SELinux: turn mount options strings into defines selinux/ss/services.c should #include <linux/selinux.h> selinux: introduce permissive types selinux: remove ptrace_sid SELinux: requesting no permissions in avc_has_perm_noaudit is a BUG() security: code cleanup security: replace remaining __FUNCTION__ occurrences SELinux: create new open permission selinux: selinux/netlabel.c should #include "netlabel.h" SELinux: unify printk messages SELinux: remove unused backpointers from security objects SELinux: Correct the NetLabel locking for the sk_security_struct
This commit is contained in:
commit
30bc94566e
@ -113,10 +113,12 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
|
|||||||
from userspace allocation. Keeping a user from writing to low pages
|
from userspace allocation. Keeping a user from writing to low pages
|
||||||
can help reduce the impact of kernel NULL pointer bugs.
|
can help reduce the impact of kernel NULL pointer bugs.
|
||||||
|
|
||||||
For most users with lots of address space a value of 65536 is
|
For most ia64, ppc64 and x86 users with lots of address space
|
||||||
reasonable and should cause no problems. Programs which use vm86
|
a value of 65536 is reasonable and should cause no problems.
|
||||||
functionality would either need additional permissions from either
|
On arm and other archs it should not be higher than 32768.
|
||||||
the LSM or the capabilities module or have this protection disabled.
|
Programs which use vm86 functionality would either need additional
|
||||||
|
permissions from either the LSM or the capabilities module or have
|
||||||
|
this protection disabled.
|
||||||
|
|
||||||
This value can be changed after boot using the
|
This value can be changed after boot using the
|
||||||
/proc/sys/vm/mmap_min_addr tunable.
|
/proc/sys/vm/mmap_min_addr tunable.
|
||||||
|
@ -267,7 +267,7 @@ static int get_file_caps(struct linux_binprm *bprm)
|
|||||||
rc = cap_from_disk(&vcaps, bprm, rc);
|
rc = cap_from_disk(&vcaps, bprm, rc);
|
||||||
if (rc)
|
if (rc)
|
||||||
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
|
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
|
||||||
__FUNCTION__, rc, bprm->filename);
|
__func__, rc, bprm->filename);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
|
|||||||
ret = get_file_caps(bprm);
|
ret = get_file_caps(bprm);
|
||||||
if (ret)
|
if (ret)
|
||||||
printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
|
printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
|
||||||
__FUNCTION__, ret, bprm->filename);
|
__func__, ret, bprm->filename);
|
||||||
|
|
||||||
/* To support inheritance of root-permissions and suid-root
|
/* To support inheritance of root-permissions and suid-root
|
||||||
* executables under compatibility mode, we raise all three
|
* executables under compatibility mode, we raise all three
|
||||||
|
@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...)
|
|||||||
|
|
||||||
#ifdef __KDEBUG
|
#ifdef __KDEBUG
|
||||||
#define kenter(FMT, ...) \
|
#define kenter(FMT, ...) \
|
||||||
printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
|
printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
|
||||||
#define kleave(FMT, ...) \
|
#define kleave(FMT, ...) \
|
||||||
printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
|
printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
|
||||||
#define kdebug(FMT, ...) \
|
#define kdebug(FMT, ...) \
|
||||||
printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
|
printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define kenter(FMT, ...) \
|
#define kenter(FMT, ...) \
|
||||||
no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
|
no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
|
||||||
#define kleave(FMT, ...) \
|
#define kleave(FMT, ...) \
|
||||||
no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
|
no_printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
|
||||||
#define kdebug(FMT, ...) \
|
#define kdebug(FMT, ...) \
|
||||||
no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
|
no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,7 +49,7 @@ module_param(debug, bool, 0600);
|
|||||||
do { \
|
do { \
|
||||||
if (debug) \
|
if (debug) \
|
||||||
printk(KERN_DEBUG "%s: %s: " fmt , \
|
printk(KERN_DEBUG "%s: %s: " fmt , \
|
||||||
MY_NAME , __FUNCTION__ , \
|
MY_NAME , __func__ , \
|
||||||
## arg); \
|
## arg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ int __init security_init(void)
|
|||||||
|
|
||||||
if (verify(&dummy_security_ops)) {
|
if (verify(&dummy_security_ops)) {
|
||||||
printk(KERN_ERR "%s could not verify "
|
printk(KERN_ERR "%s could not verify "
|
||||||
"dummy_security_ops structure.\n", __FUNCTION__);
|
"dummy_security_ops structure.\n", __func__);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ int register_security(struct security_operations *ops)
|
|||||||
{
|
{
|
||||||
if (verify(ops)) {
|
if (verify(ops)) {
|
||||||
printk(KERN_DEBUG "%s could not verify "
|
printk(KERN_DEBUG "%s could not verify "
|
||||||
"security_operations structure.\n", __FUNCTION__);
|
"security_operations structure.\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,13 +110,13 @@ int mod_reg_security(const char *name, struct security_operations *ops)
|
|||||||
{
|
{
|
||||||
if (verify(ops)) {
|
if (verify(ops)) {
|
||||||
printk(KERN_INFO "%s could not verify "
|
printk(KERN_INFO "%s could not verify "
|
||||||
"security operations.\n", __FUNCTION__);
|
"security operations.\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ops == security_ops) {
|
if (ops == security_ops) {
|
||||||
printk(KERN_INFO "%s security operations "
|
printk(KERN_INFO "%s security operations "
|
||||||
"already registered.\n", __FUNCTION__);
|
"already registered.\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
|||||||
config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
|
config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
|
||||||
int "NSA SELinux maximum supported policy format version value"
|
int "NSA SELinux maximum supported policy format version value"
|
||||||
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
||||||
range 15 22
|
range 15 23
|
||||||
default 19
|
default 19
|
||||||
help
|
help
|
||||||
This option sets the value for the maximum policy format version
|
This option sets the value for the maximum policy format version
|
||||||
|
@ -11,6 +11,7 @@ selinux-y := avc.o \
|
|||||||
nlmsgtab.o \
|
nlmsgtab.o \
|
||||||
netif.o \
|
netif.o \
|
||||||
netnode.o \
|
netnode.o \
|
||||||
|
netport.o \
|
||||||
exports.o
|
exports.o
|
||||||
|
|
||||||
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
|
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
|
||||||
|
@ -871,6 +871,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
u32 denied;
|
u32 denied;
|
||||||
|
|
||||||
|
BUG_ON(!requested);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
node = avc_lookup(ssid, tsid, tclass, requested);
|
node = avc_lookup(ssid, tsid, tclass, requested);
|
||||||
@ -890,13 +892,14 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
|||||||
|
|
||||||
denied = requested & ~(p_ae->avd.allowed);
|
denied = requested & ~(p_ae->avd.allowed);
|
||||||
|
|
||||||
if (!requested || denied) {
|
if (denied) {
|
||||||
if (selinux_enforcing || (flags & AVC_STRICT))
|
if (flags & AVC_STRICT)
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
|
else if (!selinux_enforcing || security_permissive_sid(ssid))
|
||||||
|
avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
|
||||||
|
tsid, tclass);
|
||||||
else
|
else
|
||||||
if (node)
|
rc = -EACCES;
|
||||||
avc_update_node(AVC_CALLBACK_GRANT,requested,
|
|
||||||
ssid,tsid,tclass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
#include "objsec.h"
|
#include "objsec.h"
|
||||||
#include "netif.h"
|
#include "netif.h"
|
||||||
#include "netnode.h"
|
#include "netnode.h"
|
||||||
|
#include "netport.h"
|
||||||
#include "xfrm.h"
|
#include "xfrm.h"
|
||||||
#include "netlabel.h"
|
#include "netlabel.h"
|
||||||
|
|
||||||
@ -161,8 +162,7 @@ static int task_alloc_security(struct task_struct *task)
|
|||||||
if (!tsec)
|
if (!tsec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
tsec->task = task;
|
tsec->osid = tsec->sid = SECINITSID_UNLABELED;
|
||||||
tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
|
|
||||||
task->security = tsec;
|
task->security = tsec;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -218,7 +218,6 @@ static int file_alloc_security(struct file *file)
|
|||||||
if (!fsec)
|
if (!fsec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
fsec->file = file;
|
|
||||||
fsec->sid = tsec->sid;
|
fsec->sid = tsec->sid;
|
||||||
fsec->fown_sid = tsec->sid;
|
fsec->fown_sid = tsec->sid;
|
||||||
file->f_security = fsec;
|
file->f_security = fsec;
|
||||||
@ -275,12 +274,11 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
|
|||||||
if (!ssec)
|
if (!ssec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ssec->sk = sk;
|
|
||||||
ssec->peer_sid = SECINITSID_UNLABELED;
|
ssec->peer_sid = SECINITSID_UNLABELED;
|
||||||
ssec->sid = SECINITSID_UNLABELED;
|
ssec->sid = SECINITSID_UNLABELED;
|
||||||
sk->sk_security = ssec;
|
sk->sk_security = ssec;
|
||||||
|
|
||||||
selinux_netlbl_sk_security_init(ssec, family);
|
selinux_netlbl_sk_security_reset(ssec, family);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -324,10 +322,10 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static match_table_t tokens = {
|
static match_table_t tokens = {
|
||||||
{Opt_context, "context=%s"},
|
{Opt_context, CONTEXT_STR "%s"},
|
||||||
{Opt_fscontext, "fscontext=%s"},
|
{Opt_fscontext, FSCONTEXT_STR "%s"},
|
||||||
{Opt_defcontext, "defcontext=%s"},
|
{Opt_defcontext, DEFCONTEXT_STR "%s"},
|
||||||
{Opt_rootcontext, "rootcontext=%s"},
|
{Opt_rootcontext, ROOTCONTEXT_STR "%s"},
|
||||||
{Opt_error, NULL},
|
{Opt_error, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -671,7 +669,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
|||||||
rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
|
rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
|
printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
|
||||||
__FUNCTION__, sb->s_type->name, rc);
|
__func__, sb->s_type->name, rc);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1137,7 +1135,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
|||||||
}
|
}
|
||||||
if (!dentry) {
|
if (!dentry) {
|
||||||
printk(KERN_WARNING "%s: no dentry for dev=%s "
|
printk(KERN_WARNING "%s: no dentry for dev=%s "
|
||||||
"ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
|
"ino=%ld\n", __func__, inode->i_sb->s_id,
|
||||||
inode->i_ino);
|
inode->i_ino);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
@ -1175,7 +1173,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
|||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if (rc != -ENODATA) {
|
if (rc != -ENODATA) {
|
||||||
printk(KERN_WARNING "%s: getxattr returned "
|
printk(KERN_WARNING "%s: getxattr returned "
|
||||||
"%d for dev=%s ino=%ld\n", __FUNCTION__,
|
"%d for dev=%s ino=%ld\n", __func__,
|
||||||
-rc, inode->i_sb->s_id, inode->i_ino);
|
-rc, inode->i_sb->s_id, inode->i_ino);
|
||||||
kfree(context);
|
kfree(context);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
@ -1190,7 +1188,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_WARNING "%s: context_to_sid(%s) "
|
printk(KERN_WARNING "%s: context_to_sid(%s) "
|
||||||
"returned %d for dev=%s ino=%ld\n",
|
"returned %d for dev=%s ino=%ld\n",
|
||||||
__FUNCTION__, context, -rc,
|
__func__, context, -rc,
|
||||||
inode->i_sb->s_id, inode->i_ino);
|
inode->i_sb->s_id, inode->i_ino);
|
||||||
kfree(context);
|
kfree(context);
|
||||||
/* Leave with the unlabeled SID */
|
/* Leave with the unlabeled SID */
|
||||||
@ -1618,6 +1616,35 @@ static inline u32 file_mask_to_av(int mode, int mask)
|
|||||||
return av;
|
return av;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a file mask to an access vector and include the correct open
|
||||||
|
* open permission.
|
||||||
|
*/
|
||||||
|
static inline u32 open_file_mask_to_av(int mode, int mask)
|
||||||
|
{
|
||||||
|
u32 av = file_mask_to_av(mode, mask);
|
||||||
|
|
||||||
|
if (selinux_policycap_openperm) {
|
||||||
|
/*
|
||||||
|
* lnk files and socks do not really have an 'open'
|
||||||
|
*/
|
||||||
|
if (S_ISREG(mode))
|
||||||
|
av |= FILE__OPEN;
|
||||||
|
else if (S_ISCHR(mode))
|
||||||
|
av |= CHR_FILE__OPEN;
|
||||||
|
else if (S_ISBLK(mode))
|
||||||
|
av |= BLK_FILE__OPEN;
|
||||||
|
else if (S_ISFIFO(mode))
|
||||||
|
av |= FIFO_FILE__OPEN;
|
||||||
|
else if (S_ISDIR(mode))
|
||||||
|
av |= DIR__OPEN;
|
||||||
|
else
|
||||||
|
printk(KERN_ERR "SELinux: WARNING: inside open_file_to_av "
|
||||||
|
"with unknown mode:%x\n", mode);
|
||||||
|
}
|
||||||
|
return av;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert a Linux file to an access vector. */
|
/* Convert a Linux file to an access vector. */
|
||||||
static inline u32 file_to_av(struct file *file)
|
static inline u32 file_to_av(struct file *file)
|
||||||
{
|
{
|
||||||
@ -1645,19 +1672,13 @@ static inline u32 file_to_av(struct file *file)
|
|||||||
|
|
||||||
static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
|
static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
|
||||||
{
|
{
|
||||||
struct task_security_struct *psec = parent->security;
|
|
||||||
struct task_security_struct *csec = child->security;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = secondary_ops->ptrace(parent,child);
|
rc = secondary_ops->ptrace(parent,child);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = task_has_perm(parent, child, PROCESS__PTRACE);
|
return task_has_perm(parent, child, PROCESS__PTRACE);
|
||||||
/* Save the SID of the tracing process for later use in apply_creds. */
|
|
||||||
if (!(child->ptrace & PT_PTRACED) && !rc)
|
|
||||||
csec->ptrace_sid = psec->sid;
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
|
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
|
||||||
@ -1879,6 +1900,22 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
|
|||||||
return __vm_enough_memory(mm, pages, cap_sys_admin);
|
return __vm_enough_memory(mm, pages, cap_sys_admin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task_tracer_task - return the task that is tracing the given task
|
||||||
|
* @task: task to consider
|
||||||
|
*
|
||||||
|
* Returns NULL if noone is tracing @task, or the &struct task_struct
|
||||||
|
* pointer to its tracer.
|
||||||
|
*
|
||||||
|
* Must be called under rcu_read_lock().
|
||||||
|
*/
|
||||||
|
static struct task_struct *task_tracer_task(struct task_struct *task)
|
||||||
|
{
|
||||||
|
if (task->ptrace & PT_PTRACED)
|
||||||
|
return rcu_dereference(task->parent);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* binprm security operations */
|
/* binprm security operations */
|
||||||
|
|
||||||
static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
|
static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
|
||||||
@ -1889,7 +1926,6 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
|
|||||||
if (!bsec)
|
if (!bsec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
bsec->bprm = bprm;
|
|
||||||
bsec->sid = SECINITSID_UNLABELED;
|
bsec->sid = SECINITSID_UNLABELED;
|
||||||
bsec->set = 0;
|
bsec->set = 0;
|
||||||
|
|
||||||
@ -2126,12 +2162,25 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
|
|||||||
/* Check for ptracing, and update the task SID if ok.
|
/* Check for ptracing, and update the task SID if ok.
|
||||||
Otherwise, leave SID unchanged and kill. */
|
Otherwise, leave SID unchanged and kill. */
|
||||||
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
|
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
|
||||||
rc = avc_has_perm(tsec->ptrace_sid, sid,
|
struct task_struct *tracer;
|
||||||
SECCLASS_PROCESS, PROCESS__PTRACE,
|
struct task_security_struct *sec;
|
||||||
NULL);
|
u32 ptsid = 0;
|
||||||
if (rc) {
|
|
||||||
bsec->unsafe = 1;
|
rcu_read_lock();
|
||||||
return;
|
tracer = task_tracer_task(current);
|
||||||
|
if (likely(tracer != NULL)) {
|
||||||
|
sec = tracer->security;
|
||||||
|
ptsid = sec->sid;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
if (ptsid != 0) {
|
||||||
|
rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
|
||||||
|
PROCESS__PTRACE, NULL);
|
||||||
|
if (rc) {
|
||||||
|
bsec->unsafe = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tsec->sid = sid;
|
tsec->sid = sid;
|
||||||
@ -2239,10 +2288,10 @@ static inline int match_prefix(char *prefix, int plen, char *option, int olen)
|
|||||||
|
|
||||||
static inline int selinux_option(char *option, int len)
|
static inline int selinux_option(char *option, int len)
|
||||||
{
|
{
|
||||||
return (match_prefix("context=", sizeof("context=")-1, option, len) ||
|
return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
|
||||||
match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
|
match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
|
||||||
match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
|
match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
|
||||||
match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
|
match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void take_option(char **to, char *from, int *first, int len)
|
static inline void take_option(char **to, char *from, int *first, int len)
|
||||||
@ -2412,7 +2461,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
|
|||||||
printk(KERN_WARNING "%s: "
|
printk(KERN_WARNING "%s: "
|
||||||
"security_transition_sid failed, rc=%d (dev=%s "
|
"security_transition_sid failed, rc=%d (dev=%s "
|
||||||
"ino=%ld)\n",
|
"ino=%ld)\n",
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
-rc, inode->i_sb->s_id, inode->i_ino);
|
-rc, inode->i_sb->s_id, inode->i_ino);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2536,7 +2585,7 @@ static int selinux_inode_permission(struct inode *inode, int mask,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return inode_has_perm(current, inode,
|
return inode_has_perm(current, inode,
|
||||||
file_mask_to_av(inode->i_mode, mask), NULL);
|
open_file_mask_to_av(inode->i_mode, mask), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||||
@ -2646,7 +2695,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
|
|||||||
rc = security_context_to_sid(value, size, &newsid);
|
rc = security_context_to_sid(value, size, &newsid);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_WARNING "%s: unable to obtain SID for context "
|
printk(KERN_WARNING "%s: unable to obtain SID for context "
|
||||||
"%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
|
"%s, rc=%d\n", __func__, (char *)value, -rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3087,11 +3136,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
|
|||||||
tsec2->keycreate_sid = tsec1->keycreate_sid;
|
tsec2->keycreate_sid = tsec1->keycreate_sid;
|
||||||
tsec2->sockcreate_sid = tsec1->sockcreate_sid;
|
tsec2->sockcreate_sid = tsec1->sockcreate_sid;
|
||||||
|
|
||||||
/* Retain ptracer SID across fork, if any.
|
|
||||||
This will be reset by the ptrace hook upon any
|
|
||||||
subsequent ptrace_attach operations. */
|
|
||||||
tsec2->ptrace_sid = tsec1->ptrace_sid;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3627,10 +3671,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
|
|||||||
inet_get_local_port_range(&low, &high);
|
inet_get_local_port_range(&low, &high);
|
||||||
|
|
||||||
if (snum < max(PROT_SOCK, low) || snum > high) {
|
if (snum < max(PROT_SOCK, low) || snum > high) {
|
||||||
err = security_port_sid(sk->sk_family,
|
err = sel_netport_sid(sk->sk_protocol,
|
||||||
sk->sk_type,
|
snum, &sid);
|
||||||
sk->sk_protocol, snum,
|
|
||||||
&sid);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
AVC_AUDIT_DATA_INIT(&ad,NET);
|
AVC_AUDIT_DATA_INIT(&ad,NET);
|
||||||
@ -3718,8 +3760,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
|
|||||||
snum = ntohs(addr6->sin6_port);
|
snum = ntohs(addr6->sin6_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = security_port_sid(sk->sk_family, sk->sk_type,
|
err = sel_netport_sid(sk->sk_protocol, snum, &sid);
|
||||||
sk->sk_protocol, snum, &sid);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -3950,9 +3991,8 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
|
|||||||
|
|
||||||
if (!recv_perm)
|
if (!recv_perm)
|
||||||
return 0;
|
return 0;
|
||||||
err = security_port_sid(sk->sk_family, sk->sk_type,
|
err = sel_netport_sid(sk->sk_protocol,
|
||||||
sk->sk_protocol, ntohs(ad->u.net.sport),
|
ntohs(ad->u.net.sport), &port_sid);
|
||||||
&port_sid);
|
|
||||||
if (unlikely(err)) {
|
if (unlikely(err)) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"SELinux: failure in"
|
"SELinux: failure in"
|
||||||
@ -4139,7 +4179,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
|
|||||||
newssec->peer_sid = ssec->peer_sid;
|
newssec->peer_sid = ssec->peer_sid;
|
||||||
newssec->sclass = ssec->sclass;
|
newssec->sclass = ssec->sclass;
|
||||||
|
|
||||||
selinux_netlbl_sk_security_clone(ssec, newssec);
|
selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
|
static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
|
||||||
@ -4373,9 +4413,8 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
|
|||||||
if (send_perm != 0)
|
if (send_perm != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = security_port_sid(sk->sk_family, sk->sk_type,
|
err = sel_netport_sid(sk->sk_protocol,
|
||||||
sk->sk_protocol, ntohs(ad->u.net.dport),
|
ntohs(ad->u.net.dport), &port_sid);
|
||||||
&port_sid);
|
|
||||||
if (unlikely(err)) {
|
if (unlikely(err)) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"SELinux: failure in"
|
"SELinux: failure in"
|
||||||
@ -4561,7 +4600,6 @@ static int ipc_alloc_security(struct task_struct *task,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
isec->sclass = sclass;
|
isec->sclass = sclass;
|
||||||
isec->ipc_perm = perm;
|
|
||||||
isec->sid = tsec->sid;
|
isec->sid = tsec->sid;
|
||||||
perm->security = isec;
|
perm->security = isec;
|
||||||
|
|
||||||
@ -4583,7 +4621,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
|
|||||||
if (!msec)
|
if (!msec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
msec->msg = msg;
|
|
||||||
msec->sid = SECINITSID_UNLABELED;
|
msec->sid = SECINITSID_UNLABELED;
|
||||||
msg->security = msec;
|
msg->security = msec;
|
||||||
|
|
||||||
@ -4994,14 +5031,14 @@ static int selinux_register_security (const char *name, struct security_operatio
|
|||||||
{
|
{
|
||||||
if (secondary_ops != original_ops) {
|
if (secondary_ops != original_ops) {
|
||||||
printk(KERN_ERR "%s: There is already a secondary security "
|
printk(KERN_ERR "%s: There is already a secondary security "
|
||||||
"module registered.\n", __FUNCTION__);
|
"module registered.\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
secondary_ops = ops;
|
secondary_ops = ops;
|
||||||
|
|
||||||
printk(KERN_INFO "%s: Registering secondary module %s\n",
|
printk(KERN_INFO "%s: Registering secondary module %s\n",
|
||||||
__FUNCTION__,
|
__func__,
|
||||||
name);
|
name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -5057,6 +5094,7 @@ static int selinux_setprocattr(struct task_struct *p,
|
|||||||
char *name, void *value, size_t size)
|
char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
struct task_security_struct *tsec;
|
struct task_security_struct *tsec;
|
||||||
|
struct task_struct *tracer;
|
||||||
u32 sid = 0;
|
u32 sid = 0;
|
||||||
int error;
|
int error;
|
||||||
char *str = value;
|
char *str = value;
|
||||||
@ -5145,18 +5183,24 @@ static int selinux_setprocattr(struct task_struct *p,
|
|||||||
/* Check for ptracing, and update the task SID if ok.
|
/* Check for ptracing, and update the task SID if ok.
|
||||||
Otherwise, leave SID unchanged and fail. */
|
Otherwise, leave SID unchanged and fail. */
|
||||||
task_lock(p);
|
task_lock(p);
|
||||||
if (p->ptrace & PT_PTRACED) {
|
rcu_read_lock();
|
||||||
error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
|
tracer = task_tracer_task(p);
|
||||||
|
if (tracer != NULL) {
|
||||||
|
struct task_security_struct *ptsec = tracer->security;
|
||||||
|
u32 ptsid = ptsec->sid;
|
||||||
|
rcu_read_unlock();
|
||||||
|
error = avc_has_perm_noaudit(ptsid, sid,
|
||||||
SECCLASS_PROCESS,
|
SECCLASS_PROCESS,
|
||||||
PROCESS__PTRACE, 0, &avd);
|
PROCESS__PTRACE, 0, &avd);
|
||||||
if (!error)
|
if (!error)
|
||||||
tsec->sid = sid;
|
tsec->sid = sid;
|
||||||
task_unlock(p);
|
task_unlock(p);
|
||||||
avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
|
avc_audit(ptsid, sid, SECCLASS_PROCESS,
|
||||||
PROCESS__PTRACE, &avd, error, NULL);
|
PROCESS__PTRACE, &avd, error, NULL);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
} else {
|
} else {
|
||||||
|
rcu_read_unlock();
|
||||||
tsec->sid = sid;
|
tsec->sid = sid;
|
||||||
task_unlock(p);
|
task_unlock(p);
|
||||||
}
|
}
|
||||||
@ -5194,7 +5238,6 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
|
|||||||
if (!ksec)
|
if (!ksec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ksec->obj = k;
|
|
||||||
if (tsec->keycreate_sid)
|
if (tsec->keycreate_sid)
|
||||||
ksec->sid = tsec->keycreate_sid;
|
ksec->sid = tsec->keycreate_sid;
|
||||||
else
|
else
|
||||||
@ -5631,5 +5674,3 @@ int selinux_disable(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,12 +14,17 @@
|
|||||||
S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
|
S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
|
||||||
S_(SECCLASS_DIR, DIR__SEARCH, "search")
|
S_(SECCLASS_DIR, DIR__SEARCH, "search")
|
||||||
S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
|
S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
|
||||||
|
S_(SECCLASS_DIR, DIR__OPEN, "open")
|
||||||
S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
|
S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
|
||||||
S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
|
S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
|
||||||
S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
|
S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
|
||||||
|
S_(SECCLASS_FILE, FILE__OPEN, "open")
|
||||||
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
|
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
|
||||||
S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
|
S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
|
||||||
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
|
S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
|
||||||
|
S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open")
|
||||||
|
S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open")
|
||||||
|
S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open")
|
||||||
S_(SECCLASS_FD, FD__USE, "use")
|
S_(SECCLASS_FD, FD__USE, "use")
|
||||||
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
|
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
|
||||||
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
|
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
#define DIR__REPARENT 0x00080000UL
|
#define DIR__REPARENT 0x00080000UL
|
||||||
#define DIR__SEARCH 0x00100000UL
|
#define DIR__SEARCH 0x00100000UL
|
||||||
#define DIR__RMDIR 0x00200000UL
|
#define DIR__RMDIR 0x00200000UL
|
||||||
|
#define DIR__OPEN 0x00400000UL
|
||||||
#define FILE__IOCTL 0x00000001UL
|
#define FILE__IOCTL 0x00000001UL
|
||||||
#define FILE__READ 0x00000002UL
|
#define FILE__READ 0x00000002UL
|
||||||
#define FILE__WRITE 0x00000004UL
|
#define FILE__WRITE 0x00000004UL
|
||||||
@ -99,6 +100,7 @@
|
|||||||
#define FILE__EXECUTE_NO_TRANS 0x00020000UL
|
#define FILE__EXECUTE_NO_TRANS 0x00020000UL
|
||||||
#define FILE__ENTRYPOINT 0x00040000UL
|
#define FILE__ENTRYPOINT 0x00040000UL
|
||||||
#define FILE__EXECMOD 0x00080000UL
|
#define FILE__EXECMOD 0x00080000UL
|
||||||
|
#define FILE__OPEN 0x00100000UL
|
||||||
#define LNK_FILE__IOCTL 0x00000001UL
|
#define LNK_FILE__IOCTL 0x00000001UL
|
||||||
#define LNK_FILE__READ 0x00000002UL
|
#define LNK_FILE__READ 0x00000002UL
|
||||||
#define LNK_FILE__WRITE 0x00000004UL
|
#define LNK_FILE__WRITE 0x00000004UL
|
||||||
@ -136,6 +138,7 @@
|
|||||||
#define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL
|
#define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL
|
||||||
#define CHR_FILE__ENTRYPOINT 0x00040000UL
|
#define CHR_FILE__ENTRYPOINT 0x00040000UL
|
||||||
#define CHR_FILE__EXECMOD 0x00080000UL
|
#define CHR_FILE__EXECMOD 0x00080000UL
|
||||||
|
#define CHR_FILE__OPEN 0x00100000UL
|
||||||
#define BLK_FILE__IOCTL 0x00000001UL
|
#define BLK_FILE__IOCTL 0x00000001UL
|
||||||
#define BLK_FILE__READ 0x00000002UL
|
#define BLK_FILE__READ 0x00000002UL
|
||||||
#define BLK_FILE__WRITE 0x00000004UL
|
#define BLK_FILE__WRITE 0x00000004UL
|
||||||
@ -153,6 +156,7 @@
|
|||||||
#define BLK_FILE__SWAPON 0x00004000UL
|
#define BLK_FILE__SWAPON 0x00004000UL
|
||||||
#define BLK_FILE__QUOTAON 0x00008000UL
|
#define BLK_FILE__QUOTAON 0x00008000UL
|
||||||
#define BLK_FILE__MOUNTON 0x00010000UL
|
#define BLK_FILE__MOUNTON 0x00010000UL
|
||||||
|
#define BLK_FILE__OPEN 0x00020000UL
|
||||||
#define SOCK_FILE__IOCTL 0x00000001UL
|
#define SOCK_FILE__IOCTL 0x00000001UL
|
||||||
#define SOCK_FILE__READ 0x00000002UL
|
#define SOCK_FILE__READ 0x00000002UL
|
||||||
#define SOCK_FILE__WRITE 0x00000004UL
|
#define SOCK_FILE__WRITE 0x00000004UL
|
||||||
@ -187,6 +191,7 @@
|
|||||||
#define FIFO_FILE__SWAPON 0x00004000UL
|
#define FIFO_FILE__SWAPON 0x00004000UL
|
||||||
#define FIFO_FILE__QUOTAON 0x00008000UL
|
#define FIFO_FILE__QUOTAON 0x00008000UL
|
||||||
#define FIFO_FILE__MOUNTON 0x00010000UL
|
#define FIFO_FILE__MOUNTON 0x00010000UL
|
||||||
|
#define FIFO_FILE__OPEN 0x00020000UL
|
||||||
#define FD__USE 0x00000001UL
|
#define FD__USE 0x00000001UL
|
||||||
#define SOCKET__IOCTL 0x00000001UL
|
#define SOCKET__IOCTL 0x00000001UL
|
||||||
#define SOCKET__READ 0x00000002UL
|
#define SOCKET__READ 0x00000002UL
|
||||||
|
@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void);
|
|||||||
|
|
||||||
void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
|
void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
|
||||||
int family);
|
int family);
|
||||||
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
|
|
||||||
int family);
|
|
||||||
void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
|
|
||||||
struct sk_security_struct *newssec);
|
|
||||||
|
|
||||||
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
||||||
u16 family,
|
u16 family,
|
||||||
@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset(
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static inline void selinux_netlbl_sk_security_init(
|
|
||||||
struct sk_security_struct *ssec,
|
|
||||||
int family)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static inline void selinux_netlbl_sk_security_clone(
|
|
||||||
struct sk_security_struct *ssec,
|
|
||||||
struct sk_security_struct *newssec)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
|
||||||
u16 family,
|
u16 family,
|
||||||
|
31
security/selinux/include/netport.h
Normal file
31
security/selinux/include/netport.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Network port table
|
||||||
|
*
|
||||||
|
* SELinux must keep a mapping of network ports to labels/SIDs. This
|
||||||
|
* mapping is maintained as part of the normal policy but a fast cache is
|
||||||
|
* needed to reduce the lookup overhead.
|
||||||
|
*
|
||||||
|
* Author: Paul Moore <paul.moore@hp.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) Copyright Hewlett-Packard Development Company, L.P., 2008
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SELINUX_NETPORT_H
|
||||||
|
#define _SELINUX_NETPORT_H
|
||||||
|
|
||||||
|
int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid);
|
||||||
|
|
||||||
|
#endif
|
@ -28,14 +28,12 @@
|
|||||||
#include "avc.h"
|
#include "avc.h"
|
||||||
|
|
||||||
struct task_security_struct {
|
struct task_security_struct {
|
||||||
struct task_struct *task; /* back pointer to task object */
|
|
||||||
u32 osid; /* SID prior to last execve */
|
u32 osid; /* SID prior to last execve */
|
||||||
u32 sid; /* current SID */
|
u32 sid; /* current SID */
|
||||||
u32 exec_sid; /* exec SID */
|
u32 exec_sid; /* exec SID */
|
||||||
u32 create_sid; /* fscreate SID */
|
u32 create_sid; /* fscreate SID */
|
||||||
u32 keycreate_sid; /* keycreate SID */
|
u32 keycreate_sid; /* keycreate SID */
|
||||||
u32 sockcreate_sid; /* fscreate SID */
|
u32 sockcreate_sid; /* fscreate SID */
|
||||||
u32 ptrace_sid; /* SID of ptrace parent */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct inode_security_struct {
|
struct inode_security_struct {
|
||||||
@ -50,7 +48,6 @@ struct inode_security_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct file_security_struct {
|
struct file_security_struct {
|
||||||
struct file *file; /* back pointer to file object */
|
|
||||||
u32 sid; /* SID of open file description */
|
u32 sid; /* SID of open file description */
|
||||||
u32 fown_sid; /* SID of file owner (for SIGIO) */
|
u32 fown_sid; /* SID of file owner (for SIGIO) */
|
||||||
u32 isid; /* SID of inode at the time of file open */
|
u32 isid; /* SID of inode at the time of file open */
|
||||||
@ -73,18 +70,15 @@ struct superblock_security_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct msg_security_struct {
|
struct msg_security_struct {
|
||||||
struct msg_msg *msg; /* back pointer */
|
|
||||||
u32 sid; /* SID of message */
|
u32 sid; /* SID of message */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipc_security_struct {
|
struct ipc_security_struct {
|
||||||
struct kern_ipc_perm *ipc_perm; /* back pointer */
|
|
||||||
u16 sclass; /* security class of this object */
|
u16 sclass; /* security class of this object */
|
||||||
u32 sid; /* SID of IPC resource */
|
u32 sid; /* SID of IPC resource */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bprm_security_struct {
|
struct bprm_security_struct {
|
||||||
struct linux_binprm *bprm; /* back pointer to bprm object */
|
|
||||||
u32 sid; /* SID for transformed process */
|
u32 sid; /* SID for transformed process */
|
||||||
unsigned char set;
|
unsigned char set;
|
||||||
|
|
||||||
@ -109,8 +103,13 @@ struct netnode_security_struct {
|
|||||||
u16 family; /* address family */
|
u16 family; /* address family */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct netport_security_struct {
|
||||||
|
u32 sid; /* SID for this node */
|
||||||
|
u16 port; /* port number */
|
||||||
|
u8 protocol; /* transport protocol */
|
||||||
|
};
|
||||||
|
|
||||||
struct sk_security_struct {
|
struct sk_security_struct {
|
||||||
struct sock *sk; /* back pointer to sk object */
|
|
||||||
u32 sid; /* SID of this object */
|
u32 sid; /* SID of this object */
|
||||||
u32 peer_sid; /* SID of peer */
|
u32 peer_sid; /* SID of peer */
|
||||||
u16 sclass; /* sock security class */
|
u16 sclass; /* sock security class */
|
||||||
@ -120,12 +119,10 @@ struct sk_security_struct {
|
|||||||
NLBL_REQUIRE,
|
NLBL_REQUIRE,
|
||||||
NLBL_LABELED,
|
NLBL_LABELED,
|
||||||
} nlbl_state;
|
} nlbl_state;
|
||||||
spinlock_t nlbl_lock; /* protects nlbl_state */
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct key_security_struct {
|
struct key_security_struct {
|
||||||
struct key *obj; /* back pointer */
|
|
||||||
u32 sid; /* SID of key */
|
u32 sid; /* SID of key */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,13 +26,14 @@
|
|||||||
#define POLICYDB_VERSION_AVTAB 20
|
#define POLICYDB_VERSION_AVTAB 20
|
||||||
#define POLICYDB_VERSION_RANGETRANS 21
|
#define POLICYDB_VERSION_RANGETRANS 21
|
||||||
#define POLICYDB_VERSION_POLCAP 22
|
#define POLICYDB_VERSION_POLCAP 22
|
||||||
|
#define POLICYDB_VERSION_PERMISSIVE 23
|
||||||
|
|
||||||
/* Range of policy versions we understand*/
|
/* Range of policy versions we understand*/
|
||||||
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
|
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
|
||||||
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
||||||
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
|
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
|
||||||
#else
|
#else
|
||||||
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
|
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CONTEXT_MNT 0x01
|
#define CONTEXT_MNT 0x01
|
||||||
@ -40,6 +41,11 @@
|
|||||||
#define ROOTCONTEXT_MNT 0x04
|
#define ROOTCONTEXT_MNT 0x04
|
||||||
#define DEFCONTEXT_MNT 0x08
|
#define DEFCONTEXT_MNT 0x08
|
||||||
|
|
||||||
|
#define CONTEXT_STR "context="
|
||||||
|
#define FSCONTEXT_STR "fscontext="
|
||||||
|
#define ROOTCONTEXT_STR "rootcontext="
|
||||||
|
#define DEFCONTEXT_STR "defcontext="
|
||||||
|
|
||||||
struct netlbl_lsm_secattr;
|
struct netlbl_lsm_secattr;
|
||||||
|
|
||||||
extern int selinux_enabled;
|
extern int selinux_enabled;
|
||||||
@ -48,11 +54,13 @@ extern int selinux_mls_enabled;
|
|||||||
/* Policy capabilities */
|
/* Policy capabilities */
|
||||||
enum {
|
enum {
|
||||||
POLICYDB_CAPABILITY_NETPEER,
|
POLICYDB_CAPABILITY_NETPEER,
|
||||||
|
POLICYDB_CAPABILITY_OPENPERM,
|
||||||
__POLICYDB_CAPABILITY_MAX
|
__POLICYDB_CAPABILITY_MAX
|
||||||
};
|
};
|
||||||
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
|
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
|
||||||
|
|
||||||
extern int selinux_policycap_netpeer;
|
extern int selinux_policycap_netpeer;
|
||||||
|
extern int selinux_policycap_openperm;
|
||||||
|
|
||||||
int security_load_policy(void * data, size_t len);
|
int security_load_policy(void * data, size_t len);
|
||||||
|
|
||||||
@ -67,6 +75,8 @@ struct av_decision {
|
|||||||
u32 seqno;
|
u32 seqno;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int security_permissive_sid(u32 sid);
|
||||||
|
|
||||||
int security_compute_av(u32 ssid, u32 tsid,
|
int security_compute_av(u32 ssid, u32 tsid,
|
||||||
u16 tclass, u32 requested,
|
u16 tclass, u32 requested,
|
||||||
struct av_decision *avd);
|
struct av_decision *avd);
|
||||||
@ -92,8 +102,7 @@ int security_context_to_sid_default(char *scontext, u32 scontext_len,
|
|||||||
int security_get_user_sids(u32 callsid, char *username,
|
int security_get_user_sids(u32 callsid, char *username,
|
||||||
u32 **sids, u32 *nel);
|
u32 **sids, u32 *nel);
|
||||||
|
|
||||||
int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
|
int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
|
||||||
u32 *out_sid);
|
|
||||||
|
|
||||||
int security_netif_sid(char *name, u32 *if_sid);
|
int security_netif_sid(char *name, u32 *if_sid);
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "objsec.h"
|
#include "objsec.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
#include "netlabel.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* selinux_netlbl_sidlookup_cached - Cache a SID lookup
|
* selinux_netlbl_sidlookup_cached - Cache a SID lookup
|
||||||
@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
|
|||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Attempt to label a socket using the NetLabel mechanism using the given
|
* Attempt to label a socket using the NetLabel mechanism using the given
|
||||||
* SID. Returns zero values on success, negative values on failure. The
|
* SID. Returns zero values on success, negative values on failure.
|
||||||
* caller is responsibile for calling rcu_read_lock() before calling this
|
|
||||||
* this function and rcu_read_unlock() after this function returns.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
|
static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
|
||||||
@ -86,11 +85,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
|
|||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto sock_setsid_return;
|
goto sock_setsid_return;
|
||||||
rc = netlbl_sock_setattr(sk, &secattr);
|
rc = netlbl_sock_setattr(sk, &secattr);
|
||||||
if (rc == 0) {
|
if (rc == 0)
|
||||||
spin_lock_bh(&sksec->nlbl_lock);
|
|
||||||
sksec->nlbl_state = NLBL_LABELED;
|
sksec->nlbl_state = NLBL_LABELED;
|
||||||
spin_unlock_bh(&sksec->nlbl_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
sock_setsid_return:
|
sock_setsid_return:
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
@ -128,45 +124,6 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
|
|||||||
ssec->nlbl_state = NLBL_UNSET;
|
ssec->nlbl_state = NLBL_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* selinux_netlbl_sk_security_init - Setup the NetLabel fields
|
|
||||||
* @ssec: the sk_security_struct
|
|
||||||
* @family: the socket family
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Called when a new sk_security_struct is allocated to initialize the NetLabel
|
|
||||||
* fields.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
|
|
||||||
int family)
|
|
||||||
{
|
|
||||||
/* No locking needed, we are the only one who has access to ssec */
|
|
||||||
selinux_netlbl_sk_security_reset(ssec, family);
|
|
||||||
spin_lock_init(&ssec->nlbl_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* selinux_netlbl_sk_security_clone - Copy the NetLabel fields
|
|
||||||
* @ssec: the original sk_security_struct
|
|
||||||
* @newssec: the cloned sk_security_struct
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Clone the NetLabel specific sk_security_struct fields from @ssec to
|
|
||||||
* @newssec.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
|
|
||||||
struct sk_security_struct *newssec)
|
|
||||||
{
|
|
||||||
/* We don't need to take newssec->nlbl_lock because we are the only
|
|
||||||
* thread with access to newssec, but we do need to take the RCU read
|
|
||||||
* lock as other threads could have access to ssec */
|
|
||||||
rcu_read_lock();
|
|
||||||
selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
|
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
|
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
|
||||||
* @skb: the packet
|
* @skb: the packet
|
||||||
@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
|
|||||||
struct netlbl_lsm_secattr secattr;
|
struct netlbl_lsm_secattr secattr;
|
||||||
u32 nlbl_peer_sid;
|
u32 nlbl_peer_sid;
|
||||||
|
|
||||||
rcu_read_lock();
|
if (sksec->nlbl_state != NLBL_REQUIRE)
|
||||||
|
|
||||||
if (sksec->nlbl_state != NLBL_REQUIRE) {
|
|
||||||
rcu_read_unlock();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
netlbl_secattr_init(&secattr);
|
netlbl_secattr_init(&secattr);
|
||||||
if (netlbl_sock_getattr(sk, &secattr) == 0 &&
|
if (netlbl_sock_getattr(sk, &secattr) == 0 &&
|
||||||
@ -239,8 +192,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
|
|||||||
* here we will pick up the pieces in later calls to
|
* here we will pick up the pieces in later calls to
|
||||||
* selinux_netlbl_inode_permission(). */
|
* selinux_netlbl_inode_permission(). */
|
||||||
selinux_netlbl_sock_setsid(sk, sksec->sid);
|
selinux_netlbl_sock_setsid(sk, sksec->sid);
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -254,16 +205,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
|
|||||||
*/
|
*/
|
||||||
int selinux_netlbl_socket_post_create(struct socket *sock)
|
int selinux_netlbl_socket_post_create(struct socket *sock)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct sk_security_struct *sksec = sk->sk_security;
|
struct sk_security_struct *sksec = sk->sk_security;
|
||||||
|
|
||||||
rcu_read_lock();
|
if (sksec->nlbl_state != NLBL_REQUIRE)
|
||||||
if (sksec->nlbl_state == NLBL_REQUIRE)
|
return 0;
|
||||||
rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return rc;
|
return selinux_netlbl_sock_setsid(sk, sksec->sid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,21 +236,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
|
|||||||
if (!S_ISSOCK(inode->i_mode) ||
|
if (!S_ISSOCK(inode->i_mode) ||
|
||||||
((mask & (MAY_WRITE | MAY_APPEND)) == 0))
|
((mask & (MAY_WRITE | MAY_APPEND)) == 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sock = SOCKET_I(inode);
|
sock = SOCKET_I(inode);
|
||||||
sk = sock->sk;
|
sk = sock->sk;
|
||||||
sksec = sk->sk_security;
|
sksec = sk->sk_security;
|
||||||
|
if (sksec->nlbl_state != NLBL_REQUIRE)
|
||||||
rcu_read_lock();
|
|
||||||
if (sksec->nlbl_state != NLBL_REQUIRE) {
|
|
||||||
rcu_read_unlock();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
bh_lock_sock_nested(sk);
|
bh_lock_sock_nested(sk);
|
||||||
rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
|
if (likely(sksec->nlbl_state == NLBL_REQUIRE))
|
||||||
|
rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
|
||||||
|
else
|
||||||
|
rc = 0;
|
||||||
bh_unlock_sock(sk);
|
bh_unlock_sock(sk);
|
||||||
local_bh_enable();
|
local_bh_enable();
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
|
|||||||
struct sk_security_struct *sksec = sk->sk_security;
|
struct sk_security_struct *sksec = sk->sk_security;
|
||||||
struct netlbl_lsm_secattr secattr;
|
struct netlbl_lsm_secattr secattr;
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
|
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
|
||||||
sksec->nlbl_state == NLBL_LABELED) {
|
sksec->nlbl_state == NLBL_LABELED) {
|
||||||
netlbl_secattr_init(&secattr);
|
netlbl_secattr_init(&secattr);
|
||||||
@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
|
|||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ out:
|
|||||||
nlmsg_failure:
|
nlmsg_failure:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
oom:
|
oom:
|
||||||
printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__);
|
printk(KERN_ERR "SELinux: OOM in %s\n", __func__);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
286
security/selinux/netport.c
Normal file
286
security/selinux/netport.c
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* Network port table
|
||||||
|
*
|
||||||
|
* SELinux must keep a mapping of network ports to labels/SIDs. This
|
||||||
|
* mapping is maintained as part of the normal policy but a fast cache is
|
||||||
|
* needed to reduce the lookup overhead.
|
||||||
|
*
|
||||||
|
* Author: Paul Moore <paul.moore@hp.com>
|
||||||
|
*
|
||||||
|
* This code is heavily based on the "netif" concept originally developed by
|
||||||
|
* James Morris <jmorris@redhat.com>
|
||||||
|
* (see security/selinux/netif.c for more information)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) Copyright Hewlett-Packard Development Company, L.P., 2008
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of version 2 of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/rcupdate.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/in.h>
|
||||||
|
#include <linux/in6.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/ipv6.h>
|
||||||
|
#include <net/ip.h>
|
||||||
|
#include <net/ipv6.h>
|
||||||
|
#include <asm/bug.h>
|
||||||
|
|
||||||
|
#include "netport.h"
|
||||||
|
#include "objsec.h"
|
||||||
|
|
||||||
|
#define SEL_NETPORT_HASH_SIZE 256
|
||||||
|
#define SEL_NETPORT_HASH_BKT_LIMIT 16
|
||||||
|
|
||||||
|
struct sel_netport_bkt {
|
||||||
|
int size;
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sel_netport {
|
||||||
|
struct netport_security_struct psec;
|
||||||
|
|
||||||
|
struct list_head list;
|
||||||
|
struct rcu_head rcu;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason
|
||||||
|
* for this is that I suspect most users will not make heavy use of both
|
||||||
|
* address families at the same time so one table will usually end up wasted,
|
||||||
|
* if this becomes a problem we can always add a hash table for each address
|
||||||
|
* family later */
|
||||||
|
|
||||||
|
static LIST_HEAD(sel_netport_list);
|
||||||
|
static DEFINE_SPINLOCK(sel_netport_lock);
|
||||||
|
static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sel_netport_free - Frees a port entry
|
||||||
|
* @p: the entry's RCU field
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function is designed to be used as a callback to the call_rcu()
|
||||||
|
* function so that memory allocated to a hash table port entry can be
|
||||||
|
* released safely.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void sel_netport_free(struct rcu_head *p)
|
||||||
|
{
|
||||||
|
struct sel_netport *port = container_of(p, struct sel_netport, rcu);
|
||||||
|
kfree(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sel_netport_hashfn - Hashing function for the port table
|
||||||
|
* @pnum: port number
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This is the hashing function for the port table, it returns the bucket
|
||||||
|
* number for the given port.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static unsigned int sel_netport_hashfn(u16 pnum)
|
||||||
|
{
|
||||||
|
return (pnum & (SEL_NETPORT_HASH_SIZE - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sel_netport_find - Search for a port record
|
||||||
|
* @protocol: protocol
|
||||||
|
* @port: pnum
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Search the network port table and return the matching record. If an entry
|
||||||
|
* can not be found in the table return NULL.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static struct sel_netport *sel_netport_find(u8 protocol, u16 pnum)
|
||||||
|
{
|
||||||
|
unsigned int idx;
|
||||||
|
struct sel_netport *port;
|
||||||
|
|
||||||
|
idx = sel_netport_hashfn(pnum);
|
||||||
|
list_for_each_entry_rcu(port, &sel_netport_hash[idx].list, list)
|
||||||
|
if (port->psec.port == pnum &&
|
||||||
|
port->psec.protocol == protocol)
|
||||||
|
return port;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sel_netport_insert - Insert a new port into the table
|
||||||
|
* @port: the new port record
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Add a new port record to the network address hash table. Returns zero on
|
||||||
|
* success, negative values on failure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int sel_netport_insert(struct sel_netport *port)
|
||||||
|
{
|
||||||
|
unsigned int idx;
|
||||||
|
|
||||||
|
/* we need to impose a limit on the growth of the hash table so check
|
||||||
|
* this bucket to make sure it is within the specified bounds */
|
||||||
|
idx = sel_netport_hashfn(port->psec.port);
|
||||||
|
list_add_rcu(&port->list, &sel_netport_hash[idx].list);
|
||||||
|
if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) {
|
||||||
|
struct sel_netport *tail;
|
||||||
|
tail = list_entry(port->list.prev, struct sel_netport, list);
|
||||||
|
list_del_rcu(port->list.prev);
|
||||||
|
call_rcu(&tail->rcu, sel_netport_free);
|
||||||
|
} else
|
||||||
|
sel_netport_hash[idx].size++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sel_netport_sid_slow - Lookup the SID of a network address using the policy
|
||||||
|
* @protocol: protocol
|
||||||
|
* @pnum: port
|
||||||
|
* @sid: port SID
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function determines the SID of a network port by quering the security
|
||||||
|
* policy. The result is added to the network port table to speedup future
|
||||||
|
* queries. Returns zero on success, negative values on failure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct sel_netport *port;
|
||||||
|
struct sel_netport *new = NULL;
|
||||||
|
|
||||||
|
spin_lock_bh(&sel_netport_lock);
|
||||||
|
port = sel_netport_find(protocol, pnum);
|
||||||
|
if (port != NULL) {
|
||||||
|
*sid = port->psec.sid;
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||||
|
if (new == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = security_port_sid(protocol, pnum, &new->psec.sid);
|
||||||
|
if (ret != 0)
|
||||||
|
goto out;
|
||||||
|
new->psec.port = pnum;
|
||||||
|
new->psec.protocol = protocol;
|
||||||
|
ret = sel_netport_insert(new);
|
||||||
|
if (ret != 0)
|
||||||
|
goto out;
|
||||||
|
*sid = new->psec.sid;
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock_bh(&sel_netport_lock);
|
||||||
|
if (unlikely(ret)) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"SELinux: failure in sel_netport_sid_slow(),"
|
||||||
|
" unable to determine network port label\n");
|
||||||
|
kfree(new);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sel_netport_sid - Lookup the SID of a network port
|
||||||
|
* @protocol: protocol
|
||||||
|
* @pnum: port
|
||||||
|
* @sid: port SID
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function determines the SID of a network port using the fastest method
|
||||||
|
* possible. First the port table is queried, but if an entry can't be found
|
||||||
|
* then the policy is queried and the result is added to the table to speedup
|
||||||
|
* future queries. Returns zero on success, negative values on failure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid)
|
||||||
|
{
|
||||||
|
struct sel_netport *port;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
port = sel_netport_find(protocol, pnum);
|
||||||
|
if (port != NULL) {
|
||||||
|
*sid = port->psec.sid;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return sel_netport_sid_slow(protocol, pnum, sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sel_netport_flush - Flush the entire network port table
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Remove all entries from the network address table.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void sel_netport_flush(void)
|
||||||
|
{
|
||||||
|
unsigned int idx;
|
||||||
|
struct sel_netport *port;
|
||||||
|
|
||||||
|
spin_lock_bh(&sel_netport_lock);
|
||||||
|
for (idx = 0; idx < SEL_NETPORT_HASH_SIZE; idx++) {
|
||||||
|
list_for_each_entry(port, &sel_netport_hash[idx].list, list) {
|
||||||
|
list_del_rcu(&port->list);
|
||||||
|
call_rcu(&port->rcu, sel_netport_free);
|
||||||
|
}
|
||||||
|
sel_netport_hash[idx].size = 0;
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&sel_netport_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid,
|
||||||
|
u16 class, u32 perms, u32 *retained)
|
||||||
|
{
|
||||||
|
if (event == AVC_CALLBACK_RESET) {
|
||||||
|
sel_netport_flush();
|
||||||
|
synchronize_net();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __init int sel_netport_init(void)
|
||||||
|
{
|
||||||
|
int iter;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!selinux_enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (iter = 0; iter < SEL_NETPORT_HASH_SIZE; iter++) {
|
||||||
|
INIT_LIST_HEAD(&sel_netport_hash[iter].list);
|
||||||
|
sel_netport_hash[iter].size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
|
||||||
|
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
|
||||||
|
if (ret != 0)
|
||||||
|
panic("avc_add_callback() failed, error %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
__initcall(sel_netport_init);
|
@ -42,7 +42,8 @@
|
|||||||
|
|
||||||
/* Policy capability filenames */
|
/* Policy capability filenames */
|
||||||
static char *policycap_names[] = {
|
static char *policycap_names[] = {
|
||||||
"network_peer_controls"
|
"network_peer_controls",
|
||||||
|
"open_perms"
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
|
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
|
||||||
@ -391,7 +392,7 @@ static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
|
|||||||
|
|
||||||
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
||||||
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
||||||
"max\n", __FUNCTION__, len);
|
"max\n", __func__, len);
|
||||||
length = -ERANGE;
|
length = -ERANGE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -644,7 +645,7 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
|
|||||||
|
|
||||||
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
||||||
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
||||||
"max\n", __FUNCTION__, len);
|
"max\n", __func__, len);
|
||||||
length = -ERANGE;
|
length = -ERANGE;
|
||||||
goto out3;
|
goto out3;
|
||||||
}
|
}
|
||||||
@ -821,7 +822,7 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
|
|||||||
|
|
||||||
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
||||||
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
||||||
"max\n", __FUNCTION__, len);
|
"max\n", __func__, len);
|
||||||
length = -ERANGE;
|
length = -ERANGE;
|
||||||
goto out3;
|
goto out3;
|
||||||
}
|
}
|
||||||
@ -1760,7 +1761,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
|
|||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
err:
|
err:
|
||||||
printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
|
printk(KERN_ERR "%s: failed while creating inodes\n", __func__);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,8 +280,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
|
|||||||
h->nel = 0;
|
h->nel = 0;
|
||||||
h->nslot = nslot;
|
h->nslot = nslot;
|
||||||
h->mask = mask;
|
h->mask = mask;
|
||||||
printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. "
|
printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n",
|
||||||
"Num of rules:%d\n", h->nslot, nrules);
|
h->nslot, nrules);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,18 +345,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
|||||||
if (vers < POLICYDB_VERSION_AVTAB) {
|
if (vers < POLICYDB_VERSION_AVTAB) {
|
||||||
rc = next_entry(buf32, fp, sizeof(u32));
|
rc = next_entry(buf32, fp, sizeof(u32));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: avtab: truncated entry\n");
|
printk(KERN_ERR "SELinux: avtab: truncated entry\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
items2 = le32_to_cpu(buf32[0]);
|
items2 = le32_to_cpu(buf32[0]);
|
||||||
if (items2 > ARRAY_SIZE(buf32)) {
|
if (items2 > ARRAY_SIZE(buf32)) {
|
||||||
printk(KERN_ERR "security: avtab: entry overflow\n");
|
printk(KERN_ERR "SELinux: avtab: entry overflow\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
rc = next_entry(buf32, fp, sizeof(u32)*items2);
|
rc = next_entry(buf32, fp, sizeof(u32)*items2);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: avtab: truncated entry\n");
|
printk(KERN_ERR "SELinux: avtab: truncated entry\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
items = 0;
|
items = 0;
|
||||||
@ -364,19 +364,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
|||||||
val = le32_to_cpu(buf32[items++]);
|
val = le32_to_cpu(buf32[items++]);
|
||||||
key.source_type = (u16)val;
|
key.source_type = (u16)val;
|
||||||
if (key.source_type != val) {
|
if (key.source_type != val) {
|
||||||
printk("security: avtab: truncated source type\n");
|
printk("SELinux: avtab: truncated source type\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
val = le32_to_cpu(buf32[items++]);
|
val = le32_to_cpu(buf32[items++]);
|
||||||
key.target_type = (u16)val;
|
key.target_type = (u16)val;
|
||||||
if (key.target_type != val) {
|
if (key.target_type != val) {
|
||||||
printk("security: avtab: truncated target type\n");
|
printk("SELinux: avtab: truncated target type\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
val = le32_to_cpu(buf32[items++]);
|
val = le32_to_cpu(buf32[items++]);
|
||||||
key.target_class = (u16)val;
|
key.target_class = (u16)val;
|
||||||
if (key.target_class != val) {
|
if (key.target_class != val) {
|
||||||
printk("security: avtab: truncated target class\n");
|
printk("SELinux: avtab: truncated target class\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,12 +384,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
|||||||
enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
|
enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
|
||||||
|
|
||||||
if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
|
if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
|
||||||
printk("security: avtab: null entry\n");
|
printk("SELinux: avtab: null entry\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((val & AVTAB_AV) &&
|
if ((val & AVTAB_AV) &&
|
||||||
(val & AVTAB_TYPE)) {
|
(val & AVTAB_TYPE)) {
|
||||||
printk("security: avtab: entry has both access vectors and types\n");
|
printk("SELinux: avtab: entry has both access vectors and types\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +403,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (items != items2) {
|
if (items != items2) {
|
||||||
printk("security: avtab: entry only had %d items, expected %d\n", items2, items);
|
printk("SELinux: avtab: entry only had %d items, expected %d\n", items2, items);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -411,7 +411,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
|||||||
|
|
||||||
rc = next_entry(buf16, fp, sizeof(u16)*4);
|
rc = next_entry(buf16, fp, sizeof(u16)*4);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk("security: avtab: truncated entry\n");
|
printk("SELinux: avtab: truncated entry\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
|||||||
if (!policydb_type_isvalid(pol, key.source_type) ||
|
if (!policydb_type_isvalid(pol, key.source_type) ||
|
||||||
!policydb_type_isvalid(pol, key.target_type) ||
|
!policydb_type_isvalid(pol, key.target_type) ||
|
||||||
!policydb_class_isvalid(pol, key.target_class)) {
|
!policydb_class_isvalid(pol, key.target_class)) {
|
||||||
printk(KERN_WARNING "security: avtab: invalid type or class\n");
|
printk(KERN_WARNING "SELinux: avtab: invalid type or class\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,19 +435,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
|||||||
}
|
}
|
||||||
if (!set || set > 1) {
|
if (!set || set > 1) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"security: avtab: more than one specifier\n");
|
"SELinux: avtab: more than one specifier\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = next_entry(buf32, fp, sizeof(u32));
|
rc = next_entry(buf32, fp, sizeof(u32));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk("security: avtab: truncated entry\n");
|
printk("SELinux: avtab: truncated entry\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
datum.data = le32_to_cpu(*buf32);
|
datum.data = le32_to_cpu(*buf32);
|
||||||
if ((key.specified & AVTAB_TYPE) &&
|
if ((key.specified & AVTAB_TYPE) &&
|
||||||
!policydb_type_isvalid(pol, datum.data)) {
|
!policydb_type_isvalid(pol, datum.data)) {
|
||||||
printk(KERN_WARNING "security: avtab: invalid type\n");
|
printk(KERN_WARNING "SELinux: avtab: invalid type\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return insertf(a, &key, &datum, p);
|
return insertf(a, &key, &datum, p);
|
||||||
@ -468,12 +468,12 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
|
|||||||
|
|
||||||
rc = next_entry(buf, fp, sizeof(u32));
|
rc = next_entry(buf, fp, sizeof(u32));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: avtab: truncated table\n");
|
printk(KERN_ERR "SELinux: avtab: truncated table\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
nel = le32_to_cpu(buf[0]);
|
nel = le32_to_cpu(buf[0]);
|
||||||
if (!nel) {
|
if (!nel) {
|
||||||
printk(KERN_ERR "security: avtab: table is empty\n");
|
printk(KERN_ERR "SELinux: avtab: table is empty\n");
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@ -486,9 +486,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
|
|||||||
rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
|
rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (rc == -ENOMEM)
|
if (rc == -ENOMEM)
|
||||||
printk(KERN_ERR "security: avtab: out of memory\n");
|
printk(KERN_ERR "SELinux: avtab: out of memory\n");
|
||||||
else if (rc == -EEXIST)
|
else if (rc == -EEXIST)
|
||||||
printk(KERN_ERR "security: avtab: duplicate entry\n");
|
printk(KERN_ERR "SELinux: avtab: duplicate entry\n");
|
||||||
else
|
else
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -96,7 +96,7 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
|
|||||||
if (new_state != node->cur_state) {
|
if (new_state != node->cur_state) {
|
||||||
node->cur_state = new_state;
|
node->cur_state = new_state;
|
||||||
if (new_state == -1)
|
if (new_state == -1)
|
||||||
printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
|
printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
|
||||||
/* turn the rules on or off */
|
/* turn the rules on or off */
|
||||||
for (cur = node->true_list; cur != NULL; cur = cur->next) {
|
for (cur = node->true_list; cur != NULL; cur = cur->next) {
|
||||||
if (new_state <= 0) {
|
if (new_state <= 0) {
|
||||||
@ -276,7 +276,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
|||||||
*/
|
*/
|
||||||
if (k->specified & AVTAB_TYPE) {
|
if (k->specified & AVTAB_TYPE) {
|
||||||
if (avtab_search(&p->te_avtab, k)) {
|
if (avtab_search(&p->te_avtab, k)) {
|
||||||
printk("security: type rule already exists outside of a conditional.");
|
printk("SELinux: type rule already exists outside of a conditional.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
|||||||
node_ptr = avtab_search_node(&p->te_cond_avtab, k);
|
node_ptr = avtab_search_node(&p->te_cond_avtab, k);
|
||||||
if (node_ptr) {
|
if (node_ptr) {
|
||||||
if (avtab_search_node_next(node_ptr, k->specified)) {
|
if (avtab_search_node_next(node_ptr, k->specified)) {
|
||||||
printk("security: too many conflicting type rules.");
|
printk("SELinux: too many conflicting type rules.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
found = 0;
|
found = 0;
|
||||||
@ -302,13 +302,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
printk("security: conflicting type rules.\n");
|
printk("SELinux: conflicting type rules.\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (avtab_search(&p->te_cond_avtab, k)) {
|
if (avtab_search(&p->te_cond_avtab, k)) {
|
||||||
printk("security: conflicting type rules when adding type rule for true.\n");
|
printk("SELinux: conflicting type rules when adding type rule for true.\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,7 +316,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
|||||||
|
|
||||||
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
|
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
|
||||||
if (!node_ptr) {
|
if (!node_ptr) {
|
||||||
printk("security: could not insert rule.");
|
printk("SELinux: could not insert rule.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,12 +376,12 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
|
|||||||
static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
|
static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
|
||||||
{
|
{
|
||||||
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
|
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
|
||||||
printk("security: conditional expressions uses unknown operator.\n");
|
printk("SELinux: conditional expressions uses unknown operator.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr->bool > p->p_bools.nprim) {
|
if (expr->bool > p->p_bools.nprim) {
|
||||||
printk("security: conditional expressions uses unknown bool.\n");
|
printk("SELinux: conditional expressions uses unknown bool.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -364,7 +364,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
|||||||
count = le32_to_cpu(buf[2]);
|
count = le32_to_cpu(buf[2]);
|
||||||
|
|
||||||
if (mapunit != sizeof(u64) * 8) {
|
if (mapunit != sizeof(u64) * 8) {
|
||||||
printk(KERN_ERR "security: ebitmap: map size %u does not "
|
printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
|
||||||
"match my size %Zd (high bit was %d)\n",
|
"match my size %Zd (high bit was %d)\n",
|
||||||
mapunit, sizeof(u64) * 8, e->highbit);
|
mapunit, sizeof(u64) * 8, e->highbit);
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -382,19 +382,19 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
|||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
rc = next_entry(&startbit, fp, sizeof(u32));
|
rc = next_entry(&startbit, fp, sizeof(u32));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: ebitmap: truncated map\n");
|
printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
startbit = le32_to_cpu(startbit);
|
startbit = le32_to_cpu(startbit);
|
||||||
|
|
||||||
if (startbit & (mapunit - 1)) {
|
if (startbit & (mapunit - 1)) {
|
||||||
printk(KERN_ERR "security: ebitmap start bit (%d) is "
|
printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
|
||||||
"not a multiple of the map unit size (%u)\n",
|
"not a multiple of the map unit size (%u)\n",
|
||||||
startbit, mapunit);
|
startbit, mapunit);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (startbit > e->highbit - mapunit) {
|
if (startbit > e->highbit - mapunit) {
|
||||||
printk(KERN_ERR "security: ebitmap start bit (%d) is "
|
printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
|
||||||
"beyond the end of the bitmap (%u)\n",
|
"beyond the end of the bitmap (%u)\n",
|
||||||
startbit, (e->highbit - mapunit));
|
startbit, (e->highbit - mapunit));
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -405,7 +405,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
|||||||
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: ebitmap: out of memory\n");
|
"SELinux: ebitmap: out of memory\n");
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@ -418,7 +418,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
|||||||
}
|
}
|
||||||
n = tmp;
|
n = tmp;
|
||||||
} else if (startbit <= n->startbit) {
|
} else if (startbit <= n->startbit) {
|
||||||
printk(KERN_ERR "security: ebitmap: start bit %d"
|
printk(KERN_ERR "SELinux: ebitmap: start bit %d"
|
||||||
" comes after start bit %d\n",
|
" comes after start bit %d\n",
|
||||||
startbit, n->startbit);
|
startbit, n->startbit);
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -426,7 +426,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
|||||||
|
|
||||||
rc = next_entry(&map, fp, sizeof(u64));
|
rc = next_entry(&map, fp, sizeof(u64));
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: ebitmap: truncated map\n");
|
printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
map = le64_to_cpu(map);
|
map = le64_to_cpu(map);
|
||||||
|
@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = {
|
|||||||
.version = POLICYDB_VERSION_POLCAP,
|
.version = POLICYDB_VERSION_POLCAP,
|
||||||
.sym_num = SYM_NUM,
|
.sym_num = SYM_NUM,
|
||||||
.ocon_num = OCON_NUM,
|
.ocon_num = OCON_NUM,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.version = POLICYDB_VERSION_PERMISSIVE,
|
||||||
|
.sym_num = SYM_NUM,
|
||||||
|
.ocon_num = OCON_NUM,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p)
|
|||||||
goto out_free_symtab;
|
goto out_free_symtab;
|
||||||
|
|
||||||
ebitmap_init(&p->policycaps);
|
ebitmap_init(&p->policycaps);
|
||||||
|
ebitmap_init(&p->permissive_map);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
@ -401,14 +407,14 @@ static int policydb_index_others(struct policydb *p)
|
|||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
|
|
||||||
printk(KERN_DEBUG "security: %d users, %d roles, %d types, %d bools",
|
printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
|
||||||
p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
|
p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
|
||||||
if (selinux_mls_enabled)
|
if (selinux_mls_enabled)
|
||||||
printk(", %d sens, %d cats", p->p_levels.nprim,
|
printk(", %d sens, %d cats", p->p_levels.nprim,
|
||||||
p->p_cats.nprim);
|
p->p_cats.nprim);
|
||||||
printk("\n");
|
printk("\n");
|
||||||
|
|
||||||
printk(KERN_DEBUG "security: %d classes, %d rules\n",
|
printk(KERN_DEBUG "SELinux: %d classes, %d rules\n",
|
||||||
p->p_classes.nprim, p->te_avtab.nel);
|
p->p_classes.nprim, p->te_avtab.nel);
|
||||||
|
|
||||||
#ifdef DEBUG_HASHES
|
#ifdef DEBUG_HASHES
|
||||||
@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
|
|||||||
kfree(p->type_attr_map);
|
kfree(p->type_attr_map);
|
||||||
kfree(p->undefined_perms);
|
kfree(p->undefined_perms);
|
||||||
ebitmap_destroy(&p->policycaps);
|
ebitmap_destroy(&p->policycaps);
|
||||||
|
ebitmap_destroy(&p->permissive_map);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -702,20 +709,20 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s)
|
|||||||
|
|
||||||
rc = sidtab_init(s);
|
rc = sidtab_init(s);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "security: out of memory on SID table init\n");
|
printk(KERN_ERR "SELinux: out of memory on SID table init\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
head = p->ocontexts[OCON_ISID];
|
head = p->ocontexts[OCON_ISID];
|
||||||
for (c = head; c; c = c->next) {
|
for (c = head; c; c = c->next) {
|
||||||
if (!c->context[0].user) {
|
if (!c->context[0].user) {
|
||||||
printk(KERN_ERR "security: SID %s was never "
|
printk(KERN_ERR "SELinux: SID %s was never "
|
||||||
"defined.\n", c->u.name);
|
"defined.\n", c->u.name);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (sidtab_insert(s, c->sid[0], &c->context[0])) {
|
if (sidtab_insert(s, c->sid[0], &c->context[0])) {
|
||||||
printk(KERN_ERR "security: unable to load initial "
|
printk(KERN_ERR "SELinux: unable to load initial "
|
||||||
"SID %s.\n", c->u.name);
|
"SID %s.\n", c->u.name);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
@ -809,13 +816,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
|
|||||||
|
|
||||||
items = le32_to_cpu(buf[0]);
|
items = le32_to_cpu(buf[0]);
|
||||||
if (items > ARRAY_SIZE(buf)) {
|
if (items > ARRAY_SIZE(buf)) {
|
||||||
printk(KERN_ERR "security: mls: range overflow\n");
|
printk(KERN_ERR "SELinux: mls: range overflow\n");
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
rc = next_entry(buf, fp, sizeof(u32) * items);
|
rc = next_entry(buf, fp, sizeof(u32) * items);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: mls: truncated range\n");
|
printk(KERN_ERR "SELinux: mls: truncated range\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
r->level[0].sens = le32_to_cpu(buf[0]);
|
r->level[0].sens = le32_to_cpu(buf[0]);
|
||||||
@ -826,21 +833,21 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
|
|||||||
|
|
||||||
rc = ebitmap_read(&r->level[0].cat, fp);
|
rc = ebitmap_read(&r->level[0].cat, fp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "security: mls: error reading low "
|
printk(KERN_ERR "SELinux: mls: error reading low "
|
||||||
"categories\n");
|
"categories\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (items > 1) {
|
if (items > 1) {
|
||||||
rc = ebitmap_read(&r->level[1].cat, fp);
|
rc = ebitmap_read(&r->level[1].cat, fp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "security: mls: error reading high "
|
printk(KERN_ERR "SELinux: mls: error reading high "
|
||||||
"categories\n");
|
"categories\n");
|
||||||
goto bad_high;
|
goto bad_high;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
|
rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "security: mls: out of memory\n");
|
printk(KERN_ERR "SELinux: mls: out of memory\n");
|
||||||
goto bad_high;
|
goto bad_high;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -866,7 +873,7 @@ static int context_read_and_validate(struct context *c,
|
|||||||
|
|
||||||
rc = next_entry(buf, fp, sizeof buf);
|
rc = next_entry(buf, fp, sizeof buf);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: context truncated\n");
|
printk(KERN_ERR "SELinux: context truncated\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
c->user = le32_to_cpu(buf[0]);
|
c->user = le32_to_cpu(buf[0]);
|
||||||
@ -874,7 +881,7 @@ static int context_read_and_validate(struct context *c,
|
|||||||
c->type = le32_to_cpu(buf[2]);
|
c->type = le32_to_cpu(buf[2]);
|
||||||
if (p->policyvers >= POLICYDB_VERSION_MLS) {
|
if (p->policyvers >= POLICYDB_VERSION_MLS) {
|
||||||
if (mls_read_range_helper(&c->range, fp)) {
|
if (mls_read_range_helper(&c->range, fp)) {
|
||||||
printk(KERN_ERR "security: error reading MLS range of "
|
printk(KERN_ERR "SELinux: error reading MLS range of "
|
||||||
"context\n");
|
"context\n");
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
@ -882,7 +889,7 @@ static int context_read_and_validate(struct context *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!policydb_context_isvalid(p, c)) {
|
if (!policydb_context_isvalid(p, c)) {
|
||||||
printk(KERN_ERR "security: invalid security context\n");
|
printk(KERN_ERR "SELinux: invalid security context\n");
|
||||||
context_destroy(c);
|
context_destroy(c);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1128,7 +1135,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
|
|||||||
cladatum->comdatum = hashtab_search(p->p_commons.table,
|
cladatum->comdatum = hashtab_search(p->p_commons.table,
|
||||||
cladatum->comkey);
|
cladatum->comkey);
|
||||||
if (!cladatum->comdatum) {
|
if (!cladatum->comdatum) {
|
||||||
printk(KERN_ERR "security: unknown common %s\n",
|
printk(KERN_ERR "SELinux: unknown common %s\n",
|
||||||
cladatum->comkey);
|
cladatum->comkey);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -1283,13 +1290,13 @@ static int mls_read_level(struct mls_level *lp, void *fp)
|
|||||||
|
|
||||||
rc = next_entry(buf, fp, sizeof buf);
|
rc = next_entry(buf, fp, sizeof buf);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: mls: truncated level\n");
|
printk(KERN_ERR "SELinux: mls: truncated level\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
lp->sens = le32_to_cpu(buf[0]);
|
lp->sens = le32_to_cpu(buf[0]);
|
||||||
|
|
||||||
if (ebitmap_read(&lp->cat, fp)) {
|
if (ebitmap_read(&lp->cat, fp)) {
|
||||||
printk(KERN_ERR "security: mls: error reading level "
|
printk(KERN_ERR "SELinux: mls: error reading level "
|
||||||
"categories\n");
|
"categories\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@ -1491,7 +1498,7 @@ int policydb_read(struct policydb *p, void *fp)
|
|||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
|
if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
|
||||||
printk(KERN_ERR "security: policydb magic number 0x%x does "
|
printk(KERN_ERR "SELinux: policydb magic number 0x%x does "
|
||||||
"not match expected magic number 0x%x\n",
|
"not match expected magic number 0x%x\n",
|
||||||
le32_to_cpu(buf[0]), POLICYDB_MAGIC);
|
le32_to_cpu(buf[0]), POLICYDB_MAGIC);
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -1499,27 +1506,27 @@ int policydb_read(struct policydb *p, void *fp)
|
|||||||
|
|
||||||
len = le32_to_cpu(buf[1]);
|
len = le32_to_cpu(buf[1]);
|
||||||
if (len != strlen(POLICYDB_STRING)) {
|
if (len != strlen(POLICYDB_STRING)) {
|
||||||
printk(KERN_ERR "security: policydb string length %d does not "
|
printk(KERN_ERR "SELinux: policydb string length %d does not "
|
||||||
"match expected length %Zu\n",
|
"match expected length %Zu\n",
|
||||||
len, strlen(POLICYDB_STRING));
|
len, strlen(POLICYDB_STRING));
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
policydb_str = kmalloc(len + 1,GFP_KERNEL);
|
policydb_str = kmalloc(len + 1,GFP_KERNEL);
|
||||||
if (!policydb_str) {
|
if (!policydb_str) {
|
||||||
printk(KERN_ERR "security: unable to allocate memory for policydb "
|
printk(KERN_ERR "SELinux: unable to allocate memory for policydb "
|
||||||
"string of length %d\n", len);
|
"string of length %d\n", len);
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
rc = next_entry(policydb_str, fp, len);
|
rc = next_entry(policydb_str, fp, len);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
printk(KERN_ERR "security: truncated policydb string identifier\n");
|
printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
|
||||||
kfree(policydb_str);
|
kfree(policydb_str);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
policydb_str[len] = 0;
|
policydb_str[len] = 0;
|
||||||
if (strcmp(policydb_str, POLICYDB_STRING)) {
|
if (strcmp(policydb_str, POLICYDB_STRING)) {
|
||||||
printk(KERN_ERR "security: policydb string %s does not match "
|
printk(KERN_ERR "SELinux: policydb string %s does not match "
|
||||||
"my string %s\n", policydb_str, POLICYDB_STRING);
|
"my string %s\n", policydb_str, POLICYDB_STRING);
|
||||||
kfree(policydb_str);
|
kfree(policydb_str);
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -1536,7 +1543,7 @@ int policydb_read(struct policydb *p, void *fp)
|
|||||||
p->policyvers = le32_to_cpu(buf[0]);
|
p->policyvers = le32_to_cpu(buf[0]);
|
||||||
if (p->policyvers < POLICYDB_VERSION_MIN ||
|
if (p->policyvers < POLICYDB_VERSION_MIN ||
|
||||||
p->policyvers > POLICYDB_VERSION_MAX) {
|
p->policyvers > POLICYDB_VERSION_MAX) {
|
||||||
printk(KERN_ERR "security: policydb version %d does not match "
|
printk(KERN_ERR "SELinux: policydb version %d does not match "
|
||||||
"my version range %d-%d\n",
|
"my version range %d-%d\n",
|
||||||
le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
|
le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -1570,16 +1577,20 @@ int policydb_read(struct policydb *p, void *fp)
|
|||||||
ebitmap_read(&p->policycaps, fp) != 0)
|
ebitmap_read(&p->policycaps, fp) != 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
|
if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
|
||||||
|
ebitmap_read(&p->permissive_map, fp) != 0)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
info = policydb_lookup_compat(p->policyvers);
|
info = policydb_lookup_compat(p->policyvers);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
printk(KERN_ERR "security: unable to find policy compat info "
|
printk(KERN_ERR "SELinux: unable to find policy compat info "
|
||||||
"for version %d\n", p->policyvers);
|
"for version %d\n", p->policyvers);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (le32_to_cpu(buf[2]) != info->sym_num ||
|
if (le32_to_cpu(buf[2]) != info->sym_num ||
|
||||||
le32_to_cpu(buf[3]) != info->ocon_num) {
|
le32_to_cpu(buf[3]) != info->ocon_num) {
|
||||||
printk(KERN_ERR "security: policydb table sizes (%d,%d) do "
|
printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do "
|
||||||
"not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
|
"not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
|
||||||
le32_to_cpu(buf[3]),
|
le32_to_cpu(buf[3]),
|
||||||
info->sym_num, info->ocon_num);
|
info->sym_num, info->ocon_num);
|
||||||
@ -1823,7 +1834,7 @@ int policydb_read(struct policydb *p, void *fp)
|
|||||||
for (genfs_p = NULL, genfs = p->genfs; genfs;
|
for (genfs_p = NULL, genfs = p->genfs; genfs;
|
||||||
genfs_p = genfs, genfs = genfs->next) {
|
genfs_p = genfs, genfs = genfs->next) {
|
||||||
if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
|
if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
|
||||||
printk(KERN_ERR "security: dup genfs "
|
printk(KERN_ERR "SELinux: dup genfs "
|
||||||
"fstype %s\n", newgenfs->fstype);
|
"fstype %s\n", newgenfs->fstype);
|
||||||
kfree(newgenfs->fstype);
|
kfree(newgenfs->fstype);
|
||||||
kfree(newgenfs);
|
kfree(newgenfs);
|
||||||
@ -1873,7 +1884,7 @@ int policydb_read(struct policydb *p, void *fp)
|
|||||||
if (!strcmp(newc->u.name, c->u.name) &&
|
if (!strcmp(newc->u.name, c->u.name) &&
|
||||||
(!c->v.sclass || !newc->v.sclass ||
|
(!c->v.sclass || !newc->v.sclass ||
|
||||||
newc->v.sclass == c->v.sclass)) {
|
newc->v.sclass == c->v.sclass)) {
|
||||||
printk(KERN_ERR "security: dup genfs "
|
printk(KERN_ERR "SELinux: dup genfs "
|
||||||
"entry (%s,%s)\n",
|
"entry (%s,%s)\n",
|
||||||
newgenfs->fstype, c->u.name);
|
newgenfs->fstype, c->u.name);
|
||||||
goto bad_newc;
|
goto bad_newc;
|
||||||
@ -1931,7 +1942,7 @@ int policydb_read(struct policydb *p, void *fp)
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto bad;
|
goto bad;
|
||||||
if (!mls_range_isvalid(p, &rt->target_range)) {
|
if (!mls_range_isvalid(p, &rt->target_range)) {
|
||||||
printk(KERN_WARNING "security: rangetrans: invalid range\n");
|
printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
lrt = rt;
|
lrt = rt;
|
||||||
|
@ -243,6 +243,8 @@ struct policydb {
|
|||||||
|
|
||||||
struct ebitmap policycaps;
|
struct ebitmap policycaps;
|
||||||
|
|
||||||
|
struct ebitmap permissive_map;
|
||||||
|
|
||||||
unsigned int policyvers;
|
unsigned int policyvers;
|
||||||
|
|
||||||
unsigned int reject_unknown : 1;
|
unsigned int reject_unknown : 1;
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/selinux.h>
|
||||||
#include <net/netlabel.h>
|
#include <net/netlabel.h>
|
||||||
|
|
||||||
#include "flask.h"
|
#include "flask.h"
|
||||||
@ -61,6 +62,7 @@ extern void selnl_notify_policyload(u32 seqno);
|
|||||||
unsigned int policydb_loaded_version;
|
unsigned int policydb_loaded_version;
|
||||||
|
|
||||||
int selinux_policycap_netpeer;
|
int selinux_policycap_netpeer;
|
||||||
|
int selinux_policycap_openperm;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is declared in avc.c
|
* This is declared in avc.c
|
||||||
@ -412,10 +414,35 @@ static int context_struct_compute_av(struct context *scontext,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inval_class:
|
inval_class:
|
||||||
printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass);
|
printk(KERN_ERR "%s: unrecognized class %d\n", __func__, tclass);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a sid find if the type has the permissive flag set
|
||||||
|
*/
|
||||||
|
int security_permissive_sid(u32 sid)
|
||||||
|
{
|
||||||
|
struct context *context;
|
||||||
|
u32 type;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
POLICY_RDLOCK;
|
||||||
|
|
||||||
|
context = sidtab_search(&sidtab, sid);
|
||||||
|
BUG_ON(!context);
|
||||||
|
|
||||||
|
type = context->type;
|
||||||
|
/*
|
||||||
|
* we are intentionally using type here, not type-1, the 0th bit may
|
||||||
|
* someday indicate that we are globally setting permissive in policy.
|
||||||
|
*/
|
||||||
|
rc = ebitmap_get_bit(&policydb.permissive_map, type);
|
||||||
|
|
||||||
|
POLICY_RDUNLOCK;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int security_validtrans_handle_fail(struct context *ocontext,
|
static int security_validtrans_handle_fail(struct context *ocontext,
|
||||||
struct context *ncontext,
|
struct context *ncontext,
|
||||||
struct context *tcontext,
|
struct context *tcontext,
|
||||||
@ -1096,7 +1123,7 @@ static int validate_classes(struct policydb *p)
|
|||||||
continue;
|
continue;
|
||||||
if (i > p->p_classes.nprim) {
|
if (i > p->p_classes.nprim) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"security: class %s not defined in policy\n",
|
"SELinux: class %s not defined in policy\n",
|
||||||
def_class);
|
def_class);
|
||||||
if (p->reject_unknown)
|
if (p->reject_unknown)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1107,7 +1134,7 @@ static int validate_classes(struct policydb *p)
|
|||||||
pol_class = p->p_class_val_to_name[i-1];
|
pol_class = p->p_class_val_to_name[i-1];
|
||||||
if (strcmp(pol_class, def_class)) {
|
if (strcmp(pol_class, def_class)) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: class %d is incorrect, found %s but should be %s\n",
|
"SELinux: class %d is incorrect, found %s but should be %s\n",
|
||||||
i, pol_class, def_class);
|
i, pol_class, def_class);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1125,7 +1152,7 @@ static int validate_classes(struct policydb *p)
|
|||||||
nprim = 1 << (perms->nprim - 1);
|
nprim = 1 << (perms->nprim - 1);
|
||||||
if (perm_val > nprim) {
|
if (perm_val > nprim) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"security: permission %s in class %s not defined in policy\n",
|
"SELinux: permission %s in class %s not defined in policy\n",
|
||||||
def_perm, pol_class);
|
def_perm, pol_class);
|
||||||
if (p->reject_unknown)
|
if (p->reject_unknown)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1136,14 +1163,14 @@ static int validate_classes(struct policydb *p)
|
|||||||
perdatum = hashtab_search(perms->table, def_perm);
|
perdatum = hashtab_search(perms->table, def_perm);
|
||||||
if (perdatum == NULL) {
|
if (perdatum == NULL) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: permission %s in class %s not found in policy, bad policy\n",
|
"SELinux: permission %s in class %s not found in policy, bad policy\n",
|
||||||
def_perm, pol_class);
|
def_perm, pol_class);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
pol_val = 1 << (perdatum->value - 1);
|
pol_val = 1 << (perdatum->value - 1);
|
||||||
if (pol_val != perm_val) {
|
if (pol_val != perm_val) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: permission %s in class %s has incorrect value\n",
|
"SELinux: permission %s in class %s has incorrect value\n",
|
||||||
def_perm, pol_class);
|
def_perm, pol_class);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1157,7 +1184,7 @@ static int validate_classes(struct policydb *p)
|
|||||||
BUG_ON(!cladatum);
|
BUG_ON(!cladatum);
|
||||||
if (!cladatum->comdatum) {
|
if (!cladatum->comdatum) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: class %s should have an inherits clause but does not\n",
|
"SELinux: class %s should have an inherits clause but does not\n",
|
||||||
pol_class);
|
pol_class);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1172,7 +1199,7 @@ static int validate_classes(struct policydb *p)
|
|||||||
def_perm = kdefs->av_inherit[i].common_pts[j];
|
def_perm = kdefs->av_inherit[i].common_pts[j];
|
||||||
if (j >= perms->nprim) {
|
if (j >= perms->nprim) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"security: permission %s in class %s not defined in policy\n",
|
"SELinux: permission %s in class %s not defined in policy\n",
|
||||||
def_perm, pol_class);
|
def_perm, pol_class);
|
||||||
if (p->reject_unknown)
|
if (p->reject_unknown)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1183,13 +1210,13 @@ static int validate_classes(struct policydb *p)
|
|||||||
perdatum = hashtab_search(perms->table, def_perm);
|
perdatum = hashtab_search(perms->table, def_perm);
|
||||||
if (perdatum == NULL) {
|
if (perdatum == NULL) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: permission %s in class %s not found in policy, bad policy\n",
|
"SELinux: permission %s in class %s not found in policy, bad policy\n",
|
||||||
def_perm, pol_class);
|
def_perm, pol_class);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (perdatum->value != j + 1) {
|
if (perdatum->value != j + 1) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: permission %s in class %s has incorrect value\n",
|
"SELinux: permission %s in class %s has incorrect value\n",
|
||||||
def_perm, pol_class);
|
def_perm, pol_class);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1219,7 +1246,7 @@ static inline int convert_context_handle_invalid_context(struct context *context
|
|||||||
u32 len;
|
u32 len;
|
||||||
|
|
||||||
context_struct_to_string(context, &s, &len);
|
context_struct_to_string(context, &s, &len);
|
||||||
printk(KERN_ERR "security: context %s is invalid\n", s);
|
printk(KERN_ERR "SELinux: context %s is invalid\n", s);
|
||||||
kfree(s);
|
kfree(s);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@ -1299,7 +1326,7 @@ out:
|
|||||||
bad:
|
bad:
|
||||||
context_struct_to_string(&oldc, &s, &len);
|
context_struct_to_string(&oldc, &s, &len);
|
||||||
context_destroy(&oldc);
|
context_destroy(&oldc);
|
||||||
printk(KERN_ERR "security: invalidating context %s\n", s);
|
printk(KERN_ERR "SELinux: invalidating context %s\n", s);
|
||||||
kfree(s);
|
kfree(s);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1308,6 +1335,8 @@ static void security_load_policycaps(void)
|
|||||||
{
|
{
|
||||||
selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
|
selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
|
||||||
POLICYDB_CAPABILITY_NETPEER);
|
POLICYDB_CAPABILITY_NETPEER);
|
||||||
|
selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
|
||||||
|
POLICYDB_CAPABILITY_OPENPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void selinux_complete_init(void);
|
extern void selinux_complete_init(void);
|
||||||
@ -1350,7 +1379,7 @@ int security_load_policy(void *data, size_t len)
|
|||||||
/* Verify that the kernel defined classes are correct. */
|
/* Verify that the kernel defined classes are correct. */
|
||||||
if (validate_classes(&policydb)) {
|
if (validate_classes(&policydb)) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: the definition of a class is incorrect\n");
|
"SELinux: the definition of a class is incorrect\n");
|
||||||
LOAD_UNLOCK;
|
LOAD_UNLOCK;
|
||||||
sidtab_destroy(&sidtab);
|
sidtab_destroy(&sidtab);
|
||||||
policydb_destroy(&policydb);
|
policydb_destroy(&policydb);
|
||||||
@ -1384,14 +1413,14 @@ int security_load_policy(void *data, size_t len)
|
|||||||
/* Verify that the kernel defined classes are correct. */
|
/* Verify that the kernel defined classes are correct. */
|
||||||
if (validate_classes(&newpolicydb)) {
|
if (validate_classes(&newpolicydb)) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"security: the definition of a class is incorrect\n");
|
"SELinux: the definition of a class is incorrect\n");
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = security_preserve_bools(&newpolicydb);
|
rc = security_preserve_bools(&newpolicydb);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printk(KERN_ERR "security: unable to preserve booleans\n");
|
printk(KERN_ERR "SELinux: unable to preserve booleans\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1443,17 +1472,11 @@ err:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* security_port_sid - Obtain the SID for a port.
|
* security_port_sid - Obtain the SID for a port.
|
||||||
* @domain: communication domain aka address family
|
|
||||||
* @type: socket type
|
|
||||||
* @protocol: protocol number
|
* @protocol: protocol number
|
||||||
* @port: port number
|
* @port: port number
|
||||||
* @out_sid: security identifier
|
* @out_sid: security identifier
|
||||||
*/
|
*/
|
||||||
int security_port_sid(u16 domain,
|
int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
|
||||||
u16 type,
|
|
||||||
u8 protocol,
|
|
||||||
u16 port,
|
|
||||||
u32 *out_sid)
|
|
||||||
{
|
{
|
||||||
struct ocontext *c;
|
struct ocontext *c;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -2203,7 +2226,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
|
|||||||
match = hashtab_search(policydb.p_classes.table, class);
|
match = hashtab_search(policydb.p_classes.table, class);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
printk(KERN_ERR "%s: unrecognized class %s\n",
|
printk(KERN_ERR "%s: unrecognized class %s\n",
|
||||||
__FUNCTION__, class);
|
__func__, class);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user