From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S262171AbTD3Nco (ORCPT ); Wed, 30 Apr 2003 09:32:44 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S262174AbTD3Nco (ORCPT ); Wed, 30 Apr 2003 09:32:44 -0400 Received: from 237.oncolt.com ([213.86.99.237]:39164 "EHLO warthog.warthog") by vger.kernel.org with ESMTP id S262171AbTD3Nck (ORCPT ); Wed, 30 Apr 2003 09:32:40 -0400 From: David Howells To: torvalds@transmeta.com cc: linux-kernel@vger.kernel.org Subject: [PATCH] add a stub by which a module can bind to the AFS syscall User-Agent: EMH/1.14.1 SEMI/1.14.4 (Hosorogi) FLIM/1.14.4 (=?ISO-8859-4?Q?Kashiharajing=FE-mae?=) APEL/10.4 Emacs/21.2 (i386-redhat-linux-gnu) MULE/5.0 (SAKAKI) MIME-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: text/plain; charset=US-ASCII Date: Wed, 30 Apr 2003 14:44:54 +0100 Message-ID: <25734.1051710294@warthog.warthog> Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Hi Linus, This patch makes it possible for a module to bind safely to the AFS syscall, without having to modify the syscall table directly. David diff -uNr -x'*.o' -x'.*' -xTAGS linux-2.5.67/include/linux/syscallstub.h linux-2.5.67-afs/include/linux/syscallstub.h --- linux-2.5.67/include/linux/syscallstub.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.5.67-afs/include/linux/syscallstub.h 2003-04-07 13:17:38.000000000 +0100 @@ -0,0 +1,28 @@ +/* syscallstub.h: system call stub management + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_SYSCALLSTUB_H +#define _LINUX_SYSCALLSTUB_H + +#include + +/* + * AFS system call stub management + */ +typedef int (*afs_syscall_handler_t)(long cmd, va_list va); + +extern int register_afs_syscall_handler(afs_syscall_handler_t handler, struct module *owner); +extern void unregister_afs_syscall_handler(afs_syscall_handler_t handler, struct module *owner); + +extern asmlinkage int sys_afs(long cmd, ...); + + +#endif /* _LINUX_SYSCALLSTUB_H */ diff -uNr -x'*.o' -x'.*' -xTAGS linux-2.5.67/kernel/Makefile linux-2.5.67-afs/kernel/Makefile --- linux-2.5.67/kernel/Makefile 2003-03-05 03:29:02.000000000 +0000 +++ linux-2.5.67-afs/kernel/Makefile 2003-04-07 13:16:52.000000000 +0100 @@ -6,7 +6,8 @@ exit.o itimer.o time.o softirq.o resource.o \ sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o futex.o pid.o \ - rcupdate.o intermodule.o extable.o params.o posix-timers.o + rcupdate.o intermodule.o extable.o params.o posix-timers.o \ + syscallstub.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += cpu.o diff -uNr -x'*.o' -x'.*' -xTAGS linux-2.5.67/kernel/syscallstub.c linux-2.5.67-afs/kernel/syscallstub.c --- linux-2.5.67/kernel/syscallstub.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.5.67-afs/kernel/syscallstub.c 2003-04-30 14:35:11.000000000 +0100 @@ -0,0 +1,88 @@ +/* syscallstub.c: module providable syscall stub management + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include + +/* + * AFS system call stub management + */ +static afs_syscall_handler_t afs_syscall_handler; +static struct module *afs_syscall_owner; +static rwlock_t afs_syscall_handler_lock = RW_LOCK_UNLOCKED; + +int register_afs_syscall_handler(afs_syscall_handler_t handler, struct module *owner) +{ + int ret; + + if (!handler || !owner) + return -EINVAL; + + ret = -EEXIST; + write_lock(&afs_syscall_handler_lock); + + if (!afs_syscall_handler) { + afs_syscall_handler = handler; + afs_syscall_owner = owner; + ret = 0; + } + + write_unlock(&afs_syscall_handler_lock); + + return ret; +} + +EXPORT_SYMBOL(register_afs_syscall_handler); + +void unregister_afs_syscall_handler(afs_syscall_handler_t handler, struct module *owner) +{ + write_lock(&afs_syscall_handler_lock); + + if (afs_syscall_handler==handler && afs_syscall_owner==owner) { + afs_syscall_handler = NULL; + afs_syscall_owner = NULL; + } + else { + printk("module %s tried to free AFS syscall which it did not own\n", + owner->name); + } + + write_unlock(&afs_syscall_handler_lock); +} + +EXPORT_SYMBOL(unregister_afs_syscall_handler); + +asmlinkage int sys_afs(long cmd, ...) +{ + afs_syscall_handler_t handler; + struct module *owner; + va_list va; + int ret; + + ret = -ENOSYS; + read_lock(&afs_syscall_handler_lock); + handler = afs_syscall_handler; + owner = afs_syscall_owner; + if (handler && try_module_get(owner)) + ret = 0; + read_unlock(&afs_syscall_handler_lock); + + if (ret<0) + return ret; + + va_start(va,cmd); + ret = handler(cmd,va); + va_end(va); + + module_put(owner); + return ret; +} + diff -uNr -x'*.o' -x'.*' -xTAGS linux-2.5.67/arch/i386/kernel/entry.S linux-2.5.67-afs/arch/i386/kernel/entry.S --- linux-2.5.67/arch/i386/kernel/entry.S 2003-03-28 11:37:52.000000000 +0000 +++ linux-2.5.67-afs/arch/i386/kernel/entry.S 2003-04-30 14:38:32.000000000 +0100 @@ -721,7 +721,7 @@ .long sys_bdflush .long sys_sysfs /* 135 */ .long sys_personality - .long sys_ni_syscall /* reserved for afs_syscall */ + .long sys_afs .long sys_setfsuid16 .long sys_setfsgid16 .long sys_llseek /* 140 */