diff -ruN linux-2.4.23-clean/Documentation/Configure.help linux-2.4.23-medusa/Documentation/Configure.help
--- linux-2.4.23-clean/Documentation/Configure.help 2003-12-08 19:15:19.000000000 +0100
+++ linux-2.4.23-medusa/Documentation/Configure.help 2003-12-08 19:31:37.000000000 +0100
@@ -22985,6 +22985,101 @@
This option allows you to run the kernel with data cache disabled.
Say Y if you experience CPM lock-ups.
+CONFIG_MEDUSA
+ This option provides a facility to improve overall security of
+ Linux by extending its standard security architecture, while
+ remaining fully transparent to the applications. Technically,
+ it's a kernel support of the VS security model (capable of
+ emulating vast majority of current security models), and
+ authorization server, which works with this model. Medusa comes
+ with userspace authorization server named Constable, and few
+ example configurations.
+
+ For more info see README in the source package, and
+ .
+
+CONFIG_MEDUSA_SYSCALL
+ This option allows the authorization server to check any system
+ call and its parameters. This is very low-level and it is
+ currently implemented only on the i386 architecture. On the
+ other side, it is a very useful feature and is used in many
+ configuration files.
+
+ If in doubt, say Y.
+
+CONFIG_MEDUSA_FORCE
+ This powerful option makes it possible to force execution of the
+ arbitrary code to any process. This option currently works only
+ on the i386 architecture.
+
+ Answer Y only if you really need it, otherwise answer N.
+
+CONFIG_MEDUSA_CONSTABLE
+ Say Y, if you will be using the user-space authorization
+ daemon, which communicates with kernel via character device
+ named /dev/medusa. This is how our official authorization
+ daemon Constable does it, so it is recommended to answer Y.
+
+ Don't answer M, unless you really want the support for Constable
+ to be built as a module (that way you will be unable to start
+ Constable at the boot time).
+
+ If in doubt, say Y.
+
+CONFIG_MEDUSA_INIT_WRAPPER
+ Say Y here, if you want the kernel to execute the Constable
+ immediately after bootup. If you say Y here, the Constable will
+ initialize, THEN launch the usual init application.
+ Note that Constable have to be installed at /sbin, /etc or /bin.
+
+ This is preferred, when you have a working configuration file.
+ If you are just preparing to make one, say N.
+
+CONFIG_MEDUSA_ON_NFS
+ Enabling this allows you to use Medusa file redirections to NFS
+ filesystem. Being a small hack, we created a separate config option
+ for it.
+
+ Say Y only if you need to use file redirections to NFS filesystem.
+ Otherwise say N.
+
+CONFIG_MEDUSA_NONE
+ If you say "Ignore", the system will remain fully functional
+ after the authorization server has died. Note that this may introduce
+ a security risk, and is recommended only for the configuration time,
+ to enable testing of multiple configurations.
+
+ If you say "Reboot" or "Halt", the system will reboot or halt,
+ when the authorization server dies.
+
+ If you require minumum downtime, choose "Reboot".
+ If you have the acess to your server, or don't mind your downtime,
+ choose "Halt" instead.
+ If you are just about to play with your configuration, choose "Ignore".
+
+CONFIG_MEDUSA_QUIET
+ This option prevents Medusa from displaying any kernel messages.
+
+ If you want to hide Medusa on your machine, answer Y.
+ If in doubt, say N.
+
+CONFIG_MEDUSA_MEMKOBJECT
+ This enables the authorization server to access a memory of any
+ desired user-space process. This is not a security improvement itself,
+ it is just needed by some of the security models you might want to use.
+ Note that if you will compile this as a module, it will not be loaded
+ automatically on demand - you still have to insmod it manually.
+
+ If in doubt, say Y.
+
+CONFIG_MEDUSA_FILE_CAPABILITIES
+ This option enables you to set POSIX capabilities for files.
+ Note that you can set process capabilities even with this option
+ turned off.
+
+ Answer N, unless you really know what are you doing.
+
+
#
# m68k-specific kernel options
# Documented by Chris Lawrence et al.
diff -ruN linux-2.4.23-clean/MAINTAINERS linux-2.4.23-medusa/MAINTAINERS
--- linux-2.4.23-clean/MAINTAINERS 2003-12-08 19:15:19.000000000 +0100
+++ linux-2.4.23-medusa/MAINTAINERS 2003-12-08 19:31:37.000000000 +0100
@@ -1155,6 +1155,16 @@
L: linux-fbdev-devel@lists.sourceforge.net
S: Maintained
+MEDUSA DS9 SECURITY SYSTEM
+P: Milan Pikula
+M: www@terminus.sk
+P: Marek Zelem
+P: Martin Ockajak
+M: medusa-devel@terminus.sk
+L: medusa@medusa.terminus.sk
+W: http://medusa.terminus.sk/
+S: Maintained
+
MEMORY TECHNOLOGY DEVICES
P: David Woodhouse
M: dwmw2@redhat.com
diff -ruN linux-2.4.23-clean/Makefile linux-2.4.23-medusa/Makefile
--- linux-2.4.23-clean/Makefile 2003-12-08 19:15:19.000000000 +0100
+++ linux-2.4.23-medusa/Makefile 2003-12-08 19:31:37.000000000 +0100
@@ -130,6 +130,11 @@
LIBS =$(TOPDIR)/lib/lib.a
SUBDIRS =kernel drivers mm fs net ipc lib crypto
+ifdef CONFIG_MEDUSA
+CORE_FILES += medusa/medusa.o
+SUBDIRS += medusa
+endif
+
DRIVERS-n :=
DRIVERS-y :=
DRIVERS-m :=
@@ -371,7 +376,7 @@
init/do_mounts.o: init/do_mounts.c include/config/MARKER
$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o $@ $<
-fs lib mm ipc kernel drivers net: dummy
+fs lib mm ipc kernel drivers net medusa: dummy
$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
TAGS: dummy
diff -ruN linux-2.4.23-clean/arch/i386/Makefile linux-2.4.23-medusa/arch/i386/Makefile
--- linux-2.4.23-clean/arch/i386/Makefile 2003-06-13 16:51:29.000000000 +0200
+++ linux-2.4.23-medusa/arch/i386/Makefile 2003-12-08 19:31:37.000000000 +0100
@@ -96,7 +96,7 @@
HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
-SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib
+SUBDIRS += arch/i386/tools arch/i386/kernel arch/i386/mm arch/i386/lib
CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES)
LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a
@@ -148,6 +148,7 @@
archclean:
@$(MAKEBOOT) clean
+ @$(MAKE) -C arch/$(ARCH)/tools clean
archmrproper:
diff -ruN linux-2.4.23-clean/arch/i386/config.in linux-2.4.23-medusa/arch/i386/config.in
--- linux-2.4.23-clean/arch/i386/config.in 2003-12-08 19:15:19.000000000 +0100
+++ linux-2.4.23-medusa/arch/i386/config.in 2003-12-08 19:31:37.000000000 +0100
@@ -14,6 +14,8 @@
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
+ source medusa/Config.in
+
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
diff -ruN linux-2.4.23-clean/arch/i386/kernel/Makefile linux-2.4.23-medusa/arch/i386/kernel/Makefile
--- linux-2.4.23-clean/arch/i386/kernel/Makefile 2003-12-08 19:15:19.000000000 +0100
+++ linux-2.4.23-medusa/arch/i386/kernel/Makefile 2003-12-08 19:31:37.000000000 +0100
@@ -44,4 +44,11 @@
obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
obj-$(CONFIG_EDD) += edd.o
+entry.o: $(TOPDIR)/include/asm-i386/offsets.h
+
+$(TOPDIR)/include/asm-i386/offsets.h: $(TOPDIR)/arch/i386/tools/printoffset
+
+$(TOPDIR)/arch/i386/tools/printoffset:
+ $(MAKE) -C $(TOPDIR)/arch/i386/tools
+
include $(TOPDIR)/Rules.make
diff -ruN linux-2.4.23-clean/arch/i386/kernel/entry.S linux-2.4.23-medusa/arch/i386/kernel/entry.S
--- linux-2.4.23-clean/arch/i386/kernel/entry.S 2003-06-13 16:51:29.000000000 +0200
+++ linux-2.4.23-medusa/arch/i386/kernel/entry.S 2003-12-08 19:31:37.000000000 +0100
@@ -72,14 +72,8 @@
/*
* these are offsets into the task-struct.
*/
-state = 0
-flags = 4
-sigpending = 8
-addr_limit = 12
-exec_domain = 16
-need_resched = 20
-tsk_ptrace = 24
-processor = 52
+
+#include
ENOSYS = 38
@@ -207,7 +201,29 @@
jne tracesys
cmpl $(NR_syscalls),%eax
jae badsys
+
+#ifdef CONFIG_MEDUSA_SYSCALL
+ /* cannot change: eax=syscall, ebx=current */
+ btl %eax,med_syscall(%ebx)
+ jnc 1f
+ pushl %ebx
+ pushl %eax
+ call SYMBOL_NAME(medusa_syscall_i386)
+ cmpl $1, %eax
+ popl %eax
+ popl %ebx
+ jc 3f
+ /* jne 2f */
+1: /* here used to be the ptrace-skip code. this is no longer
+2: possible with new trace semantics */
+#endif
+
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
+
+#ifdef CONFIG_MEDUSA_SYSCALL
+3:
+#endif
+
movl %eax,EAX(%esp) # save the return value
ENTRY(ret_from_sys_call)
cli # need_resched and signals atomic test
@@ -243,7 +259,26 @@
movl ORIG_EAX(%esp),%eax
cmpl $(NR_syscalls),%eax
jae tracesys_exit
+
+#ifdef CONFIG_MEDUSA_SYSCALL
+ /* cannot change: eax=syscall, ebx=current */
+ btl %eax,med_syscall(%ebx)
+ jnc 1f
+ pushl %ebx
+ pushl %eax
+ call SYMBOL_NAME(medusa_syscall_i386)
+ cmpl $1, %eax
+ popl %eax
+ popl %ebx
+ jc 3f
+ jne 2f
+1: /* here used to be the ptrace-skip code. this is no longer */
+2: /* possible with new trace semantics */
+#endif
call *SYMBOL_NAME(sys_call_table)(,%eax,4)
+#ifdef CONFIG_MEDUSA_SYSCALL
+3:
+#endif
movl %eax,EAX(%esp) # save the return value
tracesys_exit:
call SYMBOL_NAME(syscall_trace)
diff -ruN linux-2.4.23-clean/arch/i386/kernel/process.c linux-2.4.23-medusa/arch/i386/kernel/process.c
--- linux-2.4.23-clean/arch/i386/kernel/process.c 2003-12-08 19:15:19.000000000 +0100
+++ linux-2.4.23-medusa/arch/i386/kernel/process.c 2003-12-08 19:31:37.000000000 +0100
@@ -52,6 +52,10 @@
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
int hlt_counter;
@@ -507,6 +511,14 @@
/* Load the argument into eax, and push it. That way, it does
* not matter whether the called function is compiled with
* -mregparm or not. */
+#ifdef CONFIG_MEDUSA
+ "pushl %%eax\n\tpushl %%ebx\n\tpushl %%ecx\n\tpushl %%edx\n\t"
+ "movl %5,%%eax\n\t"
+ "pushl %%eax\n\t"
+ "call medusa_kernel_thread\n\t" /* call medusa */
+ "popl %%eax\n\t"
+ "popl %%edx\n\tpopl %%ecx\n\tpopl %%ebx\n\tpopl %%eax\n\t"
+#endif /* CONFIG_MEDUSA */
"movl %4,%%eax\n\t"
"pushl %%eax\n\t"
"call *%5\n\t" /* call fn */
diff -ruN linux-2.4.23-clean/arch/i386/kernel/ptrace.c linux-2.4.23-medusa/arch/i386/kernel/ptrace.c
--- linux-2.4.23-clean/arch/i386/kernel/ptrace.c 2002-08-03 02:39:42.000000000 +0200
+++ linux-2.4.23-medusa/arch/i386/kernel/ptrace.c 2003-12-08 19:31:37.000000000 +0100
@@ -14,6 +14,10 @@
#include
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
#include
#include
#include
@@ -153,6 +157,24 @@
struct user * dummy = NULL;
int i, ret;
+#ifdef CONFIG_MEDUSA
+ /* we need to get called BEFORE the kernel lock */
+ if (request != PTRACE_TRACEME) {
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ return -ESRCH;
+ if (medusa_ptrace(current, child) == MED_NO) {
+ free_task_struct(child);
+ return -EPERM;
+ }
+ }
+#define out out_tsk
+#endif /* CONFIG_MEDUSA */
+
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
@@ -164,6 +186,9 @@
ret = 0;
goto out;
}
+#ifdef CONFIG_MEDUSA
+#undef out
+#else
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
@@ -172,6 +197,7 @@
read_unlock(&tasklist_lock);
if (!child)
goto out;
+#endif
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
@@ -435,6 +461,11 @@
if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
(PT_PTRACED|PT_TRACESYS))
return;
+#ifdef CONFIG_MEDUSA
+ if (medusa_ptrace(current->p_pptr, current) == MED_NO)
+ return;
+#endif /* CONFIG_MEDUSA */
+
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
diff -ruN linux-2.4.23-clean/arch/i386/kernel/signal.c linux-2.4.23-medusa/arch/i386/kernel/signal.c
--- linux-2.4.23-clean/arch/i386/kernel/signal.c 2002-08-03 02:39:42.000000000 +0200
+++ linux-2.4.23-medusa/arch/i386/kernel/signal.c 2003-12-08 19:31:37.000000000 +0100
@@ -20,6 +20,10 @@
#include
#include
#include
+#ifdef CONFIG_MEDUSA
+#include
+#include
+#endif
#include
#include
#include
@@ -391,11 +395,30 @@
struct sigframe *frame;
int err = 0;
+#ifdef CONFIG_MEDUSA_FORCE
+ if (sig < 0) {
+ frame = get_sigframe(ka, regs, sizeof(*frame)-sig);
+ printk("get_sigframe %x %x %d\n",
+ ((unsigned char *)ka)[0],
+ ((unsigned char *)ka)[1],
+ -sig);
+ }
+ else
+#endif /* CONFIG_MEDUSA_FORCE */
frame = get_sigframe(ka, regs, sizeof(*frame));
+#ifdef CONFIG_MEDUSA_FORCE
+ if (sig < 0) {
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)-sig))
+ goto give_sigsegv;
+ } else
+#endif /* CONFIG_MEDUSA_FORCE */
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
+#ifdef CONFIG_MEDUSA_FORCE
+ if (sig >= 0)
+#endif /* CONFIG_MEDUSA_FORCE */
err |= __put_user((current->exec_domain
&& current->exec_domain->signal_invmap
&& sig < 32
@@ -418,7 +441,11 @@
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
+#ifdef CONFIG_MEDUSA_FORCE
+ if ((sig >= 0) && (ka->sa.sa_flags & SA_RESTORER)) {
+#else
if (ka->sa.sa_flags & SA_RESTORER) {
+#endif /* CONFIG_MEDUSA_FORCE */
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
} else {
err |= __put_user(frame->retcode, &frame->pretcode);
@@ -427,12 +454,22 @@
err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2));
err |= __put_user(0x80cd, (short *)(frame->retcode+6));
}
+#ifdef CONFIG_MEDUSA_FORCE
+ if (sig < 0) {
+ err |= __copy_to_user((void *)((unsigned long)frame+sizeof(*frame)), (void *)ka, -sig);
+ }
+#endif /* CONFIG_MEDUSA_FORCE */
if (err)
goto give_sigsegv;
/* Set up registers for signal handler */
regs->esp = (unsigned long) frame;
+#ifdef CONFIG_MEDUSA_FORCE
+ if (sig < 0)
+ regs->eip = (unsigned long)frame+sizeof(*frame);
+ else
+#endif /* CONFIG_MEDUSA_FORCE */
regs->eip = (unsigned long) ka->sa.sa_handler;
set_fs(USER_DS);
@@ -598,6 +635,47 @@
if (!oldset)
oldset = ¤t->blocked;
+#ifdef CONFIG_MEDUSA_FORCE
+ if (current->med.force_code) {
+ void * force_code;
+ int force_len;
+
+ printk("LAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAA\n");
+
+/****** XXX STOLEN FROM THE CODE ABOVE ********/
+ /* Are we from a system call? */
+ if (regs->orig_eax >= 0) {
+ /* If so, check system call restarting.. */
+ switch (regs->eax) {
+ case -ERESTARTNOHAND:
+ regs->eax = -EINTR;
+ break;
+
+ case -ERESTARTSYS: /* restartne nam syscall */
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->eax = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ regs->eax = regs->orig_eax;
+ regs->eip -= 2;
+ }
+ }
+/****** END OF STOLEN CODE ********/
+ spin_lock_irq(¤t->sigmask_lock);
+ force_code = current->med.force_code;
+ force_len = current->med.force_len;
+ current->med.force_code = NULL;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ /* we don't care about real-time processes */
+ setup_frame(-force_len, force_code, oldset, regs);
+ kfree(force_code);
+ return 1;
+ }
+#endif
for (;;) {
unsigned long signr;
diff -ruN linux-2.4.23-clean/arch/i386/tools/Makefile linux-2.4.23-medusa/arch/i386/tools/Makefile
--- linux-2.4.23-clean/arch/i386/tools/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/arch/i386/tools/Makefile 2003-12-08 19:31:37.000000000 +0100
@@ -0,0 +1,18 @@
+# Makefile for i386 kernel build tools
+
+TARGET=$(TOPDIR)/include/asm-$(ARCH)/offsets.h
+
+offsets all: $(TARGET)
+
+$(TARGET): printoffsets
+ ./printoffsets > $(TARGET)
+
+printoffsets: printoffsets.o
+ $(CC) $(CFLAGS) $^ -o $@
+
+printoffsets.o: $(TOPDIR)/include/linux/sched.h
+
+clean:
+ rm -f $(TARGET) printoffsets
+
+include $(TOPDIR)/Rules.make
diff -ruN linux-2.4.23-clean/arch/i386/tools/printoffsets.c linux-2.4.23-medusa/arch/i386/tools/printoffsets.c
--- linux-2.4.23-clean/arch/i386/tools/printoffsets.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/arch/i386/tools/printoffsets.c 2003-12-08 19:31:37.000000000 +0100
@@ -0,0 +1,40 @@
+#define _LOOSE_KERNEL_NAMES
+#include
+#include
+
+#define OFFSET(structure, member) ((unsigned long)(&(((structure *)NULL)->member)))
+
+struct i386_offset {
+ const char identifier[64];
+ unsigned long value;
+} offsets[] = {
+ { "state", OFFSET(struct task_struct, state) },
+ { "flags", OFFSET(struct task_struct, flags), },
+ { "sigpending", OFFSET(struct task_struct, sigpending), },
+ { "addr_limit", OFFSET(struct task_struct, addr_limit), },
+ { "exec_domain", OFFSET(struct task_struct, exec_domain), },
+ { "need_resched", OFFSET(struct task_struct, need_resched), },
+ { "tsk_ptrace", OFFSET(struct task_struct, ptrace), },
+ { "processor", OFFSET(struct task_struct, processor), },
+#ifdef CONFIG_MEDUSA_SYSCALL
+ { "med_syscall", OFFSET(struct task_struct, med.med_syscall) }
+#endif
+};
+
+extern int printf (const char *, ...);
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ printf("#ifndef _I386_OFFSETS_H_\n#define _I386_OFFSETS_H_\n\n");
+ printf("/* \n");
+ printf(" * offsets for i386\n");
+ printf(" * DO NOT TOUCH\n");
+ printf(" * generated by arch/i386/tools/print_offset.c\n");
+ printf(" */\n\n");
+ for(i = 0; i < (sizeof(offsets) / sizeof(struct i386_offset)); i++)
+ printf("%s =\t%lu\n", offsets[i].identifier, offsets[i].value);
+ printf("\n#endif\n");
+ return 0;
+}
diff -ruN linux-2.4.23-clean/fs/attr.c linux-2.4.23-medusa/fs/attr.c
--- linux-2.4.23-clean/fs/attr.c 2002-02-25 20:38:07.000000000 +0100
+++ linux-2.4.23-medusa/fs/attr.c 2003-12-08 19:31:37.000000000 +0100
@@ -13,6 +13,10 @@
#include
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
/* Taken over from the old code... */
/* POSIX UID/GID verification for setting inode attributes. */
@@ -127,6 +131,10 @@
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_notify_change(dentry,attr)) == MED_NO)
+ return -EPERM;
+#endif /* CONFIG_MEDUSA */
lock_kernel();
if (inode->i_op && inode->i_op->setattr)
error = inode->i_op->setattr(dentry, attr);
diff -ruN linux-2.4.23-clean/fs/exec.c linux-2.4.23-medusa/fs/exec.c
--- linux-2.4.23-clean/fs/exec.c 2003-12-08 19:15:44.000000000 +0100
+++ linux-2.4.23-medusa/fs/exec.c 2003-12-08 19:31:37.000000000 +0100
@@ -20,6 +20,10 @@
* table to check for several different types of binary formats. We keep
* trying until we recognize the file or we run out of supported binary
* formats.
+ *
+ * Modified formula for evolving capabilities to allow nice SUID emulation
+ * which work together with (future) VFS capabilities implementation.
+ * Feb 2002 by Marek Zelem
*/
#include
@@ -53,6 +57,12 @@
int core_setuid_ok = 0;
/* The maximal length of core_pattern is also specified in sysctl.c */
+#include
+#ifdef CONFIG_MEDUSA
+#include
+#include
+#endif /* CONFIG_MEDUSA */
+
static struct linux_binfmt *formats;
static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED;
@@ -382,7 +392,19 @@
file = ERR_PTR(-EACCES);
if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
S_ISREG(inode->i_mode)) {
+#ifdef CONFIG_MEDUSA
+ int err;
+ if ((err = medusa_exec(&(nd.dentry))) == MED_NO) {
+ path_release(&nd);
+ return ERR_PTR(-EPERM);
+ }
+ if (err == MED_YES)
+ err = 0;
+ else
+ err = permission(inode, MAY_EXEC);
+#else
int err = permission(inode, MAY_EXEC);
+#endif /* CONFIG_MEDUSA */
if (!err && !(inode->i_mode & 0111))
err = -EACCES;
file = ERR_PTR(err);
@@ -668,11 +690,23 @@
bprm->e_uid = current->euid;
bprm->e_gid = current->egid;
+ /* We don't have VFS support for capabilities yet */
+ cap_clear(bprm->cap_permitted);
+ cap_set_full(bprm->cap_inheritable);
+ cap_set_full(bprm->cap_effective);
+
if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) {
/* Set-uid? */
- if (mode & S_ISUID)
+ if (mode & S_ISUID) {
bprm->e_uid = inode->i_uid;
-
+ if (bprm->e_uid == 0) {
+ if (!issecure(SECURE_NOROOT))
+ cap_set_full(bprm->cap_permitted);
+ }
+ else {
+ cap_clear(bprm->cap_effective);
+ }
+ }
/* Set-gid? */
/*
* If setgid is set but no group execute bit then this
@@ -683,27 +717,47 @@
bprm->e_gid = inode->i_gid;
}
- /* We don't have VFS support for capabilities yet */
- cap_clear(bprm->cap_inheritable);
- cap_clear(bprm->cap_permitted);
- cap_clear(bprm->cap_effective);
+#ifdef CONFIG_MEDUSA_FILE_CAPABILITIES
+ if (MED_MAGIC_VALID(&inode->med) ||
+ file_kobj_validate_dentry(bprm->file->f_dentry,NULL) > 0) {
+ /* If the security daemon sets the file capabilities, use them */
+ cap_t(bprm->cap_inheritable) = cap_t(inode->med.icap);
+ cap_t(bprm->cap_permitted) = cap_t(inode->med.pcap);
+ cap_t(bprm->cap_effective) = cap_t(inode->med.ecap);
+ }
+#endif /* CONFIG_MEDUSA_FILE_CAPABILITIES */
- /* 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);
+#ifdef CONFIG_MEDUSA
+ {
+ int retval;
+#ifndef CONFIG_MEDUSA_FILE_CAPABILITIES
+ kernel_cap_t new_permitted, working;
+
+/* Privilege elevation check copied from compute_creds() */
+ 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);
+#endif
+ if (bprm->e_uid != current->uid || bprm->e_gid != current->gid
+#ifndef CONFIG_MEDUSA_FILE_CAPABILITIES
+ || !cap_issubset(new_permitted, current->cap_permitted)
+#endif
+ ) {
+ if ((retval = medusa_sexec(bprm)) == MED_NO)
+ return -EPERM;
+ if (retval == MED_SKIP) {
+ bprm->e_uid = current->euid;
+ bprm->e_gid = current->egid;
+#ifndef CONFIG_MEDUSA_FILE_CAPABILITIES
+ cap_clear(bprm->cap_inheritable);
+ bprm->cap_permitted = current->cap_permitted;
+ bprm->cap_effective = current->cap_effective;
+#endif
+ }
}
- if (bprm->e_uid == 0)
- cap_set_full(bprm->cap_effective);
}
+#endif /* CONFIG_MEDUSA */
memset(bprm->buf,0,BINPRM_BUF_SIZE);
return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
@@ -715,6 +769,11 @@
*
* The formula used for evolving capabilities is:
*
+ * (***) pP' = (fP & X) | (fI & pI)
+ * pI' = pP'
+ * pE' = ((pP' & pE) | fP) & X & fE
+ *
+ * original was:
* pI' = pI
* (***) pP' = (fP & X) | (fI & pI)
* pE' = pP' & fE [NB. fE is 0 or ~0]
@@ -761,6 +820,14 @@
* capability rules */
if (current->pid != 1) {
current->cap_permitted = new_permitted;
+/* This is to allow good SUID emulation (Marek Zelem ) */
+ current->cap_inheritable = new_permitted;
+ working =
+ cap_intersect(new_permitted,current->cap_effective);
+ new_permitted =
+ cap_combine(working,bprm->cap_permitted);
+ new_permitted = cap_intersect(new_permitted, cap_bset);
+/* END of good SUID emulation (Marek Zelem ) */
current->cap_effective =
cap_intersect(new_permitted, bprm->cap_effective);
}
@@ -947,7 +1014,25 @@
if (retval < 0)
goto out;
+#ifdef CONFIG_MEDUSA
+ { int flagp, flaga;
+ flagp = medusa_monitored_pexec();
+ medusa_monitor_pexec(0);
+ flaga = medusa_monitored_afterexec();
+ medusa_monitor_afterexec(0);
+#endif /* CONFIG_MEDUSA */
retval = search_binary_handler(&bprm,regs);
+#ifdef CONFIG_MEDUSA
+ medusa_monitor_afterexec(flaga);
+ medusa_monitor_pexec(flagp);
+ }
+#endif /* CONFIG_MEDUSA */
+
+#ifdef CONFIG_MEDUSA
+ if (retval >= 0)
+ medusa_afterexec(filename, argv, envp);
+#endif /* CONFIG_MEDUSA */
+
if (retval >= 0)
/* execve success */
return retval;
diff -ruN linux-2.4.23-clean/fs/inode.c linux-2.4.23-medusa/fs/inode.c
--- linux-2.4.23-clean/fs/inode.c 2003-12-08 19:15:44.000000000 +0100
+++ linux-2.4.23-medusa/fs/inode.c 2003-12-08 19:31:37.000000000 +0100
@@ -5,6 +5,9 @@
*/
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
#include
#include
#include
@@ -117,6 +120,9 @@
mapping->host = inode;
mapping->gfp_mask = GFP_HIGHUSER;
inode->i_mapping = mapping;
+#ifdef CONFIG_MEDUSA
+ medusa_clean_inode(inode);
+#endif /* CONFIG_MEDUSA */
}
return inode;
}
diff -ruN linux-2.4.23-clean/fs/namei.c linux-2.4.23-medusa/fs/namei.c
--- linux-2.4.23-clean/fs/namei.c 2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.23-medusa/fs/namei.c 2003-12-08 19:31:37.000000000 +0100
@@ -26,6 +26,11 @@
#include
#include
+#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
/* [Feb-1997 T. Schoebel-Theuer]
@@ -198,6 +203,13 @@
int permission(struct inode * inode,int mask)
{
+#ifdef CONFIG_MEDUSA
+ int r;
+ if ((r = medusa_permission(inode, mask)) == MED_NO)
+ return -EACCES;
+ if (r == MED_YES)
+ return 0;
+#endif /* CONFIG_MEDUSA */
if (inode->i_op && inode->i_op->permission) {
int retval;
lock_kernel();
@@ -264,6 +276,11 @@
{
struct dentry * dentry = d_lookup(parent, name);
+#ifdef CONFIG_MEDUSA
+ if (dentry/*speedup*/ && parent->d_inode &&
+ !MED_MAGIC_VALID(&parent->d_inode->med))
+ file_kobj_validate_dentry(parent, NULL);
+#endif /* CONFIG_MEDUSA */
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
dput(dentry);
@@ -530,6 +547,19 @@
/* Check mountpoints.. */
while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
;
+#ifdef CONFIG_MEDUSA
+ {
+ int ret;
+ if ((ret = medusa_lookup(nd->dentry->d_inode, &dentry)) == MED_NO) {
+ err = -EPERM;
+ goto out_dput;
+ }
+ if (ret == MED_SKIP) {
+ err = -ENOENT;
+ goto out_dput;
+ }
+ }
+#endif /* CONFIG_MEDUSA */
err = -ENOENT;
inode = dentry->d_inode;
@@ -592,6 +622,19 @@
}
while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
;
+#ifdef CONFIG_MEDUSA
+ {
+ int ret;
+ if ((ret = medusa_lookup(nd->dentry->d_inode, &dentry)) == MED_NO) {
+ err = -EPERM;
+ goto out_dput;
+ }
+ if (ret == MED_SKIP) {
+ err = -ENOENT;
+ goto out_dput;
+ }
+ }
+#endif /* CONFIG_MEDUSA */
inode = dentry->d_inode;
if ((lookup_flags & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) {
@@ -964,6 +1007,12 @@
mode &= S_IALLUGO;
mode |= S_IFREG;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_create(dentry, mode)) == MED_NO)
+ return -EACCES;
+ if (error == MED_SKIP)
+ return 0;
+#endif /* CONFIG_MEDUSA */
down(&dir->i_zombie);
error = may_create(dir, dentry);
if (error)
@@ -1076,6 +1125,19 @@
goto exit_dput;
while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
}
+#ifdef CONFIG_MEDUSA
+ {
+ int ret;
+ if ((ret = medusa_lookup(nd->dentry->d_inode, &dentry)) == MED_NO) {
+ error = -EPERM;
+ goto exit_dput;
+ }
+ if (ret == MED_SKIP) {
+ error = -ENOENT;
+ goto exit_dput;
+ }
+ }
+#endif /* CONFIG_MEDUSA */
error = -ENOENT;
if (!dentry->d_inode)
goto exit_dput;
@@ -1238,6 +1300,10 @@
{
int error = -EPERM;
+#ifdef CONFIG_MEDUSA
+ if(medusa_mknod(dentry, dev, mode) == MED_NO)
+ return error;
+#endif /* CONFIG_MEDUSA */
down(&dir->i_zombie);
if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
goto exit_lock;
@@ -1309,6 +1375,11 @@
{
int error;
+#ifdef CONFIG_MEDUSA
+ error = medusa_mkdir(dentry, mode);
+ if(error == MED_NO)
+ return -EPERM;
+#endif /* CONFIG_MEDUSA */
down(&dir->i_zombie);
error = may_create(dir, dentry);
if (error)
@@ -1397,6 +1468,12 @@
{
int error;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_rmdir(dentry)) == MED_NO)
+ return -EPERM;
+ if (error == MED_SKIP)
+ return 0;
+#endif /* CONFIG_MEDUSA */
error = may_delete(dir, dentry, 1);
if (error)
return error;
@@ -1472,6 +1549,12 @@
{
int error;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_unlink(dentry)) == MED_NO)
+ return -EPERM;
+ if (error == MED_SKIP)
+ return 0;
+#endif /* CONFIG_MEDUSA */
down(&dir->i_zombie);
error = may_delete(dir, dentry, 0);
if (!error) {
@@ -1541,6 +1624,10 @@
{
int error;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_symlink(dentry, oldname)) == MED_NO)
+ return -EPERM;
+#endif /* CONFIG_MEDUSA */
down(&dir->i_zombie);
error = may_create(dir, dentry);
if (error)
@@ -1667,6 +1754,14 @@
new_dentry = lookup_create(&nd, 0);
error = PTR_ERR(new_dentry);
if (!IS_ERR(new_dentry)) {
+#ifdef CONFIG_MEDUSA /* FIXME - move me to the VFS layer */
+ error = medusa_link(old_nd.dentry, newname);
+ if (error == MED_NO)
+ error = -EPERM;
+ else if (error == MED_SKIP)
+ error = 0;
+ else
+#endif /* CONFIG_MEDUSA */
error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
dput(new_dentry);
}
@@ -1716,6 +1811,13 @@
if (old_dentry->d_inode == new_dentry->d_inode)
return 0;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_rename(old_dentry, new_dentry->d_name.name)) == MED_NO)
+ return -EPERM;
+ if (error == MED_SKIP)
+ return 0;
+#endif /* CONFIG_MEDUSA */
+
error = may_delete(old_dir, old_dentry, 1);
if (error)
return error;
@@ -1794,6 +1896,13 @@
if (old_dentry->d_inode == new_dentry->d_inode)
return 0;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_rename(old_dentry, new_dentry->d_name.name)) == MED_NO)
+ return -EPERM;
+ if (error == MED_SKIP)
+ return 0;
+#endif /* CONFIG_MEDUSA */
+
error = may_delete(old_dir, old_dentry, 0);
if (error)
return error;
diff -ruN linux-2.4.23-clean/fs/open.c linux-2.4.23-medusa/fs/open.c
--- linux-2.4.23-clean/fs/open.c 2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.23-medusa/fs/open.c 2003-12-08 19:31:37.000000000 +0100
@@ -20,6 +20,10 @@
#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
int vfs_statfs(struct super_block *sb, struct statfs *buf)
{
int retval = -ENODEV;
@@ -105,6 +109,12 @@
if (length < 0)
return -EINVAL;
+#ifdef CONFIG_MEDUSA
+ if ((error = medusa_truncate(dentry, length)) == MED_NO)
+ return -EPERM;
+ if (error == MED_SKIP)
+ return 0;
+#endif /* CONFIG_MEDUSA */
down_write(&inode->i_alloc_sem);
down(&inode->i_sem);
newattrs.ia_size = length;
diff -ruN linux-2.4.23-clean/fs/proc/base.c linux-2.4.23-medusa/fs/proc/base.c
--- linux-2.4.23-clean/fs/proc/base.c 2003-12-08 19:15:44.000000000 +0100
+++ linux-2.4.23-medusa/fs/proc/base.c 2003-12-08 19:31:37.000000000 +0100
@@ -26,6 +26,10 @@
#include
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
/*
* For hysterical raisins we keep the same inumbers as in the old procfs.
* Feel free to change the macro below - just keep the range distinct from
@@ -432,7 +436,7 @@
return copied;
}
-#define mem_write NULL
+//#define mem_write NULL
#ifndef mem_write
/* This is a security hazard */
@@ -1072,6 +1076,11 @@
read_lock(&tasklist_lock);
task = find_task_by_pid(pid);
+#ifdef CONFIG_MEDUSA
+ if (task && !VS_INTERSECT(VSS(¤t->med),VS(&task->med)) &&
+ current->pid > 1 && task->pid > 1)
+ task = NULL;
+#endif /* CONFIG_MEDUSA */
if (task)
get_task_struct(task);
read_unlock(&tasklist_lock);
@@ -1124,6 +1133,11 @@
int pid = p->pid;
if (!pid)
continue;
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&p->med)) &&
+ p->pid > 1 && current->pid > 1)
+ continue;
+#endif /* CONFIG_MEDUSA */
if (--index >= 0)
continue;
pids[nr_pids] = pid;
diff -ruN linux-2.4.23-clean/fs/read_write.c linux-2.4.23-medusa/fs/read_write.c
--- linux-2.4.23-clean/fs/read_write.c 2003-08-25 13:44:43.000000000 +0200
+++ linux-2.4.23-medusa/fs/read_write.c 2003-12-08 19:31:37.000000000 +0100
@@ -27,6 +27,11 @@
#include
#include
+#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
#include
struct file_operations generic_ro_fops = {
@@ -167,6 +172,17 @@
ret = -EBADF;
file = fget(fd);
if (file) {
+#ifdef CONFIG_MEDUSA
+ int r;
+ if ((r = medusa_read(file)) == MED_NO) {
+ fput(file);
+ return -EACCES;
+ }
+ if (r == MED_SKIP) {
+ fput(file);
+ return count;
+ }
+#endif /* CONFIG_MEDUSA */
if (file->f_mode & FMODE_READ) {
ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
file, file->f_pos, count);
@@ -192,6 +208,17 @@
ret = -EBADF;
file = fget(fd);
if (file) {
+#ifdef CONFIG_MEDUSA
+ int r;
+ if ((r = medusa_write(file)) == MED_NO) {
+ fput(file);
+ return -EACCES;
+ }
+ if (r == MED_SKIP) {
+ fput(file);
+ return count;
+ }
+#endif /* CONFIG_MEDUSA */
if (file->f_mode & FMODE_WRITE) {
struct inode *inode = file->f_dentry->d_inode;
ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
@@ -337,6 +364,19 @@
file = fget(fd);
if (!file)
goto bad_file;
+#ifdef CONFIG_MEDUSA
+ {
+ int r;
+ if ((r = medusa_read(file)) == MED_NO) {
+ fput(file);
+ return -EACCES;
+ }
+ if (r == MED_SKIP) {
+ fput(file);
+ return count;
+ }
+ }
+#endif /* CONFIG_MEDUSA */
if (file->f_op && (file->f_mode & FMODE_READ) &&
(file->f_op->readv || file->f_op->read))
ret = do_readv_writev(VERIFY_WRITE, file, vector, count);
@@ -357,6 +397,19 @@
file = fget(fd);
if (!file)
goto bad_file;
+#ifdef CONFIG_MEDUSA
+ {
+ int r;
+ if ((r = medusa_write(file)) == MED_NO) {
+ fput(file);
+ return -EACCES;
+ }
+ if (r == MED_SKIP) {
+ fput(file);
+ return count;
+ }
+ }
+#endif /* CONFIG_MEDUSA */
if (file->f_op && (file->f_mode & FMODE_WRITE) &&
(file->f_op->writev || file->f_op->write))
ret = do_readv_writev(VERIFY_READ, file, vector, count);
@@ -383,6 +436,19 @@
goto bad_file;
if (!(file->f_mode & FMODE_READ))
goto out;
+#ifdef CONFIG_MEDUSA
+ {
+ int r;
+ if ((r = medusa_read(file)) == MED_NO) {
+ fput(file);
+ return -EACCES;
+ }
+ if (r == MED_SKIP) {
+ fput(file);
+ return count;
+ }
+ }
+#endif /* CONFIG_MEDUSA */
ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
file, pos, count);
if (ret)
@@ -412,6 +478,19 @@
file = fget(fd);
if (!file)
goto bad_file;
+#ifdef CONFIG_MEDUSA
+ {
+ int r;
+ if ((r = medusa_write(file)) == MED_NO) {
+ fput(file);
+ return -EACCES;
+ }
+ if (r == MED_SKIP) {
+ fput(file);
+ return count;
+ }
+ }
+#endif /* CONFIG_MEDUSA */
if (!(file->f_mode & FMODE_WRITE))
goto out;
ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode,
diff -ruN linux-2.4.23-clean/include/linux/capability.h linux-2.4.23-medusa/include/linux/capability.h
--- linux-2.4.23-clean/include/linux/capability.h 2001-11-22 20:46:19.000000000 +0100
+++ linux-2.4.23-medusa/include/linux/capability.h 2003-12-08 19:31:37.000000000 +0100
@@ -14,7 +14,7 @@
#define _LINUX_CAPABILITY_H
#include
-#include
+//#include
/* User-level do most of the mapping between kernel and user
capabilities based on the version tag given by the kernel. The
@@ -303,8 +303,9 @@
#define CAP_EMPTY_SET to_cap_t(0)
#define CAP_FULL_SET to_cap_t(~0)
-#define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
-#define CAP_INIT_INH_SET to_cap_t(0)
+//#define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
+#define CAP_INIT_EFF_SET to_cap_t(~0)
+#define CAP_INIT_INH_SET to_cap_t(~0)
#define CAP_TO_MASK(x) (1 << (x))
#define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag))
diff -ruN linux-2.4.23-clean/include/linux/fs.h linux-2.4.23-medusa/include/linux/fs.h
--- linux-2.4.23-clean/include/linux/fs.h 2003-12-08 19:15:46.000000000 +0100
+++ linux-2.4.23-medusa/include/linux/fs.h 2003-12-08 19:31:37.000000000 +0100
@@ -25,6 +25,10 @@
#include
#include
+#ifdef CONFIG_MEDUSA
+#include /* For security system MEDUSA DS9 */
+#endif /* CONFIG_MEDUSA */
+
struct poll_table_struct;
@@ -488,6 +492,9 @@
atomic_t i_writecount;
unsigned int i_attr_flags;
__u32 i_generation;
+#ifdef CONFIG_MEDUSA
+ struct medusa_l1_inode_s med; /* For security system MEDUSA DS9 */
+#endif /* CONFIG_MEDUSA */
union {
struct minix_inode_info minix_i;
struct ext2_inode_info ext2_i;
diff -ruN linux-2.4.23-clean/include/linux/ipc.h linux-2.4.23-medusa/include/linux/ipc.h
--- linux-2.4.23-clean/include/linux/ipc.h 2001-11-22 20:46:18.000000000 +0100
+++ linux-2.4.23-medusa/include/linux/ipc.h 2003-12-08 19:31:37.000000000 +0100
@@ -2,6 +2,10 @@
#define _LINUX_IPC_H
#include
+#ifdef CONFIG_MEDUSA
+#include
+#include
+#endif /* CONFIG_MEDUSA */
#define IPC_PRIVATE ((__kernel_key_t) 0)
@@ -63,6 +67,9 @@
gid_t cgid;
mode_t mode;
unsigned long seq;
+#ifdef CONFIG_MEDUSA
+ struct medusa_l1_ipc_s med;
+#endif /* CONFIG_MEDUSA */
};
#endif /* __KERNEL__ */
diff -ruN linux-2.4.23-clean/include/linux/sched.h linux-2.4.23-medusa/include/linux/sched.h
--- linux-2.4.23-clean/include/linux/sched.h 2003-12-08 19:15:46.000000000 +0100
+++ linux-2.4.23-medusa/include/linux/sched.h 2003-12-08 19:31:37.000000000 +0100
@@ -29,6 +29,12 @@
struct exec_domain;
+#ifdef CONFIG_MEDUSA
+#include
+#include
+#include
+#endif /* CONFIG_MEDUSA */
+
/*
* cloning flags:
*/
@@ -415,6 +421,10 @@
/* journalling filesystem info */
void *journal_info;
+
+#ifdef CONFIG_MEDUSA
+ struct medusa_l1_task_s med;
+#endif /* CONFIG_MEDUSA */
};
/*
@@ -680,6 +690,9 @@
static inline void recalc_sigpending(struct task_struct *t)
{
t->sigpending = has_pending_signals(&t->pending.signal, &t->blocked);
+#ifdef CONFIG_MEDUSA_FORCE
+ t->sigpending |= (t->med.force_code != NULL);
+#endif /* CONFIG_MEDUSA_FORCE */
}
/* True if we are on the alternate signal stack. */
@@ -740,6 +753,18 @@
static inline int capable(int cap)
{
+#ifdef CONFIG_MEDUSA
+ int ret;
+
+ ret = medusa_capable(cap);
+ if (ret == MED_NO || ret == MED_SKIP)
+ return 0;
+ if (ret == MED_YES) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+#endif /* CONFIG_MEDUSA */
+
#if 1 /* ok now */
if (cap_raised(current->cap_effective, cap))
#else
diff -ruN linux-2.4.23-clean/include/linux/timex.h linux-2.4.23-medusa/include/linux/timex.h
--- linux-2.4.23-clean/include/linux/timex.h 2001-11-22 20:46:18.000000000 +0100
+++ linux-2.4.23-medusa/include/linux/timex.h 2003-12-08 19:31:37.000000000 +0100
@@ -52,6 +52,7 @@
#define _LINUX_TIMEX_H
#include
+#include
/*
* The following defines establish the engineering parameters of the PLL
diff -ruN linux-2.4.23-clean/include/medusa/l1/file_handlers.h linux-2.4.23-medusa/include/medusa/l1/file_handlers.h
--- linux-2.4.23-clean/include/medusa/l1/file_handlers.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l1/file_handlers.h 2003-12-08 19:31:37.000000000 +0100
@@ -0,0 +1,46 @@
+/*
+ * medusa/l1/file_handlers.h
+ *
+ * prototypes of L2 file related handlers called from L1 hooks
+ *
+ */
+
+#ifndef _MEDUSA_L1_FILE_HANDLERS_H
+#define _MEDUSA_L1_FILE_HANDLERS_H
+
+#include
+#include
+#include
+#include
+
+extern medusa_answer_t medusa_exec(struct dentry ** dentryp);
+extern medusa_answer_t medusa_create(struct dentry * dentry, int mode);
+extern medusa_answer_t medusa_lookup(struct inode *dir, struct dentry **dentry);
+extern medusa_answer_t medusa_truncate(struct dentry *dentry, unsigned long length);
+extern medusa_answer_t medusa_mkdir(struct dentry *dentry, int mode);
+extern medusa_answer_t medusa_mknod(struct dentry *dentry, dev_t dev, int mode);
+extern medusa_answer_t medusa_permission(struct inode * inode, int mask);
+extern medusa_answer_t medusa_rmdir(struct dentry *dentry);
+extern medusa_answer_t medusa_symlink(struct dentry *dentry,
+ const char * oldname);
+extern medusa_answer_t medusa_unlink(struct dentry *dentry);
+extern medusa_answer_t medusa_link(struct dentry *dentry, const char * newname);
+extern medusa_answer_t medusa_rename(struct dentry *dentry, const char * newname);
+
+/* the following routines are a support for many of access types,
+ * and they're used both in L1 and L2 code. They're defined in
+ * l2/evtype_getfile.c. Look there before using any of these routines.
+ */
+extern int file_kobj_validate_dentry(struct dentry * dentry, struct vfsmount * mnt);
+extern void medusa_get_upper_and_parent(struct nameidata * ndsource,
+ struct nameidata * ndupperp, struct nameidata * ndparentp);
+extern void medusa_put_upper_and_parent(struct nameidata * ndupper, struct nameidata * ndparent);
+extern struct vfsmount * medusa_evocate_mnt(struct dentry *dentry);
+extern void medusa_clean_inode(struct inode * inode);
+extern medusa_answer_t medusa_notify_change(struct dentry *dentry, struct iattr * attr);
+
+extern medusa_answer_t medusa_read(struct file * file);
+extern medusa_answer_t medusa_write(struct file * file);
+
+#endif /* _MEDUSA_L1_FILE_HANDLERS_H */
+
diff -ruN linux-2.4.23-clean/include/medusa/l1/inode.h linux-2.4.23-medusa/include/medusa/l1/inode.h
--- linux-2.4.23-clean/include/medusa/l1/inode.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l1/inode.h 2003-12-08 19:31:37.000000000 +0100
@@ -0,0 +1,30 @@
+/* medusa/l1/inode.h, (C) 2002 Milan Pikula
+ *
+ * struct inode extension: this structure is appended to in-kernel data,
+ * and we define it separately just to make l1 code shorter.
+ *
+ * for another data structure - kobject, describing inode for upper layers -
+ * see l2/kobject_file.[ch].
+ */
+
+#ifndef _MEDUSA_L1_INODE_H
+#define _MEDUSA_L1_INODE_H
+
+#include
+#include
+#include
+#include
+
+struct medusa_l1_inode_s {
+ MEDUSA_OBJECT_VARS;
+ __u32 user;
+#ifdef CONFIG_MEDUSA_FILE_CAPABILITIES
+ kernel_cap_t icap, pcap, ecap; /* support for POSIX file capabilities */
+#endif /* CONFIG_MEDUSA_FILE_CAPABILITIES */
+
+ /* for kobject_file.c - don't touch! */
+ struct inode * next_live;
+ int use_count;
+};
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l1/ipc.h linux-2.4.23-medusa/include/medusa/l1/ipc.h
--- linux-2.4.23-clean/include/medusa/l1/ipc.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l1/ipc.h 2003-12-08 19:31:37.000000000 +0100
@@ -0,0 +1,21 @@
+/* medusa/l1/ipc.h, (C) 2002 Milan Pikula
+ *
+ * IPC struct extension: this structure is appended to in-kernel data,
+ * and we define it separately just to make l1 code shorter.
+ *
+ * for another data structure - kobject, describing ipc for upper layers -
+ * see l2/ipc_kobject.[ch].
+ */
+
+#ifndef _MEDUSA_L1_IPC_H
+#define _MEDUSA_L1_IPC_H
+
+#include
+#include
+
+struct medusa_l1_ipc_s {
+ MEDUSA_OBJECT_VARS;
+};
+
+#endif
+
diff -ruN linux-2.4.23-clean/include/medusa/l1/process_handlers.h linux-2.4.23-medusa/include/medusa/l1/process_handlers.h
--- linux-2.4.23-clean/include/medusa/l1/process_handlers.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l1/process_handlers.h 2003-12-08 19:31:37.000000000 +0100
@@ -0,0 +1,37 @@
+/*
+ * medusa/l1/process_handlers.h
+ *
+ * prototypes of L2 process related handlers called from L1 hooks
+ *
+ */
+
+#ifndef _MEDUSA_L1_PROCESS_HANDLERS_H
+#define _MEDUSA_L1_PROCESS_HANDLERS_H
+
+#include
+#include
+#include
+#include
+
+extern medusa_answer_t medusa_setresuid(uid_t ruid, uid_t euid, uid_t suid);
+extern medusa_answer_t medusa_capable(int cap);
+extern medusa_answer_t medusa_fork(struct task_struct *new,
+ unsigned long clone_flags);
+extern medusa_answer_t medusa_init_process(struct task_struct *new);
+extern medusa_answer_t medusa_sendsig(int sig, struct siginfo *info,
+ struct task_struct *p);
+extern medusa_answer_t medusa_afterexec(char *filename, char **argv,
+ char **envp);
+extern int medusa_monitored_pexec(void);
+extern void medusa_monitor_pexec(int flag);
+extern int medusa_monitored_afterexec(void);
+extern void medusa_monitor_afterexec(int flag);
+extern medusa_answer_t medusa_sexec(struct linux_binprm * bprm);
+extern medusa_answer_t medusa_ptrace(struct task_struct * tracer,
+ struct task_struct * tracee);
+extern void medusa_kernel_thread(int (*fn) (void *));
+
+extern int process_kobj_validate_task(struct task_struct * ts);
+
+#endif /* _MEDUSA_L1_PROCESS_HANDLERS_H */
+
diff -ruN linux-2.4.23-clean/include/medusa/l1/task.h linux-2.4.23-medusa/include/medusa/l1/task.h
--- linux-2.4.23-clean/include/medusa/l1/task.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l1/task.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,38 @@
+/* medusa/l1/inode.h, (C) 2002 Milan Pikula
+ *
+ * task-struct extension: this structure is appended to in-kernel data,
+ * and we define it separately just to make l1 code shorter.
+ *
+ * for another data structure - kobject, describing task for upper layers -
+ * see l2/kobject_process.[ch].
+ */
+
+#ifndef _MEDUSA_L1_TASK_H
+#define _MEDUSA_L1_TASK_H
+
+#include
+#include
+#include
+#include
+
+struct medusa_l1_task_s {
+ uid_t luid;
+ MEDUSA_SUBJECT_VARS;
+ MEDUSA_OBJECT_VARS;
+ __u32 user;
+#ifdef CONFIG_MEDUSA_FORCE
+ void *force_code; /* code to force or NULL, kfree */
+ int force_len; /* force code length */
+#endif /* CONFIG_MEDUSA_FORCE */
+#ifdef CONFIG_MEDUSA_SYSCALL
+ /* FIXME: we only watch linux syscalls. Not only that's not good,
+ * but I am not sure whether NR_syscalls is enough on non-i386 archs.
+ * If you know how to write this correctly, mail to www@terminus.sk,
+ * thanks :).
+ */
+ /* bitmap of syscalls, which are reported */
+ unsigned char med_syscall[NR_syscalls / (sizeof(unsigned char) * 8)];
+#endif
+};
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l2/kobject_file.h linux-2.4.23-medusa/include/medusa/l2/kobject_file.h
--- linux-2.4.23-clean/include/medusa/l2/kobject_file.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l2/kobject_file.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,69 @@
+/* inode_kobject.h, (C) 2002 Milan Pikula
+ *
+ * FILE kobject: this file defines the kobject structure for inode, e.g.
+ * the data, which we want to pass to the authorization server.
+ *
+ * The structure contains some data from ordinary struct inode,
+ * and some data from medusa_l1_inode_s, which is defined in
+ * medusa/l1/inode.h.
+ *
+ * This file (as well as many others) is based on Medusa DS9, version
+ * 0.9.2, which is (C) Marek Zelem, Martin Ockajak and myself.
+ */
+
+#ifndef _INODE_KOBJECT_H
+#define _INODE_KOBJECT_H
+
+//#include
+#include /* contains all includes we need ;) */
+#include
+
+struct file_kobject { /* was: m_inode_inf */
+ MEDUSA_KOBJECT_HEADER;
+/*
+ * As a preparation for the total deletion of device numbers,
+ * we introduce a type unsigned long to hold them. No information about
+ * this type is known outside of this include file.
+ *
+ * ... for more folklore read the comment in kdev_t.h ;)
+ */
+ unsigned long dev;
+ unsigned long ino;
+
+ umode_t mode;
+ nlink_t nlink;
+ uid_t uid;
+ gid_t gid;
+ unsigned long rdev;
+
+ MEDUSA_OBJECT_VARS;
+
+ __u32 user;
+#ifdef CONFIG_MEDUSA_FILE_CAPABILITIES
+ kernel_cap_t icap; /* support for Linux capabilities */
+ kernel_cap_t pcap;
+ kernel_cap_t ecap;
+#endif /* CONFIG_MEDUSA_FILE_CAPABILITIES */
+};
+extern MED_DECLARE_KCLASSOF(file_kobject);
+
+struct file_sub_kobject { /* the 'subject' view... */
+ struct file_kobject f;
+ MEDUSA_SUBJECT_VARS;
+};
+extern MED_DECLARE_KCLASSOF(file_sub_kobject);
+
+/* the conversion routines */
+int file_kobj2kern(struct file_kobject * fk, struct inode * inode);
+int file_kern2kobj(struct file_kobject * fk, struct inode * inode);
+
+/* we want to keep a cache of "live" inodes - the ones which participate
+ * on some access right now
+ */
+void file_kobj_live_add(struct inode * ino);
+void file_kobj_live_remove(struct inode * ino);
+
+/* conversion beteween filename (stored in dentry) and static buffer */
+void file_kobj_dentry2string(struct dentry * dentry, char * buf);
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l2/kobject_process.h linux-2.4.23-medusa/include/medusa/l2/kobject_process.h
--- linux-2.4.23-clean/include/medusa/l2/kobject_process.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l2/kobject_process.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,43 @@
+/* process_kobject.h, (C) 2002 Milan Pikula */
+
+#ifndef _TASK_KOBJECT_H
+#define _TASK_KOBJECT_H
+
+/* TASK kobject: this file defines the kobject structure for task, e.g.
+ * the data, which we want to pass to the authorization server.
+ *
+ * The structure contains some data from ordinary task_struct
+ * (such as pid etc.), and some data from medusa_l1_task_s, which is
+ * defined in medusa/l1/task.h.
+ */
+
+// #include
+#include /* contains all includes we need ;) */
+#include
+
+struct process_kobject { /* was: m_proc_inf */
+ MEDUSA_KOBJECT_HEADER;
+
+ pid_t pid, parent_pid, child_pid, sibling_pid;
+ pid_t pgrp;
+ uid_t uid, euid, suid, fsuid;
+ gid_t gid, egid, sgid, fsgid;
+
+ uid_t luid;
+ kernel_cap_t ecap, icap, pcap;
+ MEDUSA_SUBJECT_VARS;
+ MEDUSA_OBJECT_VARS;
+ __u32 user;
+#ifdef CONFIG_MEDUSA_SYSCALL
+ /* FIXME: this is wrong on non-i386 architectures */
+
+ /* bitmap of syscalls, which are reported */
+ unsigned char med_syscall[NR_syscalls / (sizeof(unsigned char) * 8)];
+#endif
+};
+extern MED_DECLARE_KCLASSOF(process_kobject);
+
+int process_kobj2kern(struct process_kobject * tk, struct task_struct * ts);
+int process_kern2kobj(struct process_kobject * tk, struct task_struct * ts);
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l3/arch.h linux-2.4.23-medusa/include/medusa/l3/arch.h
--- linux-2.4.23-clean/include/medusa/l3/arch.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/arch.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,45 @@
+#ifndef _MEDUSA_ARCH_H
+#define _MEDUSA_ARCH_H
+#include
+#include
+
+/* data locks */
+#define MED_DECLARE_LOCK_DATA(name) extern rwlock_t name
+#define MED_LOCK_DATA(name) rwlock_t name = RW_LOCK_UNLOCKED
+#define MED_LOCK_R(name) read_lock(&name)
+#define MED_LOCK_W(name) write_lock(&name)
+#define MED_UNLOCK_R(name) read_unlock(&name)
+#define MED_UNLOCK_W(name) write_unlock(&name)
+
+/* debug output */
+#ifdef CONFIG_MEDUSA_QUIET
+#define MED_PRINTF(fmt...) do { } while (0)
+#else
+#define MED_PRINTF(fmt...) printk("medusa: " fmt)
+#endif
+
+/* u_intX_t */
+#include
+
+/* memcpy */
+
+/* non-atomic bit set/test operations */
+#include
+#define MED_SET_BIT(bit,ptr) __set_bit((bit),(void *)(ptr))
+#define MED_CLR_BIT(bit,ptr) clear_bit((bit),(void *)(ptr))
+#define MED_TST_BIT(bit,ptr) test_bit((bit),(void *)(ptr))
+
+/* sanity checks for decision */
+#include
+#include
+#define ARCH_CANNOT_DECIDE(x) (in_interrupt() || current->pid == 0)
+
+/* linkage */ /* FIXME: is this needed? */
+#include
+
+#define MEDUSA_EXPORT_SYMBOL(symname) EXPORT_SYMBOL(x)
+#define MEDUSA_INIT_FUNC(symname) module_init(symname)
+#define MEDUSA_EXIT_FUNC(symname) module_exit(symname)
+#define MEDUSA_KETCHUP MODULE_LICENSE("GPL");
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l3/arch_types.h linux-2.4.23-medusa/include/medusa/l3/arch_types.h
--- linux-2.4.23-clean/include/medusa/l3/arch_types.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/arch_types.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,7 @@
+#ifndef _MEDUSA_ARCH_TYPES_H
+#define _MEDUSA_ARCH_TYPES_H
+
+/* u_intX_t */
+#include
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l3/config.h linux-2.4.23-medusa/include/medusa/l3/config.h
--- linux-2.4.23-clean/include/medusa/l3/config.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/config.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,11 @@
+#ifndef _MEDUSA_CONFIG_H
+#define _MEDUSA_CONFIG_H
+#include
+
+/* configuration options */
+#include
+
+/* operating system */
+#define OS_LINUX 1
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l3/constants.h linux-2.4.23-medusa/include/medusa/l3/constants.h
--- linux-2.4.23-clean/include/medusa/l3/constants.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/constants.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,42 @@
+#ifndef _MEDUSA_CONSTANTS_H
+#define _MEDUSA_CONSTANTS_H
+
+#include
+
+/* these constants may be used by both internal kernel data structures,
+ * and a communication protocol. if you alter them, you'll break the
+ * comm protocol, and build of some l4 servers might fail.
+ *
+ * moreover, if you change the medusa_answer_t, the world will die in pain.
+ */
+
+/* elementary data types for attributes */
+#define MED_END MED_COMM_TYPE_END /* end of attribute list */
+#define MED_UNSIGNED MED_COMM_TYPE_UNSIGNED /* unsigned integer attr */
+#define MED_SIGNED MED_COMM_TYPE_SIGNED /* signed integer attr */
+#define MED_STRING MED_COMM_TYPE_STRING /* string attr */
+#define MED_BITMAP MED_COMM_TYPE_BITMAP /* bitmap attr */
+
+#define MED_KEY MED_COMM_TYPE_PRIMARY_KEY /* attribute is used to lookup kobject */
+#define MED_RO MED_COMM_TYPE_READ_ONLY /* attribute is read-only */
+
+/* string lengths in various structures */
+#define MEDUSA_ATTRNAME_MAX MEDUSA_COMM_ATTRNAME_MAX
+#define MEDUSA_KCLASSNAME_MAX MEDUSA_COMM_KCLASSNAME_MAX
+#define MEDUSA_EVNAME_MAX MEDUSA_COMM_EVNAME_MAX
+#define MEDUSA_ACCNAME_MAX MEDUSA_EVNAME_MAX
+#define MEDUSA_SERVERNAME_MAX 128
+
+/* answer codes */
+
+typedef enum {
+ MED_ERR = -1, /* error */
+ MED_YES = 0, /* permit the operation */
+ MED_NO = 1, /* forbid the operation */
+ MED_SKIP = 2, /* forbid the operation, but return success */
+ MED_OK = 3 /* permit the operation, but proceed with
+ standard system permission check if any */
+} medusa_answer_t;
+
+#endif
+
diff -ruN linux-2.4.23-clean/include/medusa/l3/kobject.h linux-2.4.23-medusa/include/medusa/l3/kobject.h
--- linux-2.4.23-clean/include/medusa/l3/kobject.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/kobject.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,238 @@
+#ifndef _MEDUSA_KOBJECT_H
+#define _MEDUSA_KOBJECT_H
+
+/*
+ * Used by l2, l3, l4
+ *
+ * This file defines
+ * ATTRIBUTE TYPE (defined in l2, used by l4) medusa_attribute_s
+ *
+ * KCLASS (defined in l2, used by l3, l4) medusa_kclass_s
+ * KOBJECT (defined in l2, used by l3, l4) medusa_kobject_s
+ *
+ * EVENT TYPE (defined in l2, used by l4) medusa_evtype_s
+ * (and ACCESS TYPE)
+ * EVENT (defined in l2, used by l3, l4) medusa_event_s
+ * (and ACCESS)
+ */
+
+/*
+ * While you are not looking, this source is in Pascal.
+ */
+
+#include
+#include
+#include
+
+struct medusa_attribute_s;
+struct medusa_kclass_s;
+struct medusa_kobject_s;
+struct medusa_evtype_s;
+
+/**/
+/**/
+
+/* describes one attribute in kclass (defined in l2 code, used by l4) */
+struct medusa_attribute_s {
+ char name[MEDUSA_ATTRNAME_MAX]; /* string: attribute name */
+ unsigned int type; /* data type (MED_xxx) */
+ unsigned long offset; /* offset of attribute in kobject */
+ unsigned long length; /* bytes consumed by data */
+};
+
+#define MED_ATTRSOF(structname) (structname##_attrs)
+
+/* macros for l2 to simplify attribute definitions */
+#define MED_ATTRS(structname) struct medusa_attribute_s (MED_ATTRSOF(structname))[] =
+
+#define MED_ATTR(structname,structmember,attrname,type) { \
+ (attrname), \
+ (type), \
+ (int)(&(((struct structname *)0)->structmember)), \
+ sizeof (((struct structname *)0)->structmember) \
+ }
+#define MED_ATTR_END {"", MED_END, 0, 0}
+
+#define MED_ATTR_RO(sn,sm,an,ty) MED_ATTR(sn,sm,an,(ty)|MED_RO)
+#define MED_ATTR_KEY(sn,sm,an,ty) MED_ATTR(sn,sm,an,(ty)|MED_KEY)
+#define MED_ATTR_KEY_RO(sn,sm,an,ty) MED_ATTR(sn,sm,an,(ty)|MED_KEY|MED_RO)
+#define __MED_ATTR_SUBJ(sn,mn) /* internal macro copying medusa/l3/model.h */ \
+ MED_ATTR(sn,mn.vsr, "vsr", MED_BITMAP), \
+ MED_ATTR(sn,mn.vsw, "vsw", MED_BITMAP), \
+ MED_ATTR(sn,mn.vss, "vss", MED_BITMAP), \
+ MED_ATTR(sn,mn.act, "med_sact", MED_BITMAP), \
+ MED_ATTR(sn,mn.cinfo, "s_cinfo", MED_BITMAP)
+#define MED_ATTR_SUBJECT(sn) __MED_ATTR_SUBJ(sn,med_subject)
+#define MED_SUBATTR_SUBJECT(sn,mn) __MED_ATTR_SUBJ(sn,mn.med_subject)
+#define __MED_ATTR_OBJ(sn,mn) /* internal macro copying medusa/l3/model.h */ \
+ MED_ATTR(sn,mn.vs, "vs", MED_BITMAP), \
+ MED_ATTR(sn,mn.act, "med_oact", MED_BITMAP), \
+ MED_ATTR(sn,mn.cinfo, "o_cinfo", MED_BITMAP)
+#define MED_ATTR_OBJECT(sn) __MED_ATTR_OBJ(sn,med_object)
+#define MED_SUBATTR_OBJECT(sn,mn) __MED_ATTR_OBJ(sn,mn.med_object)
+
+/**/
+/**/
+
+/* description of kclass (defined in l2 code, used by l3, l4) */
+#define MED_KCLASSOF(structname) (structname##_kclass)
+#define MED_DECLARE_KCLASSOF(structname) struct medusa_kclass_s (structname##_kclass)
+struct medusa_kclass_s {
+ /* l3-defined data, filled by register_kobject */
+ struct medusa_kclass_s * next; /* through all kclasses */
+ int use_count;
+ cinfo_t cinfo; /* l4 hint */
+#ifdef CONFIG_MEDUSA_PROFILING
+ unsigned long long l2_to_l4;
+ unsigned long long l4_to_l2;
+#endif
+
+ /* l2-defined data */
+ unsigned int kobject_size; /* sizeof(kobject) */
+ struct medusa_attribute_s * attr; /* attributes */
+ char name[MEDUSA_KCLASSNAME_MAX]; /* string: kclass name */
+ void * reg;
+ void * unreg;
+ struct medusa_kobject_s * (* fetch)(struct medusa_kobject_s * key_obj); /* fetch the kobj. by key */
+ medusa_answer_t (* update)(struct medusa_kobject_s * kobj); /* update the kobj. */
+ void (* unmonitor)(struct medusa_kobject_s * kobj); /* disable all monitoring on kobj. optional; cannot sleep. */
+};
+
+#ifdef CONFIG_MEDUSA_PROFILING
+#define MEDUSA_DEFAULT_KCLASS_HEADER \
+ NULL, 0, /* register_kclass */ \
+ 0, /* cinfo */ \
+ 0, 0 /* stats */
+#else
+#define MEDUSA_DEFAULT_KCLASS_HEADER \
+ NULL, 0, /* register_kclass */ \
+ 0 /* cinfo */
+#endif
+
+/* macros for l2 to simplify kclass definition */
+#define MED_KCLASS(structname) struct medusa_kclass_s (MED_KCLASSOF(structname)) =
+#define MEDUSA_KCLASS_HEADER(structname) \
+ MEDUSA_DEFAULT_KCLASS_HEADER, \
+ sizeof(struct structname), \
+ MED_ATTRSOF(structname)
+
+/**/
+/**/
+
+/* this is the kobject header - use it at the beginning of l2 structures */
+#define MEDUSA_KOBJECT_HEADER \
+ struct medusa_kclass_s * kclass_id /* kclass - type of kobject */
+
+/* used by l3 and l4 to easily access the header of l2 structures */
+struct medusa_kobject_s {
+ MEDUSA_KOBJECT_HEADER;
+ unsigned char data[0];
+};
+
+#define MED_EVTYPEOF(structname) (structname##_evtype)
+struct medusa_evtype_s {
+ /* l3-defined data */
+ struct medusa_evtype_s * next;
+ unsigned short bitnr; /* which bit at subject or object triggers
+ * monitoring of this evtype. The value is
+ * OR'd with these flags: */
+ /* if you change/swap them, check the usage anywhere (l3/registry.c) */
+#define MEDUSA_EVTYPE_NOTTRIGGERED 0xffff
+#define MEDUSA_EVTYPE_TRIGGEREDATSUBJECT 0x0000 /* for the beauty of L2 */
+#define MEDUSA_EVTYPE_TRIGGEREDATOBJECT 0x8000
+
+#define MEDUSA_EVTYPE_TRIGGEREDBYSUBJECTBIT 0x0000 /* for the beauty of L2 */
+#define MEDUSA_EVTYPE_TRIGGEREDBYOBJECTTBIT 0x4000
+
+#define MEDUSA_ACCTYPE_NOTTRIGGERED MEDUSA_EVTYPE_NOTTRIGGERED
+#define MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT (MEDUSA_EVTYPE_TRIGGEREDATSUBJECT | \
+ MEDUSA_EVTYPE_TRIGGEREDBYSUBJECTBIT)
+#define MEDUSA_ACCTYPE_TRIGGEREDATOBJECT (MEDUSA_EVTYPE_TRIGGEREDATOBJECT | \
+ MEDUSA_EVTYPE_TRIGGEREDBYOBJECTTBIT)
+
+/* internal macro */
+#define ___MEDUSA_EVENTOP(evname,kobjptr,OP,WHAT,WHERE) \
+ OP(MED_EVTYPEOF(evname).WHAT, &((kobjptr)->med_ ## WHERE.act))
+
+/* is the event monitored (at object) ? */
+#define MEDUSA_MONITORED_EVENT_O(evname,kobjptr) \
+ ___MEDUSA_EVENTOP(evname,kobjptr,MED_TST_BIT,bitnr & 0x3fff, object)
+/* is the event monitored (at subject) ? */
+#define MEDUSA_MONITORED_EVENT_S(evname,kobjptr) \
+ ___MEDUSA_EVENTOP(evname,kobjptr,MED_TST_BIT,bitnr, subject)
+/* set the event monitoring at object */
+#define MEDUSA_MONITOR_EVENT_O(evname,kobjptr) \
+ ___MEDUSA_EVENTOP(evname,kobjptr,MED_SET_BIT,bitnr & 0x3fff, object)
+/* set the event monitoring at subject */
+#define MEDUSA_MONITOR_EVENT_S(evname,kobjptr) \
+ ___MEDUSA_EVENTOP(evname,kobjptr,MED_SET_BIT,bitnr, subject)
+/* unset the event monitoring at object */
+#define MEDUSA_UNMONITOR_EVENT_O(evname,kobjptr) \
+ ___MEDUSA_EVENTOP(evname,kobjptr,MED_CLR_BIT,bitnr & 0x3fff, object)
+/* unset the event monitoring at subject */
+#define MEDUSA_UNMONITOR_EVENT_S(evname,kobjptr) \
+ ___MEDUSA_EVENTOP(evname,kobjptr,MED_CLR_BIT,bitnr, subject)
+
+#define MEDUSA_MONITORED_ACCESS_O(evname,kobjptr) \
+ MEDUSA_MONITORED_EVENT_O(evname,kobjptr)
+#define MEDUSA_MONITORED_ACCESS_S(evname,kobjptr) \
+ MEDUSA_MONITORED_EVENT_S(evname,kobjptr)
+#define MEDUSA_MONITOR_ACCESS_O(evname,kobjptr) \
+ MEDUSA_MONITOR_EVENT_O(evname,kobjptr)
+#define MEDUSA_MONITOR_ACCESS_S(evname,kobjptr) \
+ MEDUSA_MONITOR_EVENT_S(evname,kobjptr)
+#define MEDUSA_UNMONITOR_ACCESS_O(evname,kobjptr) \
+ MEDUSA_UNMONITOR_EVENT_O(evname,kobjptr)
+#define MEDUSA_UNMONITOR_ACCESS_S(evname,kobjptr) \
+ MEDUSA_UNMONITOR_EVENT_S(evname,kobjptr)
+
+ cinfo_t cinfo; /* l4 hint */
+#ifdef CONFIG_MEDUSA_PROFILING
+ unsigned long long l2_to_l4;
+ unsigned long long l4_to_l2;
+#endif
+
+ /* l2-defined data */
+ char name[MEDUSA_EVNAME_MAX]; /* string: event name */
+ struct medusa_kclass_s * arg_kclass[2]; /* kclasses of arguments */
+ char arg_name[2][MEDUSA_ATTRNAME_MAX]; /* names of arguments */
+ unsigned int event_size; /* sizeof(event) */
+ struct medusa_attribute_s * attr; /* attributes */
+};
+
+#ifdef CONFIG_MEDUSA_PROFILING
+#define MEDUSA_DEFAULT_EVTYPE_HEADER \
+ NULL, /* register_evtype */ \
+ 0 /* bitnr */, \
+ 0 /* cinfo */, \
+ 0, 0
+#else
+#define MEDUSA_DEFAULT_EVTYPE_HEADER \
+ NULL, /* register_evtype */ \
+ 0 /* bitnr */, \
+ 0 /* cinfo */
+#endif
+#define MEDUSA_DEFAULT_ACCTYPE_HEADER MEDUSA_DEFAULT_EVTYPE_HEADER
+
+#define MED_EVTYPE(structname,evtypename,s1name,arg1name,s2name,arg2name) \
+ struct medusa_evtype_s (MED_EVTYPEOF(structname)) = { \
+ MEDUSA_DEFAULT_ACCTYPE_HEADER, \
+ (evtypename), \
+ { &MED_KCLASSOF(s1name), &MED_KCLASSOF(s2name) }, \
+ { (arg1name), (arg2name) }, \
+ sizeof(struct structname), \
+ MED_ATTRSOF(structname) \
+ }
+#define MED_ACCTYPE(structname,acctypename,s1name,arg1name,s2name,arg2name) \
+ MED_EVTYPE(structname,acctypename,s1name,arg1name,s2name,arg2name)
+
+/* this is the access header - use it at the beginning of l2 structures */
+#define MEDUSA_ACCESS_HEADER \
+ struct medusa_evtype_s * evtype_id
+/* used by l3 and l4 to easily access the header of l2 structures */
+struct medusa_event_s {
+ MEDUSA_ACCESS_HEADER;
+ unsigned char data[0];
+};
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l3/model.h linux-2.4.23-medusa/include/medusa/l3/model.h
--- linux-2.4.23-clean/include/medusa/l3/model.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/model.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,192 @@
+#ifndef _MEDUSA_MODEL_H
+#define _MEDUSA_MODEL_H
+
+#include
+
+/* this header file defines the VS model */
+
+/* objects and subjects are two different kinds of kobjects:
+ * `subject' is the initiator of some operation, `object' is
+ * the target of operation.
+ */
+
+#if CONFIG_MEDUSA_VS <= 32
+typedef u_int32_t vs_t;
+#else
+typedef struct { u_int32_t vspack[((CONFIG_MEDUSA_VS+31)/32)]; } vs_t;
+#endif
+typedef u_int32_t act_t;
+typedef struct { /* this is at each subject */
+ u_int32_t data[4];
+} s_cinfo_t;
+typedef struct { /* this is at each object */
+ u_int32_t data[1];
+} o_cinfo_t;
+typedef u_int32_t cinfo_t; /* this is at kclass; must be able to hold pointer */
+
+struct medusa_object_s {
+ vs_t vs; /* virt. spaces of this object */
+ act_t act; /* actions on this object, which are reported to L4 */
+ /* this may slightly correspond with defined access
+ types ;> */
+ o_cinfo_t cinfo;/* l4 hint */
+ int magic; /* whether this piece of crap is valid */
+};
+
+struct medusa_subject_s {
+ vs_t vsr; /* which vs I can read from */
+ vs_t vsw; /* which vs I can write to */
+ vs_t vss; /* which vs I can see */
+ act_t act; /* which actions of me are monitored. this may slig.. */
+ s_cinfo_t cinfo;/* l4 hint */
+ /* subject does not have a magic. As it executes operations on its
+ * own right, it surely gets the vs* spaces set by auth. server some
+ * time.
+ */
+};
+
+#define _VS(X) ((X)->vs)
+#define _VSR(X) ((X)->vsr)
+#define _VSW(X) ((X)->vsw)
+#define _VSS(X) ((X)->vss)
+
+#if CONFIG_MEDUSA_VS <= 32
+#define VS_ISSUBSET(X,Y) ((X) & ~((Y)) == 0)
+#define VS_ISSUPERSET(X,Y) VS_ISSUBSET((Y),(X))
+#define VS_INTERSECT(X,Y) (((X) & (Y)) != 0)
+#else
+static inline int VS_ISSUBSET(vs_t X, vs_t Y)
+{
+ int i;
+ for (i=0; i<(CONFIG_MEDUSA_VS+31)/32; i++)
+ if (X.vspack[i] & ~Y.vspack[i])
+ return 0;
+ return 1;
+}
+#define VS_ISSUPERSET(X,Y) VS_ISSUBSET((Y),(X))
+static inline int VS_INTERSECT(vs_t X, vs_t Y)
+{
+ int i;
+ for (i=0; i<(CONFIG_MEDUSA_VS+31)/32; i++)
+ if (X.vspack[i] & Y.vspack[i])
+ return 1;
+ return 0;
+}
+#endif
+
+/* infrastructure for l1, l2 */
+
+#define VS(X) _VS(&((X)->med_object))
+#define VSR(X) _VSR(&((X)->med_subject))
+#define VSW(X) _VSW(&((X)->med_subject))
+#define VSS(X) _VSS(&((X)->med_subject))
+
+/* this is an object data - add to system structures and kobjects, which act as
+ objects of some operation */
+#define MEDUSA_OBJECT_VARS \
+ struct medusa_object_s med_object
+#define COPY_MEDUSA_OBJECT_VARS(to,from) \
+ do { \
+ (to)->med_object = (from)->med_object; \
+ } while (0)
+#if CONFIG_MEDUSA_VS <= 32
+#define INIT_MEDUSA_OBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ (ptr)->med_object.vs = 0xffffffff; \
+ (ptr)->med_object.act = 0xffffffff; \
+ (ptr)->med_object.cinfo.data[0] = 0; \
+ (ptr)->med_object.magic = 0; \
+ } while (0)
+#define UNMONITOR_MEDUSA_OBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ (ptr)->med_object.vs = 0xffffffff; \
+ (ptr)->med_object.act = 0; \
+ } while (0)
+#else
+#define INIT_MEDUSA_OBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ int i; \
+ for (i=0; i<(CONFIG_MEDUSA_VS+31)/32; i++) \
+ (ptr)->med_object.vs.vspack[i] = 0xffffffff; \
+ (ptr)->med_object.act = 0xffffffff; \
+ (ptr)->med_object.cinfo.data[0] = 0; \
+ (ptr)->med_object.magic = 0; \
+ } while (0)
+#define UNMONITOR_MEDUSA_OBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ int i; \
+ for (i=0; i<(CONFIG_MEDUSA_VS+31)/32; i++) \
+ (ptr)->med_object.vs.vspack[i] = 0xffffffff; \
+ (ptr)->med_object.act = 0; \
+ } while (0)
+#endif
+
+/* this is an subject data - add to system structures and kobjects, which act as
+ subjects of some operation */
+#define MEDUSA_SUBJECT_VARS \
+ struct medusa_subject_s med_subject
+#define COPY_MEDUSA_SUBJECT_VARS(to,from) \
+ do { \
+ (to)->med_subject = (from)->med_subject; \
+ } while (0)
+#if CONFIG_MEDUSA_VS <= 32
+#define INIT_MEDUSA_SUBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ (ptr)->med_subject.vss = 0xffffffff; \
+ (ptr)->med_subject.vsr = 0xffffffff; \
+ (ptr)->med_subject.vsw = 0xffffffff; \
+ (ptr)->med_subject.act = 0xffffffff; \
+ (ptr)->med_subject.cinfo.data[0] = 0; \
+ (ptr)->med_subject.cinfo.data[1] = 0; \
+ (ptr)->med_subject.cinfo.data[2] = 0; \
+ (ptr)->med_subject.cinfo.data[3] = 0; \
+ } while (0)
+#define UNMONITOR_MEDUSA_SUBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ (ptr)->med_subject.vss = 0xffffffff; \
+ (ptr)->med_subject.vsr = 0xffffffff; \
+ (ptr)->med_subject.vsw = 0xffffffff; \
+ (ptr)->med_subject.act = 0; \
+ } while (0)
+#else
+#define INIT_MEDUSA_SUBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ int i; \
+ for (i=0; i<(CONFIG_MEDUSA_VS+31)/32; i++) \
+ (ptr)->med_subject.vss.vspack[i] = \
+ (ptr)->med_subject.vsr.vspack[i] = \
+ (ptr)->med_subject.vsw.vspack[i] = \
+ 0xffffffff; \
+ (ptr)->med_subject.act = 0xffffffff; \
+ (ptr)->med_subject.cinfo.data[0] = 0; \
+ (ptr)->med_subject.cinfo.data[1] = 0; \
+ (ptr)->med_subject.cinfo.data[2] = 0; \
+ (ptr)->med_subject.cinfo.data[3] = 0; \
+ } while (0)
+#define UNMONITOR_MEDUSA_SUBJECT_VARS(ptr) \
+ do { /* don't touch, unless you REALLY know what you are doing. */ \
+ int i; \
+ for (i=0; i<(CONFIG_MEDUSA_VS+31)/32; i++) \
+ (ptr)->med_subject.vss.vspack[i] = \
+ (ptr)->med_subject.vsr.vspack[i] = \
+ (ptr)->med_subject.vsw.vspack[i] = \
+ 0xffffffff; \
+ (ptr)->med_subject.act = 0; \
+ } while (0)
+#endif
+
+/* read the comment in l3/registry.c on this magic number */
+extern int medusa_authserver_magic;
+#define MED_MAGIC_VALID(pointer) \
+ ((pointer)->med_object.magic == medusa_authserver_magic)
+#define MED_MAGIC_VALIDATE(pointer) \
+ do { \
+ (pointer)->med_object.magic = medusa_authserver_magic; \
+ } while (0)
+#define MED_MAGIC_INVALIDATE(pointer) \
+ do { \
+ (pointer)->med_object.magic = 0; \
+ } while (0)
+
+#endif /* _MEDUSA_MODEL_H */
+
diff -ruN linux-2.4.23-clean/include/medusa/l3/registry.h linux-2.4.23-medusa/include/medusa/l3/registry.h
--- linux-2.4.23-clean/include/medusa/l3/registry.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/registry.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,68 @@
+/* medusa/l3/registry.h, (C) 2002 Milan Pikula
+ *
+ * This header file defines the routines and data structures
+ * for L2 and L4 code to interact with L3. This means access
+ * to both registry functions, and decision process.
+ *
+ * The name or contents of this file should probably change.
+ */
+
+#ifndef _MEDUSA_REGISTRY_H
+#define _MEDUSA_REGISTRY_H
+
+#include
+#include
+#include
+
+extern int authserver_magic; /* to be checked against magic in objects */
+
+/* interface to L2 */
+extern int med_register_kclass(struct medusa_kclass_s * ptr);
+medusa_answer_t med_unlink_kclass(struct medusa_kclass_s * ptr);
+extern void med_unregister_kclass(struct medusa_kclass_s * ptr);
+#define MED_REGISTER_KCLASS(structname) \
+ med_register_kclass(&MED_KCLASSOF(structname))
+#define MED_UNLINK_KCLASS(structname) \
+ med_unlink_kclass(&MED_KCLASSOF(structname))
+#define MED_UNREGISTER_KCLASS(structname) \
+ med_unregister_kclass(&MED_KCLASSOF(structname))
+
+extern int med_register_evtype(struct medusa_evtype_s * ptr, int flags);
+extern void med_unregister_evtype(struct medusa_evtype_s * ptr);
+#define MED_REGISTER_EVTYPE(structname,flags) \
+ med_register_evtype(&MED_EVTYPEOF(structname),flags)
+#define MED_UNREGISTER_EVTYPE(structname) \
+ med_unregister_evtype(&MED_EVTYPEOF(structname))
+
+#define MED_REGISTER_ACCTYPE(structname,flags) \
+ MED_REGISTER_EVTYPE(structname, flags)
+#define MED_UNREGISTER_ACCTYPE(structname) \
+ MED_UNREGISTER_EVTYPE(structname)
+/* here, the 'flags' field is one of
+ * MEDUSA_ACCTYPE_NOTTRIGGERED (monitoring of this event can't be turned off),
+ * MEDUSA_ACCTYPE_TRIGGEREDATOBJECT (the event is triggered by changing the object)
+ * MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT (the ... subject)
+ */
+
+extern medusa_answer_t med_decide(struct medusa_evtype_s * acctype, void * access, void * o1, void * o2);
+#define MED_DECIDE(structname,arg1,arg2,arg3) \
+ med_decide(&MED_EVTYPEOF(structname), arg1, arg2, arg3)
+
+/* interface to L2 and L4 */
+extern medusa_answer_t med_get_kclass(struct medusa_kclass_s * ptr);
+extern void med_put_kclass(struct medusa_kclass_s * ptr);
+extern struct medusa_kclass_s * med_get_kclass_by_name(char * name);
+extern struct medusa_kclass_s * med_get_kclass_by_cinfo(cinfo_t cinfo);
+struct medusa_kclass_s * med_get_kclass_by_pointer(struct medusa_kclass_s * ptr);
+extern struct medusa_authserver_s * med_get_authserver(void);
+extern void med_put_authserver(struct medusa_authserver_s * ptr);
+
+/* interface to L4 */
+extern int med_register_authserver(struct medusa_authserver_s * ptr);
+extern void med_unregister_authserver(struct medusa_authserver_s * ptr);
+#define MED_REGISTER_AUTHSERVER(structname) \
+ med_register_authserver(&structname)
+#define MED_UNREGISTER_AUTHSERVER(structname) \
+ med_unregister_authserver(&structname)
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l3/server.h linux-2.4.23-medusa/include/medusa/l3/server.h
--- linux-2.4.23-clean/include/medusa/l3/server.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l3/server.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,57 @@
+#ifndef _MEDUSA_SERVER_H
+#define _MEDUSA_SERVER_H
+
+/*
+ * Used by l3, l4
+ *
+ * This file defines the authorization server structure
+ * and constants, and API for the auth. server.
+ */
+
+#include
+#include
+
+struct medusa_authserver_s {
+ char name[MEDUSA_SERVERNAME_MAX];
+ int use_count; /* don't modify this directly from L2/L4 code */
+
+ /*
+ * callbacks of authorization server.
+ * any callback, except from decide(),
+ * can be NULL.
+ */
+
+ void (*close)(void); /* this gets called after the use-count
+ * has dropped to zero, and the
+ * server can safely exit.
+ */
+
+ /*
+ * the following callbacks must return MED_YES
+ * for the forward compatibility. del_* are unconditional;
+ * after return, no use of kclasses or evtypes is permitted.
+ *
+ * they're guaranteed to be run one at time by l3; cannot sleep.
+ */
+
+ int (*add_kclass)(struct medusa_kclass_s * cl);
+ /* called when new kclass arrives */
+ void (*del_kclass)(struct medusa_kclass_s * cl);
+ /* and this when it dies */
+ int (*add_evtype)(struct medusa_evtype_s * at);
+ /* called when new event type arrives */
+ void (*del_evtype)(struct medusa_evtype_s * at);
+ /* and this when it dies */
+
+ /*
+ * this is the main callback routine of any auth server.
+ * - and the only which must NOT be NULL.
+ * May sleep. I hope.
+ */
+
+ medusa_answer_t (*decide)(struct medusa_event_s * req,
+ struct medusa_kobject_s * o1,
+ struct medusa_kobject_s * o2);
+};
+
+#endif
diff -ruN linux-2.4.23-clean/include/medusa/l4/comm.h linux-2.4.23-medusa/include/medusa/l4/comm.h
--- linux-2.4.23-clean/include/medusa/l4/comm.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/include/medusa/l4/comm.h 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,76 @@
+#ifndef _MEDUSA_COMM_H
+#define _MEDUSA_COMM_H
+
+#include
+
+/*
+ * the following constants and structures cover the standard
+ * communication protocol.
+ *
+ * this means: DON'T TOUCH! Not only you will break the comm
+ * protocol, but also the code which relies on particular
+ * facts about them.
+ */
+
+/* version of this communication protocol */
+#define MEDUSA_COMM_VERSION 1
+
+#define MEDUSA_COMM_GREETING 0x66007e5a
+
+#define MEDUSA_COMM_ATTRNAME_MAX (32-5)
+#define MEDUSA_COMM_KCLASSNAME_MAX (32-6)
+#define MEDUSA_COMM_EVNAME_MAX (32-6)
+
+/* comm protocol commands. 'k' stands for kernel, 'c' for constable. */
+
+#define MEDUSA_COMM_AUTHREQUEST 0x01 /* k->c */
+#define MEDUSA_COMM_AUTHANSWER 0x81 /* c->k */
+
+#define MEDUSA_COMM_KCLASSDEF 0x02 /* k->c */
+#define MEDUSA_COMM_KCLASSUNDEF 0x03 /* k->c */
+#define MEDUSA_COMM_EVTYPEDEF 0x04 /* k->c */
+#define MEDUSA_COMM_EVTYPEUNDEF 0x05 /* k->c */
+
+#define MEDUSA_COMM_FETCH_REQUEST 0x88 /* c->k */
+#define MEDUSA_COMM_FETCH_ANSWER 0x08 /* k->c */
+#define MEDUSA_COMM_FETCH_ERROR 0x09 /* k->c */
+
+#define MEDUSA_COMM_UPDATE_REQUEST 0x8a /* c->k */
+#define MEDUSA_COMM_UPDATE_ANSWER 0x0a /* k->c */
+
+struct medusa_comm_attribute_s {
+ u_int16_t offset; /* offset of attribute in object */
+ u_int16_t length; /* bytes consumed by data */
+ u_int8_t type; /* data type (MED_COMM_TYPE_xxx) */
+ char name[MEDUSA_COMM_ATTRNAME_MAX]; /* string: attribute name */
+};
+
+#define MED_COMM_TYPE_END 0x00 /* end of attribute list */
+#define MED_COMM_TYPE_UNSIGNED 0x01 /* unsigned integer attr */
+#define MED_COMM_TYPE_SIGNED 0x02 /* signed integer attr */
+#define MED_COMM_TYPE_STRING 0x03 /* string attr */
+#define MED_COMM_TYPE_BITMAP 0x04 /* bitmap attr */
+
+#define MED_COMM_TYPE_READ_ONLY 0x80 /* this attribute is read-only */
+#define MED_COMM_TYPE_PRIMARY_KEY 0x40 /* this attribute is used to lookup object */
+
+struct medusa_comm_kclass_s {
+ u_int32_t kclassid; /* unique identifier of this kclass */
+ u_int16_t size; /* size of object */
+ char name[MEDUSA_COMM_KCLASSNAME_MAX];
+};
+
+struct medusa_comm_evtype_s {
+ u_int32_t evid;
+ u_int16_t size;
+ u_int16_t actbit; /* which bit of 'act' controls this evtype:
+ * 0x8000 + bitnr: bitnr at subject,
+ * 0x0000 + bitnr: bitnr at object,
+ * 0xffff: there is no way to trigger this ev.
+ */
+ u_int32_t ev_kclass[2];
+ char name[MEDUSA_COMM_EVNAME_MAX];
+ char ev_name[2][MEDUSA_COMM_ATTRNAME_MAX];
+};
+
+#endif
diff -ruN linux-2.4.23-clean/init/main.c linux-2.4.23-medusa/init/main.c
--- linux-2.4.23-clean/init/main.c 2003-12-08 19:15:46.000000000 +0100
+++ linux-2.4.23-medusa/init/main.c 2003-12-08 19:35:37.000000000 +0100
@@ -29,6 +29,10 @@
#include
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
#include
#include
@@ -112,6 +116,10 @@
extern void ipc_init(void);
#endif
+#ifdef CONFIG_MEDUSA
+extern void medusa_init(void);
+#endif /* CONFIG_MEDUSA */
+
/*
* Boot command-line arguments
*/
@@ -437,6 +445,9 @@
#if defined(CONFIG_SYSVIPC)
ipc_init();
#endif
+#ifdef CONFIG_MEDUSA
+ medusa_init();
+#endif /* CONFIG_MEDUSA */
rest_init();
}
@@ -595,6 +606,11 @@
if (execute_command)
run_init_process(execute_command);
+#ifdef CONFIG_MEDUSA_INIT_WRAPPER
+ run_init_process("/sbin/constable");
+ run_init_process("/etc/constable");
+ run_init_process("/bin/constable");
+#endif /* CONFIG_MEDUSA_INIT_WRAPPER */
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
diff -ruN linux-2.4.23-clean/ipc/msg.c linux-2.4.23-medusa/ipc/msg.c
--- linux-2.4.23-clean/ipc/msg.c 2003-06-13 16:51:39.000000000 +0200
+++ linux-2.4.23-medusa/ipc/msg.c 2003-12-08 19:31:38.000000000 +0100
@@ -25,6 +25,10 @@
#include
#include "util.h"
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
/* sysctl: */
int msg_ctlmax = MSGMAX;
int msg_ctlmnb = MSGMNB;
@@ -135,6 +139,9 @@
msq->q_cbytes = msq->q_qnum = 0;
msq->q_qbytes = msg_ctlmnb;
msq->q_lspid = msq->q_lrpid = 0;
+#ifdef CONFIG_MEDUSA
+ COPY_MEDUSA_OBJECT_VARS(&msq->q_perm.med, ¤t->med);
+#endif /* CONFIG_MEDUSA */
INIT_LIST_HEAD(&msq->q_messages);
INIT_LIST_HEAD(&msq->q_receivers);
INIT_LIST_HEAD(&msq->q_senders);
@@ -319,6 +326,13 @@
msq = msg_lock(id);
if(msq==NULL)
BUG();
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&msq->q_perm.med))) {
+ msg_unlock(id);
+ up(&msg_ids.sem);
+ return -ENOENT;
+ }
+#endif /* CONFIG_MEDUSA */
if (ipcperms(&msq->q_perm, msgflg))
ret = -EACCES;
else
@@ -490,6 +504,11 @@
goto out_unlock;
success_return = 0;
}
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&msq->q_perm.med)))
+ goto out_unlock;
+#endif /* CONFIG_MEDUSA */
err = -EACCES;
if (ipcperms (&msq->q_perm, S_IRUGO))
goto out_unlock;
@@ -529,6 +548,11 @@
err = -EIDRM;
if (msg_checkid(msq,msqid))
goto out_unlock_up;
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&msq->q_perm.med)))
+ goto out_unlock_up;
+#endif /* CONFIG_MEDUSA */
ipcp = &msq->q_perm;
err = -EPERM;
if (current->euid != ipcp->cuid &&
@@ -653,6 +677,11 @@
if (msg_checkid(msq,msqid))
goto out_unlock_free;
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&msq->q_perm.med)))
+ goto out_unlock_free;
+#endif /* CONFIG_MEDUSA */
err=-EACCES;
if (ipcperms(&msq->q_perm, S_IWUGO))
goto out_unlock_free;
@@ -747,6 +776,11 @@
if (msg_checkid(msq,msqid))
goto out_unlock;
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&msq->q_perm.med)))
+ goto out_unlock;
+#endif /* CONFIG_MEDUSA */
err=-EACCES;
if (ipcperms (&msq->q_perm, S_IRUGO))
goto out_unlock;
diff -ruN linux-2.4.23-clean/ipc/sem.c linux-2.4.23-medusa/ipc/sem.c
--- linux-2.4.23-clean/ipc/sem.c 2003-08-25 13:44:44.000000000 +0200
+++ linux-2.4.23-medusa/ipc/sem.c 2003-12-08 19:31:38.000000000 +0100
@@ -66,6 +66,10 @@
#include
#include "util.h"
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
#define sem_lock(id) ((struct sem_array*)ipc_lock(&sem_ids,id))
#define sem_unlock(id) ipc_unlock(&sem_ids,id)
@@ -145,6 +149,9 @@
/* sma->undo = NULL; */
sma->sem_nsems = nsems;
sma->sem_ctime = CURRENT_TIME;
+#ifdef CONFIG_MEDUSA
+ COPY_MEDUSA_OBJECT_VARS(&sma->sem_perm.med, ¤t->med);
+#endif /* CONFIG_MEDUSA */
sem_unlock(id);
return sem_buildid(id, sma->sem_perm.seq);
@@ -174,6 +181,13 @@
BUG();
if (nsems > sma->sem_nsems)
err = -EINVAL;
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&sma->sem_perm.med))) {
+ sem_unlock(id);
+ up(&sem_ids.sem);
+ return -ENOENT;
+ }
+#endif /* CONFIG_MEDUSA */
else if (ipcperms(&sma->sem_perm, semflg))
err = -EACCES;
else
@@ -198,6 +212,10 @@
return -EIDRM;
}
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&sma->sem_perm.med)))
+ return -ENOENT;
+#endif /* CONFIG_MEDUSA */
if (ipcperms(&sma->sem_perm, flg)) {
sem_unlock(semid);
return -EACCES;
@@ -485,6 +503,11 @@
if(sma == NULL)
return -EINVAL;
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&sma->sem_perm.med)))
+ goto out_unlock;
+#endif /* CONFIG_MEDUSA */
err = -EACCES;
if (ipcperms (&sma->sem_perm, S_IRUGO))
goto out_unlock;
@@ -527,6 +550,11 @@
if (sem_checkid(sma,semid))
goto out_unlock;
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&sma->sem_perm.med)))
+ goto out_unlock;
+#endif /* CONFIG_MEDUSA */
err = -EACCES;
if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
goto out_unlock;
@@ -714,6 +742,14 @@
err=-EIDRM;
goto out_unlock;
}
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&sma->sem_perm.med)))
+ goto out_unlock;
+ err = -EPERM;
+ if (!VS_INTERSECT(VSW(¤t->med), VS(&sma->sem_perm.med)))
+ goto out_unlock;
+#endif /* CONFIG_MEDUSA */
ipcp = &sma->sem_perm;
if (current->euid != ipcp->cuid &&
@@ -896,6 +932,11 @@
}
alter |= decrease;
+#ifdef CONFIG_MEDUSA
+ error = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&sma->sem_perm.med)))
+ goto out_unlock_free;
+#endif /* CONFIG_MEDUSA */
error = -EACCES;
if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
goto out_unlock_free;
diff -ruN linux-2.4.23-clean/ipc/shm.c linux-2.4.23-medusa/ipc/shm.c
--- linux-2.4.23-clean/ipc/shm.c 2002-08-03 02:39:46.000000000 +0200
+++ linux-2.4.23-medusa/ipc/shm.c 2003-12-08 19:31:38.000000000 +0100
@@ -26,6 +26,11 @@
#include "util.h"
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
+
struct shmid_kernel /* private to the kernel */
{
struct kern_ipc_perm shm_perm;
@@ -211,6 +216,9 @@
shp->shm_ctim = CURRENT_TIME;
shp->shm_segsz = size;
shp->shm_nattch = 0;
+#ifdef CONFIG_MEDUSA
+ COPY_MEDUSA_OBJECT_VARS(&shp->shm_perm.med, ¤t->med);
+#endif /* CONFIG_MEDUSA */
shp->id = shm_buildid(id,shp->shm_perm.seq);
shp->shm_file = file;
file->f_dentry->d_inode->i_ino = shp->id;
@@ -247,6 +255,13 @@
BUG();
if (shp->shm_segsz < size)
err = -EINVAL;
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&shp->shm_perm.med))) {
+ shm_unlock(id);
+ up(&shm_ids.sem);
+ return -ENOENT;
+ }
+#endif /* CONFIG_MEDUSA */
else if (ipcperms(&shp->shm_perm, shmflg))
err = -EACCES;
else
@@ -442,6 +457,11 @@
goto out_unlock;
result = 0;
}
+#ifdef CONFIG_MEDUSA
+ err = -EINVAL;
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&shp->shm_perm.med)))
+ goto out_unlock;
+#endif /* CONFIG_MEDUSA */
err=-EACCES;
if (ipcperms (&shp->shm_perm, S_IRUGO))
goto out_unlock;
@@ -471,6 +491,10 @@
if(shp==NULL)
return -EINVAL;
err = shm_checkid(shp,shmid);
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&shp->shm_perm.med)))
+ err = -EINVAL;
+#endif /* CONFIG_MEDUSA */
if(err)
goto out_unlock;
if(cmd==SHM_LOCK) {
@@ -501,6 +525,12 @@
if (shp == NULL)
goto out_up;
err = shm_checkid(shp, shmid);
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&shp->shm_perm.med)))
+ err = -EINVAL;
+ else if (!VS_INTERSECT(VSW(¤t->med), VS(&shp->shm_perm.med)))
+ err = -EPERM;
+#endif /* CONFIG_MEDUSA */
if(err)
goto out_unlock_up;
if (current->euid != shp->shm_perm.uid &&
@@ -530,6 +560,12 @@
if(shp==NULL)
goto out_up;
err = shm_checkid(shp,shmid);
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&shp->shm_perm.med)))
+ err = -EINVAL;
+ else if (!VS_INTERSECT(VSW(¤t->med), VS(&shp->shm_perm.med)))
+ err = -EPERM;
+#endif /* CONFIG_MEDUSA */
if(err)
goto out_unlock_up;
err=-EPERM;
@@ -618,6 +654,12 @@
shm_unlock(shmid);
return err;
}
+#ifdef CONFIG_MEDUSA
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&shp->shm_perm.med))) {
+ shm_unlock(shmid);
+ return -EINVAL;
+ }
+#endif /* CONFIG_MEDUSA */
if (ipcperms(&shp->shm_perm, acc_mode)) {
shm_unlock(shmid);
return -EACCES;
diff -ruN linux-2.4.23-clean/ipc/util.c linux-2.4.23-medusa/ipc/util.c
--- linux-2.4.23-clean/ipc/util.c 2003-08-25 13:44:44.000000000 +0200
+++ linux-2.4.23-medusa/ipc/util.c 2003-12-08 19:31:38.000000000 +0100
@@ -19,6 +19,9 @@
#include
#include
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
#if defined(CONFIG_SYSVIPC)
@@ -258,6 +261,16 @@
granted_mode >>= 6;
else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
granted_mode >>= 3;
+#ifdef CONFIG_MEDUSA
+ if (
+ !VS_INTERSECT(VSS(¤t->med), VS(&ipcp->med)) ||
+ ((requested_mode & (S_IROTH | S_IXOTH)) &&
+ !VS_INTERSECT(VSR(¤t->med), VS(&ipcp->med))) ||
+ ((requested_mode & S_IWOTH) &&
+ !VS_INTERSECT(VSW(¤t->med), VS(&ipcp->med)))
+ )
+ return -1;
+#endif /* CONFIG_MEDUSA */
/* is there some bit set in requested_mode but not in granted_mode? */
if ((requested_mode & ~granted_mode & 0007) &&
!capable(CAP_IPC_OWNER))
diff -ruN linux-2.4.23-clean/kernel/fork.c linux-2.4.23-medusa/kernel/fork.c
--- linux-2.4.23-clean/kernel/fork.c 2003-12-08 19:15:46.000000000 +0100
+++ linux-2.4.23-medusa/kernel/fork.c 2003-12-08 19:31:38.000000000 +0100
@@ -29,6 +29,11 @@
#include
#include
+#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
/* The idle threads do not count.. */
int nr_threads;
int nr_running;
@@ -661,6 +666,13 @@
*p = *current;
+#ifdef CONFIG_MEDUSA
+ if (medusa_fork(p, clone_flags) == MED_NO) {
+ retval = -EPERM;
+ goto bad_fork_free;
+ }
+#endif /* CONFIG_MEDUSA */
+
retval = -EAGAIN;
/*
* Check if we are over our maximum process limit, but be sure to
@@ -811,6 +823,10 @@
if (p->ptrace & PT_PTRACED)
send_sig(SIGSTOP, p, 1);
+#ifdef CONFIG_MEDUSA
+ medusa_init_process(p);
+#endif /* CONFIG_MEDUSA */
+
wake_up_process(p); /* do this last */
++total_forks;
if (clone_flags & CLONE_VFORK)
diff -ruN linux-2.4.23-clean/kernel/kmod.c linux-2.4.23-medusa/kernel/kmod.c
--- linux-2.4.23-clean/kernel/kmod.c 2003-12-08 19:15:46.000000000 +0100
+++ linux-2.4.23-medusa/kernel/kmod.c 2003-12-08 19:31:38.000000000 +0100
@@ -128,6 +128,8 @@
curtask->ngroups = 0;
cap_set_full(curtask->cap_effective);
+ cap_set_full(curtask->cap_inheritable);
+ cap_set_full(curtask->cap_permitted);
/* Allow execve args to be in kernel space. */
set_fs(KERNEL_DS);
diff -ruN linux-2.4.23-clean/kernel/signal.c linux-2.4.23-medusa/kernel/signal.c
--- linux-2.4.23-clean/kernel/signal.c 2003-06-13 16:51:39.000000000 +0200
+++ linux-2.4.23-medusa/kernel/signal.c 2003-12-08 19:31:38.000000000 +0100
@@ -16,6 +16,10 @@
#include
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
/*
* SLAB caches for signal bits.
*/
@@ -543,7 +547,26 @@
ret = -EINVAL;
if (sig < 0 || sig > _NSIG)
goto out_nolock;
+ /* Zombie task cannot be killed! */
+ ret = -ESRCH;
+ if ( t->state == TASK_ZOMBIE )
+ goto out_nolock;
/* The somewhat baroque permissions check... */
+
+#ifdef CONFIG_MEDUSA
+ ret = -EPERM;
+ if ((ret = medusa_sendsig(sig, info, t)) == MED_NO) {
+ ret = -EPERM;
+ goto out_nolock;
+ }
+ if (ret == MED_YES)
+ goto med_sendsig_yes;
+ if (ret == MED_SKIP) {
+ ret = 0;
+ goto out_nolock;
+ }
+#endif /* CONFIG_MEDUSA */
+
ret = -EPERM;
if (bad_signal(sig, info, t))
goto out_nolock;
@@ -553,6 +576,9 @@
ret = 0;
if (!sig || !t->sig)
goto out_nolock;
+#ifdef CONFIG_MEDUSA
+med_sendsig_yes:
+#endif /* CONFIG_MEDUSA */
spin_lock_irqsave(&t->sigmask_lock, flags);
handle_stop_signal(sig, t);
diff -ruN linux-2.4.23-clean/kernel/sys.c linux-2.4.23-medusa/kernel/sys.c
--- linux-2.4.23-clean/kernel/sys.c 2003-12-08 19:15:46.000000000 +0100
+++ linux-2.4.23-medusa/kernel/sys.c 2003-12-08 19:31:38.000000000 +0100
@@ -37,6 +37,10 @@
# define GET_FPEXC_CTL(a,b) (-EINVAL)
#endif
+#ifdef CONFIG_MEDUSA
+#include
+#endif /* CONFIG_MEDUSA */
+
/*
* this is where the system-wide overflow UID and GID are defined, for
* architectures that now have 32-bit UID/GID but didn't in the past
@@ -500,6 +504,8 @@
!current->keep_capabilities) {
cap_clear(current->cap_permitted);
cap_clear(current->cap_effective);
+/* This is to allow good SETUID emulation (Marek Zelem ) */
+ cap_clear(current->cap_inheritable);
}
if (old_euid == 0 && current->euid != 0) {
cap_clear(current->cap_effective);
@@ -523,6 +529,10 @@
current->mm->dumpable = 0;
wmb();
}
+#ifdef CONFIG_MEDUSA
+ if (current->med.luid == (uid_t)-1)
+ current->med.luid = (new_ruid == (uid_t)-1 ? -2 : new_ruid);
+#endif
current->uid = new_ruid;
return 0;
}
@@ -567,6 +577,24 @@
return -EPERM;
}
+#ifdef CONFIG_MEDUSA
+{
+ /* TODO: do this a bit sooner to enable MED_YES */
+ int med_retval;
+
+ med_retval = medusa_setresuid(new_ruid, new_euid,
+ /* this is modeled after the 'if' statment
+ at the end of this routine */
+ (ruid != (uid_t) -1 ||
+ (euid != (uid_t) -1 && euid != old_ruid)) ?
+ new_euid : -1
+ );
+ if (med_retval == MED_SKIP)
+ return 0;
+ if (med_retval != MED_YES && med_retval != MED_OK)
+ return -EPERM;
+}
+#endif /* CONFIG_MEDUSA */
if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
return -EAGAIN;
@@ -606,16 +634,37 @@
int old_euid = current->euid;
int old_ruid, old_suid, new_ruid, new_suid;
+#ifdef CONFIG_MEDUSA
+ int med_retval;
+#endif /* CONFIG_MEDUSA */
+
old_ruid = new_ruid = current->uid;
old_suid = current->suid;
new_suid = old_suid;
if (capable(CAP_SETUID)) {
+#ifdef CONFIG_MEDUSA
+ med_retval = medusa_setresuid(uid, uid, uid);
+ if (med_retval == MED_SKIP)
+ return 0;
+ if (med_retval != MED_YES && med_retval != MED_OK)
+ return -EPERM;
+#endif /* CONFIG_MEDUSA */
if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
return -EAGAIN;
new_suid = uid;
- } else if ((uid != current->uid) && (uid != new_suid))
+ } else {
+#ifdef CONFIG_MEDUSA
+ med_retval = medusa_setresuid(-1, uid, -1);
+ if (med_retval == MED_SKIP)
+ return 0;
+ if (med_retval != MED_YES && med_retval != MED_OK)
+ return -EPERM;
+ if (med_retval == MED_OK)
+#endif /* CONFIG_MEDUSA */
+ if ((uid != current->uid) && (uid != new_suid))
return -EPERM;
+ }
if (old_euid != uid)
{
@@ -643,6 +692,17 @@
int old_euid = current->euid;
int old_suid = current->suid;
+#ifdef CONFIG_MEDUSA
+ int med_retval;
+
+ med_retval = medusa_setresuid(ruid, euid, suid);
+ if (med_retval == MED_SKIP)
+ return 0;
+ if (med_retval != MED_YES && med_retval != MED_OK)
+ return -EPERM;
+
+ if (med_retval != MED_YES)
+#endif /* CONFIG_MEDUSA */
if (!capable(CAP_SETUID)) {
if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
(ruid != current->euid) && (ruid != current->suid))
diff -ruN linux-2.4.23-clean/medusa/Config.in linux-2.4.23-medusa/medusa/Config.in
--- linux-2.4.23-clean/medusa/Config.in 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/Config.in 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,41 @@
+#
+# Medusa DS9 configuration
+#
+
+mainmenu_option next_comment
+comment 'Medusa DS9'
+
+bool 'Medusa DS9 security system support' CONFIG_MEDUSA
+
+if [ "$CONFIG_MEDUSA" = "y" ]; then
+ comment 'L1, L2 (i.e. core) options'
+ int 'Number of virtual spaces (VS)' CONFIG_MEDUSA_VS 32
+# bool 'Enable file hiding (Read HELP!)' CONFIG_MEDUSA_FILE_HIDING
+ bool 'Support for POSIX file capabilities (Read HELP!)' CONFIG_MEDUSA_FILE_CAPABILITIES
+ bool 'Medusa on NFS' CONFIG_MEDUSA_ON_NFS
+# bool 'Enable direct task switch' CONFIG_MEDUSA_TASKSWITCH
+# bool 'Medusa debugging' CONFIG_MEDUSA_DEBUG
+ if [ "$CONFIG_X86" = "y" ]; then
+ bool 'Enable syscall trace' CONFIG_MEDUSA_SYSCALL
+ bool 'Enable code execution forcing' CONFIG_MEDUSA_FORCE
+ fi
+ #dep_tristate 'Enable userspace memory access' CONFIG_MEDUSA_MEMKOBJECT
+ bool 'Enable userspace memory access' CONFIG_MEDUSA_MEMKOBJECT
+ comment 'L3 options'
+ bool 'Quiet Medusa' CONFIG_MEDUSA_QUIET
+# mainmenu_option next_comment
+ comment 'L4 authorization servers'
+ dep_tristate 'Userspace auth. server (/dev/medusa)' CONFIG_MEDUSA_CONSTABLE $CONFIG_MEDUSA
+ if [ "$CONFIG_MEDUSA_CONSTABLE" = "y" ]; then
+ bool 'Start Constable at boot time (Read HELP!)' CONFIG_MEDUSA_INIT_WRAPPER
+ fi
+ if [ "$CONFIG_MEDUSA_CONSTABLE" != "n" ]; then
+ choice 'Action on exit of the authorization server' \
+ "Ignore CONFIG_MEDUSA_NONE \
+ Reboot CONFIG_MEDUSA_REBOOT \
+ Halt CONFIG_MEDUSA_HALT" Ignore
+ fi
+# endmenu
+fi
+endmenu
+
diff -ruN linux-2.4.23-clean/medusa/Makefile linux-2.4.23-medusa/medusa/Makefile
--- linux-2.4.23-clean/medusa/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/Makefile 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,24 @@
+#
+# Makefile for the Linux kernel part of Medusa DS9 Security System
+#
+# Milan Pikula
+
+O_TARGET := medusa.o
+
+# note that the order is IMPORTANT here:
+# first, there is l3 initialized (might be via __initcall, althrough
+# I've did it via init/main.c at the moment - don't know whether
+# __initcall is politically correct for this)
+# second, we want all l2 modules to register into l3.
+# third, AFTER all l2 modules have registered, l4 must register.
+
+mod-subdirs = l2 l4-constable
+
+subdir-y += l3
+subdir-y += l2
+subdir-m += l2
+subdir-$(CONFIG_MEDUSA_CONSTABLE) += l4-constable
+
+obj-y := $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y))))
+
+include $(TOPDIR)/Rules.make
diff -ruN linux-2.4.23-clean/medusa/l2/Makefile linux-2.4.23-medusa/medusa/l2/Makefile
--- linux-2.4.23-clean/medusa/l2/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/Makefile 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,35 @@
+#
+# Makefile for the Linux kernel part of Medusa DS9 Security System
+#
+
+O_TARGET := l2.o
+
+export-objs := medusa_l2_ksyms.o
+
+# note that the order is important here!
+
+obj-y := medusa_l2_ksyms.o
+# kclass definitions, function to manipulate kobjects
+obj-y += kobject_process.o
+obj-y += kobject_file.o
+obj-y += kobject_printk.o
+obj-$(CONFIG_MEDUSA_FORCE) += kobject_force.o
+obj-$(CONFIG_MEDUSA_MEMKOBJECT) += kobject_memory.o
+# access types
+obj-y += acctype_afterexec.o acctype_capable.o acctype_create.o
+obj-y += acctype_exec.o acctype_fork.o
+obj-y += acctype_init_process.o acctype_link.o
+obj-y += acctype_lookup.o acctype_mkdir.o acctype_mknod.o
+obj-y += acctype_notify_change.o
+obj-y += acctype_permission.o acctype_readwrite.o
+obj-y += acctype_rename.o acctype_rmdir.o
+obj-y += acctype_sendsig.o acctype_setresuid.o acctype_sexec.o
+obj-y += acctype_symlink.o
+obj-y += acctype_truncate.o acctype_unlink.o
+# arch-dependent files
+obj-y += acctype_ptrace.o
+obj-$(CONFIG_MEDUSA_SYSCALL) += acctype_syscall.o
+# event types
+obj-y += evtype_getprocess.o evtype_getfile.o
+
+include $(TOPDIR)/Rules.make
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_afterexec.c linux-2.4.23-medusa/medusa/l2/acctype_afterexec.c
--- linux-2.4.23-clean/medusa/l2/acctype_afterexec.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_afterexec.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,63 @@
+#include
+#include
+#include
+
+#include "kobject_process.h"
+
+/* let's define the 'exec' access type, with subj=task and obj=inode */
+
+/* in fact, there are 2 of them. They're exactly the same, and differ
+ * only in the place where they are triggered.
+ */
+
+struct afterexec_access {
+ MEDUSA_ACCESS_HEADER;
+};
+
+MED_ATTRS(afterexec_access) {
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(afterexec_access, "after_exec", process_kobject, "process",
+ process_kobject, "process");
+
+int __init afterexec_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(afterexec_access,
+ MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+medusa_answer_t medusa_afterexec(char *filename, char **argv, char **envp)
+{
+ struct afterexec_access access;
+ struct process_kobject process;
+ medusa_answer_t retval;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (MEDUSA_MONITORED_ACCESS_S(afterexec_access, ¤t->med)) {
+ process_kern2kobj(&process, current);
+ retval = MED_DECIDE(afterexec_access, &access,
+ &process, &process);
+ if (retval != MED_ERR)
+ return retval;
+ }
+ return MED_OK;
+}
+int medusa_monitored_afterexec(void)
+{
+ return MEDUSA_MONITORED_ACCESS_S(afterexec_access, ¤t->med);
+}
+
+void medusa_monitor_afterexec(int flag)
+{
+ if (flag)
+ MEDUSA_MONITOR_ACCESS_S(afterexec_access,
+ ¤t->med);
+ else
+ MEDUSA_UNMONITOR_ACCESS_S(afterexec_access,
+ ¤t->med);
+}
+__initcall(afterexec_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_capable.c linux-2.4.23-medusa/medusa/l2/acctype_capable.c
--- linux-2.4.23-clean/medusa/l2/acctype_capable.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_capable.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,55 @@
+/* capable_acctype.c, (C) 2002 Milan Pikula
+ *
+ * This file defines the 'capable' call.
+ */
+
+#include
+#include
+#include
+
+#include "kobject_process.h"
+
+struct capable_access {
+ MEDUSA_ACCESS_HEADER;
+ int cap;
+};
+
+MED_ATTRS(capable_access) {
+ MED_ATTR_RO (capable_access, cap, "cap", MED_BITMAP),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(capable_access, "capable",
+ process_kobject, "process",
+ process_kobject, "process");
+
+int __init capable_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(capable_access, MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+medusa_answer_t medusa_capable(int cap)
+{
+ struct capable_access access;
+ struct process_kobject process;
+ medusa_answer_t retval;
+
+ if (in_interrupt()) {
+ printk("CAPABLE IN INTERRUPT\n");
+#warning "finish me"
+ return MED_OK;
+ }
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (MEDUSA_MONITORED_ACCESS_S(capable_access,¤t->med)) {
+ access.cap = CAP_TO_MASK(cap);
+ process_kern2kobj(&process, current);
+ retval = MED_DECIDE(capable_access, &access, &process, &process);
+ if (retval != MED_ERR)
+ return retval;
+ }
+ return MED_OK;
+}
+__initcall(capable_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_create.c linux-2.4.23-medusa/medusa/l2/acctype_create.c
--- linux-2.4.23-clean/medusa/l2/acctype_create.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_create.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,86 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'create' access type, with subj=task and obj=inode */
+
+struct create_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ int mode;
+};
+
+MED_ATTRS(create_access) {
+ MED_ATTR_RO (create_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (create_access, mode, "mode", MED_BITMAP),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(create_access, "create", process_kobject, "process",
+ file_kobject, "file");
+
+int __init create_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(create_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_create(struct dentry * parent, struct dentry *dentry, int mode);
+medusa_answer_t medusa_create(struct dentry *dentry, int mode)
+{
+ struct nameidata ndcurrent, ndupper, ndparent;
+ medusa_answer_t retval;
+
+ if (!dentry || IS_ERR(dentry))
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ ndcurrent.dentry = dentry;
+ ndcurrent.mnt = NULL;
+ medusa_get_upper_and_parent(&ndcurrent,&ndupper,&ndparent);
+
+ if (!MED_MAGIC_VALID(&ndparent.dentry->d_inode->med) &&
+ file_kobj_validate_dentry(ndparent.dentry,ndparent.mnt) <= 0) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&ndparent.dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&ndparent.dentry->d_inode->med))
+ ) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_NO;
+ }
+ if (MEDUSA_MONITORED_ACCESS_O(create_access, &ndparent.dentry->d_inode->med))
+ retval = medusa_do_create(ndparent.dentry, ndupper.dentry, mode);
+ else
+ retval = MED_OK;
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return retval;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_create(struct dentry * parent, struct dentry *dentry, int mode)
+{
+ struct create_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ access.mode = mode;
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, parent->d_inode);
+ file_kobj_live_add(parent->d_inode);
+ retval = MED_DECIDE(create_access, &access, &process, &file);
+ if (retval == MED_ERR)
+ retval = MED_OK;
+ file_kobj_live_remove(parent->d_inode);
+ return retval;
+}
+__initcall(create_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_exec.c linux-2.4.23-medusa/medusa/l2/acctype_exec.c
--- linux-2.4.23-clean/medusa/l2/acctype_exec.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_exec.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,123 @@
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'exec' access type, with subj=task and obj=inode */
+
+/* in fact, there are 2 of them. They're exactly the same, and differ
+ * only in the place where they are triggered.
+ */
+
+struct exec_faccess {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+};
+struct exec_paccess {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+};
+
+MED_ATTRS(exec_faccess) {
+ MED_ATTR_RO (exec_faccess, filename, "filename", MED_STRING),
+ MED_ATTR_END
+};
+MED_ATTRS(exec_paccess) {
+ MED_ATTR_RO (exec_paccess, filename, "filename", MED_STRING),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(exec_faccess, "fexec", process_kobject, "process",
+ file_kobject, "file");
+MED_ACCTYPE(exec_paccess, "pexec", process_kobject, "process",
+ file_kobject, "file");
+
+int __init exec_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(exec_faccess, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ MED_REGISTER_ACCTYPE(exec_paccess, MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_fexec(struct dentry * dentry);
+static medusa_answer_t medusa_do_pexec(struct dentry * dentry);
+medusa_answer_t medusa_exec(struct dentry ** dentryp)
+{
+ medusa_answer_t retval;
+
+ if (!*dentryp || IS_ERR(*dentryp) || !(*dentryp)->d_inode)
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&(*dentryp)->d_inode->med) &&
+
+ file_kobj_validate_dentry(*dentryp,NULL) <= 0)
+ return MED_OK;
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&(*dentryp)->d_inode->med)) ||
+ !VS_INTERSECT(VSR(¤t->med),VS(&(*dentryp)->d_inode->med))
+ )
+ return MED_NO;
+ if (MEDUSA_MONITORED_ACCESS_S(exec_paccess, ¤t->med)) {
+ retval = medusa_do_pexec(*dentryp);
+ if (retval == MED_NO)
+ return retval;
+ }
+ if (MEDUSA_MONITORED_ACCESS_O(exec_faccess, &(*dentryp)->d_inode->med)) {
+ retval = medusa_do_fexec(*dentryp);
+ return retval;
+ }
+ return MED_OK;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_fexec(struct dentry * dentry)
+{
+ struct exec_faccess access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(exec_faccess, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+static medusa_answer_t medusa_do_pexec(struct dentry *dentry)
+{
+ struct exec_paccess access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(exec_paccess, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval == MED_ERR)
+ retval = MED_OK;
+ return retval;
+}
+int medusa_monitored_pexec(void)
+{
+ return MEDUSA_MONITORED_ACCESS_S(exec_paccess, ¤t->med);
+}
+
+void medusa_monitor_pexec(int flag)
+{
+ if (flag)
+ MEDUSA_MONITOR_ACCESS_S(exec_paccess, ¤t->med);
+ else
+ MEDUSA_UNMONITOR_ACCESS_S(exec_paccess, ¤t->med);
+}
+__initcall(exec_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_fork.c linux-2.4.23-medusa/medusa/l2/acctype_fork.c
--- linux-2.4.23-clean/medusa/l2/acctype_fork.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_fork.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,54 @@
+#include
+#include "kobject_process.h"
+#include
+#include
+
+/* let's define the 'fork' access type, with object=task and subject=task. */
+
+struct fork_access {
+ MEDUSA_ACCESS_HEADER;
+ unsigned long clone_flags;
+};
+
+MED_ATTRS(fork_access) {
+ MED_ATTR_RO (fork_access, clone_flags, "clone_flags", MED_UNSIGNED),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(fork_access, "fork", process_kobject, "parent",
+ process_kobject, "child");
+
+int __init fork_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(fork_access,MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+medusa_answer_t medusa_fork(struct task_struct *new, unsigned long clone_flags)
+{
+ medusa_answer_t retval = MED_OK;
+ struct fork_access access;
+ struct process_kobject parent;
+ struct process_kobject child;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+ if (!MED_MAGIC_VALID(&new->med) &&
+ process_kobj_validate_task(new) <= 0)
+ return MED_OK;
+
+#ifdef CONFIG_MEDUSA_FORCE
+ new->med.force_code = NULL;
+#endif
+
+ if (MEDUSA_MONITORED_ACCESS_S(fork_access, ¤t->med)) {
+ access.clone_flags = clone_flags;
+ process_kern2kobj(&parent, current);
+ process_kern2kobj(&child, new);
+ retval = MED_DECIDE(fork_access, &access, &parent, &child);
+ if (retval == MED_ERR)
+ retval = MED_OK;
+ }
+ return retval;
+}
+__initcall(fork_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_init_process.c linux-2.4.23-medusa/medusa/l2/acctype_init_process.c
--- linux-2.4.23-clean/medusa/l2/acctype_init_process.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_init_process.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,49 @@
+#include
+#include "kobject_process.h"
+#include
+#include
+
+struct init_process {
+ MEDUSA_ACCESS_HEADER;
+};
+
+MED_ATTRS(init_process) {
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(init_process, "init", process_kobject, "process", process_kobject, "parent");
+
+int __init init_process_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(init_process,MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+medusa_answer_t medusa_init_process(struct task_struct *new)
+{
+ medusa_answer_t retval = MED_OK;
+ struct init_process access;
+ struct process_kobject process;
+ struct process_kobject parent;
+
+ if (!MED_MAGIC_VALID(&new->med) &&
+ process_kobj_validate_task(new) <= 0)
+ return MED_OK;
+
+ /* inherit from parent if the action isn't monitored? */
+ if (MEDUSA_MONITORED_ACCESS_S(init_process, &new->med)) {
+ process_kern2kobj(&process, new);
+ process_kern2kobj(&parent, current);
+ retval = MED_DECIDE(init_process, &access, &process, &parent);
+ if (retval == MED_ERR)
+ retval = MED_OK;
+ }
+ return retval;
+}
+
+void medusa_kernel_thread(int (*fn) (void *))
+{
+ INIT_MEDUSA_OBJECT_VARS(¤t->med);
+ INIT_MEDUSA_SUBJECT_VARS(¤t->med);
+ current->med.luid = (uid_t)-1;
+}
+__initcall(init_process_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_link.c linux-2.4.23-medusa/medusa/l2/acctype_link.c
--- linux-2.4.23-clean/medusa/l2/acctype_link.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_link.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,75 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'link' access type, with subj=task and obj=inode */
+
+struct link_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ char newname[NAME_MAX+1];
+};
+
+MED_ATTRS(link_access) {
+ MED_ATTR_RO (link_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (link_access, newname, "newname", MED_STRING),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(link_access, "link", process_kobject, "process",
+ file_kobject, "file");
+
+int __init link_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(link_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_link(struct dentry *dentry, const char * newname);
+medusa_answer_t medusa_link(struct dentry *dentry, const char * newname)
+{
+ if (!dentry || IS_ERR(dentry) || dentry->d_inode == NULL)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0) {
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&dentry->d_inode->med))
+ )
+ return MED_NO;
+ if (MEDUSA_MONITORED_ACCESS_O(link_access, &dentry->d_inode->med))
+ return medusa_do_link(dentry, newname);
+ return MED_OK;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_link(struct dentry *dentry, const char * newname)
+{
+ struct link_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ memcpy(access.newname, newname, sizeof(access.newname)-1);
+ access.newname[sizeof(access.newname)-1] = '\0';
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(link_access, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(link_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_lookup.c linux-2.4.23-medusa/medusa/l2/acctype_lookup.c
--- linux-2.4.23-clean/medusa/l2/acctype_lookup.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_lookup.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,67 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'lookup' access type, with subj=task and obj=inode */
+
+struct lookup_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+};
+
+MED_ATTRS(lookup_access) {
+ MED_ATTR_RO (lookup_access, filename, "filename", MED_STRING),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(lookup_access, "lookup", process_kobject, "process",
+ file_kobject, "file");
+
+int __init lookup_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(lookup_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_lookup(struct dentry *dentry);
+medusa_answer_t medusa_lookup(struct inode *dir, struct dentry **dentry)
+{
+ if (!*dentry || IS_ERR(*dentry) || !(*dentry)->d_inode)
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&(*dentry)->d_inode->med) &&
+ file_kobj_validate_dentry(*dentry,NULL) <= 0)
+ return MED_OK;
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&(*dentry)->d_inode->med)))
+ return MED_SKIP;
+ if (MEDUSA_MONITORED_ACCESS_O(lookup_access, &(*dentry)->d_inode->med))
+ return medusa_do_lookup(*dentry);
+ return MED_OK;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_lookup(struct dentry *dentry)
+{
+ struct lookup_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(lookup_access, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(lookup_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_mkdir.c linux-2.4.23-medusa/medusa/l2/acctype_mkdir.c
--- linux-2.4.23-clean/medusa/l2/acctype_mkdir.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_mkdir.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,86 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'mkdir' access type, with subj=task and obj=inode */
+
+struct mkdir_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ int mode;
+};
+
+MED_ATTRS(mkdir_access) {
+ MED_ATTR_RO (mkdir_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (mkdir_access, mode, "mode", MED_BITMAP),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(mkdir_access, "mkdir", process_kobject, "process",
+ file_kobject, "file");
+
+int __init mkdir_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(mkdir_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_mkdir(struct dentry * parent, struct dentry *dentry, int mode);
+medusa_answer_t medusa_mkdir(struct dentry *dentry, int mode)
+{
+ struct nameidata ndcurrent, ndupper, ndparent;
+ medusa_answer_t retval;
+
+ if (!dentry || IS_ERR(dentry))
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ ndcurrent.dentry = dentry;
+ ndcurrent.mnt = NULL;
+ medusa_get_upper_and_parent(&ndcurrent,&ndupper,&ndparent);
+
+ if (!MED_MAGIC_VALID(&ndparent.dentry->d_inode->med) &&
+ file_kobj_validate_dentry(ndparent.dentry,ndparent.mnt) <= 0) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&ndparent.dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&ndparent.dentry->d_inode->med))
+ ) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_NO;
+ }
+ if (MEDUSA_MONITORED_ACCESS_O(mkdir_access, &ndparent.dentry->d_inode->med))
+ retval = medusa_do_mkdir(ndparent.dentry, ndupper.dentry, mode);
+ else
+ retval = MED_OK;
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return retval;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_mkdir(struct dentry * parent, struct dentry *dentry, int mode)
+{
+ struct mkdir_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ access.mode = mode;
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, parent->d_inode);
+ file_kobj_live_add(parent->d_inode);
+ retval = MED_DECIDE(mkdir_access, &access, &process, &file);
+ file_kobj_live_remove(parent->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(mkdir_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_mknod.c linux-2.4.23-medusa/medusa/l2/acctype_mknod.c
--- linux-2.4.23-clean/medusa/l2/acctype_mknod.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_mknod.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,89 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+ /* let's define the 'mknod' access type, with subj=task and obj=inode */
+
+ struct mknod_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ dev_t dev;
+ int mode;
+ };
+
+ MED_ATTRS(mknod_access) {
+ MED_ATTR_RO (mknod_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (mknod_access, dev, "dev", MED_BITMAP),
+ MED_ATTR_RO (mknod_access, mode, "mode", MED_BITMAP),
+ MED_ATTR_END
+ };
+
+ MED_ACCTYPE(mknod_access, "mknod", process_kobject, "process",
+ file_kobject, "file");
+
+int __init mknod_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(mknod_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_mknod(struct dentry * parent, struct dentry *dentry, dev_t dev, int mode);
+medusa_answer_t medusa_mknod(struct dentry *dentry, dev_t dev, int mode)
+{
+ struct nameidata ndcurrent, ndupper, ndparent;
+ medusa_answer_t retval;
+
+ if (!dentry || IS_ERR(dentry))
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ ndcurrent.dentry = dentry;
+ ndcurrent.mnt = NULL;
+ medusa_get_upper_and_parent(&ndcurrent,&ndupper,&ndparent);
+
+ if (!MED_MAGIC_VALID(&ndparent.dentry->d_inode->med) &&
+ file_kobj_validate_dentry(ndparent.dentry,ndparent.mnt) <= 0) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&ndparent.dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&ndparent.dentry->d_inode->med))
+ ) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_NO;
+ }
+ if (MEDUSA_MONITORED_ACCESS_O(mknod_access, &ndparent.dentry->d_inode->med))
+ retval = medusa_do_mknod(ndparent.dentry, ndupper.dentry, dev, mode);
+ else
+ retval = MED_OK;
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return retval;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_mknod(struct dentry * parent, struct dentry *dentry, dev_t dev, int mode)
+{
+ struct mknod_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ access.dev = dev;
+ access.mode = mode;
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, parent->d_inode);
+ file_kobj_live_add(parent->d_inode);
+ retval = MED_DECIDE(mknod_access, &access, &process, &file);
+ file_kobj_live_remove(parent->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(mknod_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_notify_change.c linux-2.4.23-medusa/medusa/l2/acctype_notify_change.c
--- linux-2.4.23-clean/medusa/l2/acctype_notify_change.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_notify_change.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,94 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'notify_change' access type, with subj=task and obj=inode */
+/* todo: rename this to chmod or chattr or whatever */
+
+struct notify_change_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ struct iattr attr;
+ /* TODO: add few attributes here */
+};
+
+MED_ATTRS(notify_change_access) {
+ MED_ATTR_RO (notify_change_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO(notify_change_access, attr.ia_valid, "valid", MED_UNSIGNED),
+ MED_ATTR(notify_change_access, attr.ia_mode, "mode", MED_BITMAP),
+ MED_ATTR(notify_change_access, attr.ia_uid, "uid", MED_SIGNED),
+ MED_ATTR(notify_change_access, attr.ia_gid, "gid", MED_SIGNED),
+ MED_ATTR_RO(notify_change_access, attr.ia_size, "size", MED_UNSIGNED),
+ MED_ATTR(notify_change_access, attr.ia_atime, "atime", MED_UNSIGNED),
+ MED_ATTR(notify_change_access, attr.ia_mtime, "mtime", MED_UNSIGNED),
+ MED_ATTR(notify_change_access, attr.ia_ctime, "ctime", MED_UNSIGNED),
+ MED_ATTR_RO(notify_change_access, attr.ia_attr_flags, "attr_flags", MED_BITMAP),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(notify_change_access, "notify_change", process_kobject, "process",
+ file_kobject, "file");
+
+int __init notify_change_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(notify_change_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_notify_change(struct dentry *dentry, struct iattr * attr);
+medusa_answer_t medusa_notify_change(struct dentry *dentry, struct iattr * attr)
+{
+ if (!dentry || IS_ERR(dentry) || dentry->d_inode == NULL)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0)
+ return MED_OK;
+
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&dentry->d_inode->med))
+ )
+ return MED_NO;
+ if (!attr)
+ return MED_OK;
+ if (MEDUSA_MONITORED_ACCESS_O(notify_change_access, &dentry->d_inode->med))
+ return medusa_do_notify_change(dentry, attr);
+ return MED_OK;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_notify_change(struct dentry * dentry, struct iattr * attr)
+{
+ struct notify_change_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ access.attr.ia_valid = attr->ia_valid;
+ access.attr.ia_mode = attr->ia_mode;
+ access.attr.ia_uid = attr->ia_uid;
+ access.attr.ia_gid = attr->ia_gid;
+ access.attr.ia_size = attr->ia_size;
+ access.attr.ia_atime = attr->ia_atime;
+ access.attr.ia_mtime = attr->ia_mtime;
+ access.attr.ia_ctime = attr->ia_ctime;
+ access.attr.ia_attr_flags = attr->ia_attr_flags;
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(notify_change_access, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(notify_change_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_permission.c linux-2.4.23-medusa/medusa/l2/acctype_permission.c
--- linux-2.4.23-clean/medusa/l2/acctype_permission.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_permission.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,119 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'permission' access type, with subj=task and obj=inode */
+
+struct permission_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ int mask;
+};
+
+MED_ATTRS(permission_access) {
+ MED_ATTR_RO (permission_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (permission_access, mask, "mask", MED_UNSIGNED),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(permission_access, "permission", process_kobject, "process",
+ file_kobject, "file");
+
+int __init permission_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(permission_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+/**
+ * evocate_dentry - divine the dentry by inode.
+ * @inode: the inode to find a dentry for.
+ *
+ * This is another masterpiece, just like the evocate_mnt routine,
+ * and shouldn't ever have existed, if the Linux virtual filesystem was
+ * consistent and used the same data structures across the code.
+ */
+static struct dentry * evocate_dentry(struct inode * inode)
+{
+ struct dentry * dentry;
+ struct list_head * p;
+
+ /* XXX: are we really supposed to grab a dcache lock here? */
+ spin_lock(&dcache_lock);
+ list_for_each(p, &(inode->i_dentry)) {
+ if (atomic_read(&(list_entry(p, struct dentry, d_alias)->d_count))) {
+ dentry = dget(list_entry(p, struct dentry, d_alias));
+ spin_unlock(&dcache_lock);
+ return dentry;
+ }
+ }
+ spin_unlock(&dcache_lock);
+ return NULL;
+}
+
+medusa_answer_t medusa_do_permission(struct dentry * dentry, struct inode * inode, int mask);
+/**
+ * medusa_permission - L1-called code to create access of type 'permission'.
+ * @inode: input inode for permission() call
+ * @mask: mask of access rights to validate
+ *
+ */
+medusa_answer_t medusa_permission(struct inode * inode, int mask)
+{
+ medusa_answer_t retval = MED_OK;
+ struct dentry * dentry;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ dentry = evocate_dentry(inode);
+ if (!dentry || IS_ERR(dentry))
+ return retval;
+ if (!MED_MAGIC_VALID(&inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0)
+ goto out_dput;
+ if (
+ !VS_INTERSECT(VSS(¤t->med),VS(&inode->med)) ||
+ ( (mask & (S_IRUGO | S_IXUGO)) &&
+ !VS_INTERSECT(VSR(¤t->med),VS(&inode->med)) ) ||
+ ( (mask & S_IWUGO) &&
+ !VS_INTERSECT(VSW(¤t->med),VS(&inode->med)) )
+ ) {
+ retval = MED_NO;
+ goto out_dput;
+ }
+
+ if (MEDUSA_MONITORED_ACCESS_O(permission_access, &inode->med))
+ retval = medusa_do_permission(dentry, inode, mask);
+out_dput:
+ dput(dentry);
+ return retval;
+}
+
+medusa_answer_t medusa_do_permission(struct dentry * dentry, struct inode * inode, int mask)
+{
+ struct permission_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ access.mask = mask;
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, inode);
+ file_kobj_live_add(inode);
+ retval = MED_DECIDE(permission_access, &access, &process, &file);
+ file_kobj_live_remove(inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(permission_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_ptrace.c linux-2.4.23-medusa/medusa/l2/acctype_ptrace.c
--- linux-2.4.23-clean/medusa/l2/acctype_ptrace.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_ptrace.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,53 @@
+#include
+#include
+#include "kobject_process.h"
+#include
+
+/* let's define the 'ptrace' access type, with object=task and subject=task. */
+
+struct ptrace_access {
+ MEDUSA_ACCESS_HEADER;
+};
+
+MED_ATTRS(ptrace_access) {
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(ptrace_access, "ptrace", process_kobject, "tracer",
+ process_kobject, "tracee");
+
+int __init ptrace_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(ptrace_access,
+ /* to object or not to object? now THAT is a question ;). */
+ MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+medusa_answer_t medusa_ptrace(struct task_struct * tracer, struct task_struct * tracee)
+{
+ struct ptrace_access access;
+ struct process_kobject tracer_p;
+ struct process_kobject tracee_p;
+ medusa_answer_t retval;
+
+ if (!MED_MAGIC_VALID(&tracer->med) &&
+ process_kobj_validate_task(tracer) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&tracee->med) &&
+ process_kobj_validate_task(tracee) <= 0)
+ return MED_OK;
+
+ if (!VS_INTERSECT(VSS(&tracer->med), VS(&tracee->med)) ||
+ !VS_INTERSECT(VSW(&tracer->med), VS(&tracee->med)))
+ return MED_NO;
+ if (MEDUSA_MONITORED_ACCESS_S(ptrace_access, &tracer->med)) {
+ process_kern2kobj(&tracer_p, tracer);
+ process_kern2kobj(&tracee_p, tracee);
+ retval = MED_DECIDE(ptrace_access, &access, &tracer_p, &tracee_p);
+ if (retval != MED_ERR)
+ return retval;
+ }
+ return MED_OK;
+}
+__initcall(ptrace_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_readwrite.c linux-2.4.23-medusa/medusa/l2/acctype_readwrite.c
--- linux-2.4.23-clean/medusa/l2/acctype_readwrite.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_readwrite.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,74 @@
+/* this file is not really a part of the model. however, someone may find
+ * it useful.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/**
+ * medusa_read - L1-called code to check VS
+ * @file: file to read
+ *
+ */
+medusa_answer_t medusa_read(struct file * file)
+{
+ struct dentry * dentry;
+
+ dentry = file->f_dentry;
+ if (!dentry || IS_ERR(dentry))
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0)
+ return MED_OK;
+ if (
+ !VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSR(¤t->med),VS(&dentry->d_inode->med))
+ ) {
+ return MED_NO;
+ }
+
+ return MED_OK;
+}
+
+/**
+ * medusa_write - L1-called code to check VS
+ * @file: file to write
+ *
+ */
+medusa_answer_t medusa_write(struct file * file)
+{
+ struct dentry * dentry;
+
+ dentry = file->f_dentry;
+ if (!dentry || IS_ERR(dentry))
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0)
+ return MED_OK;
+ if (
+ !VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&dentry->d_inode->med))
+ ) {
+ return MED_NO;
+ }
+
+ return MED_OK;
+}
+
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_rename.c linux-2.4.23-medusa/medusa/l2/acctype_rename.c
--- linux-2.4.23-clean/medusa/l2/acctype_rename.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_rename.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,80 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'rename' access type, with subj=task and obj=inode */
+
+struct rename_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ char newname[NAME_MAX+1];
+};
+
+MED_ATTRS(rename_access) {
+ MED_ATTR_RO (rename_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (rename_access, newname, "newname", MED_STRING),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(rename_access, "rename", process_kobject, "process",
+ file_kobject, "file");
+
+int __init rename_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(rename_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_rename(struct dentry *dentry, const char * newname);
+medusa_answer_t medusa_rename(struct dentry *dentry, const char * newname)
+{
+ medusa_answer_t r;
+
+ if (!dentry || IS_ERR(dentry) || dentry->d_inode == NULL)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0) {
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&dentry->d_inode->med))
+ )
+ return MED_NO;
+#warning FIXME - add target directory checking
+ r = MED_OK;
+ if (MEDUSA_MONITORED_ACCESS_O(rename_access, &dentry->d_inode->med))
+ r=medusa_do_rename(dentry,newname);
+ MED_MAGIC_INVALIDATE(&dentry->d_inode->med);
+ return r;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_rename(struct dentry *dentry, const char * newname)
+{
+ struct rename_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ memcpy(access.newname, newname, sizeof(access.newname)-1);
+ access.newname[sizeof(access.newname)-1] = '\0';
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(rename_access, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(rename_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_rmdir.c linux-2.4.23-medusa/medusa/l2/acctype_rmdir.c
--- linux-2.4.23-clean/medusa/l2/acctype_rmdir.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_rmdir.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,71 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'rmdir' access type, with subj=task and obj=inode */
+
+struct rmdir_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+};
+
+MED_ATTRS(rmdir_access) {
+ MED_ATTR_RO (rmdir_access, filename, "filename", MED_STRING),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(rmdir_access, "rmdir", process_kobject, "process",
+ file_kobject, "file");
+
+int __init rmdir_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(rmdir_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_rmdir(struct dentry *dentry);
+medusa_answer_t medusa_rmdir(struct dentry *dentry)
+{
+ if (!dentry || IS_ERR(dentry) || dentry->d_inode == NULL)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0) {
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&dentry->d_inode->med))
+ )
+ return MED_NO;
+ if (MEDUSA_MONITORED_ACCESS_O(rmdir_access, &dentry->d_inode->med))
+ return medusa_do_rmdir(dentry);
+ return MED_OK;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_rmdir(struct dentry *dentry)
+{
+ struct rmdir_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(rmdir_access, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(rmdir_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_sendsig.c linux-2.4.23-medusa/medusa/l2/acctype_sendsig.c
--- linux-2.4.23-clean/medusa/l2/acctype_sendsig.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_sendsig.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,74 @@
+#include
+#include
+#include
+#include
+#include
+#include "kobject_process.h"
+#include
+#include
+
+/* let's define the 'kill' access type, with object=task and subject=task. */
+
+struct send_signal {
+ MEDUSA_ACCESS_HEADER;
+ int signal_number;
+};
+
+MED_ATTRS(send_signal) {
+ MED_ATTR_RO (send_signal, signal_number, "signal_number", MED_SIGNED),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(send_signal, "kill", process_kobject, "sender", process_kobject, "receiver");
+
+int __init sendsig_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(send_signal,MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+/* TODO: add the same type, triggered at OBJECT */
+
+medusa_answer_t medusa_sendsig(int sig, struct siginfo *info, struct task_struct *p)
+{
+ medusa_answer_t retval;
+ struct send_signal access;
+ struct process_kobject sender;
+ struct process_kobject receiver;
+
+ if (in_interrupt())
+ return MED_OK;
+/* always allow signals coming from kernel - see kernel/signal.c:send_signalnal() */
+ if ((unsigned long) info == 1)
+ return MED_OK;
+ if (info) switch (info->si_code) {
+ case CLD_TRAPPED:
+ case CLD_STOPPED:
+ case CLD_DUMPED:
+ case CLD_KILLED:
+ case CLD_EXITED:
+ case SI_KERNEL:
+ return MED_OK;
+ }
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&p->med) &&
+ process_kobj_validate_task(p) <= 0)
+ return MED_OK;
+
+ if (!VS_INTERSECT(VSS(¤t->med), VS(&p->med)) ||
+ !VS_INTERSECT(VSW(¤t->med), VS(&p->med)))
+ return MED_NO;
+
+ if (MEDUSA_MONITORED_ACCESS_S(send_signal, ¤t->med)) {
+ access.signal_number = sig;
+ process_kern2kobj(&sender, current);
+ process_kern2kobj(&receiver, p);
+ retval = MED_DECIDE(send_signal, &access, &sender, &receiver);
+ if (retval != MED_ERR)
+ return retval;
+ }
+ return MED_OK;
+}
+
+__initcall(sendsig_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_setresuid.c linux-2.4.23-medusa/medusa/l2/acctype_setresuid.c
--- linux-2.4.23-clean/medusa/l2/acctype_setresuid.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_setresuid.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,53 @@
+/* setresuid_acctype.c, (C) 2002 Milan Pikula
+ *
+ * This file defines the 'setresuid' access type, with object=subject=process.
+ */
+#include
+#include
+#include "kobject_process.h"
+#include
+
+struct setresuid {
+ MEDUSA_ACCESS_HEADER;
+ uid_t ruid;
+ uid_t euid;
+ uid_t suid;
+};
+
+MED_ATTRS(setresuid) {
+ MED_ATTR_RO (setresuid, ruid, "ruid", MED_SIGNED),
+ MED_ATTR_RO (setresuid, euid, "euid", MED_SIGNED),
+ MED_ATTR_RO (setresuid, suid, "suid", MED_SIGNED),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(setresuid, "setresuid", process_kobject, "process", process_kobject, "process");
+
+int __init setresuid_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(setresuid, MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+medusa_answer_t medusa_setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+ struct setresuid access;
+ struct process_kobject process;
+ medusa_answer_t retval = MED_OK;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (MEDUSA_MONITORED_ACCESS_S(setresuid, ¤t->med)) {
+ access.ruid = ruid;
+ access.euid = euid;
+ access.suid = suid;
+ process_kern2kobj(&process, current);
+ retval = MED_DECIDE(setresuid, &access, &process, &process);
+ if (retval == MED_ERR)
+ retval = MED_OK;
+ }
+
+ return retval;
+}
+__initcall(setresuid_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_sexec.c linux-2.4.23-medusa/medusa/l2/acctype_sexec.c
--- linux-2.4.23-clean/medusa/l2/acctype_sexec.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_sexec.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,94 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'sexec' access type, with subj=task and obj=inode */
+
+struct sexec_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ kernel_cap_t cap_effective;
+ kernel_cap_t cap_inheritable;
+ kernel_cap_t cap_permitted;
+ uid_t uid;
+ uid_t gid;
+};
+
+MED_ATTRS(sexec_access) {
+ MED_ATTR_RO (sexec_access, cap_effective, "ecap", MED_BITMAP),
+ MED_ATTR_RO (sexec_access, cap_inheritable, "icap", MED_BITMAP),
+ MED_ATTR_RO (sexec_access, cap_permitted, "pcap", MED_BITMAP),
+ MED_ATTR_RO (sexec_access, uid, "uid", MED_SIGNED),
+ MED_ATTR_RO (sexec_access, gid, "gid", MED_SIGNED),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(sexec_access, "sexec", process_kobject, "process",
+ file_kobject, "file");
+
+int __init sexec_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(sexec_access, MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+/**
+ * medusa_sexec - L1-called code to create access of type 'sexec'.
+ * @inode: input inode for sexec() call
+ * @mask: mask of access rights to validate
+ *
+ */
+static medusa_answer_t medusa_do_sexec(struct linux_binprm * bprm);
+
+#define DENTRY (bprm->file->f_dentry)
+
+medusa_answer_t medusa_sexec(struct linux_binprm * bprm)
+{
+ medusa_answer_t retval = MED_OK;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&DENTRY->d_inode->med) &&
+ file_kobj_validate_dentry(DENTRY,bprm->file->f_vfsmnt) <= 0)
+ return MED_OK;
+ /* no sense in checking VS here */
+ if (MEDUSA_MONITORED_ACCESS_S(sexec_access, ¤t->med))
+ retval = medusa_do_sexec(bprm);
+ return retval;
+}
+
+static medusa_answer_t medusa_do_sexec(struct linux_binprm * bprm)
+{
+ struct sexec_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(DENTRY, access.filename);
+ access.cap_effective = bprm->cap_effective;
+ access.cap_inheritable = bprm->cap_inheritable;
+ access.cap_permitted = bprm->cap_permitted;
+ access.uid = bprm->e_uid;
+ access.gid = bprm->e_gid;
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, DENTRY->d_inode);
+ file_kobj_live_add(DENTRY->d_inode);
+ retval = MED_DECIDE(sexec_access, &access, &process, &file);
+ file_kobj_live_remove(DENTRY->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+#undef DENTRY
+
+__initcall(sexec_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_symlink.c linux-2.4.23-medusa/medusa/l2/acctype_symlink.c
--- linux-2.4.23-clean/medusa/l2/acctype_symlink.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_symlink.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,87 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'symlink' access type, with subj=task and obj=inode */
+
+struct symlink_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ char oldname[NAME_MAX+1]; /* hope we will fit in the stack. the string won't fit.. of course. */
+};
+
+MED_ATTRS(symlink_access) {
+ MED_ATTR_RO (symlink_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (symlink_access, oldname, "oldname", MED_STRING),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(symlink_access, "symlink", process_kobject, "process",
+ file_kobject, "file");
+
+int __init symlink_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(symlink_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_symlink(struct dentry * parent, struct dentry *dentry, const char * oldname);
+medusa_answer_t medusa_symlink(struct dentry *dentry, const char * oldname)
+{
+ struct nameidata ndcurrent, ndupper, ndparent;
+ medusa_answer_t retval;
+
+ if (!dentry || IS_ERR(dentry))
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ ndcurrent.dentry = dentry;
+ ndcurrent.mnt = NULL;
+ medusa_get_upper_and_parent(&ndcurrent,&ndupper,&ndparent);
+
+ if (!MED_MAGIC_VALID(&ndparent.dentry->d_inode->med) &&
+ file_kobj_validate_dentry(ndparent.dentry,ndparent.mnt) <= 0) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&ndparent.dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&ndparent.dentry->d_inode->med))
+ ) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_NO;
+ }
+ if (MEDUSA_MONITORED_ACCESS_O(symlink_access, &ndparent.dentry->d_inode->med))
+ retval = medusa_do_symlink(ndparent.dentry, ndupper.dentry, oldname);
+ else
+ retval = MED_OK;
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return retval;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_symlink(struct dentry * parent, struct dentry *dentry, const char * oldname)
+{
+ struct symlink_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ memcpy(access.oldname, oldname, sizeof(access.oldname)-1);
+ access.oldname[sizeof(access.oldname)-1] = '\0';
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, parent->d_inode);
+ file_kobj_live_add(parent->d_inode);
+ retval = MED_DECIDE(symlink_access, &access, &process, &file);
+ file_kobj_live_remove(parent->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(symlink_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_syscall.c linux-2.4.23-medusa/medusa/l2/acctype_syscall.c
--- linux-2.4.23-clean/medusa/l2/acctype_syscall.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_syscall.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,76 @@
+#include
+#include
+#include
+#include "kobject_process.h"
+#include
+#include
+
+/* let's define the 'syscall' access type, with subject=task and object=task. */
+
+struct syscall_access {
+ MEDUSA_ACCESS_HEADER;
+ unsigned int sysnr;
+ unsigned int arg1;
+ unsigned int arg2;
+ unsigned int arg3;
+ unsigned int arg4;
+ unsigned int arg5;
+ unsigned int arg6;
+ unsigned int arg7;
+ /* is that enough on all archs? */
+};
+
+MED_ATTRS(syscall_access) {
+ MED_ATTR_RO (syscall_access, sysnr, "sysnr", MED_UNSIGNED),
+ MED_ATTR (syscall_access, arg1, "arg1", MED_UNSIGNED),
+ MED_ATTR (syscall_access, arg2, "arg2", MED_UNSIGNED),
+ MED_ATTR (syscall_access, arg3, "arg3", MED_UNSIGNED),
+ MED_ATTR (syscall_access, arg4, "arg4", MED_UNSIGNED),
+ MED_ATTR (syscall_access, arg5, "arg5", MED_UNSIGNED),
+ MED_ATTR (syscall_access, arg6, "arg6", MED_UNSIGNED),
+ MED_ATTR (syscall_access, arg7, "arg7", MED_UNSIGNED),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(syscall_access, "syscall", process_kobject, "process", process_kobject, "process");
+
+int __init syscall_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(syscall_access,MEDUSA_ACCTYPE_TRIGGEREDATSUBJECT);
+ return 0;
+}
+
+medusa_answer_t asmlinkage medusa_syscall_i386(
+ unsigned int eax, /* in: syscall #, out: retval */
+ struct task_struct *curr,
+ volatile unsigned int p1,
+ volatile unsigned int p2,
+ volatile unsigned int p3,
+ volatile unsigned int p4,
+ volatile unsigned int p5)
+{
+ medusa_answer_t retval = MED_OK;
+ struct syscall_access access;
+ struct process_kobject proc;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (MEDUSA_MONITORED_ACCESS_S(syscall_access, ¤t->med)) {
+ access.sysnr = eax;
+ access.arg1 = p1; access.arg2 = p2;
+ access.arg3 = p3; access.arg4 = p4;
+ access.arg5 = p5;
+ access.arg6 = access.arg7 = 0;
+ process_kern2kobj(&proc, current);
+ retval = MED_DECIDE(syscall_access, &access, &proc, &proc);
+ }
+ /* this needs more optimization some day */
+ if (retval == MED_NO)
+ return 0; /* deny */
+ if (retval != MED_SKIP)
+ return 1; /* allow */
+ return 2; /* skip trace code */
+}
+
+__initcall(syscall_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_truncate.c linux-2.4.23-medusa/medusa/l2/acctype_truncate.c
--- linux-2.4.23-clean/medusa/l2/acctype_truncate.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_truncate.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,72 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'truncate' access type, with subj=task and obj=inode */
+
+struct truncate_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+ loff_t length;
+};
+
+MED_ATTRS(truncate_access) {
+ MED_ATTR_RO (truncate_access, filename, "filename", MED_STRING),
+ MED_ATTR_RO (truncate_access, length, "length", MED_UNSIGNED),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(truncate_access, "truncate", process_kobject, "process",
+ file_kobject, "file");
+
+int __init truncate_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(truncate_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_truncate(struct dentry *dentry, unsigned long length);
+medusa_answer_t medusa_truncate(struct dentry *dentry, unsigned long length)
+{
+ if (!dentry || IS_ERR(dentry) || !dentry->d_inode)
+ return MED_OK;
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0)
+ return MED_OK;
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&dentry->d_inode->med))
+ )
+ return MED_NO;
+ if (MEDUSA_MONITORED_ACCESS_O(truncate_access, &dentry->d_inode->med))
+ return medusa_do_truncate(dentry, length);
+ return MED_OK;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_truncate(struct dentry *dentry, unsigned long length)
+{
+ struct truncate_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ access.length = length;
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(truncate_access, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(truncate_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/acctype_unlink.c linux-2.4.23-medusa/medusa/l2/acctype_unlink.c
--- linux-2.4.23-clean/medusa/l2/acctype_unlink.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/acctype_unlink.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,71 @@
+#include
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* let's define the 'unlink' access type, with subj=task and obj=inode */
+
+struct unlink_access {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+};
+
+MED_ATTRS(unlink_access) {
+ MED_ATTR_RO (unlink_access, filename, "filename", MED_STRING),
+ MED_ATTR_END
+};
+
+MED_ACCTYPE(unlink_access, "unlink", process_kobject, "process",
+ file_kobject, "file");
+
+int __init unlink_acctype_init(void) {
+ MED_REGISTER_ACCTYPE(unlink_access, MEDUSA_ACCTYPE_TRIGGEREDATOBJECT);
+ return 0;
+}
+
+static medusa_answer_t medusa_do_unlink(struct dentry *dentry);
+medusa_answer_t medusa_unlink(struct dentry *dentry)
+{
+ if (!dentry || IS_ERR(dentry) || dentry->d_inode == NULL)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(¤t->med) &&
+ process_kobj_validate_task(current) <= 0)
+ return MED_OK;
+
+ if (!MED_MAGIC_VALID(&dentry->d_inode->med) &&
+ file_kobj_validate_dentry(dentry,NULL) <= 0) {
+ return MED_OK;
+ }
+ if (!VS_INTERSECT(VSS(¤t->med),VS(&dentry->d_inode->med)) ||
+ !VS_INTERSECT(VSW(¤t->med),VS(&dentry->d_inode->med))
+ )
+ return MED_NO;
+ if (MEDUSA_MONITORED_ACCESS_O(unlink_access, &dentry->d_inode->med))
+ return medusa_do_unlink(dentry);
+ return MED_OK;
+}
+
+/* XXX Don't try to inline this. GCC tries to be too smart about stack. */
+static medusa_answer_t medusa_do_unlink(struct dentry *dentry)
+{
+ struct unlink_access access;
+ struct process_kobject process;
+ struct file_kobject file;
+ medusa_answer_t retval;
+
+ file_kobj_dentry2string(dentry, access.filename);
+ process_kern2kobj(&process, current);
+ file_kern2kobj(&file, dentry->d_inode);
+ file_kobj_live_add(dentry->d_inode);
+ retval = MED_DECIDE(unlink_access, &access, &process, &file);
+ file_kobj_live_remove(dentry->d_inode);
+ if (retval != MED_ERR)
+ return retval;
+ return MED_OK;
+}
+__initcall(unlink_acctype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/evtype_getfile.c linux-2.4.23-medusa/medusa/l2/evtype_getfile.c
--- linux-2.4.23-clean/medusa/l2/evtype_getfile.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/evtype_getfile.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,255 @@
+/* (C) 2002 Milan Pikula */
+
+#include
+#include
+#include
+
+#include "kobject_process.h"
+#include "kobject_file.h"
+#include
+
+/* the getfile event types (yes, there are more of them) are a bit special:
+ * 1) they are called from the beginning of various access types to get the
+ * initial VS set,
+ * 2) they gain some additional information, which enables L4 code to keep
+ * the file hierarchy, if it wants.
+ * 3) due to creepy VFS design in Linux we sometimes do some magic.
+ */
+
+struct getfile_event {
+ MEDUSA_ACCESS_HEADER;
+ char filename[NAME_MAX+1];
+};
+
+MED_ATTRS(getfile_event) {
+ MED_ATTR_RO (getfile_event, filename, "filename", MED_STRING),
+ MED_ATTR_END
+};
+MED_EVTYPE(getfile_event, "getfile", file_kobject, "file",
+ file_kobject, "parent");
+
+/**
+ * medusa_evocate_mnt - find the uppermost struct vfsmount for given dentry/inode.
+ * @dentry: dentry to perform lookup on.
+ *
+ * This is a helper routine for file_kobj_validate_dentry. It does the black
+ * magic to get the needed information, and owes for its existence to
+ * the dirty design of VFS, where some parts of information are just missing.
+ * From all possible vfsmounts, we must return the uppermost one to get
+ * it right; and we try to avoid recursion 'cause we value the stack.
+ */
+
+struct vfsmount * medusa_evocate_mnt(struct dentry *dentry)
+{
+ int depth, last_depth, maxdepth, can_nest;
+ struct vfsmount * p;
+ int count = 0;
+
+ /* get the local root */
+ spin_lock(&dcache_lock);
+ while (!IS_ROOT(dentry))
+ dentry = dentry->d_parent;
+ dget(dentry);
+ spin_unlock(&dcache_lock);
+
+ maxdepth = 0;
+ do {
+ can_nest = 0;
+ last_depth = -1; depth = 0;
+
+ /* hope that init isn't chrooted; get "global" root */
+ read_lock(&init_task.fs->lock);
+ p = init_task.fs->rootmnt;
+ while (p->mnt_parent != p->mnt_parent->mnt_parent)
+ p = p->mnt_parent;
+ mntget(p);
+ read_unlock(&init_task.fs->lock);
+
+ spin_lock(&dcache_lock);
+ do {
+ count++;
+ if (depth == maxdepth) {
+ if (p->mnt_root == dentry) {
+ spin_unlock(&dcache_lock);
+ dput(dentry);
+ return p;
+ }
+ can_nest = can_nest || !list_empty(&(p->mnt_mounts));
+ }
+ if ((depth < maxdepth) && (last_depth <= depth) && !list_empty(&(p->mnt_mounts))) {
+
+ mntput(p);
+ p = mntget(list_entry((p->mnt_mounts.next), struct vfsmount, mnt_child));
+ last_depth = depth++;
+ continue;
+
+ }
+ if (!list_empty(&(p->mnt_child)) && list_entry((p->mnt_child.next), struct vfsmount, mnt_mounts) != p->mnt_parent) {
+
+ mntput(p);
+ p = mntget(list_entry((p->mnt_child.next), struct vfsmount, mnt_child));
+ last_depth = depth;
+ continue;
+
+ }
+
+ mntput(p);
+ p = mntget(p->mnt_parent);
+ last_depth = depth--;
+
+ } while (depth >= 0);
+ spin_unlock(&dcache_lock);
+ mntput(p);
+ maxdepth++;
+ } while (can_nest);
+
+ dput(dentry);
+ printk("Fatal error: too drunk to evocate mnt. Returning init's mnt instead.\n");
+ return mntget(init_task.fs->rootmnt);
+}
+
+static medusa_answer_t do_file_kobj_validate_dentry(struct nameidata * ndcurrent,
+ struct nameidata * ndupper, struct nameidata * ndparent);
+
+void medusa_clean_inode(struct inode * inode)
+{
+ INIT_MEDUSA_OBJECT_VARS(&inode->med);
+}
+void medusa_get_upper_and_parent(struct nameidata * ndsource,
+ struct nameidata * ndupperp, struct nameidata * ndparentp)
+{
+ *ndupperp = *ndsource;
+ dget(ndupperp->dentry);
+ if (ndupperp->mnt)
+ mntget(ndupperp->mnt);
+ else if (IS_ROOT(ndupperp->dentry))
+ ndupperp->mnt = medusa_evocate_mnt(ndupperp->dentry); /* FIXME: may fail [?] */
+
+ while (IS_ROOT(ndupperp->dentry)) {
+ struct vfsmount * tmp;
+ if (ndupperp->mnt->mnt_parent == ndupperp->mnt->mnt_parent->mnt_parent)
+ break;
+ dput(ndupperp->dentry);
+ ndupperp->dentry = dget(ndupperp->mnt->mnt_mountpoint);
+ tmp = mntget(ndupperp->mnt->mnt_parent);
+ mntput(ndupperp->mnt);
+ ndupperp->mnt = tmp;
+ }
+ if (ndparentp) {
+ if (IS_ROOT(ndupperp->dentry))
+ *ndparentp = *ndsource;
+ else {
+ ndparentp->dentry = ndupperp->dentry->d_parent;
+ ndparentp->mnt = ndupperp->mnt;
+ }
+ dget(ndparentp->dentry);
+ if (ndparentp->mnt)
+ mntget(ndparentp->mnt);
+ }
+
+ /* Now we have dentry and mnt. If IS_ROOT(dentry) then the dentry is global filesystem root */
+ return;
+}
+
+void medusa_put_upper_and_parent(struct nameidata * ndupper, struct nameidata * ndparent)
+{
+ if (ndupper) {
+ dput(ndupper->dentry);
+ if (ndupper->mnt)
+ mntput(ndupper->mnt);
+ }
+ if (ndparent) {
+ dput(ndparent->dentry);
+ if (ndparent->mnt)
+ mntput(ndparent->mnt);
+ }
+}
+
+/**
+ * file_kobj_validate_dentry - get dentry security information from auth. server
+ * @dentry: dentry to get the information for.
+ * @mnt: optional vfsmount structure for that dentry
+ *
+ * This routine expects the existing, but !MED_MAGIC_VALID dentry.
+ */
+int file_kobj_validate_dentry(struct dentry * dentry, struct vfsmount * mnt)
+{
+ struct nameidata ndcurrent;
+ struct nameidata ndupper;
+ struct nameidata ndparent;
+
+ INIT_MEDUSA_OBJECT_VARS(&dentry->d_inode->med);
+#ifdef CONFIG_MEDUSA_FILE_CAPABILITIES
+ cap_clear(dentry->d_inode->med.pcap);
+ cap_set_full(dentry->d_inode->med.icap);
+ cap_set_full(dentry->d_inode->med.ecap);
+#endif
+ ndcurrent.dentry = dentry;
+ ndcurrent.mnt = mnt; /* may be NULL */
+ medusa_get_upper_and_parent(&ndcurrent, &ndupper, &ndparent);
+
+ if (ndparent.dentry->d_inode == NULL) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return 0;
+ }
+
+ if (ndcurrent.dentry != ndparent.dentry) {
+ if (!MED_MAGIC_VALID(&ndparent.dentry->d_inode->med) &&
+ file_kobj_validate_dentry(ndparent.dentry, ndparent.mnt) <= 0) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return 0;
+ }
+
+ if (!MEDUSA_MONITORED_ACCESS_O(getfile_event,
+ &ndparent.dentry->d_inode->med)) {
+
+ COPY_MEDUSA_OBJECT_VARS(&ndcurrent.dentry->d_inode->med,
+ &ndparent.dentry->d_inode->med);
+ ndcurrent.dentry->d_inode->med.user = ndparent.dentry->d_inode->med.user;
+#ifdef CONFIG_MEDUSA_FILE_CAPABILITIES
+ ndcurrent.dentry->d_inode->med.icap = ndparent.dentry->d_inode->med.icap;
+ ndcurrent.dentry->d_inode->med.pcap = ndparent.dentry->d_inode->med.pcap;
+ ndcurrent.dentry->d_inode->med.ecap = ndparent.dentry->d_inode->med.ecap;
+#endif
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return 1;
+ }
+ }
+
+ /* we're global root, or cannot inherit from our parent */
+
+ if (do_file_kobj_validate_dentry(&ndcurrent, &ndupper, &ndparent)
+ != MED_ERR) {
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return MED_MAGIC_VALID(&ndcurrent.dentry->d_inode->med);
+ }
+ medusa_put_upper_and_parent(&ndupper, &ndparent);
+ return -1;
+}
+
+static medusa_answer_t do_file_kobj_validate_dentry(struct nameidata * ndcurrent,
+ struct nameidata * ndupper, struct nameidata * ndparent)
+{
+ struct getfile_event event;
+ struct file_kobject file;
+ struct file_kobject directory;
+ medusa_answer_t retval;
+
+ file_kern2kobj(&file, ndcurrent->dentry->d_inode);
+ file_kobj_dentry2string(ndupper->dentry, event.filename);
+ file_kern2kobj(&directory, ndparent->dentry->d_inode);
+ file_kobj_live_add(ndcurrent->dentry->d_inode);
+ file_kobj_live_add(ndparent->dentry->d_inode);
+ retval = MED_DECIDE(getfile_event, &event, &file, &directory);
+ file_kobj_live_remove(ndparent->dentry->d_inode);
+ file_kobj_live_remove(ndcurrent->dentry->d_inode);
+ return retval;
+}
+
+int __init getfile_evtype_init(void) {
+ MED_REGISTER_EVTYPE(getfile_event,
+ MEDUSA_EVTYPE_TRIGGEREDATSUBJECT |
+ MEDUSA_EVTYPE_TRIGGEREDBYOBJECTTBIT);
+ return 0;
+}
+__initcall(getfile_evtype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/evtype_getprocess.c linux-2.4.23-medusa/medusa/l2/evtype_getprocess.c
--- linux-2.4.23-clean/medusa/l2/evtype_getprocess.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/evtype_getprocess.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,52 @@
+/* (C) 2002 Milan Pikula */
+
+#include
+#include
+
+#include "kobject_process.h"
+#include
+
+/*
+ *
+ * This routine has to validate the process. Because we don't have
+ * the (useful) information to build the process hierarchy, it is
+ * useless to call L3 here. We do it anyway: otherwise the first
+ * access after restart of auth. server will go with full VS set,
+ * and thus will succeed.
+ *
+ */
+
+struct getprocess_event {
+ MEDUSA_ACCESS_HEADER;
+};
+
+MED_ATTRS(getprocess_event) {
+ MED_ATTR_END
+};
+MED_EVTYPE(getprocess_event, "getprocess", process_kobject, "process",
+ process_kobject, "process");
+
+int process_kobj_validate_task(struct task_struct * ts)
+{
+ medusa_answer_t retval;
+ struct getprocess_event event;
+ struct process_kobject proc;
+
+ INIT_MEDUSA_OBJECT_VARS(&ts->med);
+ INIT_MEDUSA_SUBJECT_VARS(&ts->med);
+#ifdef CONFIG_MEDUSA_FORCE
+ ts->med.force_code = NULL;
+#endif
+ process_kern2kobj(&proc, ts);
+ retval = MED_DECIDE(getprocess_event, &event, &proc, &proc);
+ if (retval != MED_ERR)
+ return 1;
+ return -1;
+}
+
+int __init getprocess_evtype_init(void) {
+ MED_REGISTER_EVTYPE(getprocess_event,
+ MEDUSA_EVTYPE_NOTTRIGGERED);
+ return 0;
+}
+__initcall(getprocess_evtype_init);
diff -ruN linux-2.4.23-clean/medusa/l2/kobject_file.c linux-2.4.23-medusa/medusa/l2/kobject_file.c
--- linux-2.4.23-clean/medusa/l2/kobject_file.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-medusa/medusa/l2/kobject_file.c 2003-12-08 19:31:38.000000000 +0100
@@ -0,0 +1,228 @@
+/* file_kobject.c, (C) 2002 Milan Pikula */
+
+#include
+#include
+#include
+#include