lkml.org 
[lkml]   [1998]   [Jan]   [17]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateSat, 17 Jan 1998 14:05:50 +0000 (GMT)
FromMatthew Kirkwood <>
Subjectrevoke() again.
Hi,

OK people, here's a patch against 2.1.80-pre4.  I'd still like to expand
the call to take a couple of flags, mostly the ability not to revoke file
descriptors held by processes with the same (e?)uid.  Otherwise, if I log
in on tty1 and get granted the floppy and start a dd, then log in on tty2
and the old fd is revoked things can get pretty boring...

Given this, my my biggest challenge is to find a different name.  My
current thoughts make me think that recind() might just be the answer,
unless anyone has any better ideas.

Cheers,
Matthew.

diff -ruN linux-2.1.80-pre4-clean/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.1.80-pre4-clean/arch/i386/kernel/entry.S	Sat Jan 10 19:57:29 1998
+++ linux/arch/i386/kernel/entry.S	Sat Jan 17 13:56:12 1998
@@ -532,7 +532,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.80-pre4-clean/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.1.80-pre4-clean/drivers/char/tty_io.c	Thu Jan  1 00:40:08 1998
+++ linux/drivers/char/tty_io.c	Sat Jan 17 13:56:12 1998
@@ -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.80-pre4-clean/fs/Makefile linux/fs/Makefile
--- linux-2.1.80-pre4-clean/fs/Makefile	Sun Jan  4 18:40:16 1998
+++ linux/fs/Makefile	Sat Jan 17 13:56:12 1998
@@ -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 ntfs \
diff -ruN linux-2.1.80-pre4-clean/fs/revoke.c linux/fs/revoke.c
--- linux-2.1.80-pre4-clean/fs/revoke.c	Thu Jan  1 01:00:00 1970
+++ linux/fs/revoke.c	Sat Jan 17 13:57:27 1998
@@ -0,0 +1,139 @@
+/*
+ *  linux/fs/revoke.c
+ *
+ *  Copyright (C) 1997  Matthew Kirkwood <weejock@ferret.lmh.ox.ac.uk>
+ *  Copyright (C) 1997  Chris Evans <chris@ferret.lmh.ox.ac.uk>
+ *
+ */
+
+#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;
+}

\
 
 \ /
  Last update: 2005-03-22 12:41    [from the cache]
©2003-2008