===== arch/i386/kernel/entry.S 1.77 vs edited ===== --- 1.77/arch/i386/kernel/entry.S 2004-05-22 23:56:24 +02:00 +++ edited/arch/i386/kernel/entry.S 2004-08-10 20:11:29 +02:00 @@ -886,5 +886,6 @@ .long sys_mq_notify .long sys_mq_getsetattr .long sys_ni_syscall /* reserved for kexec */ + .long sys_revoke syscall_table_size=(.-sys_call_table) ===== fs/open.c 1.68 vs edited ===== --- 1.68/fs/open.c 2004-08-08 03:54:13 +02:00 +++ edited/fs/open.c 2004-08-11 18:58:26 +02:00 @@ -1043,6 +1043,134 @@ EXPORT_SYMBOL(sys_close); +static int revoke_ret_ebadf(void) +{ + return -EBADF; +} + +static ssize_t revoke_read(struct file *filp, + char *buf, + size_t count, + loff_t *ppos) +{ + return 0; +} + +static int revoke_release(struct inode *inode, struct file *filp) +{ + fops_put(filp->f_op); + filp->f_op = NULL; + return 0; +} + +static ssize_t revoke_readv(struct file *filp, + const struct iovec *iov, + unsigned long count, + loff_t *ppos) +{ + return 0; +} + +static struct file_operations revoke_fops = { + .owner = THIS_MODULE, + .llseek = (void *)revoke_ret_ebadf, + .read = revoke_read, + .write = (void *)revoke_ret_ebadf, + .readdir = (void *)revoke_ret_ebadf, + .poll = (void *)revoke_ret_ebadf, + .ioctl = (void *)revoke_ret_ebadf, + .mmap = (void *)revoke_ret_ebadf, + .open = (void *)revoke_ret_ebadf, + .flush = (void *)revoke_ret_ebadf, + .release = revoke_release, + .fsync = (void *)revoke_ret_ebadf, + .fasync = (void *)revoke_ret_ebadf, + .lock = (void *)revoke_ret_ebadf, + .readv = revoke_readv, + .writev = (void *)revoke_ret_ebadf, +}; + +static int filp_revoke(struct file *filp, struct inode *inode) +{ + struct file_operations *fops = filp->f_op; + int ret = 0; + + down(&inode->i_sem); + if (!fops || !file_count(filp)) + goto out_truncate; + + filp->f_op = &revoke_fops; + + if (fops->flush) + fops->flush(filp); + if (fops->release) + ret = fops->release(inode, filp); + fops_put(fops); + +out_truncate: + vmtruncate(inode, (loff_t)0); + up(&inode->i_sem); + return ret; +} + +asmlinkage int sys_revoke(const char *path) +{ + struct nameidata nd; + struct super_block *sb; + struct list_head *p; + struct file *filp; + int ret = 0; +printk("called sys_revoke()\n"); + + if (user_path_walk(path, &nd)) { +printk("user_path_walk() failed\n"); + ret = -ENOENT; + goto out; + } + if (!nd.dentry->d_inode) { +printk("no inode\n"); + ret = -ENOENT; + goto out_release; + } + /* Allow only on Character or Block Devices. */ + if (!S_ISCHR(nd.dentry->d_inode->i_mode) && + !S_ISBLK(nd.dentry->d_inode->i_mode)) { +printk("no CHK/BLK\n"); + ret = -EINVAL; + goto out_release; + } + if ((current->fsuid != nd.dentry->d_inode->i_uid) || + !capable(CAP_FOWNER)) { +printk("perm\n"); + ret = -EPERM; + goto out_release; + } + + sb = nd.dentry->d_inode->i_sb; + file_list_lock(); + for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { + filp = list_entry(p, struct file, f_list); + + if (!filp || !filp->f_dentry) + continue; + if (nd.dentry != filp->f_dentry) + continue; + if (filp->f_op == &revoke_fops) + continue; + if (!filp->f_dentry->d_inode) + continue; + + ret = filp_revoke(filp, filp->f_dentry->d_inode); + } + file_list_unlock(); +printk("done"); + +out_release: + path_release(&nd); +out: + return ret; +} + /* * This routine simulates a hangup on the tty, to arrange that users * are given clean terminals at login time. ===== include/asm-i386/unistd.h 1.39 vs edited ===== --- 1.39/include/asm-i386/unistd.h 2004-08-02 10:00:44 +02:00 +++ edited/include/asm-i386/unistd.h 2004-08-10 20:14:44 +02:00 @@ -289,8 +289,9 @@ #define __NR_mq_notify (__NR_mq_open+4) #define __NR_mq_getsetattr (__NR_mq_open+5) #define __NR_sys_kexec_load 283 +#define __NR_revoke 284 -#define NR_syscalls 284 +#define NR_syscalls 285 /* user-visible error numbers are in the range -1 - -124: see */