[MORE SHITE] revoke() again. (v0.0.0.0.0.4 :)

Matthew Kirkwood (weejock@ferret.lmh.ox.ac.uk)
Fri, 12 Dec 1997 02:02:39 +0000 (GMT)


Hi,

OK, apologies for battering the list, but here is
there yet another revoke patch. In this version
(oooh!) are the tty thing suggested by tytso, and
a forced, but friendly, unmap of mmap()ed stuff,
which *BSD seems to omit.

Once again, there are perhaps some abstraction
breakages which could introduce leaks, so any/all
of ThoseInTheKnow(tm) are invited to assist and/or
abuse.

TODO: Add entry points for other architectures.

C/F/A/E?

Matthew.

diff -ruN linux-2.1.71-clean/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.1.71-clean/arch/i386/kernel/entry.S Tue Dec 2 17:15:11 1997
+++ linux/arch/i386/kernel/entry.S Fri Dec 12 00:38:24 1997
@@ -535,7 +535,8 @@
.long SYMBOL_NAME(sys_rt_sigsuspend)
.long SYMBOL_NAME(sys_pread) /* 180 */
.long SYMBOL_NAME(sys_pwrite)
+ .long SYMBOL_NAME(sys_revoke)

- .rept NR_syscalls-181
+ .rept NR_syscalls-182
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff -ruN linux-2.1.71-clean/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.1.71-clean/drivers/char/tty_io.c Thu Dec 4 21:08:49 1997
+++ linux/drivers/char/tty_io.c Fri Dec 12 01:50:21 1997
@@ -1121,10 +1121,10 @@
redirect = NULL;
}

+ filp->private_data = 0;
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing))
return;
- filp->private_data = 0;

#ifdef TTY_DEBUG_HANGUP
printk("freeing tty structure...");
diff -ruN linux-2.1.71-clean/fs/Makefile linux/fs/Makefile
--- linux-2.1.71-clean/fs/Makefile Tue Dec 2 22:24:04 1997
+++ linux/fs/Makefile Fri Dec 12 00:38:24 1997
@@ -13,7 +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 \
- inode.o dcache.o attr.o bad_inode.o $(BINFMTS)
+ inode.o dcache.o attr.o bad_inode.o revoke.o $(BINFMTS)

MOD_LIST_NAME := FS_MODULES
ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos \
diff -ruN linux-2.1.71-clean/fs/revoke.c linux/fs/revoke.c
--- linux-2.1.71-clean/fs/revoke.c Thu Jan 1 01:00:00 1970
+++ linux/fs/revoke.c Fri Dec 12 01:50:45 1997
@@ -0,0 +1,139 @@
+/*
+ * linux/fs/revoke.c
+ *
+ * Copyright (C) 1997 Matthew Kirkwood
+ * Copyright (C) 1997 Chris Evans
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/smp_lock.h>
+#include <linux/fs.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+
+#include <linux/stat.h>
+
+
+static int ret_ebadf(void)
+{
+ return -EBADF;
+}
+
+/* BSD man page mandates read() performs thus. Pity certain BSDs don't
+ * adhere to this.
+ */
+
+static ssize_t ret_no_bytes(struct file* filp, char* buf, size_t len, loff_t* off)
+{
+ return 0;
+}
+
+static int revoked_release(struct inode * inode, struct file * filp)
+{
+ filp->f_op = NULL;
+ return 0;
+}
+
+static struct file_operations revokedf_ops = {
+ ret_ebadf, /* llseek */
+ ret_no_bytes, /* read */
+ ret_ebadf, /* write */
+ ret_ebadf, /* readdir */
+ ret_ebadf, /* poll */
+ ret_ebadf, /* ioctl */
+ ret_ebadf, /* mmap */
+ ret_ebadf, /* open */
+ revoked_release, /* release */
+ ret_ebadf, /* fsync */
+ ret_ebadf, /* fasync */
+ ret_ebadf, /* check_media_change */
+ ret_ebadf, /* revalidate */
+ ret_ebadf, /* lock */
+};
+
+
+static void do_revoke(struct inode * inode, struct file * filp)
+{
+ down(&inode->i_sem);
+
+/* Close the file */
+ if(filp->f_op->release)
+ (*filp->f_op->release)(inode, filp);
+
+/* Right. Did someone mmap() the fd while they held it open?
+ * Better sort this out. Does your OS get it right :-)
+ * Hint: See some of the *BSD. We discovered problems..
+ */
+ vmtruncate(inode, 0);
+
+ up(&inode->i_sem);
+
+/* The file_ops to do what we want... */
+ filp->f_op = &revokedf_ops;
+}
+
+asmlinkage int sys_revoke(char * path)
+{
+int error;
+struct dentry * dentry;
+struct inode * inode;
+kdev_t dev;
+unsigned long inum;
+
+struct file * filp;
+
+ lock_kernel();
+ dentry = namei(path);
+
+ error = PTR_ERR(dentry);
+ if(IS_ERR(dentry))
+ goto out;
+
+ inode = dentry->d_inode;
+
+/* Check if owner or superuser */
+ if( (inode->i_uid != current->uid)
+ && (inode->i_uid != current->euid)
+ && !suser()) {
+ error = -EPERM;
+ goto dput_out;
+ }
+
+/* Why only devices? */
+ if(!(inode->i_mode & (S_IFBLK | S_IFCHR))) {
+ error = -EINVAL;
+ goto dput_out;
+ }
+
+/*
+ * Now, trawl the file table and see if we can revoke anything.
+ *
+ * Should I canonify the name, or is it OK to rely on the dev
+ * and inode values?
+ */
+ dev = inode->i_dev;
+ inum = inode->i_ino;
+
+ filp = inuse_filps;
+ while(filp) {
+ if(!filp->f_dentry)
+ continue;
+
+ inode = filp->f_dentry->d_inode;
+ if((inode->i_dev == dev) && (inode->i_ino == inum)) {
+ do_revoke(inode,filp);
+ }
+
+ filp = filp->f_next;
+ }
+
+dput_out:
+ dput(dentry);
+out:
+ unlock_kernel();
+ return error;
+}