diff -urN linux-2.2.13/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.2.13/Documentation/Configure.help Tue Oct 19 17:14:00 1999 +++ linux/Documentation/Configure.help Thu Dec 9 17:12:46 1999 @@ -7446,6 +7446,73 @@ If you are not a part of a fairly large, distributed network, you probably do not need an automounter, and can say N here. +VFS Plug-in support for filesystem capabilities +CONFIG_VFS_CAP_PLUGIN + + The kernel's decisions about whether a user-level process is + privileged enough to do things, not normally permitted to + non-administrators, are regulated by fine grained 'capabilities'. + + Historically, UNIX-like systems have had a single administrator + account (aka. 'root' or 'superuser') with UID=0, who was able to do + anything with the system. More modern UNIXes and Linux have broken + up this single point of total security into an orthogonal set of + lesser privileges which a fleeting POSIX committee decided to call + 'capabilities' and hence their name under Linux. In other UNIX + systems are labeled 'privileges'. + + This option concerns adding some module hooks into the kernel to + make it possible to associate set-capability bits on files which do + not reside on a capability-aware filesystem. If you are happy + running a system that is effectively not capability aware (you like + the single superuser account). Or you are happy with only setting + capabilities on files that reside on capability-aware filesystems, you + should say 'n' here (which is safe). This option is intended for + people that know what they are doing (or want to explore :). An + example plug-in kernel module for storing filesystem capabilities is + available from here: + + ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.3/ + + To select this option, you need to have enabled module support. + +VFS CAP Plug-in can preempt filesystem +CONFIG_VFS_CAP_PLUGIN_PREEMPT + + This option makes the kernel always call a loaded module for + capability information and permits the module to force the kernel to + ignore capability information stored on the filesystem. Think twice + before enabling this option. + +VFS CAP Plug-in can modify filesystem +CONFIG_VFS_CAP_PLUGIN_MODIFY + + This option makes the kernel always call a loaded module for + capability information after the native filesystem has been + consulted for capabilities. In this way, the module is able to + further modify the filesystem's stored capabilities for the + file. Think twice before enabling this option. + +VFS CAP Plug-in can be unloaded +CONFIG_VFS_CAP_PLUGIN_UNLOCKABLE + + If you've got this far and you are not developing a new module, you + should say no to this option. The option is basically a developer + feature to make it convenient to try new capability storage schemes + without having to reboot the system each time a change is made. In + general, saying 'n' here will give you some degree of confidence that + there is no backdoor into the system's policy for raising and lowering + capabilities. (Summary: say 'n' unless you know what you're doing.) + +Capability bounded set (similar to secure-level of old) +CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE + If you like the secure-level that was present in earlier kernels, this + option is for you. It implements a global bound on the capabilities that + can be used on a running system. (It goes against the capability model + as proposed in the defunct POSIX.1e specification, but its no worse than + what we used to have. Summary: don't change if you don't know what you + are doing.) + UFS filesystem support CONFIG_UFS_FS BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, diff -urN linux-2.2.13/MAINTAINERS linux/MAINTAINERS --- linux-2.2.13/MAINTAINERS Tue Oct 19 17:14:00 1999 +++ linux/MAINTAINERS Thu Dec 9 16:41:29 1999 @@ -186,6 +186,13 @@ L: linux-computone@lazuli.wittsend.com S: Supported +CAPABILITIES +P: Andrew G. Morgan +M: morgan@transmeta.com +L: linux-privs@mit.edu +W: http://www.kernel.org/pub/linux/libs/linux-privs +S: Maintained + CONFIGURE, MENUCONFIG, XCONFIG P: Michael Elizabeth Chastain M: mec@shout.net diff -urN linux-2.2.13/arch/i386/defconfig linux/arch/i386/defconfig --- linux-2.2.13/arch/i386/defconfig Wed Aug 25 17:29:46 1999 +++ linux/arch/i386/defconfig Sat Dec 11 19:28:16 1999 @@ -304,6 +304,7 @@ # # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y +CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE=y # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_FAT_FS is not set diff -urN linux-2.2.13/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c --- linux-2.2.13/arch/i386/kernel/mca.c Mon Jun 7 16:18:16 1999 +++ linux/arch/i386/kernel/mca.c Thu Dec 9 16:54:19 1999 @@ -150,6 +150,7 @@ NULL, /* smap */ NULL, /* updatepage */ NULL /* revalidate */ + NULL, /* capability */ }; #endif diff -urN linux-2.2.13/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- linux-2.2.13/arch/i386/kernel/mtrr.c Wed Aug 25 17:29:46 1999 +++ linux/arch/i386/kernel/mtrr.c Thu Dec 9 16:41:29 1999 @@ -1483,7 +1483,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct proc_dir_entry proc_root_mtrr = { diff -urN linux-2.2.13/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- linux-2.2.13/arch/ppc/kernel/ppc_htab.c Wed Aug 25 17:29:46 1999 +++ linux/arch/ppc/kernel/ppc_htab.c Thu Dec 9 16:41:29 1999 @@ -78,7 +78,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* these will go into processor.h when I'm done debugging -- Cort */ diff -urN linux-2.2.13/drivers/ap1000/ringbuf.c linux/drivers/ap1000/ringbuf.c --- linux-2.2.13/drivers/ap1000/ringbuf.c Wed Mar 10 16:51:35 1999 +++ linux/drivers/ap1000/ringbuf.c Thu Dec 9 16:41:29 1999 @@ -322,5 +322,9 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/drivers/char/ftape/lowlevel/ftape-proc.c linux/drivers/char/ftape/lowlevel/ftape-proc.c --- linux-2.2.13/drivers/char/ftape/lowlevel/ftape-proc.c Mon Aug 24 13:02:44 1998 +++ linux/drivers/char/ftape/lowlevel/ftape-proc.c Thu Dec 9 16:41:29 1999 @@ -117,6 +117,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* diff -urN linux-2.2.13/drivers/pci/proc.c linux/drivers/pci/proc.c --- linux-2.2.13/drivers/pci/proc.c Mon Aug 24 13:14:10 1998 +++ linux/drivers/pci/proc.c Thu Dec 9 16:41:29 1999 @@ -226,7 +226,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; int diff -urN linux-2.2.13/drivers/zorro/proc.c linux/drivers/zorro/proc.c --- linux-2.2.13/drivers/zorro/proc.c Mon Aug 24 13:14:10 1998 +++ linux/drivers/zorro/proc.c Thu Dec 9 16:41:29 1999 @@ -93,7 +93,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; int diff -urN linux-2.2.13/fs/Config.in linux/fs/Config.in --- linux-2.2.13/fs/Config.in Mon Aug 9 12:04:40 1999 +++ linux/fs/Config.in Thu Dec 9 17:08:28 1999 @@ -7,6 +7,16 @@ bool 'Quota support' CONFIG_QUOTA tristate 'Kernel automounter support' CONFIG_AUTOFS_FS +if [ "$CONFIG_MODULES" = "y" ]; then + bool 'VFS plug-in support for filesystem capabilities' CONFIG_VFS_CAP_PLUGIN + if [ "$CONFIG_VFS_CAP_PLUGIN" = "y" ]; then + bool ' plug-in can preempt native filesystem support' CONFIG_VFS_CAP_PLUGIN_PREEMPT + bool ' plug-in can modify native filesystem support' CONFIG_VFS_CAP_PLUGIN_MODIFY + bool ' plug-in can be unloaded' CONFIG_VFS_CAP_PLUGIN_UNLOCKABLE + fi +fi + +bool 'Support for capability bound' CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS diff -urN linux-2.2.13/fs/Makefile linux/fs/Makefile --- linux-2.2.13/fs/Makefile Wed Aug 25 17:29:49 1999 +++ linux/fs/Makefile Thu Dec 9 16:42:51 1999 @@ -13,6 +13,7 @@ O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \ super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \ + capability.o \ dcache.o inode.o attr.o bad_inode.o file.o $(BINFMTS) MOD_LIST_NAME := FS_MODULES diff -urN linux-2.2.13/fs/adfs/dir.c linux/fs/adfs/dir.c --- linux-2.2.13/fs/adfs/dir.c Thu May 13 23:25:58 1999 +++ linux/fs/adfs/dir.c Thu Dec 9 16:41:29 1999 @@ -56,7 +56,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; unsigned int adfs_val (unsigned char *p, int len) diff -urN linux-2.2.13/fs/adfs/file.c linux/fs/adfs/file.c --- linux-2.2.13/fs/adfs/file.c Mon Aug 24 13:02:44 1998 +++ linux/fs/adfs/file.c Thu Dec 9 16:41:29 1999 @@ -66,5 +66,8 @@ adfs_bmap, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/affs/dir.c linux/fs/affs/dir.c --- linux-2.2.13/fs/affs/dir.c Fri Apr 23 21:20:37 1999 +++ linux/fs/affs/dir.c Thu Dec 9 16:41:29 1999 @@ -64,7 +64,8 @@ NULL, /* permissions */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; static ssize_t diff -urN linux-2.2.13/fs/affs/file.c linux/fs/affs/file.c --- linux-2.2.13/fs/affs/file.c Mon Aug 24 13:02:44 1998 +++ linux/fs/affs/file.c Thu Dec 9 16:41:29 1999 @@ -81,7 +81,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct file_operations affs_file_operations_ofs = { @@ -122,7 +123,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; #define AFFS_ISINDEX(x) ((x < 129) || \ diff -urN linux-2.2.13/fs/affs/symlink.c linux/fs/affs/symlink.c --- linux-2.2.13/fs/affs/symlink.c Sat Sep 19 13:39:45 1998 +++ linux/fs/affs/symlink.c Thu Dec 9 16:41:29 1999 @@ -40,7 +40,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int diff -urN linux-2.2.13/fs/autofs/dir.c linux/fs/autofs/dir.c --- linux-2.2.13/fs/autofs/dir.c Thu May 13 23:25:58 1999 +++ linux/fs/autofs/dir.c Thu Dec 9 16:41:29 1999 @@ -80,6 +80,7 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/autofs/root.c linux/fs/autofs/root.c --- linux-2.2.13/fs/autofs/root.c Thu May 13 23:25:58 1999 +++ linux/fs/autofs/root.c Thu Dec 9 16:41:29 1999 @@ -61,7 +61,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldir) diff -urN linux-2.2.13/fs/autofs/symlink.c linux/fs/autofs/symlink.c --- linux-2.2.13/fs/autofs/symlink.c Tue Oct 27 14:13:53 1998 +++ linux/fs/autofs/symlink.c Thu Dec 9 16:41:29 1999 @@ -56,5 +56,6 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/bad_inode.c linux/fs/bad_inode.c --- linux-2.2.13/fs/bad_inode.c Mon Sep 21 14:37:20 1998 +++ linux/fs/bad_inode.c Thu Dec 9 16:41:29 1999 @@ -67,7 +67,8 @@ EIO_ERROR, /* permission */ EIO_ERROR, /* smap */ EIO_ERROR, /* update_page */ - EIO_ERROR /* revalidate */ + EIO_ERROR, /* revalidate */ + EIO_ERROR, /* capability */ }; diff -urN linux-2.2.13/fs/capability.c linux/fs/capability.c --- linux-2.2.13/fs/capability.c Wed Dec 31 16:00:00 1969 +++ linux/fs/capability.c Thu Dec 9 16:41:29 1999 @@ -0,0 +1,140 @@ +/* + * fs/capability.c - vfs capability support + * + * Copyright (c) 1999 Andrew G. Morgan + */ + +#include +#include +#include + +#ifdef CONFIG_VFS_CAP_PLUGIN + +/* this is a function hook for a module to set via the a call to + fs_capability_fn_register */ + +static int (*fs_capability_fn)(struct dentry *dentry, int operation, + kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) = NULL; + +/* + * This function may normally be called once to load and lock support + * for a filesystem capability method that can be used as a substitute + * or override of native filesystem capabilities. + */ + +static spinlock_t module_capability_register_lock; + +int fs_capability_fn_register(int (*fs_cap_fn)(struct dentry *dentry, + int operation, + kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted)) +{ + if (!capable(CAP_SETFCAP)) { + printk(KERN_WARNING + "refusing attempt to register fs_capability_fn\n"); + return 0; + } + + spin_lock(&module_capability_register_lock); + +#ifdef CONFIG_VFS_CAP_PLUGIN_UNLOCKABLE + printk("fs_capability_fn_register(%p)\n", fs_cap_fn); + if (fs_cap_fn == NULL) { + printk(KERN_NOTICE "unlock-n-unload fs_capability_fn\n"); + fs_capability_fn = fs_cap_fn; + goto done; + } else +#endif /* CONFIG_VFS_CAP_PLUGIN_UNLOCKABLE */ + + if (fs_capability_fn) { + printk(KERN_WARNING + "ignoring attempt to reset fs_capability_fn\n"); + goto failed; + } + + printk(KERN_NOTICE "load-n-lock fs_capability_fn (%p)\n", + fs_capability_fn); + fs_capability_fn = fs_cap_fn; + +done: + spin_unlock(&module_capability_register_lock); + return 1; + +failed: + spin_unlock(&module_capability_register_lock); + return 0; +} + +#endif /* CONFIG_VFS_CAP_PLUGIN */ + +int vfs_cap_dentry(struct dentry *dentry, int operation, + kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) +{ + int retval = -ENOSYS; + + if (operation == _CAP_FS_GET) { + /* + * Start from a secure base + */ + cap_clear(*effective); + cap_clear(*inheritable); + cap_clear(*permitted); + } + + if (IS_ERR(dentry) || !(dentry->d_inode)) { + return -ENOENT; + } + + if (!S_ISREG(dentry->d_inode->i_mode)) { + return -EACCES; + } + +#if defined(CONFIG_VFS_CAP_PLUGIN) && defined(CONFIG_VFS_CAP_PLUGIN_PREEMPT) + if (fs_capability_fn != NULL) { + retval = fs_capability_fn(dentry, operation | _CAP_FS_PREEMPT, + effective, inheritable, permitted); + /* + * opportunity to override filesystem support + */ + if (retval != -ENOSYS) { + return retval; + } + } +#endif /* CONFIG_VFS_CAP_PLUGIN && CONFIG_VFS_CAP_PLUGIN_PREEMPT */ + + /* if the filesystem can handle it, use its custom function */ + if ((dentry->d_inode != NULL) + && (dentry->d_inode->i_op != NULL) + && (dentry->d_inode->i_op->capability != NULL)) { + retval = dentry->d_inode->i_op->capability(dentry->d_inode, + operation, + effective, + inheritable, + permitted); + } + +#ifdef CONFIG_VFS_CAP_PLUGIN + +#ifndef CONFIG_VFS_CAP_PLUGIN_MODIFY + if (retval == -ENOSYS) { +#endif /* ndef CONFIG_VFS_CAP_PLUGIN_MODIFY */ + + if (fs_capability_fn != NULL) { + retval = fs_capability_fn(dentry, operation, + effective, inheritable, + permitted); + } + +#ifndef CONFIG_VFS_CAP_PLUGIN_MODIFY + } +#endif /* ndef CONFIG_VFS_CAP_PLUGIN_MODIFY */ + +#endif /* CONFIG_VFS_CAP_PLUGIN */ + + return retval; +} diff -urN linux-2.2.13/fs/coda/dir.c linux/fs/coda/dir.c --- linux-2.2.13/fs/coda/dir.c Mon Aug 9 12:05:10 1999 +++ linux/fs/coda/dir.c Thu Dec 9 16:41:29 1999 @@ -84,7 +84,8 @@ coda_permission, /* permission */ NULL, /* smap */ NULL, /* update page */ - coda_revalidate_inode /* revalidate */ + coda_revalidate_inode, /* revalidate */ + NULL, /* capability */ }; struct file_operations coda_dir_operations = { diff -urN linux-2.2.13/fs/coda/file.c linux/fs/coda/file.c --- linux-2.2.13/fs/coda/file.c Mon Aug 9 12:05:10 1999 +++ linux/fs/coda/file.c Thu Dec 9 16:41:29 1999 @@ -54,7 +54,8 @@ coda_permission, /* permission */ NULL, /* smap */ NULL, /* update page */ - coda_revalidate_inode /* revalidate */ + coda_revalidate_inode, /* revalidate */ + NULL, /* capability */ }; struct file_operations coda_file_operations = { diff -urN linux-2.2.13/fs/coda/pioctl.c linux/fs/coda/pioctl.c --- linux-2.2.13/fs/coda/pioctl.c Mon Aug 31 15:46:10 1998 +++ linux/fs/coda/pioctl.c Thu Dec 9 16:41:29 1999 @@ -53,7 +53,8 @@ coda_ioctl_permission, /* permission */ NULL, /* smap */ NULL, /* update page */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; struct file_operations coda_ioctl_operations = { diff -urN linux-2.2.13/fs/coda/symlink.c linux/fs/coda/symlink.c --- linux-2.2.13/fs/coda/symlink.c Fri Dec 18 12:45:00 1998 +++ linux/fs/coda/symlink.c Thu Dec 9 16:41:29 1999 @@ -49,7 +49,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* update page */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int coda_readlink(struct dentry *de, char *buffer, int length) diff -urN linux-2.2.13/fs/devices.c linux/fs/devices.c --- linux-2.2.13/fs/devices.c Wed Dec 23 11:39:49 1998 +++ linux/fs/devices.c Thu Dec 9 16:41:29 1999 @@ -281,7 +281,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* @@ -334,7 +338,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* diff -urN linux-2.2.13/fs/devpts/root.c linux/fs/devpts/root.c --- linux-2.2.13/fs/devpts/root.c Sat May 8 17:56:37 1999 +++ linux/fs/devpts/root.c Thu Dec 9 16:41:29 1999 @@ -58,7 +58,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct dentry_operations devpts_dentry_operations = { diff -urN linux-2.2.13/fs/exec.c linux/fs/exec.c --- linux-2.2.13/fs/exec.c Tue Oct 19 17:14:01 1999 +++ linux/fs/exec.c Thu Dec 9 16:41:29 1999 @@ -605,10 +605,15 @@ id_change = 1; } - /* We don't have VFS support for capabilities yet */ - cap_clear(bprm->cap_inheritable); - cap_clear(bprm->cap_permitted); - cap_clear(bprm->cap_effective); + + /* For gets, this is guaranteed to succeed... */ + + (void) vfs_cap_dentry(bprm->dentry, _CAP_FS_GET, + &bprm->cap_effective, + &bprm->cap_inheritable, + &bprm->cap_permitted); + + /* if we're in the old "superuser knows best" scheme fake things */ /* To support inheritance of root-permissions and suid-root * executables under compatibility mode, we raise the diff -urN linux-2.2.13/fs/ext2/dir.c linux/fs/ext2/dir.c --- linux-2.2.13/fs/ext2/dir.c Fri Apr 23 21:20:37 1999 +++ linux/fs/ext2/dir.c Thu Dec 9 16:41:29 1999 @@ -72,7 +72,10 @@ NULL, /* bmap */ NULL, /* truncate */ ext2_permission, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; int ext2_check_dir_entry (const char * function, struct inode * dir, diff -urN linux-2.2.13/fs/ext2/file.c linux/fs/ext2/file.c --- linux-2.2.13/fs/ext2/file.c Tue Oct 19 17:14:01 1999 +++ linux/fs/ext2/file.c Thu Dec 9 16:41:29 1999 @@ -100,7 +100,10 @@ ext2_bmap, /* bmap */ ext2_truncate, /* truncate */ ext2_permission, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* diff -urN linux-2.2.13/fs/ext2/symlink.c linux/fs/ext2/symlink.c --- linux-2.2.13/fs/ext2/symlink.c Sat Sep 19 13:38:18 1998 +++ linux/fs/ext2/symlink.c Thu Dec 9 16:41:29 1999 @@ -48,7 +48,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct dentry * ext2_follow_link(struct dentry * dentry, diff -urN linux-2.2.13/fs/fat/file.c linux/fs/fat/file.c --- linux-2.2.13/fs/fat/file.c Sun Feb 28 09:47:37 1999 +++ linux/fs/fat/file.c Thu Dec 9 16:41:29 1999 @@ -62,7 +62,10 @@ fat_bmap, /* bmap */ fat_truncate, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* #Specification: msdos / special devices / mmap @@ -112,7 +115,10 @@ NULL, /* bmap */ fat_truncate, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct file_operations fat_file_operations_readpage = { @@ -147,7 +153,10 @@ NULL, /* bmap */ fat_truncate, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; #define MSDOS_PREFETCH 32 diff -urN linux-2.2.13/fs/fifo.c linux/fs/fifo.c --- linux-2.2.13/fs/fifo.c Fri Nov 13 10:07:26 1998 +++ linux/fs/fifo.c Thu Dec 9 16:41:29 1999 @@ -145,7 +145,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; void init_fifo(struct inode * inode) diff -urN linux-2.2.13/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c --- linux-2.2.13/fs/hfs/dir_cap.c Thu May 13 23:25:58 1999 +++ linux/fs/hfs/dir_cap.c Thu Dec 9 16:41:29 1999 @@ -92,7 +92,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; struct inode_operations hfs_cap_fdir_inode_operations = { @@ -113,7 +116,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; struct inode_operations hfs_cap_rdir_inode_operations = { @@ -134,7 +140,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /*================ File-local functions ================*/ diff -urN linux-2.2.13/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c --- linux-2.2.13/fs/hfs/dir_dbl.c Thu May 13 23:25:58 1999 +++ linux/fs/hfs/dir_dbl.c Thu Dec 9 16:41:29 1999 @@ -92,7 +92,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c --- linux-2.2.13/fs/hfs/dir_nat.c Thu May 13 23:25:58 1999 +++ linux/fs/hfs/dir_nat.c Thu Dec 9 16:41:29 1999 @@ -100,7 +100,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; struct inode_operations hfs_nat_hdir_inode_operations = { @@ -123,7 +124,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; /*================ File-local functions ================*/ diff -urN linux-2.2.13/fs/hfs/file.c linux/fs/hfs/file.c --- linux-2.2.13/fs/hfs/file.c Mon Nov 2 09:35:16 1998 +++ linux/fs/hfs/file.c Thu Dec 9 16:41:29 1999 @@ -70,7 +70,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; /*================ Variable-like macros ================*/ diff -urN linux-2.2.13/fs/hfs/file_cap.c linux/fs/hfs/file_cap.c --- linux-2.2.13/fs/hfs/file_cap.c Mon Nov 2 09:35:16 1998 +++ linux/fs/hfs/file_cap.c Thu Dec 9 16:41:29 1999 @@ -84,7 +84,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidata */ + NULL, /* revalidate */ + NULL, /* capability */ }; /*================ File-local functions ================*/ diff -urN linux-2.2.13/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c --- linux-2.2.13/fs/hfs/file_hdr.c Wed May 12 13:26:34 1999 +++ linux/fs/hfs/file_hdr.c Thu Dec 9 16:41:29 1999 @@ -86,7 +86,8 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = { diff -urN linux-2.2.13/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c --- linux-2.2.13/fs/hpfs/hpfs_fs.c Fri Apr 23 21:20:38 1999 +++ linux/fs/hpfs/hpfs_fs.c Thu Dec 9 16:41:29 1999 @@ -184,6 +184,10 @@ &hpfs_bmap, /* bmap */ NULL, /* truncate */ NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* directory ops */ @@ -227,6 +231,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* Four 512-byte buffers and the 2k block obtained by concatenating them */ diff -urN linux-2.2.13/fs/isofs/dir.c linux/fs/isofs/dir.c --- linux-2.2.13/fs/isofs/dir.c Fri Apr 23 21:20:38 1999 +++ linux/fs/isofs/dir.c Thu Dec 9 16:41:29 1999 @@ -61,7 +61,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int isofs_name_translate(char * old, int len, char * new) diff -urN linux-2.2.13/fs/isofs/file.c linux/fs/isofs/file.c --- linux-2.2.13/fs/isofs/file.c Sun Mar 7 15:25:23 1999 +++ linux/fs/isofs/file.c Thu Dec 9 16:41:29 1999 @@ -52,5 +52,9 @@ NULL, /* writepage */ isofs_bmap, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/isofs/symlink.c linux/fs/isofs/symlink.c --- linux-2.2.13/fs/isofs/symlink.c Sat Sep 19 13:42:23 1998 +++ linux/fs/isofs/symlink.c Thu Dec 9 16:41:29 1999 @@ -41,7 +41,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen) diff -urN linux-2.2.13/fs/minix/dir.c linux/fs/minix/dir.c --- linux-2.2.13/fs/minix/dir.c Fri Apr 23 21:20:38 1999 +++ linux/fs/minix/dir.c Thu Dec 9 16:41:29 1999 @@ -56,7 +56,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int minix_readdir(struct file * filp, diff -urN linux-2.2.13/fs/minix/file.c linux/fs/minix/file.c --- linux-2.2.13/fs/minix/file.c Mon Aug 9 12:04:41 1999 +++ linux/fs/minix/file.c Thu Dec 9 16:41:29 1999 @@ -63,7 +63,11 @@ NULL, /* writepage */ minix_bmap, /* bmap */ minix_truncate, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static ssize_t minix_file_write(struct file * filp, const char * buf, diff -urN linux-2.2.13/fs/minix/symlink.c linux/fs/minix/symlink.c --- linux-2.2.13/fs/minix/symlink.c Sat Sep 19 13:42:44 1998 +++ linux/fs/minix/symlink.c Thu Dec 9 16:41:29 1999 @@ -37,7 +37,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct dentry * minix_follow_link(struct dentry * dentry, diff -urN linux-2.2.13/fs/msdos/namei.c linux/fs/msdos/namei.c --- linux-2.2.13/fs/msdos/namei.c Mon Aug 9 12:04:41 1999 +++ linux/fs/msdos/namei.c Thu Dec 9 16:41:29 1999 @@ -635,6 +635,7 @@ NULL, /* smap */ NULL, /* updatepage */ NULL, /* revalidate */ + NULL, /* capability */ }; static void msdos_put_super_callback(struct super_block *sb) diff -urN linux-2.2.13/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c --- linux-2.2.13/fs/ncpfs/dir.c Mon Aug 9 12:04:57 1999 +++ linux/fs/ncpfs/dir.c Thu Dec 9 16:41:29 1999 @@ -99,6 +99,7 @@ NULL, /* smap */ NULL, /* updatepage */ NULL, /* revalidate */ + NULL, /* capability */ }; static ssize_t diff -urN linux-2.2.13/fs/ncpfs/file.c linux/fs/ncpfs/file.c --- linux-2.2.13/fs/ncpfs/file.c Wed Jun 2 11:30:30 1999 +++ linux/fs/ncpfs/file.c Thu Dec 9 16:41:29 1999 @@ -296,5 +296,10 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* bmap */ - NULL /* truncate */ + NULL, /* truncate */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/nfs/dir.c linux/fs/nfs/dir.c --- linux-2.2.13/fs/nfs/dir.c Tue Oct 19 17:14:02 1999 +++ linux/fs/nfs/dir.c Thu Dec 9 16:41:29 1999 @@ -99,6 +99,7 @@ NULL, /* smap */ NULL, /* updatepage */ nfs_revalidate, /* revalidate */ + NULL, /* capability */ }; static ssize_t diff -urN linux-2.2.13/fs/nfs/file.c linux/fs/nfs/file.c --- linux-2.2.13/fs/nfs/file.c Tue Oct 19 17:14:02 1999 +++ linux/fs/nfs/file.c Thu Dec 9 16:41:29 1999 @@ -77,6 +77,7 @@ NULL, /* smap */ nfs_updatepage, /* updatepage */ nfs_revalidate, /* revalidate */ + NULL, /* capability */ }; /* Hack for future NFS swap support */ diff -urN linux-2.2.13/fs/nfs/symlink.c linux/fs/nfs/symlink.c --- linux-2.2.13/fs/nfs/symlink.c Mon Apr 12 09:57:11 1999 +++ linux/fs/nfs/symlink.c Thu Dec 9 16:41:29 1999 @@ -41,7 +41,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen) diff -urN linux-2.2.13/fs/ntfs/fs.c linux/fs/ntfs/fs.c --- linux-2.2.13/fs/ntfs/fs.c Fri Apr 23 21:20:38 1999 +++ linux/fs/ntfs/fs.c Thu Dec 9 16:41:29 1999 @@ -447,6 +447,7 @@ NULL, /* smap */ NULL, /* updatepage */ NULL, /* revalidate */ + NULL, /* capability */ }; #ifdef CONFIG_NTFS_RW @@ -630,6 +631,7 @@ NULL, /* smap */ NULL, /* updatepage */ NULL, /* revalidate */ + NULL, /* capability */ }; static struct file_operations ntfs_dir_operations = { @@ -679,6 +681,7 @@ NULL, /* smap */ NULL, /* updatepage */ NULL, /* revalidate */ + NULL, /* capability */ }; /* ntfs_read_inode is called by the Virtual File System (the kernel layer that diff -urN linux-2.2.13/fs/pipe.c linux/fs/pipe.c --- linux-2.2.13/fs/pipe.c Mon Aug 9 12:04:41 1999 +++ linux/fs/pipe.c Thu Dec 9 16:41:29 1999 @@ -455,7 +455,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; int do_pipe(int *fd) diff -urN linux-2.2.13/fs/proc/array.c linux/fs/proc/array.c --- linux-2.2.13/fs/proc/array.c Tue Oct 19 17:14:02 1999 +++ linux/fs/proc/array.c Thu Dec 9 16:41:29 1999 @@ -1566,7 +1566,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static ssize_t arraylong_read(struct file * file, char * buf, @@ -1614,5 +1618,9 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/proc/base.c linux/fs/proc/base.c --- linux-2.2.13/fs/proc/base.c Mon Aug 24 13:02:43 1998 +++ linux/fs/proc/base.c Thu Dec 9 16:41:29 1999 @@ -49,7 +49,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* diff -urN linux-2.2.13/fs/proc/fd.c linux/fs/proc/fd.c --- linux-2.2.13/fs/proc/fd.c Tue Oct 19 17:14:02 1999 +++ linux/fs/proc/fd.c Thu Dec 9 16:41:29 1999 @@ -55,7 +55,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - proc_permission /* permission */ + proc_permission, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* diff -urN linux-2.2.13/fs/proc/generic.c linux/fs/proc/generic.c --- linux-2.2.13/fs/proc/generic.c Mon Aug 24 13:02:44 1998 +++ linux/fs/proc/generic.c Thu Dec 9 16:41:29 1999 @@ -64,7 +64,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* @@ -87,7 +91,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/proc/kmsg.c linux/fs/proc/kmsg.c --- linux-2.2.13/fs/proc/kmsg.c Tue Nov 17 10:09:00 1998 +++ linux/fs/proc/kmsg.c Thu Dec 9 16:41:29 1999 @@ -76,5 +76,9 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/proc/link.c linux/fs/proc/link.c --- linux-2.2.13/fs/proc/link.c Mon Aug 9 12:04:41 1999 +++ linux/fs/proc/link.c Thu Dec 9 16:41:29 1999 @@ -53,7 +53,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - proc_permission /* permission */ + proc_permission, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct dentry * proc_follow_link(struct dentry *dentry, diff -urN linux-2.2.13/fs/proc/mem.c linux/fs/proc/mem.c --- linux-2.2.13/fs/proc/mem.c Wed Sep 23 15:24:37 1998 +++ linux/fs/proc/mem.c Thu Dec 9 16:41:30 1999 @@ -340,5 +340,9 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - proc_permission /* permission */ + proc_permission, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/proc/net.c linux/fs/proc/net.c --- linux-2.2.13/fs/proc/net.c Mon Aug 24 13:14:09 1998 +++ linux/fs/proc/net.c Thu Dec 9 16:41:30 1999 @@ -117,5 +117,9 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/proc/omirr.c linux/fs/proc/omirr.c --- linux-2.2.13/fs/proc/omirr.c Mon Aug 24 13:14:09 1998 +++ linux/fs/proc/omirr.c Thu Dec 9 16:41:30 1999 @@ -294,5 +294,8 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- linux-2.2.13/fs/proc/openpromfs.c Wed Apr 28 08:47:39 1999 +++ linux/fs/proc/openpromfs.c Thu Dec 9 16:41:30 1999 @@ -581,7 +581,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct file_operations openpromfs_nodenum_ops = { @@ -615,7 +619,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct file_operations openprom_alias_operations = { @@ -649,7 +657,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int lookup_children(u16 n, const char * name, int len) diff -urN linux-2.2.13/fs/proc/proc_devtree.c linux/fs/proc/proc_devtree.c --- linux-2.2.13/fs/proc/proc_devtree.c Sat Sep 19 13:43:36 1998 +++ linux/fs/proc/proc_devtree.c Thu Dec 9 16:41:30 1999 @@ -62,7 +62,10 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct dentry *devtree_follow_link(struct dentry *dentry, diff -urN linux-2.2.13/fs/proc/root.c linux/fs/proc/root.c --- linux-2.2.13/fs/proc/root.c Tue Oct 19 17:14:02 1999 +++ linux/fs/proc/root.c Thu Dec 9 16:41:30 1999 @@ -75,7 +75,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* @@ -98,7 +102,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* @@ -140,7 +148,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* @@ -297,7 +309,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; struct proc_dir_entry proc_openprom = { @@ -482,7 +498,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct inode_operations proc_link_inode_operations = { @@ -502,7 +522,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct proc_dir_entry proc_root_loadavg = { diff -urN linux-2.2.13/fs/proc/scsi.c linux/fs/proc/scsi.c --- linux-2.2.13/fs/proc/scsi.c Mon Aug 24 13:14:10 1998 +++ linux/fs/proc/scsi.c Thu Dec 9 16:41:30 1999 @@ -75,7 +75,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; int get_not_present_info(char *buffer, char **start, off_t offset, int length) diff -urN linux-2.2.13/fs/qnx4/dir.c linux/fs/qnx4/dir.c --- linux-2.2.13/fs/qnx4/dir.c Tue Oct 19 17:14:02 1999 +++ linux/fs/qnx4/dir.c Thu Dec 9 16:41:30 1999 @@ -124,5 +124,8 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/qnx4/file.c linux/fs/qnx4/file.c --- linux-2.2.13/fs/qnx4/file.c Fri Mar 26 13:57:41 1999 +++ linux/fs/qnx4/file.c Thu Dec 9 16:41:30 1999 @@ -198,7 +198,10 @@ NULL, #endif NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int qnx4_readpage(struct file *file, struct page *page) diff -urN linux-2.2.13/fs/qnx4/symlinks.c linux/fs/qnx4/symlinks.c --- linux-2.2.13/fs/qnx4/symlinks.c Mon Aug 9 12:04:41 1999 +++ linux/fs/qnx4/symlinks.c Thu Dec 9 16:41:30 1999 @@ -46,7 +46,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct dentry *qnx4_follow_link(struct dentry *dentry, diff -urN linux-2.2.13/fs/romfs/inode.c linux/fs/romfs/inode.c --- linux-2.2.13/fs/romfs/inode.c Fri Apr 23 21:20:38 1999 +++ linux/fs/romfs/inode.c Thu Dec 9 16:41:30 1999 @@ -514,6 +514,9 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct file_operations romfs_dir_operations = { @@ -556,6 +559,9 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct inode_operations romfs_link_inode_operations = { @@ -577,6 +583,9 @@ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static mode_t romfs_modemap[] = diff -urN linux-2.2.13/fs/smbfs/dir.c linux/fs/smbfs/dir.c --- linux-2.2.13/fs/smbfs/dir.c Sat May 8 17:56:37 1999 +++ linux/fs/smbfs/dir.c Thu Dec 9 16:41:30 1999 @@ -67,6 +67,7 @@ NULL, /* smap */ NULL, /* updatepage */ smb_revalidate_inode, /* revalidate */ + NULL, /* capability */ }; static ssize_t diff -urN linux-2.2.13/fs/smbfs/file.c linux/fs/smbfs/file.c --- linux-2.2.13/fs/smbfs/file.c Wed Feb 17 15:59:32 1999 +++ linux/fs/smbfs/file.c Thu Dec 9 16:41:30 1999 @@ -388,4 +388,5 @@ NULL, /* smap */ smb_updatepage, /* updatepage */ smb_revalidate_inode, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/sysv/dir.c linux/fs/sysv/dir.c --- linux-2.2.13/fs/sysv/dir.c Fri Apr 23 21:20:38 1999 +++ linux/fs/sysv/dir.c Thu Dec 9 16:41:30 1999 @@ -63,7 +63,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) diff -urN linux-2.2.13/fs/sysv/file.c linux/fs/sysv/file.c --- linux-2.2.13/fs/sysv/file.c Mon Aug 24 13:02:44 1998 +++ linux/fs/sysv/file.c Thu Dec 9 16:41:30 1999 @@ -70,7 +70,11 @@ NULL, /* writepage */ sysv_bmap, /* bmap */ sysv_truncate, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; ssize_t sysv_file_read(struct file * filp, char * buf, diff -urN linux-2.2.13/fs/sysv/symlink.c linux/fs/sysv/symlink.c --- linux-2.2.13/fs/sysv/symlink.c Sat Sep 19 13:45:42 1998 +++ linux/fs/sysv/symlink.c Thu Dec 9 16:41:30 1999 @@ -43,7 +43,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; static struct dentry *sysv_follow_link(struct dentry * dentry, diff -urN linux-2.2.13/fs/ufs/dir.c linux/fs/ufs/dir.c --- linux-2.2.13/fs/ufs/dir.c Fri Apr 23 21:20:38 1999 +++ linux/fs/ufs/dir.c Thu Dec 9 16:41:30 1999 @@ -215,4 +215,7 @@ NULL, /* truncate */ ufs_permission, /* permission */ NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/ufs/file.c linux/fs/ufs/file.c --- linux-2.2.13/fs/ufs/file.c Thu Jan 14 10:31:41 1999 +++ linux/fs/ufs/file.c Thu Dec 9 16:41:30 1999 @@ -84,7 +84,10 @@ ufs_bmap, /* bmap */ ufs_truncate, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* diff -urN linux-2.2.13/fs/ufs/symlink.c linux/fs/ufs/symlink.c --- linux-2.2.13/fs/ufs/symlink.c Thu Jan 14 10:31:41 1999 +++ linux/fs/ufs/symlink.c Thu Dec 9 16:41:30 1999 @@ -134,5 +134,8 @@ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ - NULL /* smap */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/umsdos/dir.c linux/fs/umsdos/dir.c --- linux-2.2.13/fs/umsdos/dir.c Mon Aug 9 12:04:41 1999 +++ linux/fs/umsdos/dir.c Thu Dec 9 16:41:30 1999 @@ -840,4 +840,5 @@ NULL, /* smap */ NULL, /* updatepage */ NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/umsdos/file.c linux/fs/umsdos/file.c --- linux-2.2.13/fs/umsdos/file.c Mon Aug 9 12:04:41 1999 +++ linux/fs/umsdos/file.c Thu Dec 9 16:41:30 1999 @@ -103,7 +103,10 @@ fat_bmap, /* bmap */ UMSDOS_truncate, /* truncate */ NULL, /* permission */ - fat_smap /* smap */ + fat_smap, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* For other with larger and unaligned file system */ @@ -142,6 +145,9 @@ UMSDOS_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* For other with larger and unaligned file system with readpage */ @@ -180,4 +186,7 @@ UMSDOS_truncate, /* truncate */ NULL, /* permission */ NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c --- linux-2.2.13/fs/umsdos/rdir.c Fri Apr 23 21:20:38 1999 +++ linux/fs/umsdos/rdir.c Thu Dec 9 16:41:30 1999 @@ -255,4 +255,5 @@ NULL, /* smap */ NULL, /* updatepage */ NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/umsdos/symlink.c linux/fs/umsdos/symlink.c --- linux-2.2.13/fs/umsdos/symlink.c Sat Sep 19 13:46:28 1998 +++ linux/fs/umsdos/symlink.c Thu Dec 9 16:41:30 1999 @@ -142,6 +142,7 @@ NULL, /* permission */ NULL, /* smap */ NULL, /* updatepage */ - NULL /* revalidate */ + NULL, /* revalidate */ + NULL, /* capability */ }; diff -urN linux-2.2.13/fs/vfat/namei.c linux/fs/vfat/namei.c --- linux-2.2.13/fs/vfat/namei.c Mon Aug 9 12:04:41 1999 +++ linux/fs/vfat/namei.c Thu Dec 9 16:41:30 1999 @@ -1240,7 +1240,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; struct super_block *vfat_read_super(struct super_block *sb,void *data, diff -urN linux-2.2.13/include/linux/capability.h linux/include/linux/capability.h --- linux-2.2.13/include/linux/capability.h Tue Oct 19 17:14:02 1999 +++ linux/include/linux/capability.h Sat Dec 11 19:29:59 1999 @@ -10,12 +10,14 @@ #define _LINUX_CAPABILITY_H #include -#include /* User-level do most of the mapping between kernel and user capabilities based on the version tag given by the kernel. The kernel might be somewhat backwards compatible, but don't bet on - it. */ + it. See, + + ftp://linux.kernel.org/pub/linux/libs/linux-privs + */ /* XXX - Note, cap_t, is defined by POSIX to be an "opaque" pointer to a set of three capability sets. The transposition of 3*the @@ -23,11 +25,20 @@ library since the draft standard requires the use of malloc/free etc.. */ -#define _LINUX_CAPABILITY_VERSION 0x19980330 +#define _LINUX_CAPABILITY_VERSION 0x19990414 + +#define _CAPABILITY_TYPE_PROCESS 0x00000001 +#define _CAPABILITY_TYPE_FILE 0x00000002 +#define _CAPABILITY_TYPE_FILDES 0x00000003 typedef struct __user_cap_header_struct { __u32 version; - int pid; + int type; + union { + int pid; /* process manipulation */ + const char *path; /* filename manipulation */ + unsigned int fildes; /* filedescriptor manipulation */ + } u; } *cap_user_header_t; typedef struct __user_cap_data_struct { @@ -263,11 +274,24 @@ #define CAP_SYS_TTY_CONFIG 26 +/* Allow changes to capability flags associated with files */ + +#define CAP_SETFCAP 27 + #ifdef __KERNEL__ /* * Bounding set */ +#ifdef CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE + extern kernel_cap_t cap_bset; +# define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag) & cap_bset) + +#else /* ndef CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE */ + +# define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag)) + +#endif /* CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE */ /* * Internal kernel functions only @@ -290,10 +314,9 @@ #define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP)) #define CAP_INIT_INH_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP)) -#define CAP_TO_MASK(x) (1 << (x)) -#define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag)) -#define cap_lower(c, flag) (cap_t(c) &= ~CAP_TO_MASK(flag)) -#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag) & cap_bset) +#define CAP_TO_MASK(x) (1 << (x)) +#define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag)) +#define cap_lower(c, flag) (cap_t(c) &= ~CAP_TO_MASK(flag)) static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b) { @@ -332,6 +355,23 @@ #define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK) +/* + * filesystem capability operations (arguments to vfs_cap_inode) + */ + +#define _CAP_FS_SET 0x0001 +#define _CAP_FS_GET 0x0002 + +/* preemption is a flag |'d with one of the above flags and used to + tell the 'VFS_CAP_PLUGIN' that the operation is being done in + advance of querying the filesystem's support for capabilities. The + return of -ENOSYS by the module in such a case indicates that the + module has ignored this call. Any other return value indicates that + the module has specified the capabilities on this file and that the + kernel should not go on to interrogate the filesystem. */ + +#define _CAP_FS_PREEMPT 0x1000 + #endif /* __KERNEL__ */ -#endif /* !_LINUX_CAPABILITY_H */ +#endif /* ndef _LINUX_CAPABILITY_H */ diff -urN linux-2.2.13/include/linux/fs.h linux/include/linux/fs.h --- linux-2.2.13/include/linux/fs.h Tue Oct 19 17:14:02 1999 +++ linux/include/linux/fs.h Sat Dec 11 19:29:59 1999 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -568,6 +569,15 @@ extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *); extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); +extern int vfs_cap_dentry(struct dentry *, int, kernel_cap_t *, + kernel_cap_t *, kernel_cap_t *); + +extern int fs_capability_fn_register(int + (*fs_cap_fn)(struct dentry *dentry, + int operation, + kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted)); /* * This is the "filldir" function type, used by readdir() to let @@ -617,6 +627,8 @@ int (*smap) (struct inode *,int); int (*updatepage) (struct file *, struct page *, unsigned long, unsigned int, int); int (*revalidate) (struct dentry *); + int (*capability) (struct inode *, int, + kernel_cap_t *, kernel_cap_t *, kernel_cap_t *); }; struct super_operations { diff -urN linux-2.2.13/include/linux/sched.h linux/include/linux/sched.h --- linux-2.2.13/include/linux/sched.h Tue Oct 19 17:14:02 1999 +++ linux/include/linux/sched.h Sat Dec 11 19:29:59 1999 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include /* @@ -66,7 +68,6 @@ extern int last_pid; #include -#include #include #include #include @@ -611,11 +612,7 @@ extern inline int capable(int cap) { -#if 1 /* ok now */ if (cap_raised(current->cap_effective, cap)) -#else - if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0) -#endif { current->flags |= PF_SUPERPRIV; return 1; diff -urN linux-2.2.13/kernel/capability.c linux/kernel/capability.c --- linux-2.2.13/kernel/capability.c Mon Aug 9 12:04:41 1999 +++ linux/kernel/capability.c Thu Dec 9 17:16:30 1999 @@ -2,49 +2,48 @@ * linux/kernel/capability.c * * Copyright (C) 1997 Andrew Main - * Integrated into 2.1.97+, Andrew G. Morgan + * Integrated into 2.1.97+, Andrew G. Morgan + * added filesystem capability support Andrew G. Morgan */ #include -#include - -/* Note: never hold tasklist_lock while spinning for this one */ -spinlock_t task_capability_lock; +#include +#include +#include -/* - * For sys_getproccap() and sys_setproccap(), any of the three - * capability set pointers may be NULL -- indicating that that set is - * uninteresting and/or not to be changed. - */ +#include -kernel_cap_t cap_bset = CAP_FULL_SET; +/* verify that the user knows the correct capability structure */ -asmlinkage int sys_capget(cap_user_header_t header, cap_user_data_t dataptr) +static int check_cap_version(cap_user_header_t header) { - int error, pid; __u32 version; - struct task_struct *target; - struct __user_cap_data_struct data; if (get_user(version, &header->version)) return -EFAULT; - error = -EINVAL; if (version != _LINUX_CAPABILITY_VERSION) { version = _LINUX_CAPABILITY_VERSION; if (put_user(version, &header->version)) - error = -EFAULT; - return error; + return -EFAULT; + return -EINVAL; } - if (get_user(pid, &header->pid)) - return -EFAULT; + return 0; +} + + +/* Note: never hold tasklist_lock while spinning for this one */ +spinlock_t task_capability_lock; + +static int getpcap(int pid, struct __user_cap_data_struct *data) +{ + int error = 0; + struct task_struct *target; if (pid < 0) return -EINVAL; - error = 0; - spin_lock(&task_capability_lock); if (pid && pid != current->pid) { @@ -57,15 +56,117 @@ } if (!error) { - data.permitted = cap_t(target->cap_permitted); - data.inheritable = cap_t(target->cap_inheritable); - data.effective = cap_t(target->cap_effective); + data->permitted = cap_t(target->cap_permitted); + data->inheritable = cap_t(target->cap_inheritable); + data->effective = cap_t(target->cap_effective); } if (target != current) read_unlock(&tasklist_lock); + spin_unlock(&task_capability_lock); + return error; +} + +static int dofdcap(unsigned int fd, int operation, kernel_cap_t *effective, + kernel_cap_t *inheritable, kernel_cap_t *permitted) +{ + struct file * file; + int error = -EBADF; + + lock_kernel(); + file = fget(fd); + if (file == NULL) { + goto out; + } + if (!IS_ERR(file->f_dentry)) { + error = vfs_cap_dentry(file->f_dentry, operation, + effective, inheritable, permitted); + } + fput(file); + +out: + unlock_kernel(); + + return error; +} + +static int dofcap(const char *filename, int operation, kernel_cap_t *effective, + kernel_cap_t *inheritable, kernel_cap_t *permitted) +{ + struct dentry * dentry; + int error; + + lock_kernel(); + dentry = namei(filename); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = vfs_cap_dentry(dentry, operation, + effective, inheritable, permitted); + dput(dentry); + } + unlock_kernel(); + + return error; +} + +asmlinkage int sys_capget(cap_user_header_t header, cap_user_data_t dataptr) +{ + int error, type; + struct __user_cap_data_struct data; + + error = check_cap_version(header); + if (error) { + return error; + } + + if (get_user(type, &header->type)) + return -EFAULT; + + switch (type) { + + case _CAPABILITY_TYPE_PROCESS: + { + int pid; + + if (get_user(pid, &header->u.pid)) + return -EFAULT; + + error = getpcap(pid, &data); + break; + } + + case _CAPABILITY_TYPE_FILDES: + { + unsigned int fd; + + if (get_user(fd, &header->u.fildes)) { + return -EFAULT; + } + + error = dofdcap(fd, _CAP_FS_GET, &data.effective, + &data.inheritable, &data.permitted); + break; + } + + case _CAPABILITY_TYPE_FILE: + { + const char * filename; + + if (get_user(filename, &header->u.path)) { + return -EFAULT; + } + + error = dofcap(filename, _CAP_FS_GET, &data.effective, + &data.inheritable, &data.permitted); + break; + } + + default: + return -EINVAL; + } + if (!error) { if (copy_to_user(dataptr, &data, sizeof data)) return -EFAULT; @@ -83,7 +184,6 @@ { struct task_struct *target; - /* FIXME: do we need to have a write lock here..? */ read_lock(&tasklist_lock); for_each_task(target) { if (target->pgrp != pgrp) @@ -103,7 +203,6 @@ { struct task_struct *target; - /* FIXME: do we need to have a write lock here..? */ read_lock(&tasklist_lock); /* ALL means everyone other than self or 'init' */ for_each_task(target) { @@ -126,35 +225,12 @@ * E: must be set to a subset of (new target) Permitted */ -asmlinkage int sys_capset(cap_user_header_t header, const cap_user_data_t data) +static int setpcap(int pid, kernel_cap_t *effective, kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - kernel_cap_t inheritable, permitted, effective; - __u32 version; struct task_struct *target; - int error, pid; - - if (get_user(version, &header->version)) - return -EFAULT; + int error = -EPERM; - if (version != _LINUX_CAPABILITY_VERSION) { - version = _LINUX_CAPABILITY_VERSION; - if (put_user(version, &header->version)) - return -EFAULT; - return -EINVAL; - } - - if (get_user(pid, &header->pid)) - return -EFAULT; - - if (pid && !capable(CAP_SETPCAP)) - return -EPERM; - - if (copy_from_user(&effective, &data->effective, sizeof(effective)) || - copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || - copy_from_user(&permitted, &data->permitted, sizeof(permitted))) - return -EFAULT; - - error = -EPERM; spin_lock(&task_capability_lock); if (pid > 0 && pid != current->pid) { @@ -170,21 +246,21 @@ /* verify restrictions on target's new Inheritable set */ - if (!cap_issubset(inheritable, + if (!cap_issubset(*inheritable, cap_combine(target->cap_inheritable, current->cap_permitted))) { goto out; } /* verify restrictions on target's new Permitted set */ - if (!cap_issubset(permitted, + if (!cap_issubset(*permitted, cap_combine(target->cap_permitted, current->cap_permitted))) { goto out; } /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ - if (!cap_issubset(effective, permitted)) { + if (!cap_issubset(*effective, *permitted)) { goto out; } @@ -194,23 +270,106 @@ if (pid < 0) { if (pid == -1) /* all procs other than current and init */ - cap_set_all(&effective, &inheritable, &permitted); + cap_set_all(effective, inheritable, permitted); else /* all procs in process group */ - cap_set_pg(-pid, &effective, &inheritable, &permitted); + cap_set_pg(-pid, effective, inheritable, permitted); goto spin_out; } else { /* FIXME: do we need to have a write lock here..? */ - target->cap_effective = effective; - target->cap_inheritable = inheritable; - target->cap_permitted = permitted; + target->cap_effective = *effective; + target->cap_inheritable = *inheritable; + target->cap_permitted = *permitted; } out: if (target != current) { read_unlock(&tasklist_lock); } + spin_out: spin_unlock(&task_capability_lock); + + return error; +} + +asmlinkage int sys_capset(cap_user_header_t header, const cap_user_data_t data) +{ + kernel_cap_t effective, permitted, inheritable; + int error, type; + + error = check_cap_version(header); + if (error) { + return error; + } + + if (get_user(type, &header->type)) + return -EFAULT; + + if (copy_from_user(&effective, &data->effective, sizeof(effective)) || + copy_from_user(&inheritable, &data->inheritable, + sizeof(inheritable)) || + copy_from_user(&permitted, &data->permitted, sizeof(permitted))) { + return -EFAULT; + } + + switch (type) { + + case _CAPABILITY_TYPE_PROCESS: + { + int pid; + + if (get_user(pid, &header->u.pid)) { + return -EFAULT; + } + if (pid && !capable(CAP_SETPCAP)) { + return -EPERM; + } + + error = setpcap(pid, &effective, &inheritable, &permitted); + + break; + } + + case _CAPABILITY_TYPE_FILDES: + { + unsigned int fd; + + if (get_user(fd, &header->u.fildes)) { + return -EFAULT; + } + if (!capable(CAP_SETFCAP)) { + return -EPERM; + } + + error = dofdcap(fd, _CAP_FS_SET, &effective, &inheritable, + &permitted); + break; + } + + case _CAPABILITY_TYPE_FILE: + { + const char *filename; + + if (get_user(filename, &header->u.path)) { + return -EFAULT; + } + if (!capable(CAP_SETFCAP)) { + return -EPERM; + } + + error = dofcap(filename, _CAP_FS_SET, &effective, &inheritable, + &permitted); + break; + } + + default: + return -EINVAL; + } + return error; } + +#ifdef CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE +kernel_cap_t cap_bset = CAP_FULL_SET; +#endif /* CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE */ diff -urN linux-2.2.13/kernel/ksyms.c linux/kernel/ksyms.c --- linux-2.2.13/kernel/ksyms.c Tue Oct 19 17:14:02 1999 +++ linux/kernel/ksyms.c Fri Dec 10 20:04:39 1999 @@ -344,7 +344,9 @@ EXPORT_SYMBOL(secure_tcp_sequence_number); EXPORT_SYMBOL(get_random_bytes); EXPORT_SYMBOL(securebits); +#ifdef CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE EXPORT_SYMBOL(cap_bset); +#endif /* CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE */ /* Program loader interfaces */ EXPORT_SYMBOL(setup_arg_pages); @@ -405,6 +407,11 @@ /* library functions */ EXPORT_SYMBOL(strnicmp); + +#ifdef CONFIG_VFS_CAP_PLUGIN +/* capabilities */ +EXPORT_SYMBOL(fs_capability_fn_register); +#endif /* CONFIG_VFS_CAP_PLUGIN */ /* init task, for moving kthread roots - ought to export a function ?? */ EXPORT_SYMBOL(init_task_union); diff -urN linux-2.2.13/kernel/sysctl.c linux/kernel/sysctl.c --- linux-2.2.13/kernel/sysctl.c Tue Oct 19 17:14:02 1999 +++ linux/kernel/sysctl.c Sat Dec 11 17:50:25 1999 @@ -128,7 +128,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - proc_sys_permission + proc_sys_permission, + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; extern struct proc_dir_entry proc_sys_root; @@ -169,8 +173,10 @@ 0644, NULL, &proc_doutsstring, &sysctl_string}, {KERN_PANIC, "panic", &panic_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, +#ifdef CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE {KERN_CAP_BSET, "cap-bound", &cap_bset, sizeof(kernel_cap_t), 0600, NULL, &proc_dointvec_bset}, +#endif /* CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE */ #ifdef CONFIG_BLK_DEV_INITRD {KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int), 0644, NULL, &proc_dointvec}, @@ -809,16 +815,19 @@ return do_proc_dointvec(table,write,filp,buffer,lenp,1,OP_SET); } + +#ifdef CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE */ /* * init may raise the set. */ - + int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp) { return do_proc_dointvec(table,write,filp,buffer,lenp,1, (current->pid == 1) ? OP_SET : OP_AND); } +#endif /* CONFIG_PERMIT_CAPABILITY_DENIAL_OF_SERVICE */ int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, diff -urN linux-2.2.13/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c --- linux-2.2.13/net/wanrouter/wanproc.c Sun Nov 15 09:52:29 1998 +++ linux/net/wanrouter/wanproc.c Thu Dec 9 16:41:30 1999 @@ -129,7 +129,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - router_proc_perms + router_proc_perms, + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /* @@ -169,7 +173,11 @@ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ - router_proc_perms + router_proc_perms, + NULL, /* smap */ + NULL, /* updatepage */ + NULL, /* revalidate */ + NULL, /* capability */ }; /*