(2006-08-06) rescue-bootcd
This commit is contained in:
1
extra/linux-2.6.10/security/.built-in.o.cmd
Normal file
1
extra/linux-2.6.10/security/.built-in.o.cmd
Normal file
@@ -0,0 +1 @@
|
||||
cmd_security/built-in.o := ld -m elf_i386 -r -o security/built-in.o security/commoncap.o
|
||||
288
extra/linux-2.6.10/security/.commoncap.o.cmd
Normal file
288
extra/linux-2.6.10/security/.commoncap.o.cmd
Normal file
@@ -0,0 +1,288 @@
|
||||
cmd_security/commoncap.o := gcc -Wp,-MD,security/.commoncap.o.d -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium-mmx -Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -DKBUILD_BASENAME=commoncap -DKBUILD_MODNAME=commoncap -c -o security/commoncap.o security/commoncap.c
|
||||
|
||||
deps_security/commoncap.o := \
|
||||
security/commoncap.c \
|
||||
include/linux/config.h \
|
||||
$(wildcard include/config/h.h) \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
$(wildcard include/config/magic/sysrq.h) \
|
||||
include/asm/param.h \
|
||||
include/linux/capability.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
include/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/linux/compiler.h \
|
||||
include/linux/compiler-gcc3.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
include/asm/posix_types.h \
|
||||
include/asm/types.h \
|
||||
$(wildcard include/config/highmem64g.h) \
|
||||
$(wildcard include/config/lbd.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/lockmeter.h) \
|
||||
include/linux/preempt.h \
|
||||
include/linux/linkage.h \
|
||||
include/asm/linkage.h \
|
||||
$(wildcard include/config/regparm.h) \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/thread_info.h \
|
||||
include/linux/bitops.h \
|
||||
include/asm/bitops.h \
|
||||
include/asm/thread_info.h \
|
||||
$(wildcard include/config/4kstacks.h) \
|
||||
$(wildcard include/config/debug/stack/usage.h) \
|
||||
include/asm/page.h \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/highmem4g.h) \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
include/asm/processor.h \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
include/asm/vm86.h \
|
||||
include/asm/math_emu.h \
|
||||
include/asm/sigcontext.h \
|
||||
include/asm/segment.h \
|
||||
include/asm/cpufeature.h \
|
||||
include/asm/msr.h \
|
||||
include/asm/system.h \
|
||||
$(wildcard include/config/x86/cmpxchg.h) \
|
||||
$(wildcard include/config/x86/oostore.h) \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/debug/spinlock/sleep.h) \
|
||||
/usr/lib/gcc/i686-pc-linux-gnu/3.4.1/include/stdarg.h \
|
||||
include/asm/byteorder.h \
|
||||
$(wildcard include/config/x86/bswap.h) \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/linux/byteorder/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm/bug.h \
|
||||
include/asm-generic/bug.h \
|
||||
include/linux/cache.h \
|
||||
include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
include/asm/percpu.h \
|
||||
include/asm-generic/percpu.h \
|
||||
include/linux/stringify.h \
|
||||
include/linux/timex.h \
|
||||
$(wildcard include/config/time/interpolation.h) \
|
||||
include/linux/time.h \
|
||||
include/linux/seqlock.h \
|
||||
include/asm/timex.h \
|
||||
$(wildcard include/config/x86/elan.h) \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
$(wildcard include/config/x86/generic.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/asm/div64.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
include/asm/string.h \
|
||||
include/asm/semaphore.h \
|
||||
include/asm/atomic.h \
|
||||
$(wildcard include/config/m386.h) \
|
||||
include/linux/wait.h \
|
||||
include/linux/list.h \
|
||||
include/linux/prefetch.h \
|
||||
include/asm/current.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/generic/spinlock.h) \
|
||||
include/asm/rwsem.h \
|
||||
include/asm/ptrace.h \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
include/asm/mmu.h \
|
||||
include/linux/smp.h \
|
||||
include/linux/sem.h \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
include/linux/ipc.h \
|
||||
include/asm/ipcbuf.h \
|
||||
include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
include/asm/signal.h \
|
||||
include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h \
|
||||
include/linux/resource.h \
|
||||
include/asm/resource.h \
|
||||
include/linux/securebits.h \
|
||||
include/linux/fs_struct.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/percpu.h \
|
||||
include/linux/slab.h \
|
||||
$(wildcard include/config/.h) \
|
||||
include/linux/gfp.h \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
include/linux/numa.h \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/asm/topology.h \
|
||||
include/asm-generic/topology.h \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/hotplug.h) \
|
||||
include/linux/kmalloc_sizes.h \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/large/allocs.h) \
|
||||
include/linux/param.h \
|
||||
include/linux/timer.h \
|
||||
include/linux/aio.h \
|
||||
include/linux/workqueue.h \
|
||||
include/linux/aio_abi.h \
|
||||
include/linux/stat.h \
|
||||
include/asm/stat.h \
|
||||
include/linux/kmod.h \
|
||||
$(wildcard include/config/kmod.h) \
|
||||
include/linux/errno.h \
|
||||
include/asm/errno.h \
|
||||
include/asm-generic/errno.h \
|
||||
include/asm-generic/errno-base.h \
|
||||
include/linux/elf.h \
|
||||
include/asm/elf.h \
|
||||
include/asm/user.h \
|
||||
include/linux/utsname.h \
|
||||
include/linux/kobject.h \
|
||||
include/linux/sysfs.h \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
include/linux/kref.h \
|
||||
include/linux/kobject_uevent.h \
|
||||
$(wildcard include/config/kobject/uevent.h) \
|
||||
include/linux/moduleparam.h \
|
||||
include/asm/local.h \
|
||||
include/asm/module.h \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip2.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
include/linux/security.h \
|
||||
$(wildcard include/config/security/network.h) \
|
||||
include/linux/fs.h \
|
||||
$(wildcard include/config/dnotify.h) \
|
||||
$(wildcard include/config/quota.h) \
|
||||
$(wildcard include/config/epoll.h) \
|
||||
$(wildcard include/config/auditsyscall.h) \
|
||||
include/linux/limits.h \
|
||||
include/linux/kdev_t.h \
|
||||
include/linux/ioctl.h \
|
||||
include/asm/ioctl.h \
|
||||
include/linux/dcache.h \
|
||||
include/linux/rcupdate.h \
|
||||
include/linux/prio_tree.h \
|
||||
include/linux/radix-tree.h \
|
||||
include/linux/audit.h \
|
||||
$(wildcard include/config/audit.h) \
|
||||
include/linux/quota.h \
|
||||
include/linux/dqblk_xfs.h \
|
||||
include/linux/dqblk_v1.h \
|
||||
include/linux/dqblk_v2.h \
|
||||
include/linux/nfs_fs_i.h \
|
||||
include/linux/nfs.h \
|
||||
include/linux/sunrpc/msg_prot.h \
|
||||
include/linux/fcntl.h \
|
||||
include/asm/fcntl.h \
|
||||
include/linux/err.h \
|
||||
include/linux/binfmts.h \
|
||||
include/linux/shm.h \
|
||||
include/asm/shmparam.h \
|
||||
include/asm/shmbuf.h \
|
||||
include/linux/msg.h \
|
||||
include/asm/msgbuf.h \
|
||||
include/linux/file.h \
|
||||
include/linux/mm.h \
|
||||
$(wildcard include/config/sysctl.h) \
|
||||
$(wildcard include/config/stack/growsup.h) \
|
||||
$(wildcard include/config/highmem.h) \
|
||||
$(wildcard include/config/shmem.h) \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
$(wildcard include/config/debug/pagealloc.h) \
|
||||
$(wildcard include/config/arch/gate/area.h) \
|
||||
include/asm/pgtable.h \
|
||||
$(wildcard include/config/highpte.h) \
|
||||
include/asm/fixmap.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
$(wildcard include/config/x86/visws/apic.h) \
|
||||
$(wildcard include/config/x86/f00f/bug.h) \
|
||||
$(wildcard include/config/x86/cyclone/timer.h) \
|
||||
$(wildcard include/config/acpi/boot.h) \
|
||||
$(wildcard include/config/pci/mmconfig.h) \
|
||||
include/asm/acpi.h \
|
||||
$(wildcard include/config/acpi/pci.h) \
|
||||
$(wildcard include/config/acpi/sleep.h) \
|
||||
include/asm/apicdef.h \
|
||||
include/asm/pgtable-2level-defs.h \
|
||||
include/asm/pgtable-2level.h \
|
||||
include/asm-generic/pgtable.h \
|
||||
include/linux/page-flags.h \
|
||||
$(wildcard include/config/swap.h) \
|
||||
include/linux/mman.h \
|
||||
include/asm/mman.h \
|
||||
include/linux/pagemap.h \
|
||||
include/linux/highmem.h \
|
||||
include/asm/cacheflush.h \
|
||||
include/asm/uaccess.h \
|
||||
$(wildcard include/config/x86/intel/usercopy.h) \
|
||||
$(wildcard include/config/x86/wp/works/ok.h) \
|
||||
include/linux/swap.h \
|
||||
include/linux/smp_lock.h \
|
||||
$(wildcard include/config/lock/kernel.h) \
|
||||
include/linux/skbuff.h \
|
||||
$(wildcard include/config/netfilter.h) \
|
||||
$(wildcard include/config/bridge/netfilter.h) \
|
||||
$(wildcard include/config/vlan/8021q.h) \
|
||||
$(wildcard include/config/vlan/8021q/module.h) \
|
||||
$(wildcard include/config/netfilter/debug.h) \
|
||||
$(wildcard include/config/hippi.h) \
|
||||
$(wildcard include/config/net/sched.h) \
|
||||
$(wildcard include/config/net/cls/act.h) \
|
||||
include/linux/poll.h \
|
||||
include/asm/poll.h \
|
||||
include/linux/net.h \
|
||||
include/asm/socket.h \
|
||||
include/asm/sockios.h \
|
||||
include/net/checksum.h \
|
||||
include/asm/checksum.h \
|
||||
include/linux/in6.h \
|
||||
include/linux/netlink.h \
|
||||
include/linux/socket.h \
|
||||
$(wildcard include/config/compat.h) \
|
||||
include/linux/sockios.h \
|
||||
include/linux/uio.h \
|
||||
include/linux/ptrace.h \
|
||||
include/linux/xattr.h \
|
||||
include/linux/hugetlb.h \
|
||||
$(wildcard include/config/hugetlbfs.h) \
|
||||
|
||||
security/commoncap.o: $(deps_security/commoncap.o)
|
||||
|
||||
$(deps_security/commoncap.o):
|
||||
90
extra/linux-2.6.10/security/Kconfig
Normal file
90
extra/linux-2.6.10/security/Kconfig
Normal file
@@ -0,0 +1,90 @@
|
||||
#
|
||||
# Security configuration
|
||||
#
|
||||
|
||||
menu "Security options"
|
||||
|
||||
config KEYS
|
||||
bool "Enable access key retention support"
|
||||
help
|
||||
This option provides support for retaining authentication tokens and
|
||||
access keys in the kernel.
|
||||
|
||||
It also includes provision of methods by which such keys might be
|
||||
associated with a process so that network filesystems, encryption
|
||||
support and the like can find them.
|
||||
|
||||
Furthermore, a special type of key is available that acts as keyring:
|
||||
a searchable sequence of keys. Each process is equipped with access
|
||||
to five standard keyrings: UID-specific, GID-specific, session,
|
||||
process and thread.
|
||||
|
||||
If you are unsure as to whether this is required, answer N.
|
||||
|
||||
config KEYS_DEBUG_PROC_KEYS
|
||||
bool "Enable the /proc/keys file by which all keys may be viewed"
|
||||
depends on KEYS
|
||||
help
|
||||
This option turns on support for the /proc/keys file through which
|
||||
all the keys on the system can be listed.
|
||||
|
||||
This option is a slight security risk in that it makes it possible
|
||||
for anyone to see all the keys on the system. Normally the manager
|
||||
pretends keys that are inaccessible to a process don't exist as far
|
||||
as that process is concerned.
|
||||
|
||||
config SECURITY
|
||||
bool "Enable different security models"
|
||||
help
|
||||
This allows you to choose different security modules to be
|
||||
configured into your kernel.
|
||||
|
||||
If this option is not selected, the default Linux security
|
||||
model will be used.
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_NETWORK
|
||||
bool "Socket and Networking Security Hooks"
|
||||
depends on SECURITY
|
||||
help
|
||||
This enables the socket and networking security hooks.
|
||||
If enabled, a security module can use these hooks to
|
||||
implement socket and networking access controls.
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_CAPABILITIES
|
||||
tristate "Default Linux Capabilities"
|
||||
depends on SECURITY
|
||||
help
|
||||
This enables the "default" Linux capabilities functionality.
|
||||
If you are unsure how to answer this question, answer Y.
|
||||
|
||||
config SECURITY_ROOTPLUG
|
||||
tristate "Root Plug Support"
|
||||
depends on USB && SECURITY
|
||||
help
|
||||
This is a sample LSM module that should only be used as such.
|
||||
It prevents any programs running with egid == 0 if a specific
|
||||
USB device is not present in the system.
|
||||
|
||||
See <http://www.linuxjournal.com/article.php?sid=6279> for
|
||||
more information about this module.
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_SECLVL
|
||||
tristate "BSD Secure Levels"
|
||||
depends on SECURITY
|
||||
select CRYPTO_SHA1
|
||||
help
|
||||
Implements BSD Secure Levels as an LSM. See
|
||||
Documentation/seclvl.txt for instructions on how to use this
|
||||
module.
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
source security/selinux/Kconfig
|
||||
|
||||
endmenu
|
||||
|
||||
19
extra/linux-2.6.10/security/Makefile
Normal file
19
extra/linux-2.6.10/security/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Makefile for the kernel security code
|
||||
#
|
||||
|
||||
obj-$(CONFIG_KEYS) += keys/
|
||||
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
|
||||
|
||||
# if we don't select a security model, use the default capabilities
|
||||
ifneq ($(CONFIG_SECURITY),y)
|
||||
obj-y += commoncap.o
|
||||
endif
|
||||
|
||||
# Object file lists
|
||||
obj-$(CONFIG_SECURITY) += security.o dummy.o
|
||||
# Must precede capability.o in order to stack properly.
|
||||
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
|
||||
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
|
||||
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
|
||||
obj-$(CONFIG_SECURITY_SECLVL) += seclvl.o
|
||||
BIN
extra/linux-2.6.10/security/built-in.o
Normal file
BIN
extra/linux-2.6.10/security/built-in.o
Normal file
Binary file not shown.
104
extra/linux-2.6.10/security/capability.c
Normal file
104
extra/linux-2.6.10/security/capability.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Capabilities Linux Security Module
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
static struct security_operations capability_ops = {
|
||||
.ptrace = cap_ptrace,
|
||||
.capget = cap_capget,
|
||||
.capset_check = cap_capset_check,
|
||||
.capset_set = cap_capset_set,
|
||||
.capable = cap_capable,
|
||||
.settime = cap_settime,
|
||||
.netlink_send = cap_netlink_send,
|
||||
.netlink_recv = cap_netlink_recv,
|
||||
|
||||
.bprm_apply_creds = cap_bprm_apply_creds,
|
||||
.bprm_set_security = cap_bprm_set_security,
|
||||
.bprm_secureexec = cap_bprm_secureexec,
|
||||
|
||||
.inode_setxattr = cap_inode_setxattr,
|
||||
.inode_removexattr = cap_inode_removexattr,
|
||||
|
||||
.task_post_setuid = cap_task_post_setuid,
|
||||
.task_reparent_to_init = cap_task_reparent_to_init,
|
||||
|
||||
.syslog = cap_syslog,
|
||||
|
||||
.vm_enough_memory = cap_vm_enough_memory,
|
||||
};
|
||||
|
||||
#define MY_NAME __stringify(KBUILD_MODNAME)
|
||||
|
||||
/* flag to keep track of how we were registered */
|
||||
static int secondary;
|
||||
|
||||
static int capability_disable;
|
||||
module_param_named(disable, capability_disable, int, 0);
|
||||
MODULE_PARM_DESC(disable, "To disable capabilities module set disable = 1");
|
||||
|
||||
static int __init capability_init (void)
|
||||
{
|
||||
if (capability_disable) {
|
||||
printk(KERN_INFO "Capabilities disabled at initialization\n");
|
||||
return 0;
|
||||
}
|
||||
/* register ourselves with the security framework */
|
||||
if (register_security (&capability_ops)) {
|
||||
/* try registering with primary module */
|
||||
if (mod_reg_security (MY_NAME, &capability_ops)) {
|
||||
printk (KERN_INFO "Failure registering capabilities "
|
||||
"with primary security module.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
secondary = 1;
|
||||
}
|
||||
printk (KERN_INFO "Capability LSM initialized%s\n",
|
||||
secondary ? " as secondary" : "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit capability_exit (void)
|
||||
{
|
||||
if (capability_disable)
|
||||
return;
|
||||
/* remove ourselves from the security framework */
|
||||
if (secondary) {
|
||||
if (mod_unreg_security (MY_NAME, &capability_ops))
|
||||
printk (KERN_INFO "Failure unregistering capabilities "
|
||||
"with primary module.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (unregister_security (&capability_ops)) {
|
||||
printk (KERN_INFO
|
||||
"Failure unregistering capabilities with the kernel\n");
|
||||
}
|
||||
}
|
||||
|
||||
security_initcall (capability_init);
|
||||
module_exit (capability_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Standard Linux Capabilities Security Module");
|
||||
MODULE_LICENSE("GPL");
|
||||
414
extra/linux-2.6.10/security/commoncap.c
Normal file
414
extra/linux-2.6.10/security/commoncap.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/* Common capabilities, needed by capability.o and root_plug.o
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/hugetlb.h>
|
||||
|
||||
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
NETLINK_CB(skb).eff_cap = current->cap_effective;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(cap_netlink_send);
|
||||
|
||||
int cap_netlink_recv(struct sk_buff *skb)
|
||||
{
|
||||
if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(cap_netlink_recv);
|
||||
|
||||
int cap_capable (struct task_struct *tsk, int cap)
|
||||
{
|
||||
/* Derived from include/linux/sched.h:capable. */
|
||||
if (cap_raised(tsk->cap_effective, cap))
|
||||
return 0;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
int cap_settime(struct timespec *ts, struct timezone *tz)
|
||||
{
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cap_ptrace (struct task_struct *parent, struct task_struct *child)
|
||||
{
|
||||
/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
|
||||
if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
|
||||
!capable(CAP_SYS_PTRACE))
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cap_capget (struct task_struct *target, kernel_cap_t *effective,
|
||||
kernel_cap_t *inheritable, kernel_cap_t *permitted)
|
||||
{
|
||||
/* Derived from kernel/capability.c:sys_capget. */
|
||||
*effective = cap_t (target->cap_effective);
|
||||
*inheritable = cap_t (target->cap_inheritable);
|
||||
*permitted = cap_t (target->cap_permitted);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
|
||||
kernel_cap_t *inheritable, kernel_cap_t *permitted)
|
||||
{
|
||||
/* Derived from kernel/capability.c:sys_capset. */
|
||||
/* verify restrictions on target's new Inheritable set */
|
||||
if (!cap_issubset (*inheritable,
|
||||
cap_combine (target->cap_inheritable,
|
||||
current->cap_permitted))) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* verify restrictions on target's new Permitted set */
|
||||
if (!cap_issubset (*permitted,
|
||||
cap_combine (target->cap_permitted,
|
||||
current->cap_permitted))) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* verify the _new_Effective_ is a subset of the _new_Permitted_ */
|
||||
if (!cap_issubset (*effective, *permitted)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
|
||||
kernel_cap_t *inheritable, kernel_cap_t *permitted)
|
||||
{
|
||||
target->cap_effective = *effective;
|
||||
target->cap_inheritable = *inheritable;
|
||||
target->cap_permitted = *permitted;
|
||||
}
|
||||
|
||||
int cap_bprm_set_security (struct linux_binprm *bprm)
|
||||
{
|
||||
/* Copied from fs/exec.c:prepare_binprm. */
|
||||
|
||||
/* We don't have VFS support for capabilities yet */
|
||||
cap_clear (bprm->cap_inheritable);
|
||||
cap_clear (bprm->cap_permitted);
|
||||
cap_clear (bprm->cap_effective);
|
||||
|
||||
/* To support inheritance of root-permissions and suid-root
|
||||
* executables under compatibility mode, we raise all three
|
||||
* capability sets for the file.
|
||||
*
|
||||
* If only the real uid is 0, we only raise the inheritable
|
||||
* and permitted sets of the executable file.
|
||||
*/
|
||||
|
||||
if (!issecure (SECURE_NOROOT)) {
|
||||
if (bprm->e_uid == 0 || current->uid == 0) {
|
||||
cap_set_full (bprm->cap_inheritable);
|
||||
cap_set_full (bprm->cap_permitted);
|
||||
}
|
||||
if (bprm->e_uid == 0)
|
||||
cap_set_full (bprm->cap_effective);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
|
||||
{
|
||||
/* Derived from fs/exec.c:compute_creds. */
|
||||
kernel_cap_t new_permitted, working;
|
||||
|
||||
new_permitted = cap_intersect (bprm->cap_permitted, cap_bset);
|
||||
working = cap_intersect (bprm->cap_inheritable,
|
||||
current->cap_inheritable);
|
||||
new_permitted = cap_combine (new_permitted, working);
|
||||
|
||||
if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
|
||||
!cap_issubset (new_permitted, current->cap_permitted)) {
|
||||
current->mm->dumpable = 0;
|
||||
|
||||
if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
|
||||
if (!capable(CAP_SETUID)) {
|
||||
bprm->e_uid = current->uid;
|
||||
bprm->e_gid = current->gid;
|
||||
}
|
||||
if (!capable (CAP_SETPCAP)) {
|
||||
new_permitted = cap_intersect (new_permitted,
|
||||
current->cap_permitted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current->suid = current->euid = current->fsuid = bprm->e_uid;
|
||||
current->sgid = current->egid = current->fsgid = bprm->e_gid;
|
||||
|
||||
/* For init, we want to retain the capabilities set
|
||||
* in the init_task struct. Thus we skip the usual
|
||||
* capability rules */
|
||||
if (current->pid != 1) {
|
||||
current->cap_permitted = new_permitted;
|
||||
current->cap_effective =
|
||||
cap_intersect (new_permitted, bprm->cap_effective);
|
||||
}
|
||||
|
||||
/* AUD: Audit candidate if current->cap_effective is set */
|
||||
|
||||
current->keep_capabilities = 0;
|
||||
}
|
||||
|
||||
int cap_bprm_secureexec (struct linux_binprm *bprm)
|
||||
{
|
||||
/* If/when this module is enhanced to incorporate capability
|
||||
bits on files, the test below should be extended to also perform a
|
||||
test between the old and new capability sets. For now,
|
||||
it simply preserves the legacy decision algorithm used by
|
||||
the old userland. */
|
||||
return (current->euid != current->uid ||
|
||||
current->egid != current->gid);
|
||||
}
|
||||
|
||||
int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
||||
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
|
||||
!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cap_inode_removexattr(struct dentry *dentry, char *name)
|
||||
{
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
||||
sizeof(XATTR_SECURITY_PREFIX) - 1) &&
|
||||
!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* moved from kernel/sys.c. */
|
||||
/*
|
||||
* cap_emulate_setxuid() fixes the effective / permitted capabilities of
|
||||
* a process after a call to setuid, setreuid, or setresuid.
|
||||
*
|
||||
* 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
|
||||
* {r,e,s}uid != 0, the permitted and effective capabilities are
|
||||
* cleared.
|
||||
*
|
||||
* 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
|
||||
* capabilities of the process are cleared.
|
||||
*
|
||||
* 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
|
||||
* capabilities are set to the permitted capabilities.
|
||||
*
|
||||
* fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
|
||||
* never happen.
|
||||
*
|
||||
* -astor
|
||||
*
|
||||
* cevans - New behaviour, Oct '99
|
||||
* A process may, via prctl(), elect to keep its capabilities when it
|
||||
* calls setuid() and switches away from uid==0. Both permitted and
|
||||
* effective sets will be retained.
|
||||
* Without this change, it was impossible for a daemon to drop only some
|
||||
* of its privilege. The call to setuid(!=0) would drop all privileges!
|
||||
* Keeping uid 0 is not an option because uid 0 owns too many vital
|
||||
* files..
|
||||
* Thanks to Olaf Kirch and Peter Benie for spotting this.
|
||||
*/
|
||||
static inline void cap_emulate_setxuid (int old_ruid, int old_euid,
|
||||
int old_suid)
|
||||
{
|
||||
if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
|
||||
(current->uid != 0 && current->euid != 0 && current->suid != 0) &&
|
||||
!current->keep_capabilities) {
|
||||
cap_clear (current->cap_permitted);
|
||||
cap_clear (current->cap_effective);
|
||||
}
|
||||
if (old_euid == 0 && current->euid != 0) {
|
||||
cap_clear (current->cap_effective);
|
||||
}
|
||||
if (old_euid != 0 && current->euid == 0) {
|
||||
current->cap_effective = current->cap_permitted;
|
||||
}
|
||||
}
|
||||
|
||||
int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
|
||||
int flags)
|
||||
{
|
||||
switch (flags) {
|
||||
case LSM_SETID_RE:
|
||||
case LSM_SETID_ID:
|
||||
case LSM_SETID_RES:
|
||||
/* Copied from kernel/sys.c:setreuid/setuid/setresuid. */
|
||||
if (!issecure (SECURE_NO_SETUID_FIXUP)) {
|
||||
cap_emulate_setxuid (old_ruid, old_euid, old_suid);
|
||||
}
|
||||
break;
|
||||
case LSM_SETID_FS:
|
||||
{
|
||||
uid_t old_fsuid = old_ruid;
|
||||
|
||||
/* Copied from kernel/sys.c:setfsuid. */
|
||||
|
||||
/*
|
||||
* FIXME - is fsuser used for all CAP_FS_MASK capabilities?
|
||||
* if not, we might be a bit too harsh here.
|
||||
*/
|
||||
|
||||
if (!issecure (SECURE_NO_SETUID_FIXUP)) {
|
||||
if (old_fsuid == 0 && current->fsuid != 0) {
|
||||
cap_t (current->cap_effective) &=
|
||||
~CAP_FS_MASK;
|
||||
}
|
||||
if (old_fsuid != 0 && current->fsuid == 0) {
|
||||
cap_t (current->cap_effective) |=
|
||||
(cap_t (current->cap_permitted) &
|
||||
CAP_FS_MASK);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cap_task_reparent_to_init (struct task_struct *p)
|
||||
{
|
||||
p->cap_effective = CAP_INIT_EFF_SET;
|
||||
p->cap_inheritable = CAP_INIT_INH_SET;
|
||||
p->cap_permitted = CAP_FULL_SET;
|
||||
p->keep_capabilities = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int cap_syslog (int type)
|
||||
{
|
||||
if ((type != 3 && type != 10) && !capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that a process has enough memory to allocate a new virtual
|
||||
* mapping. 0 means there is enough memory for the allocation to
|
||||
* succeed and -ENOMEM implies there is not.
|
||||
*
|
||||
* We currently support three overcommit policies, which are set via the
|
||||
* vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting
|
||||
*
|
||||
* Strict overcommit modes added 2002 Feb 26 by Alan Cox.
|
||||
* Additional code 2002 Jul 20 by Robert Love.
|
||||
*/
|
||||
int cap_vm_enough_memory(long pages)
|
||||
{
|
||||
unsigned long free, allowed;
|
||||
|
||||
vm_acct_memory(pages);
|
||||
|
||||
/*
|
||||
* Sometimes we want to use more memory than we have
|
||||
*/
|
||||
if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
|
||||
return 0;
|
||||
|
||||
if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
|
||||
unsigned long n;
|
||||
|
||||
free = get_page_cache_size();
|
||||
free += nr_swap_pages;
|
||||
|
||||
/*
|
||||
* Any slabs which are created with the
|
||||
* SLAB_RECLAIM_ACCOUNT flag claim to have contents
|
||||
* which are reclaimable, under pressure. The dentry
|
||||
* cache and most inode caches should fall into this
|
||||
*/
|
||||
free += atomic_read(&slab_reclaim_pages);
|
||||
|
||||
/*
|
||||
* Leave the last 3% for root
|
||||
*/
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
free -= free / 32;
|
||||
|
||||
if (free > pages)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* nr_free_pages() is very expensive on large systems,
|
||||
* only call if we're about to fail.
|
||||
*/
|
||||
n = nr_free_pages();
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
n -= n / 32;
|
||||
free += n;
|
||||
|
||||
if (free > pages)
|
||||
return 0;
|
||||
vm_unacct_memory(pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
allowed = (totalram_pages - hugetlb_total_pages())
|
||||
* sysctl_overcommit_ratio / 100;
|
||||
/*
|
||||
* Leave the last 3% for root
|
||||
*/
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
allowed -= allowed / 32;
|
||||
allowed += total_swap_pages;
|
||||
|
||||
if (atomic_read(&vm_committed_space) < allowed)
|
||||
return 0;
|
||||
|
||||
vm_unacct_memory(pages);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(cap_capable);
|
||||
EXPORT_SYMBOL(cap_settime);
|
||||
EXPORT_SYMBOL(cap_ptrace);
|
||||
EXPORT_SYMBOL(cap_capget);
|
||||
EXPORT_SYMBOL(cap_capset_check);
|
||||
EXPORT_SYMBOL(cap_capset_set);
|
||||
EXPORT_SYMBOL(cap_bprm_set_security);
|
||||
EXPORT_SYMBOL(cap_bprm_apply_creds);
|
||||
EXPORT_SYMBOL(cap_bprm_secureexec);
|
||||
EXPORT_SYMBOL(cap_inode_setxattr);
|
||||
EXPORT_SYMBOL(cap_inode_removexattr);
|
||||
EXPORT_SYMBOL(cap_task_post_setuid);
|
||||
EXPORT_SYMBOL(cap_task_reparent_to_init);
|
||||
EXPORT_SYMBOL(cap_syslog);
|
||||
EXPORT_SYMBOL(cap_vm_enough_memory);
|
||||
|
||||
MODULE_DESCRIPTION("Standard Linux Common Capabilities Security Module");
|
||||
MODULE_LICENSE("GPL");
|
||||
BIN
extra/linux-2.6.10/security/commoncap.o
Normal file
BIN
extra/linux-2.6.10/security/commoncap.o
Normal file
Binary file not shown.
1038
extra/linux-2.6.10/security/dummy.c
Normal file
1038
extra/linux-2.6.10/security/dummy.c
Normal file
File diff suppressed because it is too large
Load Diff
14
extra/linux-2.6.10/security/keys/Makefile
Normal file
14
extra/linux-2.6.10/security/keys/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Makefile for key management
|
||||
#
|
||||
|
||||
obj-y := \
|
||||
key.o \
|
||||
keyring.o \
|
||||
keyctl.o \
|
||||
process_keys.o \
|
||||
user_defined.o \
|
||||
request_key.o
|
||||
|
||||
obj-$(CONFIG_KEYS_COMPAT) += compat.o
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
78
extra/linux-2.6.10/security/keys/compat.c
Normal file
78
extra/linux-2.6.10/security/keys/compat.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/* compat.c: 32-bit compatibility syscall for 64-bit systems
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/keyctl.h>
|
||||
#include <linux/compat.h>
|
||||
#include "internal.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* the key control system call, 32-bit compatibility version for 64-bit archs
|
||||
* - this should only be called if the 64-bit arch uses weird pointers in
|
||||
* 32-bit mode or doesn't guarantee that the top 32-bits of the argument
|
||||
* registers on taking a 32-bit syscall are zero
|
||||
* - if you can, you should call sys_keyctl directly
|
||||
*/
|
||||
asmlinkage long compat_sys_keyctl(u32 option,
|
||||
u32 arg2, u32 arg3, u32 arg4, u32 arg5)
|
||||
{
|
||||
switch (option) {
|
||||
case KEYCTL_GET_KEYRING_ID:
|
||||
return keyctl_get_keyring_ID(arg2, arg3);
|
||||
|
||||
case KEYCTL_JOIN_SESSION_KEYRING:
|
||||
return keyctl_join_session_keyring(compat_ptr(arg3));
|
||||
|
||||
case KEYCTL_UPDATE:
|
||||
return keyctl_update_key(arg2, compat_ptr(arg3), arg4);
|
||||
|
||||
case KEYCTL_REVOKE:
|
||||
return keyctl_revoke_key(arg2);
|
||||
|
||||
case KEYCTL_DESCRIBE:
|
||||
return keyctl_describe_key(arg2, compat_ptr(arg3), arg4);
|
||||
|
||||
case KEYCTL_CLEAR:
|
||||
return keyctl_keyring_clear(arg2);
|
||||
|
||||
case KEYCTL_LINK:
|
||||
return keyctl_keyring_link(arg2, arg3);
|
||||
|
||||
case KEYCTL_UNLINK:
|
||||
return keyctl_keyring_unlink(arg2, arg3);
|
||||
|
||||
case KEYCTL_SEARCH:
|
||||
return keyctl_keyring_search(arg2, compat_ptr(arg3),
|
||||
compat_ptr(arg4), arg5);
|
||||
|
||||
case KEYCTL_READ:
|
||||
return keyctl_read_key(arg2, compat_ptr(arg3), arg4);
|
||||
|
||||
case KEYCTL_CHOWN:
|
||||
return keyctl_chown_key(arg2, arg3, arg4);
|
||||
|
||||
case KEYCTL_SETPERM:
|
||||
return keyctl_setperm_key(arg2, arg3);
|
||||
|
||||
case KEYCTL_INSTANTIATE:
|
||||
return keyctl_instantiate_key(arg2, compat_ptr(arg3), arg4,
|
||||
arg5);
|
||||
|
||||
case KEYCTL_NEGATE:
|
||||
return keyctl_negate_key(arg2, arg3, arg4);
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
} /* end compat_sys_keyctl() */
|
||||
123
extra/linux-2.6.10/security/keys/internal.h
Normal file
123
extra/linux-2.6.10/security/keys/internal.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/* internal.h: authentication token and access key management internal defs
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _INTERNAL_H
|
||||
#define _INTERNAL_H
|
||||
|
||||
#include <linux/key.h>
|
||||
#include <linux/key-ui.h>
|
||||
|
||||
extern struct key_type key_type_dead;
|
||||
extern struct key_type key_type_user;
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* keep track of keys for a user
|
||||
* - this needs to be separate to user_struct to avoid a refcount-loop
|
||||
* (user_struct pins some keyrings which pin this struct)
|
||||
* - this also keeps track of keys under request from userspace for this UID
|
||||
*/
|
||||
struct key_user {
|
||||
struct rb_node node;
|
||||
struct list_head consq; /* construction queue */
|
||||
spinlock_t lock;
|
||||
atomic_t usage; /* for accessing qnkeys & qnbytes */
|
||||
atomic_t nkeys; /* number of keys */
|
||||
atomic_t nikeys; /* number of instantiated keys */
|
||||
uid_t uid;
|
||||
int qnkeys; /* number of keys allocated to this user */
|
||||
int qnbytes; /* number of bytes allocated to this user */
|
||||
};
|
||||
|
||||
#define KEYQUOTA_MAX_KEYS 100
|
||||
#define KEYQUOTA_MAX_BYTES 10000
|
||||
#define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */
|
||||
|
||||
extern struct rb_root key_user_tree;
|
||||
extern spinlock_t key_user_lock;
|
||||
extern struct key_user root_key_user;
|
||||
|
||||
extern struct key_user *key_user_lookup(uid_t uid);
|
||||
extern void key_user_put(struct key_user *user);
|
||||
|
||||
|
||||
|
||||
extern struct rb_root key_serial_tree;
|
||||
extern spinlock_t key_serial_lock;
|
||||
extern struct semaphore key_alloc_sem;
|
||||
extern struct rw_semaphore key_construction_sem;
|
||||
extern wait_queue_head_t request_key_conswq;
|
||||
|
||||
|
||||
extern void keyring_publish_name(struct key *keyring);
|
||||
|
||||
extern int __key_link(struct key *keyring, struct key *key);
|
||||
|
||||
extern struct key *__keyring_search_one(struct key *keyring,
|
||||
const struct key_type *type,
|
||||
const char *description,
|
||||
key_perm_t perm);
|
||||
|
||||
typedef int (*key_match_func_t)(const struct key *, const void *);
|
||||
|
||||
extern struct key *keyring_search_aux(struct key *keyring,
|
||||
struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match);
|
||||
|
||||
extern struct key *search_process_keyrings_aux(struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match);
|
||||
|
||||
extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
|
||||
|
||||
extern int install_thread_keyring(struct task_struct *tsk);
|
||||
|
||||
/*
|
||||
* keyctl functions
|
||||
*/
|
||||
extern long keyctl_get_keyring_ID(key_serial_t, int);
|
||||
extern long keyctl_join_session_keyring(const char __user *);
|
||||
extern long keyctl_update_key(key_serial_t, const void __user *, size_t);
|
||||
extern long keyctl_revoke_key(key_serial_t);
|
||||
extern long keyctl_keyring_clear(key_serial_t);
|
||||
extern long keyctl_keyring_link(key_serial_t, key_serial_t);
|
||||
extern long keyctl_keyring_unlink(key_serial_t, key_serial_t);
|
||||
extern long keyctl_describe_key(key_serial_t, char __user *, size_t);
|
||||
extern long keyctl_keyring_search(key_serial_t, const char __user *,
|
||||
const char __user *, key_serial_t);
|
||||
extern long keyctl_read_key(key_serial_t, char __user *, size_t);
|
||||
extern long keyctl_chown_key(key_serial_t, uid_t, gid_t);
|
||||
extern long keyctl_setperm_key(key_serial_t, key_perm_t);
|
||||
extern long keyctl_instantiate_key(key_serial_t, const void __user *,
|
||||
size_t, key_serial_t);
|
||||
extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
|
||||
|
||||
|
||||
/*
|
||||
* debugging key validation
|
||||
*/
|
||||
#ifdef KEY_DEBUGGING
|
||||
extern void __key_check(const struct key *);
|
||||
|
||||
static inline void key_check(const struct key *key)
|
||||
{
|
||||
if (key && (IS_ERR(key) || key->magic != KEY_DEBUG_MAGIC))
|
||||
__key_check(key);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define key_check(key) do {} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _INTERNAL_H */
|
||||
1039
extra/linux-2.6.10/security/keys/key.c
Normal file
1039
extra/linux-2.6.10/security/keys/key.c
Normal file
File diff suppressed because it is too large
Load Diff
987
extra/linux-2.6.10/security/keys/keyctl.c
Normal file
987
extra/linux-2.6.10/security/keys/keyctl.c
Normal file
@@ -0,0 +1,987 @@
|
||||
/* keyctl.c: userspace keyctl operations
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/keyctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* extract the description of a new key from userspace and either add it as a
|
||||
* new key to the specified keyring or update a matching key in that keyring
|
||||
* - the keyring must be writable
|
||||
* - returns the new key's serial number
|
||||
* - implements add_key()
|
||||
*/
|
||||
asmlinkage long sys_add_key(const char __user *_type,
|
||||
const char __user *_description,
|
||||
const void __user *_payload,
|
||||
size_t plen,
|
||||
key_serial_t ringid)
|
||||
{
|
||||
struct key *keyring, *key;
|
||||
char type[32], *description;
|
||||
void *payload;
|
||||
long dlen, ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (plen > 32767)
|
||||
goto error;
|
||||
|
||||
/* draw all the data into kernel space */
|
||||
ret = strncpy_from_user(type, _type, sizeof(type) - 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
type[31] = '\0';
|
||||
|
||||
ret = -EFAULT;
|
||||
dlen = strnlen_user(_description, PAGE_SIZE - 1);
|
||||
if (dlen <= 0)
|
||||
goto error;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (dlen > PAGE_SIZE - 1)
|
||||
goto error;
|
||||
|
||||
ret = -ENOMEM;
|
||||
description = kmalloc(dlen + 1, GFP_KERNEL);
|
||||
if (!description)
|
||||
goto error;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(description, _description, dlen + 1) != 0)
|
||||
goto error2;
|
||||
|
||||
/* pull the payload in if one was supplied */
|
||||
payload = NULL;
|
||||
|
||||
if (_payload) {
|
||||
ret = -ENOMEM;
|
||||
payload = kmalloc(plen, GFP_KERNEL);
|
||||
if (!payload)
|
||||
goto error2;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(payload, _payload, plen) != 0)
|
||||
goto error3;
|
||||
}
|
||||
|
||||
/* find the target keyring (which must be writable) */
|
||||
keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error3;
|
||||
}
|
||||
|
||||
/* create or update the requested key and add it to the target
|
||||
* keyring */
|
||||
key = key_create_or_update(keyring, type, description,
|
||||
payload, plen, 0);
|
||||
if (!IS_ERR(key)) {
|
||||
ret = key->serial;
|
||||
key_put(key);
|
||||
}
|
||||
else {
|
||||
ret = PTR_ERR(key);
|
||||
}
|
||||
|
||||
key_put(keyring);
|
||||
error3:
|
||||
kfree(payload);
|
||||
error2:
|
||||
kfree(description);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end sys_add_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the process keyrings for a matching key
|
||||
* - nested keyrings may also be searched if they have Search permission
|
||||
* - if a key is found, it will be attached to the destination keyring if
|
||||
* there's one specified
|
||||
* - /sbin/request-key will be invoked if _callout_info is non-NULL
|
||||
* - the _callout_info string will be passed to /sbin/request-key
|
||||
* - if the _callout_info string is empty, it will be rendered as "-"
|
||||
* - implements request_key()
|
||||
*/
|
||||
asmlinkage long sys_request_key(const char __user *_type,
|
||||
const char __user *_description,
|
||||
const char __user *_callout_info,
|
||||
key_serial_t destringid)
|
||||
{
|
||||
struct key_type *ktype;
|
||||
struct key *key, *dest;
|
||||
char type[32], *description, *callout_info;
|
||||
long dlen, ret;
|
||||
|
||||
/* pull the type into kernel space */
|
||||
ret = strncpy_from_user(type, _type, sizeof(type) - 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
type[31] = '\0';
|
||||
|
||||
/* pull the description into kernel space */
|
||||
ret = -EFAULT;
|
||||
dlen = strnlen_user(_description, PAGE_SIZE - 1);
|
||||
if (dlen <= 0)
|
||||
goto error;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (dlen > PAGE_SIZE - 1)
|
||||
goto error;
|
||||
|
||||
ret = -ENOMEM;
|
||||
description = kmalloc(dlen + 1, GFP_KERNEL);
|
||||
if (!description)
|
||||
goto error;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(description, _description, dlen + 1) != 0)
|
||||
goto error2;
|
||||
|
||||
/* pull the callout info into kernel space */
|
||||
callout_info = NULL;
|
||||
if (_callout_info) {
|
||||
ret = -EFAULT;
|
||||
dlen = strnlen_user(_callout_info, PAGE_SIZE - 1);
|
||||
if (dlen <= 0)
|
||||
goto error2;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (dlen > PAGE_SIZE - 1)
|
||||
goto error2;
|
||||
|
||||
ret = -ENOMEM;
|
||||
callout_info = kmalloc(dlen + 1, GFP_KERNEL);
|
||||
if (!callout_info)
|
||||
goto error2;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(callout_info, _callout_info, dlen + 1) != 0)
|
||||
goto error3;
|
||||
}
|
||||
|
||||
/* get the destination keyring if specified */
|
||||
dest = NULL;
|
||||
if (destringid) {
|
||||
dest = lookup_user_key(destringid, 1, 0, KEY_WRITE);
|
||||
if (IS_ERR(dest)) {
|
||||
ret = PTR_ERR(dest);
|
||||
goto error3;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the key type */
|
||||
ktype = key_type_lookup(type);
|
||||
if (IS_ERR(ktype)) {
|
||||
ret = PTR_ERR(ktype);
|
||||
goto error4;
|
||||
}
|
||||
|
||||
/* do the search */
|
||||
key = request_key(ktype, description, callout_info);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error5;
|
||||
}
|
||||
|
||||
/* link the resulting key to the destination keyring */
|
||||
if (dest) {
|
||||
ret = key_link(dest, key);
|
||||
if (ret < 0)
|
||||
goto error6;
|
||||
}
|
||||
|
||||
ret = key->serial;
|
||||
|
||||
error6:
|
||||
key_put(key);
|
||||
error5:
|
||||
key_type_put(ktype);
|
||||
error4:
|
||||
key_put(dest);
|
||||
error3:
|
||||
kfree(callout_info);
|
||||
error2:
|
||||
kfree(description);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end sys_request_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* get the ID of the specified process keyring
|
||||
* - the keyring must have search permission to be found
|
||||
* - implements keyctl(KEYCTL_GET_KEYRING_ID)
|
||||
*/
|
||||
long keyctl_get_keyring_ID(key_serial_t id, int create)
|
||||
{
|
||||
struct key *key;
|
||||
long ret;
|
||||
|
||||
key = lookup_user_key(id, create, 0, KEY_SEARCH);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = key->serial;
|
||||
key_put(key);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_get_keyring_ID() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* join the session keyring
|
||||
* - implements keyctl(KEYCTL_JOIN_SESSION_KEYRING)
|
||||
*/
|
||||
long keyctl_join_session_keyring(const char __user *_name)
|
||||
{
|
||||
char *name;
|
||||
long nlen, ret;
|
||||
|
||||
/* fetch the name from userspace */
|
||||
name = NULL;
|
||||
if (_name) {
|
||||
ret = -EFAULT;
|
||||
nlen = strnlen_user(_name, PAGE_SIZE - 1);
|
||||
if (nlen <= 0)
|
||||
goto error;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (nlen > PAGE_SIZE - 1)
|
||||
goto error;
|
||||
|
||||
ret = -ENOMEM;
|
||||
name = kmalloc(nlen + 1, GFP_KERNEL);
|
||||
if (!name)
|
||||
goto error;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(name, _name, nlen + 1) != 0)
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* join the session */
|
||||
ret = join_session_keyring(name);
|
||||
|
||||
error2:
|
||||
kfree(name);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_join_session_keyring() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* update a key's data payload
|
||||
* - the key must be writable
|
||||
* - implements keyctl(KEYCTL_UPDATE)
|
||||
*/
|
||||
long keyctl_update_key(key_serial_t id,
|
||||
const void __user *_payload,
|
||||
size_t plen)
|
||||
{
|
||||
struct key *key;
|
||||
void *payload;
|
||||
long ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (plen > PAGE_SIZE)
|
||||
goto error;
|
||||
|
||||
/* pull the payload in if one was supplied */
|
||||
payload = NULL;
|
||||
if (_payload) {
|
||||
ret = -ENOMEM;
|
||||
payload = kmalloc(plen, GFP_KERNEL);
|
||||
if (!payload)
|
||||
goto error;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(payload, _payload, plen) != 0)
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* find the target key (which must be writable) */
|
||||
key = lookup_user_key(id, 0, 0, KEY_WRITE);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* update the key */
|
||||
ret = key_update(key, payload, plen);
|
||||
|
||||
key_put(key);
|
||||
error2:
|
||||
kfree(payload);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_update_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* revoke a key
|
||||
* - the key must be writable
|
||||
* - implements keyctl(KEYCTL_REVOKE)
|
||||
*/
|
||||
long keyctl_revoke_key(key_serial_t id)
|
||||
{
|
||||
struct key *key;
|
||||
long ret;
|
||||
|
||||
key = lookup_user_key(id, 0, 0, KEY_WRITE);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
key_revoke(key);
|
||||
ret = 0;
|
||||
|
||||
key_put(key);
|
||||
error:
|
||||
return 0;
|
||||
|
||||
} /* end keyctl_revoke_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* clear the specified process keyring
|
||||
* - the keyring must be writable
|
||||
* - implements keyctl(KEYCTL_CLEAR)
|
||||
*/
|
||||
long keyctl_keyring_clear(key_serial_t ringid)
|
||||
{
|
||||
struct key *keyring;
|
||||
long ret;
|
||||
|
||||
keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = keyring_clear(keyring);
|
||||
|
||||
key_put(keyring);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_keyring_clear() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* link a key into a keyring
|
||||
* - the keyring must be writable
|
||||
* - the key must be linkable
|
||||
* - implements keyctl(KEYCTL_LINK)
|
||||
*/
|
||||
long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
|
||||
{
|
||||
struct key *keyring, *key;
|
||||
long ret;
|
||||
|
||||
keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error;
|
||||
}
|
||||
|
||||
key = lookup_user_key(id, 1, 0, KEY_LINK);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error2;
|
||||
}
|
||||
|
||||
ret = key_link(keyring, key);
|
||||
|
||||
key_put(key);
|
||||
error2:
|
||||
key_put(keyring);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_keyring_link() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* unlink the first attachment of a key from a keyring
|
||||
* - the keyring must be writable
|
||||
* - we don't need any permissions on the key
|
||||
* - implements keyctl(KEYCTL_UNLINK)
|
||||
*/
|
||||
long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
|
||||
{
|
||||
struct key *keyring, *key;
|
||||
long ret;
|
||||
|
||||
keyring = lookup_user_key(ringid, 0, 0, KEY_WRITE);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error;
|
||||
}
|
||||
|
||||
key = lookup_user_key(id, 0, 0, 0);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error2;
|
||||
}
|
||||
|
||||
ret = key_unlink(keyring, key);
|
||||
|
||||
key_put(key);
|
||||
error2:
|
||||
key_put(keyring);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_keyring_unlink() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* describe a user key
|
||||
* - the key must have view permission
|
||||
* - if there's a buffer, we place up to buflen bytes of data into it
|
||||
* - unless there's an error, we return the amount of description available,
|
||||
* irrespective of how much we may have copied
|
||||
* - the description is formatted thus:
|
||||
* type;uid;gid;perm;description<NUL>
|
||||
* - implements keyctl(KEYCTL_DESCRIBE)
|
||||
*/
|
||||
long keyctl_describe_key(key_serial_t keyid,
|
||||
char __user *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
struct key *key;
|
||||
char *tmpbuf;
|
||||
long ret;
|
||||
|
||||
key = lookup_user_key(keyid, 0, 1, KEY_VIEW);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* calculate how much description we're going to return */
|
||||
ret = -ENOMEM;
|
||||
tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!tmpbuf)
|
||||
goto error2;
|
||||
|
||||
ret = snprintf(tmpbuf, PAGE_SIZE - 1,
|
||||
"%s;%d;%d;%06x;%s",
|
||||
key->type->name,
|
||||
key->uid,
|
||||
key->gid,
|
||||
key->perm,
|
||||
key->description ? key->description :""
|
||||
);
|
||||
|
||||
/* include a NUL char at the end of the data */
|
||||
if (ret > PAGE_SIZE - 1)
|
||||
ret = PAGE_SIZE - 1;
|
||||
tmpbuf[ret] = 0;
|
||||
ret++;
|
||||
|
||||
/* consider returning the data */
|
||||
if (buffer && buflen > 0) {
|
||||
if (buflen > ret)
|
||||
buflen = ret;
|
||||
|
||||
if (copy_to_user(buffer, tmpbuf, buflen) != 0)
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
kfree(tmpbuf);
|
||||
error2:
|
||||
key_put(key);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_describe_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the specified keyring for a matching key
|
||||
* - the start keyring must be searchable
|
||||
* - nested keyrings may also be searched if they are searchable
|
||||
* - only keys with search permission may be found
|
||||
* - if a key is found, it will be attached to the destination keyring if
|
||||
* there's one specified
|
||||
* - implements keyctl(KEYCTL_SEARCH)
|
||||
*/
|
||||
long keyctl_keyring_search(key_serial_t ringid,
|
||||
const char __user *_type,
|
||||
const char __user *_description,
|
||||
key_serial_t destringid)
|
||||
{
|
||||
struct key_type *ktype;
|
||||
struct key *keyring, *key, *dest;
|
||||
char type[32], *description;
|
||||
long dlen, ret;
|
||||
|
||||
/* pull the type and description into kernel space */
|
||||
ret = strncpy_from_user(type, _type, sizeof(type) - 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
type[31] = '\0';
|
||||
|
||||
ret = -EFAULT;
|
||||
dlen = strnlen_user(_description, PAGE_SIZE - 1);
|
||||
if (dlen <= 0)
|
||||
goto error;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (dlen > PAGE_SIZE - 1)
|
||||
goto error;
|
||||
|
||||
ret = -ENOMEM;
|
||||
description = kmalloc(dlen + 1, GFP_KERNEL);
|
||||
if (!description)
|
||||
goto error;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(description, _description, dlen + 1) != 0)
|
||||
goto error2;
|
||||
|
||||
/* get the keyring at which to begin the search */
|
||||
keyring = lookup_user_key(ringid, 0, 0, KEY_SEARCH);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* get the destination keyring if specified */
|
||||
dest = NULL;
|
||||
if (destringid) {
|
||||
dest = lookup_user_key(destringid, 1, 0, KEY_WRITE);
|
||||
if (IS_ERR(dest)) {
|
||||
ret = PTR_ERR(dest);
|
||||
goto error3;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the key type */
|
||||
ktype = key_type_lookup(type);
|
||||
if (IS_ERR(ktype)) {
|
||||
ret = PTR_ERR(ktype);
|
||||
goto error4;
|
||||
}
|
||||
|
||||
/* do the search */
|
||||
key = keyring_search(keyring, ktype, description);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
|
||||
/* treat lack or presence of a negative key the same */
|
||||
if (ret == -EAGAIN)
|
||||
ret = -ENOKEY;
|
||||
goto error5;
|
||||
}
|
||||
|
||||
/* link the resulting key to the destination keyring if we can */
|
||||
if (dest) {
|
||||
ret = -EACCES;
|
||||
if (!key_permission(key, KEY_LINK))
|
||||
goto error6;
|
||||
|
||||
ret = key_link(dest, key);
|
||||
if (ret < 0)
|
||||
goto error6;
|
||||
}
|
||||
|
||||
ret = key->serial;
|
||||
|
||||
error6:
|
||||
key_put(key);
|
||||
error5:
|
||||
key_type_put(ktype);
|
||||
error4:
|
||||
key_put(dest);
|
||||
error3:
|
||||
key_put(keyring);
|
||||
error2:
|
||||
kfree(description);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_keyring_search() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* see if the key we're looking at is the target key
|
||||
*/
|
||||
static int keyctl_read_key_same(const struct key *key, const void *target)
|
||||
{
|
||||
return key == target;
|
||||
|
||||
} /* end keyctl_read_key_same() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* read a user key's payload
|
||||
* - the keyring must be readable or the key must be searchable from the
|
||||
* process's keyrings
|
||||
* - if there's a buffer, we place up to buflen bytes of data into it
|
||||
* - unless there's an error, we return the amount of data in the key,
|
||||
* irrespective of how much we may have copied
|
||||
* - implements keyctl(KEYCTL_READ)
|
||||
*/
|
||||
long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
|
||||
{
|
||||
struct key *key, *skey;
|
||||
long ret;
|
||||
|
||||
/* find the key first */
|
||||
key = lookup_user_key(keyid, 0, 0, 0);
|
||||
if (!IS_ERR(key)) {
|
||||
/* see if we can read it directly */
|
||||
if (key_permission(key, KEY_READ))
|
||||
goto can_read_key;
|
||||
|
||||
/* can't; see if it's searchable from this process's
|
||||
* keyrings */
|
||||
ret = -ENOKEY;
|
||||
if (key_permission(key, KEY_SEARCH)) {
|
||||
/* okay - we do have search permission on the key
|
||||
* itself, but do we have the key? */
|
||||
skey = search_process_keyrings_aux(key->type, key,
|
||||
keyctl_read_key_same);
|
||||
if (!IS_ERR(skey))
|
||||
goto can_read_key2;
|
||||
}
|
||||
|
||||
goto error2;
|
||||
}
|
||||
|
||||
ret = -ENOKEY;
|
||||
goto error;
|
||||
|
||||
/* the key is probably readable - now try to read it */
|
||||
can_read_key2:
|
||||
key_put(skey);
|
||||
can_read_key:
|
||||
ret = key_validate(key);
|
||||
if (ret == 0) {
|
||||
ret = -EOPNOTSUPP;
|
||||
if (key->type->read) {
|
||||
/* read the data with the semaphore held (since we
|
||||
* might sleep) */
|
||||
down_read(&key->sem);
|
||||
ret = key->type->read(key, buffer, buflen);
|
||||
up_read(&key->sem);
|
||||
}
|
||||
}
|
||||
|
||||
error2:
|
||||
key_put(key);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_read_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* change the ownership of a key
|
||||
* - the keyring owned by the changer
|
||||
* - if the uid or gid is -1, then that parameter is not changed
|
||||
* - implements keyctl(KEYCTL_CHOWN)
|
||||
*/
|
||||
long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
|
||||
{
|
||||
struct key *key;
|
||||
long ret;
|
||||
|
||||
ret = 0;
|
||||
if (uid == (uid_t) -1 && gid == (gid_t) -1)
|
||||
goto error;
|
||||
|
||||
key = lookup_user_key(id, 1, 1, 0);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* make the changes with the locks held to prevent chown/chown races */
|
||||
ret = -EACCES;
|
||||
down_write(&key->sem);
|
||||
write_lock(&key->lock);
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
/* only the sysadmin can chown a key to some other UID */
|
||||
if (uid != (uid_t) -1 && key->uid != uid)
|
||||
goto no_access;
|
||||
|
||||
/* only the sysadmin can set the key's GID to a group other
|
||||
* than one of those that the current process subscribes to */
|
||||
if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
|
||||
goto no_access;
|
||||
}
|
||||
|
||||
/* change the UID (have to update the quotas) */
|
||||
if (uid != (uid_t) -1 && uid != key->uid) {
|
||||
/* don't support UID changing yet */
|
||||
ret = -EOPNOTSUPP;
|
||||
goto no_access;
|
||||
}
|
||||
|
||||
/* change the GID */
|
||||
if (gid != (gid_t) -1)
|
||||
key->gid = gid;
|
||||
|
||||
ret = 0;
|
||||
|
||||
no_access:
|
||||
write_unlock(&key->lock);
|
||||
up_write(&key->sem);
|
||||
key_put(key);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_chown_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* change the permission mask on a key
|
||||
* - the keyring owned by the changer
|
||||
* - implements keyctl(KEYCTL_SETPERM)
|
||||
*/
|
||||
long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
|
||||
{
|
||||
struct key *key;
|
||||
long ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
|
||||
goto error;
|
||||
|
||||
key = lookup_user_key(id, 1, 1, 0);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* make the changes with the locks held to prevent chown/chmod
|
||||
* races */
|
||||
ret = -EACCES;
|
||||
down_write(&key->sem);
|
||||
write_lock(&key->lock);
|
||||
|
||||
/* if we're not the sysadmin, we can only chmod a key that we
|
||||
* own */
|
||||
if (!capable(CAP_SYS_ADMIN) && key->uid != current->fsuid)
|
||||
goto no_access;
|
||||
|
||||
/* changing the permissions mask */
|
||||
key->perm = perm;
|
||||
ret = 0;
|
||||
|
||||
no_access:
|
||||
write_unlock(&key->lock);
|
||||
up_write(&key->sem);
|
||||
key_put(key);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_setperm_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* instantiate the key with the specified payload, and, if one is given, link
|
||||
* the key into the keyring
|
||||
*/
|
||||
long keyctl_instantiate_key(key_serial_t id,
|
||||
const void __user *_payload,
|
||||
size_t plen,
|
||||
key_serial_t ringid)
|
||||
{
|
||||
struct key *key, *keyring;
|
||||
void *payload;
|
||||
long ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (plen > 32767)
|
||||
goto error;
|
||||
|
||||
/* pull the payload in if one was supplied */
|
||||
payload = NULL;
|
||||
|
||||
if (_payload) {
|
||||
ret = -ENOMEM;
|
||||
payload = kmalloc(plen, GFP_KERNEL);
|
||||
if (!payload)
|
||||
goto error;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_from_user(payload, _payload, plen) != 0)
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* find the target key (which must be writable) */
|
||||
key = lookup_user_key(id, 0, 1, KEY_WRITE);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* find the destination keyring if present (which must also be
|
||||
* writable) */
|
||||
keyring = NULL;
|
||||
if (ringid) {
|
||||
keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error3;
|
||||
}
|
||||
}
|
||||
|
||||
/* instantiate the key and link it into a keyring */
|
||||
ret = key_instantiate_and_link(key, payload, plen, keyring);
|
||||
|
||||
key_put(keyring);
|
||||
error3:
|
||||
key_put(key);
|
||||
error2:
|
||||
kfree(payload);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_instantiate_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* negatively instantiate the key with the given timeout (in seconds), and, if
|
||||
* one is given, link the key into the keyring
|
||||
*/
|
||||
long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
|
||||
{
|
||||
struct key *key, *keyring;
|
||||
long ret;
|
||||
|
||||
/* find the target key (which must be writable) */
|
||||
key = lookup_user_key(id, 0, 1, KEY_WRITE);
|
||||
if (IS_ERR(key)) {
|
||||
ret = PTR_ERR(key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* find the destination keyring if present (which must also be
|
||||
* writable) */
|
||||
keyring = NULL;
|
||||
if (ringid) {
|
||||
keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error2;
|
||||
}
|
||||
}
|
||||
|
||||
/* instantiate the key and link it into a keyring */
|
||||
ret = key_negate_and_link(key, timeout, keyring);
|
||||
|
||||
key_put(keyring);
|
||||
error2:
|
||||
key_put(key);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyctl_negate_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* the key control system call
|
||||
*/
|
||||
asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
switch (option) {
|
||||
case KEYCTL_GET_KEYRING_ID:
|
||||
return keyctl_get_keyring_ID((key_serial_t) arg2,
|
||||
(int) arg3);
|
||||
|
||||
case KEYCTL_JOIN_SESSION_KEYRING:
|
||||
return keyctl_join_session_keyring((const char __user *) arg3);
|
||||
|
||||
case KEYCTL_UPDATE:
|
||||
return keyctl_update_key((key_serial_t) arg2,
|
||||
(const void __user *) arg3,
|
||||
(size_t) arg4);
|
||||
|
||||
case KEYCTL_REVOKE:
|
||||
return keyctl_revoke_key((key_serial_t) arg2);
|
||||
|
||||
case KEYCTL_DESCRIBE:
|
||||
return keyctl_describe_key((key_serial_t) arg2,
|
||||
(char __user *) arg3,
|
||||
(unsigned) arg4);
|
||||
|
||||
case KEYCTL_CLEAR:
|
||||
return keyctl_keyring_clear((key_serial_t) arg2);
|
||||
|
||||
case KEYCTL_LINK:
|
||||
return keyctl_keyring_link((key_serial_t) arg2,
|
||||
(key_serial_t) arg3);
|
||||
|
||||
case KEYCTL_UNLINK:
|
||||
return keyctl_keyring_unlink((key_serial_t) arg2,
|
||||
(key_serial_t) arg3);
|
||||
|
||||
case KEYCTL_SEARCH:
|
||||
return keyctl_keyring_search((key_serial_t) arg2,
|
||||
(const char __user *) arg3,
|
||||
(const char __user *) arg4,
|
||||
(key_serial_t) arg5);
|
||||
|
||||
case KEYCTL_READ:
|
||||
return keyctl_read_key((key_serial_t) arg2,
|
||||
(char __user *) arg3,
|
||||
(size_t) arg4);
|
||||
|
||||
case KEYCTL_CHOWN:
|
||||
return keyctl_chown_key((key_serial_t) arg2,
|
||||
(uid_t) arg3,
|
||||
(gid_t) arg4);
|
||||
|
||||
case KEYCTL_SETPERM:
|
||||
return keyctl_setperm_key((key_serial_t) arg2,
|
||||
(key_perm_t) arg3);
|
||||
|
||||
case KEYCTL_INSTANTIATE:
|
||||
return keyctl_instantiate_key((key_serial_t) arg2,
|
||||
(const void __user *) arg3,
|
||||
(size_t) arg4,
|
||||
(key_serial_t) arg5);
|
||||
|
||||
case KEYCTL_NEGATE:
|
||||
return keyctl_negate_key((key_serial_t) arg2,
|
||||
(unsigned) arg3,
|
||||
(key_serial_t) arg4);
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
} /* end sys_keyctl() */
|
||||
895
extra/linux-2.6.10/security/keys/keyring.c
Normal file
895
extra/linux-2.6.10/security/keys/keyring.c
Normal file
@@ -0,0 +1,895 @@
|
||||
/* keyring.c: keyring handling
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
/*
|
||||
* when plumbing the depths of the key tree, this sets a hard limit set on how
|
||||
* deep we're willing to go
|
||||
*/
|
||||
#define KEYRING_SEARCH_MAX_DEPTH 6
|
||||
|
||||
/*
|
||||
* we keep all named keyrings in a hash to speed looking them up
|
||||
*/
|
||||
#define KEYRING_NAME_HASH_SIZE (1 << 5)
|
||||
|
||||
static struct list_head keyring_name_hash[KEYRING_NAME_HASH_SIZE];
|
||||
static rwlock_t keyring_name_lock = RW_LOCK_UNLOCKED;
|
||||
|
||||
static inline unsigned keyring_hash(const char *desc)
|
||||
{
|
||||
unsigned bucket = 0;
|
||||
|
||||
for (; *desc; desc++)
|
||||
bucket += (unsigned char) *desc;
|
||||
|
||||
return bucket & (KEYRING_NAME_HASH_SIZE - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* the keyring type definition
|
||||
*/
|
||||
static int keyring_instantiate(struct key *keyring,
|
||||
const void *data, size_t datalen);
|
||||
static int keyring_duplicate(struct key *keyring, const struct key *source);
|
||||
static int keyring_match(const struct key *keyring, const void *criterion);
|
||||
static void keyring_destroy(struct key *keyring);
|
||||
static void keyring_describe(const struct key *keyring, struct seq_file *m);
|
||||
static long keyring_read(const struct key *keyring,
|
||||
char __user *buffer, size_t buflen);
|
||||
|
||||
struct key_type key_type_keyring = {
|
||||
.name = "keyring",
|
||||
.def_datalen = sizeof(struct keyring_list),
|
||||
.instantiate = keyring_instantiate,
|
||||
.duplicate = keyring_duplicate,
|
||||
.match = keyring_match,
|
||||
.destroy = keyring_destroy,
|
||||
.describe = keyring_describe,
|
||||
.read = keyring_read,
|
||||
};
|
||||
|
||||
/*
|
||||
* semaphore to serialise link/link calls to prevent two link calls in parallel
|
||||
* introducing a cycle
|
||||
*/
|
||||
DECLARE_RWSEM(keyring_serialise_link_sem);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* publish the name of a keyring so that it can be found by name (if it has
|
||||
* one)
|
||||
*/
|
||||
void keyring_publish_name(struct key *keyring)
|
||||
{
|
||||
int bucket;
|
||||
|
||||
if (keyring->description) {
|
||||
bucket = keyring_hash(keyring->description);
|
||||
|
||||
write_lock(&keyring_name_lock);
|
||||
|
||||
if (!keyring_name_hash[bucket].next)
|
||||
INIT_LIST_HEAD(&keyring_name_hash[bucket]);
|
||||
|
||||
list_add_tail(&keyring->type_data.link,
|
||||
&keyring_name_hash[bucket]);
|
||||
|
||||
write_unlock(&keyring_name_lock);
|
||||
}
|
||||
|
||||
} /* end keyring_publish_name() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* initialise a keyring
|
||||
* - we object if we were given any data
|
||||
*/
|
||||
static int keyring_instantiate(struct key *keyring,
|
||||
const void *data, size_t datalen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (datalen == 0) {
|
||||
/* make the keyring available by name if it has one */
|
||||
keyring_publish_name(keyring);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end keyring_instantiate() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* duplicate the list of subscribed keys from a source keyring into this one
|
||||
*/
|
||||
static int keyring_duplicate(struct key *keyring, const struct key *source)
|
||||
{
|
||||
struct keyring_list *sklist, *klist;
|
||||
unsigned max;
|
||||
size_t size;
|
||||
int loop, ret;
|
||||
|
||||
const unsigned limit =
|
||||
(PAGE_SIZE - sizeof(*klist)) / sizeof(struct key);
|
||||
|
||||
ret = 0;
|
||||
sklist = source->payload.subscriptions;
|
||||
|
||||
if (sklist && sklist->nkeys > 0) {
|
||||
max = sklist->nkeys;
|
||||
BUG_ON(max > limit);
|
||||
|
||||
max = (max + 3) & ~3;
|
||||
if (max > limit)
|
||||
max = limit;
|
||||
|
||||
ret = -ENOMEM;
|
||||
size = sizeof(*klist) + sizeof(struct key) * max;
|
||||
klist = kmalloc(size, GFP_KERNEL);
|
||||
if (!klist)
|
||||
goto error;
|
||||
|
||||
klist->maxkeys = max;
|
||||
klist->nkeys = sklist->nkeys;
|
||||
memcpy(klist->keys,
|
||||
sklist->keys,
|
||||
sklist->nkeys * sizeof(struct key));
|
||||
|
||||
for (loop = klist->nkeys - 1; loop >= 0; loop--)
|
||||
atomic_inc(&klist->keys[loop]->usage);
|
||||
|
||||
keyring->payload.subscriptions = klist;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyring_duplicate() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* match keyrings on their name
|
||||
*/
|
||||
static int keyring_match(const struct key *keyring, const void *description)
|
||||
{
|
||||
return keyring->description &&
|
||||
strcmp(keyring->description, description) == 0;
|
||||
|
||||
} /* end keyring_match() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* dispose of the data dangling from the corpse of a keyring
|
||||
*/
|
||||
static void keyring_destroy(struct key *keyring)
|
||||
{
|
||||
struct keyring_list *klist;
|
||||
int loop;
|
||||
|
||||
if (keyring->description) {
|
||||
write_lock(&keyring_name_lock);
|
||||
list_del(&keyring->type_data.link);
|
||||
write_unlock(&keyring_name_lock);
|
||||
}
|
||||
|
||||
klist = keyring->payload.subscriptions;
|
||||
if (klist) {
|
||||
for (loop = klist->nkeys - 1; loop >= 0; loop--)
|
||||
key_put(klist->keys[loop]);
|
||||
kfree(klist);
|
||||
}
|
||||
|
||||
} /* end keyring_destroy() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* describe the keyring
|
||||
*/
|
||||
static void keyring_describe(const struct key *keyring, struct seq_file *m)
|
||||
{
|
||||
struct keyring_list *klist;
|
||||
|
||||
if (keyring->description) {
|
||||
seq_puts(m, keyring->description);
|
||||
}
|
||||
else {
|
||||
seq_puts(m, "[anon]");
|
||||
}
|
||||
|
||||
klist = keyring->payload.subscriptions;
|
||||
if (klist)
|
||||
seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
|
||||
else
|
||||
seq_puts(m, ": empty");
|
||||
|
||||
} /* end keyring_describe() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* read a list of key IDs from the keyring's contents
|
||||
*/
|
||||
static long keyring_read(const struct key *keyring,
|
||||
char __user *buffer, size_t buflen)
|
||||
{
|
||||
struct keyring_list *klist;
|
||||
struct key *key;
|
||||
size_t qty, tmp;
|
||||
int loop, ret;
|
||||
|
||||
ret = 0;
|
||||
klist = keyring->payload.subscriptions;
|
||||
|
||||
if (klist) {
|
||||
/* calculate how much data we could return */
|
||||
qty = klist->nkeys * sizeof(key_serial_t);
|
||||
|
||||
if (buffer && buflen > 0) {
|
||||
if (buflen > qty)
|
||||
buflen = qty;
|
||||
|
||||
/* copy the IDs of the subscribed keys into the
|
||||
* buffer */
|
||||
ret = -EFAULT;
|
||||
|
||||
for (loop = 0; loop < klist->nkeys; loop++) {
|
||||
key = klist->keys[loop];
|
||||
|
||||
tmp = sizeof(key_serial_t);
|
||||
if (tmp > buflen)
|
||||
tmp = buflen;
|
||||
|
||||
if (copy_to_user(buffer,
|
||||
&key->serial,
|
||||
tmp) != 0)
|
||||
goto error;
|
||||
|
||||
buflen -= tmp;
|
||||
if (buflen == 0)
|
||||
break;
|
||||
buffer += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
ret = qty;
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end keyring_read() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* allocate a keyring and link into the destination keyring
|
||||
*/
|
||||
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
|
||||
int not_in_quota, struct key *dest)
|
||||
{
|
||||
struct key *keyring;
|
||||
int ret;
|
||||
|
||||
keyring = key_alloc(&key_type_keyring, description,
|
||||
uid, gid, KEY_USR_ALL, not_in_quota);
|
||||
|
||||
if (!IS_ERR(keyring)) {
|
||||
ret = key_instantiate_and_link(keyring, NULL, 0, dest);
|
||||
if (ret < 0) {
|
||||
key_put(keyring);
|
||||
keyring = ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
return keyring;
|
||||
|
||||
} /* end keyring_alloc() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the supplied keyring tree for a key that matches the criterion
|
||||
* - perform a breadth-then-depth search up to the prescribed limit
|
||||
* - we only find keys on which we have search permission
|
||||
* - we use the supplied match function to see if the description (or other
|
||||
* feature of interest) matches
|
||||
* - we readlock the keyrings as we search down the tree
|
||||
* - we return -EAGAIN if we didn't find any matching key
|
||||
* - we return -ENOKEY if we only found negative matching keys
|
||||
*/
|
||||
struct key *keyring_search_aux(struct key *keyring,
|
||||
struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match)
|
||||
{
|
||||
struct {
|
||||
struct key *keyring;
|
||||
int kix;
|
||||
} stack[KEYRING_SEARCH_MAX_DEPTH];
|
||||
|
||||
struct keyring_list *keylist;
|
||||
struct timespec now;
|
||||
struct key *key;
|
||||
long err;
|
||||
int sp, psp, kix;
|
||||
|
||||
key_check(keyring);
|
||||
|
||||
/* top keyring must have search permission to begin the search */
|
||||
key = ERR_PTR(-EACCES);
|
||||
if (!key_permission(keyring, KEY_SEARCH))
|
||||
goto error;
|
||||
|
||||
key = ERR_PTR(-ENOTDIR);
|
||||
if (keyring->type != &key_type_keyring)
|
||||
goto error;
|
||||
|
||||
now = current_kernel_time();
|
||||
err = -EAGAIN;
|
||||
sp = 0;
|
||||
|
||||
/* start processing a new keyring */
|
||||
descend:
|
||||
read_lock(&keyring->lock);
|
||||
if (keyring->flags & KEY_FLAG_REVOKED)
|
||||
goto not_this_keyring;
|
||||
|
||||
keylist = keyring->payload.subscriptions;
|
||||
if (!keylist)
|
||||
goto not_this_keyring;
|
||||
|
||||
/* iterate through the keys in this keyring first */
|
||||
for (kix = 0; kix < keylist->nkeys; kix++) {
|
||||
key = keylist->keys[kix];
|
||||
|
||||
/* ignore keys not of this type */
|
||||
if (key->type != type)
|
||||
continue;
|
||||
|
||||
/* skip revoked keys and expired keys */
|
||||
if (key->flags & KEY_FLAG_REVOKED)
|
||||
continue;
|
||||
|
||||
if (key->expiry && now.tv_sec >= key->expiry)
|
||||
continue;
|
||||
|
||||
/* keys that don't match */
|
||||
if (!match(key, description))
|
||||
continue;
|
||||
|
||||
/* key must have search permissions */
|
||||
if (!key_permission(key, KEY_SEARCH))
|
||||
continue;
|
||||
|
||||
/* we set a different error code if we find a negative key */
|
||||
if (key->flags & KEY_FLAG_NEGATIVE) {
|
||||
err = -ENOKEY;
|
||||
continue;
|
||||
}
|
||||
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* search through the keyrings nested in this one */
|
||||
kix = 0;
|
||||
ascend:
|
||||
while (kix < keylist->nkeys) {
|
||||
key = keylist->keys[kix];
|
||||
if (key->type != &key_type_keyring)
|
||||
goto next;
|
||||
|
||||
/* recursively search nested keyrings
|
||||
* - only search keyrings for which we have search permission
|
||||
*/
|
||||
if (sp >= KEYRING_SEARCH_MAX_DEPTH)
|
||||
goto next;
|
||||
|
||||
if (!key_permission(key, KEY_SEARCH))
|
||||
goto next;
|
||||
|
||||
/* evade loops in the keyring tree */
|
||||
for (psp = 0; psp < sp; psp++)
|
||||
if (stack[psp].keyring == keyring)
|
||||
goto next;
|
||||
|
||||
/* stack the current position */
|
||||
stack[sp].keyring = keyring;
|
||||
stack[sp].kix = kix;
|
||||
sp++;
|
||||
|
||||
/* begin again with the new keyring */
|
||||
keyring = key;
|
||||
goto descend;
|
||||
|
||||
next:
|
||||
kix++;
|
||||
}
|
||||
|
||||
/* the keyring we're looking at was disqualified or didn't contain a
|
||||
* matching key */
|
||||
not_this_keyring:
|
||||
read_unlock(&keyring->lock);
|
||||
|
||||
if (sp > 0) {
|
||||
/* resume the processing of a keyring higher up in the tree */
|
||||
sp--;
|
||||
keyring = stack[sp].keyring;
|
||||
keylist = keyring->payload.subscriptions;
|
||||
kix = stack[sp].kix + 1;
|
||||
goto ascend;
|
||||
}
|
||||
|
||||
key = ERR_PTR(err);
|
||||
goto error;
|
||||
|
||||
/* we found a viable match */
|
||||
found:
|
||||
atomic_inc(&key->usage);
|
||||
read_unlock(&keyring->lock);
|
||||
|
||||
/* unwind the keyring stack */
|
||||
while (sp > 0) {
|
||||
sp--;
|
||||
read_unlock(&stack[sp].keyring->lock);
|
||||
}
|
||||
|
||||
key_check(key);
|
||||
error:
|
||||
return key;
|
||||
|
||||
} /* end keyring_search_aux() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the supplied keyring tree for a key that matches the criterion
|
||||
* - perform a breadth-then-depth search up to the prescribed limit
|
||||
* - we only find keys on which we have search permission
|
||||
* - we readlock the keyrings as we search down the tree
|
||||
* - we return -EAGAIN if we didn't find any matching key
|
||||
* - we return -ENOKEY if we only found negative matching keys
|
||||
*/
|
||||
struct key *keyring_search(struct key *keyring,
|
||||
struct key_type *type,
|
||||
const char *description)
|
||||
{
|
||||
return keyring_search_aux(keyring, type, description, type->match);
|
||||
|
||||
} /* end keyring_search() */
|
||||
|
||||
EXPORT_SYMBOL(keyring_search);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the given keyring only (no recursion)
|
||||
* - keyring must be locked by caller
|
||||
*/
|
||||
struct key *__keyring_search_one(struct key *keyring,
|
||||
const struct key_type *ktype,
|
||||
const char *description,
|
||||
key_perm_t perm)
|
||||
{
|
||||
struct keyring_list *klist;
|
||||
struct key *key;
|
||||
int loop;
|
||||
|
||||
klist = keyring->payload.subscriptions;
|
||||
if (klist) {
|
||||
for (loop = 0; loop < klist->nkeys; loop++) {
|
||||
key = klist->keys[loop];
|
||||
|
||||
if (key->type == ktype &&
|
||||
key->type->match(key, description) &&
|
||||
key_permission(key, perm) &&
|
||||
!(key->flags & KEY_FLAG_REVOKED)
|
||||
)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
key = ERR_PTR(-ENOKEY);
|
||||
goto error;
|
||||
|
||||
found:
|
||||
atomic_inc(&key->usage);
|
||||
error:
|
||||
return key;
|
||||
|
||||
} /* end __keyring_search_one() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* find a keyring with the specified name
|
||||
* - all named keyrings are searched
|
||||
* - only find keyrings with search permission for the process
|
||||
* - only find keyrings with a serial number greater than the one specified
|
||||
*/
|
||||
struct key *find_keyring_by_name(const char *name, key_serial_t bound)
|
||||
{
|
||||
struct key *keyring;
|
||||
int bucket;
|
||||
|
||||
keyring = ERR_PTR(-EINVAL);
|
||||
if (!name)
|
||||
goto error;
|
||||
|
||||
bucket = keyring_hash(name);
|
||||
|
||||
read_lock(&keyring_name_lock);
|
||||
|
||||
if (keyring_name_hash[bucket].next) {
|
||||
/* search this hash bucket for a keyring with a matching name
|
||||
* that's readable and that hasn't been revoked */
|
||||
list_for_each_entry(keyring,
|
||||
&keyring_name_hash[bucket],
|
||||
type_data.link
|
||||
) {
|
||||
if (keyring->flags & KEY_FLAG_REVOKED)
|
||||
continue;
|
||||
|
||||
if (strcmp(keyring->description, name) != 0)
|
||||
continue;
|
||||
|
||||
if (!key_permission(keyring, KEY_SEARCH))
|
||||
continue;
|
||||
|
||||
/* found a potential candidate, but we still need to
|
||||
* check the serial number */
|
||||
if (keyring->serial <= bound)
|
||||
continue;
|
||||
|
||||
/* we've got a match */
|
||||
atomic_inc(&keyring->usage);
|
||||
read_unlock(&keyring_name_lock);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
read_unlock(&keyring_name_lock);
|
||||
keyring = ERR_PTR(-ENOKEY);
|
||||
|
||||
error:
|
||||
return keyring;
|
||||
|
||||
} /* end find_keyring_by_name() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* see if a cycle will will be created by inserting acyclic tree B in acyclic
|
||||
* tree A at the topmost level (ie: as a direct child of A)
|
||||
* - since we are adding B to A at the top level, checking for cycles should
|
||||
* just be a matter of seeing if node A is somewhere in tree B
|
||||
*/
|
||||
static int keyring_detect_cycle(struct key *A, struct key *B)
|
||||
{
|
||||
struct {
|
||||
struct key *subtree;
|
||||
int kix;
|
||||
} stack[KEYRING_SEARCH_MAX_DEPTH];
|
||||
|
||||
struct keyring_list *keylist;
|
||||
struct key *subtree, *key;
|
||||
int sp, kix, ret;
|
||||
|
||||
ret = -EDEADLK;
|
||||
if (A == B)
|
||||
goto error;
|
||||
|
||||
subtree = B;
|
||||
sp = 0;
|
||||
|
||||
/* start processing a new keyring */
|
||||
descend:
|
||||
read_lock(&subtree->lock);
|
||||
if (subtree->flags & KEY_FLAG_REVOKED)
|
||||
goto not_this_keyring;
|
||||
|
||||
keylist = subtree->payload.subscriptions;
|
||||
if (!keylist)
|
||||
goto not_this_keyring;
|
||||
kix = 0;
|
||||
|
||||
ascend:
|
||||
/* iterate through the remaining keys in this keyring */
|
||||
for (; kix < keylist->nkeys; kix++) {
|
||||
key = keylist->keys[kix];
|
||||
|
||||
if (key == A)
|
||||
goto cycle_detected;
|
||||
|
||||
/* recursively check nested keyrings */
|
||||
if (key->type == &key_type_keyring) {
|
||||
if (sp >= KEYRING_SEARCH_MAX_DEPTH)
|
||||
goto too_deep;
|
||||
|
||||
/* stack the current position */
|
||||
stack[sp].subtree = subtree;
|
||||
stack[sp].kix = kix;
|
||||
sp++;
|
||||
|
||||
/* begin again with the new keyring */
|
||||
subtree = key;
|
||||
goto descend;
|
||||
}
|
||||
}
|
||||
|
||||
/* the keyring we're looking at was disqualified or didn't contain a
|
||||
* matching key */
|
||||
not_this_keyring:
|
||||
read_unlock(&subtree->lock);
|
||||
|
||||
if (sp > 0) {
|
||||
/* resume the checking of a keyring higher up in the tree */
|
||||
sp--;
|
||||
subtree = stack[sp].subtree;
|
||||
keylist = subtree->payload.subscriptions;
|
||||
kix = stack[sp].kix + 1;
|
||||
goto ascend;
|
||||
}
|
||||
|
||||
ret = 0; /* no cycles detected */
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
too_deep:
|
||||
ret = -ELOOP;
|
||||
goto error_unwind;
|
||||
cycle_detected:
|
||||
ret = -EDEADLK;
|
||||
error_unwind:
|
||||
read_unlock(&subtree->lock);
|
||||
|
||||
/* unwind the keyring stack */
|
||||
while (sp > 0) {
|
||||
sp--;
|
||||
read_unlock(&stack[sp].subtree->lock);
|
||||
}
|
||||
|
||||
goto error;
|
||||
|
||||
} /* end keyring_detect_cycle() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* link a key into to a keyring
|
||||
* - must be called with the keyring's semaphore held
|
||||
*/
|
||||
int __key_link(struct key *keyring, struct key *key)
|
||||
{
|
||||
struct keyring_list *klist, *nklist;
|
||||
unsigned max;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
ret = -EKEYREVOKED;
|
||||
if (keyring->flags & KEY_FLAG_REVOKED)
|
||||
goto error;
|
||||
|
||||
ret = -ENOTDIR;
|
||||
if (keyring->type != &key_type_keyring)
|
||||
goto error;
|
||||
|
||||
/* serialise link/link calls to prevent parallel calls causing a
|
||||
* cycle when applied to two keyring in opposite orders */
|
||||
down_write(&keyring_serialise_link_sem);
|
||||
|
||||
/* check that we aren't going to create a cycle adding one keyring to
|
||||
* another */
|
||||
if (key->type == &key_type_keyring) {
|
||||
ret = keyring_detect_cycle(keyring, key);
|
||||
if (ret < 0)
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* check that we aren't going to overrun the user's quota */
|
||||
ret = key_payload_reserve(keyring,
|
||||
keyring->datalen + KEYQUOTA_LINK_BYTES);
|
||||
if (ret < 0)
|
||||
goto error2;
|
||||
|
||||
klist = keyring->payload.subscriptions;
|
||||
|
||||
if (klist && klist->nkeys < klist->maxkeys) {
|
||||
/* there's sufficient slack space to add directly */
|
||||
atomic_inc(&key->usage);
|
||||
|
||||
write_lock(&keyring->lock);
|
||||
klist->keys[klist->nkeys++] = key;
|
||||
write_unlock(&keyring->lock);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
else {
|
||||
/* grow the key list */
|
||||
max = 4;
|
||||
if (klist)
|
||||
max += klist->maxkeys;
|
||||
|
||||
ret = -ENFILE;
|
||||
size = sizeof(*klist) + sizeof(*key) * max;
|
||||
if (size > PAGE_SIZE)
|
||||
goto error3;
|
||||
|
||||
ret = -ENOMEM;
|
||||
nklist = kmalloc(size, GFP_KERNEL);
|
||||
if (!nklist)
|
||||
goto error3;
|
||||
nklist->maxkeys = max;
|
||||
nklist->nkeys = 0;
|
||||
|
||||
if (klist) {
|
||||
nklist->nkeys = klist->nkeys;
|
||||
memcpy(nklist->keys,
|
||||
klist->keys,
|
||||
sizeof(struct key *) * klist->nkeys);
|
||||
}
|
||||
|
||||
/* add the key into the new space */
|
||||
atomic_inc(&key->usage);
|
||||
|
||||
write_lock(&keyring->lock);
|
||||
keyring->payload.subscriptions = nklist;
|
||||
nklist->keys[nklist->nkeys++] = key;
|
||||
write_unlock(&keyring->lock);
|
||||
|
||||
/* dispose of the old keyring list */
|
||||
kfree(klist);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
error2:
|
||||
up_write(&keyring_serialise_link_sem);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
error3:
|
||||
/* undo the quota changes */
|
||||
key_payload_reserve(keyring,
|
||||
keyring->datalen - KEYQUOTA_LINK_BYTES);
|
||||
goto error2;
|
||||
|
||||
} /* end __key_link() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* link a key to a keyring
|
||||
*/
|
||||
int key_link(struct key *keyring, struct key *key)
|
||||
{
|
||||
int ret;
|
||||
|
||||
key_check(keyring);
|
||||
key_check(key);
|
||||
|
||||
down_write(&keyring->sem);
|
||||
ret = __key_link(keyring, key);
|
||||
up_write(&keyring->sem);
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end key_link() */
|
||||
|
||||
EXPORT_SYMBOL(key_link);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* unlink the first link to a key from a keyring
|
||||
*/
|
||||
int key_unlink(struct key *keyring, struct key *key)
|
||||
{
|
||||
struct keyring_list *klist;
|
||||
int loop, ret;
|
||||
|
||||
key_check(keyring);
|
||||
key_check(key);
|
||||
|
||||
ret = -ENOTDIR;
|
||||
if (keyring->type != &key_type_keyring)
|
||||
goto error;
|
||||
|
||||
down_write(&keyring->sem);
|
||||
|
||||
klist = keyring->payload.subscriptions;
|
||||
if (klist) {
|
||||
/* search the keyring for the key */
|
||||
for (loop = 0; loop < klist->nkeys; loop++)
|
||||
if (klist->keys[loop] == key)
|
||||
goto key_is_present;
|
||||
}
|
||||
|
||||
up_write(&keyring->sem);
|
||||
ret = -ENOENT;
|
||||
goto error;
|
||||
|
||||
key_is_present:
|
||||
/* adjust the user's quota */
|
||||
key_payload_reserve(keyring,
|
||||
keyring->datalen - KEYQUOTA_LINK_BYTES);
|
||||
|
||||
/* shuffle down the key pointers
|
||||
* - it might be worth shrinking the allocated memory, but that runs
|
||||
* the risk of ENOMEM as we would have to copy
|
||||
*/
|
||||
write_lock(&keyring->lock);
|
||||
|
||||
klist->nkeys--;
|
||||
if (loop < klist->nkeys)
|
||||
memcpy(&klist->keys[loop],
|
||||
&klist->keys[loop + 1],
|
||||
(klist->nkeys - loop) * sizeof(struct key *));
|
||||
|
||||
write_unlock(&keyring->lock);
|
||||
|
||||
up_write(&keyring->sem);
|
||||
key_put(key);
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end key_unlink() */
|
||||
|
||||
EXPORT_SYMBOL(key_unlink);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* clear the specified process keyring
|
||||
* - implements keyctl(KEYCTL_CLEAR)
|
||||
*/
|
||||
int keyring_clear(struct key *keyring)
|
||||
{
|
||||
struct keyring_list *klist;
|
||||
int loop, ret;
|
||||
|
||||
ret = -ENOTDIR;
|
||||
if (keyring->type == &key_type_keyring) {
|
||||
/* detach the pointer block with the locks held */
|
||||
down_write(&keyring->sem);
|
||||
|
||||
klist = keyring->payload.subscriptions;
|
||||
if (klist) {
|
||||
/* adjust the quota */
|
||||
key_payload_reserve(keyring,
|
||||
sizeof(struct keyring_list));
|
||||
|
||||
write_lock(&keyring->lock);
|
||||
keyring->payload.subscriptions = NULL;
|
||||
write_unlock(&keyring->lock);
|
||||
}
|
||||
|
||||
up_write(&keyring->sem);
|
||||
|
||||
/* free the keys after the locks have been dropped */
|
||||
if (klist) {
|
||||
for (loop = klist->nkeys - 1; loop >= 0; loop--)
|
||||
key_put(klist->keys[loop]);
|
||||
|
||||
kfree(klist);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end keyring_clear() */
|
||||
|
||||
EXPORT_SYMBOL(keyring_clear);
|
||||
251
extra/linux-2.6.10/security/keys/proc.c
Normal file
251
extra/linux-2.6.10/security/keys/proc.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/* proc.c: proc files for key database enumeration
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <asm/errno.h>
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
|
||||
static int proc_keys_open(struct inode *inode, struct file *file);
|
||||
static void *proc_keys_start(struct seq_file *p, loff_t *_pos);
|
||||
static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos);
|
||||
static void proc_keys_stop(struct seq_file *p, void *v);
|
||||
static int proc_keys_show(struct seq_file *m, void *v);
|
||||
|
||||
static struct seq_operations proc_keys_ops = {
|
||||
.start = proc_keys_start,
|
||||
.next = proc_keys_next,
|
||||
.stop = proc_keys_stop,
|
||||
.show = proc_keys_show,
|
||||
};
|
||||
|
||||
static struct file_operations proc_keys_fops = {
|
||||
.open = proc_keys_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int proc_key_users_open(struct inode *inode, struct file *file);
|
||||
static void *proc_key_users_start(struct seq_file *p, loff_t *_pos);
|
||||
static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos);
|
||||
static void proc_key_users_stop(struct seq_file *p, void *v);
|
||||
static int proc_key_users_show(struct seq_file *m, void *v);
|
||||
|
||||
static struct seq_operations proc_key_users_ops = {
|
||||
.start = proc_key_users_start,
|
||||
.next = proc_key_users_next,
|
||||
.stop = proc_key_users_stop,
|
||||
.show = proc_key_users_show,
|
||||
};
|
||||
|
||||
static struct file_operations proc_key_users_fops = {
|
||||
.open = proc_key_users_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* declare the /proc files
|
||||
*/
|
||||
static int __init key_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *p;
|
||||
|
||||
#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
|
||||
p = create_proc_entry("keys", 0, NULL);
|
||||
if (!p)
|
||||
panic("Cannot create /proc/keys\n");
|
||||
|
||||
p->proc_fops = &proc_keys_fops;
|
||||
#endif
|
||||
|
||||
p = create_proc_entry("key-users", 0, NULL);
|
||||
if (!p)
|
||||
panic("Cannot create /proc/key-users\n");
|
||||
|
||||
p->proc_fops = &proc_key_users_fops;
|
||||
|
||||
return 0;
|
||||
|
||||
} /* end key_proc_init() */
|
||||
|
||||
__initcall(key_proc_init);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* implement "/proc/keys" to provides a list of the keys on the system
|
||||
*/
|
||||
#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
|
||||
|
||||
static int proc_keys_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &proc_keys_ops);
|
||||
|
||||
}
|
||||
|
||||
static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
|
||||
{
|
||||
struct rb_node *_p;
|
||||
loff_t pos = *_pos;
|
||||
|
||||
spin_lock(&key_serial_lock);
|
||||
|
||||
_p = rb_first(&key_serial_tree);
|
||||
while (pos > 0 && _p) {
|
||||
pos--;
|
||||
_p = rb_next(_p);
|
||||
}
|
||||
|
||||
return _p;
|
||||
|
||||
}
|
||||
|
||||
static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
|
||||
{
|
||||
(*_pos)++;
|
||||
return rb_next((struct rb_node *) v);
|
||||
|
||||
}
|
||||
|
||||
static void proc_keys_stop(struct seq_file *p, void *v)
|
||||
{
|
||||
spin_unlock(&key_serial_lock);
|
||||
}
|
||||
|
||||
static int proc_keys_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct rb_node *_p = v;
|
||||
struct key *key = rb_entry(_p, struct key, serial_node);
|
||||
struct timespec now;
|
||||
unsigned long timo;
|
||||
char xbuf[12];
|
||||
|
||||
now = current_kernel_time();
|
||||
|
||||
read_lock(&key->lock);
|
||||
|
||||
/* come up with a suitable timeout value */
|
||||
if (key->expiry == 0) {
|
||||
memcpy(xbuf, "perm", 5);
|
||||
}
|
||||
else if (now.tv_sec >= key->expiry) {
|
||||
memcpy(xbuf, "expd", 5);
|
||||
}
|
||||
else {
|
||||
timo = key->expiry - now.tv_sec;
|
||||
|
||||
if (timo < 60)
|
||||
sprintf(xbuf, "%lus", timo);
|
||||
else if (timo < 60*60)
|
||||
sprintf(xbuf, "%lum", timo / 60);
|
||||
else if (timo < 60*60*24)
|
||||
sprintf(xbuf, "%luh", timo / (60*60));
|
||||
else if (timo < 60*60*24*7)
|
||||
sprintf(xbuf, "%lud", timo / (60*60*24));
|
||||
else
|
||||
sprintf(xbuf, "%luw", timo / (60*60*24*7));
|
||||
}
|
||||
|
||||
seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ",
|
||||
key->serial,
|
||||
key->flags & KEY_FLAG_INSTANTIATED ? 'I' : '-',
|
||||
key->flags & KEY_FLAG_REVOKED ? 'R' : '-',
|
||||
key->flags & KEY_FLAG_DEAD ? 'D' : '-',
|
||||
key->flags & KEY_FLAG_IN_QUOTA ? 'Q' : '-',
|
||||
key->flags & KEY_FLAG_USER_CONSTRUCT ? 'U' : '-',
|
||||
key->flags & KEY_FLAG_NEGATIVE ? 'N' : '-',
|
||||
atomic_read(&key->usage),
|
||||
xbuf,
|
||||
key->perm,
|
||||
key->uid,
|
||||
key->gid,
|
||||
key->type->name);
|
||||
|
||||
if (key->type->describe)
|
||||
key->type->describe(key, m);
|
||||
seq_putc(m, '\n');
|
||||
|
||||
read_unlock(&key->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* implement "/proc/key-users" to provides a list of the key users
|
||||
*/
|
||||
static int proc_key_users_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &proc_key_users_ops);
|
||||
|
||||
}
|
||||
|
||||
static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
|
||||
{
|
||||
struct rb_node *_p;
|
||||
loff_t pos = *_pos;
|
||||
|
||||
spin_lock(&key_user_lock);
|
||||
|
||||
_p = rb_first(&key_user_tree);
|
||||
while (pos > 0 && _p) {
|
||||
pos--;
|
||||
_p = rb_next(_p);
|
||||
}
|
||||
|
||||
return _p;
|
||||
|
||||
}
|
||||
|
||||
static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
|
||||
{
|
||||
(*_pos)++;
|
||||
return rb_next((struct rb_node *) v);
|
||||
|
||||
}
|
||||
|
||||
static void proc_key_users_stop(struct seq_file *p, void *v)
|
||||
{
|
||||
spin_unlock(&key_user_lock);
|
||||
}
|
||||
|
||||
static int proc_key_users_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct rb_node *_p = v;
|
||||
struct key_user *user = rb_entry(_p, struct key_user, node);
|
||||
|
||||
seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
|
||||
user->uid,
|
||||
atomic_read(&user->usage),
|
||||
atomic_read(&user->nkeys),
|
||||
atomic_read(&user->nikeys),
|
||||
user->qnkeys,
|
||||
KEYQUOTA_MAX_KEYS,
|
||||
user->qnbytes,
|
||||
KEYQUOTA_MAX_BYTES
|
||||
);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
640
extra/linux-2.6.10/security/keys/process_keys.c
Normal file
640
extra/linux-2.6.10/security/keys/process_keys.c
Normal file
@@ -0,0 +1,640 @@
|
||||
/* process_keys.c: management of a process's keyrings
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/keyctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
/* session keyring create vs join semaphore */
|
||||
static DECLARE_MUTEX(key_session_sem);
|
||||
|
||||
/* the root user's tracking struct */
|
||||
struct key_user root_key_user = {
|
||||
.usage = ATOMIC_INIT(3),
|
||||
.consq = LIST_HEAD_INIT(root_key_user.consq),
|
||||
.lock = SPIN_LOCK_UNLOCKED,
|
||||
.nkeys = ATOMIC_INIT(2),
|
||||
.nikeys = ATOMIC_INIT(2),
|
||||
.uid = 0,
|
||||
};
|
||||
|
||||
/* the root user's UID keyring */
|
||||
struct key root_user_keyring = {
|
||||
.usage = ATOMIC_INIT(1),
|
||||
.serial = 2,
|
||||
.type = &key_type_keyring,
|
||||
.user = &root_key_user,
|
||||
.lock = RW_LOCK_UNLOCKED,
|
||||
.sem = __RWSEM_INITIALIZER(root_user_keyring.sem),
|
||||
.perm = KEY_USR_ALL,
|
||||
.flags = KEY_FLAG_INSTANTIATED,
|
||||
.description = "_uid.0",
|
||||
#ifdef KEY_DEBUGGING
|
||||
.magic = KEY_DEBUG_MAGIC,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* the root user's default session keyring */
|
||||
struct key root_session_keyring = {
|
||||
.usage = ATOMIC_INIT(1),
|
||||
.serial = 1,
|
||||
.type = &key_type_keyring,
|
||||
.user = &root_key_user,
|
||||
.lock = RW_LOCK_UNLOCKED,
|
||||
.sem = __RWSEM_INITIALIZER(root_session_keyring.sem),
|
||||
.perm = KEY_USR_ALL,
|
||||
.flags = KEY_FLAG_INSTANTIATED,
|
||||
.description = "_uid_ses.0",
|
||||
#ifdef KEY_DEBUGGING
|
||||
.magic = KEY_DEBUG_MAGIC,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* allocate the keyrings to be associated with a UID
|
||||
*/
|
||||
int alloc_uid_keyring(struct user_struct *user)
|
||||
{
|
||||
struct key *uid_keyring, *session_keyring;
|
||||
char buf[20];
|
||||
int ret;
|
||||
|
||||
/* concoct a default session keyring */
|
||||
sprintf(buf, "_uid_ses.%u", user->uid);
|
||||
|
||||
session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL);
|
||||
if (IS_ERR(session_keyring)) {
|
||||
ret = PTR_ERR(session_keyring);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* and a UID specific keyring, pointed to by the default session
|
||||
* keyring */
|
||||
sprintf(buf, "_uid.%u", user->uid);
|
||||
|
||||
uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0,
|
||||
session_keyring);
|
||||
if (IS_ERR(uid_keyring)) {
|
||||
key_put(session_keyring);
|
||||
ret = PTR_ERR(uid_keyring);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* install the keyrings */
|
||||
user->uid_keyring = uid_keyring;
|
||||
user->session_keyring = session_keyring;
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end alloc_uid_keyring() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* deal with the UID changing
|
||||
*/
|
||||
void switch_uid_keyring(struct user_struct *new_user)
|
||||
{
|
||||
#if 0 /* do nothing for now */
|
||||
struct key *old;
|
||||
|
||||
/* switch to the new user's session keyring if we were running under
|
||||
* root's default session keyring */
|
||||
if (new_user->uid != 0 &&
|
||||
current->session_keyring == &root_session_keyring
|
||||
) {
|
||||
atomic_inc(&new_user->session_keyring->usage);
|
||||
|
||||
task_lock(current);
|
||||
old = current->session_keyring;
|
||||
current->session_keyring = new_user->session_keyring;
|
||||
task_unlock(current);
|
||||
|
||||
key_put(old);
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* end switch_uid_keyring() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* install a fresh thread keyring, discarding the old one
|
||||
*/
|
||||
int install_thread_keyring(struct task_struct *tsk)
|
||||
{
|
||||
struct key *keyring, *old;
|
||||
char buf[20];
|
||||
int ret;
|
||||
|
||||
sprintf(buf, "_tid.%u", tsk->pid);
|
||||
|
||||
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error;
|
||||
}
|
||||
|
||||
task_lock(tsk);
|
||||
old = tsk->thread_keyring;
|
||||
tsk->thread_keyring = keyring;
|
||||
task_unlock(tsk);
|
||||
|
||||
ret = 0;
|
||||
|
||||
key_put(old);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end install_thread_keyring() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* install a fresh process keyring, discarding the old one
|
||||
*/
|
||||
static int install_process_keyring(struct task_struct *tsk)
|
||||
{
|
||||
struct key *keyring, *old;
|
||||
char buf[20];
|
||||
int ret;
|
||||
|
||||
sprintf(buf, "_pid.%u", tsk->tgid);
|
||||
|
||||
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error;
|
||||
}
|
||||
|
||||
task_lock(tsk);
|
||||
old = tsk->process_keyring;
|
||||
tsk->process_keyring = keyring;
|
||||
task_unlock(tsk);
|
||||
|
||||
ret = 0;
|
||||
|
||||
key_put(old);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end install_process_keyring() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* install a session keyring, discarding the old one
|
||||
* - if a keyring is not supplied, an empty one is invented
|
||||
*/
|
||||
static int install_session_keyring(struct task_struct *tsk,
|
||||
struct key *keyring)
|
||||
{
|
||||
struct key *old;
|
||||
char buf[20];
|
||||
int ret;
|
||||
|
||||
/* create an empty session keyring */
|
||||
if (!keyring) {
|
||||
sprintf(buf, "_ses.%u", tsk->tgid);
|
||||
|
||||
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
atomic_inc(&keyring->usage);
|
||||
}
|
||||
|
||||
/* install the keyring */
|
||||
task_lock(tsk);
|
||||
old = tsk->session_keyring;
|
||||
tsk->session_keyring = keyring;
|
||||
task_unlock(tsk);
|
||||
|
||||
ret = 0;
|
||||
|
||||
key_put(old);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end install_session_keyring() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* copy the keys for fork
|
||||
*/
|
||||
int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
key_check(tsk->session_keyring);
|
||||
key_check(tsk->process_keyring);
|
||||
key_check(tsk->thread_keyring);
|
||||
|
||||
if (tsk->session_keyring)
|
||||
atomic_inc(&tsk->session_keyring->usage);
|
||||
|
||||
if (tsk->process_keyring) {
|
||||
if (clone_flags & CLONE_THREAD) {
|
||||
atomic_inc(&tsk->process_keyring->usage);
|
||||
}
|
||||
else {
|
||||
tsk->process_keyring = NULL;
|
||||
ret = install_process_keyring(tsk);
|
||||
}
|
||||
}
|
||||
|
||||
tsk->thread_keyring = NULL;
|
||||
return ret;
|
||||
|
||||
} /* end copy_keys() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* dispose of keys upon exit
|
||||
*/
|
||||
void exit_keys(struct task_struct *tsk)
|
||||
{
|
||||
key_put(tsk->session_keyring);
|
||||
key_put(tsk->process_keyring);
|
||||
key_put(tsk->thread_keyring);
|
||||
|
||||
} /* end exit_keys() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* deal with execve()
|
||||
*/
|
||||
int exec_keys(struct task_struct *tsk)
|
||||
{
|
||||
struct key *old;
|
||||
|
||||
/* newly exec'd tasks don't get a thread keyring */
|
||||
task_lock(tsk);
|
||||
old = tsk->thread_keyring;
|
||||
tsk->thread_keyring = NULL;
|
||||
task_unlock(tsk);
|
||||
|
||||
key_put(old);
|
||||
|
||||
/* newly exec'd tasks get a fresh process keyring */
|
||||
return install_process_keyring(tsk);
|
||||
|
||||
} /* end exec_keys() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* deal with SUID programs
|
||||
* - we might want to make this invent a new session keyring
|
||||
*/
|
||||
int suid_keys(struct task_struct *tsk)
|
||||
{
|
||||
return 0;
|
||||
|
||||
} /* end suid_keys() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* the filesystem user ID changed
|
||||
*/
|
||||
void key_fsuid_changed(struct task_struct *tsk)
|
||||
{
|
||||
/* update the ownership of the process keyring */
|
||||
if (tsk->process_keyring) {
|
||||
down_write(&tsk->process_keyring->sem);
|
||||
write_lock(&tsk->process_keyring->lock);
|
||||
tsk->process_keyring->uid = tsk->fsuid;
|
||||
write_unlock(&tsk->process_keyring->lock);
|
||||
up_write(&tsk->process_keyring->sem);
|
||||
}
|
||||
|
||||
/* update the ownership of the thread keyring */
|
||||
if (tsk->thread_keyring) {
|
||||
down_write(&tsk->thread_keyring->sem);
|
||||
write_lock(&tsk->thread_keyring->lock);
|
||||
tsk->thread_keyring->uid = tsk->fsuid;
|
||||
write_unlock(&tsk->thread_keyring->lock);
|
||||
up_write(&tsk->thread_keyring->sem);
|
||||
}
|
||||
|
||||
} /* end key_fsuid_changed() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* the filesystem group ID changed
|
||||
*/
|
||||
void key_fsgid_changed(struct task_struct *tsk)
|
||||
{
|
||||
/* update the ownership of the process keyring */
|
||||
if (tsk->process_keyring) {
|
||||
down_write(&tsk->process_keyring->sem);
|
||||
write_lock(&tsk->process_keyring->lock);
|
||||
tsk->process_keyring->gid = tsk->fsgid;
|
||||
write_unlock(&tsk->process_keyring->lock);
|
||||
up_write(&tsk->process_keyring->sem);
|
||||
}
|
||||
|
||||
/* update the ownership of the thread keyring */
|
||||
if (tsk->thread_keyring) {
|
||||
down_write(&tsk->thread_keyring->sem);
|
||||
write_lock(&tsk->thread_keyring->lock);
|
||||
tsk->thread_keyring->gid = tsk->fsgid;
|
||||
write_unlock(&tsk->thread_keyring->lock);
|
||||
up_write(&tsk->thread_keyring->sem);
|
||||
}
|
||||
|
||||
} /* end key_fsgid_changed() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the process keyrings for the first matching key
|
||||
* - we use the supplied match function to see if the description (or other
|
||||
* feature of interest) matches
|
||||
* - we return -EAGAIN if we didn't find any matching key
|
||||
* - we return -ENOKEY if we found only negative matching keys
|
||||
*/
|
||||
struct key *search_process_keyrings_aux(struct key_type *type,
|
||||
const void *description,
|
||||
key_match_func_t match)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct key *key, *ret, *err, *session;
|
||||
|
||||
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
|
||||
* searchable, but we failed to find a key or we found a negative key;
|
||||
* otherwise we want to return a sample error (probably -EACCES) if
|
||||
* none of the keyrings were searchable
|
||||
*
|
||||
* in terms of priority: success > -ENOKEY > -EAGAIN > other error
|
||||
*/
|
||||
key = NULL;
|
||||
ret = NULL;
|
||||
err = ERR_PTR(-EAGAIN);
|
||||
|
||||
/* search the thread keyring first */
|
||||
if (tsk->thread_keyring) {
|
||||
key = keyring_search_aux(tsk->thread_keyring, type,
|
||||
description, match);
|
||||
if (!IS_ERR(key))
|
||||
goto found;
|
||||
|
||||
switch (PTR_ERR(key)) {
|
||||
case -EAGAIN: /* no key */
|
||||
if (ret)
|
||||
break;
|
||||
case -ENOKEY: /* negative key */
|
||||
ret = key;
|
||||
break;
|
||||
default:
|
||||
err = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* search the process keyring second */
|
||||
if (tsk->process_keyring) {
|
||||
key = keyring_search_aux(tsk->process_keyring, type,
|
||||
description, match);
|
||||
if (!IS_ERR(key))
|
||||
goto found;
|
||||
|
||||
switch (PTR_ERR(key)) {
|
||||
case -EAGAIN: /* no key */
|
||||
if (ret)
|
||||
break;
|
||||
case -ENOKEY: /* negative key */
|
||||
ret = key;
|
||||
break;
|
||||
default:
|
||||
err = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* search the session keyring last */
|
||||
session = tsk->session_keyring;
|
||||
if (!session)
|
||||
session = tsk->user->session_keyring;
|
||||
|
||||
key = keyring_search_aux(session, type,
|
||||
description, match);
|
||||
if (!IS_ERR(key))
|
||||
goto found;
|
||||
|
||||
switch (PTR_ERR(key)) {
|
||||
case -EAGAIN: /* no key */
|
||||
if (ret)
|
||||
break;
|
||||
case -ENOKEY: /* negative key */
|
||||
ret = key;
|
||||
break;
|
||||
default:
|
||||
err = key;
|
||||
break;
|
||||
}
|
||||
|
||||
/* no key - decide on the error we're going to go for */
|
||||
key = ret ? ret : err;
|
||||
|
||||
found:
|
||||
return key;
|
||||
|
||||
} /* end search_process_keyrings_aux() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* search the process keyrings for the first matching key
|
||||
* - we return -EAGAIN if we didn't find any matching key
|
||||
* - we return -ENOKEY if we found only negative matching keys
|
||||
*/
|
||||
struct key *search_process_keyrings(struct key_type *type,
|
||||
const char *description)
|
||||
{
|
||||
return search_process_keyrings_aux(type, description, type->match);
|
||||
|
||||
} /* end search_process_keyrings() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* lookup a key given a key ID from userspace with a given permissions mask
|
||||
* - don't create special keyrings unless so requested
|
||||
* - partially constructed keys aren't found unless requested
|
||||
*/
|
||||
struct key *lookup_user_key(key_serial_t id, int create, int partial,
|
||||
key_perm_t perm)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct key *key;
|
||||
int ret;
|
||||
|
||||
key = ERR_PTR(-ENOKEY);
|
||||
|
||||
switch (id) {
|
||||
case KEY_SPEC_THREAD_KEYRING:
|
||||
if (!tsk->thread_keyring) {
|
||||
if (!create)
|
||||
goto error;
|
||||
|
||||
ret = install_thread_keyring(tsk);
|
||||
if (ret < 0) {
|
||||
key = ERR_PTR(ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
key = tsk->thread_keyring;
|
||||
atomic_inc(&key->usage);
|
||||
break;
|
||||
|
||||
case KEY_SPEC_PROCESS_KEYRING:
|
||||
if (!tsk->process_keyring) {
|
||||
if (!create)
|
||||
goto error;
|
||||
|
||||
ret = install_process_keyring(tsk);
|
||||
if (ret < 0) {
|
||||
key = ERR_PTR(ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
key = tsk->process_keyring;
|
||||
atomic_inc(&key->usage);
|
||||
break;
|
||||
|
||||
case KEY_SPEC_SESSION_KEYRING:
|
||||
if (!tsk->session_keyring) {
|
||||
/* always install a session keyring upon access if one
|
||||
* doesn't exist yet */
|
||||
ret = install_session_keyring(
|
||||
tsk, tsk->user->session_keyring);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
key = tsk->session_keyring;
|
||||
atomic_inc(&key->usage);
|
||||
break;
|
||||
|
||||
case KEY_SPEC_USER_KEYRING:
|
||||
key = tsk->user->uid_keyring;
|
||||
atomic_inc(&key->usage);
|
||||
break;
|
||||
|
||||
case KEY_SPEC_USER_SESSION_KEYRING:
|
||||
key = tsk->user->session_keyring;
|
||||
atomic_inc(&key->usage);
|
||||
break;
|
||||
|
||||
case KEY_SPEC_GROUP_KEYRING:
|
||||
/* group keyrings are not yet supported */
|
||||
key = ERR_PTR(-EINVAL);
|
||||
goto error;
|
||||
|
||||
default:
|
||||
key = ERR_PTR(-EINVAL);
|
||||
if (id < 1)
|
||||
goto error;
|
||||
|
||||
key = key_lookup(id);
|
||||
if (IS_ERR(key))
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check the status and permissions */
|
||||
if (perm) {
|
||||
ret = key_validate(key);
|
||||
if (ret < 0)
|
||||
goto invalid_key;
|
||||
}
|
||||
|
||||
ret = -EIO;
|
||||
if (!partial && !(key->flags & KEY_FLAG_INSTANTIATED))
|
||||
goto invalid_key;
|
||||
|
||||
ret = -EACCES;
|
||||
if (!key_permission(key, perm))
|
||||
goto invalid_key;
|
||||
|
||||
error:
|
||||
return key;
|
||||
|
||||
invalid_key:
|
||||
key_put(key);
|
||||
key = ERR_PTR(ret);
|
||||
goto error;
|
||||
|
||||
} /* end lookup_user_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* join the named keyring as the session keyring if possible, or attempt to
|
||||
* create a new one of that name if not
|
||||
* - if the name is NULL, an empty anonymous keyring is installed instead
|
||||
* - named session keyring joining is done with a semaphore held
|
||||
*/
|
||||
long join_session_keyring(const char *name)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct key *keyring;
|
||||
long ret;
|
||||
|
||||
/* if no name is provided, install an anonymous keyring */
|
||||
if (!name) {
|
||||
ret = install_session_keyring(tsk, NULL);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = tsk->session_keyring->serial;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* allow the user to join or create a named keyring */
|
||||
down(&key_session_sem);
|
||||
|
||||
/* look for an existing keyring of this name */
|
||||
keyring = find_keyring_by_name(name, 0);
|
||||
if (PTR_ERR(keyring) == -ENOKEY) {
|
||||
/* not found - try and create a new one */
|
||||
keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL);
|
||||
if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (IS_ERR(keyring)) {
|
||||
ret = PTR_ERR(keyring);
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* we've got a keyring - now to install it */
|
||||
ret = install_session_keyring(tsk, keyring);
|
||||
if (ret < 0)
|
||||
goto error2;
|
||||
|
||||
key_put(keyring);
|
||||
|
||||
ret = tsk->session_keyring->serial;
|
||||
|
||||
error2:
|
||||
up(&key_session_sem);
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end join_session_keyring() */
|
||||
337
extra/linux-2.6.10/security/keys/request_key.c
Normal file
337
extra/linux-2.6.10/security/keys/request_key.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/* request_key.c: request a key from userspace
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/err.h>
|
||||
#include "internal.h"
|
||||
|
||||
struct key_construction {
|
||||
struct list_head link; /* link in construction queue */
|
||||
struct key *key; /* key being constructed */
|
||||
};
|
||||
|
||||
/* when waiting for someone else's keys, you get added to this */
|
||||
DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* request userspace finish the construction of a key
|
||||
* - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
|
||||
* - if callout_info is an empty string, it'll be rendered as a "-" instead
|
||||
*/
|
||||
static int call_request_key(struct key *key,
|
||||
const char *op,
|
||||
const char *callout_info)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
char *argv[10], *envp[3], uid_str[12], gid_str[12];
|
||||
char key_str[12], keyring_str[3][12];
|
||||
int i;
|
||||
|
||||
/* record the UID and GID */
|
||||
sprintf(uid_str, "%d", current->fsuid);
|
||||
sprintf(gid_str, "%d", current->fsgid);
|
||||
|
||||
/* we say which key is under construction */
|
||||
sprintf(key_str, "%d", key->serial);
|
||||
|
||||
/* we specify the process's default keyrings */
|
||||
task_lock(current);
|
||||
sprintf(keyring_str[0], "%d",
|
||||
tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
|
||||
sprintf(keyring_str[1], "%d",
|
||||
tsk->process_keyring ? tsk->process_keyring->serial : 0);
|
||||
sprintf(keyring_str[2], "%d",
|
||||
(tsk->session_keyring ?
|
||||
tsk->session_keyring->serial :
|
||||
tsk->user->session_keyring->serial));
|
||||
task_unlock(tsk);
|
||||
|
||||
/* set up a minimal environment */
|
||||
i = 0;
|
||||
envp[i++] = "HOME=/";
|
||||
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
|
||||
envp[i] = NULL;
|
||||
|
||||
/* set up the argument list */
|
||||
i = 0;
|
||||
argv[i++] = "/sbin/request-key";
|
||||
argv[i++] = (char *) op;
|
||||
argv[i++] = key_str;
|
||||
argv[i++] = uid_str;
|
||||
argv[i++] = gid_str;
|
||||
argv[i++] = keyring_str[0];
|
||||
argv[i++] = keyring_str[1];
|
||||
argv[i++] = keyring_str[2];
|
||||
argv[i++] = callout_info[0] ? (char *) callout_info : "-";
|
||||
argv[i] = NULL;
|
||||
|
||||
/* do it */
|
||||
return call_usermodehelper(argv[0], argv, envp, 1);
|
||||
|
||||
} /* end call_request_key() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* call out to userspace for the key
|
||||
* - called with the construction sem held, but the sem is dropped here
|
||||
* - we ignore program failure and go on key status instead
|
||||
*/
|
||||
static struct key *__request_key_construction(struct key_type *type,
|
||||
const char *description,
|
||||
const char *callout_info)
|
||||
{
|
||||
struct key_construction cons;
|
||||
struct timespec now;
|
||||
struct key *key;
|
||||
int ret, negative;
|
||||
|
||||
/* create a key and add it to the queue */
|
||||
key = key_alloc(type, description,
|
||||
current->fsuid, current->fsgid, KEY_USR_ALL, 0);
|
||||
if (IS_ERR(key))
|
||||
goto alloc_failed;
|
||||
|
||||
write_lock(&key->lock);
|
||||
key->flags |= KEY_FLAG_USER_CONSTRUCT;
|
||||
write_unlock(&key->lock);
|
||||
|
||||
cons.key = key;
|
||||
list_add_tail(&cons.link, &key->user->consq);
|
||||
|
||||
/* we drop the construction sem here on behalf of the caller */
|
||||
up_write(&key_construction_sem);
|
||||
|
||||
/* make the call */
|
||||
ret = call_request_key(key, "create", callout_info);
|
||||
if (ret < 0)
|
||||
goto request_failed;
|
||||
|
||||
/* if the key wasn't instantiated, then we want to give an error */
|
||||
ret = -ENOKEY;
|
||||
if (!(key->flags & KEY_FLAG_INSTANTIATED))
|
||||
goto request_failed;
|
||||
|
||||
down_write(&key_construction_sem);
|
||||
list_del(&cons.link);
|
||||
up_write(&key_construction_sem);
|
||||
|
||||
/* also give an error if the key was negatively instantiated */
|
||||
check_not_negative:
|
||||
if (key->flags & KEY_FLAG_NEGATIVE) {
|
||||
key_put(key);
|
||||
key = ERR_PTR(-ENOKEY);
|
||||
}
|
||||
|
||||
out:
|
||||
return key;
|
||||
|
||||
request_failed:
|
||||
/* it wasn't instantiated
|
||||
* - remove from construction queue
|
||||
* - mark the key as dead
|
||||
*/
|
||||
negative = 0;
|
||||
down_write(&key_construction_sem);
|
||||
|
||||
list_del(&cons.link);
|
||||
|
||||
write_lock(&key->lock);
|
||||
key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
|
||||
|
||||
/* check it didn't get instantiated between the check and the down */
|
||||
if (!(key->flags & KEY_FLAG_INSTANTIATED)) {
|
||||
key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE;
|
||||
negative = 1;
|
||||
}
|
||||
|
||||
write_unlock(&key->lock);
|
||||
up_write(&key_construction_sem);
|
||||
|
||||
if (!negative)
|
||||
goto check_not_negative; /* surprisingly, the key got
|
||||
* instantiated */
|
||||
|
||||
/* set the timeout and store in the session keyring if we can */
|
||||
now = current_kernel_time();
|
||||
key->expiry = now.tv_sec + key_negative_timeout;
|
||||
|
||||
if (current->session_keyring)
|
||||
key_link(current->session_keyring, key);
|
||||
key_put(key);
|
||||
|
||||
/* notify anyone who was waiting */
|
||||
wake_up_all(&request_key_conswq);
|
||||
|
||||
key = ERR_PTR(ret);
|
||||
goto out;
|
||||
|
||||
alloc_failed:
|
||||
up_write(&key_construction_sem);
|
||||
goto out;
|
||||
|
||||
} /* end __request_key_construction() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* call out to userspace to request the key
|
||||
* - we check the construction queue first to see if an appropriate key is
|
||||
* already being constructed by userspace
|
||||
*/
|
||||
static struct key *request_key_construction(struct key_type *type,
|
||||
const char *description,
|
||||
struct key_user *user,
|
||||
const char *callout_info)
|
||||
{
|
||||
struct key_construction *pcons;
|
||||
struct key *key, *ckey;
|
||||
|
||||
DECLARE_WAITQUEUE(myself, current);
|
||||
|
||||
/* see if there's such a key under construction already */
|
||||
down_write(&key_construction_sem);
|
||||
|
||||
list_for_each_entry(pcons, &user->consq, link) {
|
||||
ckey = pcons->key;
|
||||
|
||||
if (ckey->type != type)
|
||||
continue;
|
||||
|
||||
if (type->match(ckey, description))
|
||||
goto found_key_under_construction;
|
||||
}
|
||||
|
||||
/* see about getting userspace to construct the key */
|
||||
key = __request_key_construction(type, description, callout_info);
|
||||
error:
|
||||
return key;
|
||||
|
||||
/* someone else has the same key under construction
|
||||
* - we want to keep an eye on their key
|
||||
*/
|
||||
found_key_under_construction:
|
||||
atomic_inc(&ckey->usage);
|
||||
up_write(&key_construction_sem);
|
||||
|
||||
/* wait for the key to be completed one way or another */
|
||||
add_wait_queue(&request_key_conswq, &myself);
|
||||
|
||||
for (;;) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
if (!(ckey->flags & KEY_FLAG_USER_CONSTRUCT))
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&request_key_conswq, &myself);
|
||||
|
||||
/* we'll need to search this process's keyrings to see if the key is
|
||||
* now there since we can't automatically assume it's also available
|
||||
* there */
|
||||
key_put(ckey);
|
||||
ckey = NULL;
|
||||
|
||||
key = NULL; /* request a retry */
|
||||
goto error;
|
||||
|
||||
} /* end request_key_construction() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* request a key
|
||||
* - search the process's keyrings
|
||||
* - check the list of keys being created or updated
|
||||
* - call out to userspace for a key if requested (supplementary info can be
|
||||
* passed)
|
||||
*/
|
||||
struct key *request_key(struct key_type *type,
|
||||
const char *description,
|
||||
const char *callout_info)
|
||||
{
|
||||
struct key_user *user;
|
||||
struct key *key;
|
||||
|
||||
/* search all the process keyrings for a key */
|
||||
key = search_process_keyrings_aux(type, description, type->match);
|
||||
|
||||
if (PTR_ERR(key) == -EAGAIN) {
|
||||
/* the search failed, but the keyrings were searchable, so we
|
||||
* should consult userspace if we can */
|
||||
key = ERR_PTR(-ENOKEY);
|
||||
if (!callout_info)
|
||||
goto error;
|
||||
|
||||
/* - get hold of the user's construction queue */
|
||||
user = key_user_lookup(current->fsuid);
|
||||
if (IS_ERR(user)) {
|
||||
key = ERR_PTR(PTR_ERR(user));
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* ask userspace (returns NULL if it waited on a key
|
||||
* being constructed) */
|
||||
key = request_key_construction(type, description,
|
||||
user, callout_info);
|
||||
if (key)
|
||||
break;
|
||||
|
||||
/* someone else made the key we want, so we need to
|
||||
* search again as it might now be available to us */
|
||||
key = search_process_keyrings_aux(type, description,
|
||||
type->match);
|
||||
if (PTR_ERR(key) != -EAGAIN)
|
||||
break;
|
||||
}
|
||||
|
||||
key_user_put(user);
|
||||
}
|
||||
|
||||
error:
|
||||
return key;
|
||||
|
||||
} /* end request_key() */
|
||||
|
||||
EXPORT_SYMBOL(request_key);
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* validate a key
|
||||
*/
|
||||
int key_validate(struct key *key)
|
||||
{
|
||||
struct timespec now;
|
||||
int ret = 0;
|
||||
|
||||
if (key) {
|
||||
/* check it's still accessible */
|
||||
ret = -EKEYREVOKED;
|
||||
if (key->flags & (KEY_FLAG_REVOKED | KEY_FLAG_DEAD))
|
||||
goto error;
|
||||
|
||||
/* check it hasn't expired */
|
||||
ret = 0;
|
||||
if (key->expiry) {
|
||||
now = current_kernel_time();
|
||||
if (now.tv_sec >= key->expiry)
|
||||
ret = -EKEYEXPIRED;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end key_validate() */
|
||||
|
||||
EXPORT_SYMBOL(key_validate);
|
||||
191
extra/linux-2.6.10/security/keys/user_defined.c
Normal file
191
extra/linux-2.6.10/security/keys/user_defined.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/* user_defined.c: user defined key type
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
static int user_instantiate(struct key *key, const void *data, size_t datalen);
|
||||
static int user_duplicate(struct key *key, const struct key *source);
|
||||
static int user_update(struct key *key, const void *data, size_t datalen);
|
||||
static int user_match(const struct key *key, const void *criterion);
|
||||
static void user_destroy(struct key *key);
|
||||
static void user_describe(const struct key *user, struct seq_file *m);
|
||||
static long user_read(const struct key *key,
|
||||
char __user *buffer, size_t buflen);
|
||||
|
||||
/*
|
||||
* user defined keys take an arbitrary string as the description and an
|
||||
* arbitrary blob of data as the payload
|
||||
*/
|
||||
struct key_type key_type_user = {
|
||||
.name = "user",
|
||||
.instantiate = user_instantiate,
|
||||
.duplicate = user_duplicate,
|
||||
.update = user_update,
|
||||
.match = user_match,
|
||||
.destroy = user_destroy,
|
||||
.describe = user_describe,
|
||||
.read = user_read,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* instantiate a user defined key
|
||||
*/
|
||||
static int user_instantiate(struct key *key, const void *data, size_t datalen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
goto error;
|
||||
|
||||
ret = key_payload_reserve(key, datalen);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
/* attach the data */
|
||||
ret = -ENOMEM;
|
||||
key->payload.data = kmalloc(datalen, GFP_KERNEL);
|
||||
if (!key->payload.data)
|
||||
goto error;
|
||||
|
||||
memcpy(key->payload.data, data, datalen);
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end user_instantiate() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* duplicate a user defined key
|
||||
*/
|
||||
static int user_duplicate(struct key *key, const struct key *source)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* just copy the payload */
|
||||
ret = -ENOMEM;
|
||||
key->payload.data = kmalloc(source->datalen, GFP_KERNEL);
|
||||
|
||||
if (key->payload.data) {
|
||||
key->datalen = source->datalen;
|
||||
memcpy(key->payload.data, source->payload.data, source->datalen);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end user_duplicate() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* update a user defined key
|
||||
*/
|
||||
static int user_update(struct key *key, const void *data, size_t datalen)
|
||||
{
|
||||
void *new, *zap;
|
||||
int ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
goto error;
|
||||
|
||||
/* copy the data */
|
||||
ret = -ENOMEM;
|
||||
new = kmalloc(datalen, GFP_KERNEL);
|
||||
if (!new)
|
||||
goto error;
|
||||
|
||||
memcpy(new, data, datalen);
|
||||
|
||||
/* check the quota and attach the new data */
|
||||
zap = new;
|
||||
write_lock(&key->lock);
|
||||
|
||||
ret = key_payload_reserve(key, datalen);
|
||||
|
||||
if (ret == 0) {
|
||||
/* attach the new data, displacing the old */
|
||||
zap = key->payload.data;
|
||||
key->payload.data = new;
|
||||
key->expiry = 0;
|
||||
}
|
||||
|
||||
write_unlock(&key->lock);
|
||||
kfree(zap);
|
||||
|
||||
error:
|
||||
return ret;
|
||||
|
||||
} /* end user_update() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* match users on their name
|
||||
*/
|
||||
static int user_match(const struct key *key, const void *description)
|
||||
{
|
||||
return strcmp(key->description, description) == 0;
|
||||
|
||||
} /* end user_match() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* dispose of the data dangling from the corpse of a user
|
||||
*/
|
||||
static void user_destroy(struct key *key)
|
||||
{
|
||||
kfree(key->payload.data);
|
||||
|
||||
} /* end user_destroy() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* describe the user
|
||||
*/
|
||||
static void user_describe(const struct key *key, struct seq_file *m)
|
||||
{
|
||||
seq_puts(m, key->description);
|
||||
|
||||
seq_printf(m, ": %u", key->datalen);
|
||||
|
||||
} /* end user_describe() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* read the key data
|
||||
*/
|
||||
static long user_read(const struct key *key,
|
||||
char __user *buffer, size_t buflen)
|
||||
{
|
||||
long ret = key->datalen;
|
||||
|
||||
/* we can return the data as is */
|
||||
if (buffer && buflen > 0) {
|
||||
if (buflen > key->datalen)
|
||||
buflen = key->datalen;
|
||||
|
||||
if (copy_to_user(buffer, key->payload.data, buflen) != 0)
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end user_read() */
|
||||
142
extra/linux-2.6.10/security/root_plug.c
Normal file
142
extra/linux-2.6.10/security/root_plug.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Root Plug sample LSM module
|
||||
*
|
||||
* Originally written for a Linux Journal.
|
||||
*
|
||||
* Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
|
||||
*
|
||||
* Prevents any programs running with egid == 0 if a specific USB device
|
||||
* is not present in the system. Yes, it can be gotten around, but is a
|
||||
* nice starting point for people to play with, and learn the LSM
|
||||
* interface.
|
||||
*
|
||||
* If you want to turn this into something with a semblance of security,
|
||||
* you need to hook the task_* functions also.
|
||||
*
|
||||
* See http://www.linuxjournal.com/article.php?sid=6279 for more information
|
||||
* about this code.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
/* flag to keep track of how we were registered */
|
||||
static int secondary;
|
||||
|
||||
/* default is a generic type of usb to serial converter */
|
||||
static int vendor_id = 0x0557;
|
||||
static int product_id = 0x2008;
|
||||
|
||||
module_param(vendor_id, uint, 0400);
|
||||
MODULE_PARM_DESC(vendor_id, "USB Vendor ID of device to look for");
|
||||
|
||||
module_param(product_id, uint, 0400);
|
||||
MODULE_PARM_DESC(product_id, "USB Product ID of device to look for");
|
||||
|
||||
/* should we print out debug messages */
|
||||
static int debug = 0;
|
||||
|
||||
module_param(debug, bool, 0600);
|
||||
MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||
|
||||
#if defined(CONFIG_SECURITY_ROOTPLUG_MODULE)
|
||||
#define MY_NAME THIS_MODULE->name
|
||||
#else
|
||||
#define MY_NAME "root_plug"
|
||||
#endif
|
||||
|
||||
#define root_dbg(fmt, arg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG "%s: %s: " fmt , \
|
||||
MY_NAME , __FUNCTION__ , \
|
||||
## arg); \
|
||||
} while (0)
|
||||
|
||||
static int rootplug_bprm_check_security (struct linux_binprm *bprm)
|
||||
{
|
||||
struct usb_device *dev;
|
||||
|
||||
root_dbg("file %s, e_uid = %d, e_gid = %d\n",
|
||||
bprm->filename, bprm->e_uid, bprm->e_gid);
|
||||
|
||||
if (bprm->e_gid == 0) {
|
||||
dev = usb_find_device(vendor_id, product_id);
|
||||
if (!dev) {
|
||||
root_dbg("e_gid = 0, and device not found, "
|
||||
"task not allowed to run...\n");
|
||||
return -EPERM;
|
||||
}
|
||||
usb_put_dev(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct security_operations rootplug_security_ops = {
|
||||
/* Use the capability functions for some of the hooks */
|
||||
.ptrace = cap_ptrace,
|
||||
.capget = cap_capget,
|
||||
.capset_check = cap_capset_check,
|
||||
.capset_set = cap_capset_set,
|
||||
.capable = cap_capable,
|
||||
|
||||
.bprm_apply_creds = cap_bprm_apply_creds,
|
||||
.bprm_set_security = cap_bprm_set_security,
|
||||
|
||||
.task_post_setuid = cap_task_post_setuid,
|
||||
.task_reparent_to_init = cap_task_reparent_to_init,
|
||||
|
||||
.bprm_check_security = rootplug_bprm_check_security,
|
||||
};
|
||||
|
||||
static int __init rootplug_init (void)
|
||||
{
|
||||
/* register ourselves with the security framework */
|
||||
if (register_security (&rootplug_security_ops)) {
|
||||
printk (KERN_INFO
|
||||
"Failure registering Root Plug module with the kernel\n");
|
||||
/* try registering with primary module */
|
||||
if (mod_reg_security (MY_NAME, &rootplug_security_ops)) {
|
||||
printk (KERN_INFO "Failure registering Root Plug "
|
||||
" module with primary security module.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
secondary = 1;
|
||||
}
|
||||
printk (KERN_INFO "Root Plug module initialized, "
|
||||
"vendor_id = %4.4x, product id = %4.4x\n", vendor_id, product_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit rootplug_exit (void)
|
||||
{
|
||||
/* remove ourselves from the security framework */
|
||||
if (secondary) {
|
||||
if (mod_unreg_security (MY_NAME, &rootplug_security_ops))
|
||||
printk (KERN_INFO "Failure unregistering Root Plug "
|
||||
" module with primary module.\n");
|
||||
} else {
|
||||
if (unregister_security (&rootplug_security_ops)) {
|
||||
printk (KERN_INFO "Failure unregistering Root Plug "
|
||||
"module with the kernel\n");
|
||||
}
|
||||
}
|
||||
printk (KERN_INFO "Root Plug module removed\n");
|
||||
}
|
||||
|
||||
security_initcall (rootplug_init);
|
||||
module_exit (rootplug_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Root Plug sample LSM module, written for Linux Journal article");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
747
extra/linux-2.6.10/security/seclvl.c
Normal file
747
extra/linux-2.6.10/security/seclvl.c
Normal file
@@ -0,0 +1,747 @@
|
||||
/**
|
||||
* BSD Secure Levels LSM
|
||||
*
|
||||
* Maintainers:
|
||||
* Michael A. Halcrow <mike@halcrow.us>
|
||||
* Serge Hallyn <hallyn@cs.wm.edu>
|
||||
*
|
||||
* Copyright (c) 2001 WireX Communications, Inc <chris@wirex.com>
|
||||
* Copyright (c) 2001 Greg Kroah-Hartman <greg@kroah.com>
|
||||
* Copyright (c) 2002 International Business Machines <robb@austin.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
|
||||
/**
|
||||
* Module parameter that defines the initial secure level.
|
||||
*
|
||||
* When built as a module, it defaults to seclvl 1, which is the
|
||||
* behavior of BSD secure levels. Note that this default behavior
|
||||
* wrecks havoc on a machine when the seclvl module is compiled into
|
||||
* the kernel. In that case, we default to seclvl 0.
|
||||
*/
|
||||
#ifdef CONFIG_SECURITY_SECLVL_MODULE
|
||||
static int initlvl = 1;
|
||||
#else
|
||||
static int initlvl;
|
||||
#endif
|
||||
module_param(initlvl, int, 0);
|
||||
MODULE_PARM_DESC(initlvl, "Initial secure level (defaults to 1)");
|
||||
|
||||
/* Module parameter that defines the verbosity level */
|
||||
static int verbosity;
|
||||
module_param(verbosity, int, 0);
|
||||
MODULE_PARM_DESC(verbosity, "Initial verbosity level (0 or 1; defaults to "
|
||||
"0, which is Quiet)");
|
||||
|
||||
/**
|
||||
* Optional password which can be passed in to bring seclvl to 0
|
||||
* (i.e., for halt/reboot). Defaults to NULL (the passwd attribute
|
||||
* file will not be registered in sysfs).
|
||||
*
|
||||
* This gets converted to its SHA1 hash when stored. It's probably
|
||||
* not a good idea to use this parameter when loading seclvl from a
|
||||
* script; use sha1_passwd instead.
|
||||
*/
|
||||
|
||||
#define MAX_PASSWD_SIZE 32
|
||||
static char passwd[MAX_PASSWD_SIZE];
|
||||
module_param_string(passwd, passwd, sizeof(passwd), 0);
|
||||
MODULE_PARM_DESC(passwd,
|
||||
"Plaintext of password that sets seclvl=0 when written to "
|
||||
"(sysfs mount point)/seclvl/passwd\n");
|
||||
|
||||
/**
|
||||
* SHA1 hashed version of the optional password which can be passed in
|
||||
* to bring seclvl to 0 (i.e., for halt/reboot). Must be in
|
||||
* hexadecimal format (40 characters). Defaults to NULL (the passwd
|
||||
* attribute file will not be registered in sysfs).
|
||||
*
|
||||
* Use the sha1sum utility to generate the SHA1 hash of a password:
|
||||
*
|
||||
* echo -n "secret" | sha1sum
|
||||
*/
|
||||
#define MAX_SHA1_PASSWD 41
|
||||
static char sha1_passwd[MAX_SHA1_PASSWD];
|
||||
module_param_string(sha1_passwd, sha1_passwd, sizeof(sha1_passwd), 0);
|
||||
MODULE_PARM_DESC(sha1_passwd,
|
||||
"SHA1 hash (40 hexadecimal characters) of password that "
|
||||
"sets seclvl=0 when plaintext password is written to "
|
||||
"(sysfs mount point)/seclvl/passwd\n");
|
||||
|
||||
static int hideHash = 1;
|
||||
module_param(hideHash, int, 0);
|
||||
MODULE_PARM_DESC(hideHash, "When set to 0, reading seclvl/passwd from sysfs "
|
||||
"will return the SHA1-hashed value of the password that "
|
||||
"lowers the secure level to 0.\n");
|
||||
|
||||
#define MY_NAME "seclvl"
|
||||
|
||||
/**
|
||||
* This time-limits log writes to one per second.
|
||||
*/
|
||||
#define seclvl_printk(verb, type, fmt, arg...) \
|
||||
do { \
|
||||
if (verbosity >= verb) { \
|
||||
static unsigned long _prior; \
|
||||
unsigned long _now = jiffies; \
|
||||
if ((_now - _prior) > HZ) { \
|
||||
printk(type "%s: %s: " fmt, \
|
||||
MY_NAME, __FUNCTION__ , \
|
||||
## arg); \
|
||||
_prior = _now; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* kobject stuff
|
||||
*/
|
||||
|
||||
struct subsystem seclvl_subsys;
|
||||
|
||||
struct seclvl_obj {
|
||||
char *name;
|
||||
struct list_head slot_list;
|
||||
struct kobject kobj;
|
||||
};
|
||||
|
||||
/**
|
||||
* There is a seclvl_attribute struct for each file in sysfs.
|
||||
*
|
||||
* In our case, we have one of these structs for "passwd" and another
|
||||
* for "seclvl".
|
||||
*/
|
||||
struct seclvl_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t(*show) (struct seclvl_obj *, char *);
|
||||
ssize_t(*store) (struct seclvl_obj *, const char *, size_t);
|
||||
};
|
||||
|
||||
/**
|
||||
* When this function is called, one of the files in sysfs is being
|
||||
* written to. attribute->store is a function pointer to whatever the
|
||||
* struct seclvl_attribute store function pointer points to. It is
|
||||
* unique for "passwd" and "seclvl".
|
||||
*/
|
||||
static ssize_t
|
||||
seclvl_attr_store(struct kobject *kobj,
|
||||
struct attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
|
||||
struct seclvl_attribute *attribute =
|
||||
container_of(attr, struct seclvl_attribute, attr);
|
||||
return (attribute->store ? attribute->store(obj, buf, len) : 0);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
seclvl_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
|
||||
{
|
||||
struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
|
||||
struct seclvl_attribute *attribute =
|
||||
container_of(attr, struct seclvl_attribute, attr);
|
||||
return (attribute->show ? attribute->show(obj, buf) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function pointers for show and store
|
||||
*/
|
||||
struct sysfs_ops seclvlfs_sysfs_ops = {
|
||||
.show = seclvl_attr_show,
|
||||
.store = seclvl_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type seclvl_ktype = {
|
||||
.sysfs_ops = &seclvlfs_sysfs_ops
|
||||
};
|
||||
|
||||
decl_subsys(seclvl, &seclvl_ktype, NULL);
|
||||
|
||||
/**
|
||||
* The actual security level. Ranges between -1 and 2 inclusive.
|
||||
*/
|
||||
static int seclvl;
|
||||
|
||||
/**
|
||||
* flag to keep track of how we were registered
|
||||
*/
|
||||
static int secondary;
|
||||
|
||||
/**
|
||||
* Verifies that the requested secure level is valid, given the current
|
||||
* secure level.
|
||||
*/
|
||||
static int seclvl_sanity(int reqlvl)
|
||||
{
|
||||
if ((reqlvl < -1) || (reqlvl > 2)) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to set seclvl out of "
|
||||
"range: [%d]\n", reqlvl);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((seclvl == 0) && (reqlvl == -1))
|
||||
return 0;
|
||||
if (reqlvl < seclvl) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to lower seclvl to "
|
||||
"[%d]\n", reqlvl);
|
||||
return -EPERM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the user reads the sysfs handle to this kernel
|
||||
* object
|
||||
*/
|
||||
static ssize_t seclvl_read_file(struct seclvl_obj *obj, char *buff)
|
||||
{
|
||||
return snprintf(buff, PAGE_SIZE, "%d\n", seclvl);
|
||||
}
|
||||
|
||||
/**
|
||||
* security level advancement rules:
|
||||
* Valid levels are -1 through 2, inclusive.
|
||||
* From -1, stuck. [ in case compiled into kernel ]
|
||||
* From 0 or above, can only increment.
|
||||
*/
|
||||
static int do_seclvl_advance(int newlvl)
|
||||
{
|
||||
if (newlvl <= seclvl) {
|
||||
seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
|
||||
"[%d]\n", newlvl);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (newlvl > 2) {
|
||||
seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
|
||||
"[%d]\n", newlvl);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (seclvl == -1) {
|
||||
seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "
|
||||
"seclvl [%d]\n", seclvl);
|
||||
return -EPERM;
|
||||
}
|
||||
seclvl = newlvl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the user writes to the sysfs handle to this kernel
|
||||
* object (seclvl/seclvl). It expects a single-digit number.
|
||||
*/
|
||||
static ssize_t
|
||||
seclvl_write_file(struct seclvl_obj *obj, const char *buff, size_t count)
|
||||
{
|
||||
unsigned long val;
|
||||
if (count > 2 || (count == 2 && buff[1] != '\n')) {
|
||||
seclvl_printk(1, KERN_WARNING, "Invalid value passed to "
|
||||
"seclvl: [%s]\n", buff);
|
||||
return -EINVAL;
|
||||
}
|
||||
val = buff[0] - 48;
|
||||
if (seclvl_sanity(val)) {
|
||||
seclvl_printk(1, KERN_WARNING, "Illegal secure level "
|
||||
"requested: [%d]\n", (int)val);
|
||||
return -EPERM;
|
||||
}
|
||||
if (do_seclvl_advance(val)) {
|
||||
seclvl_printk(0, KERN_ERR, "Failure advancing security level "
|
||||
"to %lu\n", val);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Generate sysfs_attr_seclvl */
|
||||
struct seclvl_attribute sysfs_attr_seclvl =
|
||||
__ATTR(seclvl, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_file,
|
||||
seclvl_write_file);
|
||||
|
||||
static unsigned char hashedPassword[SHA1_DIGEST_SIZE];
|
||||
|
||||
/**
|
||||
* Called whenever the user reads the sysfs passwd handle.
|
||||
*/
|
||||
static ssize_t seclvl_read_passwd(struct seclvl_obj *obj, char *buff)
|
||||
{
|
||||
/* So just how good *is* your password? :-) */
|
||||
char tmp[3];
|
||||
int i = 0;
|
||||
buff[0] = '\0';
|
||||
if (hideHash) {
|
||||
/* Security through obscurity */
|
||||
return 0;
|
||||
}
|
||||
while (i < SHA1_DIGEST_SIZE) {
|
||||
snprintf(tmp, 3, "%02x", hashedPassword[i]);
|
||||
strncat(buff, tmp, 2);
|
||||
i++;
|
||||
}
|
||||
strcat(buff, "\n");
|
||||
return ((SHA1_DIGEST_SIZE * 2) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a block of plaintext of into its SHA1 hashed value.
|
||||
*
|
||||
* It would be nice if crypto had a wrapper to do this for us linear
|
||||
* people...
|
||||
*/
|
||||
static int
|
||||
plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len)
|
||||
{
|
||||
char *pgVirtAddr;
|
||||
struct crypto_tfm *tfm;
|
||||
struct scatterlist sg[1];
|
||||
if (len > PAGE_SIZE) {
|
||||
seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d "
|
||||
"characters). Largest possible is %lu "
|
||||
"bytes.\n", len, PAGE_SIZE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
tfm = crypto_alloc_tfm("sha1", 0);
|
||||
if (tfm == NULL) {
|
||||
seclvl_printk(0, KERN_ERR,
|
||||
"Failed to load transform for SHA1\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
// Just get a new page; don't play around with page boundaries
|
||||
// and scatterlists.
|
||||
pgVirtAddr = (char *)__get_free_page(GFP_KERNEL);
|
||||
sg[0].page = virt_to_page(pgVirtAddr);
|
||||
sg[0].offset = 0;
|
||||
sg[0].length = len;
|
||||
strncpy(pgVirtAddr, plaintext, len);
|
||||
crypto_digest_init(tfm);
|
||||
crypto_digest_update(tfm, sg, 1);
|
||||
crypto_digest_final(tfm, hash);
|
||||
crypto_free_tfm(tfm);
|
||||
free_page((unsigned long)pgVirtAddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the user writes to the sysfs passwd handle to this kernel
|
||||
* object. It hashes the password and compares the hashed results.
|
||||
*/
|
||||
static ssize_t
|
||||
seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)
|
||||
{
|
||||
int i;
|
||||
unsigned char tmp[SHA1_DIGEST_SIZE];
|
||||
int rc;
|
||||
int len;
|
||||
if (!*passwd && !*sha1_passwd) {
|
||||
seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "
|
||||
"seclvl module, but neither a plain text "
|
||||
"password nor a SHA1 hashed password was "
|
||||
"passed in as a module parameter! This is a "
|
||||
"bug, since it should not be possible to be in "
|
||||
"this part of the module; please tell a "
|
||||
"maintainer about this event.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
len = strlen(buff);
|
||||
/* ``echo "secret" > seclvl/passwd'' includes a newline */
|
||||
if (buff[len - 1] == '\n') {
|
||||
len--;
|
||||
}
|
||||
/* Hash the password, then compare the hashed values */
|
||||
if ((rc = plaintext_to_sha1(tmp, buff, len))) {
|
||||
seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
|
||||
"[%d]\n", rc);
|
||||
return rc;
|
||||
}
|
||||
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
|
||||
if (hashedPassword[i] != tmp[i]) {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
seclvl_printk(0, KERN_INFO,
|
||||
"Password accepted; seclvl reduced to 0.\n");
|
||||
seclvl = 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Generate sysfs_attr_passwd */
|
||||
struct seclvl_attribute sysfs_attr_passwd =
|
||||
__ATTR(passwd, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_passwd,
|
||||
seclvl_write_passwd);
|
||||
|
||||
/**
|
||||
* Explicitely disallow ptrace'ing the init process.
|
||||
*/
|
||||
static int seclvl_ptrace(struct task_struct *parent, struct task_struct *child)
|
||||
{
|
||||
if (seclvl >= 0) {
|
||||
if (child->pid == 1) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to ptrace "
|
||||
"the init process dissallowed in "
|
||||
"secure level %d\n", seclvl);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capability checks for seclvl. The majority of the policy
|
||||
* enforcement for seclvl takes place here.
|
||||
*/
|
||||
static int seclvl_capable(struct task_struct *tsk, int cap)
|
||||
{
|
||||
/* init can do anything it wants */
|
||||
if (tsk->pid == 1)
|
||||
return 0;
|
||||
|
||||
switch (seclvl) {
|
||||
case 2:
|
||||
/* fall through */
|
||||
case 1:
|
||||
if (cap == CAP_LINUX_IMMUTABLE) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to modify "
|
||||
"the IMMUTABLE and/or APPEND extended "
|
||||
"attribute on a file with the IMMUTABLE "
|
||||
"and/or APPEND extended attribute set "
|
||||
"denied in seclvl [%d]\n", seclvl);
|
||||
return -EPERM;
|
||||
} else if (cap == CAP_SYS_RAWIO) { // Somewhat broad...
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to perform "
|
||||
"raw I/O while in secure level [%d] "
|
||||
"denied\n", seclvl);
|
||||
return -EPERM;
|
||||
} else if (cap == CAP_NET_ADMIN) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to perform "
|
||||
"network administrative task while "
|
||||
"in secure level [%d] denied\n", seclvl);
|
||||
return -EPERM;
|
||||
} else if (cap == CAP_SETUID) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to setuid "
|
||||
"while in secure level [%d] denied\n",
|
||||
seclvl);
|
||||
return -EPERM;
|
||||
} else if (cap == CAP_SETGID) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to setgid "
|
||||
"while in secure level [%d] denied\n",
|
||||
seclvl);
|
||||
} else if (cap == CAP_SYS_MODULE) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to perform "
|
||||
"a module operation while in secure "
|
||||
"level [%d] denied\n", seclvl);
|
||||
return -EPERM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* from dummy.c */
|
||||
if (cap_is_fs_cap(cap) ? tsk->fsuid == 0 : tsk->euid == 0)
|
||||
return 0; /* capability granted */
|
||||
seclvl_printk(1, KERN_WARNING, "Capability denied\n");
|
||||
return -EPERM; /* capability denied */
|
||||
}
|
||||
|
||||
/**
|
||||
* Disallow reversing the clock in seclvl > 1
|
||||
*/
|
||||
static int seclvl_settime(struct timespec *tv, struct timezone *tz)
|
||||
{
|
||||
struct timespec now;
|
||||
if (seclvl > 1) {
|
||||
now = current_kernel_time();
|
||||
if (tv->tv_sec < now.tv_sec ||
|
||||
(tv->tv_sec == now.tv_sec && tv->tv_nsec < now.tv_nsec)) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to decrement "
|
||||
"time in secure level %d denied: "
|
||||
"current->pid = [%d], "
|
||||
"current->group_leader->pid = [%d]\n",
|
||||
seclvl, current->pid,
|
||||
current->group_leader->pid);
|
||||
return -EPERM;
|
||||
} /* if attempt to decrement time */
|
||||
} /* if seclvl > 1 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* claim the blockdev to exclude mounters, release on file close */
|
||||
static int seclvl_bd_claim(struct inode *inode)
|
||||
{
|
||||
int holder;
|
||||
struct block_device *bdev = NULL;
|
||||
dev_t dev = inode->i_rdev;
|
||||
bdev = open_by_devnum(dev, FMODE_WRITE);
|
||||
if (bdev) {
|
||||
if (bd_claim(bdev, &holder)) {
|
||||
blkdev_put(bdev);
|
||||
return -EPERM;
|
||||
}
|
||||
/* claimed, mark it to release on close */
|
||||
inode->i_security = current;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* release the blockdev if you claimed it */
|
||||
static void seclvl_bd_release(struct inode *inode)
|
||||
{
|
||||
if (inode && S_ISBLK(inode->i_mode) && inode->i_security == current) {
|
||||
struct block_device *bdev = inode->i_bdev;
|
||||
if (bdev) {
|
||||
bd_release(bdev);
|
||||
blkdev_put(bdev);
|
||||
inode->i_security = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Security for writes to block devices is regulated by this seclvl
|
||||
* function. Deny all writes to block devices in seclvl 2. In
|
||||
* seclvl 1, we only deny writes to *mounted* block devices.
|
||||
*/
|
||||
static int
|
||||
seclvl_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
{
|
||||
if (current->pid != 1 && S_ISBLK(inode->i_mode) && (mask & MAY_WRITE)) {
|
||||
switch (seclvl) {
|
||||
case 2:
|
||||
seclvl_printk(1, KERN_WARNING, "Write to block device "
|
||||
"denied in secure level [%d]\n", seclvl);
|
||||
return -EPERM;
|
||||
case 1:
|
||||
if (seclvl_bd_claim(inode)) {
|
||||
seclvl_printk(1, KERN_WARNING,
|
||||
"Write to mounted block device "
|
||||
"denied in secure level [%d]\n",
|
||||
seclvl);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The SUID and SGID bits cannot be set in seclvl >= 1
|
||||
*/
|
||||
static int seclvl_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
{
|
||||
if (seclvl > 0) {
|
||||
if (iattr->ia_valid & ATTR_MODE)
|
||||
if (iattr->ia_mode & S_ISUID ||
|
||||
iattr->ia_mode & S_ISGID) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to "
|
||||
"modify SUID or SGID bit "
|
||||
"denied in seclvl [%d]\n",
|
||||
seclvl);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* release busied block devices */
|
||||
static void seclvl_file_free_security(struct file *filp)
|
||||
{
|
||||
struct dentry *dentry = filp->f_dentry;
|
||||
struct inode *inode = NULL;
|
||||
|
||||
if (dentry) {
|
||||
inode = dentry->d_inode;
|
||||
seclvl_bd_release(inode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cannot unmount in secure level 2
|
||||
*/
|
||||
static int seclvl_umount(struct vfsmount *mnt, int flags)
|
||||
{
|
||||
if (current->pid == 1) {
|
||||
return 0;
|
||||
}
|
||||
if (seclvl == 2) {
|
||||
seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure "
|
||||
"level %d\n", seclvl);
|
||||
return -EPERM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct security_operations seclvl_ops = {
|
||||
.ptrace = seclvl_ptrace,
|
||||
.capable = seclvl_capable,
|
||||
.inode_permission = seclvl_inode_permission,
|
||||
.inode_setattr = seclvl_inode_setattr,
|
||||
.file_free_security = seclvl_file_free_security,
|
||||
.settime = seclvl_settime,
|
||||
.sb_umount = seclvl_umount,
|
||||
};
|
||||
|
||||
/**
|
||||
* Process the password-related module parameters
|
||||
*/
|
||||
static int processPassword(void)
|
||||
{
|
||||
int rc = 0;
|
||||
hashedPassword[0] = '\0';
|
||||
if (*passwd) {
|
||||
if (*sha1_passwd) {
|
||||
seclvl_printk(0, KERN_ERR, "Error: Both "
|
||||
"passwd and sha1_passwd "
|
||||
"were set, but they are mutually "
|
||||
"exclusive.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((rc = plaintext_to_sha1(hashedPassword, passwd,
|
||||
strlen(passwd)))) {
|
||||
seclvl_printk(0, KERN_ERR, "Error: SHA1 support not "
|
||||
"in kernel\n");
|
||||
return rc;
|
||||
}
|
||||
/* All static data goes to the BSS, which zero's the
|
||||
* plaintext password out for us. */
|
||||
} else if (*sha1_passwd) { // Base 16
|
||||
int i;
|
||||
i = strlen(sha1_passwd);
|
||||
if (i != (SHA1_DIGEST_SIZE * 2)) {
|
||||
seclvl_printk(0, KERN_ERR, "Received [%d] bytes; "
|
||||
"expected [%d] for the hexadecimal "
|
||||
"representation of the SHA1 hash of "
|
||||
"the password.\n",
|
||||
i, (SHA1_DIGEST_SIZE * 2));
|
||||
return -EINVAL;
|
||||
}
|
||||
while ((i -= 2) + 2) {
|
||||
unsigned char tmp;
|
||||
tmp = sha1_passwd[i + 2];
|
||||
sha1_passwd[i + 2] = '\0';
|
||||
hashedPassword[i / 2] = (unsigned char)
|
||||
simple_strtol(&sha1_passwd[i], NULL, 16);
|
||||
sha1_passwd[i + 2] = tmp;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sysfs registrations
|
||||
*/
|
||||
static int doSysfsRegistrations(void)
|
||||
{
|
||||
int rc = 0;
|
||||
if ((rc = subsystem_register(&seclvl_subsys))) {
|
||||
seclvl_printk(0, KERN_WARNING,
|
||||
"Error [%d] registering seclvl subsystem\n", rc);
|
||||
return rc;
|
||||
}
|
||||
sysfs_create_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);
|
||||
if (*passwd || *sha1_passwd) {
|
||||
sysfs_create_file(&seclvl_subsys.kset.kobj,
|
||||
&sysfs_attr_passwd.attr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the seclvl module.
|
||||
*/
|
||||
static int __init seclvl_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
if (verbosity < 0 || verbosity > 1) {
|
||||
printk(KERN_ERR "Error: bad verbosity [%d]; only 0 or 1 "
|
||||
"are valid values\n", verbosity);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
sysfs_attr_seclvl.attr.owner = THIS_MODULE;
|
||||
sysfs_attr_passwd.attr.owner = THIS_MODULE;
|
||||
if (initlvl < -1 || initlvl > 2) {
|
||||
seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "
|
||||
"[%d].\n", initlvl);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
seclvl = initlvl;
|
||||
if ((rc = processPassword())) {
|
||||
seclvl_printk(0, KERN_ERR, "Error processing the password "
|
||||
"module parameter(s): rc = [%d]\n", rc);
|
||||
goto exit;
|
||||
}
|
||||
/* register ourselves with the security framework */
|
||||
if (register_security(&seclvl_ops)) {
|
||||
seclvl_printk(0, KERN_ERR,
|
||||
"seclvl: Failure registering with the "
|
||||
"kernel.\n");
|
||||
/* try registering with primary module */
|
||||
rc = mod_reg_security(MY_NAME, &seclvl_ops);
|
||||
if (rc) {
|
||||
seclvl_printk(0, KERN_ERR, "seclvl: Failure "
|
||||
"registering with primary security "
|
||||
"module.\n");
|
||||
goto exit;
|
||||
} /* if primary module registered */
|
||||
secondary = 1;
|
||||
} /* if we registered ourselves with the security framework */
|
||||
if ((rc = doSysfsRegistrations())) {
|
||||
seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
|
||||
goto exit;
|
||||
}
|
||||
seclvl_printk(0, KERN_INFO, "seclvl: Successfully initialized.\n");
|
||||
exit:
|
||||
if (rc) {
|
||||
printk(KERN_ERR "seclvl: Error during initialization: rc = "
|
||||
"[%d]\n", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the seclvl module.
|
||||
*/
|
||||
static void __exit seclvl_exit(void)
|
||||
{
|
||||
sysfs_remove_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);
|
||||
if (*passwd || *sha1_passwd) {
|
||||
sysfs_remove_file(&seclvl_subsys.kset.kobj,
|
||||
&sysfs_attr_passwd.attr);
|
||||
}
|
||||
subsystem_unregister(&seclvl_subsys);
|
||||
if (secondary == 1) {
|
||||
mod_unreg_security(MY_NAME, &seclvl_ops);
|
||||
} else if (unregister_security(&seclvl_ops)) {
|
||||
seclvl_printk(0, KERN_INFO,
|
||||
"seclvl: Failure unregistering with the "
|
||||
"kernel\n");
|
||||
}
|
||||
}
|
||||
|
||||
module_init(seclvl_init);
|
||||
module_exit(seclvl_exit);
|
||||
|
||||
MODULE_AUTHOR("Michael A. Halcrow <mike@halcrow.us>");
|
||||
MODULE_DESCRIPTION("LSM implementation of the BSD Secure Levels");
|
||||
MODULE_LICENSE("GPL");
|
||||
203
extra/linux-2.6.10/security/security.c
Normal file
203
extra/linux-2.6.10/security/security.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Security plug functions
|
||||
*
|
||||
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
|
||||
* Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
|
||||
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#define SECURITY_FRAMEWORK_VERSION "1.0.0"
|
||||
|
||||
/* things that live in dummy.c */
|
||||
extern struct security_operations dummy_security_ops;
|
||||
extern void security_fixup_ops(struct security_operations *ops);
|
||||
|
||||
struct security_operations *security_ops; /* Initialized to NULL */
|
||||
|
||||
static inline int verify(struct security_operations *ops)
|
||||
{
|
||||
/* verify the security_operations structure exists */
|
||||
if (!ops)
|
||||
return -EINVAL;
|
||||
security_fixup_ops(ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init do_security_initcalls(void)
|
||||
{
|
||||
initcall_t *call;
|
||||
call = &__security_initcall_start;
|
||||
while (call < &__security_initcall_end) {
|
||||
(*call) ();
|
||||
call++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* security_init - initializes the security framework
|
||||
*
|
||||
* This should be called early in the kernel initialization sequence.
|
||||
*/
|
||||
int __init security_init(void)
|
||||
{
|
||||
printk(KERN_INFO "Security Framework v" SECURITY_FRAMEWORK_VERSION
|
||||
" initialized\n");
|
||||
|
||||
if (verify(&dummy_security_ops)) {
|
||||
printk(KERN_ERR "%s could not verify "
|
||||
"dummy_security_ops structure.\n", __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
security_ops = &dummy_security_ops;
|
||||
do_security_initcalls();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* register_security - registers a security framework with the kernel
|
||||
* @ops: a pointer to the struct security_options that is to be registered
|
||||
*
|
||||
* This function is to allow a security module to register itself with the
|
||||
* kernel security subsystem. Some rudimentary checking is done on the @ops
|
||||
* value passed to this function. A call to unregister_security() should be
|
||||
* done to remove this security_options structure from the kernel.
|
||||
*
|
||||
* If there is already a security module registered with the kernel,
|
||||
* an error will be returned. Otherwise 0 is returned on success.
|
||||
*/
|
||||
int register_security(struct security_operations *ops)
|
||||
{
|
||||
if (verify(ops)) {
|
||||
printk(KERN_DEBUG "%s could not verify "
|
||||
"security_operations structure.\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (security_ops != &dummy_security_ops)
|
||||
return -EAGAIN;
|
||||
|
||||
security_ops = ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister_security - unregisters a security framework with the kernel
|
||||
* @ops: a pointer to the struct security_options that is to be registered
|
||||
*
|
||||
* This function removes a struct security_operations variable that had
|
||||
* previously been registered with a successful call to register_security().
|
||||
*
|
||||
* If @ops does not match the valued previously passed to register_security()
|
||||
* an error is returned. Otherwise the default security options is set to the
|
||||
* the dummy_security_ops structure, and 0 is returned.
|
||||
*/
|
||||
int unregister_security(struct security_operations *ops)
|
||||
{
|
||||
if (ops != security_ops) {
|
||||
printk(KERN_INFO "%s: trying to unregister "
|
||||
"a security_opts structure that is not "
|
||||
"registered, failing.\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
security_ops = &dummy_security_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mod_reg_security - allows security modules to be "stacked"
|
||||
* @name: a pointer to a string with the name of the security_options to be registered
|
||||
* @ops: a pointer to the struct security_options that is to be registered
|
||||
*
|
||||
* This function allows security modules to be stacked if the currently loaded
|
||||
* security module allows this to happen. It passes the @name and @ops to the
|
||||
* register_security function of the currently loaded security module.
|
||||
*
|
||||
* The return value depends on the currently loaded security module, with 0 as
|
||||
* success.
|
||||
*/
|
||||
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__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ops == security_ops) {
|
||||
printk(KERN_INFO "%s security operations "
|
||||
"already registered.\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return security_ops->register_security(name, ops);
|
||||
}
|
||||
|
||||
/**
|
||||
* mod_unreg_security - allows a security module registered with mod_reg_security() to be unloaded
|
||||
* @name: a pointer to a string with the name of the security_options to be removed
|
||||
* @ops: a pointer to the struct security_options that is to be removed
|
||||
*
|
||||
* This function allows security modules that have been successfully registered
|
||||
* with a call to mod_reg_security() to be unloaded from the system.
|
||||
* This calls the currently loaded security module's unregister_security() call
|
||||
* with the @name and @ops variables.
|
||||
*
|
||||
* The return value depends on the currently loaded security module, with 0 as
|
||||
* success.
|
||||
*/
|
||||
int mod_unreg_security(const char *name, struct security_operations *ops)
|
||||
{
|
||||
if (ops == security_ops) {
|
||||
printk(KERN_INFO "%s invalid attempt to unregister "
|
||||
" primary security ops.\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return security_ops->unregister_security(name, ops);
|
||||
}
|
||||
|
||||
/**
|
||||
* capable - calls the currently loaded security module's capable() function with the specified capability
|
||||
* @cap: the requested capability level.
|
||||
*
|
||||
* This function calls the currently loaded security module's capable()
|
||||
* function with a pointer to the current task and the specified @cap value.
|
||||
*
|
||||
* This allows the security module to implement the capable function call
|
||||
* however it chooses to.
|
||||
*/
|
||||
int capable(int cap)
|
||||
{
|
||||
if (security_ops->capable(current, cap)) {
|
||||
/* capability denied */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* capability granted */
|
||||
current->flags |= PF_SUPERPRIV;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(register_security);
|
||||
EXPORT_SYMBOL_GPL(unregister_security);
|
||||
EXPORT_SYMBOL_GPL(mod_reg_security);
|
||||
EXPORT_SYMBOL_GPL(mod_unreg_security);
|
||||
EXPORT_SYMBOL(capable);
|
||||
EXPORT_SYMBOL(security_ops);
|
||||
78
extra/linux-2.6.10/security/selinux/Kconfig
Normal file
78
extra/linux-2.6.10/security/selinux/Kconfig
Normal file
@@ -0,0 +1,78 @@
|
||||
config SECURITY_SELINUX
|
||||
bool "NSA SELinux Support"
|
||||
depends on SECURITY && NET
|
||||
default n
|
||||
help
|
||||
This selects NSA Security-Enhanced Linux (SELinux).
|
||||
You will also need a policy configuration and a labeled filesystem.
|
||||
You can obtain the policy compiler (checkpolicy), the utility for
|
||||
labeling filesystems (setfiles), and an example policy configuration
|
||||
from <http://www.nsa.gov/selinux/>.
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_SELINUX_BOOTPARAM
|
||||
bool "NSA SELinux boot parameter"
|
||||
depends on SECURITY_SELINUX
|
||||
default n
|
||||
help
|
||||
This option adds a kernel parameter 'selinux', which allows SELinux
|
||||
to be disabled at boot. If this option is selected, SELinux
|
||||
functionality can be disabled with selinux=0 on the kernel
|
||||
command line. The purpose of this option is to allow a single
|
||||
kernel image to be distributed with SELinux built in, but not
|
||||
necessarily enabled.
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_SELINUX_BOOTPARAM_VALUE
|
||||
int "NSA SELinux boot parameter default value"
|
||||
depends on SECURITY_SELINUX_BOOTPARAM
|
||||
range 0 1
|
||||
default 1
|
||||
help
|
||||
This option sets the default value for the kernel parameter
|
||||
'selinux', which allows SELinux to be disabled at boot. If this
|
||||
option is set to 0 (zero), the SELinux kernel parameter will
|
||||
default to 0, disabling SELinux at bootup. If this option is
|
||||
set to 1 (one), the SELinux kernel paramater will default to 1,
|
||||
enabling SELinux at bootup.
|
||||
|
||||
If you are unsure how to answer this question, answer 1.
|
||||
|
||||
config SECURITY_SELINUX_DISABLE
|
||||
bool "NSA SELinux runtime disable"
|
||||
depends on SECURITY_SELINUX
|
||||
default n
|
||||
help
|
||||
This option enables writing to a selinuxfs node 'disable', which
|
||||
allows SELinux to be disabled at runtime prior to the policy load.
|
||||
SELinux will then remain disabled until the next boot.
|
||||
This option is similar to the selinux=0 boot parameter, but is to
|
||||
support runtime disabling of SELinux, e.g. from /sbin/init, for
|
||||
portability across platforms where boot parameters are difficult
|
||||
to employ.
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
config SECURITY_SELINUX_DEVELOP
|
||||
bool "NSA SELinux Development Support"
|
||||
depends on SECURITY_SELINUX
|
||||
default y
|
||||
help
|
||||
This enables the development support option of NSA SELinux,
|
||||
which is useful for experimenting with SELinux and developing
|
||||
policies. If unsure, say Y. With this option enabled, the
|
||||
kernel will start in permissive mode (log everything, deny nothing)
|
||||
unless you specify enforcing=1 on the kernel command line. You
|
||||
can interactively toggle the kernel between enforcing mode and
|
||||
permissive mode (if permitted by the policy) via /selinux/enforce.
|
||||
|
||||
config SECURITY_SELINUX_MLS
|
||||
bool "NSA SELinux MLS policy (EXPERIMENTAL)"
|
||||
depends on SECURITY_SELINUX && EXPERIMENTAL
|
||||
default n
|
||||
help
|
||||
This enables the NSA SELinux Multi-Level Security (MLS) policy in
|
||||
addition to the default RBAC/TE policy. This policy is
|
||||
experimental and has not been configured for use. Unless you
|
||||
specifically want to experiment with MLS, say N.
|
||||
12
extra/linux-2.6.10/security/selinux/Makefile
Normal file
12
extra/linux-2.6.10/security/selinux/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Makefile for building the SELinux module as part of the kernel tree.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
|
||||
|
||||
selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
|
||||
|
||||
selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
|
||||
|
||||
EXTRA_CFLAGS += -Isecurity/selinux/include
|
||||
|
||||
1068
extra/linux-2.6.10/security/selinux/avc.c
Normal file
1068
extra/linux-2.6.10/security/selinux/avc.c
Normal file
File diff suppressed because it is too large
Load Diff
4492
extra/linux-2.6.10/security/selinux/hooks.c
Normal file
4492
extra/linux-2.6.10/security/selinux/hooks.c
Normal file
File diff suppressed because it is too large
Load Diff
44
extra/linux-2.6.10/security/selinux/include/av_inherit.h
Normal file
44
extra/linux-2.6.10/security/selinux/include/av_inherit.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* This file is automatically generated. Do not edit. */
|
||||
/* FLASK */
|
||||
|
||||
struct av_inherit
|
||||
{
|
||||
u16 tclass;
|
||||
char **common_pts;
|
||||
u32 common_base;
|
||||
};
|
||||
|
||||
static struct av_inherit av_inherit[] = {
|
||||
{ SECCLASS_DIR, common_file_perm_to_string, 0x00020000UL },
|
||||
{ SECCLASS_FILE, common_file_perm_to_string, 0x00020000UL },
|
||||
{ SECCLASS_LNK_FILE, common_file_perm_to_string, 0x00020000UL },
|
||||
{ SECCLASS_CHR_FILE, common_file_perm_to_string, 0x00020000UL },
|
||||
{ SECCLASS_BLK_FILE, common_file_perm_to_string, 0x00020000UL },
|
||||
{ SECCLASS_SOCK_FILE, common_file_perm_to_string, 0x00020000UL },
|
||||
{ SECCLASS_FIFO_FILE, common_file_perm_to_string, 0x00020000UL },
|
||||
{ SECCLASS_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_TCP_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_UDP_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_RAWIP_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_PACKET_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_KEY_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_UNIX_STREAM_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_UNIX_DGRAM_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_IPC, common_ipc_perm_to_string, 0x00000200UL },
|
||||
{ SECCLASS_SEM, common_ipc_perm_to_string, 0x00000200UL },
|
||||
{ SECCLASS_MSGQ, common_ipc_perm_to_string, 0x00000200UL },
|
||||
{ SECCLASS_SHM, common_ipc_perm_to_string, 0x00000200UL },
|
||||
{ SECCLASS_NETLINK_ROUTE_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_FIREWALL_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_TCPDIAG_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_NFLOG_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_XFRM_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_SELINUX_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_AUDIT_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_IP6FW_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
{ SECCLASS_NETLINK_DNRT_SOCKET, common_socket_perm_to_string, 0x00400000UL },
|
||||
};
|
||||
|
||||
|
||||
/* FLASK */
|
||||
225
extra/linux-2.6.10/security/selinux/include/av_perm_to_string.h
Normal file
225
extra/linux-2.6.10/security/selinux/include/av_perm_to_string.h
Normal file
@@ -0,0 +1,225 @@
|
||||
/* This file is automatically generated. Do not edit. */
|
||||
/* FLASK */
|
||||
|
||||
struct av_perm_to_string
|
||||
{
|
||||
u16 tclass;
|
||||
u32 value;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static struct av_perm_to_string av_perm_to_string[] = {
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod" },
|
||||
{ SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget" },
|
||||
{ SECCLASS_DIR, DIR__ADD_NAME, "add_name" },
|
||||
{ SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name" },
|
||||
{ SECCLASS_DIR, DIR__REPARENT, "reparent" },
|
||||
{ SECCLASS_DIR, DIR__SEARCH, "search" },
|
||||
{ SECCLASS_DIR, DIR__RMDIR, "rmdir" },
|
||||
{ SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans" },
|
||||
{ SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint" },
|
||||
{ SECCLASS_FD, FD__USE, "use" },
|
||||
{ SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto" },
|
||||
{ SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn" },
|
||||
{ SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom" },
|
||||
{ SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind" },
|
||||
{ SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind" },
|
||||
{ SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind" },
|
||||
{ SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv" },
|
||||
{ SECCLASS_NODE, NODE__TCP_SEND, "tcp_send" },
|
||||
{ SECCLASS_NODE, NODE__UDP_RECV, "udp_recv" },
|
||||
{ SECCLASS_NODE, NODE__UDP_SEND, "udp_send" },
|
||||
{ SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv" },
|
||||
{ SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send" },
|
||||
{ SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest" },
|
||||
{ SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv" },
|
||||
{ SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send" },
|
||||
{ SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv" },
|
||||
{ SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send" },
|
||||
{ SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv" },
|
||||
{ SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send" },
|
||||
{ SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto" },
|
||||
{ SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn" },
|
||||
{ SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom" },
|
||||
{ SECCLASS_PROCESS, PROCESS__FORK, "fork" },
|
||||
{ SECCLASS_PROCESS, PROCESS__TRANSITION, "transition" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SIGNULL, "signull" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SIGNAL, "signal" },
|
||||
{ SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace" },
|
||||
{ SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched" },
|
||||
{ SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession" },
|
||||
{ SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid" },
|
||||
{ SECCLASS_PROCESS, PROCESS__GETCAP, "getcap" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SETCAP, "setcap" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SHARE, "share" },
|
||||
{ SECCLASS_PROCESS, PROCESS__GETATTR, "getattr" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate" },
|
||||
{ SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SIGINH, "siginh" },
|
||||
{ SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit" },
|
||||
{ SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh" },
|
||||
{ SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue" },
|
||||
{ SECCLASS_MSG, MSG__SEND, "send" },
|
||||
{ SECCLASS_MSG, MSG__RECEIVE, "receive" },
|
||||
{ SECCLASS_SHM, SHM__LOCK, "lock" },
|
||||
{ SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av" },
|
||||
{ SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create" },
|
||||
{ SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member" },
|
||||
{ SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context" },
|
||||
{ SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy" },
|
||||
{ SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel" },
|
||||
{ SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user" },
|
||||
{ SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce" },
|
||||
{ SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool" },
|
||||
{ SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info" },
|
||||
{ SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read" },
|
||||
{ SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod" },
|
||||
{ SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod" },
|
||||
{ SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease" },
|
||||
{ SECCLASS_PASSWD, PASSWD__PASSWD, "passwd" },
|
||||
{ SECCLASS_PASSWD, PASSWD__CHFN, "chfn" },
|
||||
{ SECCLASS_PASSWD, PASSWD__CHSH, "chsh" },
|
||||
{ SECCLASS_PASSWD, PASSWD__ROOTOK, "rootok" },
|
||||
{ SECCLASS_DRAWABLE, DRAWABLE__CREATE, "create" },
|
||||
{ SECCLASS_DRAWABLE, DRAWABLE__DESTROY, "destroy" },
|
||||
{ SECCLASS_DRAWABLE, DRAWABLE__DRAW, "draw" },
|
||||
{ SECCLASS_DRAWABLE, DRAWABLE__COPY, "copy" },
|
||||
{ SECCLASS_DRAWABLE, DRAWABLE__GETATTR, "getattr" },
|
||||
{ SECCLASS_GC, GC__CREATE, "create" },
|
||||
{ SECCLASS_GC, GC__FREE, "free" },
|
||||
{ SECCLASS_GC, GC__GETATTR, "getattr" },
|
||||
{ SECCLASS_GC, GC__SETATTR, "setattr" },
|
||||
{ SECCLASS_WINDOW, WINDOW__ADDCHILD, "addchild" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CREATE, "create" },
|
||||
{ SECCLASS_WINDOW, WINDOW__DESTROY, "destroy" },
|
||||
{ SECCLASS_WINDOW, WINDOW__MAP, "map" },
|
||||
{ SECCLASS_WINDOW, WINDOW__UNMAP, "unmap" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CHSTACK, "chstack" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CHPROPLIST, "chproplist" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CHPROP, "chprop" },
|
||||
{ SECCLASS_WINDOW, WINDOW__LISTPROP, "listprop" },
|
||||
{ SECCLASS_WINDOW, WINDOW__GETATTR, "getattr" },
|
||||
{ SECCLASS_WINDOW, WINDOW__SETATTR, "setattr" },
|
||||
{ SECCLASS_WINDOW, WINDOW__SETFOCUS, "setfocus" },
|
||||
{ SECCLASS_WINDOW, WINDOW__MOVE, "move" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CHSELECTION, "chselection" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CHPARENT, "chparent" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CTRLLIFE, "ctrllife" },
|
||||
{ SECCLASS_WINDOW, WINDOW__ENUMERATE, "enumerate" },
|
||||
{ SECCLASS_WINDOW, WINDOW__TRANSPARENT, "transparent" },
|
||||
{ SECCLASS_WINDOW, WINDOW__MOUSEMOTION, "mousemotion" },
|
||||
{ SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT, "clientcomevent" },
|
||||
{ SECCLASS_WINDOW, WINDOW__INPUTEVENT, "inputevent" },
|
||||
{ SECCLASS_WINDOW, WINDOW__DRAWEVENT, "drawevent" },
|
||||
{ SECCLASS_WINDOW, WINDOW__WINDOWCHANGEEVENT, "windowchangeevent" },
|
||||
{ SECCLASS_WINDOW, WINDOW__WINDOWCHANGEREQUEST, "windowchangerequest" },
|
||||
{ SECCLASS_WINDOW, WINDOW__SERVERCHANGEEVENT, "serverchangeevent" },
|
||||
{ SECCLASS_WINDOW, WINDOW__EXTENSIONEVENT, "extensionevent" },
|
||||
{ SECCLASS_FONT, FONT__LOAD, "load" },
|
||||
{ SECCLASS_FONT, FONT__FREE, "free" },
|
||||
{ SECCLASS_FONT, FONT__GETATTR, "getattr" },
|
||||
{ SECCLASS_FONT, FONT__USE, "use" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__CREATE, "create" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__FREE, "free" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__INSTALL, "install" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__UNINSTALL, "uninstall" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__LIST, "list" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__READ, "read" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__STORE, "store" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__GETATTR, "getattr" },
|
||||
{ SECCLASS_COLORMAP, COLORMAP__SETATTR, "setattr" },
|
||||
{ SECCLASS_PROPERTY, PROPERTY__CREATE, "create" },
|
||||
{ SECCLASS_PROPERTY, PROPERTY__FREE, "free" },
|
||||
{ SECCLASS_PROPERTY, PROPERTY__READ, "read" },
|
||||
{ SECCLASS_PROPERTY, PROPERTY__WRITE, "write" },
|
||||
{ SECCLASS_CURSOR, CURSOR__CREATE, "create" },
|
||||
{ SECCLASS_CURSOR, CURSOR__CREATEGLYPH, "createglyph" },
|
||||
{ SECCLASS_CURSOR, CURSOR__FREE, "free" },
|
||||
{ SECCLASS_CURSOR, CURSOR__ASSIGN, "assign" },
|
||||
{ SECCLASS_CURSOR, CURSOR__SETATTR, "setattr" },
|
||||
{ SECCLASS_XCLIENT, XCLIENT__KILL, "kill" },
|
||||
{ SECCLASS_XINPUT, XINPUT__LOOKUP, "lookup" },
|
||||
{ SECCLASS_XINPUT, XINPUT__GETATTR, "getattr" },
|
||||
{ SECCLASS_XINPUT, XINPUT__SETATTR, "setattr" },
|
||||
{ SECCLASS_XINPUT, XINPUT__SETFOCUS, "setfocus" },
|
||||
{ SECCLASS_XINPUT, XINPUT__WARPPOINTER, "warppointer" },
|
||||
{ SECCLASS_XINPUT, XINPUT__ACTIVEGRAB, "activegrab" },
|
||||
{ SECCLASS_XINPUT, XINPUT__PASSIVEGRAB, "passivegrab" },
|
||||
{ SECCLASS_XINPUT, XINPUT__UNGRAB, "ungrab" },
|
||||
{ SECCLASS_XINPUT, XINPUT__BELL, "bell" },
|
||||
{ SECCLASS_XINPUT, XINPUT__MOUSEMOTION, "mousemotion" },
|
||||
{ SECCLASS_XINPUT, XINPUT__RELABELINPUT, "relabelinput" },
|
||||
{ SECCLASS_XSERVER, XSERVER__SCREENSAVER, "screensaver" },
|
||||
{ SECCLASS_XSERVER, XSERVER__GETHOSTLIST, "gethostlist" },
|
||||
{ SECCLASS_XSERVER, XSERVER__SETHOSTLIST, "sethostlist" },
|
||||
{ SECCLASS_XSERVER, XSERVER__GETFONTPATH, "getfontpath" },
|
||||
{ SECCLASS_XSERVER, XSERVER__SETFONTPATH, "setfontpath" },
|
||||
{ SECCLASS_XSERVER, XSERVER__GETATTR, "getattr" },
|
||||
{ SECCLASS_XSERVER, XSERVER__GRAB, "grab" },
|
||||
{ SECCLASS_XSERVER, XSERVER__UNGRAB, "ungrab" },
|
||||
{ SECCLASS_XEXTENSION, XEXTENSION__QUERY, "query" },
|
||||
{ SECCLASS_XEXTENSION, XEXTENSION__USE, "use" },
|
||||
{ SECCLASS_PAX, PAX__PAGEEXEC, "pageexec" },
|
||||
{ SECCLASS_PAX, PAX__EMUTRAMP, "emutramp" },
|
||||
{ SECCLASS_PAX, PAX__MPROTECT, "mprotect" },
|
||||
{ SECCLASS_PAX, PAX__RANDMMAP, "randmmap" },
|
||||
{ SECCLASS_PAX, PAX__RANDEXEC, "randexec" },
|
||||
{ SECCLASS_PAX, PAX__SEGMEXEC, "segmexec" },
|
||||
{ SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read" },
|
||||
{ SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write" },
|
||||
{ SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read" },
|
||||
{ SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write" },
|
||||
{ SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read" },
|
||||
{ SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write" },
|
||||
{ SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read" },
|
||||
{ SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write" },
|
||||
{ SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read" },
|
||||
{ SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write" },
|
||||
{ SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read" },
|
||||
{ SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write" },
|
||||
};
|
||||
|
||||
|
||||
/* FLASK */
|
||||
880
extra/linux-2.6.10/security/selinux/include/av_permissions.h
Normal file
880
extra/linux-2.6.10/security/selinux/include/av_permissions.h
Normal file
@@ -0,0 +1,880 @@
|
||||
/* This file is automatically generated. Do not edit. */
|
||||
/* FLASK */
|
||||
|
||||
#define COMMON_FILE__IOCTL 0x00000001UL
|
||||
#define COMMON_FILE__READ 0x00000002UL
|
||||
#define COMMON_FILE__WRITE 0x00000004UL
|
||||
#define COMMON_FILE__CREATE 0x00000008UL
|
||||
#define COMMON_FILE__GETATTR 0x00000010UL
|
||||
#define COMMON_FILE__SETATTR 0x00000020UL
|
||||
#define COMMON_FILE__LOCK 0x00000040UL
|
||||
#define COMMON_FILE__RELABELFROM 0x00000080UL
|
||||
#define COMMON_FILE__RELABELTO 0x00000100UL
|
||||
#define COMMON_FILE__APPEND 0x00000200UL
|
||||
#define COMMON_FILE__UNLINK 0x00000400UL
|
||||
#define COMMON_FILE__LINK 0x00000800UL
|
||||
#define COMMON_FILE__RENAME 0x00001000UL
|
||||
#define COMMON_FILE__EXECUTE 0x00002000UL
|
||||
#define COMMON_FILE__SWAPON 0x00004000UL
|
||||
#define COMMON_FILE__QUOTAON 0x00008000UL
|
||||
#define COMMON_FILE__MOUNTON 0x00010000UL
|
||||
|
||||
#define COMMON_SOCKET__IOCTL 0x00000001UL
|
||||
#define COMMON_SOCKET__READ 0x00000002UL
|
||||
#define COMMON_SOCKET__WRITE 0x00000004UL
|
||||
#define COMMON_SOCKET__CREATE 0x00000008UL
|
||||
#define COMMON_SOCKET__GETATTR 0x00000010UL
|
||||
#define COMMON_SOCKET__SETATTR 0x00000020UL
|
||||
#define COMMON_SOCKET__LOCK 0x00000040UL
|
||||
#define COMMON_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define COMMON_SOCKET__RELABELTO 0x00000100UL
|
||||
#define COMMON_SOCKET__APPEND 0x00000200UL
|
||||
#define COMMON_SOCKET__BIND 0x00000400UL
|
||||
#define COMMON_SOCKET__CONNECT 0x00000800UL
|
||||
#define COMMON_SOCKET__LISTEN 0x00001000UL
|
||||
#define COMMON_SOCKET__ACCEPT 0x00002000UL
|
||||
#define COMMON_SOCKET__GETOPT 0x00004000UL
|
||||
#define COMMON_SOCKET__SETOPT 0x00008000UL
|
||||
#define COMMON_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define COMMON_SOCKET__RECVFROM 0x00020000UL
|
||||
#define COMMON_SOCKET__SENDTO 0x00040000UL
|
||||
#define COMMON_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define COMMON_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define COMMON_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define COMMON_IPC__CREATE 0x00000001UL
|
||||
#define COMMON_IPC__DESTROY 0x00000002UL
|
||||
#define COMMON_IPC__GETATTR 0x00000004UL
|
||||
#define COMMON_IPC__SETATTR 0x00000008UL
|
||||
#define COMMON_IPC__READ 0x00000010UL
|
||||
#define COMMON_IPC__WRITE 0x00000020UL
|
||||
#define COMMON_IPC__ASSOCIATE 0x00000040UL
|
||||
#define COMMON_IPC__UNIX_READ 0x00000080UL
|
||||
#define COMMON_IPC__UNIX_WRITE 0x00000100UL
|
||||
|
||||
#define FILESYSTEM__MOUNT 0x00000001UL
|
||||
#define FILESYSTEM__REMOUNT 0x00000002UL
|
||||
#define FILESYSTEM__UNMOUNT 0x00000004UL
|
||||
#define FILESYSTEM__GETATTR 0x00000008UL
|
||||
#define FILESYSTEM__RELABELFROM 0x00000010UL
|
||||
#define FILESYSTEM__RELABELTO 0x00000020UL
|
||||
#define FILESYSTEM__TRANSITION 0x00000040UL
|
||||
#define FILESYSTEM__ASSOCIATE 0x00000080UL
|
||||
#define FILESYSTEM__QUOTAMOD 0x00000100UL
|
||||
#define FILESYSTEM__QUOTAGET 0x00000200UL
|
||||
|
||||
#define DIR__IOCTL 0x00000001UL
|
||||
#define DIR__READ 0x00000002UL
|
||||
#define DIR__WRITE 0x00000004UL
|
||||
#define DIR__CREATE 0x00000008UL
|
||||
#define DIR__GETATTR 0x00000010UL
|
||||
#define DIR__SETATTR 0x00000020UL
|
||||
#define DIR__LOCK 0x00000040UL
|
||||
#define DIR__RELABELFROM 0x00000080UL
|
||||
#define DIR__RELABELTO 0x00000100UL
|
||||
#define DIR__APPEND 0x00000200UL
|
||||
#define DIR__UNLINK 0x00000400UL
|
||||
#define DIR__LINK 0x00000800UL
|
||||
#define DIR__RENAME 0x00001000UL
|
||||
#define DIR__EXECUTE 0x00002000UL
|
||||
#define DIR__SWAPON 0x00004000UL
|
||||
#define DIR__QUOTAON 0x00008000UL
|
||||
#define DIR__MOUNTON 0x00010000UL
|
||||
|
||||
#define DIR__ADD_NAME 0x00020000UL
|
||||
#define DIR__REMOVE_NAME 0x00040000UL
|
||||
#define DIR__REPARENT 0x00080000UL
|
||||
#define DIR__SEARCH 0x00100000UL
|
||||
#define DIR__RMDIR 0x00200000UL
|
||||
|
||||
#define FILE__IOCTL 0x00000001UL
|
||||
#define FILE__READ 0x00000002UL
|
||||
#define FILE__WRITE 0x00000004UL
|
||||
#define FILE__CREATE 0x00000008UL
|
||||
#define FILE__GETATTR 0x00000010UL
|
||||
#define FILE__SETATTR 0x00000020UL
|
||||
#define FILE__LOCK 0x00000040UL
|
||||
#define FILE__RELABELFROM 0x00000080UL
|
||||
#define FILE__RELABELTO 0x00000100UL
|
||||
#define FILE__APPEND 0x00000200UL
|
||||
#define FILE__UNLINK 0x00000400UL
|
||||
#define FILE__LINK 0x00000800UL
|
||||
#define FILE__RENAME 0x00001000UL
|
||||
#define FILE__EXECUTE 0x00002000UL
|
||||
#define FILE__SWAPON 0x00004000UL
|
||||
#define FILE__QUOTAON 0x00008000UL
|
||||
#define FILE__MOUNTON 0x00010000UL
|
||||
|
||||
#define FILE__EXECUTE_NO_TRANS 0x00020000UL
|
||||
#define FILE__ENTRYPOINT 0x00040000UL
|
||||
|
||||
#define LNK_FILE__IOCTL 0x00000001UL
|
||||
#define LNK_FILE__READ 0x00000002UL
|
||||
#define LNK_FILE__WRITE 0x00000004UL
|
||||
#define LNK_FILE__CREATE 0x00000008UL
|
||||
#define LNK_FILE__GETATTR 0x00000010UL
|
||||
#define LNK_FILE__SETATTR 0x00000020UL
|
||||
#define LNK_FILE__LOCK 0x00000040UL
|
||||
#define LNK_FILE__RELABELFROM 0x00000080UL
|
||||
#define LNK_FILE__RELABELTO 0x00000100UL
|
||||
#define LNK_FILE__APPEND 0x00000200UL
|
||||
#define LNK_FILE__UNLINK 0x00000400UL
|
||||
#define LNK_FILE__LINK 0x00000800UL
|
||||
#define LNK_FILE__RENAME 0x00001000UL
|
||||
#define LNK_FILE__EXECUTE 0x00002000UL
|
||||
#define LNK_FILE__SWAPON 0x00004000UL
|
||||
#define LNK_FILE__QUOTAON 0x00008000UL
|
||||
#define LNK_FILE__MOUNTON 0x00010000UL
|
||||
|
||||
#define CHR_FILE__IOCTL 0x00000001UL
|
||||
#define CHR_FILE__READ 0x00000002UL
|
||||
#define CHR_FILE__WRITE 0x00000004UL
|
||||
#define CHR_FILE__CREATE 0x00000008UL
|
||||
#define CHR_FILE__GETATTR 0x00000010UL
|
||||
#define CHR_FILE__SETATTR 0x00000020UL
|
||||
#define CHR_FILE__LOCK 0x00000040UL
|
||||
#define CHR_FILE__RELABELFROM 0x00000080UL
|
||||
#define CHR_FILE__RELABELTO 0x00000100UL
|
||||
#define CHR_FILE__APPEND 0x00000200UL
|
||||
#define CHR_FILE__UNLINK 0x00000400UL
|
||||
#define CHR_FILE__LINK 0x00000800UL
|
||||
#define CHR_FILE__RENAME 0x00001000UL
|
||||
#define CHR_FILE__EXECUTE 0x00002000UL
|
||||
#define CHR_FILE__SWAPON 0x00004000UL
|
||||
#define CHR_FILE__QUOTAON 0x00008000UL
|
||||
#define CHR_FILE__MOUNTON 0x00010000UL
|
||||
|
||||
#define BLK_FILE__IOCTL 0x00000001UL
|
||||
#define BLK_FILE__READ 0x00000002UL
|
||||
#define BLK_FILE__WRITE 0x00000004UL
|
||||
#define BLK_FILE__CREATE 0x00000008UL
|
||||
#define BLK_FILE__GETATTR 0x00000010UL
|
||||
#define BLK_FILE__SETATTR 0x00000020UL
|
||||
#define BLK_FILE__LOCK 0x00000040UL
|
||||
#define BLK_FILE__RELABELFROM 0x00000080UL
|
||||
#define BLK_FILE__RELABELTO 0x00000100UL
|
||||
#define BLK_FILE__APPEND 0x00000200UL
|
||||
#define BLK_FILE__UNLINK 0x00000400UL
|
||||
#define BLK_FILE__LINK 0x00000800UL
|
||||
#define BLK_FILE__RENAME 0x00001000UL
|
||||
#define BLK_FILE__EXECUTE 0x00002000UL
|
||||
#define BLK_FILE__SWAPON 0x00004000UL
|
||||
#define BLK_FILE__QUOTAON 0x00008000UL
|
||||
#define BLK_FILE__MOUNTON 0x00010000UL
|
||||
|
||||
#define SOCK_FILE__IOCTL 0x00000001UL
|
||||
#define SOCK_FILE__READ 0x00000002UL
|
||||
#define SOCK_FILE__WRITE 0x00000004UL
|
||||
#define SOCK_FILE__CREATE 0x00000008UL
|
||||
#define SOCK_FILE__GETATTR 0x00000010UL
|
||||
#define SOCK_FILE__SETATTR 0x00000020UL
|
||||
#define SOCK_FILE__LOCK 0x00000040UL
|
||||
#define SOCK_FILE__RELABELFROM 0x00000080UL
|
||||
#define SOCK_FILE__RELABELTO 0x00000100UL
|
||||
#define SOCK_FILE__APPEND 0x00000200UL
|
||||
#define SOCK_FILE__UNLINK 0x00000400UL
|
||||
#define SOCK_FILE__LINK 0x00000800UL
|
||||
#define SOCK_FILE__RENAME 0x00001000UL
|
||||
#define SOCK_FILE__EXECUTE 0x00002000UL
|
||||
#define SOCK_FILE__SWAPON 0x00004000UL
|
||||
#define SOCK_FILE__QUOTAON 0x00008000UL
|
||||
#define SOCK_FILE__MOUNTON 0x00010000UL
|
||||
|
||||
#define FIFO_FILE__IOCTL 0x00000001UL
|
||||
#define FIFO_FILE__READ 0x00000002UL
|
||||
#define FIFO_FILE__WRITE 0x00000004UL
|
||||
#define FIFO_FILE__CREATE 0x00000008UL
|
||||
#define FIFO_FILE__GETATTR 0x00000010UL
|
||||
#define FIFO_FILE__SETATTR 0x00000020UL
|
||||
#define FIFO_FILE__LOCK 0x00000040UL
|
||||
#define FIFO_FILE__RELABELFROM 0x00000080UL
|
||||
#define FIFO_FILE__RELABELTO 0x00000100UL
|
||||
#define FIFO_FILE__APPEND 0x00000200UL
|
||||
#define FIFO_FILE__UNLINK 0x00000400UL
|
||||
#define FIFO_FILE__LINK 0x00000800UL
|
||||
#define FIFO_FILE__RENAME 0x00001000UL
|
||||
#define FIFO_FILE__EXECUTE 0x00002000UL
|
||||
#define FIFO_FILE__SWAPON 0x00004000UL
|
||||
#define FIFO_FILE__QUOTAON 0x00008000UL
|
||||
#define FIFO_FILE__MOUNTON 0x00010000UL
|
||||
|
||||
#define FD__USE 0x00000001UL
|
||||
|
||||
#define SOCKET__IOCTL 0x00000001UL
|
||||
#define SOCKET__READ 0x00000002UL
|
||||
#define SOCKET__WRITE 0x00000004UL
|
||||
#define SOCKET__CREATE 0x00000008UL
|
||||
#define SOCKET__GETATTR 0x00000010UL
|
||||
#define SOCKET__SETATTR 0x00000020UL
|
||||
#define SOCKET__LOCK 0x00000040UL
|
||||
#define SOCKET__RELABELFROM 0x00000080UL
|
||||
#define SOCKET__RELABELTO 0x00000100UL
|
||||
#define SOCKET__APPEND 0x00000200UL
|
||||
#define SOCKET__BIND 0x00000400UL
|
||||
#define SOCKET__CONNECT 0x00000800UL
|
||||
#define SOCKET__LISTEN 0x00001000UL
|
||||
#define SOCKET__ACCEPT 0x00002000UL
|
||||
#define SOCKET__GETOPT 0x00004000UL
|
||||
#define SOCKET__SETOPT 0x00008000UL
|
||||
#define SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define SOCKET__RECVFROM 0x00020000UL
|
||||
#define SOCKET__SENDTO 0x00040000UL
|
||||
#define SOCKET__RECV_MSG 0x00080000UL
|
||||
#define SOCKET__SEND_MSG 0x00100000UL
|
||||
#define SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define TCP_SOCKET__IOCTL 0x00000001UL
|
||||
#define TCP_SOCKET__READ 0x00000002UL
|
||||
#define TCP_SOCKET__WRITE 0x00000004UL
|
||||
#define TCP_SOCKET__CREATE 0x00000008UL
|
||||
#define TCP_SOCKET__GETATTR 0x00000010UL
|
||||
#define TCP_SOCKET__SETATTR 0x00000020UL
|
||||
#define TCP_SOCKET__LOCK 0x00000040UL
|
||||
#define TCP_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define TCP_SOCKET__RELABELTO 0x00000100UL
|
||||
#define TCP_SOCKET__APPEND 0x00000200UL
|
||||
#define TCP_SOCKET__BIND 0x00000400UL
|
||||
#define TCP_SOCKET__CONNECT 0x00000800UL
|
||||
#define TCP_SOCKET__LISTEN 0x00001000UL
|
||||
#define TCP_SOCKET__ACCEPT 0x00002000UL
|
||||
#define TCP_SOCKET__GETOPT 0x00004000UL
|
||||
#define TCP_SOCKET__SETOPT 0x00008000UL
|
||||
#define TCP_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define TCP_SOCKET__RECVFROM 0x00020000UL
|
||||
#define TCP_SOCKET__SENDTO 0x00040000UL
|
||||
#define TCP_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define TCP_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define TCP_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define TCP_SOCKET__CONNECTTO 0x00400000UL
|
||||
#define TCP_SOCKET__NEWCONN 0x00800000UL
|
||||
#define TCP_SOCKET__ACCEPTFROM 0x01000000UL
|
||||
#define TCP_SOCKET__NODE_BIND 0x02000000UL
|
||||
|
||||
#define UDP_SOCKET__IOCTL 0x00000001UL
|
||||
#define UDP_SOCKET__READ 0x00000002UL
|
||||
#define UDP_SOCKET__WRITE 0x00000004UL
|
||||
#define UDP_SOCKET__CREATE 0x00000008UL
|
||||
#define UDP_SOCKET__GETATTR 0x00000010UL
|
||||
#define UDP_SOCKET__SETATTR 0x00000020UL
|
||||
#define UDP_SOCKET__LOCK 0x00000040UL
|
||||
#define UDP_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define UDP_SOCKET__RELABELTO 0x00000100UL
|
||||
#define UDP_SOCKET__APPEND 0x00000200UL
|
||||
#define UDP_SOCKET__BIND 0x00000400UL
|
||||
#define UDP_SOCKET__CONNECT 0x00000800UL
|
||||
#define UDP_SOCKET__LISTEN 0x00001000UL
|
||||
#define UDP_SOCKET__ACCEPT 0x00002000UL
|
||||
#define UDP_SOCKET__GETOPT 0x00004000UL
|
||||
#define UDP_SOCKET__SETOPT 0x00008000UL
|
||||
#define UDP_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define UDP_SOCKET__RECVFROM 0x00020000UL
|
||||
#define UDP_SOCKET__SENDTO 0x00040000UL
|
||||
#define UDP_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define UDP_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define UDP_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define UDP_SOCKET__NODE_BIND 0x00400000UL
|
||||
|
||||
#define RAWIP_SOCKET__IOCTL 0x00000001UL
|
||||
#define RAWIP_SOCKET__READ 0x00000002UL
|
||||
#define RAWIP_SOCKET__WRITE 0x00000004UL
|
||||
#define RAWIP_SOCKET__CREATE 0x00000008UL
|
||||
#define RAWIP_SOCKET__GETATTR 0x00000010UL
|
||||
#define RAWIP_SOCKET__SETATTR 0x00000020UL
|
||||
#define RAWIP_SOCKET__LOCK 0x00000040UL
|
||||
#define RAWIP_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define RAWIP_SOCKET__RELABELTO 0x00000100UL
|
||||
#define RAWIP_SOCKET__APPEND 0x00000200UL
|
||||
#define RAWIP_SOCKET__BIND 0x00000400UL
|
||||
#define RAWIP_SOCKET__CONNECT 0x00000800UL
|
||||
#define RAWIP_SOCKET__LISTEN 0x00001000UL
|
||||
#define RAWIP_SOCKET__ACCEPT 0x00002000UL
|
||||
#define RAWIP_SOCKET__GETOPT 0x00004000UL
|
||||
#define RAWIP_SOCKET__SETOPT 0x00008000UL
|
||||
#define RAWIP_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define RAWIP_SOCKET__RECVFROM 0x00020000UL
|
||||
#define RAWIP_SOCKET__SENDTO 0x00040000UL
|
||||
#define RAWIP_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define RAWIP_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define RAWIP_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define RAWIP_SOCKET__NODE_BIND 0x00400000UL
|
||||
|
||||
#define NODE__TCP_RECV 0x00000001UL
|
||||
#define NODE__TCP_SEND 0x00000002UL
|
||||
#define NODE__UDP_RECV 0x00000004UL
|
||||
#define NODE__UDP_SEND 0x00000008UL
|
||||
#define NODE__RAWIP_RECV 0x00000010UL
|
||||
#define NODE__RAWIP_SEND 0x00000020UL
|
||||
#define NODE__ENFORCE_DEST 0x00000040UL
|
||||
|
||||
#define NETIF__TCP_RECV 0x00000001UL
|
||||
#define NETIF__TCP_SEND 0x00000002UL
|
||||
#define NETIF__UDP_RECV 0x00000004UL
|
||||
#define NETIF__UDP_SEND 0x00000008UL
|
||||
#define NETIF__RAWIP_RECV 0x00000010UL
|
||||
#define NETIF__RAWIP_SEND 0x00000020UL
|
||||
|
||||
#define NETLINK_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define PACKET_SOCKET__IOCTL 0x00000001UL
|
||||
#define PACKET_SOCKET__READ 0x00000002UL
|
||||
#define PACKET_SOCKET__WRITE 0x00000004UL
|
||||
#define PACKET_SOCKET__CREATE 0x00000008UL
|
||||
#define PACKET_SOCKET__GETATTR 0x00000010UL
|
||||
#define PACKET_SOCKET__SETATTR 0x00000020UL
|
||||
#define PACKET_SOCKET__LOCK 0x00000040UL
|
||||
#define PACKET_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define PACKET_SOCKET__RELABELTO 0x00000100UL
|
||||
#define PACKET_SOCKET__APPEND 0x00000200UL
|
||||
#define PACKET_SOCKET__BIND 0x00000400UL
|
||||
#define PACKET_SOCKET__CONNECT 0x00000800UL
|
||||
#define PACKET_SOCKET__LISTEN 0x00001000UL
|
||||
#define PACKET_SOCKET__ACCEPT 0x00002000UL
|
||||
#define PACKET_SOCKET__GETOPT 0x00004000UL
|
||||
#define PACKET_SOCKET__SETOPT 0x00008000UL
|
||||
#define PACKET_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define PACKET_SOCKET__RECVFROM 0x00020000UL
|
||||
#define PACKET_SOCKET__SENDTO 0x00040000UL
|
||||
#define PACKET_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define PACKET_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define PACKET_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define KEY_SOCKET__IOCTL 0x00000001UL
|
||||
#define KEY_SOCKET__READ 0x00000002UL
|
||||
#define KEY_SOCKET__WRITE 0x00000004UL
|
||||
#define KEY_SOCKET__CREATE 0x00000008UL
|
||||
#define KEY_SOCKET__GETATTR 0x00000010UL
|
||||
#define KEY_SOCKET__SETATTR 0x00000020UL
|
||||
#define KEY_SOCKET__LOCK 0x00000040UL
|
||||
#define KEY_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define KEY_SOCKET__RELABELTO 0x00000100UL
|
||||
#define KEY_SOCKET__APPEND 0x00000200UL
|
||||
#define KEY_SOCKET__BIND 0x00000400UL
|
||||
#define KEY_SOCKET__CONNECT 0x00000800UL
|
||||
#define KEY_SOCKET__LISTEN 0x00001000UL
|
||||
#define KEY_SOCKET__ACCEPT 0x00002000UL
|
||||
#define KEY_SOCKET__GETOPT 0x00004000UL
|
||||
#define KEY_SOCKET__SETOPT 0x00008000UL
|
||||
#define KEY_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define KEY_SOCKET__RECVFROM 0x00020000UL
|
||||
#define KEY_SOCKET__SENDTO 0x00040000UL
|
||||
#define KEY_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define KEY_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define KEY_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define UNIX_STREAM_SOCKET__IOCTL 0x00000001UL
|
||||
#define UNIX_STREAM_SOCKET__READ 0x00000002UL
|
||||
#define UNIX_STREAM_SOCKET__WRITE 0x00000004UL
|
||||
#define UNIX_STREAM_SOCKET__CREATE 0x00000008UL
|
||||
#define UNIX_STREAM_SOCKET__GETATTR 0x00000010UL
|
||||
#define UNIX_STREAM_SOCKET__SETATTR 0x00000020UL
|
||||
#define UNIX_STREAM_SOCKET__LOCK 0x00000040UL
|
||||
#define UNIX_STREAM_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define UNIX_STREAM_SOCKET__RELABELTO 0x00000100UL
|
||||
#define UNIX_STREAM_SOCKET__APPEND 0x00000200UL
|
||||
#define UNIX_STREAM_SOCKET__BIND 0x00000400UL
|
||||
#define UNIX_STREAM_SOCKET__CONNECT 0x00000800UL
|
||||
#define UNIX_STREAM_SOCKET__LISTEN 0x00001000UL
|
||||
#define UNIX_STREAM_SOCKET__ACCEPT 0x00002000UL
|
||||
#define UNIX_STREAM_SOCKET__GETOPT 0x00004000UL
|
||||
#define UNIX_STREAM_SOCKET__SETOPT 0x00008000UL
|
||||
#define UNIX_STREAM_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define UNIX_STREAM_SOCKET__RECVFROM 0x00020000UL
|
||||
#define UNIX_STREAM_SOCKET__SENDTO 0x00040000UL
|
||||
#define UNIX_STREAM_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define UNIX_STREAM_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define UNIX_STREAM_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define UNIX_STREAM_SOCKET__CONNECTTO 0x00400000UL
|
||||
#define UNIX_STREAM_SOCKET__NEWCONN 0x00800000UL
|
||||
#define UNIX_STREAM_SOCKET__ACCEPTFROM 0x01000000UL
|
||||
|
||||
#define UNIX_DGRAM_SOCKET__IOCTL 0x00000001UL
|
||||
#define UNIX_DGRAM_SOCKET__READ 0x00000002UL
|
||||
#define UNIX_DGRAM_SOCKET__WRITE 0x00000004UL
|
||||
#define UNIX_DGRAM_SOCKET__CREATE 0x00000008UL
|
||||
#define UNIX_DGRAM_SOCKET__GETATTR 0x00000010UL
|
||||
#define UNIX_DGRAM_SOCKET__SETATTR 0x00000020UL
|
||||
#define UNIX_DGRAM_SOCKET__LOCK 0x00000040UL
|
||||
#define UNIX_DGRAM_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define UNIX_DGRAM_SOCKET__RELABELTO 0x00000100UL
|
||||
#define UNIX_DGRAM_SOCKET__APPEND 0x00000200UL
|
||||
#define UNIX_DGRAM_SOCKET__BIND 0x00000400UL
|
||||
#define UNIX_DGRAM_SOCKET__CONNECT 0x00000800UL
|
||||
#define UNIX_DGRAM_SOCKET__LISTEN 0x00001000UL
|
||||
#define UNIX_DGRAM_SOCKET__ACCEPT 0x00002000UL
|
||||
#define UNIX_DGRAM_SOCKET__GETOPT 0x00004000UL
|
||||
#define UNIX_DGRAM_SOCKET__SETOPT 0x00008000UL
|
||||
#define UNIX_DGRAM_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define UNIX_DGRAM_SOCKET__RECVFROM 0x00020000UL
|
||||
#define UNIX_DGRAM_SOCKET__SENDTO 0x00040000UL
|
||||
#define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define PROCESS__FORK 0x00000001UL
|
||||
#define PROCESS__TRANSITION 0x00000002UL
|
||||
#define PROCESS__SIGCHLD 0x00000004UL
|
||||
#define PROCESS__SIGKILL 0x00000008UL
|
||||
#define PROCESS__SIGSTOP 0x00000010UL
|
||||
#define PROCESS__SIGNULL 0x00000020UL
|
||||
#define PROCESS__SIGNAL 0x00000040UL
|
||||
#define PROCESS__PTRACE 0x00000080UL
|
||||
#define PROCESS__GETSCHED 0x00000100UL
|
||||
#define PROCESS__SETSCHED 0x00000200UL
|
||||
#define PROCESS__GETSESSION 0x00000400UL
|
||||
#define PROCESS__GETPGID 0x00000800UL
|
||||
#define PROCESS__SETPGID 0x00001000UL
|
||||
#define PROCESS__GETCAP 0x00002000UL
|
||||
#define PROCESS__SETCAP 0x00004000UL
|
||||
#define PROCESS__SHARE 0x00008000UL
|
||||
#define PROCESS__GETATTR 0x00010000UL
|
||||
#define PROCESS__SETEXEC 0x00020000UL
|
||||
#define PROCESS__SETFSCREATE 0x00040000UL
|
||||
#define PROCESS__NOATSECURE 0x00080000UL
|
||||
#define PROCESS__SIGINH 0x00100000UL
|
||||
#define PROCESS__SETRLIMIT 0x00200000UL
|
||||
#define PROCESS__RLIMITINH 0x00400000UL
|
||||
|
||||
#define IPC__CREATE 0x00000001UL
|
||||
#define IPC__DESTROY 0x00000002UL
|
||||
#define IPC__GETATTR 0x00000004UL
|
||||
#define IPC__SETATTR 0x00000008UL
|
||||
#define IPC__READ 0x00000010UL
|
||||
#define IPC__WRITE 0x00000020UL
|
||||
#define IPC__ASSOCIATE 0x00000040UL
|
||||
#define IPC__UNIX_READ 0x00000080UL
|
||||
#define IPC__UNIX_WRITE 0x00000100UL
|
||||
|
||||
#define SEM__CREATE 0x00000001UL
|
||||
#define SEM__DESTROY 0x00000002UL
|
||||
#define SEM__GETATTR 0x00000004UL
|
||||
#define SEM__SETATTR 0x00000008UL
|
||||
#define SEM__READ 0x00000010UL
|
||||
#define SEM__WRITE 0x00000020UL
|
||||
#define SEM__ASSOCIATE 0x00000040UL
|
||||
#define SEM__UNIX_READ 0x00000080UL
|
||||
#define SEM__UNIX_WRITE 0x00000100UL
|
||||
|
||||
#define MSGQ__CREATE 0x00000001UL
|
||||
#define MSGQ__DESTROY 0x00000002UL
|
||||
#define MSGQ__GETATTR 0x00000004UL
|
||||
#define MSGQ__SETATTR 0x00000008UL
|
||||
#define MSGQ__READ 0x00000010UL
|
||||
#define MSGQ__WRITE 0x00000020UL
|
||||
#define MSGQ__ASSOCIATE 0x00000040UL
|
||||
#define MSGQ__UNIX_READ 0x00000080UL
|
||||
#define MSGQ__UNIX_WRITE 0x00000100UL
|
||||
|
||||
#define MSGQ__ENQUEUE 0x00000200UL
|
||||
|
||||
#define MSG__SEND 0x00000001UL
|
||||
#define MSG__RECEIVE 0x00000002UL
|
||||
|
||||
#define SHM__CREATE 0x00000001UL
|
||||
#define SHM__DESTROY 0x00000002UL
|
||||
#define SHM__GETATTR 0x00000004UL
|
||||
#define SHM__SETATTR 0x00000008UL
|
||||
#define SHM__READ 0x00000010UL
|
||||
#define SHM__WRITE 0x00000020UL
|
||||
#define SHM__ASSOCIATE 0x00000040UL
|
||||
#define SHM__UNIX_READ 0x00000080UL
|
||||
#define SHM__UNIX_WRITE 0x00000100UL
|
||||
|
||||
#define SHM__LOCK 0x00000200UL
|
||||
|
||||
#define SECURITY__COMPUTE_AV 0x00000001UL
|
||||
#define SECURITY__COMPUTE_CREATE 0x00000002UL
|
||||
#define SECURITY__COMPUTE_MEMBER 0x00000004UL
|
||||
#define SECURITY__CHECK_CONTEXT 0x00000008UL
|
||||
#define SECURITY__LOAD_POLICY 0x00000010UL
|
||||
#define SECURITY__COMPUTE_RELABEL 0x00000020UL
|
||||
#define SECURITY__COMPUTE_USER 0x00000040UL
|
||||
#define SECURITY__SETENFORCE 0x00000080UL
|
||||
#define SECURITY__SETBOOL 0x00000100UL
|
||||
|
||||
#define SYSTEM__IPC_INFO 0x00000001UL
|
||||
#define SYSTEM__SYSLOG_READ 0x00000002UL
|
||||
#define SYSTEM__SYSLOG_MOD 0x00000004UL
|
||||
#define SYSTEM__SYSLOG_CONSOLE 0x00000008UL
|
||||
|
||||
#define CAPABILITY__CHOWN 0x00000001UL
|
||||
#define CAPABILITY__DAC_OVERRIDE 0x00000002UL
|
||||
#define CAPABILITY__DAC_READ_SEARCH 0x00000004UL
|
||||
#define CAPABILITY__FOWNER 0x00000008UL
|
||||
#define CAPABILITY__FSETID 0x00000010UL
|
||||
#define CAPABILITY__KILL 0x00000020UL
|
||||
#define CAPABILITY__SETGID 0x00000040UL
|
||||
#define CAPABILITY__SETUID 0x00000080UL
|
||||
#define CAPABILITY__SETPCAP 0x00000100UL
|
||||
#define CAPABILITY__LINUX_IMMUTABLE 0x00000200UL
|
||||
#define CAPABILITY__NET_BIND_SERVICE 0x00000400UL
|
||||
#define CAPABILITY__NET_BROADCAST 0x00000800UL
|
||||
#define CAPABILITY__NET_ADMIN 0x00001000UL
|
||||
#define CAPABILITY__NET_RAW 0x00002000UL
|
||||
#define CAPABILITY__IPC_LOCK 0x00004000UL
|
||||
#define CAPABILITY__IPC_OWNER 0x00008000UL
|
||||
#define CAPABILITY__SYS_MODULE 0x00010000UL
|
||||
#define CAPABILITY__SYS_RAWIO 0x00020000UL
|
||||
#define CAPABILITY__SYS_CHROOT 0x00040000UL
|
||||
#define CAPABILITY__SYS_PTRACE 0x00080000UL
|
||||
#define CAPABILITY__SYS_PACCT 0x00100000UL
|
||||
#define CAPABILITY__SYS_ADMIN 0x00200000UL
|
||||
#define CAPABILITY__SYS_BOOT 0x00400000UL
|
||||
#define CAPABILITY__SYS_NICE 0x00800000UL
|
||||
#define CAPABILITY__SYS_RESOURCE 0x01000000UL
|
||||
#define CAPABILITY__SYS_TIME 0x02000000UL
|
||||
#define CAPABILITY__SYS_TTY_CONFIG 0x04000000UL
|
||||
#define CAPABILITY__MKNOD 0x08000000UL
|
||||
#define CAPABILITY__LEASE 0x10000000UL
|
||||
|
||||
#define PASSWD__PASSWD 0x00000001UL
|
||||
#define PASSWD__CHFN 0x00000002UL
|
||||
#define PASSWD__CHSH 0x00000004UL
|
||||
#define PASSWD__ROOTOK 0x00000008UL
|
||||
|
||||
#define DRAWABLE__CREATE 0x00000001UL
|
||||
#define DRAWABLE__DESTROY 0x00000002UL
|
||||
#define DRAWABLE__DRAW 0x00000004UL
|
||||
#define DRAWABLE__COPY 0x00000008UL
|
||||
#define DRAWABLE__GETATTR 0x00000010UL
|
||||
|
||||
#define GC__CREATE 0x00000001UL
|
||||
#define GC__FREE 0x00000002UL
|
||||
#define GC__GETATTR 0x00000004UL
|
||||
#define GC__SETATTR 0x00000008UL
|
||||
|
||||
#define WINDOW__ADDCHILD 0x00000001UL
|
||||
#define WINDOW__CREATE 0x00000002UL
|
||||
#define WINDOW__DESTROY 0x00000004UL
|
||||
#define WINDOW__MAP 0x00000008UL
|
||||
#define WINDOW__UNMAP 0x00000010UL
|
||||
#define WINDOW__CHSTACK 0x00000020UL
|
||||
#define WINDOW__CHPROPLIST 0x00000040UL
|
||||
#define WINDOW__CHPROP 0x00000080UL
|
||||
#define WINDOW__LISTPROP 0x00000100UL
|
||||
#define WINDOW__GETATTR 0x00000200UL
|
||||
#define WINDOW__SETATTR 0x00000400UL
|
||||
#define WINDOW__SETFOCUS 0x00000800UL
|
||||
#define WINDOW__MOVE 0x00001000UL
|
||||
#define WINDOW__CHSELECTION 0x00002000UL
|
||||
#define WINDOW__CHPARENT 0x00004000UL
|
||||
#define WINDOW__CTRLLIFE 0x00008000UL
|
||||
#define WINDOW__ENUMERATE 0x00010000UL
|
||||
#define WINDOW__TRANSPARENT 0x00020000UL
|
||||
#define WINDOW__MOUSEMOTION 0x00040000UL
|
||||
#define WINDOW__CLIENTCOMEVENT 0x00080000UL
|
||||
#define WINDOW__INPUTEVENT 0x00100000UL
|
||||
#define WINDOW__DRAWEVENT 0x00200000UL
|
||||
#define WINDOW__WINDOWCHANGEEVENT 0x00400000UL
|
||||
#define WINDOW__WINDOWCHANGEREQUEST 0x00800000UL
|
||||
#define WINDOW__SERVERCHANGEEVENT 0x01000000UL
|
||||
#define WINDOW__EXTENSIONEVENT 0x02000000UL
|
||||
|
||||
#define FONT__LOAD 0x00000001UL
|
||||
#define FONT__FREE 0x00000002UL
|
||||
#define FONT__GETATTR 0x00000004UL
|
||||
#define FONT__USE 0x00000008UL
|
||||
|
||||
#define COLORMAP__CREATE 0x00000001UL
|
||||
#define COLORMAP__FREE 0x00000002UL
|
||||
#define COLORMAP__INSTALL 0x00000004UL
|
||||
#define COLORMAP__UNINSTALL 0x00000008UL
|
||||
#define COLORMAP__LIST 0x00000010UL
|
||||
#define COLORMAP__READ 0x00000020UL
|
||||
#define COLORMAP__STORE 0x00000040UL
|
||||
#define COLORMAP__GETATTR 0x00000080UL
|
||||
#define COLORMAP__SETATTR 0x00000100UL
|
||||
|
||||
#define PROPERTY__CREATE 0x00000001UL
|
||||
#define PROPERTY__FREE 0x00000002UL
|
||||
#define PROPERTY__READ 0x00000004UL
|
||||
#define PROPERTY__WRITE 0x00000008UL
|
||||
|
||||
#define CURSOR__CREATE 0x00000001UL
|
||||
#define CURSOR__CREATEGLYPH 0x00000002UL
|
||||
#define CURSOR__FREE 0x00000004UL
|
||||
#define CURSOR__ASSIGN 0x00000008UL
|
||||
#define CURSOR__SETATTR 0x00000010UL
|
||||
|
||||
#define XCLIENT__KILL 0x00000001UL
|
||||
|
||||
#define XINPUT__LOOKUP 0x00000001UL
|
||||
#define XINPUT__GETATTR 0x00000002UL
|
||||
#define XINPUT__SETATTR 0x00000004UL
|
||||
#define XINPUT__SETFOCUS 0x00000008UL
|
||||
#define XINPUT__WARPPOINTER 0x00000010UL
|
||||
#define XINPUT__ACTIVEGRAB 0x00000020UL
|
||||
#define XINPUT__PASSIVEGRAB 0x00000040UL
|
||||
#define XINPUT__UNGRAB 0x00000080UL
|
||||
#define XINPUT__BELL 0x00000100UL
|
||||
#define XINPUT__MOUSEMOTION 0x00000200UL
|
||||
#define XINPUT__RELABELINPUT 0x00000400UL
|
||||
|
||||
#define XSERVER__SCREENSAVER 0x00000001UL
|
||||
#define XSERVER__GETHOSTLIST 0x00000002UL
|
||||
#define XSERVER__SETHOSTLIST 0x00000004UL
|
||||
#define XSERVER__GETFONTPATH 0x00000008UL
|
||||
#define XSERVER__SETFONTPATH 0x00000010UL
|
||||
#define XSERVER__GETATTR 0x00000020UL
|
||||
#define XSERVER__GRAB 0x00000040UL
|
||||
#define XSERVER__UNGRAB 0x00000080UL
|
||||
|
||||
#define XEXTENSION__QUERY 0x00000001UL
|
||||
#define XEXTENSION__USE 0x00000002UL
|
||||
|
||||
#define PAX__PAGEEXEC 0x00000001UL
|
||||
#define PAX__EMUTRAMP 0x00000002UL
|
||||
#define PAX__MPROTECT 0x00000004UL
|
||||
#define PAX__RANDMMAP 0x00000008UL
|
||||
#define PAX__RANDEXEC 0x00000010UL
|
||||
#define PAX__SEGMEXEC 0x00000020UL
|
||||
|
||||
#define NETLINK_ROUTE_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_ROUTE_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_ROUTE_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_ROUTE_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_ROUTE_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_ROUTE_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_ROUTE_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_ROUTE_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_ROUTE_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_ROUTE_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_ROUTE_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_ROUTE_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_ROUTE_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_ROUTE_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_ROUTE_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_ROUTE_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_ROUTE_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_ROUTE_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_ROUTE_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_ROUTE_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_ROUTE_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_ROUTE_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_ROUTE_SOCKET__NLMSG_READ 0x00400000UL
|
||||
#define NETLINK_ROUTE_SOCKET__NLMSG_WRITE 0x00800000UL
|
||||
|
||||
#define NETLINK_FIREWALL_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_FIREWALL_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_FIREWALL_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_FIREWALL_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_FIREWALL_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_FIREWALL_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_FIREWALL_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_FIREWALL_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_FIREWALL_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_FIREWALL_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_FIREWALL_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_FIREWALL_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_FIREWALL_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_FIREWALL_SOCKET__NLMSG_READ 0x00400000UL
|
||||
#define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE 0x00800000UL
|
||||
|
||||
#define NETLINK_TCPDIAG_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_TCPDIAG_SOCKET__NLMSG_READ 0x00400000UL
|
||||
#define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE 0x00800000UL
|
||||
|
||||
#define NETLINK_NFLOG_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_NFLOG_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_NFLOG_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_NFLOG_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_NFLOG_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_NFLOG_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_NFLOG_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_NFLOG_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_NFLOG_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_NFLOG_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_NFLOG_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_NFLOG_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_NFLOG_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_NFLOG_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_NFLOG_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_NFLOG_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_NFLOG_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_NFLOG_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_NFLOG_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_NFLOG_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_NFLOG_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_NFLOG_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_XFRM_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_XFRM_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_XFRM_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_XFRM_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_XFRM_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_XFRM_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_XFRM_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_XFRM_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_XFRM_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_XFRM_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_XFRM_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_XFRM_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_XFRM_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_XFRM_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_XFRM_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_XFRM_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_XFRM_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_XFRM_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_XFRM_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_XFRM_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_XFRM_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_XFRM_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_XFRM_SOCKET__NLMSG_READ 0x00400000UL
|
||||
#define NETLINK_XFRM_SOCKET__NLMSG_WRITE 0x00800000UL
|
||||
|
||||
#define NETLINK_SELINUX_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_SELINUX_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_SELINUX_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_SELINUX_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_SELINUX_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_SELINUX_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_SELINUX_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_SELINUX_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_SELINUX_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_SELINUX_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_SELINUX_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_SELINUX_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_SELINUX_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_SELINUX_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_SELINUX_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_SELINUX_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_SELINUX_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_SELINUX_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_SELINUX_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_SELINUX_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_SELINUX_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_SELINUX_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_AUDIT_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_AUDIT_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_AUDIT_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_AUDIT_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_AUDIT_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_AUDIT_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_AUDIT_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_AUDIT_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_AUDIT_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_AUDIT_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_AUDIT_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_AUDIT_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_AUDIT_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_AUDIT_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_AUDIT_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_AUDIT_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_AUDIT_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_AUDIT_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_AUDIT_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_AUDIT_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_AUDIT_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_AUDIT_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_AUDIT_SOCKET__NLMSG_READ 0x00400000UL
|
||||
#define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL
|
||||
|
||||
#define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_IP6FW_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_IP6FW_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_IP6FW_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_IP6FW_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_IP6FW_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_IP6FW_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_IP6FW_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_IP6FW_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_IP6FW_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_IP6FW_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_IP6FW_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_IP6FW_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_IP6FW_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_IP6FW_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_IP6FW_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_IP6FW_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_IP6FW_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_IP6FW_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_IP6FW_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_IP6FW_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define NETLINK_IP6FW_SOCKET__NLMSG_READ 0x00400000UL
|
||||
#define NETLINK_IP6FW_SOCKET__NLMSG_WRITE 0x00800000UL
|
||||
|
||||
#define NETLINK_DNRT_SOCKET__IOCTL 0x00000001UL
|
||||
#define NETLINK_DNRT_SOCKET__READ 0x00000002UL
|
||||
#define NETLINK_DNRT_SOCKET__WRITE 0x00000004UL
|
||||
#define NETLINK_DNRT_SOCKET__CREATE 0x00000008UL
|
||||
#define NETLINK_DNRT_SOCKET__GETATTR 0x00000010UL
|
||||
#define NETLINK_DNRT_SOCKET__SETATTR 0x00000020UL
|
||||
#define NETLINK_DNRT_SOCKET__LOCK 0x00000040UL
|
||||
#define NETLINK_DNRT_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define NETLINK_DNRT_SOCKET__RELABELTO 0x00000100UL
|
||||
#define NETLINK_DNRT_SOCKET__APPEND 0x00000200UL
|
||||
#define NETLINK_DNRT_SOCKET__BIND 0x00000400UL
|
||||
#define NETLINK_DNRT_SOCKET__CONNECT 0x00000800UL
|
||||
#define NETLINK_DNRT_SOCKET__LISTEN 0x00001000UL
|
||||
#define NETLINK_DNRT_SOCKET__ACCEPT 0x00002000UL
|
||||
#define NETLINK_DNRT_SOCKET__GETOPT 0x00004000UL
|
||||
#define NETLINK_DNRT_SOCKET__SETOPT 0x00008000UL
|
||||
#define NETLINK_DNRT_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define NETLINK_DNRT_SOCKET__RECVFROM 0x00020000UL
|
||||
#define NETLINK_DNRT_SOCKET__SENDTO 0x00040000UL
|
||||
#define NETLINK_DNRT_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define NETLINK_DNRT_SOCKET__SEND_MSG 0x00100000UL
|
||||
|
||||
/* FLASK */
|
||||
155
extra/linux-2.6.10/security/selinux/include/avc.h
Normal file
155
extra/linux-2.6.10/security/selinux/include/avc.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Access vector cache interface for object managers.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SELINUX_AVC_H_
|
||||
#define _SELINUX_AVC_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/in6.h>
|
||||
#include <asm/system.h>
|
||||
#include "flask.h"
|
||||
#include "av_permissions.h"
|
||||
#include "security.h"
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||
extern int selinux_enforcing;
|
||||
#else
|
||||
#define selinux_enforcing 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An entry in the AVC.
|
||||
*/
|
||||
struct avc_entry;
|
||||
|
||||
/*
|
||||
* A reference to an AVC entry.
|
||||
*/
|
||||
struct avc_entry_ref {
|
||||
struct avc_entry *ae;
|
||||
};
|
||||
|
||||
/* Initialize an AVC entry reference before first use. */
|
||||
static inline void avc_entry_ref_init(struct avc_entry_ref *h)
|
||||
{
|
||||
h->ae = NULL;
|
||||
}
|
||||
|
||||
struct task_struct;
|
||||
struct vfsmount;
|
||||
struct dentry;
|
||||
struct inode;
|
||||
struct sock;
|
||||
struct sk_buff;
|
||||
|
||||
/* Auxiliary data to use in generating the audit record. */
|
||||
struct avc_audit_data {
|
||||
char type;
|
||||
#define AVC_AUDIT_DATA_FS 1
|
||||
#define AVC_AUDIT_DATA_NET 2
|
||||
#define AVC_AUDIT_DATA_CAP 3
|
||||
#define AVC_AUDIT_DATA_IPC 4
|
||||
struct task_struct *tsk;
|
||||
union {
|
||||
struct {
|
||||
struct vfsmount *mnt;
|
||||
struct dentry *dentry;
|
||||
struct inode *inode;
|
||||
} fs;
|
||||
struct {
|
||||
char *netif;
|
||||
struct sock *sk;
|
||||
u16 family;
|
||||
u16 dport;
|
||||
u16 sport;
|
||||
union {
|
||||
struct {
|
||||
u32 daddr;
|
||||
u32 saddr;
|
||||
} v4;
|
||||
struct {
|
||||
struct in6_addr daddr;
|
||||
struct in6_addr saddr;
|
||||
} v6;
|
||||
} fam;
|
||||
} net;
|
||||
int cap;
|
||||
int ipc_id;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define v4info fam.v4
|
||||
#define v6info fam.v6
|
||||
|
||||
/* Initialize an AVC audit data structure. */
|
||||
#define AVC_AUDIT_DATA_INIT(_d,_t) \
|
||||
{ memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
|
||||
|
||||
/*
|
||||
* AVC statistics
|
||||
*/
|
||||
#define AVC_ENTRY_LOOKUPS 0
|
||||
#define AVC_ENTRY_HITS 1
|
||||
#define AVC_ENTRY_MISSES 2
|
||||
#define AVC_ENTRY_DISCARDS 3
|
||||
#define AVC_CAV_LOOKUPS 4
|
||||
#define AVC_CAV_HITS 5
|
||||
#define AVC_CAV_PROBES 6
|
||||
#define AVC_CAV_MISSES 7
|
||||
#define AVC_NSTATS 8
|
||||
|
||||
/*
|
||||
* AVC display support
|
||||
*/
|
||||
struct audit_buffer;
|
||||
void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
|
||||
void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass);
|
||||
|
||||
/*
|
||||
* AVC operations
|
||||
*/
|
||||
|
||||
void __init avc_init(void);
|
||||
|
||||
int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
|
||||
u32 requested, struct avc_entry_ref *aeref);
|
||||
|
||||
int avc_insert(u32 ssid, u32 tsid, u16 tclass,
|
||||
struct avc_entry *ae, struct avc_entry_ref *out_aeref);
|
||||
|
||||
void avc_audit(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct av_decision *avd, int result, struct avc_audit_data *auditdata);
|
||||
|
||||
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct avc_entry_ref *aeref, struct av_decision *avd);
|
||||
|
||||
int avc_has_perm(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct avc_entry_ref *aeref, struct avc_audit_data *auditdata);
|
||||
|
||||
#define AVC_CALLBACK_GRANT 1
|
||||
#define AVC_CALLBACK_TRY_REVOKE 2
|
||||
#define AVC_CALLBACK_REVOKE 4
|
||||
#define AVC_CALLBACK_RESET 8
|
||||
#define AVC_CALLBACK_AUDITALLOW_ENABLE 16
|
||||
#define AVC_CALLBACK_AUDITALLOW_DISABLE 32
|
||||
#define AVC_CALLBACK_AUDITDENY_ENABLE 64
|
||||
#define AVC_CALLBACK_AUDITDENY_DISABLE 128
|
||||
|
||||
int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 perms,
|
||||
u32 *out_retained),
|
||||
u32 events, u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 perms);
|
||||
|
||||
#endif /* _SELINUX_AVC_H_ */
|
||||
|
||||
27
extra/linux-2.6.10/security/selinux/include/avc_ss.h
Normal file
27
extra/linux-2.6.10/security/selinux/include/avc_ss.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Access vector cache interface for the security server.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SELINUX_AVC_SS_H_
|
||||
#define _SELINUX_AVC_SS_H_
|
||||
|
||||
#include "flask.h"
|
||||
|
||||
int avc_ss_grant(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno);
|
||||
|
||||
int avc_ss_try_revoke(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno,
|
||||
u32 *out_retained);
|
||||
|
||||
int avc_ss_revoke(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno);
|
||||
|
||||
int avc_ss_reset(u32 seqno);
|
||||
|
||||
int avc_ss_set_auditallow(u32 ssid, u32 tsid, u16 tclass, u32 perms,
|
||||
u32 seqno, u32 enable);
|
||||
|
||||
int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass, u32 perms,
|
||||
u32 seqno, u32 enable);
|
||||
|
||||
#endif /* _SELINUX_AVC_SS_H_ */
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/* This file is automatically generated. Do not edit. */
|
||||
/*
|
||||
* Security object class definitions
|
||||
*/
|
||||
static char *class_to_string[] =
|
||||
{
|
||||
"null",
|
||||
"security",
|
||||
"process",
|
||||
"system",
|
||||
"capability",
|
||||
"filesystem",
|
||||
"file",
|
||||
"dir",
|
||||
"fd",
|
||||
"lnk_file",
|
||||
"chr_file",
|
||||
"blk_file",
|
||||
"sock_file",
|
||||
"fifo_file",
|
||||
"socket",
|
||||
"tcp_socket",
|
||||
"udp_socket",
|
||||
"rawip_socket",
|
||||
"node",
|
||||
"netif",
|
||||
"netlink_socket",
|
||||
"packet_socket",
|
||||
"key_socket",
|
||||
"unix_stream_socket",
|
||||
"unix_dgram_socket",
|
||||
"sem",
|
||||
"msg",
|
||||
"msgq",
|
||||
"shm",
|
||||
"ipc",
|
||||
"passwd",
|
||||
"drawable",
|
||||
"window",
|
||||
"gc",
|
||||
"font",
|
||||
"colormap",
|
||||
"property",
|
||||
"cursor",
|
||||
"xclient",
|
||||
"xinput",
|
||||
"xserver",
|
||||
"xextension",
|
||||
"pax",
|
||||
"netlink_route_socket",
|
||||
"netlink_firewall_socket",
|
||||
"netlink_tcpdiag_socket",
|
||||
"netlink_nflog_socket",
|
||||
"netlink_xfrm_socket",
|
||||
"netlink_selinux_socket",
|
||||
"netlink_audit_socket",
|
||||
"netlink_ip6fw_socket",
|
||||
"netlink_dnrt_socket",
|
||||
};
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/* This file is automatically generated. Do not edit. */
|
||||
/* FLASK */
|
||||
|
||||
static char *common_file_perm_to_string[] =
|
||||
{
|
||||
"ioctl",
|
||||
"read",
|
||||
"write",
|
||||
"create",
|
||||
"getattr",
|
||||
"setattr",
|
||||
"lock",
|
||||
"relabelfrom",
|
||||
"relabelto",
|
||||
"append",
|
||||
"unlink",
|
||||
"link",
|
||||
"rename",
|
||||
"execute",
|
||||
"swapon",
|
||||
"quotaon",
|
||||
"mounton",
|
||||
};
|
||||
|
||||
static char *common_socket_perm_to_string[] =
|
||||
{
|
||||
"ioctl",
|
||||
"read",
|
||||
"write",
|
||||
"create",
|
||||
"getattr",
|
||||
"setattr",
|
||||
"lock",
|
||||
"relabelfrom",
|
||||
"relabelto",
|
||||
"append",
|
||||
"bind",
|
||||
"connect",
|
||||
"listen",
|
||||
"accept",
|
||||
"getopt",
|
||||
"setopt",
|
||||
"shutdown",
|
||||
"recvfrom",
|
||||
"sendto",
|
||||
"recv_msg",
|
||||
"send_msg",
|
||||
"name_bind",
|
||||
};
|
||||
|
||||
static char *common_ipc_perm_to_string[] =
|
||||
{
|
||||
"create",
|
||||
"destroy",
|
||||
"getattr",
|
||||
"setattr",
|
||||
"read",
|
||||
"write",
|
||||
"associate",
|
||||
"unix_read",
|
||||
"unix_write",
|
||||
};
|
||||
|
||||
|
||||
/* FLASK */
|
||||
22
extra/linux-2.6.10/security/selinux/include/conditional.h
Normal file
22
extra/linux-2.6.10/security/selinux/include/conditional.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Interface to booleans in the security server. This is exported
|
||||
* for the selinuxfs.
|
||||
*
|
||||
* Author: Karl MacMillan <kmacmillan@tresys.com>
|
||||
*
|
||||
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SELINUX_CONDITIONAL_H_
|
||||
#define _SELINUX_CONDITIONAL_H_
|
||||
|
||||
int security_get_bools(int *len, char ***names, int **values);
|
||||
|
||||
int security_set_bools(int len, int *values);
|
||||
|
||||
int security_get_bool_value(int bool);
|
||||
|
||||
#endif
|
||||
93
extra/linux-2.6.10/security/selinux/include/flask.h
Normal file
93
extra/linux-2.6.10/security/selinux/include/flask.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* This file is automatically generated. Do not edit. */
|
||||
#ifndef _SELINUX_FLASK_H_
|
||||
#define _SELINUX_FLASK_H_
|
||||
|
||||
/*
|
||||
* Security object class definitions
|
||||
*/
|
||||
#define SECCLASS_SECURITY 1
|
||||
#define SECCLASS_PROCESS 2
|
||||
#define SECCLASS_SYSTEM 3
|
||||
#define SECCLASS_CAPABILITY 4
|
||||
#define SECCLASS_FILESYSTEM 5
|
||||
#define SECCLASS_FILE 6
|
||||
#define SECCLASS_DIR 7
|
||||
#define SECCLASS_FD 8
|
||||
#define SECCLASS_LNK_FILE 9
|
||||
#define SECCLASS_CHR_FILE 10
|
||||
#define SECCLASS_BLK_FILE 11
|
||||
#define SECCLASS_SOCK_FILE 12
|
||||
#define SECCLASS_FIFO_FILE 13
|
||||
#define SECCLASS_SOCKET 14
|
||||
#define SECCLASS_TCP_SOCKET 15
|
||||
#define SECCLASS_UDP_SOCKET 16
|
||||
#define SECCLASS_RAWIP_SOCKET 17
|
||||
#define SECCLASS_NODE 18
|
||||
#define SECCLASS_NETIF 19
|
||||
#define SECCLASS_NETLINK_SOCKET 20
|
||||
#define SECCLASS_PACKET_SOCKET 21
|
||||
#define SECCLASS_KEY_SOCKET 22
|
||||
#define SECCLASS_UNIX_STREAM_SOCKET 23
|
||||
#define SECCLASS_UNIX_DGRAM_SOCKET 24
|
||||
#define SECCLASS_SEM 25
|
||||
#define SECCLASS_MSG 26
|
||||
#define SECCLASS_MSGQ 27
|
||||
#define SECCLASS_SHM 28
|
||||
#define SECCLASS_IPC 29
|
||||
#define SECCLASS_PASSWD 30
|
||||
#define SECCLASS_DRAWABLE 31
|
||||
#define SECCLASS_WINDOW 32
|
||||
#define SECCLASS_GC 33
|
||||
#define SECCLASS_FONT 34
|
||||
#define SECCLASS_COLORMAP 35
|
||||
#define SECCLASS_PROPERTY 36
|
||||
#define SECCLASS_CURSOR 37
|
||||
#define SECCLASS_XCLIENT 38
|
||||
#define SECCLASS_XINPUT 39
|
||||
#define SECCLASS_XSERVER 40
|
||||
#define SECCLASS_XEXTENSION 41
|
||||
#define SECCLASS_PAX 42
|
||||
#define SECCLASS_NETLINK_ROUTE_SOCKET 43
|
||||
#define SECCLASS_NETLINK_FIREWALL_SOCKET 44
|
||||
#define SECCLASS_NETLINK_TCPDIAG_SOCKET 45
|
||||
#define SECCLASS_NETLINK_NFLOG_SOCKET 46
|
||||
#define SECCLASS_NETLINK_XFRM_SOCKET 47
|
||||
#define SECCLASS_NETLINK_SELINUX_SOCKET 48
|
||||
#define SECCLASS_NETLINK_AUDIT_SOCKET 49
|
||||
#define SECCLASS_NETLINK_IP6FW_SOCKET 50
|
||||
#define SECCLASS_NETLINK_DNRT_SOCKET 51
|
||||
|
||||
/*
|
||||
* Security identifier indices for initial entities
|
||||
*/
|
||||
#define SECINITSID_KERNEL 1
|
||||
#define SECINITSID_SECURITY 2
|
||||
#define SECINITSID_UNLABELED 3
|
||||
#define SECINITSID_FS 4
|
||||
#define SECINITSID_FILE 5
|
||||
#define SECINITSID_FILE_LABELS 6
|
||||
#define SECINITSID_INIT 7
|
||||
#define SECINITSID_ANY_SOCKET 8
|
||||
#define SECINITSID_PORT 9
|
||||
#define SECINITSID_NETIF 10
|
||||
#define SECINITSID_NETMSG 11
|
||||
#define SECINITSID_NODE 12
|
||||
#define SECINITSID_IGMP_PACKET 13
|
||||
#define SECINITSID_ICMP_SOCKET 14
|
||||
#define SECINITSID_TCP_SOCKET 15
|
||||
#define SECINITSID_SYSCTL_MODPROBE 16
|
||||
#define SECINITSID_SYSCTL 17
|
||||
#define SECINITSID_SYSCTL_FS 18
|
||||
#define SECINITSID_SYSCTL_KERNEL 19
|
||||
#define SECINITSID_SYSCTL_NET 20
|
||||
#define SECINITSID_SYSCTL_NET_UNIX 21
|
||||
#define SECINITSID_SYSCTL_VM 22
|
||||
#define SECINITSID_SYSCTL_DEV 23
|
||||
#define SECINITSID_KMOD 24
|
||||
#define SECINITSID_POLICY 25
|
||||
#define SECINITSID_SCMP_PACKET 26
|
||||
#define SECINITSID_DEVNULL 27
|
||||
|
||||
#define SECINITSID_NUM 27
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
/* This file is automatically generated. Do not edit. */
|
||||
static char *initial_sid_to_string[] =
|
||||
{
|
||||
"null",
|
||||
"kernel",
|
||||
"security",
|
||||
"unlabeled",
|
||||
"fs",
|
||||
"file",
|
||||
"file_labels",
|
||||
"init",
|
||||
"any_socket",
|
||||
"port",
|
||||
"netif",
|
||||
"netmsg",
|
||||
"node",
|
||||
"igmp_packet",
|
||||
"icmp_socket",
|
||||
"tcp_socket",
|
||||
"sysctl_modprobe",
|
||||
"sysctl",
|
||||
"sysctl_fs",
|
||||
"sysctl_kernel",
|
||||
"sysctl_net",
|
||||
"sysctl_net_unix",
|
||||
"sysctl_vm",
|
||||
"sysctl_dev",
|
||||
"kmod",
|
||||
"policy",
|
||||
"scmp_packet",
|
||||
"devnull",
|
||||
};
|
||||
|
||||
21
extra/linux-2.6.10/security/selinux/include/netif.h
Normal file
21
extra/linux-2.6.10/security/selinux/include/netif.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Network interface table.
|
||||
*
|
||||
* Network interfaces (devices) do not have a security field, so we
|
||||
* maintain a table associating each interface with a SID.
|
||||
*
|
||||
* Author: James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef _SELINUX_NETIF_H_
|
||||
#define _SELINUX_NETIF_H_
|
||||
|
||||
int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid);
|
||||
|
||||
#endif /* _SELINUX_NETIF_H_ */
|
||||
|
||||
112
extra/linux-2.6.10/security/selinux/include/objsec.h
Normal file
112
extra/linux-2.6.10/security/selinux/include/objsec.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* NSA Security-Enhanced Linux (SELinux) security module
|
||||
*
|
||||
* This file contains the SELinux security data structures for kernel objects.
|
||||
*
|
||||
* Author(s): Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
* Chris Vance, <cvance@nai.com>
|
||||
* Wayne Salamon, <wsalamon@nai.com>
|
||||
* James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2001,2002 Networks Associates Technology, Inc.
|
||||
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef _SELINUX_OBJSEC_H_
|
||||
#define _SELINUX_OBJSEC_H_
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/in.h>
|
||||
#include "flask.h"
|
||||
#include "avc.h"
|
||||
|
||||
struct task_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
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 */
|
||||
struct avc_entry_ref avcr; /* reference to process permissions */
|
||||
u32 ptrace_sid; /* SID of ptrace parent */
|
||||
};
|
||||
|
||||
struct inode_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
struct inode *inode; /* back pointer to inode object */
|
||||
struct list_head list; /* list of inode_security_struct */
|
||||
u32 task_sid; /* SID of creating task */
|
||||
u32 sid; /* SID of this object */
|
||||
u16 sclass; /* security class of this object */
|
||||
struct avc_entry_ref avcr; /* reference to object permissions */
|
||||
unsigned char initialized; /* initialization flag */
|
||||
struct semaphore sem;
|
||||
unsigned char inherit; /* inherit SID from parent entry */
|
||||
};
|
||||
|
||||
struct file_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
struct file *file; /* back pointer to file object */
|
||||
u32 sid; /* SID of open file description */
|
||||
u32 fown_sid; /* SID of file owner (for SIGIO) */
|
||||
struct avc_entry_ref avcr; /* reference to fd permissions */
|
||||
struct avc_entry_ref inode_avcr; /* reference to object permissions */
|
||||
};
|
||||
|
||||
struct superblock_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
struct super_block *sb; /* back pointer to sb object */
|
||||
struct list_head list; /* list of superblock_security_struct */
|
||||
u32 sid; /* SID of file system */
|
||||
u32 def_sid; /* default SID for labeling */
|
||||
unsigned int behavior; /* labeling behavior */
|
||||
unsigned char initialized; /* initialization flag */
|
||||
unsigned char proc; /* proc fs */
|
||||
struct semaphore sem;
|
||||
struct list_head isec_head;
|
||||
spinlock_t isec_lock;
|
||||
};
|
||||
|
||||
struct msg_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
struct msg_msg *msg; /* back pointer */
|
||||
u32 sid; /* SID of message */
|
||||
struct avc_entry_ref avcr; /* reference to permissions */
|
||||
};
|
||||
|
||||
struct ipc_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
struct kern_ipc_perm *ipc_perm; /* back pointer */
|
||||
u16 sclass; /* security class of this object */
|
||||
u32 sid; /* SID of IPC resource */
|
||||
struct avc_entry_ref avcr; /* reference to permissions */
|
||||
};
|
||||
|
||||
struct bprm_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
struct linux_binprm *bprm; /* back pointer to bprm object */
|
||||
u32 sid; /* SID for transformed process */
|
||||
unsigned char set;
|
||||
};
|
||||
|
||||
struct netif_security_struct {
|
||||
struct net_device *dev; /* back pointer */
|
||||
u32 if_sid; /* SID for this interface */
|
||||
u32 msg_sid; /* default SID for messages received on this interface */
|
||||
};
|
||||
|
||||
struct sk_security_struct {
|
||||
unsigned long magic; /* magic number for this module */
|
||||
struct sock *sk; /* back pointer to sk object */
|
||||
u32 peer_sid; /* SID of peer */
|
||||
};
|
||||
|
||||
extern int inode_security_set_sid(struct inode *inode, u32 sid);
|
||||
|
||||
#endif /* _SELINUX_OBJSEC_H_ */
|
||||
96
extra/linux-2.6.10/security/selinux/include/security.h
Normal file
96
extra/linux-2.6.10/security/selinux/include/security.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Security server interface.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SELINUX_SECURITY_H_
|
||||
#define _SELINUX_SECURITY_H_
|
||||
|
||||
#include "flask.h"
|
||||
|
||||
#define SECSID_NULL 0x00000000 /* unspecified SID */
|
||||
#define SECSID_WILD 0xffffffff /* wildcard SID */
|
||||
#define SECCLASS_NULL 0x0000 /* no class */
|
||||
|
||||
#define SELINUX_MAGIC 0xf97cff8c
|
||||
|
||||
/* Identify specific policy version changes */
|
||||
#define POLICYDB_VERSION_BASE 15
|
||||
#define POLICYDB_VERSION_BOOL 16
|
||||
#define POLICYDB_VERSION_IPV6 17
|
||||
#define POLICYDB_VERSION_NLCLASS 18
|
||||
|
||||
/* Range of policy versions we understand*/
|
||||
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
|
||||
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NLCLASS
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
|
||||
extern int selinux_enabled;
|
||||
#else
|
||||
#define selinux_enabled 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
#define selinux_mls_enabled 1
|
||||
#else
|
||||
#define selinux_mls_enabled 0
|
||||
#endif
|
||||
|
||||
int security_load_policy(void * data, size_t len);
|
||||
|
||||
struct av_decision {
|
||||
u32 allowed;
|
||||
u32 decided;
|
||||
u32 auditallow;
|
||||
u32 auditdeny;
|
||||
u32 seqno;
|
||||
};
|
||||
|
||||
int security_compute_av(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 requested,
|
||||
struct av_decision *avd);
|
||||
|
||||
int security_transition_sid(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 *out_sid);
|
||||
|
||||
int security_member_sid(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 *out_sid);
|
||||
|
||||
int security_change_sid(u32 ssid, u32 tsid,
|
||||
u16 tclass, u32 *out_sid);
|
||||
|
||||
int security_sid_to_context(u32 sid, char **scontext,
|
||||
u32 *scontext_len);
|
||||
|
||||
int security_context_to_sid(char *scontext, u32 scontext_len,
|
||||
u32 *out_sid);
|
||||
|
||||
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_netif_sid(char *name, u32 *if_sid,
|
||||
u32 *msg_sid);
|
||||
|
||||
int security_node_sid(u16 domain, void *addr, u32 addrlen,
|
||||
u32 *out_sid);
|
||||
|
||||
#define SECURITY_FS_USE_XATTR 1 /* use xattr */
|
||||
#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
|
||||
#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
|
||||
#define SECURITY_FS_USE_GENFS 4 /* use the genfs support */
|
||||
#define SECURITY_FS_USE_NONE 5 /* no labeling support */
|
||||
#define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */
|
||||
|
||||
int security_fs_use(const char *fstype, unsigned int *behavior,
|
||||
u32 *sid);
|
||||
|
||||
int security_genfs_sid(const char *fstype, char *name, u16 sclass,
|
||||
u32 *sid);
|
||||
|
||||
#endif /* _SELINUX_SECURITY_H_ */
|
||||
|
||||
270
extra/linux-2.6.10/security/selinux/netif.c
Normal file
270
extra/linux-2.6.10/security/selinux/netif.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Network interface table.
|
||||
*
|
||||
* Network interfaces (devices) do not have a security field, so we
|
||||
* maintain a table associating each interface with a SID.
|
||||
*
|
||||
* Author: James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
#include "security.h"
|
||||
#include "objsec.h"
|
||||
#include "netif.h"
|
||||
|
||||
#define SEL_NETIF_HASH_SIZE 64
|
||||
#define SEL_NETIF_HASH_MAX 1024
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUGP printk
|
||||
#else
|
||||
#define DEBUGP(format, args...)
|
||||
#endif
|
||||
|
||||
struct sel_netif
|
||||
{
|
||||
struct list_head list;
|
||||
struct netif_security_struct nsec;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
static u32 sel_netif_total;
|
||||
static LIST_HEAD(sel_netif_list);
|
||||
static spinlock_t sel_netif_lock = SPIN_LOCK_UNLOCKED;
|
||||
static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE];
|
||||
|
||||
static inline u32 sel_netif_hasfn(struct net_device *dev)
|
||||
{
|
||||
return (dev->ifindex & (SEL_NETIF_HASH_SIZE - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* All of the devices should normally fit in the hash, so we optimize
|
||||
* for that case.
|
||||
*/
|
||||
static inline struct sel_netif *sel_netif_find(struct net_device *dev)
|
||||
{
|
||||
struct list_head *pos;
|
||||
int idx = sel_netif_hasfn(dev);
|
||||
|
||||
__list_for_each_rcu(pos, &sel_netif_hash[idx]) {
|
||||
struct sel_netif *netif = list_entry(pos,
|
||||
struct sel_netif, list);
|
||||
if (likely(netif->nsec.dev == dev))
|
||||
return netif;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sel_netif_insert(struct sel_netif *netif)
|
||||
{
|
||||
int idx, ret = 0;
|
||||
|
||||
if (sel_netif_total >= SEL_NETIF_HASH_MAX) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
idx = sel_netif_hasfn(netif->nsec.dev);
|
||||
list_add_rcu(&netif->list, &sel_netif_hash[idx]);
|
||||
sel_netif_total++;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sel_netif_free(struct rcu_head *p)
|
||||
{
|
||||
struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head);
|
||||
|
||||
DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
|
||||
kfree(netif);
|
||||
}
|
||||
|
||||
static void sel_netif_destroy(struct sel_netif *netif)
|
||||
{
|
||||
DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
|
||||
|
||||
list_del_rcu(&netif->list);
|
||||
sel_netif_total--;
|
||||
call_rcu(&netif->rcu_head, sel_netif_free);
|
||||
}
|
||||
|
||||
static struct sel_netif *sel_netif_lookup(struct net_device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sel_netif *netif, *new;
|
||||
struct netif_security_struct *nsec;
|
||||
|
||||
netif = sel_netif_find(dev);
|
||||
if (likely(netif != NULL))
|
||||
goto out;
|
||||
|
||||
new = kmalloc(sizeof(*new), GFP_ATOMIC);
|
||||
if (!new) {
|
||||
netif = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(new, 0, sizeof(*new));
|
||||
nsec = &new->nsec;
|
||||
|
||||
ret = security_netif_sid(dev->name, &nsec->if_sid, &nsec->msg_sid);
|
||||
if (ret < 0) {
|
||||
kfree(new);
|
||||
netif = ERR_PTR(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nsec->dev = dev;
|
||||
|
||||
spin_lock_bh(&sel_netif_lock);
|
||||
|
||||
netif = sel_netif_find(dev);
|
||||
if (netif) {
|
||||
spin_unlock_bh(&sel_netif_lock);
|
||||
kfree(new);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sel_netif_insert(new);
|
||||
spin_unlock_bh(&sel_netif_lock);
|
||||
|
||||
if (ret) {
|
||||
kfree(new);
|
||||
netif = ERR_PTR(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
netif = new;
|
||||
|
||||
DEBUGP("new: ifindex=%u name=%s if_sid=%u msg_sid=%u\n", dev->ifindex, dev->name,
|
||||
nsec->if_sid, nsec->msg_sid);
|
||||
out:
|
||||
return netif;
|
||||
}
|
||||
|
||||
static void sel_netif_assign_sids(u32 if_sid_in, u32 msg_sid_in, u32 *if_sid_out, u32 *msg_sid_out)
|
||||
{
|
||||
if (if_sid_out)
|
||||
*if_sid_out = if_sid_in;
|
||||
if (msg_sid_out)
|
||||
*msg_sid_out = msg_sid_in;
|
||||
}
|
||||
|
||||
static int sel_netif_sids_slow(struct net_device *dev, u32 *if_sid, u32 *msg_sid)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 tmp_if_sid, tmp_msg_sid;
|
||||
|
||||
ret = security_netif_sid(dev->name, &tmp_if_sid, &tmp_msg_sid);
|
||||
if (!ret)
|
||||
sel_netif_assign_sids(tmp_if_sid, tmp_msg_sid, if_sid, msg_sid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sel_netif *netif;
|
||||
|
||||
rcu_read_lock();
|
||||
netif = sel_netif_lookup(dev);
|
||||
if (IS_ERR(netif)) {
|
||||
rcu_read_unlock();
|
||||
ret = sel_netif_sids_slow(dev, if_sid, msg_sid);
|
||||
goto out;
|
||||
}
|
||||
sel_netif_assign_sids(netif->nsec.if_sid, netif->nsec.msg_sid, if_sid, msg_sid);
|
||||
rcu_read_unlock();
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sel_netif_kill(struct net_device *dev)
|
||||
{
|
||||
struct sel_netif *netif;
|
||||
|
||||
spin_lock_bh(&sel_netif_lock);
|
||||
netif = sel_netif_find(dev);
|
||||
if (netif)
|
||||
sel_netif_destroy(netif);
|
||||
spin_unlock_bh(&sel_netif_lock);
|
||||
}
|
||||
|
||||
static void sel_netif_flush(void)
|
||||
{
|
||||
int idx;
|
||||
|
||||
spin_lock_bh(&sel_netif_lock);
|
||||
for (idx = 0; idx < SEL_NETIF_HASH_SIZE; idx++) {
|
||||
struct sel_netif *netif;
|
||||
|
||||
list_for_each_entry(netif, &sel_netif_hash[idx], list)
|
||||
sel_netif_destroy(netif);
|
||||
}
|
||||
spin_unlock_bh(&sel_netif_lock);
|
||||
}
|
||||
|
||||
static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
|
||||
u16 class, u32 perms, u32 *retained)
|
||||
{
|
||||
if (event == AVC_CALLBACK_RESET) {
|
||||
sel_netif_flush();
|
||||
synchronize_net();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
|
||||
if (event == NETDEV_DOWN)
|
||||
sel_netif_kill(dev);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block sel_netif_netdev_notifier = {
|
||||
.notifier_call = sel_netif_netdev_notifier_handler,
|
||||
};
|
||||
|
||||
static __init int sel_netif_init(void)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
||||
if (!selinux_enabled)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < SEL_NETIF_HASH_SIZE; i++)
|
||||
INIT_LIST_HEAD(&sel_netif_hash[i]);
|
||||
|
||||
register_netdevice_notifier(&sel_netif_netdev_notifier);
|
||||
|
||||
err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET,
|
||||
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
|
||||
if (err)
|
||||
panic("avc_add_callback() failed, error %d\n", err);
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
__initcall(sel_netif_init);
|
||||
|
||||
113
extra/linux-2.6.10/security/selinux/netlink.c
Normal file
113
extra/linux-2.6.10/security/selinux/netlink.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Netlink event notifications for SELinux.
|
||||
*
|
||||
* Author: James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/selinux_netlink.h>
|
||||
|
||||
static struct sock *selnl;
|
||||
|
||||
static int selnl_msglen(int msgtype)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (msgtype) {
|
||||
case SELNL_MSG_SETENFORCE:
|
||||
ret = sizeof(struct selnl_msg_setenforce);
|
||||
break;
|
||||
|
||||
case SELNL_MSG_POLICYLOAD:
|
||||
ret = sizeof(struct selnl_msg_policyload);
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *data)
|
||||
{
|
||||
switch (msgtype) {
|
||||
case SELNL_MSG_SETENFORCE: {
|
||||
struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
|
||||
|
||||
memset(msg, 0, len);
|
||||
msg->val = *((int *)data);
|
||||
break;
|
||||
}
|
||||
|
||||
case SELNL_MSG_POLICYLOAD: {
|
||||
struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
|
||||
|
||||
memset(msg, 0, len);
|
||||
msg->seqno = *((u32 *)data);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static void selnl_notify(int msgtype, void *data)
|
||||
{
|
||||
int len;
|
||||
unsigned char *tmp;
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
len = selnl_msglen(msgtype);
|
||||
|
||||
skb = alloc_skb(NLMSG_SPACE(len), GFP_USER);
|
||||
if (!skb)
|
||||
goto oom;
|
||||
|
||||
tmp = skb->tail;
|
||||
nlh = NLMSG_PUT(skb, 0, 0, msgtype, len);
|
||||
selnl_add_payload(nlh, len, msgtype, data);
|
||||
nlh->nlmsg_len = skb->tail - tmp;
|
||||
netlink_broadcast(selnl, skb, 0, SELNL_GRP_AVC, GFP_USER);
|
||||
out:
|
||||
return;
|
||||
|
||||
nlmsg_failure:
|
||||
kfree_skb(skb);
|
||||
oom:
|
||||
printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void selnl_notify_setenforce(int val)
|
||||
{
|
||||
selnl_notify(SELNL_MSG_SETENFORCE, &val);
|
||||
}
|
||||
|
||||
void selnl_notify_policyload(u32 seqno)
|
||||
{
|
||||
selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
|
||||
}
|
||||
|
||||
static int __init selnl_init(void)
|
||||
{
|
||||
selnl = netlink_kernel_create(NETLINK_SELINUX, NULL);
|
||||
if (selnl == NULL)
|
||||
panic("SELinux: Cannot create netlink socket.");
|
||||
netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(selnl_init);
|
||||
153
extra/linux-2.6.10/security/selinux/nlmsgtab.c
Normal file
153
extra/linux-2.6.10/security/selinux/nlmsgtab.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Netlink message type permission tables, for user generated messages.
|
||||
*
|
||||
* Author: James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/netfilter_ipv4/ip_queue.h>
|
||||
#include <linux/tcp_diag.h>
|
||||
#include <linux/xfrm.h>
|
||||
#include <linux/audit.h>
|
||||
|
||||
#include "flask.h"
|
||||
#include "av_permissions.h"
|
||||
|
||||
struct nlmsg_perm
|
||||
{
|
||||
u16 nlmsg_type;
|
||||
u32 perm;
|
||||
};
|
||||
|
||||
static struct nlmsg_perm nlmsg_route_perms[] =
|
||||
{
|
||||
{ RTM_NEWLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETLINK, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_SETLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_NEWADDR, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELADDR, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETADDR, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWROUTE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELROUTE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETROUTE, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWRULE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELRULE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETRULE, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWQDISC, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELQDISC, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETQDISC, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_DELTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_NEWPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||
{ RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
{ RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||
};
|
||||
|
||||
static struct nlmsg_perm nlmsg_firewall_perms[] =
|
||||
{
|
||||
{ IPQM_MODE, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
|
||||
{ IPQM_VERDICT, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
|
||||
};
|
||||
|
||||
static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
|
||||
{
|
||||
{ TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
|
||||
};
|
||||
|
||||
static struct nlmsg_perm nlmsg_xfrm_perms[] =
|
||||
{
|
||||
{ XFRM_MSG_NEWSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
|
||||
{ XFRM_MSG_DELSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
|
||||
{ XFRM_MSG_GETSA, NETLINK_XFRM_SOCKET__NLMSG_READ },
|
||||
{ XFRM_MSG_NEWPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
|
||||
{ XFRM_MSG_DELPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
|
||||
{ XFRM_MSG_GETPOLICY, NETLINK_XFRM_SOCKET__NLMSG_READ },
|
||||
{ XFRM_MSG_ALLOCSPI, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
|
||||
{ XFRM_MSG_UPDPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
|
||||
{ XFRM_MSG_UPDSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
|
||||
};
|
||||
|
||||
static struct nlmsg_perm nlmsg_audit_perms[] =
|
||||
{
|
||||
{ AUDIT_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ },
|
||||
{ AUDIT_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
|
||||
{ AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READ },
|
||||
{ AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
|
||||
{ AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
|
||||
{ AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
|
||||
{ AUDIT_LOGIN, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
|
||||
};
|
||||
|
||||
|
||||
static int nlmsg_perm(u16 nlmsg_type, u32 *perm, struct nlmsg_perm *tab, size_t tabsize)
|
||||
{
|
||||
int i, err = -EINVAL;
|
||||
|
||||
for (i = 0; i < tabsize/sizeof(struct nlmsg_perm); i++)
|
||||
if (nlmsg_type == tab[i].nlmsg_type) {
|
||||
*perm = tab[i].perm;
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
switch (sclass) {
|
||||
case SECCLASS_NETLINK_ROUTE_SOCKET:
|
||||
err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
|
||||
sizeof(nlmsg_route_perms));
|
||||
break;
|
||||
|
||||
case SECCLASS_NETLINK_FIREWALL_SOCKET:
|
||||
case NETLINK_IP6_FW:
|
||||
err = nlmsg_perm(nlmsg_type, perm, nlmsg_firewall_perms,
|
||||
sizeof(nlmsg_firewall_perms));
|
||||
break;
|
||||
|
||||
case SECCLASS_NETLINK_TCPDIAG_SOCKET:
|
||||
err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms,
|
||||
sizeof(nlmsg_tcpdiag_perms));
|
||||
break;
|
||||
|
||||
case SECCLASS_NETLINK_XFRM_SOCKET:
|
||||
err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms,
|
||||
sizeof(nlmsg_xfrm_perms));
|
||||
break;
|
||||
|
||||
case SECCLASS_NETLINK_AUDIT_SOCKET:
|
||||
err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
|
||||
sizeof(nlmsg_audit_perms));
|
||||
break;
|
||||
|
||||
/* No messaging from userspace, or class unknown/unhandled */
|
||||
default:
|
||||
err = -ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
992
extra/linux-2.6.10/security/selinux/selinuxfs.c
Normal file
992
extra/linux-2.6.10/security/selinux/selinuxfs.c
Normal file
@@ -0,0 +1,992 @@
|
||||
/* Updated: Karl MacMillan <kmacmillan@tresys.com>
|
||||
*
|
||||
* Added conditional policy language extensions
|
||||
*
|
||||
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/major.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
/* selinuxfs pseudo filesystem for exporting the security policy API.
|
||||
Based on the proc code and the fs/nfsd/nfsctl.c code. */
|
||||
|
||||
#include "flask.h"
|
||||
#include "avc.h"
|
||||
#include "avc_ss.h"
|
||||
#include "security.h"
|
||||
#include "objsec.h"
|
||||
#include "conditional.h"
|
||||
|
||||
static DECLARE_MUTEX(sel_sem);
|
||||
|
||||
/* global data for booleans */
|
||||
static struct dentry *bool_dir = NULL;
|
||||
static int bool_num = 0;
|
||||
static int *bool_pending_values = NULL;
|
||||
|
||||
extern void selnl_notify_setenforce(int val);
|
||||
|
||||
/* Check whether a task is allowed to use a security operation. */
|
||||
int task_has_security(struct task_struct *tsk,
|
||||
u32 perms)
|
||||
{
|
||||
struct task_security_struct *tsec;
|
||||
|
||||
tsec = tsk->security;
|
||||
if (!tsec)
|
||||
return -EACCES;
|
||||
|
||||
return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
|
||||
SECCLASS_SECURITY, perms, NULL, NULL);
|
||||
}
|
||||
|
||||
enum sel_inos {
|
||||
SEL_ROOT_INO = 2,
|
||||
SEL_LOAD, /* load policy */
|
||||
SEL_ENFORCE, /* get or set enforcing status */
|
||||
SEL_CONTEXT, /* validate context */
|
||||
SEL_ACCESS, /* compute access decision */
|
||||
SEL_CREATE, /* compute create labeling decision */
|
||||
SEL_RELABEL, /* compute relabeling decision */
|
||||
SEL_USER, /* compute reachable user contexts */
|
||||
SEL_POLICYVERS, /* return policy version for this kernel */
|
||||
SEL_COMMIT_BOOLS, /* commit new boolean values */
|
||||
SEL_MLS, /* return if MLS policy is enabled */
|
||||
SEL_DISABLE /* disable SELinux until next reboot */
|
||||
};
|
||||
|
||||
#define TMPBUFLEN 12
|
||||
static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing);
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||
static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
char *page;
|
||||
ssize_t length;
|
||||
int new_value;
|
||||
|
||||
if (count < 0 || count >= PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
if (*ppos != 0) {
|
||||
/* No partial writes. */
|
||||
return -EINVAL;
|
||||
}
|
||||
page = (char*)get_zeroed_page(GFP_KERNEL);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
length = -EFAULT;
|
||||
if (copy_from_user(page, buf, count))
|
||||
goto out;
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(page, "%d", &new_value) != 1)
|
||||
goto out;
|
||||
|
||||
if (new_value != selinux_enforcing) {
|
||||
length = task_has_security(current, SECURITY__SETENFORCE);
|
||||
if (length)
|
||||
goto out;
|
||||
selinux_enforcing = new_value;
|
||||
if (selinux_enforcing)
|
||||
avc_ss_reset(0);
|
||||
selnl_notify_setenforce(selinux_enforcing);
|
||||
}
|
||||
length = count;
|
||||
out:
|
||||
free_page((unsigned long) page);
|
||||
return length;
|
||||
}
|
||||
#else
|
||||
#define sel_write_enforce NULL
|
||||
#endif
|
||||
|
||||
static struct file_operations sel_enforce_ops = {
|
||||
.read = sel_read_enforce,
|
||||
.write = sel_write_enforce,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
static ssize_t sel_write_disable(struct file * file, const char __user * buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
char *page;
|
||||
ssize_t length;
|
||||
int new_value;
|
||||
extern int selinux_disable(void);
|
||||
|
||||
if (count < 0 || count >= PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
if (*ppos != 0) {
|
||||
/* No partial writes. */
|
||||
return -EINVAL;
|
||||
}
|
||||
page = (char*)get_zeroed_page(GFP_KERNEL);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
length = -EFAULT;
|
||||
if (copy_from_user(page, buf, count))
|
||||
goto out;
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(page, "%d", &new_value) != 1)
|
||||
goto out;
|
||||
|
||||
if (new_value) {
|
||||
length = selinux_disable();
|
||||
if (length < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
length = count;
|
||||
out:
|
||||
free_page((unsigned long) page);
|
||||
return length;
|
||||
}
|
||||
#else
|
||||
#define sel_write_disable NULL
|
||||
#endif
|
||||
|
||||
static struct file_operations sel_disable_ops = {
|
||||
.write = sel_write_disable,
|
||||
};
|
||||
|
||||
static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX);
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
static struct file_operations sel_policyvers_ops = {
|
||||
.read = sel_read_policyvers,
|
||||
};
|
||||
|
||||
/* declaration for sel_write_load */
|
||||
static int sel_make_bools(void);
|
||||
|
||||
static ssize_t sel_read_mls(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
static struct file_operations sel_mls_ops = {
|
||||
.read = sel_read_mls,
|
||||
};
|
||||
|
||||
static ssize_t sel_write_load(struct file * file, const char __user * buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
int ret;
|
||||
ssize_t length;
|
||||
void *data = NULL;
|
||||
|
||||
down(&sel_sem);
|
||||
|
||||
length = task_has_security(current, SECURITY__LOAD_POLICY);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
if (*ppos != 0) {
|
||||
/* No partial writes. */
|
||||
length = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((count < 0) || (count > 64 * 1024 * 1024)
|
||||
|| (data = vmalloc(count)) == NULL) {
|
||||
length = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
length = -EFAULT;
|
||||
if (copy_from_user(data, buf, count) != 0)
|
||||
goto out;
|
||||
|
||||
length = security_load_policy(data, count);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
ret = sel_make_bools();
|
||||
if (ret)
|
||||
length = ret;
|
||||
else
|
||||
length = count;
|
||||
out:
|
||||
up(&sel_sem);
|
||||
vfree(data);
|
||||
return length;
|
||||
}
|
||||
|
||||
static struct file_operations sel_load_ops = {
|
||||
.write = sel_write_load,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t sel_write_context(struct file * file, const char __user * buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
||||
{
|
||||
char *page;
|
||||
u32 sid;
|
||||
ssize_t length;
|
||||
|
||||
length = task_has_security(current, SECURITY__CHECK_CONTEXT);
|
||||
if (length)
|
||||
return length;
|
||||
|
||||
if (count < 0 || count >= PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
if (*ppos != 0) {
|
||||
/* No partial writes. */
|
||||
return -EINVAL;
|
||||
}
|
||||
page = (char*)get_zeroed_page(GFP_KERNEL);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
length = -EFAULT;
|
||||
if (copy_from_user(page, buf, count))
|
||||
goto out;
|
||||
|
||||
length = security_context_to_sid(page, count, &sid);
|
||||
if (length < 0)
|
||||
goto out;
|
||||
|
||||
length = count;
|
||||
out:
|
||||
free_page((unsigned long) page);
|
||||
return length;
|
||||
}
|
||||
|
||||
static struct file_operations sel_context_ops = {
|
||||
.write = sel_write_context,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
|
||||
*/
|
||||
static ssize_t sel_write_access(struct file * file, char *buf, size_t size);
|
||||
static ssize_t sel_write_create(struct file * file, char *buf, size_t size);
|
||||
static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size);
|
||||
static ssize_t sel_write_user(struct file * file, char *buf, size_t size);
|
||||
|
||||
static ssize_t (*write_op[])(struct file *, char *, size_t) = {
|
||||
[SEL_ACCESS] = sel_write_access,
|
||||
[SEL_CREATE] = sel_write_create,
|
||||
[SEL_RELABEL] = sel_write_relabel,
|
||||
[SEL_USER] = sel_write_user,
|
||||
};
|
||||
|
||||
static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
|
||||
{
|
||||
ino_t ino = file->f_dentry->d_inode->i_ino;
|
||||
char *data;
|
||||
ssize_t rv;
|
||||
|
||||
if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
|
||||
return -EINVAL;
|
||||
|
||||
data = simple_transaction_get(file, buf, size);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
rv = write_op[ino](file, data, size);
|
||||
if (rv>0) {
|
||||
simple_transaction_set(file, rv);
|
||||
rv = size;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static struct file_operations transaction_ops = {
|
||||
.write = selinux_transaction_write,
|
||||
.read = simple_transaction_read,
|
||||
.release = simple_transaction_release,
|
||||
};
|
||||
|
||||
/*
|
||||
* payload - write methods
|
||||
* If the method has a response, the response should be put in buf,
|
||||
* and the length returned. Otherwise return 0 or and -error.
|
||||
*/
|
||||
|
||||
static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
|
||||
{
|
||||
char *scon, *tcon;
|
||||
u32 ssid, tsid;
|
||||
u16 tclass;
|
||||
u32 req;
|
||||
struct av_decision avd;
|
||||
ssize_t length;
|
||||
|
||||
length = task_has_security(current, SECURITY__COMPUTE_AV);
|
||||
if (length)
|
||||
return length;
|
||||
|
||||
length = -ENOMEM;
|
||||
scon = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!scon)
|
||||
return length;
|
||||
memset(scon, 0, size+1);
|
||||
|
||||
tcon = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!tcon)
|
||||
goto out;
|
||||
memset(tcon, 0, size+1);
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
|
||||
goto out2;
|
||||
|
||||
length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = security_compute_av(ssid, tsid, tclass, req, &avd);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
|
||||
"%x %x %x %x %u",
|
||||
avd.allowed, avd.decided,
|
||||
avd.auditallow, avd.auditdeny,
|
||||
avd.seqno);
|
||||
out2:
|
||||
kfree(tcon);
|
||||
out:
|
||||
kfree(scon);
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
|
||||
{
|
||||
char *scon, *tcon;
|
||||
u32 ssid, tsid, newsid;
|
||||
u16 tclass;
|
||||
ssize_t length;
|
||||
char *newcon;
|
||||
u32 len;
|
||||
|
||||
length = task_has_security(current, SECURITY__COMPUTE_CREATE);
|
||||
if (length)
|
||||
return length;
|
||||
|
||||
length = -ENOMEM;
|
||||
scon = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!scon)
|
||||
return length;
|
||||
memset(scon, 0, size+1);
|
||||
|
||||
tcon = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!tcon)
|
||||
goto out;
|
||||
memset(tcon, 0, size+1);
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
|
||||
goto out2;
|
||||
|
||||
length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = security_transition_sid(ssid, tsid, tclass, &newsid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = security_sid_to_context(newsid, &newcon, &len);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
||||
printk(KERN_ERR "%s: context size (%u) exceeds payload "
|
||||
"max\n", __FUNCTION__, len);
|
||||
length = -ERANGE;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
memcpy(buf, newcon, len);
|
||||
length = len;
|
||||
out3:
|
||||
kfree(newcon);
|
||||
out2:
|
||||
kfree(tcon);
|
||||
out:
|
||||
kfree(scon);
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
|
||||
{
|
||||
char *scon, *tcon;
|
||||
u32 ssid, tsid, newsid;
|
||||
u16 tclass;
|
||||
ssize_t length;
|
||||
char *newcon;
|
||||
u32 len;
|
||||
|
||||
length = task_has_security(current, SECURITY__COMPUTE_RELABEL);
|
||||
if (length)
|
||||
return length;
|
||||
|
||||
length = -ENOMEM;
|
||||
scon = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!scon)
|
||||
return length;
|
||||
memset(scon, 0, size+1);
|
||||
|
||||
tcon = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!tcon)
|
||||
goto out;
|
||||
memset(tcon, 0, size+1);
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
|
||||
goto out2;
|
||||
|
||||
length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = security_change_sid(ssid, tsid, tclass, &newsid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = security_sid_to_context(newsid, &newcon, &len);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
if (len > SIMPLE_TRANSACTION_LIMIT) {
|
||||
length = -ERANGE;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
memcpy(buf, newcon, len);
|
||||
length = len;
|
||||
out3:
|
||||
kfree(newcon);
|
||||
out2:
|
||||
kfree(tcon);
|
||||
out:
|
||||
kfree(scon);
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
|
||||
{
|
||||
char *con, *user, *ptr;
|
||||
u32 sid, *sids;
|
||||
ssize_t length;
|
||||
char *newcon;
|
||||
int i, rc;
|
||||
u32 len, nsids;
|
||||
|
||||
length = task_has_security(current, SECURITY__COMPUTE_USER);
|
||||
if (length)
|
||||
return length;
|
||||
|
||||
length = -ENOMEM;
|
||||
con = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!con)
|
||||
return length;
|
||||
memset(con, 0, size+1);
|
||||
|
||||
user = kmalloc(size+1, GFP_KERNEL);
|
||||
if (!user)
|
||||
goto out;
|
||||
memset(user, 0, size+1);
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(buf, "%s %s", con, user) != 2)
|
||||
goto out2;
|
||||
|
||||
length = security_context_to_sid(con, strlen(con)+1, &sid);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = security_get_user_sids(sid, user, &sids, &nsids);
|
||||
if (length < 0)
|
||||
goto out2;
|
||||
|
||||
length = sprintf(buf, "%u", nsids) + 1;
|
||||
ptr = buf + length;
|
||||
for (i = 0; i < nsids; i++) {
|
||||
rc = security_sid_to_context(sids[i], &newcon, &len);
|
||||
if (rc) {
|
||||
length = rc;
|
||||
goto out3;
|
||||
}
|
||||
if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
|
||||
kfree(newcon);
|
||||
length = -ERANGE;
|
||||
goto out3;
|
||||
}
|
||||
memcpy(ptr, newcon, len);
|
||||
kfree(newcon);
|
||||
ptr += len;
|
||||
length += len;
|
||||
}
|
||||
out3:
|
||||
kfree(sids);
|
||||
out2:
|
||||
kfree(user);
|
||||
out:
|
||||
kfree(con);
|
||||
return length;
|
||||
}
|
||||
|
||||
static struct inode *sel_make_inode(struct super_block *sb, int mode)
|
||||
{
|
||||
struct inode *ret = new_inode(sb);
|
||||
|
||||
if (ret) {
|
||||
ret->i_mode = mode;
|
||||
ret->i_uid = ret->i_gid = 0;
|
||||
ret->i_blksize = PAGE_CACHE_SIZE;
|
||||
ret->i_blocks = 0;
|
||||
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define BOOL_INO_OFFSET 30
|
||||
|
||||
static ssize_t sel_read_bool(struct file *filep, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *page = NULL;
|
||||
ssize_t length;
|
||||
ssize_t end;
|
||||
ssize_t ret;
|
||||
int cur_enforcing;
|
||||
struct inode *inode;
|
||||
|
||||
down(&sel_sem);
|
||||
|
||||
ret = -EFAULT;
|
||||
|
||||
/* check to see if this file has been deleted */
|
||||
if (!filep->f_op)
|
||||
goto out;
|
||||
|
||||
if (count < 0 || count > PAGE_SIZE) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode = filep->f_dentry->d_inode;
|
||||
cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
|
||||
if (cur_enforcing < 0) {
|
||||
ret = cur_enforcing;
|
||||
goto out;
|
||||
}
|
||||
|
||||
length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
|
||||
bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
|
||||
if (length < 0) {
|
||||
ret = length;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*ppos >= length) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if (count + *ppos > length)
|
||||
count = length - *ppos;
|
||||
end = count + *ppos;
|
||||
if (copy_to_user(buf, (char *) page + *ppos, count)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
*ppos = end;
|
||||
ret = count;
|
||||
out:
|
||||
up(&sel_sem);
|
||||
if (page)
|
||||
free_page((unsigned long)page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *page = NULL;
|
||||
ssize_t length = -EFAULT;
|
||||
int new_value;
|
||||
struct inode *inode;
|
||||
|
||||
down(&sel_sem);
|
||||
|
||||
length = task_has_security(current, SECURITY__SETBOOL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
/* check to see if this file has been deleted */
|
||||
if (!filep->f_op)
|
||||
goto out;
|
||||
|
||||
if (count < 0 || count >= PAGE_SIZE) {
|
||||
length = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (*ppos != 0) {
|
||||
/* No partial writes. */
|
||||
goto out;
|
||||
}
|
||||
page = (char*)get_zeroed_page(GFP_KERNEL);
|
||||
if (!page) {
|
||||
length = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(page, buf, count))
|
||||
goto out;
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(page, "%d", &new_value) != 1)
|
||||
goto out;
|
||||
|
||||
if (new_value)
|
||||
new_value = 1;
|
||||
|
||||
inode = filep->f_dentry->d_inode;
|
||||
bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
|
||||
length = count;
|
||||
|
||||
out:
|
||||
up(&sel_sem);
|
||||
if (page)
|
||||
free_page((unsigned long) page);
|
||||
return length;
|
||||
}
|
||||
|
||||
static struct file_operations sel_bool_ops = {
|
||||
.read = sel_read_bool,
|
||||
.write = sel_write_bool,
|
||||
};
|
||||
|
||||
static ssize_t sel_commit_bools_write(struct file *filep,
|
||||
const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *page = NULL;
|
||||
ssize_t length = -EFAULT;
|
||||
int new_value;
|
||||
|
||||
down(&sel_sem);
|
||||
|
||||
length = task_has_security(current, SECURITY__SETBOOL);
|
||||
if (length)
|
||||
goto out;
|
||||
|
||||
/* check to see if this file has been deleted */
|
||||
if (!filep->f_op)
|
||||
goto out;
|
||||
|
||||
if (count < 0 || count >= PAGE_SIZE) {
|
||||
length = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (*ppos != 0) {
|
||||
/* No partial writes. */
|
||||
goto out;
|
||||
}
|
||||
page = (char*)get_zeroed_page(GFP_KERNEL);
|
||||
if (!page) {
|
||||
length = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(page, buf, count))
|
||||
goto out;
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(page, "%d", &new_value) != 1)
|
||||
goto out;
|
||||
|
||||
if (new_value) {
|
||||
security_set_bools(bool_num, bool_pending_values);
|
||||
}
|
||||
|
||||
length = count;
|
||||
|
||||
out:
|
||||
up(&sel_sem);
|
||||
if (page)
|
||||
free_page((unsigned long) page);
|
||||
return length;
|
||||
}
|
||||
|
||||
static struct file_operations sel_commit_bools_ops = {
|
||||
.write = sel_commit_bools_write,
|
||||
};
|
||||
|
||||
/* delete booleans - partial revoke() from
|
||||
* fs/proc/generic.c proc_kill_inodes */
|
||||
static void sel_remove_bools(struct dentry *de)
|
||||
{
|
||||
struct list_head *p, *node;
|
||||
struct super_block *sb = de->d_sb;
|
||||
|
||||
spin_lock(&dcache_lock);
|
||||
node = de->d_subdirs.next;
|
||||
while (node != &de->d_subdirs) {
|
||||
struct dentry *d = list_entry(node, struct dentry, d_child);
|
||||
list_del_init(node);
|
||||
|
||||
if (d->d_inode) {
|
||||
d = dget_locked(d);
|
||||
spin_unlock(&dcache_lock);
|
||||
d_delete(d);
|
||||
simple_unlink(de->d_inode, d);
|
||||
dput(d);
|
||||
spin_lock(&dcache_lock);
|
||||
}
|
||||
node = de->d_subdirs.next;
|
||||
}
|
||||
|
||||
spin_unlock(&dcache_lock);
|
||||
|
||||
file_list_lock();
|
||||
list_for_each(p, &sb->s_files) {
|
||||
struct file * filp = list_entry(p, struct file, f_list);
|
||||
struct dentry * dentry = filp->f_dentry;
|
||||
|
||||
if (dentry->d_parent != de) {
|
||||
continue;
|
||||
}
|
||||
filp->f_op = NULL;
|
||||
}
|
||||
file_list_unlock();
|
||||
}
|
||||
|
||||
#define BOOL_DIR_NAME "booleans"
|
||||
|
||||
static int sel_make_bools(void)
|
||||
{
|
||||
int i, ret = 0;
|
||||
ssize_t len;
|
||||
struct dentry *dentry = NULL;
|
||||
struct dentry *dir = bool_dir;
|
||||
struct inode *inode = NULL;
|
||||
struct inode_security_struct *isec;
|
||||
char **names = NULL, *page;
|
||||
int num;
|
||||
int *values = NULL;
|
||||
u32 sid;
|
||||
|
||||
/* remove any existing files */
|
||||
if (bool_pending_values)
|
||||
kfree(bool_pending_values);
|
||||
|
||||
sel_remove_bools(dir);
|
||||
|
||||
if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
|
||||
ret = security_get_bools(&num, &names, &values);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dentry = d_alloc_name(dir, names[i]);
|
||||
if (!dentry) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);
|
||||
if (!inode) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]);
|
||||
if (len < 0) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
} else if (len >= PAGE_SIZE) {
|
||||
ret = -ENAMETOOLONG;
|
||||
goto err;
|
||||
}
|
||||
isec = (struct inode_security_struct*)inode->i_security;
|
||||
if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
|
||||
goto err;
|
||||
isec->sid = sid;
|
||||
isec->initialized = 1;
|
||||
inode->i_fop = &sel_bool_ops;
|
||||
inode->i_ino = i + BOOL_INO_OFFSET;
|
||||
d_add(dentry, inode);
|
||||
}
|
||||
bool_num = num;
|
||||
bool_pending_values = values;
|
||||
out:
|
||||
free_page((unsigned long)page);
|
||||
if (names) {
|
||||
for (i = 0; i < num; i++) {
|
||||
if (names[i])
|
||||
kfree(names[i]);
|
||||
}
|
||||
kfree(names);
|
||||
}
|
||||
return ret;
|
||||
err:
|
||||
d_genocide(dir);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#define NULL_FILE_NAME "null"
|
||||
|
||||
struct dentry *selinux_null = NULL;
|
||||
|
||||
static int sel_fill_super(struct super_block * sb, void * data, int silent)
|
||||
{
|
||||
int ret;
|
||||
struct dentry *dentry;
|
||||
struct inode *inode;
|
||||
struct inode_security_struct *isec;
|
||||
|
||||
static struct tree_descr selinux_files[] = {
|
||||
[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
|
||||
[SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
|
||||
[SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO},
|
||||
[SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
|
||||
[SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},
|
||||
[SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},
|
||||
[SEL_USER] = {"user", &transaction_ops, S_IRUGO|S_IWUGO},
|
||||
[SEL_POLICYVERS] = {"policyvers", &sel_policyvers_ops, S_IRUGO},
|
||||
[SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR},
|
||||
[SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
|
||||
[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
|
||||
/* last one */ {""}
|
||||
};
|
||||
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME);
|
||||
if (!dentry)
|
||||
return -ENOMEM;
|
||||
|
||||
inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);
|
||||
if (!inode)
|
||||
goto out;
|
||||
inode->i_op = &simple_dir_inode_operations;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
d_add(dentry, inode);
|
||||
bool_dir = dentry;
|
||||
ret = sel_make_bools();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
|
||||
if (!dentry)
|
||||
return -ENOMEM;
|
||||
|
||||
inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
|
||||
if (!inode)
|
||||
goto out;
|
||||
isec = (struct inode_security_struct*)inode->i_security;
|
||||
isec->sid = SECINITSID_DEVNULL;
|
||||
isec->sclass = SECCLASS_CHR_FILE;
|
||||
isec->initialized = 1;
|
||||
|
||||
init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
|
||||
d_add(dentry, inode);
|
||||
selinux_null = dentry;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
dput(dentry);
|
||||
printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static struct super_block *sel_get_sb(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
return get_sb_single(fs_type, flags, data, sel_fill_super);
|
||||
}
|
||||
|
||||
static struct file_system_type sel_fs_type = {
|
||||
.name = "selinuxfs",
|
||||
.get_sb = sel_get_sb,
|
||||
.kill_sb = kill_litter_super,
|
||||
};
|
||||
|
||||
struct vfsmount *selinuxfs_mount;
|
||||
|
||||
static int __init init_sel_fs(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return 0;
|
||||
err = register_filesystem(&sel_fs_type);
|
||||
if (!err) {
|
||||
selinuxfs_mount = kern_mount(&sel_fs_type);
|
||||
if (IS_ERR(selinuxfs_mount)) {
|
||||
printk(KERN_ERR "selinuxfs: could not mount!\n");
|
||||
err = PTR_ERR(selinuxfs_mount);
|
||||
selinuxfs_mount = NULL;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
__initcall(init_sel_fs);
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
void exit_sel_fs(void)
|
||||
{
|
||||
unregister_filesystem(&sel_fs_type);
|
||||
}
|
||||
#endif
|
||||
11
extra/linux-2.6.10/security/selinux/ss/Makefile
Normal file
11
extra/linux-2.6.10/security/selinux/ss/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Makefile for building the SELinux security server as part of the kernel tree.
|
||||
#
|
||||
|
||||
EXTRA_CFLAGS += -Isecurity/selinux/include
|
||||
obj-y := ss.o
|
||||
|
||||
ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o
|
||||
|
||||
ss-$(CONFIG_SECURITY_SELINUX_MLS) += mls.o
|
||||
|
||||
414
extra/linux-2.6.10/security/selinux/ss/avtab.c
Normal file
414
extra/linux-2.6.10/security/selinux/ss/avtab.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Implementation of the access vector table type.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
|
||||
/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
|
||||
*
|
||||
* Added conditional policy language extensions
|
||||
*
|
||||
* Copyright (C) 2003 Tresys Technology, LLC
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "avtab.h"
|
||||
#include "policydb.h"
|
||||
|
||||
#define AVTAB_HASH(keyp) \
|
||||
((keyp->target_class + \
|
||||
(keyp->target_type << 2) + \
|
||||
(keyp->source_type << 9)) & \
|
||||
AVTAB_HASH_MASK)
|
||||
|
||||
static kmem_cache_t *avtab_node_cachep;
|
||||
|
||||
static struct avtab_node*
|
||||
avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur,
|
||||
struct avtab_key *key, struct avtab_datum *datum)
|
||||
{
|
||||
struct avtab_node * newnode;
|
||||
newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL);
|
||||
if (newnode == NULL)
|
||||
return NULL;
|
||||
memset(newnode, 0, sizeof(struct avtab_node));
|
||||
newnode->key = *key;
|
||||
newnode->datum = *datum;
|
||||
if (prev) {
|
||||
newnode->next = prev->next;
|
||||
prev->next = newnode;
|
||||
} else {
|
||||
newnode->next = h->htable[hvalue];
|
||||
h->htable[hvalue] = newnode;
|
||||
}
|
||||
|
||||
h->nel++;
|
||||
return newnode;
|
||||
}
|
||||
|
||||
int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
|
||||
{
|
||||
int hvalue;
|
||||
struct avtab_node *prev, *cur, *newnode;
|
||||
|
||||
if (!h)
|
||||
return -EINVAL;
|
||||
|
||||
hvalue = AVTAB_HASH(key);
|
||||
for (prev = NULL, cur = h->htable[hvalue];
|
||||
cur;
|
||||
prev = cur, cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class == cur->key.target_class &&
|
||||
(datum->specified & cur->datum.specified))
|
||||
return -EEXIST;
|
||||
if (key->source_type < cur->key.source_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type < cur->key.target_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class < cur->key.target_class)
|
||||
break;
|
||||
}
|
||||
|
||||
newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
|
||||
if(!newnode)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unlike avtab_insert(), this function allow multiple insertions of the same
|
||||
* key/specified mask into the table, as needed by the conditional avtab.
|
||||
* It also returns a pointer to the node inserted.
|
||||
*/
|
||||
struct avtab_node *
|
||||
avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_datum * datum)
|
||||
{
|
||||
int hvalue;
|
||||
struct avtab_node *prev, *cur, *newnode;
|
||||
|
||||
if (!h)
|
||||
return NULL;
|
||||
hvalue = AVTAB_HASH(key);
|
||||
for (prev = NULL, cur = h->htable[hvalue];
|
||||
cur;
|
||||
prev = cur, cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class == cur->key.target_class &&
|
||||
(datum->specified & cur->datum.specified))
|
||||
break;
|
||||
if (key->source_type < cur->key.source_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type < cur->key.target_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class < cur->key.target_class)
|
||||
break;
|
||||
}
|
||||
newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified)
|
||||
{
|
||||
int hvalue;
|
||||
struct avtab_node *cur;
|
||||
|
||||
if (!h)
|
||||
return NULL;
|
||||
|
||||
hvalue = AVTAB_HASH(key);
|
||||
for (cur = h->htable[hvalue]; cur; cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class == cur->key.target_class &&
|
||||
(specified & cur->datum.specified))
|
||||
return &cur->datum;
|
||||
|
||||
if (key->source_type < cur->key.source_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type < cur->key.target_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class < cur->key.target_class)
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This search function returns a node pointer, and can be used in
|
||||
* conjunction with avtab_search_next_node()
|
||||
*/
|
||||
struct avtab_node*
|
||||
avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
|
||||
{
|
||||
int hvalue;
|
||||
struct avtab_node *cur;
|
||||
|
||||
if (!h)
|
||||
return NULL;
|
||||
|
||||
hvalue = AVTAB_HASH(key);
|
||||
for (cur = h->htable[hvalue]; cur; cur = cur->next) {
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class == cur->key.target_class &&
|
||||
(specified & cur->datum.specified))
|
||||
return cur;
|
||||
|
||||
if (key->source_type < cur->key.source_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type < cur->key.target_type)
|
||||
break;
|
||||
if (key->source_type == cur->key.source_type &&
|
||||
key->target_type == cur->key.target_type &&
|
||||
key->target_class < cur->key.target_class)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct avtab_node*
|
||||
avtab_search_node_next(struct avtab_node *node, int specified)
|
||||
{
|
||||
struct avtab_node *cur;
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
for (cur = node->next; cur; cur = cur->next) {
|
||||
if (node->key.source_type == cur->key.source_type &&
|
||||
node->key.target_type == cur->key.target_type &&
|
||||
node->key.target_class == cur->key.target_class &&
|
||||
(specified & cur->datum.specified))
|
||||
return cur;
|
||||
|
||||
if (node->key.source_type < cur->key.source_type)
|
||||
break;
|
||||
if (node->key.source_type == cur->key.source_type &&
|
||||
node->key.target_type < cur->key.target_type)
|
||||
break;
|
||||
if (node->key.source_type == cur->key.source_type &&
|
||||
node->key.target_type == cur->key.target_type &&
|
||||
node->key.target_class < cur->key.target_class)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void avtab_destroy(struct avtab *h)
|
||||
{
|
||||
int i;
|
||||
struct avtab_node *cur, *temp;
|
||||
|
||||
if (!h || !h->htable)
|
||||
return;
|
||||
|
||||
for (i = 0; i < AVTAB_SIZE; i++) {
|
||||
cur = h->htable[i];
|
||||
while (cur != NULL) {
|
||||
temp = cur;
|
||||
cur = cur->next;
|
||||
kmem_cache_free(avtab_node_cachep, temp);
|
||||
}
|
||||
h->htable[i] = NULL;
|
||||
}
|
||||
vfree(h->htable);
|
||||
h->htable = NULL;
|
||||
}
|
||||
|
||||
|
||||
int avtab_map(struct avtab *h,
|
||||
int (*apply) (struct avtab_key *k,
|
||||
struct avtab_datum *d,
|
||||
void *args),
|
||||
void *args)
|
||||
{
|
||||
int i, ret;
|
||||
struct avtab_node *cur;
|
||||
|
||||
if (!h)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < AVTAB_SIZE; i++) {
|
||||
cur = h->htable[i];
|
||||
while (cur != NULL) {
|
||||
ret = apply(&cur->key, &cur->datum, args);
|
||||
if (ret)
|
||||
return ret;
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avtab_init(struct avtab *h)
|
||||
{
|
||||
int i;
|
||||
|
||||
h->htable = vmalloc(sizeof(*(h->htable)) * AVTAB_SIZE);
|
||||
if (!h->htable)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < AVTAB_SIZE; i++)
|
||||
h->htable[i] = NULL;
|
||||
h->nel = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void avtab_hash_eval(struct avtab *h, char *tag)
|
||||
{
|
||||
int i, chain_len, slots_used, max_chain_len;
|
||||
struct avtab_node *cur;
|
||||
|
||||
slots_used = 0;
|
||||
max_chain_len = 0;
|
||||
for (i = 0; i < AVTAB_SIZE; i++) {
|
||||
cur = h->htable[i];
|
||||
if (cur) {
|
||||
slots_used++;
|
||||
chain_len = 0;
|
||||
while (cur) {
|
||||
chain_len++;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (chain_len > max_chain_len)
|
||||
max_chain_len = chain_len;
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest "
|
||||
"chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
|
||||
max_chain_len);
|
||||
}
|
||||
|
||||
int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey)
|
||||
{
|
||||
__u32 *buf;
|
||||
__u32 items, items2;
|
||||
|
||||
memset(avkey, 0, sizeof(struct avtab_key));
|
||||
memset(avdatum, 0, sizeof(struct avtab_datum));
|
||||
|
||||
buf = next_entry(fp, sizeof(__u32));
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: avtab: truncated entry\n");
|
||||
goto bad;
|
||||
}
|
||||
items2 = le32_to_cpu(buf[0]);
|
||||
buf = next_entry(fp, sizeof(__u32)*items2);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: avtab: truncated entry\n");
|
||||
goto bad;
|
||||
}
|
||||
items = 0;
|
||||
avkey->source_type = le32_to_cpu(buf[items++]);
|
||||
avkey->target_type = le32_to_cpu(buf[items++]);
|
||||
avkey->target_class = le32_to_cpu(buf[items++]);
|
||||
avdatum->specified = le32_to_cpu(buf[items++]);
|
||||
if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) {
|
||||
printk(KERN_ERR "security: avtab: null entry\n");
|
||||
goto bad;
|
||||
}
|
||||
if ((avdatum->specified & AVTAB_AV) &&
|
||||
(avdatum->specified & AVTAB_TYPE)) {
|
||||
printk(KERN_ERR "security: avtab: entry has both access vectors and types\n");
|
||||
goto bad;
|
||||
}
|
||||
if (avdatum->specified & AVTAB_AV) {
|
||||
if (avdatum->specified & AVTAB_ALLOWED)
|
||||
avtab_allowed(avdatum) = le32_to_cpu(buf[items++]);
|
||||
if (avdatum->specified & AVTAB_AUDITDENY)
|
||||
avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]);
|
||||
if (avdatum->specified & AVTAB_AUDITALLOW)
|
||||
avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]);
|
||||
} else {
|
||||
if (avdatum->specified & AVTAB_TRANSITION)
|
||||
avtab_transition(avdatum) = le32_to_cpu(buf[items++]);
|
||||
if (avdatum->specified & AVTAB_CHANGE)
|
||||
avtab_change(avdatum) = le32_to_cpu(buf[items++]);
|
||||
if (avdatum->specified & AVTAB_MEMBER)
|
||||
avtab_member(avdatum) = le32_to_cpu(buf[items++]);
|
||||
}
|
||||
if (items != items2) {
|
||||
printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n",
|
||||
items2, items);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return 0;
|
||||
bad:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int avtab_read(struct avtab *a, void *fp, u32 config)
|
||||
{
|
||||
int i, rc = -EINVAL;
|
||||
struct avtab_key avkey;
|
||||
struct avtab_datum avdatum;
|
||||
u32 *buf;
|
||||
u32 nel;
|
||||
|
||||
|
||||
buf = next_entry(fp, sizeof(u32));
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: avtab: truncated table\n");
|
||||
goto bad;
|
||||
}
|
||||
nel = le32_to_cpu(buf[0]);
|
||||
if (!nel) {
|
||||
printk(KERN_ERR "security: avtab: table is empty\n");
|
||||
goto bad;
|
||||
}
|
||||
for (i = 0; i < nel; i++) {
|
||||
if (avtab_read_item(fp, &avdatum, &avkey))
|
||||
goto bad;
|
||||
rc = avtab_insert(a, &avkey, &avdatum);
|
||||
if (rc) {
|
||||
if (rc == -ENOMEM)
|
||||
printk(KERN_ERR "security: avtab: out of memory\n");
|
||||
if (rc == -EEXIST)
|
||||
printk(KERN_ERR "security: avtab: duplicate entry\n");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
|
||||
bad:
|
||||
avtab_destroy(a);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void avtab_cache_init(void)
|
||||
{
|
||||
avtab_node_cachep = kmem_cache_create("avtab_node",
|
||||
sizeof(struct avtab_node),
|
||||
0, SLAB_PANIC, NULL, NULL);
|
||||
}
|
||||
|
||||
void avtab_cache_destroy(void)
|
||||
{
|
||||
kmem_cache_destroy (avtab_node_cachep);
|
||||
}
|
||||
91
extra/linux-2.6.10/security/selinux/ss/avtab.h
Normal file
91
extra/linux-2.6.10/security/selinux/ss/avtab.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* An access vector table (avtab) is a hash table
|
||||
* of access vectors and transition types indexed
|
||||
* by a type pair and a class. An access vector
|
||||
* table is used to represent the type enforcement
|
||||
* tables.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
|
||||
/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
|
||||
*
|
||||
* Added conditional policy language extensions
|
||||
*
|
||||
* Copyright (C) 2003 Tresys Technology, LLC
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*/
|
||||
#ifndef _SS_AVTAB_H_
|
||||
#define _SS_AVTAB_H_
|
||||
|
||||
struct avtab_key {
|
||||
u32 source_type; /* source type */
|
||||
u32 target_type; /* target type */
|
||||
u32 target_class; /* target object class */
|
||||
};
|
||||
|
||||
struct avtab_datum {
|
||||
#define AVTAB_ALLOWED 1
|
||||
#define AVTAB_AUDITALLOW 2
|
||||
#define AVTAB_AUDITDENY 4
|
||||
#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
|
||||
#define AVTAB_TRANSITION 16
|
||||
#define AVTAB_MEMBER 32
|
||||
#define AVTAB_CHANGE 64
|
||||
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
|
||||
#define AVTAB_ENABLED 0x80000000 /* reserved for used in cond_avtab */
|
||||
u32 specified; /* what fields are specified */
|
||||
u32 data[3]; /* access vectors or types */
|
||||
#define avtab_allowed(x) (x)->data[0]
|
||||
#define avtab_auditdeny(x) (x)->data[1]
|
||||
#define avtab_auditallow(x) (x)->data[2]
|
||||
#define avtab_transition(x) (x)->data[0]
|
||||
#define avtab_change(x) (x)->data[1]
|
||||
#define avtab_member(x) (x)->data[2]
|
||||
};
|
||||
|
||||
struct avtab_node {
|
||||
struct avtab_key key;
|
||||
struct avtab_datum datum;
|
||||
struct avtab_node *next;
|
||||
};
|
||||
|
||||
struct avtab {
|
||||
struct avtab_node **htable;
|
||||
u32 nel; /* number of elements */
|
||||
};
|
||||
|
||||
int avtab_init(struct avtab *);
|
||||
int avtab_insert(struct avtab *h, struct avtab_key *k, struct avtab_datum *d);
|
||||
struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified);
|
||||
void avtab_destroy(struct avtab *h);
|
||||
int avtab_map(struct avtab *h,
|
||||
int (*apply) (struct avtab_key *k,
|
||||
struct avtab_datum *d,
|
||||
void *args),
|
||||
void *args);
|
||||
void avtab_hash_eval(struct avtab *h, char *tag);
|
||||
|
||||
int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey);
|
||||
int avtab_read(struct avtab *a, void *fp, u32 config);
|
||||
|
||||
struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
|
||||
struct avtab_datum *datum);
|
||||
|
||||
struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified);
|
||||
|
||||
struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
|
||||
|
||||
void avtab_cache_init(void);
|
||||
void avtab_cache_destroy(void);
|
||||
|
||||
#define AVTAB_HASH_BITS 15
|
||||
#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
|
||||
#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
|
||||
|
||||
#define AVTAB_SIZE AVTAB_HASH_BUCKETS
|
||||
|
||||
#endif /* _SS_AVTAB_H_ */
|
||||
|
||||
487
extra/linux-2.6.10/security/selinux/ss/conditional.c
Normal file
487
extra/linux-2.6.10/security/selinux/ss/conditional.c
Normal file
@@ -0,0 +1,487 @@
|
||||
/* Authors: Karl MacMillan <kmacmillan@tresys.com>
|
||||
* Frank Mayer <mayerf@tresys.com>
|
||||
*
|
||||
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "security.h"
|
||||
#include "conditional.h"
|
||||
|
||||
/*
|
||||
* cond_evaluate_expr evaluates a conditional expr
|
||||
* in reverse polish notation. It returns true (1), false (0),
|
||||
* or undefined (-1). Undefined occurs when the expression
|
||||
* exceeds the stack depth of COND_EXPR_MAXDEPTH.
|
||||
*/
|
||||
static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
|
||||
{
|
||||
|
||||
struct cond_expr *cur;
|
||||
int s[COND_EXPR_MAXDEPTH];
|
||||
int sp = -1;
|
||||
|
||||
for (cur = expr; cur != NULL; cur = cur->next) {
|
||||
switch (cur->expr_type) {
|
||||
case COND_BOOL:
|
||||
if (sp == (COND_EXPR_MAXDEPTH - 1))
|
||||
return -1;
|
||||
sp++;
|
||||
s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
|
||||
break;
|
||||
case COND_NOT:
|
||||
if (sp < 0)
|
||||
return -1;
|
||||
s[sp] = !s[sp];
|
||||
break;
|
||||
case COND_OR:
|
||||
if (sp < 1)
|
||||
return -1;
|
||||
sp--;
|
||||
s[sp] |= s[sp + 1];
|
||||
break;
|
||||
case COND_AND:
|
||||
if (sp < 1)
|
||||
return -1;
|
||||
sp--;
|
||||
s[sp] &= s[sp + 1];
|
||||
break;
|
||||
case COND_XOR:
|
||||
if (sp < 1)
|
||||
return -1;
|
||||
sp--;
|
||||
s[sp] ^= s[sp + 1];
|
||||
break;
|
||||
case COND_EQ:
|
||||
if (sp < 1)
|
||||
return -1;
|
||||
sp--;
|
||||
s[sp] = (s[sp] == s[sp + 1]);
|
||||
break;
|
||||
case COND_NEQ:
|
||||
if (sp < 1)
|
||||
return -1;
|
||||
sp--;
|
||||
s[sp] = (s[sp] != s[sp + 1]);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return s[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* evaluate_cond_node evaluates the conditional stored in
|
||||
* a struct cond_node and if the result is different than the
|
||||
* current state of the node it sets the rules in the true/false
|
||||
* list appropriately. If the result of the expression is undefined
|
||||
* all of the rules are disabled for safety.
|
||||
*/
|
||||
int evaluate_cond_node(struct policydb *p, struct cond_node *node)
|
||||
{
|
||||
int new_state;
|
||||
struct cond_av_list* cur;
|
||||
|
||||
new_state = cond_evaluate_expr(p, node->expr);
|
||||
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");
|
||||
/* turn the rules on or off */
|
||||
for (cur = node->true_list; cur != NULL; cur = cur->next) {
|
||||
if (new_state <= 0) {
|
||||
cur->node->datum.specified &= ~AVTAB_ENABLED;
|
||||
} else {
|
||||
cur->node->datum.specified |= AVTAB_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
for (cur = node->false_list; cur != NULL; cur = cur->next) {
|
||||
/* -1 or 1 */
|
||||
if (new_state) {
|
||||
cur->node->datum.specified &= ~AVTAB_ENABLED;
|
||||
} else {
|
||||
cur->node->datum.specified |= AVTAB_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cond_policydb_init(struct policydb *p)
|
||||
{
|
||||
p->bool_val_to_struct = NULL;
|
||||
p->cond_list = NULL;
|
||||
if (avtab_init(&p->te_cond_avtab))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cond_av_list_destroy(struct cond_av_list *list)
|
||||
{
|
||||
struct cond_av_list *cur, *next;
|
||||
for (cur = list; cur != NULL; cur = next) {
|
||||
next = cur->next;
|
||||
/* the avtab_ptr_t node is destroy by the avtab */
|
||||
kfree(cur);
|
||||
}
|
||||
}
|
||||
|
||||
static void cond_node_destroy(struct cond_node *node)
|
||||
{
|
||||
struct cond_expr *cur_expr, *next_expr;
|
||||
|
||||
for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) {
|
||||
next_expr = cur_expr->next;
|
||||
kfree(cur_expr);
|
||||
}
|
||||
cond_av_list_destroy(node->true_list);
|
||||
cond_av_list_destroy(node->false_list);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
static void cond_list_destroy(struct cond_node *list)
|
||||
{
|
||||
struct cond_node *next, *cur;
|
||||
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
for (cur = list; cur != NULL; cur = next) {
|
||||
next = cur->next;
|
||||
cond_node_destroy(cur);
|
||||
}
|
||||
}
|
||||
|
||||
void cond_policydb_destroy(struct policydb *p)
|
||||
{
|
||||
if (p->bool_val_to_struct != NULL)
|
||||
kfree(p->bool_val_to_struct);
|
||||
avtab_destroy(&p->te_cond_avtab);
|
||||
cond_list_destroy(p->cond_list);
|
||||
}
|
||||
|
||||
int cond_init_bool_indexes(struct policydb *p)
|
||||
{
|
||||
if (p->bool_val_to_struct)
|
||||
kfree(p->bool_val_to_struct);
|
||||
p->bool_val_to_struct = (struct cond_bool_datum**)
|
||||
kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
|
||||
if (!p->bool_val_to_struct)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cond_destroy_bool(void *key, void *datum, void *p)
|
||||
{
|
||||
if (key)
|
||||
kfree(key);
|
||||
kfree(datum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cond_index_bool(void *key, void *datum, void *datap)
|
||||
{
|
||||
struct policydb *p;
|
||||
struct cond_bool_datum *booldatum;
|
||||
|
||||
booldatum = datum;
|
||||
p = datap;
|
||||
|
||||
if (!booldatum->value || booldatum->value > p->p_bools.nprim)
|
||||
return -EINVAL;
|
||||
|
||||
p->p_bool_val_to_name[booldatum->value - 1] = key;
|
||||
p->bool_val_to_struct[booldatum->value -1] = booldatum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bool_isvalid(struct cond_bool_datum *b)
|
||||
{
|
||||
if (!(b->state == 0 || b->state == 1))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
|
||||
{
|
||||
char *key = NULL;
|
||||
struct cond_bool_datum *booldatum;
|
||||
__u32 *buf, len;
|
||||
|
||||
booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
|
||||
if (!booldatum)
|
||||
return -1;
|
||||
memset(booldatum, 0, sizeof(struct cond_bool_datum));
|
||||
|
||||
buf = next_entry(fp, sizeof(__u32) * 3);
|
||||
if (!buf)
|
||||
goto err;
|
||||
|
||||
booldatum->value = le32_to_cpu(buf[0]);
|
||||
booldatum->state = le32_to_cpu(buf[1]);
|
||||
|
||||
if (!bool_isvalid(booldatum))
|
||||
goto err;
|
||||
|
||||
len = le32_to_cpu(buf[2]);
|
||||
|
||||
buf = next_entry(fp, len);
|
||||
if (!buf)
|
||||
goto err;
|
||||
key = kmalloc(len + 1, GFP_KERNEL);
|
||||
if (!key)
|
||||
goto err;
|
||||
memcpy(key, buf, len);
|
||||
key[len] = 0;
|
||||
if (hashtab_insert(h, key, booldatum))
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
cond_destroy_bool(key, booldatum, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list,
|
||||
struct cond_av_list *other)
|
||||
{
|
||||
struct cond_av_list *list, *last = NULL, *cur;
|
||||
struct avtab_key key;
|
||||
struct avtab_datum datum;
|
||||
struct avtab_node *node_ptr;
|
||||
int len, i;
|
||||
__u32 *buf;
|
||||
__u8 found;
|
||||
|
||||
*ret_list = NULL;
|
||||
|
||||
len = 0;
|
||||
buf = next_entry(fp, sizeof(__u32));
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
len = le32_to_cpu(buf[0]);
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (avtab_read_item(fp, &datum, &key))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* For type rules we have to make certain there aren't any
|
||||
* conflicting rules by searching the te_avtab and the
|
||||
* cond_te_avtab.
|
||||
*/
|
||||
if (datum.specified & AVTAB_TYPE) {
|
||||
if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) {
|
||||
printk("security: type rule already exists outside of a conditional.");
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* If we are reading the false list other will be a pointer to
|
||||
* the true list. We can have duplicate entries if there is only
|
||||
* 1 other entry and it is in our true list.
|
||||
*
|
||||
* If we are reading the true list (other == NULL) there shouldn't
|
||||
* be any other entries.
|
||||
*/
|
||||
if (other) {
|
||||
node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE);
|
||||
if (node_ptr) {
|
||||
if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) {
|
||||
printk("security: too many conflicting type rules.");
|
||||
goto err;
|
||||
}
|
||||
found = 0;
|
||||
for (cur = other; cur != NULL; cur = cur->next) {
|
||||
if (cur->node == node_ptr) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
printk("security: conflicting type rules.");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) {
|
||||
printk("security: conflicting type rules when adding type rule for true.");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum);
|
||||
if (!node_ptr) {
|
||||
printk("security: could not insert rule.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
|
||||
if (!list)
|
||||
goto err;
|
||||
memset(list, 0, sizeof(struct cond_av_list));
|
||||
|
||||
list->node = node_ptr;
|
||||
if (i == 0)
|
||||
*ret_list = list;
|
||||
else
|
||||
last->next = list;
|
||||
last = list;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
cond_av_list_destroy(*ret_list);
|
||||
*ret_list = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (expr->bool > p->p_bools.nprim) {
|
||||
printk("security: conditional expressions uses unknown bool.\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
|
||||
{
|
||||
__u32 *buf;
|
||||
int len, i;
|
||||
struct cond_expr *expr = NULL, *last = NULL;
|
||||
|
||||
buf = next_entry(fp, sizeof(__u32));
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
node->cur_state = le32_to_cpu(buf[0]);
|
||||
|
||||
len = 0;
|
||||
buf = next_entry(fp, sizeof(__u32));
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
/* expr */
|
||||
len = le32_to_cpu(buf[0]);
|
||||
|
||||
for (i = 0; i < len; i++ ) {
|
||||
buf = next_entry(fp, sizeof(__u32) * 2);
|
||||
if (!buf)
|
||||
goto err;
|
||||
|
||||
expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
|
||||
if (!expr) {
|
||||
goto err;
|
||||
}
|
||||
memset(expr, 0, sizeof(struct cond_expr));
|
||||
|
||||
expr->expr_type = le32_to_cpu(buf[0]);
|
||||
expr->bool = le32_to_cpu(buf[1]);
|
||||
|
||||
if (!expr_isvalid(p, expr))
|
||||
goto err;
|
||||
|
||||
if (i == 0) {
|
||||
node->expr = expr;
|
||||
} else {
|
||||
last->next = expr;
|
||||
}
|
||||
last = expr;
|
||||
}
|
||||
|
||||
if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
|
||||
goto err;
|
||||
if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0)
|
||||
goto err;
|
||||
return 0;
|
||||
err:
|
||||
cond_node_destroy(node);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cond_read_list(struct policydb *p, void *fp)
|
||||
{
|
||||
struct cond_node *node, *last = NULL;
|
||||
__u32 *buf;
|
||||
int i, len;
|
||||
|
||||
buf = next_entry(fp, sizeof(__u32));
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
len = le32_to_cpu(buf[0]);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
node = kmalloc(sizeof(struct cond_node), GFP_KERNEL);
|
||||
if (!node)
|
||||
goto err;
|
||||
memset(node, 0, sizeof(struct cond_node));
|
||||
|
||||
if (cond_read_node(p, node, fp) != 0)
|
||||
goto err;
|
||||
|
||||
if (i == 0) {
|
||||
p->cond_list = node;
|
||||
} else {
|
||||
last->next = node;
|
||||
}
|
||||
last = node;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
cond_list_destroy(p->cond_list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Determine whether additional permissions are granted by the conditional
|
||||
* av table, and if so, add them to the result
|
||||
*/
|
||||
void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd)
|
||||
{
|
||||
struct avtab_node *node;
|
||||
|
||||
if(!ctab || !key || !avd)
|
||||
return;
|
||||
|
||||
for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL;
|
||||
node = avtab_search_node_next(node, AVTAB_AV)) {
|
||||
if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
|
||||
(node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
|
||||
avd->allowed |= avtab_allowed(&node->datum);
|
||||
if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
|
||||
(node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
|
||||
/* Since a '0' in an auditdeny mask represents a
|
||||
* permission we do NOT want to audit (dontaudit), we use
|
||||
* the '&' operand to ensure that all '0's in the mask
|
||||
* are retained (much unlike the allow and auditallow cases).
|
||||
*/
|
||||
avd->auditdeny &= avtab_auditdeny(&node->datum);
|
||||
if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
|
||||
(node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
|
||||
avd->auditallow |= avtab_auditallow(&node->datum);
|
||||
}
|
||||
return;
|
||||
}
|
||||
77
extra/linux-2.6.10/security/selinux/ss/conditional.h
Normal file
77
extra/linux-2.6.10/security/selinux/ss/conditional.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* Authors: Karl MacMillan <kmacmillan@tresys.com>
|
||||
* Frank Mayer <mayerf@tresys.com>
|
||||
*
|
||||
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CONDITIONAL_H_
|
||||
#define _CONDITIONAL_H_
|
||||
|
||||
#include "avtab.h"
|
||||
#include "symtab.h"
|
||||
#include "policydb.h"
|
||||
|
||||
#define COND_EXPR_MAXDEPTH 10
|
||||
|
||||
/*
|
||||
* A conditional expression is a list of operators and operands
|
||||
* in reverse polish notation.
|
||||
*/
|
||||
struct cond_expr {
|
||||
#define COND_BOOL 1 /* plain bool */
|
||||
#define COND_NOT 2 /* !bool */
|
||||
#define COND_OR 3 /* bool || bool */
|
||||
#define COND_AND 4 /* bool && bool */
|
||||
#define COND_XOR 5 /* bool ^ bool */
|
||||
#define COND_EQ 6 /* bool == bool */
|
||||
#define COND_NEQ 7 /* bool != bool */
|
||||
#define COND_LAST 8
|
||||
__u32 expr_type;
|
||||
__u32 bool;
|
||||
struct cond_expr *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* Each cond_node contains a list of rules to be enabled/disabled
|
||||
* depending on the current value of the conditional expression. This
|
||||
* struct is for that list.
|
||||
*/
|
||||
struct cond_av_list {
|
||||
struct avtab_node *node;
|
||||
struct cond_av_list *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* A cond node represents a conditional block in a policy. It
|
||||
* contains a conditional expression, the current state of the expression,
|
||||
* two lists of rules to enable/disable depending on the value of the
|
||||
* expression (the true list corresponds to if and the false list corresponds
|
||||
* to else)..
|
||||
*/
|
||||
struct cond_node {
|
||||
int cur_state;
|
||||
struct cond_expr *expr;
|
||||
struct cond_av_list *true_list;
|
||||
struct cond_av_list *false_list;
|
||||
struct cond_node *next;
|
||||
};
|
||||
|
||||
int cond_policydb_init(struct policydb* p);
|
||||
void cond_policydb_destroy(struct policydb* p);
|
||||
|
||||
int cond_init_bool_indexes(struct policydb* p);
|
||||
int cond_destroy_bool(void *key, void *datum, void *p);
|
||||
|
||||
int cond_index_bool(void *key, void *datum, void *datap);
|
||||
|
||||
int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
|
||||
int cond_read_list(struct policydb *p, void *fp);
|
||||
|
||||
void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
|
||||
|
||||
int evaluate_cond_node(struct policydb *p, struct cond_node *node);
|
||||
|
||||
#endif /* _CONDITIONAL_H_ */
|
||||
54
extra/linux-2.6.10/security/selinux/ss/constraint.h
Normal file
54
extra/linux-2.6.10/security/selinux/ss/constraint.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* A constraint is a condition that must be satisfied in
|
||||
* order for one or more permissions to be granted.
|
||||
* Constraints are used to impose additional restrictions
|
||||
* beyond the type-based rules in `te' or the role-based
|
||||
* transition rules in `rbac'. Constraints are typically
|
||||
* used to prevent a process from transitioning to a new user
|
||||
* identity or role unless it is in a privileged type.
|
||||
* Constraints are likewise typically used to prevent a
|
||||
* process from labeling an object with a different user
|
||||
* identity.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_CONSTRAINT_H_
|
||||
#define _SS_CONSTRAINT_H_
|
||||
|
||||
#include "ebitmap.h"
|
||||
|
||||
#define CEXPR_MAXDEPTH 5
|
||||
|
||||
struct constraint_expr {
|
||||
#define CEXPR_NOT 1 /* not expr */
|
||||
#define CEXPR_AND 2 /* expr and expr */
|
||||
#define CEXPR_OR 3 /* expr or expr */
|
||||
#define CEXPR_ATTR 4 /* attr op attr */
|
||||
#define CEXPR_NAMES 5 /* attr op names */
|
||||
u32 expr_type; /* expression type */
|
||||
|
||||
#define CEXPR_USER 1 /* user */
|
||||
#define CEXPR_ROLE 2 /* role */
|
||||
#define CEXPR_TYPE 4 /* type */
|
||||
#define CEXPR_TARGET 8 /* target if set, source otherwise */
|
||||
u32 attr; /* attribute */
|
||||
|
||||
#define CEXPR_EQ 1 /* == or eq */
|
||||
#define CEXPR_NEQ 2 /* != */
|
||||
#define CEXPR_DOM 3 /* dom */
|
||||
#define CEXPR_DOMBY 4 /* domby */
|
||||
#define CEXPR_INCOMP 5 /* incomp */
|
||||
u32 op; /* operator */
|
||||
|
||||
struct ebitmap names; /* names */
|
||||
|
||||
struct constraint_expr *next; /* next expression */
|
||||
};
|
||||
|
||||
struct constraint_node {
|
||||
u32 permissions; /* constrained permissions */
|
||||
struct constraint_expr *expr; /* constraint on permissions */
|
||||
struct constraint_node *next; /* next constraint */
|
||||
};
|
||||
|
||||
#endif /* _SS_CONSTRAINT_H_ */
|
||||
117
extra/linux-2.6.10/security/selinux/ss/context.h
Normal file
117
extra/linux-2.6.10/security/selinux/ss/context.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* A security context is a set of security attributes
|
||||
* associated with each subject and object controlled
|
||||
* by the security policy. Security contexts are
|
||||
* externally represented as variable-length strings
|
||||
* that can be interpreted by a user or application
|
||||
* with an understanding of the security policy.
|
||||
* Internally, the security server uses a simple
|
||||
* structure. This structure is private to the
|
||||
* security server and can be changed without affecting
|
||||
* clients of the security server.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_CONTEXT_H_
|
||||
#define _SS_CONTEXT_H_
|
||||
|
||||
#include "ebitmap.h"
|
||||
#include "mls_types.h"
|
||||
|
||||
/*
|
||||
* A security context consists of an authenticated user
|
||||
* identity, a role, a type and a MLS range.
|
||||
*/
|
||||
struct context {
|
||||
u32 user;
|
||||
u32 role;
|
||||
u32 type;
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
struct mls_range range;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
|
||||
static inline void mls_context_init(struct context *c)
|
||||
{
|
||||
memset(&c->range, 0, sizeof(c->range));
|
||||
}
|
||||
|
||||
static inline int mls_context_cpy(struct context *dst, struct context *src)
|
||||
{
|
||||
int rc;
|
||||
|
||||
dst->range.level[0].sens = src->range.level[0].sens;
|
||||
rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
dst->range.level[1].sens = src->range.level[1].sens;
|
||||
rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
|
||||
if (rc)
|
||||
ebitmap_destroy(&dst->range.level[0].cat);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int mls_context_cmp(struct context *c1, struct context *c2)
|
||||
{
|
||||
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
|
||||
ebitmap_cmp(&c1->range.level[0].cat,&c2->range.level[0].cat) &&
|
||||
(c1->range.level[1].sens == c2->range.level[1].sens) &&
|
||||
ebitmap_cmp(&c1->range.level[1].cat,&c2->range.level[1].cat));
|
||||
}
|
||||
|
||||
static inline void mls_context_destroy(struct context *c)
|
||||
{
|
||||
ebitmap_destroy(&c->range.level[0].cat);
|
||||
ebitmap_destroy(&c->range.level[1].cat);
|
||||
mls_context_init(c);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void mls_context_init(struct context *c)
|
||||
{ }
|
||||
|
||||
static inline int mls_context_cpy(struct context *dst, struct context *src)
|
||||
{ return 0; }
|
||||
|
||||
static inline int mls_context_cmp(struct context *c1, struct context *c2)
|
||||
{ return 1; }
|
||||
|
||||
static inline void mls_context_destroy(struct context *c)
|
||||
{ }
|
||||
|
||||
#endif
|
||||
|
||||
static inline void context_init(struct context *c)
|
||||
{
|
||||
memset(c, 0, sizeof(*c));
|
||||
}
|
||||
|
||||
static inline int context_cpy(struct context *dst, struct context *src)
|
||||
{
|
||||
dst->user = src->user;
|
||||
dst->role = src->role;
|
||||
dst->type = src->type;
|
||||
return mls_context_cpy(dst, src);
|
||||
}
|
||||
|
||||
static inline void context_destroy(struct context *c)
|
||||
{
|
||||
c->user = c->role = c->type = 0;
|
||||
mls_context_destroy(c);
|
||||
}
|
||||
|
||||
static inline int context_cmp(struct context *c1, struct context *c2)
|
||||
{
|
||||
return ((c1->user == c2->user) &&
|
||||
(c1->role == c2->role) &&
|
||||
(c1->type == c2->type) &&
|
||||
mls_context_cmp(c1, c2));
|
||||
}
|
||||
|
||||
#endif /* _SS_CONTEXT_H_ */
|
||||
|
||||
335
extra/linux-2.6.10/security/selinux/ss/ebitmap.c
Normal file
335
extra/linux-2.6.10/security/selinux/ss/ebitmap.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Implementation of the extensible bitmap type.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include "ebitmap.h"
|
||||
#include "policydb.h"
|
||||
|
||||
int ebitmap_or(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2)
|
||||
{
|
||||
struct ebitmap_node *n1, *n2, *new, *prev;
|
||||
|
||||
ebitmap_init(dst);
|
||||
|
||||
n1 = e1->node;
|
||||
n2 = e2->node;
|
||||
prev = NULL;
|
||||
while (n1 || n2) {
|
||||
new = kmalloc(sizeof(*new), GFP_ATOMIC);
|
||||
if (!new) {
|
||||
ebitmap_destroy(dst);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(new, 0, sizeof(*new));
|
||||
if (n1 && n2 && n1->startbit == n2->startbit) {
|
||||
new->startbit = n1->startbit;
|
||||
new->map = n1->map | n2->map;
|
||||
n1 = n1->next;
|
||||
n2 = n2->next;
|
||||
} else if (!n2 || (n1 && n1->startbit < n2->startbit)) {
|
||||
new->startbit = n1->startbit;
|
||||
new->map = n1->map;
|
||||
n1 = n1->next;
|
||||
} else {
|
||||
new->startbit = n2->startbit;
|
||||
new->map = n2->map;
|
||||
n2 = n2->next;
|
||||
}
|
||||
|
||||
new->next = NULL;
|
||||
if (prev)
|
||||
prev->next = new;
|
||||
else
|
||||
dst->node = new;
|
||||
prev = new;
|
||||
}
|
||||
|
||||
dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
|
||||
{
|
||||
struct ebitmap_node *n1, *n2;
|
||||
|
||||
if (e1->highbit != e2->highbit)
|
||||
return 0;
|
||||
|
||||
n1 = e1->node;
|
||||
n2 = e2->node;
|
||||
while (n1 && n2 &&
|
||||
(n1->startbit == n2->startbit) &&
|
||||
(n1->map == n2->map)) {
|
||||
n1 = n1->next;
|
||||
n2 = n2->next;
|
||||
}
|
||||
|
||||
if (n1 || n2)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
|
||||
{
|
||||
struct ebitmap_node *n, *new, *prev;
|
||||
|
||||
ebitmap_init(dst);
|
||||
n = src->node;
|
||||
prev = NULL;
|
||||
while (n) {
|
||||
new = kmalloc(sizeof(*new), GFP_ATOMIC);
|
||||
if (!new) {
|
||||
ebitmap_destroy(dst);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(new, 0, sizeof(*new));
|
||||
new->startbit = n->startbit;
|
||||
new->map = n->map;
|
||||
new->next = NULL;
|
||||
if (prev)
|
||||
prev->next = new;
|
||||
else
|
||||
dst->node = new;
|
||||
prev = new;
|
||||
n = n->next;
|
||||
}
|
||||
|
||||
dst->highbit = src->highbit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
|
||||
{
|
||||
struct ebitmap_node *n1, *n2;
|
||||
|
||||
if (e1->highbit < e2->highbit)
|
||||
return 0;
|
||||
|
||||
n1 = e1->node;
|
||||
n2 = e2->node;
|
||||
while (n1 && n2 && (n1->startbit <= n2->startbit)) {
|
||||
if (n1->startbit < n2->startbit) {
|
||||
n1 = n1->next;
|
||||
continue;
|
||||
}
|
||||
if ((n1->map & n2->map) != n2->map)
|
||||
return 0;
|
||||
|
||||
n1 = n1->next;
|
||||
n2 = n2->next;
|
||||
}
|
||||
|
||||
if (n2)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
|
||||
{
|
||||
struct ebitmap_node *n;
|
||||
|
||||
if (e->highbit < bit)
|
||||
return 0;
|
||||
|
||||
n = e->node;
|
||||
while (n && (n->startbit <= bit)) {
|
||||
if ((n->startbit + MAPSIZE) > bit) {
|
||||
if (n->map & (MAPBIT << (bit - n->startbit)))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
n = n->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
|
||||
{
|
||||
struct ebitmap_node *n, *prev, *new;
|
||||
|
||||
prev = NULL;
|
||||
n = e->node;
|
||||
while (n && n->startbit <= bit) {
|
||||
if ((n->startbit + MAPSIZE) > bit) {
|
||||
if (value) {
|
||||
n->map |= (MAPBIT << (bit - n->startbit));
|
||||
} else {
|
||||
n->map &= ~(MAPBIT << (bit - n->startbit));
|
||||
if (!n->map) {
|
||||
/* drop this node from the bitmap */
|
||||
|
||||
if (!n->next) {
|
||||
/*
|
||||
* this was the highest map
|
||||
* within the bitmap
|
||||
*/
|
||||
if (prev)
|
||||
e->highbit = prev->startbit + MAPSIZE;
|
||||
else
|
||||
e->highbit = 0;
|
||||
}
|
||||
if (prev)
|
||||
prev->next = n->next;
|
||||
else
|
||||
e->node = n->next;
|
||||
|
||||
kfree(n);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
prev = n;
|
||||
n = n->next;
|
||||
}
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
new = kmalloc(sizeof(*new), GFP_ATOMIC);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
memset(new, 0, sizeof(*new));
|
||||
|
||||
new->startbit = bit & ~(MAPSIZE - 1);
|
||||
new->map = (MAPBIT << (bit - new->startbit));
|
||||
|
||||
if (!n)
|
||||
/* this node will be the highest map within the bitmap */
|
||||
e->highbit = new->startbit + MAPSIZE;
|
||||
|
||||
if (prev) {
|
||||
new->next = prev->next;
|
||||
prev->next = new;
|
||||
} else {
|
||||
new->next = e->node;
|
||||
e->node = new;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ebitmap_destroy(struct ebitmap *e)
|
||||
{
|
||||
struct ebitmap_node *n, *temp;
|
||||
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
n = e->node;
|
||||
while (n) {
|
||||
temp = n;
|
||||
n = n->next;
|
||||
kfree(temp);
|
||||
}
|
||||
|
||||
e->highbit = 0;
|
||||
e->node = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
int ebitmap_read(struct ebitmap *e, void *fp)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
struct ebitmap_node *n, *l;
|
||||
u32 *buf, mapsize, count, i;
|
||||
u64 map;
|
||||
|
||||
ebitmap_init(e);
|
||||
|
||||
buf = next_entry(fp, sizeof(u32)*3);
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
mapsize = le32_to_cpu(buf[0]);
|
||||
e->highbit = le32_to_cpu(buf[1]);
|
||||
count = le32_to_cpu(buf[2]);
|
||||
|
||||
if (mapsize != MAPSIZE) {
|
||||
printk(KERN_ERR "security: ebitmap: map size %u does not "
|
||||
"match my size %Zd (high bit was %d)\n", mapsize,
|
||||
MAPSIZE, e->highbit);
|
||||
goto out;
|
||||
}
|
||||
if (!e->highbit) {
|
||||
e->node = NULL;
|
||||
goto ok;
|
||||
}
|
||||
if (e->highbit & (MAPSIZE - 1)) {
|
||||
printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
|
||||
"multiple of the map size (%Zd)\n", e->highbit, MAPSIZE);
|
||||
goto bad;
|
||||
}
|
||||
l = NULL;
|
||||
for (i = 0; i < count; i++) {
|
||||
buf = next_entry(fp, sizeof(u32));
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: ebitmap: truncated map\n");
|
||||
goto bad;
|
||||
}
|
||||
n = kmalloc(sizeof(*n), GFP_KERNEL);
|
||||
if (!n) {
|
||||
printk(KERN_ERR "security: ebitmap: out of memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
memset(n, 0, sizeof(*n));
|
||||
|
||||
n->startbit = le32_to_cpu(buf[0]);
|
||||
|
||||
if (n->startbit & (MAPSIZE - 1)) {
|
||||
printk(KERN_ERR "security: ebitmap start bit (%d) is "
|
||||
"not a multiple of the map size (%Zd)\n",
|
||||
n->startbit, MAPSIZE);
|
||||
goto bad_free;
|
||||
}
|
||||
if (n->startbit > (e->highbit - MAPSIZE)) {
|
||||
printk(KERN_ERR "security: ebitmap start bit (%d) is "
|
||||
"beyond the end of the bitmap (%Zd)\n",
|
||||
n->startbit, (e->highbit - MAPSIZE));
|
||||
goto bad_free;
|
||||
}
|
||||
buf = next_entry(fp, sizeof(u64));
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: ebitmap: truncated map\n");
|
||||
goto bad_free;
|
||||
}
|
||||
memcpy(&map, buf, sizeof(u64));
|
||||
n->map = le64_to_cpu(map);
|
||||
|
||||
if (!n->map) {
|
||||
printk(KERN_ERR "security: ebitmap: null map in "
|
||||
"ebitmap (startbit %d)\n", n->startbit);
|
||||
goto bad_free;
|
||||
}
|
||||
if (l) {
|
||||
if (n->startbit <= l->startbit) {
|
||||
printk(KERN_ERR "security: ebitmap: start "
|
||||
"bit %d comes after start bit %d\n",
|
||||
n->startbit, l->startbit);
|
||||
goto bad_free;
|
||||
}
|
||||
l->next = n;
|
||||
} else
|
||||
e->node = n;
|
||||
|
||||
l = n;
|
||||
}
|
||||
|
||||
ok:
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
bad_free:
|
||||
kfree(n);
|
||||
bad:
|
||||
ebitmap_destroy(e);
|
||||
goto out;
|
||||
}
|
||||
49
extra/linux-2.6.10/security/selinux/ss/ebitmap.h
Normal file
49
extra/linux-2.6.10/security/selinux/ss/ebitmap.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* An extensible bitmap is a bitmap that supports an
|
||||
* arbitrary number of bits. Extensible bitmaps are
|
||||
* used to represent sets of values, such as types,
|
||||
* roles, categories, and classes.
|
||||
*
|
||||
* Each extensible bitmap is implemented as a linked
|
||||
* list of bitmap nodes, where each bitmap node has
|
||||
* an explicitly specified starting bit position within
|
||||
* the total bitmap.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_EBITMAP_H_
|
||||
#define _SS_EBITMAP_H_
|
||||
|
||||
#define MAPTYPE u64 /* portion of bitmap in each node */
|
||||
#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */
|
||||
#define MAPBIT 1ULL /* a bit in the node bitmap */
|
||||
|
||||
struct ebitmap_node {
|
||||
u32 startbit; /* starting position in the total bitmap */
|
||||
MAPTYPE map; /* this node's portion of the bitmap */
|
||||
struct ebitmap_node *next;
|
||||
};
|
||||
|
||||
struct ebitmap {
|
||||
struct ebitmap_node *node; /* first node in the bitmap */
|
||||
u32 highbit; /* highest position in the total bitmap */
|
||||
};
|
||||
|
||||
#define ebitmap_length(e) ((e)->highbit)
|
||||
#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
|
||||
|
||||
static inline void ebitmap_init(struct ebitmap *e)
|
||||
{
|
||||
memset(e, 0, sizeof(*e));
|
||||
}
|
||||
|
||||
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
|
||||
int ebitmap_or(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2);
|
||||
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
|
||||
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
|
||||
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
|
||||
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
|
||||
void ebitmap_destroy(struct ebitmap *e);
|
||||
int ebitmap_read(struct ebitmap *e, void *fp);
|
||||
|
||||
#endif /* _SS_EBITMAP_H_ */
|
||||
280
extra/linux-2.6.10/security/selinux/ss/hashtab.c
Normal file
280
extra/linux-2.6.10/security/selinux/ss/hashtab.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Implementation of the hash table type.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include "hashtab.h"
|
||||
|
||||
struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
|
||||
int (*keycmp)(struct hashtab *h, void *key1, void *key2),
|
||||
u32 size)
|
||||
{
|
||||
struct hashtab *p;
|
||||
u32 i;
|
||||
|
||||
p = kmalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (p == NULL)
|
||||
return p;
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->size = size;
|
||||
p->nel = 0;
|
||||
p->hash_value = hash_value;
|
||||
p->keycmp = keycmp;
|
||||
p->htable = kmalloc(sizeof(*(p->htable)) * size, GFP_KERNEL);
|
||||
if (p->htable == NULL) {
|
||||
kfree(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
p->htable[i] = NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int hashtab_insert(struct hashtab *h, void *key, void *datum)
|
||||
{
|
||||
u32 hvalue;
|
||||
struct hashtab_node *prev, *cur, *newnode;
|
||||
|
||||
if (!h || h->nel == HASHTAB_MAX_NODES)
|
||||
return -EINVAL;
|
||||
|
||||
hvalue = h->hash_value(h, key);
|
||||
prev = NULL;
|
||||
cur = h->htable[hvalue];
|
||||
while (cur && h->keycmp(h, key, cur->key) > 0) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (cur && (h->keycmp(h, key, cur->key) == 0))
|
||||
return -EEXIST;
|
||||
|
||||
newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
|
||||
if (newnode == NULL)
|
||||
return -ENOMEM;
|
||||
memset(newnode, 0, sizeof(*newnode));
|
||||
newnode->key = key;
|
||||
newnode->datum = datum;
|
||||
if (prev) {
|
||||
newnode->next = prev->next;
|
||||
prev->next = newnode;
|
||||
} else {
|
||||
newnode->next = h->htable[hvalue];
|
||||
h->htable[hvalue] = newnode;
|
||||
}
|
||||
|
||||
h->nel++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hashtab_remove(struct hashtab *h, void *key,
|
||||
void (*destroy)(void *k, void *d, void *args),
|
||||
void *args)
|
||||
{
|
||||
u32 hvalue;
|
||||
struct hashtab_node *cur, *last;
|
||||
|
||||
if (!h)
|
||||
return -EINVAL;
|
||||
|
||||
hvalue = h->hash_value(h, key);
|
||||
last = NULL;
|
||||
cur = h->htable[hvalue];
|
||||
while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
|
||||
last = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
|
||||
return -ENOENT;
|
||||
|
||||
if (last == NULL)
|
||||
h->htable[hvalue] = cur->next;
|
||||
else
|
||||
last->next = cur->next;
|
||||
|
||||
if (destroy)
|
||||
destroy(cur->key, cur->datum, args);
|
||||
kfree(cur);
|
||||
h->nel--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hashtab_replace(struct hashtab *h, void *key, void *datum,
|
||||
void (*destroy)(void *k, void *d, void *args),
|
||||
void *args)
|
||||
{
|
||||
u32 hvalue;
|
||||
struct hashtab_node *prev, *cur, *newnode;
|
||||
|
||||
if (!h)
|
||||
return -EINVAL;
|
||||
|
||||
hvalue = h->hash_value(h, key);
|
||||
prev = NULL;
|
||||
cur = h->htable[hvalue];
|
||||
while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (cur && (h->keycmp(h, key, cur->key) == 0)) {
|
||||
if (destroy)
|
||||
destroy(cur->key, cur->datum, args);
|
||||
cur->key = key;
|
||||
cur->datum = datum;
|
||||
} else {
|
||||
newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
|
||||
if (newnode == NULL)
|
||||
return -ENOMEM;
|
||||
memset(newnode, 0, sizeof(*newnode));
|
||||
newnode->key = key;
|
||||
newnode->datum = datum;
|
||||
if (prev) {
|
||||
newnode->next = prev->next;
|
||||
prev->next = newnode;
|
||||
} else {
|
||||
newnode->next = h->htable[hvalue];
|
||||
h->htable[hvalue] = newnode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *hashtab_search(struct hashtab *h, void *key)
|
||||
{
|
||||
u32 hvalue;
|
||||
struct hashtab_node *cur;
|
||||
|
||||
if (!h)
|
||||
return NULL;
|
||||
|
||||
hvalue = h->hash_value(h, key);
|
||||
cur = h->htable[hvalue];
|
||||
while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
|
||||
cur = cur->next;
|
||||
|
||||
if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
|
||||
return NULL;
|
||||
|
||||
return cur->datum;
|
||||
}
|
||||
|
||||
void hashtab_destroy(struct hashtab *h)
|
||||
{
|
||||
u32 i;
|
||||
struct hashtab_node *cur, *temp;
|
||||
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
for (i = 0; i < h->size; i++) {
|
||||
cur = h->htable[i];
|
||||
while (cur != NULL) {
|
||||
temp = cur;
|
||||
cur = cur->next;
|
||||
kfree(temp);
|
||||
}
|
||||
h->htable[i] = NULL;
|
||||
}
|
||||
|
||||
kfree(h->htable);
|
||||
h->htable = NULL;
|
||||
|
||||
kfree(h);
|
||||
}
|
||||
|
||||
int hashtab_map(struct hashtab *h,
|
||||
int (*apply)(void *k, void *d, void *args),
|
||||
void *args)
|
||||
{
|
||||
u32 i;
|
||||
int ret;
|
||||
struct hashtab_node *cur;
|
||||
|
||||
if (!h)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < h->size; i++) {
|
||||
cur = h->htable[i];
|
||||
while (cur != NULL) {
|
||||
ret = apply(cur->key, cur->datum, args);
|
||||
if (ret)
|
||||
return ret;
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hashtab_map_remove_on_error(struct hashtab *h,
|
||||
int (*apply)(void *k, void *d, void *args),
|
||||
void (*destroy)(void *k, void *d, void *args),
|
||||
void *args)
|
||||
{
|
||||
u32 i;
|
||||
int ret;
|
||||
struct hashtab_node *last, *cur, *temp;
|
||||
|
||||
if (!h)
|
||||
return;
|
||||
|
||||
for (i = 0; i < h->size; i++) {
|
||||
last = NULL;
|
||||
cur = h->htable[i];
|
||||
while (cur != NULL) {
|
||||
ret = apply(cur->key, cur->datum, args);
|
||||
if (ret) {
|
||||
if (last)
|
||||
last->next = cur->next;
|
||||
else
|
||||
h->htable[i] = cur->next;
|
||||
|
||||
temp = cur;
|
||||
cur = cur->next;
|
||||
if (destroy)
|
||||
destroy(temp->key, temp->datum, args);
|
||||
kfree(temp);
|
||||
h->nel--;
|
||||
} else {
|
||||
last = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
|
||||
{
|
||||
u32 i, chain_len, slots_used, max_chain_len;
|
||||
struct hashtab_node *cur;
|
||||
|
||||
slots_used = 0;
|
||||
max_chain_len = 0;
|
||||
for (slots_used = max_chain_len = i = 0; i < h->size; i++) {
|
||||
cur = h->htable[i];
|
||||
if (cur) {
|
||||
slots_used++;
|
||||
chain_len = 0;
|
||||
while (cur) {
|
||||
chain_len++;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (chain_len > max_chain_len)
|
||||
max_chain_len = chain_len;
|
||||
}
|
||||
}
|
||||
|
||||
info->slots_used = slots_used;
|
||||
info->max_chain_len = max_chain_len;
|
||||
}
|
||||
125
extra/linux-2.6.10/security/selinux/ss/hashtab.h
Normal file
125
extra/linux-2.6.10/security/selinux/ss/hashtab.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* A hash table (hashtab) maintains associations between
|
||||
* key values and datum values. The type of the key values
|
||||
* and the type of the datum values is arbitrary. The
|
||||
* functions for hash computation and key comparison are
|
||||
* provided by the creator of the table.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_HASHTAB_H_
|
||||
#define _SS_HASHTAB_H_
|
||||
|
||||
#define HASHTAB_MAX_NODES 0xffffffff
|
||||
|
||||
struct hashtab_node {
|
||||
void *key;
|
||||
void *datum;
|
||||
struct hashtab_node *next;
|
||||
};
|
||||
|
||||
struct hashtab {
|
||||
struct hashtab_node **htable; /* hash table */
|
||||
u32 size; /* number of slots in hash table */
|
||||
u32 nel; /* number of elements in hash table */
|
||||
u32 (*hash_value)(struct hashtab *h, void *key);
|
||||
/* hash function */
|
||||
int (*keycmp)(struct hashtab *h, void *key1, void *key2);
|
||||
/* key comparison function */
|
||||
};
|
||||
|
||||
struct hashtab_info {
|
||||
u32 slots_used;
|
||||
u32 max_chain_len;
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a new hash table with the specified characteristics.
|
||||
*
|
||||
* Returns NULL if insufficent space is available or
|
||||
* the new hash table otherwise.
|
||||
*/
|
||||
struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
|
||||
int (*keycmp)(struct hashtab *h, void *key1, void *key2),
|
||||
u32 size);
|
||||
|
||||
/*
|
||||
* Inserts the specified (key, datum) pair into the specified hash table.
|
||||
*
|
||||
* Returns -ENOMEM on memory allocation error,
|
||||
* -EEXIST if there is already an entry with the same key,
|
||||
* -EINVAL for general errors or
|
||||
* 0 otherwise.
|
||||
*/
|
||||
int hashtab_insert(struct hashtab *h, void *k, void *d);
|
||||
|
||||
/*
|
||||
* Removes the entry with the specified key from the hash table.
|
||||
* Applies the specified destroy function to (key,datum,args) for
|
||||
* the entry.
|
||||
*
|
||||
* Returns -ENOENT if no entry has the specified key,
|
||||
* -EINVAL for general errors or
|
||||
*0 otherwise.
|
||||
*/
|
||||
int hashtab_remove(struct hashtab *h, void *k,
|
||||
void (*destroy)(void *k, void *d, void *args),
|
||||
void *args);
|
||||
|
||||
/*
|
||||
* Insert or replace the specified (key, datum) pair in the specified
|
||||
* hash table. If an entry for the specified key already exists,
|
||||
* then the specified destroy function is applied to (key,datum,args)
|
||||
* for the entry prior to replacing the entry's contents.
|
||||
*
|
||||
* Returns -ENOMEM if insufficient space is available,
|
||||
* -EINVAL for general errors or
|
||||
* 0 otherwise.
|
||||
*/
|
||||
int hashtab_replace(struct hashtab *h, void *k, void *d,
|
||||
void (*destroy)(void *k, void *d, void *args),
|
||||
void *args);
|
||||
|
||||
/*
|
||||
* Searches for the entry with the specified key in the hash table.
|
||||
*
|
||||
* Returns NULL if no entry has the specified key or
|
||||
* the datum of the entry otherwise.
|
||||
*/
|
||||
void *hashtab_search(struct hashtab *h, void *k);
|
||||
|
||||
/*
|
||||
* Destroys the specified hash table.
|
||||
*/
|
||||
void hashtab_destroy(struct hashtab *h);
|
||||
|
||||
/*
|
||||
* Applies the specified apply function to (key,datum,args)
|
||||
* for each entry in the specified hash table.
|
||||
*
|
||||
* The order in which the function is applied to the entries
|
||||
* is dependent upon the internal structure of the hash table.
|
||||
*
|
||||
* If apply returns a non-zero status, then hashtab_map will cease
|
||||
* iterating through the hash table and will propagate the error
|
||||
* return to its caller.
|
||||
*/
|
||||
int hashtab_map(struct hashtab *h,
|
||||
int (*apply)(void *k, void *d, void *args),
|
||||
void *args);
|
||||
|
||||
/*
|
||||
* Same as hashtab_map, except that if apply returns a non-zero status,
|
||||
* then the (key,datum) pair will be removed from the hashtab and the
|
||||
* destroy function will be applied to (key,datum,args).
|
||||
*/
|
||||
void hashtab_map_remove_on_error(struct hashtab *h,
|
||||
int (*apply)(void *k, void *d, void *args),
|
||||
void (*destroy)(void *k, void *d, void *args),
|
||||
void *args);
|
||||
|
||||
|
||||
/* Fill info with some hash table statistics */
|
||||
void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
|
||||
|
||||
#endif /* _SS_HASHTAB_H */
|
||||
754
extra/linux-2.6.10/security/selinux/ss/mls.c
Normal file
754
extra/linux-2.6.10/security/selinux/ss/mls.c
Normal file
@@ -0,0 +1,754 @@
|
||||
/*
|
||||
* Implementation of the multi-level security (MLS) policy.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include "mls.h"
|
||||
#include "policydb.h"
|
||||
#include "services.h"
|
||||
|
||||
/*
|
||||
* Remove any permissions from `allowed' that are
|
||||
* denied by the MLS policy.
|
||||
*/
|
||||
void mls_compute_av(struct context *scontext,
|
||||
struct context *tcontext,
|
||||
struct class_datum *tclass,
|
||||
u32 *allowed)
|
||||
{
|
||||
unsigned int rel[2];
|
||||
int l;
|
||||
|
||||
for (l = 0; l < 2; l++)
|
||||
rel[l] = mls_level_relation(scontext->range.level[l],
|
||||
tcontext->range.level[l]);
|
||||
|
||||
if (rel[1] != MLS_RELATION_EQ) {
|
||||
if (rel[1] != MLS_RELATION_DOM &&
|
||||
!ebitmap_get_bit(&policydb.trustedreaders, scontext->type - 1) &&
|
||||
!ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
|
||||
/* read(s,t) = (s.high >= t.high) = False */
|
||||
*allowed = (*allowed) & ~(tclass->mlsperms.read);
|
||||
}
|
||||
if (rel[1] != MLS_RELATION_DOMBY &&
|
||||
!ebitmap_get_bit(&policydb.trustedreaders, tcontext->type - 1) &&
|
||||
!ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
|
||||
/* readby(s,t) = read(t,s) = False */
|
||||
*allowed = (*allowed) & ~(tclass->mlsperms.readby);
|
||||
}
|
||||
}
|
||||
if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) ||
|
||||
((!mls_level_eq(tcontext->range.level[0],
|
||||
tcontext->range.level[1])) &&
|
||||
(rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) &&
|
||||
!ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) &&
|
||||
!ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
|
||||
/*
|
||||
* write(s,t) = ((s.low <= t.low = t.high) or (s.low
|
||||
* <= t.low <= t.high <= s.high)) = False
|
||||
*/
|
||||
*allowed = (*allowed) & ~(tclass->mlsperms.write);
|
||||
}
|
||||
|
||||
if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) ||
|
||||
((!mls_level_eq(scontext->range.level[0],
|
||||
scontext->range.level[1])) &&
|
||||
(rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) &&
|
||||
!ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) &&
|
||||
!ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
|
||||
/* writeby(s,t) = write(t,s) = False */
|
||||
*allowed = (*allowed) & ~(tclass->mlsperms.writeby);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the length in bytes for the MLS fields of the
|
||||
* security context string representation of `context'.
|
||||
*/
|
||||
int mls_compute_context_len(struct context * context)
|
||||
{
|
||||
int i, l, len;
|
||||
|
||||
|
||||
len = 0;
|
||||
for (l = 0; l < 2; l++) {
|
||||
len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]) + 1;
|
||||
|
||||
for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
|
||||
if (ebitmap_get_bit(&context->range.level[l].cat, i - 1))
|
||||
len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
|
||||
|
||||
if (mls_level_relation(context->range.level[0], context->range.level[1])
|
||||
== MLS_RELATION_EQ)
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the security context string representation of
|
||||
* the MLS fields of `context' into the string `*scontext'.
|
||||
* Update `*scontext' to point to the end of the MLS fields.
|
||||
*/
|
||||
int mls_sid_to_context(struct context *context,
|
||||
char **scontext)
|
||||
{
|
||||
char *scontextp;
|
||||
int i, l;
|
||||
|
||||
scontextp = *scontext;
|
||||
|
||||
for (l = 0; l < 2; l++) {
|
||||
strcpy(scontextp,
|
||||
policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
|
||||
scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
|
||||
*scontextp = ':';
|
||||
scontextp++;
|
||||
for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
|
||||
if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
|
||||
strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
|
||||
scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
|
||||
*scontextp = ',';
|
||||
scontextp++;
|
||||
}
|
||||
if (mls_level_relation(context->range.level[0], context->range.level[1])
|
||||
!= MLS_RELATION_EQ) {
|
||||
scontextp--;
|
||||
sprintf(scontextp, "-");
|
||||
scontextp++;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*scontext = scontextp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if the MLS fields in the security context
|
||||
* structure `c' are valid. Return 0 otherwise.
|
||||
*/
|
||||
int mls_context_isvalid(struct policydb *p, struct context *c)
|
||||
{
|
||||
unsigned int relation;
|
||||
struct level_datum *levdatum;
|
||||
struct user_datum *usrdatum;
|
||||
struct mls_range_list *rnode;
|
||||
int i, l;
|
||||
|
||||
/*
|
||||
* MLS range validity checks: high must dominate low, low level must
|
||||
* be valid (category set <-> sensitivity check), and high level must
|
||||
* be valid (category set <-> sensitivity check)
|
||||
*/
|
||||
relation = mls_level_relation(c->range.level[1],
|
||||
c->range.level[0]);
|
||||
if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ)))
|
||||
/* High does not dominate low. */
|
||||
return 0;
|
||||
|
||||
for (l = 0; l < 2; l++) {
|
||||
if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim)
|
||||
return 0;
|
||||
levdatum = hashtab_search(p->p_levels.table,
|
||||
p->p_sens_val_to_name[c->range.level[l].sens - 1]);
|
||||
if (!levdatum)
|
||||
return 0;
|
||||
|
||||
for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
|
||||
if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
|
||||
if (i > p->p_cats.nprim)
|
||||
return 0;
|
||||
if (!ebitmap_get_bit(&levdatum->level->cat, i - 1))
|
||||
/*
|
||||
* Category may not be associated with
|
||||
* sensitivity in low level.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c->role == OBJECT_R_VAL)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* User must be authorized for the MLS range.
|
||||
*/
|
||||
if (!c->user || c->user > p->p_users.nprim)
|
||||
return 0;
|
||||
usrdatum = p->user_val_to_struct[c->user - 1];
|
||||
for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) {
|
||||
if (mls_range_contains(rnode->range, c->range))
|
||||
break;
|
||||
}
|
||||
if (!rnode)
|
||||
/* user may not be associated with range */
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the MLS fields in the security context structure
|
||||
* `context' based on the string representation in
|
||||
* the string `*scontext'. Update `*scontext' to
|
||||
* point to the end of the string representation of
|
||||
* the MLS fields.
|
||||
*
|
||||
* This function modifies the string in place, inserting
|
||||
* NULL characters to terminate the MLS fields.
|
||||
*/
|
||||
int mls_context_to_sid(char oldc,
|
||||
char **scontext,
|
||||
struct context *context)
|
||||
{
|
||||
|
||||
char delim;
|
||||
char *scontextp, *p;
|
||||
struct level_datum *levdatum;
|
||||
struct cat_datum *catdatum;
|
||||
int l, rc = -EINVAL;
|
||||
|
||||
if (!oldc) {
|
||||
/* No MLS component to the security context. Try
|
||||
to use a default 'unclassified' value. */
|
||||
levdatum = hashtab_search(policydb.p_levels.table,
|
||||
"unclassified");
|
||||
if (!levdatum)
|
||||
goto out;
|
||||
context->range.level[0].sens = levdatum->level->sens;
|
||||
context->range.level[1].sens = context->range.level[0].sens;
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Extract low sensitivity. */
|
||||
scontextp = p = *scontext;
|
||||
while (*p && *p != ':' && *p != '-')
|
||||
p++;
|
||||
|
||||
delim = *p;
|
||||
if (delim != 0)
|
||||
*p++ = 0;
|
||||
|
||||
for (l = 0; l < 2; l++) {
|
||||
levdatum = hashtab_search(policydb.p_levels.table, scontextp);
|
||||
if (!levdatum)
|
||||
goto out;
|
||||
|
||||
context->range.level[l].sens = levdatum->level->sens;
|
||||
|
||||
if (delim == ':') {
|
||||
/* Extract low category set. */
|
||||
while (1) {
|
||||
scontextp = p;
|
||||
while (*p && *p != ',' && *p != '-')
|
||||
p++;
|
||||
delim = *p;
|
||||
if (delim != 0)
|
||||
*p++ = 0;
|
||||
|
||||
catdatum = hashtab_search(policydb.p_cats.table,
|
||||
scontextp);
|
||||
if (!catdatum)
|
||||
goto out;
|
||||
|
||||
rc = ebitmap_set_bit(&context->range.level[l].cat,
|
||||
catdatum->value - 1, 1);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (delim != ',')
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (delim == '-') {
|
||||
/* Extract high sensitivity. */
|
||||
scontextp = p;
|
||||
while (*p && *p != ':')
|
||||
p++;
|
||||
|
||||
delim = *p;
|
||||
if (delim != 0)
|
||||
*p++ = 0;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (l == 0) {
|
||||
context->range.level[1].sens = context->range.level[0].sens;
|
||||
rc = ebitmap_cpy(&context->range.level[1].cat,
|
||||
&context->range.level[0].cat);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
*scontext = ++p;
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies the MLS range from `src' into `dst'.
|
||||
*/
|
||||
static inline int mls_copy_context(struct context *dst,
|
||||
struct context *src)
|
||||
{
|
||||
int l, rc = 0;
|
||||
|
||||
/* Copy the MLS range from the source context */
|
||||
for (l = 0; l < 2; l++) {
|
||||
|
||||
dst->range.level[l].sens = src->range.level[l].sens;
|
||||
rc = ebitmap_cpy(&dst->range.level[l].cat,
|
||||
&src->range.level[l].cat);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the MLS fields in the security context
|
||||
* structure `c' from the values specified in the
|
||||
* policy `oldp' to the values specified in the policy `newp'.
|
||||
*/
|
||||
int mls_convert_context(struct policydb *oldp,
|
||||
struct policydb *newp,
|
||||
struct context *c)
|
||||
{
|
||||
struct level_datum *levdatum;
|
||||
struct cat_datum *catdatum;
|
||||
struct ebitmap bitmap;
|
||||
int l, i;
|
||||
|
||||
for (l = 0; l < 2; l++) {
|
||||
levdatum = hashtab_search(newp->p_levels.table,
|
||||
oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
|
||||
|
||||
if (!levdatum)
|
||||
return -EINVAL;
|
||||
c->range.level[l].sens = levdatum->level->sens;
|
||||
|
||||
ebitmap_init(&bitmap);
|
||||
for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
|
||||
if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
|
||||
int rc;
|
||||
|
||||
catdatum = hashtab_search(newp->p_cats.table,
|
||||
oldp->p_cat_val_to_name[i - 1]);
|
||||
if (!catdatum)
|
||||
return -EINVAL;
|
||||
rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
ebitmap_destroy(&c->range.level[l].cat);
|
||||
c->range.level[l].cat = bitmap;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mls_compute_sid(struct context *scontext,
|
||||
struct context *tcontext,
|
||||
u16 tclass,
|
||||
u32 specified,
|
||||
struct context *newcontext)
|
||||
{
|
||||
switch (specified) {
|
||||
case AVTAB_TRANSITION:
|
||||
case AVTAB_CHANGE:
|
||||
/* Use the process MLS attributes. */
|
||||
return mls_copy_context(newcontext, scontext);
|
||||
case AVTAB_MEMBER:
|
||||
/* Only polyinstantiate the MLS attributes if
|
||||
the type is being polyinstantiated */
|
||||
if (newcontext->type != tcontext->type) {
|
||||
/* Use the process MLS attributes. */
|
||||
return mls_copy_context(newcontext, scontext);
|
||||
} else {
|
||||
/* Use the related object MLS attributes. */
|
||||
return mls_copy_context(newcontext, tcontext);
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void mls_user_destroy(struct user_datum *usrdatum)
|
||||
{
|
||||
struct mls_range_list *rnode, *rtmp;
|
||||
rnode = usrdatum->ranges;
|
||||
while (rnode) {
|
||||
rtmp = rnode;
|
||||
rnode = rnode->next;
|
||||
ebitmap_destroy(&rtmp->range.level[0].cat);
|
||||
ebitmap_destroy(&rtmp->range.level[1].cat);
|
||||
kfree(rtmp);
|
||||
}
|
||||
}
|
||||
|
||||
int mls_read_perm(struct perm_datum *perdatum, void *fp)
|
||||
{
|
||||
u32 *buf;
|
||||
|
||||
buf = next_entry(fp, sizeof(u32));
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
perdatum->base_perms = le32_to_cpu(buf[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a MLS level structure from a policydb binary
|
||||
* representation file.
|
||||
*/
|
||||
struct mls_level *mls_read_level(void *fp)
|
||||
{
|
||||
struct mls_level *l;
|
||||
u32 *buf;
|
||||
|
||||
l = kmalloc(sizeof(*l), GFP_ATOMIC);
|
||||
if (!l) {
|
||||
printk(KERN_ERR "security: mls: out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(l, 0, sizeof(*l));
|
||||
|
||||
buf = next_entry(fp, sizeof(u32));
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: mls: truncated level\n");
|
||||
goto bad;
|
||||
}
|
||||
l->sens = cpu_to_le32(buf[0]);
|
||||
|
||||
if (ebitmap_read(&l->cat, fp)) {
|
||||
printk(KERN_ERR "security: mls: error reading level "
|
||||
"categories\n");
|
||||
goto bad;
|
||||
}
|
||||
return l;
|
||||
|
||||
bad:
|
||||
kfree(l);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read a MLS range structure from a policydb binary
|
||||
* representation file.
|
||||
*/
|
||||
static int mls_read_range_helper(struct mls_range *r, void *fp)
|
||||
{
|
||||
u32 *buf;
|
||||
int items, rc = -EINVAL;
|
||||
|
||||
buf = next_entry(fp, sizeof(u32));
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
items = le32_to_cpu(buf[0]);
|
||||
buf = next_entry(fp, sizeof(u32) * items);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: mls: truncated range\n");
|
||||
goto out;
|
||||
}
|
||||
r->level[0].sens = le32_to_cpu(buf[0]);
|
||||
if (items > 1) {
|
||||
r->level[1].sens = le32_to_cpu(buf[1]);
|
||||
} else {
|
||||
r->level[1].sens = r->level[0].sens;
|
||||
}
|
||||
|
||||
rc = ebitmap_read(&r->level[0].cat, fp);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "security: 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 "
|
||||
"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");
|
||||
goto bad_high;
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
bad_high:
|
||||
ebitmap_destroy(&r->level[0].cat);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int mls_read_range(struct context *c, void *fp)
|
||||
{
|
||||
return mls_read_range_helper(&c->range, fp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read a MLS perms structure from a policydb binary
|
||||
* representation file.
|
||||
*/
|
||||
int mls_read_class(struct class_datum *cladatum, void *fp)
|
||||
{
|
||||
struct mls_perms *p = &cladatum->mlsperms;
|
||||
u32 *buf;
|
||||
|
||||
buf = next_entry(fp, sizeof(u32)*4);
|
||||
if (!buf) {
|
||||
printk(KERN_ERR "security: mls: truncated mls permissions\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
p->read = le32_to_cpu(buf[0]);
|
||||
p->readby = le32_to_cpu(buf[1]);
|
||||
p->write = le32_to_cpu(buf[2]);
|
||||
p->writeby = le32_to_cpu(buf[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mls_read_user(struct user_datum *usrdatum, void *fp)
|
||||
{
|
||||
struct mls_range_list *r, *l;
|
||||
int rc = 0;
|
||||
u32 nel, i;
|
||||
u32 *buf;
|
||||
|
||||
buf = next_entry(fp, sizeof(u32));
|
||||
if (!buf) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
nel = le32_to_cpu(buf[0]);
|
||||
l = NULL;
|
||||
for (i = 0; i < nel; i++) {
|
||||
r = kmalloc(sizeof(*r), GFP_ATOMIC);
|
||||
if (!r) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset(r, 0, sizeof(*r));
|
||||
|
||||
rc = mls_read_range_helper(&r->range, fp);
|
||||
if (rc) {
|
||||
kfree(r);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (l)
|
||||
l->next = r;
|
||||
else
|
||||
usrdatum->ranges = r;
|
||||
l = r;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int mls_read_nlevels(struct policydb *p, void *fp)
|
||||
{
|
||||
u32 *buf;
|
||||
|
||||
buf = next_entry(fp, sizeof(u32));
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
p->nlevels = le32_to_cpu(buf[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mls_read_trusted(struct policydb *p, void *fp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = ebitmap_read(&p->trustedreaders, fp);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = ebitmap_read(&p->trustedwriters, fp);
|
||||
if (rc)
|
||||
goto bad;
|
||||
rc = ebitmap_read(&p->trustedobjects, fp);
|
||||
if (rc)
|
||||
goto bad2;
|
||||
out:
|
||||
return rc;
|
||||
bad2:
|
||||
ebitmap_destroy(&p->trustedwriters);
|
||||
bad:
|
||||
ebitmap_destroy(&p->trustedreaders);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int sens_index(void *key, void *datum, void *datap)
|
||||
{
|
||||
struct policydb *p;
|
||||
struct level_datum *levdatum;
|
||||
|
||||
|
||||
levdatum = datum;
|
||||
p = datap;
|
||||
|
||||
if (!levdatum->isalias)
|
||||
p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cat_index(void *key, void *datum, void *datap)
|
||||
{
|
||||
struct policydb *p;
|
||||
struct cat_datum *catdatum;
|
||||
|
||||
|
||||
catdatum = datum;
|
||||
p = datap;
|
||||
|
||||
|
||||
if (!catdatum->isalias)
|
||||
p->p_cat_val_to_name[catdatum->value - 1] = key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sens_destroy(void *key, void *datum, void *p)
|
||||
{
|
||||
struct level_datum *levdatum;
|
||||
|
||||
kfree(key);
|
||||
levdatum = datum;
|
||||
if (!levdatum->isalias) {
|
||||
ebitmap_destroy(&levdatum->level->cat);
|
||||
kfree(levdatum->level);
|
||||
}
|
||||
kfree(datum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cat_destroy(void *key, void *datum, void *p)
|
||||
{
|
||||
kfree(key);
|
||||
kfree(datum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sens_read(struct policydb *p, struct hashtab *h, void *fp)
|
||||
{
|
||||
char *key = NULL;
|
||||
struct level_datum *levdatum;
|
||||
int rc;
|
||||
u32 *buf, len;
|
||||
|
||||
levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
|
||||
if (!levdatum) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset(levdatum, 0, sizeof(*levdatum));
|
||||
|
||||
buf = next_entry(fp, sizeof(u32)*2);
|
||||
if (!buf) {
|
||||
rc = -EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
len = le32_to_cpu(buf[0]);
|
||||
levdatum->isalias = le32_to_cpu(buf[1]);
|
||||
|
||||
buf = next_entry(fp, len);
|
||||
if (!buf) {
|
||||
rc = -EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
key = kmalloc(len + 1,GFP_ATOMIC);
|
||||
if (!key) {
|
||||
rc = -ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
memcpy(key, buf, len);
|
||||
key[len] = 0;
|
||||
|
||||
levdatum->level = mls_read_level(fp);
|
||||
if (!levdatum->level) {
|
||||
rc = -EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
rc = hashtab_insert(h, key, levdatum);
|
||||
if (rc)
|
||||
goto bad;
|
||||
out:
|
||||
return rc;
|
||||
bad:
|
||||
sens_destroy(key, levdatum, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
int cat_read(struct policydb *p, struct hashtab *h, void *fp)
|
||||
{
|
||||
char *key = NULL;
|
||||
struct cat_datum *catdatum;
|
||||
int rc;
|
||||
u32 *buf, len;
|
||||
|
||||
catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
|
||||
if (!catdatum) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset(catdatum, 0, sizeof(*catdatum));
|
||||
|
||||
buf = next_entry(fp, sizeof(u32)*3);
|
||||
if (!buf) {
|
||||
rc = -EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
len = le32_to_cpu(buf[0]);
|
||||
catdatum->value = le32_to_cpu(buf[1]);
|
||||
catdatum->isalias = le32_to_cpu(buf[2]);
|
||||
|
||||
buf = next_entry(fp, len);
|
||||
if (!buf) {
|
||||
rc = -EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
key = kmalloc(len + 1,GFP_ATOMIC);
|
||||
if (!key) {
|
||||
rc = -ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
memcpy(key, buf, len);
|
||||
key[len] = 0;
|
||||
|
||||
rc = hashtab_insert(h, key, catdatum);
|
||||
if (rc)
|
||||
goto bad;
|
||||
out:
|
||||
return rc;
|
||||
|
||||
bad:
|
||||
cat_destroy(key, catdatum, NULL);
|
||||
goto out;
|
||||
}
|
||||
99
extra/linux-2.6.10/security/selinux/ss/mls.h
Normal file
99
extra/linux-2.6.10/security/selinux/ss/mls.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Multi-level security (MLS) policy operations.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_MLS_H_
|
||||
#define _SS_MLS_H_
|
||||
|
||||
#include "context.h"
|
||||
#include "policydb.h"
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
|
||||
void mls_compute_av(struct context *scontext,
|
||||
struct context *tcontext,
|
||||
struct class_datum *tclass,
|
||||
u32 *allowed);
|
||||
|
||||
int mls_compute_context_len(struct context *context);
|
||||
int mls_sid_to_context(struct context *context, char **scontext);
|
||||
int mls_context_isvalid(struct policydb *p, struct context *c);
|
||||
|
||||
int mls_context_to_sid(char oldc,
|
||||
char **scontext,
|
||||
struct context *context);
|
||||
|
||||
int mls_convert_context(struct policydb *oldp,
|
||||
struct policydb *newp,
|
||||
struct context *context);
|
||||
|
||||
int mls_compute_sid(struct context *scontext,
|
||||
struct context *tcontext,
|
||||
u16 tclass,
|
||||
u32 specified,
|
||||
struct context *newcontext);
|
||||
|
||||
int sens_index(void *key, void *datum, void *datap);
|
||||
int cat_index(void *key, void *datum, void *datap);
|
||||
int sens_destroy(void *key, void *datum, void *p);
|
||||
int cat_destroy(void *key, void *datum, void *p);
|
||||
int sens_read(struct policydb *p, struct hashtab *h, void *fp);
|
||||
int cat_read(struct policydb *p, struct hashtab *h, void *fp);
|
||||
|
||||
#define mls_for_user_ranges(user, usercon) { \
|
||||
struct mls_range_list *__ranges; \
|
||||
for (__ranges = user->ranges; __ranges; __ranges = __ranges->next) { \
|
||||
usercon.range = __ranges->range;
|
||||
|
||||
#define mls_end_user_ranges } }
|
||||
|
||||
#define mls_symtab_names "levels", "categories",
|
||||
#define mls_symtab_sizes 16, 16,
|
||||
#define mls_index_f sens_index, cat_index,
|
||||
#define mls_destroy_f sens_destroy, cat_destroy,
|
||||
#define mls_read_f sens_read, cat_read,
|
||||
#define mls_write_f sens_write, cat_write,
|
||||
#define mls_policydb_index_others(p) printk(", %d levels", p->nlevels);
|
||||
|
||||
#define mls_set_config(config) config |= POLICYDB_CONFIG_MLS
|
||||
|
||||
void mls_user_destroy(struct user_datum *usrdatum);
|
||||
int mls_read_range(struct context *c, void *fp);
|
||||
int mls_read_perm(struct perm_datum *perdatum, void *fp);
|
||||
int mls_read_class(struct class_datum *cladatum, void *fp);
|
||||
int mls_read_user(struct user_datum *usrdatum, void *fp);
|
||||
int mls_read_nlevels(struct policydb *p, void *fp);
|
||||
int mls_read_trusted(struct policydb *p, void *fp);
|
||||
|
||||
#else
|
||||
|
||||
#define mls_compute_av(scontext, tcontext, tclass_datum, allowed)
|
||||
#define mls_compute_context_len(context) 0
|
||||
#define mls_sid_to_context(context, scontextpp)
|
||||
#define mls_context_isvalid(p, c) 1
|
||||
#define mls_context_to_sid(oldc, context_str, context) 0
|
||||
#define mls_convert_context(oldp, newp, c) 0
|
||||
#define mls_compute_sid(scontext, tcontext, tclass, specified, newcontextp) 0
|
||||
#define mls_for_user_ranges(user, usercon)
|
||||
#define mls_end_user_ranges
|
||||
#define mls_symtab_names
|
||||
#define mls_symtab_sizes
|
||||
#define mls_index_f
|
||||
#define mls_destroy_f
|
||||
#define mls_read_f
|
||||
#define mls_write_f
|
||||
#define mls_policydb_index_others(p)
|
||||
#define mls_set_config(config)
|
||||
#define mls_user_destroy(usrdatum)
|
||||
#define mls_read_range(c, fp) 0
|
||||
#define mls_read_perm(p, fp) 0
|
||||
#define mls_read_class(c, fp) 0
|
||||
#define mls_read_user(u, fp) 0
|
||||
#define mls_read_nlevels(p, fp) 0
|
||||
#define mls_read_trusted(p, fp) 0
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SS_MLS_H */
|
||||
|
||||
58
extra/linux-2.6.10/security/selinux/ss/mls_types.h
Normal file
58
extra/linux-2.6.10/security/selinux/ss/mls_types.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Type definitions for the multi-level security (MLS) policy.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_MLS_TYPES_H_
|
||||
#define _SS_MLS_TYPES_H_
|
||||
|
||||
struct mls_level {
|
||||
u32 sens; /* sensitivity */
|
||||
struct ebitmap cat; /* category set */
|
||||
};
|
||||
|
||||
struct mls_range {
|
||||
struct mls_level level[2]; /* low == level[0], high == level[1] */
|
||||
};
|
||||
|
||||
struct mls_range_list {
|
||||
struct mls_range range;
|
||||
struct mls_range_list *next;
|
||||
};
|
||||
|
||||
#define MLS_RELATION_DOM 1 /* source dominates */
|
||||
#define MLS_RELATION_DOMBY 2 /* target dominates */
|
||||
#define MLS_RELATION_EQ 4 /* source and target are equivalent */
|
||||
#define MLS_RELATION_INCOMP 8 /* source and target are incomparable */
|
||||
|
||||
#define mls_level_eq(l1,l2) \
|
||||
(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat))
|
||||
|
||||
#define mls_level_relation(l1,l2) ( \
|
||||
(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat)) ? \
|
||||
MLS_RELATION_EQ : \
|
||||
(((l1).sens >= (l2).sens) && ebitmap_contains(&(l1).cat, &(l2).cat)) ? \
|
||||
MLS_RELATION_DOM : \
|
||||
(((l2).sens >= (l1).sens) && ebitmap_contains(&(l2).cat, &(l1).cat)) ? \
|
||||
MLS_RELATION_DOMBY : \
|
||||
MLS_RELATION_INCOMP )
|
||||
|
||||
#define mls_range_contains(r1,r2) \
|
||||
((mls_level_relation((r1).level[0], (r2).level[0]) & \
|
||||
(MLS_RELATION_EQ | MLS_RELATION_DOMBY)) && \
|
||||
(mls_level_relation((r1).level[1], (r2).level[1]) & \
|
||||
(MLS_RELATION_EQ | MLS_RELATION_DOM)))
|
||||
|
||||
/*
|
||||
* Every access vector permission is mapped to a set of MLS base
|
||||
* permissions, based on the flow properties of the corresponding
|
||||
* operation.
|
||||
*/
|
||||
struct mls_perms {
|
||||
u32 read; /* permissions that map to `read' */
|
||||
u32 readby; /* permissions that map to `readby' */
|
||||
u32 write; /* permissions that map to `write' */
|
||||
u32 writeby; /* permissions that map to `writeby' */
|
||||
};
|
||||
|
||||
#endif /* _SS_MLS_TYPES_H_ */
|
||||
1563
extra/linux-2.6.10/security/selinux/ss/policydb.c
Normal file
1563
extra/linux-2.6.10/security/selinux/ss/policydb.c
Normal file
File diff suppressed because it is too large
Load Diff
288
extra/linux-2.6.10/security/selinux/ss/policydb.h
Normal file
288
extra/linux-2.6.10/security/selinux/ss/policydb.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* A policy database (policydb) specifies the
|
||||
* configuration data for the security policy.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
|
||||
/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
|
||||
*
|
||||
* Added conditional policy language extensions
|
||||
*
|
||||
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SS_POLICYDB_H_
|
||||
#define _SS_POLICYDB_H_
|
||||
|
||||
#include "symtab.h"
|
||||
#include "avtab.h"
|
||||
#include "sidtab.h"
|
||||
#include "context.h"
|
||||
#include "constraint.h"
|
||||
|
||||
/*
|
||||
* A datum type is defined for each kind of symbol
|
||||
* in the configuration data: individual permissions,
|
||||
* common prefixes for access vectors, classes,
|
||||
* users, roles, types, sensitivities, categories, etc.
|
||||
*/
|
||||
|
||||
/* Permission attributes */
|
||||
struct perm_datum {
|
||||
u32 value; /* permission bit + 1 */
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
#define MLS_BASE_READ 1 /* MLS base permission `read' */
|
||||
#define MLS_BASE_WRITE 2 /* MLS base permission `write' */
|
||||
#define MLS_BASE_READBY 4 /* MLS base permission `readby' */
|
||||
#define MLS_BASE_WRITEBY 8 /* MLS base permission `writeby' */
|
||||
u32 base_perms; /* MLS base permission mask */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Attributes of a common prefix for access vectors */
|
||||
struct common_datum {
|
||||
u32 value; /* internal common value */
|
||||
struct symtab permissions; /* common permissions */
|
||||
};
|
||||
|
||||
/* Class attributes */
|
||||
struct class_datum {
|
||||
u32 value; /* class value */
|
||||
char *comkey; /* common name */
|
||||
struct common_datum *comdatum; /* common datum */
|
||||
struct symtab permissions; /* class-specific permission symbol table */
|
||||
struct constraint_node *constraints; /* constraints on class permissions */
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
struct mls_perms mlsperms; /* MLS base permission masks */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Role attributes */
|
||||
struct role_datum {
|
||||
u32 value; /* internal role value */
|
||||
struct ebitmap dominates; /* set of roles dominated by this role */
|
||||
struct ebitmap types; /* set of authorized types for role */
|
||||
};
|
||||
|
||||
struct role_trans {
|
||||
u32 role; /* current role */
|
||||
u32 type; /* program executable type */
|
||||
u32 new_role; /* new role */
|
||||
struct role_trans *next;
|
||||
};
|
||||
|
||||
struct role_allow {
|
||||
u32 role; /* current role */
|
||||
u32 new_role; /* new role */
|
||||
struct role_allow *next;
|
||||
};
|
||||
|
||||
/* Type attributes */
|
||||
struct type_datum {
|
||||
u32 value; /* internal type value */
|
||||
unsigned char primary; /* primary name? */
|
||||
};
|
||||
|
||||
/* User attributes */
|
||||
struct user_datum {
|
||||
u32 value; /* internal user value */
|
||||
struct ebitmap roles; /* set of authorized roles for user */
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
struct mls_range_list *ranges; /* list of authorized MLS ranges for user */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
/* Sensitivity attributes */
|
||||
struct level_datum {
|
||||
struct mls_level *level; /* sensitivity and associated categories */
|
||||
unsigned char isalias; /* is this sensitivity an alias for another? */
|
||||
};
|
||||
|
||||
/* Category attributes */
|
||||
struct cat_datum {
|
||||
u32 value; /* internal category bit + 1 */
|
||||
unsigned char isalias; /* is this category an alias for another? */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Boolean data type */
|
||||
struct cond_bool_datum {
|
||||
__u32 value; /* internal type value */
|
||||
int state;
|
||||
};
|
||||
|
||||
struct cond_node;
|
||||
|
||||
/*
|
||||
* The configuration data includes security contexts for
|
||||
* initial SIDs, unlabeled file systems, TCP and UDP port numbers,
|
||||
* network interfaces, and nodes. This structure stores the
|
||||
* relevant data for one such entry. Entries of the same kind
|
||||
* (e.g. all initial SIDs) are linked together into a list.
|
||||
*/
|
||||
struct ocontext {
|
||||
union {
|
||||
char *name; /* name of initial SID, fs, netif, fstype, path */
|
||||
struct {
|
||||
u8 protocol;
|
||||
u16 low_port;
|
||||
u16 high_port;
|
||||
} port; /* TCP or UDP port information */
|
||||
struct {
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
} node; /* node information */
|
||||
struct {
|
||||
u32 addr[4];
|
||||
u32 mask[4];
|
||||
} node6; /* IPv6 node information */
|
||||
} u;
|
||||
union {
|
||||
u32 sclass; /* security class for genfs */
|
||||
u32 behavior; /* labeling behavior for fs_use */
|
||||
} v;
|
||||
struct context context[2]; /* security context(s) */
|
||||
u32 sid[2]; /* SID(s) */
|
||||
struct ocontext *next;
|
||||
};
|
||||
|
||||
struct genfs {
|
||||
char *fstype;
|
||||
struct ocontext *head;
|
||||
struct genfs *next;
|
||||
};
|
||||
|
||||
/* symbol table array indices */
|
||||
#define SYM_COMMONS 0
|
||||
#define SYM_CLASSES 1
|
||||
#define SYM_ROLES 2
|
||||
#define SYM_TYPES 3
|
||||
#define SYM_USERS 4
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
#define SYM_LEVELS 5
|
||||
#define SYM_CATS 6
|
||||
#define SYM_BOOLS 7
|
||||
#define SYM_NUM 8
|
||||
#else
|
||||
#define SYM_BOOLS 5
|
||||
#define SYM_NUM 6
|
||||
#endif
|
||||
|
||||
/* object context array indices */
|
||||
#define OCON_ISID 0 /* initial SIDs */
|
||||
#define OCON_FS 1 /* unlabeled file systems */
|
||||
#define OCON_PORT 2 /* TCP and UDP port numbers */
|
||||
#define OCON_NETIF 3 /* network interfaces */
|
||||
#define OCON_NODE 4 /* nodes */
|
||||
#define OCON_FSUSE 5 /* fs_use */
|
||||
#define OCON_NODE6 6 /* IPv6 nodes */
|
||||
#define OCON_NUM 7
|
||||
|
||||
/* The policy database */
|
||||
struct policydb {
|
||||
/* symbol tables */
|
||||
struct symtab symtab[SYM_NUM];
|
||||
#define p_commons symtab[SYM_COMMONS]
|
||||
#define p_classes symtab[SYM_CLASSES]
|
||||
#define p_roles symtab[SYM_ROLES]
|
||||
#define p_types symtab[SYM_TYPES]
|
||||
#define p_users symtab[SYM_USERS]
|
||||
#define p_levels symtab[SYM_LEVELS]
|
||||
#define p_cats symtab[SYM_CATS]
|
||||
#define p_bools symtab[SYM_BOOLS]
|
||||
|
||||
/* symbol names indexed by (value - 1) */
|
||||
char **sym_val_to_name[SYM_NUM];
|
||||
#define p_common_val_to_name sym_val_to_name[SYM_COMMONS]
|
||||
#define p_class_val_to_name sym_val_to_name[SYM_CLASSES]
|
||||
#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
|
||||
#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
|
||||
#define p_user_val_to_name sym_val_to_name[SYM_USERS]
|
||||
#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
|
||||
#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
|
||||
#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
|
||||
|
||||
/* class, role, and user attributes indexed by (value - 1) */
|
||||
struct class_datum **class_val_to_struct;
|
||||
struct role_datum **role_val_to_struct;
|
||||
struct user_datum **user_val_to_struct;
|
||||
|
||||
/* type enforcement access vectors and transitions */
|
||||
struct avtab te_avtab;
|
||||
|
||||
/* role transitions */
|
||||
struct role_trans *role_tr;
|
||||
|
||||
/* bools indexed by (value - 1) */
|
||||
struct cond_bool_datum **bool_val_to_struct;
|
||||
/* type enforcement conditional access vectors and transitions */
|
||||
struct avtab te_cond_avtab;
|
||||
/* linked list indexing te_cond_avtab by conditional */
|
||||
struct cond_node* cond_list;
|
||||
|
||||
/* role allows */
|
||||
struct role_allow *role_allow;
|
||||
|
||||
/* security contexts of initial SIDs, unlabeled file systems,
|
||||
TCP or UDP port numbers, network interfaces and nodes */
|
||||
struct ocontext *ocontexts[OCON_NUM];
|
||||
|
||||
/* security contexts for files in filesystems that cannot support
|
||||
a persistent label mapping or use another
|
||||
fixed labeling behavior. */
|
||||
struct genfs *genfs;
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_MLS
|
||||
/* number of legitimate MLS levels */
|
||||
u32 nlevels;
|
||||
|
||||
struct ebitmap trustedreaders;
|
||||
struct ebitmap trustedwriters;
|
||||
struct ebitmap trustedobjects;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int policydb_init(struct policydb *p);
|
||||
extern int policydb_index_classes(struct policydb *p);
|
||||
extern int policydb_index_others(struct policydb *p);
|
||||
extern void policydb_destroy(struct policydb *p);
|
||||
extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
|
||||
extern int policydb_context_isvalid(struct policydb *p, struct context *c);
|
||||
extern int policydb_read(struct policydb *p, void *fp);
|
||||
|
||||
#define PERM_SYMTAB_SIZE 32
|
||||
|
||||
#define POLICYDB_CONFIG_MLS 1
|
||||
|
||||
#define OBJECT_R "object_r"
|
||||
#define OBJECT_R_VAL 1
|
||||
|
||||
#define POLICYDB_MAGIC SELINUX_MAGIC
|
||||
#define POLICYDB_STRING "SE Linux"
|
||||
|
||||
struct policy_file {
|
||||
char *data;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static inline void *next_entry(struct policy_file *fp, size_t bytes)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
if (bytes > fp->len)
|
||||
return NULL;
|
||||
|
||||
buf = fp->data;
|
||||
fp->data += bytes;
|
||||
fp->len -= bytes;
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* _SS_POLICYDB_H_ */
|
||||
|
||||
1627
extra/linux-2.6.10/security/selinux/ss/services.c
Normal file
1627
extra/linux-2.6.10/security/selinux/ss/services.c
Normal file
File diff suppressed because it is too large
Load Diff
21
extra/linux-2.6.10/security/selinux/ss/services.h
Normal file
21
extra/linux-2.6.10/security/selinux/ss/services.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Implementation of the security services.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_SERVICES_H_
|
||||
#define _SS_SERVICES_H_
|
||||
|
||||
#include "policydb.h"
|
||||
#include "sidtab.h"
|
||||
|
||||
/*
|
||||
* The security server uses two global data structures
|
||||
* when providing its services: the SID table (sidtab)
|
||||
* and the policy database (policydb).
|
||||
*/
|
||||
extern struct sidtab sidtab;
|
||||
extern struct policydb policydb;
|
||||
|
||||
#endif /* _SS_SERVICES_H_ */
|
||||
|
||||
341
extra/linux-2.6.10/security/selinux/ss/sidtab.c
Normal file
341
extra/linux-2.6.10/security/selinux/ss/sidtab.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Implementation of the SID table type.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include "flask.h"
|
||||
#include "security.h"
|
||||
#include "sidtab.h"
|
||||
|
||||
#define SIDTAB_HASH(sid) \
|
||||
(sid & SIDTAB_HASH_MASK)
|
||||
|
||||
#define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)
|
||||
#define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)
|
||||
#define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)
|
||||
|
||||
int sidtab_init(struct sidtab *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
s->htable = kmalloc(sizeof(*(s->htable)) * SIDTAB_SIZE, GFP_ATOMIC);
|
||||
if (!s->htable)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < SIDTAB_SIZE; i++)
|
||||
s->htable[i] = NULL;
|
||||
s->nel = 0;
|
||||
s->next_sid = 1;
|
||||
s->shutdown = 0;
|
||||
INIT_SIDTAB_LOCK(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
|
||||
{
|
||||
int hvalue, rc = 0;
|
||||
struct sidtab_node *prev, *cur, *newnode;
|
||||
|
||||
if (!s) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hvalue = SIDTAB_HASH(sid);
|
||||
prev = NULL;
|
||||
cur = s->htable[hvalue];
|
||||
while (cur != NULL && sid > cur->sid) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (cur && sid == cur->sid) {
|
||||
rc = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
newnode = kmalloc(sizeof(*newnode), GFP_ATOMIC);
|
||||
if (newnode == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
newnode->sid = sid;
|
||||
if (context_cpy(&newnode->context, context)) {
|
||||
kfree(newnode);
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
newnode->next = prev->next;
|
||||
wmb();
|
||||
prev->next = newnode;
|
||||
} else {
|
||||
newnode->next = s->htable[hvalue];
|
||||
wmb();
|
||||
s->htable[hvalue] = newnode;
|
||||
}
|
||||
|
||||
s->nel++;
|
||||
if (sid >= s->next_sid)
|
||||
s->next_sid = sid + 1;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sidtab_remove(struct sidtab *s, u32 sid)
|
||||
{
|
||||
int hvalue, rc = 0;
|
||||
struct sidtab_node *cur, *last;
|
||||
|
||||
if (!s) {
|
||||
rc = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hvalue = SIDTAB_HASH(sid);
|
||||
last = NULL;
|
||||
cur = s->htable[hvalue];
|
||||
while (cur != NULL && sid > cur->sid) {
|
||||
last = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (cur == NULL || sid != cur->sid) {
|
||||
rc = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (last == NULL)
|
||||
s->htable[hvalue] = cur->next;
|
||||
else
|
||||
last->next = cur->next;
|
||||
|
||||
context_destroy(&cur->context);
|
||||
|
||||
kfree(cur);
|
||||
s->nel--;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct context *sidtab_search(struct sidtab *s, u32 sid)
|
||||
{
|
||||
int hvalue;
|
||||
struct sidtab_node *cur;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
hvalue = SIDTAB_HASH(sid);
|
||||
cur = s->htable[hvalue];
|
||||
while (cur != NULL && sid > cur->sid)
|
||||
cur = cur->next;
|
||||
|
||||
if (cur == NULL || sid != cur->sid) {
|
||||
/* Remap invalid SIDs to the unlabeled SID. */
|
||||
sid = SECINITSID_UNLABELED;
|
||||
hvalue = SIDTAB_HASH(sid);
|
||||
cur = s->htable[hvalue];
|
||||
while (cur != NULL && sid > cur->sid)
|
||||
cur = cur->next;
|
||||
if (!cur || sid != cur->sid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &cur->context;
|
||||
}
|
||||
|
||||
int sidtab_map(struct sidtab *s,
|
||||
int (*apply) (u32 sid,
|
||||
struct context *context,
|
||||
void *args),
|
||||
void *args)
|
||||
{
|
||||
int i, rc = 0;
|
||||
struct sidtab_node *cur;
|
||||
|
||||
if (!s)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < SIDTAB_SIZE; i++) {
|
||||
cur = s->htable[i];
|
||||
while (cur != NULL) {
|
||||
rc = apply(cur->sid, &cur->context, args);
|
||||
if (rc)
|
||||
goto out;
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void sidtab_map_remove_on_error(struct sidtab *s,
|
||||
int (*apply) (u32 sid,
|
||||
struct context *context,
|
||||
void *args),
|
||||
void *args)
|
||||
{
|
||||
int i, ret;
|
||||
struct sidtab_node *last, *cur, *temp;
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
for (i = 0; i < SIDTAB_SIZE; i++) {
|
||||
last = NULL;
|
||||
cur = s->htable[i];
|
||||
while (cur != NULL) {
|
||||
ret = apply(cur->sid, &cur->context, args);
|
||||
if (ret) {
|
||||
if (last) {
|
||||
last->next = cur->next;
|
||||
} else {
|
||||
s->htable[i] = cur->next;
|
||||
}
|
||||
|
||||
temp = cur;
|
||||
cur = cur->next;
|
||||
context_destroy(&temp->context);
|
||||
kfree(temp);
|
||||
s->nel--;
|
||||
} else {
|
||||
last = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline u32 sidtab_search_context(struct sidtab *s,
|
||||
struct context *context)
|
||||
{
|
||||
int i;
|
||||
struct sidtab_node *cur;
|
||||
|
||||
for (i = 0; i < SIDTAB_SIZE; i++) {
|
||||
cur = s->htable[i];
|
||||
while (cur != NULL) {
|
||||
if (context_cmp(&cur->context, context))
|
||||
return cur->sid;
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sidtab_context_to_sid(struct sidtab *s,
|
||||
struct context *context,
|
||||
u32 *out_sid)
|
||||
{
|
||||
u32 sid;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
*out_sid = SECSID_NULL;
|
||||
|
||||
sid = sidtab_search_context(s, context);
|
||||
if (!sid) {
|
||||
SIDTAB_LOCK(s, flags);
|
||||
/* Rescan now that we hold the lock. */
|
||||
sid = sidtab_search_context(s, context);
|
||||
if (sid)
|
||||
goto unlock_out;
|
||||
/* No SID exists for the context. Allocate a new one. */
|
||||
if (s->next_sid == UINT_MAX || s->shutdown) {
|
||||
ret = -ENOMEM;
|
||||
goto unlock_out;
|
||||
}
|
||||
sid = s->next_sid++;
|
||||
ret = sidtab_insert(s, sid, context);
|
||||
if (ret)
|
||||
s->next_sid--;
|
||||
unlock_out:
|
||||
SIDTAB_UNLOCK(s, flags);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*out_sid = sid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sidtab_hash_eval(struct sidtab *h, char *tag)
|
||||
{
|
||||
int i, chain_len, slots_used, max_chain_len;
|
||||
struct sidtab_node *cur;
|
||||
|
||||
slots_used = 0;
|
||||
max_chain_len = 0;
|
||||
for (i = 0; i < SIDTAB_SIZE; i++) {
|
||||
cur = h->htable[i];
|
||||
if (cur) {
|
||||
slots_used++;
|
||||
chain_len = 0;
|
||||
while (cur) {
|
||||
chain_len++;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (chain_len > max_chain_len)
|
||||
max_chain_len = chain_len;
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest "
|
||||
"chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE,
|
||||
max_chain_len);
|
||||
}
|
||||
|
||||
void sidtab_destroy(struct sidtab *s)
|
||||
{
|
||||
int i;
|
||||
struct sidtab_node *cur, *temp;
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
for (i = 0; i < SIDTAB_SIZE; i++) {
|
||||
cur = s->htable[i];
|
||||
while (cur != NULL) {
|
||||
temp = cur;
|
||||
cur = cur->next;
|
||||
context_destroy(&temp->context);
|
||||
kfree(temp);
|
||||
}
|
||||
s->htable[i] = NULL;
|
||||
}
|
||||
kfree(s->htable);
|
||||
s->htable = NULL;
|
||||
s->nel = 0;
|
||||
s->next_sid = 1;
|
||||
}
|
||||
|
||||
void sidtab_set(struct sidtab *dst, struct sidtab *src)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
SIDTAB_LOCK(src, flags);
|
||||
dst->htable = src->htable;
|
||||
dst->nel = src->nel;
|
||||
dst->next_sid = src->next_sid;
|
||||
dst->shutdown = 0;
|
||||
SIDTAB_UNLOCK(src, flags);
|
||||
}
|
||||
|
||||
void sidtab_shutdown(struct sidtab *s)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
SIDTAB_LOCK(s, flags);
|
||||
s->shutdown = 1;
|
||||
SIDTAB_UNLOCK(s, flags);
|
||||
}
|
||||
59
extra/linux-2.6.10/security/selinux/ss/sidtab.h
Normal file
59
extra/linux-2.6.10/security/selinux/ss/sidtab.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* A security identifier table (sidtab) is a hash table
|
||||
* of security context structures indexed by SID value.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_SIDTAB_H_
|
||||
#define _SS_SIDTAB_H_
|
||||
|
||||
#include "context.h"
|
||||
|
||||
struct sidtab_node {
|
||||
u32 sid; /* security identifier */
|
||||
struct context context; /* security context structure */
|
||||
struct sidtab_node *next;
|
||||
};
|
||||
|
||||
#define SIDTAB_HASH_BITS 7
|
||||
#define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS)
|
||||
#define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1)
|
||||
|
||||
#define SIDTAB_SIZE SIDTAB_HASH_BUCKETS
|
||||
|
||||
struct sidtab {
|
||||
struct sidtab_node **htable;
|
||||
unsigned int nel; /* number of elements */
|
||||
unsigned int next_sid; /* next SID to allocate */
|
||||
unsigned char shutdown;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
int sidtab_init(struct sidtab *s);
|
||||
int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);
|
||||
struct context *sidtab_search(struct sidtab *s, u32 sid);
|
||||
|
||||
int sidtab_map(struct sidtab *s,
|
||||
int (*apply) (u32 sid,
|
||||
struct context *context,
|
||||
void *args),
|
||||
void *args);
|
||||
|
||||
void sidtab_map_remove_on_error(struct sidtab *s,
|
||||
int (*apply) (u32 sid,
|
||||
struct context *context,
|
||||
void *args),
|
||||
void *args);
|
||||
|
||||
int sidtab_context_to_sid(struct sidtab *s,
|
||||
struct context *context,
|
||||
u32 *sid);
|
||||
|
||||
void sidtab_hash_eval(struct sidtab *h, char *tag);
|
||||
void sidtab_destroy(struct sidtab *s);
|
||||
void sidtab_set(struct sidtab *dst, struct sidtab *src);
|
||||
void sidtab_shutdown(struct sidtab *s);
|
||||
|
||||
#endif /* _SS_SIDTAB_H_ */
|
||||
|
||||
|
||||
44
extra/linux-2.6.10/security/selinux/ss/symtab.c
Normal file
44
extra/linux-2.6.10/security/selinux/ss/symtab.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Implementation of the symbol table type.
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include "symtab.h"
|
||||
|
||||
static unsigned int symhash(struct hashtab *h, void *key)
|
||||
{
|
||||
char *p, *keyp;
|
||||
unsigned int size;
|
||||
unsigned int val;
|
||||
|
||||
val = 0;
|
||||
keyp = key;
|
||||
size = strlen(keyp);
|
||||
for (p = keyp; (p - keyp) < size; p++)
|
||||
val = (val << 4 | (val >> (8*sizeof(unsigned int)-4))) ^ (*p);
|
||||
return val & (h->size - 1);
|
||||
}
|
||||
|
||||
static int symcmp(struct hashtab *h, void *key1, void *key2)
|
||||
{
|
||||
char *keyp1, *keyp2;
|
||||
|
||||
keyp1 = key1;
|
||||
keyp2 = key2;
|
||||
return strcmp(keyp1, keyp2);
|
||||
}
|
||||
|
||||
|
||||
int symtab_init(struct symtab *s, unsigned int size)
|
||||
{
|
||||
s->table = hashtab_create(symhash, symcmp, size);
|
||||
if (!s->table)
|
||||
return -1;
|
||||
s->nprim = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
23
extra/linux-2.6.10/security/selinux/ss/symtab.h
Normal file
23
extra/linux-2.6.10/security/selinux/ss/symtab.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* A symbol table (symtab) maintains associations between symbol
|
||||
* strings and datum values. The type of the datum values
|
||||
* is arbitrary. The symbol table type is implemented
|
||||
* using the hash table type (hashtab).
|
||||
*
|
||||
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
|
||||
*/
|
||||
#ifndef _SS_SYMTAB_H_
|
||||
#define _SS_SYMTAB_H_
|
||||
|
||||
#include "hashtab.h"
|
||||
|
||||
struct symtab {
|
||||
struct hashtab *table; /* hash table (keyed on a string) */
|
||||
u32 nprim; /* number of primary names in table */
|
||||
};
|
||||
|
||||
int symtab_init(struct symtab *s, unsigned int size);
|
||||
|
||||
#endif /* _SS_SYMTAB_H_ */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user