Hello, > From: Pekka Enberg <penberg@xxxxxxxxxxxxxx> > > The revokeat(2) and frevoke(2) system calls invalidate open file > descriptors and shared mappings of an inode. After an successful > revocation, operations on file descriptors fail with the EBADF or > ENXIO error code for regular and device files, > respectively. Attempting to read from or write to a revoked mapping > causes SIGBUS. > > The actual operation is done in two passes: > > 1. Revoke all file descriptors that point to the given inode. We do > this under tasklist_lock so that after this pass, we don't need > to worry about racing with close(2) or dup(2). > > 2. Take down shared memory mappings of each revoked file and close > the file pointer. > > The file descriptors are kept until the owning task does close(2) and > memory mapping ranges preserved until the owning task does munmap(2). > > Signed-off-by: Pekka Enberg <penberg@xxxxxxxxxxxxxx> Have you considered using similar hack as bad_inode.c instead of revoked_inode.c? > Index: 2.6/fs/revoked_inode.c > =================================================================== > --- /dev/null > +++ 2.6/fs/revoked_inode.c > @@ -0,0 +1,664 @@ > +/* > + * linux/fs/revoked_inode.c > + * > + * Copyright (C) 1997, Stephen Tweedie > + * > + * Provide stub functions for revoked inodes > + */ > + > +#include <linux/fs.h> > +#include <linux/module.h> > +#include <linux/stat.h> > +#include <linux/time.h> > +#include <linux/smp_lock.h> > +#include <linux/namei.h> > +#include <linux/poll.h> > + > +static loff_t revoked_file_llseek(struct file *file, loff_t offset, int origin) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_read(struct file *filp, char __user * buf, > + size_t size, loff_t * ppos) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_write(struct file *filp, const char __user * buf, > + size_t siz, loff_t * ppos) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_aio_read(struct kiocb *iocb, > + const struct iovec *iov, > + unsigned long nr_segs, loff_t pos) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_aio_write(struct kiocb *iocb, > + const struct iovec *iov, > + unsigned long nr_segs, loff_t pos) > +{ > + return -EBADF; > +} > + > +static int revoked_file_readdir(struct file *filp, void *dirent, > + filldir_t filldir) > +{ > + return -EBADF; > +} > + > +static unsigned int revoked_file_poll(struct file *filp, poll_table * wait) > +{ > + return POLLERR; > +} > + > +static int revoked_file_ioctl(struct inode *inode, struct file *filp, > + unsigned int cmd, unsigned long arg) > +{ > + return -EBADF; > +} > + > +static long revoked_file_unlocked_ioctl(struct file *file, unsigned cmd, > + unsigned long arg) > +{ > + return -EBADF; > +} > + > +static long revoked_file_compat_ioctl(struct file *file, unsigned int cmd, > + unsigned long arg) > +{ > + return -EBADF; > +} > + > +static int revoked_file_mmap(struct file *file, struct vm_area_struct *vma) > +{ > + return -EBADF; > +} > + > +static int revoked_file_open(struct inode *inode, struct file *filp) > +{ > + return -EBADF; > +} > + > +static int revoked_file_flush(struct file *file, fl_owner_t id) > +{ > + return 0; > +} > + > +static int revoked_file_release(struct inode *inode, struct file *filp) > +{ > + return -EBADF; > +} > + > +static int revoked_file_fsync(struct file *file, struct dentry *dentry, > + int datasync) > +{ > + return -EBADF; > +} > + > +static int revoked_file_aio_fsync(struct kiocb *iocb, int datasync) > +{ > + return -EBADF; > +} > + > +static int revoked_file_fasync(int fd, struct file *filp, int on) > +{ > + return -EBADF; > +} > + > +static int revoked_file_lock(struct file *file, int cmd, struct file_lock *fl) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_sendfile(struct file *in_file, loff_t * ppos, > + size_t count, read_actor_t actor, > + void *target) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_sendpage(struct file *file, struct page *page, > + int off, size_t len, loff_t * pos, > + int more) > +{ > + return -EBADF; > +} > + > +static unsigned long revoked_file_get_unmapped_area(struct file *file, > + unsigned long addr, > + unsigned long len, > + unsigned long pgoff, > + unsigned long flags) > +{ > + return -EBADF; > +} > + > +static int revoked_file_check_flags(int flags) > +{ > + return -EBADF; > +} > + > +static int revoked_file_dir_notify(struct file *file, unsigned long arg) > +{ > + return -EBADF; > +} > + > +static int revoked_file_flock(struct file *filp, int cmd, struct file_lock *fl) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_splice_write(struct pipe_inode_info *pipe, > + struct file *out, loff_t * ppos, > + size_t len, unsigned int flags) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_file_splice_read(struct file *in, loff_t * ppos, > + struct pipe_inode_info *pipe, > + size_t len, unsigned int flags) > +{ > + return -EBADF; > +} > + > +static const struct file_operations revoked_file_ops = { > + .llseek = revoked_file_llseek, > + .read = revoked_file_read, > + .write = revoked_file_write, > + .aio_read = revoked_file_aio_read, > + .aio_write = revoked_file_aio_write, > + .readdir = revoked_file_readdir, > + .poll = revoked_file_poll, > + .ioctl = revoked_file_ioctl, > + .unlocked_ioctl = revoked_file_unlocked_ioctl, > + .compat_ioctl = revoked_file_compat_ioctl, > + .mmap = revoked_file_mmap, > + .open = revoked_file_open, > + .flush = revoked_file_flush, > + .release = revoked_file_release, > + .fsync = revoked_file_fsync, > + .aio_fsync = revoked_file_aio_fsync, > + .fasync = revoked_file_fasync, > + .lock = revoked_file_lock, > + .sendfile = revoked_file_sendfile, > + .sendpage = revoked_file_sendpage, > + .get_unmapped_area = revoked_file_get_unmapped_area, > + .check_flags = revoked_file_check_flags, > + .dir_notify = revoked_file_dir_notify, > + .flock = revoked_file_flock, > + .splice_write = revoked_file_splice_write, > + .splice_read = revoked_file_splice_read, > +}; > + > +static int revoked_inode_create(struct inode *dir, struct dentry *dentry, > + int mode, struct nameidata *nd) > +{ > + return -EBADF; > +} > + > +static struct dentry *revoked_inode_lookup(struct inode *dir, > + struct dentry *dentry, > + struct nameidata *nd) > +{ > + return ERR_PTR(-EBADF); > +} > + > +static int revoked_inode_link(struct dentry *old_dentry, struct inode *dir, > + struct dentry *dentry) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_unlink(struct inode *dir, struct dentry *dentry) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_symlink(struct inode *dir, struct dentry *dentry, > + const char *symname) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_mkdir(struct inode *dir, struct dentry *dentry, > + int mode) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_rmdir(struct inode *dir, struct dentry *dentry) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_mknod(struct inode *dir, struct dentry *dentry, > + int mode, dev_t rdev) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_rename(struct inode *old_dir, > + struct dentry *old_dentry, > + struct inode *new_dir, > + struct dentry *new_dentry) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_readlink(struct dentry *dentry, char __user * buffer, > + int buflen) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_permission(struct inode *inode, int mask, > + struct nameidata *nd) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, > + struct kstat *stat) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_setattr(struct dentry *direntry, struct iattr *attrs) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_setxattr(struct dentry *dentry, const char *name, > + const void *value, size_t size, int flags) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_inode_getxattr(struct dentry *dentry, const char *name, > + void *buffer, size_t size) > +{ > + return -EBADF; > +} > + > +static ssize_t revoked_inode_listxattr(struct dentry *dentry, char *buffer, > + size_t buffer_size) > +{ > + return -EBADF; > +} > + > +static int revoked_inode_removexattr(struct dentry *dentry, const char *name) > +{ > + return -EBADF; > +} > + > +static struct inode_operations revoked_inode_ops = { > + .create = revoked_inode_create, > + .lookup = revoked_inode_lookup, > + .link = revoked_inode_link, > + .unlink = revoked_inode_unlink, > + .symlink = revoked_inode_symlink, > + .mkdir = revoked_inode_mkdir, > + .rmdir = revoked_inode_rmdir, > + .mknod = revoked_inode_mknod, > + .rename = revoked_inode_rename, > + .readlink = revoked_inode_readlink, > + /* follow_link must be no-op, otherwise unmounting this inode > + won't work */ > + /* put_link returns void */ > + /* truncate returns void */ > + .permission = revoked_inode_permission, > + .getattr = revoked_inode_getattr, > + .setattr = revoked_inode_setattr, > + .setxattr = revoked_inode_setxattr, > + .getxattr = revoked_inode_getxattr, > + .listxattr = revoked_inode_listxattr, > + .removexattr = revoked_inode_removexattr, > + /* truncate_range returns void */ > +}; > + > +static loff_t revoked_special_file_llseek(struct file *file, loff_t offset, > + int origin) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_read(struct file *filp, char __user * buf, > + size_t size, loff_t * ppos) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_write(struct file *filp, > + const char __user * buf, size_t siz, > + loff_t * ppos) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_aio_read(struct kiocb *iocb, > + const struct iovec *iov, > + unsigned long nr_segs, loff_t pos) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_aio_write(struct kiocb *iocb, > + const struct iovec *iov, > + unsigned long nr_segs, loff_t pos) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_readdir(struct file *filp, void *dirent, > + filldir_t filldir) > +{ > + return -ENXIO; > +} > + > +static unsigned int revoked_special_file_poll(struct file *filp, > + poll_table * wait) > +{ > + return POLLERR; > +} > + > +static int revoked_special_file_ioctl(struct inode *inode, struct file *filp, > + unsigned int cmd, unsigned long arg) > +{ > + return -ENXIO; > +} > + > +static long revoked_special_file_unlocked_ioctl(struct file *file, unsigned cmd, > + unsigned long arg) > +{ > + return -ENXIO; > +} > + > +static long revoked_special_file_compat_ioctl(struct file *file, > + unsigned int cmd, > + unsigned long arg) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_mmap(struct file *file, > + struct vm_area_struct *vma) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_open(struct inode *inode, struct file *filp) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_flush(struct file *file, fl_owner_t id) > +{ > + return 0; > +} > + > +static int revoked_special_file_release(struct inode *inode, struct file *filp) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_fsync(struct file *file, struct dentry *dentry, > + int datasync) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_aio_fsync(struct kiocb *iocb, int datasync) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_fasync(int fd, struct file *filp, int on) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_lock(struct file *file, int cmd, > + struct file_lock *fl) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_sendfile(struct file *in_file, > + loff_t * ppos, size_t count, > + read_actor_t actor, void *target) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_sendpage(struct file *file, > + struct page *page, int off, > + size_t len, loff_t * pos, int more) > +{ > + return -ENXIO; > +} > + > +static unsigned long revoked_special_file_get_unmapped_area(struct file *file, > + unsigned long addr, > + unsigned long len, > + unsigned long pgoff, > + unsigned long flags) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_check_flags(int flags) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_dir_notify(struct file *file, unsigned long arg) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_file_flock(struct file *filp, int cmd, > + struct file_lock *fl) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_splice_write(struct pipe_inode_info *pipe, > + struct file *out, > + loff_t * ppos, size_t len, > + unsigned int flags) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_file_splice_read(struct file *in, loff_t * ppos, > + struct pipe_inode_info *pipe, > + size_t len, unsigned int flags) > +{ > + return -ENXIO; > +} > + > +static const struct file_operations revoked_special_file_ops = { > + .llseek = revoked_special_file_llseek, > + .read = revoked_special_file_read, > + .write = revoked_special_file_write, > + .aio_read = revoked_special_file_aio_read, > + .aio_write = revoked_special_file_aio_write, > + .readdir = revoked_special_file_readdir, > + .poll = revoked_special_file_poll, > + .ioctl = revoked_special_file_ioctl, > + .unlocked_ioctl = revoked_special_file_unlocked_ioctl, > + .compat_ioctl = revoked_special_file_compat_ioctl, > + .mmap = revoked_special_file_mmap, > + .open = revoked_special_file_open, > + .flush = revoked_special_file_flush, > + .release = revoked_special_file_release, > + .fsync = revoked_special_file_fsync, > + .aio_fsync = revoked_special_file_aio_fsync, > + .fasync = revoked_special_file_fasync, > + .lock = revoked_special_file_lock, > + .sendfile = revoked_special_file_sendfile, > + .sendpage = revoked_special_file_sendpage, > + .get_unmapped_area = revoked_special_file_get_unmapped_area, > + .check_flags = revoked_special_file_check_flags, > + .dir_notify = revoked_special_file_dir_notify, > + .flock = revoked_special_file_flock, > + .splice_write = revoked_special_file_splice_write, > + .splice_read = revoked_special_file_splice_read, > +}; > + > +static int revoked_special_inode_create(struct inode *dir, > + struct dentry *dentry, int mode, > + struct nameidata *nd) > +{ > + return -ENXIO; > +} > + > +static struct dentry *revoked_special_inode_lookup(struct inode *dir, > + struct dentry *dentry, > + struct nameidata *nd) > +{ > + return ERR_PTR(-ENXIO); > +} > + > +static int revoked_special_inode_link(struct dentry *old_dentry, > + struct inode *dir, struct dentry *dentry) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_unlink(struct inode *dir, > + struct dentry *dentry) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_symlink(struct inode *dir, > + struct dentry *dentry, > + const char *symname) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_mkdir(struct inode *dir, struct dentry *dentry, > + int mode) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_rmdir(struct inode *dir, struct dentry *dentry) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_mknod(struct inode *dir, struct dentry *dentry, > + int mode, dev_t rdev) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_rename(struct inode *old_dir, > + struct dentry *old_dentry, > + struct inode *new_dir, > + struct dentry *new_dentry) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_readlink(struct dentry *dentry, > + char __user * buffer, int buflen) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_permission(struct inode *inode, int mask, > + struct nameidata *nd) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_getattr(struct vfsmount *mnt, > + struct dentry *dentry, > + struct kstat *stat) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_setattr(struct dentry *direntry, > + struct iattr *attrs) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_setxattr(struct dentry *dentry, > + const char *name, const void *value, > + size_t size, int flags) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_inode_getxattr(struct dentry *dentry, > + const char *name, void *buffer, > + size_t size) > +{ > + return -ENXIO; > +} > + > +static ssize_t revoked_special_inode_listxattr(struct dentry *dentry, > + char *buffer, size_t buffer_size) > +{ > + return -ENXIO; > +} > + > +static int revoked_special_inode_removexattr(struct dentry *dentry, > + const char *name) > +{ > + return -ENXIO; > +} > + > +static struct inode_operations revoked_special_inode_ops = { > + .create = revoked_special_inode_create, > + .lookup = revoked_special_inode_lookup, > + .link = revoked_special_inode_link, > + .unlink = revoked_special_inode_unlink, > + .symlink = revoked_special_inode_symlink, > + .mkdir = revoked_special_inode_mkdir, > + .rmdir = revoked_special_inode_rmdir, > + .mknod = revoked_special_inode_mknod, > + .rename = revoked_special_inode_rename, > + .readlink = revoked_special_inode_readlink, > + /* follow_link must be no-op, otherwise unmounting this inode > + won't work */ > + /* put_link returns void */ > + /* truncate returns void */ > + .permission = revoked_special_inode_permission, > + .getattr = revoked_special_inode_getattr, > + .setattr = revoked_special_inode_setattr, > + .setxattr = revoked_special_inode_setxattr, > + .getxattr = revoked_special_inode_getxattr, > + .listxattr = revoked_special_inode_listxattr, > + .removexattr = revoked_special_inode_removexattr, > + /* truncate_range returns void */ > +}; > + > +void make_revoked_inode(struct inode *inode, int mode) > +{ > + remove_inode_hash(inode); > + > + inode->i_mode = mode; > + inode->i_atime = inode->i_mtime = inode->i_ctime = > + current_fs_time(inode->i_sb); > + > + if (special_file(mode)) { > + inode->i_op = &revoked_special_inode_ops; > + inode->i_fop = &revoked_special_file_ops; > + } else { > + inode->i_op = &revoked_inode_ops; > + inode->i_fop = &revoked_file_ops; > + } > +} > - > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ Honza -- Jan Kara <jack@xxxxxxx> SuSE CR Labs - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html