mirror of
https://github.com/torvalds/linux.git
synced 2024-12-18 17:12:55 +00:00
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
|
||||
can help reduce the impact of kernel NULL pointer bugs.
|
||||
|
||||
For most users with lots of address space a value of 65536 is
|
||||
reasonable and should cause no problems. Programs which use vm86
|
||||
functionality would either need additional permissions from either
|
||||
the LSM or the capabilities module or have this protection disabled.
|
||||
For most ia64, ppc64 and x86 users with lots of address space
|
||||
a value of 65536 is reasonable and should cause no problems.
|
||||
On arm and other archs it should not be higher than 32768.
|
||||
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
|
||||
/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);
|
||||
if (rc)
|
||||
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
|
||||
__FUNCTION__, rc, bprm->filename);
|
||||
__func__, rc, bprm->filename);
|
||||
|
||||
out:
|
||||
dput(dentry);
|
||||
@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
|
||||
ret = get_file_caps(bprm);
|
||||
if (ret)
|
||||
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
|
||||
* executables under compatibility mode, we raise all three
|
||||
|
@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...)
|
||||
|
||||
#ifdef __KDEBUG
|
||||
#define kenter(FMT, ...) \
|
||||
printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
|
||||
printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
|
||||
#define kleave(FMT, ...) \
|
||||
printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
|
||||
printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
|
||||
#define kdebug(FMT, ...) \
|
||||
printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#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, ...) \
|
||||
no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
|
||||
no_printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
|
||||
#define kdebug(FMT, ...) \
|
||||
no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
|
||||
#endif
|
||||
|
@ -49,7 +49,7 @@ module_param(debug, bool, 0600);
|
||||
do { \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG "%s: %s: " fmt , \
|
||||
MY_NAME , __FUNCTION__ , \
|
||||
MY_NAME , __func__ , \
|
||||
## arg); \
|
||||
} while (0)
|
||||
|
||||
|
@ -57,7 +57,7 @@ int __init security_init(void)
|
||||
|
||||
if (verify(&dummy_security_ops)) {
|
||||
printk(KERN_ERR "%s could not verify "
|
||||
"dummy_security_ops structure.\n", __FUNCTION__);
|
||||
"dummy_security_ops structure.\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ int register_security(struct security_operations *ops)
|
||||
{
|
||||
if (verify(ops)) {
|
||||
printk(KERN_DEBUG "%s could not verify "
|
||||
"security_operations structure.\n", __FUNCTION__);
|
||||
"security_operations structure.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -110,13 +110,13 @@ int mod_reg_security(const char *name, struct security_operations *ops)
|
||||
{
|
||||
if (verify(ops)) {
|
||||
printk(KERN_INFO "%s could not verify "
|
||||
"security operations.\n", __FUNCTION__);
|
||||
"security operations.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ops == security_ops) {
|
||||
printk(KERN_INFO "%s security operations "
|
||||
"already registered.\n", __FUNCTION__);
|
||||
"already registered.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
||||
config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
|
||||
int "NSA SELinux maximum supported policy format version value"
|
||||
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
||||
range 15 22
|
||||
range 15 23
|
||||
default 19
|
||||
help
|
||||
This option sets the value for the maximum policy format version
|
||||
|
@ -11,6 +11,7 @@ selinux-y := avc.o \
|
||||
nlmsgtab.o \
|
||||
netif.o \
|
||||
netnode.o \
|
||||
netport.o \
|
||||
exports.o
|
||||
|
||||
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
|
||||
|
@ -871,6 +871,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
||||
int rc = 0;
|
||||
u32 denied;
|
||||
|
||||
BUG_ON(!requested);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
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);
|
||||
|
||||
if (!requested || denied) {
|
||||
if (selinux_enforcing || (flags & AVC_STRICT))
|
||||
if (denied) {
|
||||
if (flags & AVC_STRICT)
|
||||
rc = -EACCES;
|
||||
else if (!selinux_enforcing || security_permissive_sid(ssid))
|
||||
avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
|
||||
tsid, tclass);
|
||||
else
|
||||
if (node)
|
||||
avc_update_node(AVC_CALLBACK_GRANT,requested,
|
||||
ssid,tsid,tclass);
|
||||
rc = -EACCES;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
@ -80,6 +80,7 @@
|
||||
#include "objsec.h"
|
||||
#include "netif.h"
|
||||
#include "netnode.h"
|
||||
#include "netport.h"
|
||||
#include "xfrm.h"
|
||||
#include "netlabel.h"
|
||||
|
||||
@ -161,8 +162,7 @@ static int task_alloc_security(struct task_struct *task)
|
||||
if (!tsec)
|
||||
return -ENOMEM;
|
||||
|
||||
tsec->task = task;
|
||||
tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
|
||||
tsec->osid = tsec->sid = SECINITSID_UNLABELED;
|
||||
task->security = tsec;
|
||||
|
||||
return 0;
|
||||
@ -218,7 +218,6 @@ static int file_alloc_security(struct file *file)
|
||||
if (!fsec)
|
||||
return -ENOMEM;
|
||||
|
||||
fsec->file = file;
|
||||
fsec->sid = tsec->sid;
|
||||
fsec->fown_sid = tsec->sid;
|
||||
file->f_security = fsec;
|
||||
@ -275,12 +274,11 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
|
||||
if (!ssec)
|
||||
return -ENOMEM;
|
||||
|
||||
ssec->sk = sk;
|
||||
ssec->peer_sid = SECINITSID_UNLABELED;
|
||||
ssec->sid = SECINITSID_UNLABELED;
|
||||
sk->sk_security = ssec;
|
||||
|
||||
selinux_netlbl_sk_security_init(ssec, family);
|
||||
selinux_netlbl_sk_security_reset(ssec, family);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -324,10 +322,10 @@ enum {
|
||||
};
|
||||
|
||||
static match_table_t tokens = {
|
||||
{Opt_context, "context=%s"},
|
||||
{Opt_fscontext, "fscontext=%s"},
|
||||
{Opt_defcontext, "defcontext=%s"},
|
||||
{Opt_rootcontext, "rootcontext=%s"},
|
||||
{Opt_context, CONTEXT_STR "%s"},
|
||||
{Opt_fscontext, FSCONTEXT_STR "%s"},
|
||||
{Opt_defcontext, DEFCONTEXT_STR "%s"},
|
||||
{Opt_rootcontext, ROOTCONTEXT_STR "%s"},
|
||||
{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);
|
||||
if (rc) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1137,7 +1135,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
||||
}
|
||||
if (!dentry) {
|
||||
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);
|
||||
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 != -ENODATA) {
|
||||
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);
|
||||
kfree(context);
|
||||
goto out_unlock;
|
||||
@ -1190,7 +1188,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
||||
if (rc) {
|
||||
printk(KERN_WARNING "%s: context_to_sid(%s) "
|
||||
"returned %d for dev=%s ino=%ld\n",
|
||||
__FUNCTION__, context, -rc,
|
||||
__func__, context, -rc,
|
||||
inode->i_sb->s_id, inode->i_ino);
|
||||
kfree(context);
|
||||
/* Leave with the unlabeled SID */
|
||||
@ -1618,6 +1616,35 @@ static inline u32 file_mask_to_av(int mode, int mask)
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
struct task_security_struct *psec = parent->security;
|
||||
struct task_security_struct *csec = child->security;
|
||||
int rc;
|
||||
|
||||
rc = secondary_ops->ptrace(parent,child);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = 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;
|
||||
return task_has_perm(parent, child, PROCESS__PTRACE);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
bsec->bprm = bprm;
|
||||
bsec->sid = SECINITSID_UNLABELED;
|
||||
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.
|
||||
Otherwise, leave SID unchanged and kill. */
|
||||
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
|
||||
rc = avc_has_perm(tsec->ptrace_sid, sid,
|
||||
SECCLASS_PROCESS, PROCESS__PTRACE,
|
||||
NULL);
|
||||
if (rc) {
|
||||
bsec->unsafe = 1;
|
||||
return;
|
||||
struct task_struct *tracer;
|
||||
struct task_security_struct *sec;
|
||||
u32 ptsid = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
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;
|
||||
@ -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)
|
||||
{
|
||||
return (match_prefix("context=", sizeof("context=")-1, option, len) ||
|
||||
match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
|
||||
match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
|
||||
match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
|
||||
return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
|
||||
match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
|
||||
match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-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)
|
||||
@ -2412,7 +2461,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
|
||||
printk(KERN_WARNING "%s: "
|
||||
"security_transition_sid failed, rc=%d (dev=%s "
|
||||
"ino=%ld)\n",
|
||||
__FUNCTION__,
|
||||
__func__,
|
||||
-rc, inode->i_sb->s_id, inode->i_ino);
|
||||
return rc;
|
||||
}
|
||||
@ -2536,7 +2585,7 @@ static int selinux_inode_permission(struct inode *inode, int mask,
|
||||
}
|
||||
|
||||
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)
|
||||
@ -2646,7 +2695,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
|
||||
rc = security_context_to_sid(value, size, &newsid);
|
||||
if (rc) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3087,11 +3136,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
|
||||
tsec2->keycreate_sid = tsec1->keycreate_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;
|
||||
}
|
||||
|
||||
@ -3627,10 +3671,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
|
||||
inet_get_local_port_range(&low, &high);
|
||||
|
||||
if (snum < max(PROT_SOCK, low) || snum > high) {
|
||||
err = security_port_sid(sk->sk_family,
|
||||
sk->sk_type,
|
||||
sk->sk_protocol, snum,
|
||||
&sid);
|
||||
err = sel_netport_sid(sk->sk_protocol,
|
||||
snum, &sid);
|
||||
if (err)
|
||||
goto out;
|
||||
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);
|
||||
}
|
||||
|
||||
err = security_port_sid(sk->sk_family, sk->sk_type,
|
||||
sk->sk_protocol, snum, &sid);
|
||||
err = sel_netport_sid(sk->sk_protocol, snum, &sid);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -3950,9 +3991,8 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
|
||||
|
||||
if (!recv_perm)
|
||||
return 0;
|
||||
err = security_port_sid(sk->sk_family, sk->sk_type,
|
||||
sk->sk_protocol, ntohs(ad->u.net.sport),
|
||||
&port_sid);
|
||||
err = sel_netport_sid(sk->sk_protocol,
|
||||
ntohs(ad->u.net.sport), &port_sid);
|
||||
if (unlikely(err)) {
|
||||
printk(KERN_WARNING
|
||||
"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->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)
|
||||
@ -4373,9 +4413,8 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
|
||||
if (send_perm != 0)
|
||||
return 0;
|
||||
|
||||
err = security_port_sid(sk->sk_family, sk->sk_type,
|
||||
sk->sk_protocol, ntohs(ad->u.net.dport),
|
||||
&port_sid);
|
||||
err = sel_netport_sid(sk->sk_protocol,
|
||||
ntohs(ad->u.net.dport), &port_sid);
|
||||
if (unlikely(err)) {
|
||||
printk(KERN_WARNING
|
||||
"SELinux: failure in"
|
||||
@ -4561,7 +4600,6 @@ static int ipc_alloc_security(struct task_struct *task,
|
||||
return -ENOMEM;
|
||||
|
||||
isec->sclass = sclass;
|
||||
isec->ipc_perm = perm;
|
||||
isec->sid = tsec->sid;
|
||||
perm->security = isec;
|
||||
|
||||
@ -4583,7 +4621,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
|
||||
if (!msec)
|
||||
return -ENOMEM;
|
||||
|
||||
msec->msg = msg;
|
||||
msec->sid = SECINITSID_UNLABELED;
|
||||
msg->security = msec;
|
||||
|
||||
@ -4994,14 +5031,14 @@ static int selinux_register_security (const char *name, struct security_operatio
|
||||
{
|
||||
if (secondary_ops != original_ops) {
|
||||
printk(KERN_ERR "%s: There is already a secondary security "
|
||||
"module registered.\n", __FUNCTION__);
|
||||
"module registered.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
secondary_ops = ops;
|
||||
|
||||
printk(KERN_INFO "%s: Registering secondary module %s\n",
|
||||
__FUNCTION__,
|
||||
__func__,
|
||||
name);
|
||||
|
||||
return 0;
|
||||
@ -5057,6 +5094,7 @@ static int selinux_setprocattr(struct task_struct *p,
|
||||
char *name, void *value, size_t size)
|
||||
{
|
||||
struct task_security_struct *tsec;
|
||||
struct task_struct *tracer;
|
||||
u32 sid = 0;
|
||||
int error;
|
||||
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.
|
||||
Otherwise, leave SID unchanged and fail. */
|
||||
task_lock(p);
|
||||
if (p->ptrace & PT_PTRACED) {
|
||||
error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
|
||||
rcu_read_lock();
|
||||
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,
|
||||
PROCESS__PTRACE, 0, &avd);
|
||||
if (!error)
|
||||
tsec->sid = sid;
|
||||
task_unlock(p);
|
||||
avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
|
||||
avc_audit(ptsid, sid, SECCLASS_PROCESS,
|
||||
PROCESS__PTRACE, &avd, error, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
} else {
|
||||
rcu_read_unlock();
|
||||
tsec->sid = sid;
|
||||
task_unlock(p);
|
||||
}
|
||||
@ -5194,7 +5238,6 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
|
||||
if (!ksec)
|
||||
return -ENOMEM;
|
||||
|
||||
ksec->obj = k;
|
||||
if (tsec->keycreate_sid)
|
||||
ksec->sid = tsec->keycreate_sid;
|
||||
else
|
||||
@ -5631,5 +5674,3 @@ int selinux_disable(void)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -14,12 +14,17 @@
|
||||
S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
|
||||
S_(SECCLASS_DIR, DIR__SEARCH, "search")
|
||||
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__ENTRYPOINT, "entrypoint")
|
||||
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__ENTRYPOINT, "entrypoint")
|
||||
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_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
|
||||
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
|
||||
|
@ -79,6 +79,7 @@
|
||||
#define DIR__REPARENT 0x00080000UL
|
||||
#define DIR__SEARCH 0x00100000UL
|
||||
#define DIR__RMDIR 0x00200000UL
|
||||
#define DIR__OPEN 0x00400000UL
|
||||
#define FILE__IOCTL 0x00000001UL
|
||||
#define FILE__READ 0x00000002UL
|
||||
#define FILE__WRITE 0x00000004UL
|
||||
@ -99,6 +100,7 @@
|
||||
#define FILE__EXECUTE_NO_TRANS 0x00020000UL
|
||||
#define FILE__ENTRYPOINT 0x00040000UL
|
||||
#define FILE__EXECMOD 0x00080000UL
|
||||
#define FILE__OPEN 0x00100000UL
|
||||
#define LNK_FILE__IOCTL 0x00000001UL
|
||||
#define LNK_FILE__READ 0x00000002UL
|
||||
#define LNK_FILE__WRITE 0x00000004UL
|
||||
@ -136,6 +138,7 @@
|
||||
#define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL
|
||||
#define CHR_FILE__ENTRYPOINT 0x00040000UL
|
||||
#define CHR_FILE__EXECMOD 0x00080000UL
|
||||
#define CHR_FILE__OPEN 0x00100000UL
|
||||
#define BLK_FILE__IOCTL 0x00000001UL
|
||||
#define BLK_FILE__READ 0x00000002UL
|
||||
#define BLK_FILE__WRITE 0x00000004UL
|
||||
@ -153,6 +156,7 @@
|
||||
#define BLK_FILE__SWAPON 0x00004000UL
|
||||
#define BLK_FILE__QUOTAON 0x00008000UL
|
||||
#define BLK_FILE__MOUNTON 0x00010000UL
|
||||
#define BLK_FILE__OPEN 0x00020000UL
|
||||
#define SOCK_FILE__IOCTL 0x00000001UL
|
||||
#define SOCK_FILE__READ 0x00000002UL
|
||||
#define SOCK_FILE__WRITE 0x00000004UL
|
||||
@ -187,6 +191,7 @@
|
||||
#define FIFO_FILE__SWAPON 0x00004000UL
|
||||
#define FIFO_FILE__QUOTAON 0x00008000UL
|
||||
#define FIFO_FILE__MOUNTON 0x00010000UL
|
||||
#define FIFO_FILE__OPEN 0x00020000UL
|
||||
#define FD__USE 0x00000001UL
|
||||
#define SOCKET__IOCTL 0x00000001UL
|
||||
#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,
|
||||
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,
|
||||
u16 family,
|
||||
@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset(
|
||||
{
|
||||
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,
|
||||
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"
|
||||
|
||||
struct task_security_struct {
|
||||
struct task_struct *task; /* back pointer to task object */
|
||||
u32 osid; /* SID prior to last execve */
|
||||
u32 sid; /* current SID */
|
||||
u32 exec_sid; /* exec SID */
|
||||
u32 create_sid; /* fscreate SID */
|
||||
u32 keycreate_sid; /* keycreate SID */
|
||||
u32 sockcreate_sid; /* fscreate SID */
|
||||
u32 ptrace_sid; /* SID of ptrace parent */
|
||||
};
|
||||
|
||||
struct inode_security_struct {
|
||||
@ -50,7 +48,6 @@ struct inode_security_struct {
|
||||
};
|
||||
|
||||
struct file_security_struct {
|
||||
struct file *file; /* back pointer to file object */
|
||||
u32 sid; /* SID of open file description */
|
||||
u32 fown_sid; /* SID of file owner (for SIGIO) */
|
||||
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_msg *msg; /* back pointer */
|
||||
u32 sid; /* SID of message */
|
||||
};
|
||||
|
||||
struct ipc_security_struct {
|
||||
struct kern_ipc_perm *ipc_perm; /* back pointer */
|
||||
u16 sclass; /* security class of this object */
|
||||
u32 sid; /* SID of IPC resource */
|
||||
};
|
||||
|
||||
struct bprm_security_struct {
|
||||
struct linux_binprm *bprm; /* back pointer to bprm object */
|
||||
u32 sid; /* SID for transformed process */
|
||||
unsigned char set;
|
||||
|
||||
@ -109,8 +103,13 @@ struct netnode_security_struct {
|
||||
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 sock *sk; /* back pointer to sk object */
|
||||
u32 sid; /* SID of this object */
|
||||
u32 peer_sid; /* SID of peer */
|
||||
u16 sclass; /* sock security class */
|
||||
@ -120,12 +119,10 @@ struct sk_security_struct {
|
||||
NLBL_REQUIRE,
|
||||
NLBL_LABELED,
|
||||
} nlbl_state;
|
||||
spinlock_t nlbl_lock; /* protects nlbl_state */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct key_security_struct {
|
||||
struct key *obj; /* back pointer */
|
||||
u32 sid; /* SID of key */
|
||||
};
|
||||
|
||||
|
@ -26,13 +26,14 @@
|
||||
#define POLICYDB_VERSION_AVTAB 20
|
||||
#define POLICYDB_VERSION_RANGETRANS 21
|
||||
#define POLICYDB_VERSION_POLCAP 22
|
||||
#define POLICYDB_VERSION_PERMISSIVE 23
|
||||
|
||||
/* Range of policy versions we understand*/
|
||||
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
|
||||
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
|
||||
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
|
||||
#else
|
||||
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
|
||||
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
|
||||
#endif
|
||||
|
||||
#define CONTEXT_MNT 0x01
|
||||
@ -40,6 +41,11 @@
|
||||
#define ROOTCONTEXT_MNT 0x04
|
||||
#define DEFCONTEXT_MNT 0x08
|
||||
|
||||
#define CONTEXT_STR "context="
|
||||
#define FSCONTEXT_STR "fscontext="
|
||||
#define ROOTCONTEXT_STR "rootcontext="
|
||||
#define DEFCONTEXT_STR "defcontext="
|
||||
|
||||
struct netlbl_lsm_secattr;
|
||||
|
||||
extern int selinux_enabled;
|
||||
@ -48,11 +54,13 @@ extern int selinux_mls_enabled;
|
||||
/* Policy capabilities */
|
||||
enum {
|
||||
POLICYDB_CAPABILITY_NETPEER,
|
||||
POLICYDB_CAPABILITY_OPENPERM,
|
||||
__POLICYDB_CAPABILITY_MAX
|
||||
};
|
||||
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
|
||||
|
||||
extern int selinux_policycap_netpeer;
|
||||
extern int selinux_policycap_openperm;
|
||||
|
||||
int security_load_policy(void * data, size_t len);
|
||||
|
||||
@ -67,6 +75,8 @@ struct av_decision {
|
||||
u32 seqno;
|
||||
};
|
||||
|
||||
int security_permissive_sid(u32 sid);
|
||||
|
||||
int security_compute_av(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
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,
|
||||
u32 **sids, u32 *nel);
|
||||
|
||||
int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
|
||||
u32 *out_sid);
|
||||
int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
|
||||
|
||||
int security_netif_sid(char *name, u32 *if_sid);
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include "objsec.h"
|
||||
#include "security.h"
|
||||
#include "netlabel.h"
|
||||
|
||||
/**
|
||||
* selinux_netlbl_sidlookup_cached - Cache a SID lookup
|
||||
@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
|
||||
*
|
||||
* Description:
|
||||
* Attempt to label a socket using the NetLabel mechanism using the given
|
||||
* SID. Returns zero values on success, negative values on failure. The
|
||||
* caller is responsibile for calling rcu_read_lock() before calling this
|
||||
* this function and rcu_read_unlock() after this function returns.
|
||||
* SID. Returns zero values on success, negative values on failure.
|
||||
*
|
||||
*/
|
||||
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)
|
||||
goto sock_setsid_return;
|
||||
rc = netlbl_sock_setattr(sk, &secattr);
|
||||
if (rc == 0) {
|
||||
spin_lock_bh(&sksec->nlbl_lock);
|
||||
if (rc == 0)
|
||||
sksec->nlbl_state = NLBL_LABELED;
|
||||
spin_unlock_bh(&sksec->nlbl_lock);
|
||||
}
|
||||
|
||||
sock_setsid_return:
|
||||
netlbl_secattr_destroy(&secattr);
|
||||
@ -128,45 +124,6 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
|
||||
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
|
||||
* @skb: the packet
|
||||
@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
|
||||
struct netlbl_lsm_secattr secattr;
|
||||
u32 nlbl_peer_sid;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (sksec->nlbl_state != NLBL_REQUIRE) {
|
||||
rcu_read_unlock();
|
||||
if (sksec->nlbl_state != NLBL_REQUIRE)
|
||||
return;
|
||||
}
|
||||
|
||||
netlbl_secattr_init(&secattr);
|
||||
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
|
||||
* selinux_netlbl_inode_permission(). */
|
||||
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 rc = 0;
|
||||
struct sock *sk = sock->sk;
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
|
||||
rcu_read_lock();
|
||||
if (sksec->nlbl_state == NLBL_REQUIRE)
|
||||
rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
|
||||
rcu_read_unlock();
|
||||
if (sksec->nlbl_state != NLBL_REQUIRE)
|
||||
return 0;
|
||||
|
||||
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) ||
|
||||
((mask & (MAY_WRITE | MAY_APPEND)) == 0))
|
||||
return 0;
|
||||
|
||||
sock = SOCKET_I(inode);
|
||||
sk = sock->sk;
|
||||
sksec = sk->sk_security;
|
||||
|
||||
rcu_read_lock();
|
||||
if (sksec->nlbl_state != NLBL_REQUIRE) {
|
||||
rcu_read_unlock();
|
||||
if (sksec->nlbl_state != NLBL_REQUIRE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
local_bh_disable();
|
||||
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);
|
||||
local_bh_enable();
|
||||
rcu_read_unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
struct netlbl_lsm_secattr secattr;
|
||||
|
||||
rcu_read_lock();
|
||||
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
|
||||
sksec->nlbl_state == NLBL_LABELED) {
|
||||
netlbl_secattr_init(&secattr);
|
||||
@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
|
||||
rc = -EACCES;
|
||||
netlbl_secattr_destroy(&secattr);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ out:
|
||||
nlmsg_failure:
|
||||
kfree_skb(skb);
|
||||
oom:
|
||||
printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__);
|
||||
printk(KERN_ERR "SELinux: OOM in %s\n", __func__);
|
||||
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 */
|
||||
static char *policycap_names[] = {
|
||||
"network_peer_controls"
|
||||
"network_peer_controls",
|
||||
"open_perms"
|
||||
};
|
||||
|
||||
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) {
|
||||
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
||||
"max\n", __FUNCTION__, len);
|
||||
"max\n", __func__, len);
|
||||
length = -ERANGE;
|
||||
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) {
|
||||
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
||||
"max\n", __FUNCTION__, len);
|
||||
"max\n", __func__, len);
|
||||
length = -ERANGE;
|
||||
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) {
|
||||
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
||||
"max\n", __FUNCTION__, len);
|
||||
"max\n", __func__, len);
|
||||
length = -ERANGE;
|
||||
goto out3;
|
||||
}
|
||||
@ -1760,7 +1761,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
|
||||
out:
|
||||
return ret;
|
||||
err:
|
||||
printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
|
||||
printk(KERN_ERR "%s: failed while creating inodes\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -280,8 +280,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
|
||||
h->nel = 0;
|
||||
h->nslot = nslot;
|
||||
h->mask = mask;
|
||||
printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. "
|
||||
"Num of rules:%d\n", h->nslot, nrules);
|
||||
printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n",
|
||||
h->nslot, nrules);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -345,18 +345,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
||||
if (vers < POLICYDB_VERSION_AVTAB) {
|
||||
rc = next_entry(buf32, fp, sizeof(u32));
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: avtab: truncated entry\n");
|
||||
printk(KERN_ERR "SELinux: avtab: truncated entry\n");
|
||||
return -1;
|
||||
}
|
||||
items2 = le32_to_cpu(buf32[0]);
|
||||
if (items2 > ARRAY_SIZE(buf32)) {
|
||||
printk(KERN_ERR "security: avtab: entry overflow\n");
|
||||
printk(KERN_ERR "SELinux: avtab: entry overflow\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
rc = next_entry(buf32, fp, sizeof(u32)*items2);
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: avtab: truncated entry\n");
|
||||
printk(KERN_ERR "SELinux: avtab: truncated entry\n");
|
||||
return -1;
|
||||
}
|
||||
items = 0;
|
||||
@ -364,19 +364,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
||||
val = le32_to_cpu(buf32[items++]);
|
||||
key.source_type = (u16)val;
|
||||
if (key.source_type != val) {
|
||||
printk("security: avtab: truncated source type\n");
|
||||
printk("SELinux: avtab: truncated source type\n");
|
||||
return -1;
|
||||
}
|
||||
val = le32_to_cpu(buf32[items++]);
|
||||
key.target_type = (u16)val;
|
||||
if (key.target_type != val) {
|
||||
printk("security: avtab: truncated target type\n");
|
||||
printk("SELinux: avtab: truncated target type\n");
|
||||
return -1;
|
||||
}
|
||||
val = le32_to_cpu(buf32[items++]);
|
||||
key.target_class = (u16)val;
|
||||
if (key.target_class != val) {
|
||||
printk("security: avtab: truncated target class\n");
|
||||
printk("SELinux: avtab: truncated target class\n");
|
||||
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;
|
||||
|
||||
if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
|
||||
printk("security: avtab: null entry\n");
|
||||
printk("SELinux: avtab: null entry\n");
|
||||
return -1;
|
||||
}
|
||||
if ((val & AVTAB_AV) &&
|
||||
(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;
|
||||
}
|
||||
|
||||
@ -403,7 +403,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
||||
}
|
||||
|
||||
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 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);
|
||||
if (rc < 0) {
|
||||
printk("security: avtab: truncated entry\n");
|
||||
printk("SELinux: avtab: truncated entry\n");
|
||||
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) ||
|
||||
!policydb_type_isvalid(pol, key.target_type) ||
|
||||
!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;
|
||||
}
|
||||
|
||||
@ -435,19 +435,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
|
||||
}
|
||||
if (!set || set > 1) {
|
||||
printk(KERN_WARNING
|
||||
"security: avtab: more than one specifier\n");
|
||||
"SELinux: avtab: more than one specifier\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = next_entry(buf32, fp, sizeof(u32));
|
||||
if (rc < 0) {
|
||||
printk("security: avtab: truncated entry\n");
|
||||
printk("SELinux: avtab: truncated entry\n");
|
||||
return -1;
|
||||
}
|
||||
datum.data = le32_to_cpu(*buf32);
|
||||
if ((key.specified & AVTAB_TYPE) &&
|
||||
!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 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));
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: avtab: truncated table\n");
|
||||
printk(KERN_ERR "SELinux: avtab: truncated table\n");
|
||||
goto bad;
|
||||
}
|
||||
nel = le32_to_cpu(buf[0]);
|
||||
if (!nel) {
|
||||
printk(KERN_ERR "security: avtab: table is empty\n");
|
||||
printk(KERN_ERR "SELinux: avtab: table is empty\n");
|
||||
rc = -EINVAL;
|
||||
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);
|
||||
if (rc) {
|
||||
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)
|
||||
printk(KERN_ERR "security: avtab: duplicate entry\n");
|
||||
printk(KERN_ERR "SELinux: avtab: duplicate entry\n");
|
||||
else
|
||||
rc = -EINVAL;
|
||||
goto bad;
|
||||
|
@ -96,7 +96,7 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
|
||||
if (new_state != node->cur_state) {
|
||||
node->cur_state = new_state;
|
||||
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 */
|
||||
for (cur = node->true_list; cur != NULL; cur = cur->next) {
|
||||
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 (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;
|
||||
}
|
||||
/*
|
||||
@ -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);
|
||||
if (node_ptr) {
|
||||
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;
|
||||
}
|
||||
found = 0;
|
||||
@ -302,13 +302,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
printk("security: conflicting type rules.\n");
|
||||
printk("SELinux: conflicting type rules.\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
if (!node_ptr) {
|
||||
printk("security: could not insert rule.");
|
||||
printk("SELinux: could not insert rule.");
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 1;
|
||||
|
@ -364,7 +364,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
count = le32_to_cpu(buf[2]);
|
||||
|
||||
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",
|
||||
mapunit, sizeof(u64) * 8, e->highbit);
|
||||
goto bad;
|
||||
@ -382,19 +382,19 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
for (i = 0; i < count; i++) {
|
||||
rc = next_entry(&startbit, fp, sizeof(u32));
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: ebitmap: truncated map\n");
|
||||
printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
|
||||
goto bad;
|
||||
}
|
||||
startbit = le32_to_cpu(startbit);
|
||||
|
||||
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",
|
||||
startbit, mapunit);
|
||||
goto bad;
|
||||
}
|
||||
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",
|
||||
startbit, (e->highbit - mapunit));
|
||||
goto bad;
|
||||
@ -405,7 +405,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp) {
|
||||
printk(KERN_ERR
|
||||
"security: ebitmap: out of memory\n");
|
||||
"SELinux: ebitmap: out of memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
@ -418,7 +418,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
}
|
||||
n = tmp;
|
||||
} 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",
|
||||
startbit, n->startbit);
|
||||
goto bad;
|
||||
@ -426,7 +426,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
|
||||
rc = next_entry(&map, fp, sizeof(u64));
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: ebitmap: truncated map\n");
|
||||
printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
|
||||
goto bad;
|
||||
}
|
||||
map = le64_to_cpu(map);
|
||||
|
@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = {
|
||||
.version = POLICYDB_VERSION_POLCAP,
|
||||
.sym_num = SYM_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;
|
||||
|
||||
ebitmap_init(&p->policycaps);
|
||||
ebitmap_init(&p->permissive_map);
|
||||
|
||||
out:
|
||||
return rc;
|
||||
@ -401,14 +407,14 @@ static int policydb_index_others(struct policydb *p)
|
||||
{
|
||||
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);
|
||||
if (selinux_mls_enabled)
|
||||
printk(", %d sens, %d cats", p->p_levels.nprim,
|
||||
p->p_cats.nprim);
|
||||
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);
|
||||
|
||||
#ifdef DEBUG_HASHES
|
||||
@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
|
||||
kfree(p->type_attr_map);
|
||||
kfree(p->undefined_perms);
|
||||
ebitmap_destroy(&p->policycaps);
|
||||
ebitmap_destroy(&p->permissive_map);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -702,20 +709,20 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s)
|
||||
|
||||
rc = sidtab_init(s);
|
||||
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;
|
||||
}
|
||||
|
||||
head = p->ocontexts[OCON_ISID];
|
||||
for (c = head; c; c = c->next) {
|
||||
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);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
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);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
@ -809,13 +816,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
|
||||
|
||||
items = le32_to_cpu(buf[0]);
|
||||
if (items > ARRAY_SIZE(buf)) {
|
||||
printk(KERN_ERR "security: mls: range overflow\n");
|
||||
printk(KERN_ERR "SELinux: mls: range overflow\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rc = next_entry(buf, fp, sizeof(u32) * items);
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: mls: truncated range\n");
|
||||
printk(KERN_ERR "SELinux: mls: truncated range\n");
|
||||
goto out;
|
||||
}
|
||||
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);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "security: mls: error reading low "
|
||||
printk(KERN_ERR "SELinux: mls: error reading low "
|
||||
"categories\n");
|
||||
goto out;
|
||||
}
|
||||
if (items > 1) {
|
||||
rc = ebitmap_read(&r->level[1].cat, fp);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "security: mls: error reading high "
|
||||
printk(KERN_ERR "SELinux: mls: error reading high "
|
||||
"categories\n");
|
||||
goto bad_high;
|
||||
}
|
||||
} else {
|
||||
rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "security: mls: out of memory\n");
|
||||
printk(KERN_ERR "SELinux: mls: out of memory\n");
|
||||
goto bad_high;
|
||||
}
|
||||
}
|
||||
@ -866,7 +873,7 @@ static int context_read_and_validate(struct context *c,
|
||||
|
||||
rc = next_entry(buf, fp, sizeof buf);
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: context truncated\n");
|
||||
printk(KERN_ERR "SELinux: context truncated\n");
|
||||
goto out;
|
||||
}
|
||||
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]);
|
||||
if (p->policyvers >= POLICYDB_VERSION_MLS) {
|
||||
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");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
@ -882,7 +889,7 @@ static int context_read_and_validate(struct context *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);
|
||||
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->comkey);
|
||||
if (!cladatum->comdatum) {
|
||||
printk(KERN_ERR "security: unknown common %s\n",
|
||||
printk(KERN_ERR "SELinux: unknown common %s\n",
|
||||
cladatum->comkey);
|
||||
rc = -EINVAL;
|
||||
goto bad;
|
||||
@ -1283,13 +1290,13 @@ static int mls_read_level(struct mls_level *lp, void *fp)
|
||||
|
||||
rc = next_entry(buf, fp, sizeof buf);
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: mls: truncated level\n");
|
||||
printk(KERN_ERR "SELinux: mls: truncated level\n");
|
||||
goto bad;
|
||||
}
|
||||
lp->sens = le32_to_cpu(buf[0]);
|
||||
|
||||
if (ebitmap_read(&lp->cat, fp)) {
|
||||
printk(KERN_ERR "security: mls: error reading level "
|
||||
printk(KERN_ERR "SELinux: mls: error reading level "
|
||||
"categories\n");
|
||||
goto bad;
|
||||
}
|
||||
@ -1491,7 +1498,7 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
goto bad;
|
||||
|
||||
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",
|
||||
le32_to_cpu(buf[0]), POLICYDB_MAGIC);
|
||||
goto bad;
|
||||
@ -1499,27 +1506,27 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
|
||||
len = le32_to_cpu(buf[1]);
|
||||
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",
|
||||
len, strlen(POLICYDB_STRING));
|
||||
goto bad;
|
||||
}
|
||||
policydb_str = kmalloc(len + 1,GFP_KERNEL);
|
||||
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);
|
||||
rc = -ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
rc = next_entry(policydb_str, fp, len);
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "security: truncated policydb string identifier\n");
|
||||
printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
|
||||
kfree(policydb_str);
|
||||
goto bad;
|
||||
}
|
||||
policydb_str[len] = 0;
|
||||
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);
|
||||
kfree(policydb_str);
|
||||
goto bad;
|
||||
@ -1536,7 +1543,7 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
p->policyvers = le32_to_cpu(buf[0]);
|
||||
if (p->policyvers < POLICYDB_VERSION_MIN ||
|
||||
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",
|
||||
le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
|
||||
goto bad;
|
||||
@ -1570,16 +1577,20 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
ebitmap_read(&p->policycaps, fp) != 0)
|
||||
goto bad;
|
||||
|
||||
if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
|
||||
ebitmap_read(&p->permissive_map, fp) != 0)
|
||||
goto bad;
|
||||
|
||||
info = policydb_lookup_compat(p->policyvers);
|
||||
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);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(buf[2]) != info->sym_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]),
|
||||
le32_to_cpu(buf[3]),
|
||||
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;
|
||||
genfs_p = genfs, genfs = genfs->next) {
|
||||
if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
|
||||
printk(KERN_ERR "security: dup genfs "
|
||||
printk(KERN_ERR "SELinux: dup genfs "
|
||||
"fstype %s\n", newgenfs->fstype);
|
||||
kfree(newgenfs->fstype);
|
||||
kfree(newgenfs);
|
||||
@ -1873,7 +1884,7 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
if (!strcmp(newc->u.name, c->u.name) &&
|
||||
(!c->v.sclass || !newc->v.sclass ||
|
||||
newc->v.sclass == c->v.sclass)) {
|
||||
printk(KERN_ERR "security: dup genfs "
|
||||
printk(KERN_ERR "SELinux: dup genfs "
|
||||
"entry (%s,%s)\n",
|
||||
newgenfs->fstype, c->u.name);
|
||||
goto bad_newc;
|
||||
@ -1931,7 +1942,7 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
if (rc)
|
||||
goto bad;
|
||||
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;
|
||||
}
|
||||
lrt = rt;
|
||||
|
@ -243,6 +243,8 @@ struct policydb {
|
||||
|
||||
struct ebitmap policycaps;
|
||||
|
||||
struct ebitmap permissive_map;
|
||||
|
||||
unsigned int policyvers;
|
||||
|
||||
unsigned int reject_unknown : 1;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/selinux.h>
|
||||
#include <net/netlabel.h>
|
||||
|
||||
#include "flask.h"
|
||||
@ -61,6 +62,7 @@ extern void selnl_notify_policyload(u32 seqno);
|
||||
unsigned int policydb_loaded_version;
|
||||
|
||||
int selinux_policycap_netpeer;
|
||||
int selinux_policycap_openperm;
|
||||
|
||||
/*
|
||||
* This is declared in avc.c
|
||||
@ -412,10 +414,35 @@ static int context_struct_compute_av(struct context *scontext,
|
||||
return 0;
|
||||
|
||||
inval_class:
|
||||
printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass);
|
||||
printk(KERN_ERR "%s: unrecognized class %d\n", __func__, tclass);
|
||||
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,
|
||||
struct context *ncontext,
|
||||
struct context *tcontext,
|
||||
@ -1096,7 +1123,7 @@ static int validate_classes(struct policydb *p)
|
||||
continue;
|
||||
if (i > p->p_classes.nprim) {
|
||||
printk(KERN_INFO
|
||||
"security: class %s not defined in policy\n",
|
||||
"SELinux: class %s not defined in policy\n",
|
||||
def_class);
|
||||
if (p->reject_unknown)
|
||||
return -EINVAL;
|
||||
@ -1107,7 +1134,7 @@ static int validate_classes(struct policydb *p)
|
||||
pol_class = p->p_class_val_to_name[i-1];
|
||||
if (strcmp(pol_class, def_class)) {
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1125,7 +1152,7 @@ static int validate_classes(struct policydb *p)
|
||||
nprim = 1 << (perms->nprim - 1);
|
||||
if (perm_val > nprim) {
|
||||
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);
|
||||
if (p->reject_unknown)
|
||||
return -EINVAL;
|
||||
@ -1136,14 +1163,14 @@ static int validate_classes(struct policydb *p)
|
||||
perdatum = hashtab_search(perms->table, def_perm);
|
||||
if (perdatum == NULL) {
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
pol_val = 1 << (perdatum->value - 1);
|
||||
if (pol_val != perm_val) {
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1157,7 +1184,7 @@ static int validate_classes(struct policydb *p)
|
||||
BUG_ON(!cladatum);
|
||||
if (!cladatum->comdatum) {
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1172,7 +1199,7 @@ static int validate_classes(struct policydb *p)
|
||||
def_perm = kdefs->av_inherit[i].common_pts[j];
|
||||
if (j >= perms->nprim) {
|
||||
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);
|
||||
if (p->reject_unknown)
|
||||
return -EINVAL;
|
||||
@ -1183,13 +1210,13 @@ static int validate_classes(struct policydb *p)
|
||||
perdatum = hashtab_search(perms->table, def_perm);
|
||||
if (perdatum == NULL) {
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (perdatum->value != j + 1) {
|
||||
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);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1219,7 +1246,7 @@ static inline int convert_context_handle_invalid_context(struct context *context
|
||||
u32 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);
|
||||
}
|
||||
return rc;
|
||||
@ -1299,7 +1326,7 @@ out:
|
||||
bad:
|
||||
context_struct_to_string(&oldc, &s, &len);
|
||||
context_destroy(&oldc);
|
||||
printk(KERN_ERR "security: invalidating context %s\n", s);
|
||||
printk(KERN_ERR "SELinux: invalidating context %s\n", s);
|
||||
kfree(s);
|
||||
goto out;
|
||||
}
|
||||
@ -1308,6 +1335,8 @@ static void security_load_policycaps(void)
|
||||
{
|
||||
selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
|
||||
POLICYDB_CAPABILITY_NETPEER);
|
||||
selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
|
||||
POLICYDB_CAPABILITY_OPENPERM);
|
||||
}
|
||||
|
||||
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. */
|
||||
if (validate_classes(&policydb)) {
|
||||
printk(KERN_ERR
|
||||
"security: the definition of a class is incorrect\n");
|
||||
"SELinux: the definition of a class is incorrect\n");
|
||||
LOAD_UNLOCK;
|
||||
sidtab_destroy(&sidtab);
|
||||
policydb_destroy(&policydb);
|
||||
@ -1384,14 +1413,14 @@ int security_load_policy(void *data, size_t len)
|
||||
/* Verify that the kernel defined classes are correct. */
|
||||
if (validate_classes(&newpolicydb)) {
|
||||
printk(KERN_ERR
|
||||
"security: the definition of a class is incorrect\n");
|
||||
"SELinux: the definition of a class is incorrect\n");
|
||||
rc = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = security_preserve_bools(&newpolicydb);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "security: unable to preserve booleans\n");
|
||||
printk(KERN_ERR "SELinux: unable to preserve booleans\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -1443,17 +1472,11 @@ err:
|
||||
|
||||
/**
|
||||
* security_port_sid - Obtain the SID for a port.
|
||||
* @domain: communication domain aka address family
|
||||
* @type: socket type
|
||||
* @protocol: protocol number
|
||||
* @port: port number
|
||||
* @out_sid: security identifier
|
||||
*/
|
||||
int security_port_sid(u16 domain,
|
||||
u16 type,
|
||||
u8 protocol,
|
||||
u16 port,
|
||||
u32 *out_sid)
|
||||
int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
|
||||
{
|
||||
struct ocontext *c;
|
||||
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);
|
||||
if (!match) {
|
||||
printk(KERN_ERR "%s: unrecognized class %s\n",
|
||||
__FUNCTION__, class);
|
||||
__func__, class);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user