lkml.org 
[lkml]   [1998]   [Mar]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectIdea: flink() and anon_open()
Date
From

I'd like to suggest two new system calls. They are logical extensions
of the existing filesystem features, and they make it possible to do
all sorts of interesting things. I particularly want them because I'm
writing a program that will be used to install system-critical files
(libc), and there are some race conditions that they would eliminate.

First is flink(fd, path). This is exactly like link() except that it
takes a file descriptor instead of an existing pathname. This allows
you to reattach a file that's been deleted but still open, or name a
file whose descriptor was passed to you.

Second is anon_open(dir, flags, mode). This call returns a file
descriptor on an anonymous file, as if you had created a file and
immediately unlinked it. (I'm not enamored of the function name.) The
first argument is a hint as to where the file "belongs", so that it
can allocate space in the right filesystem. For temporary files that
would be /tmp or /var/tmp. The most obvious use is to avoid the races
surrounding temporary file creation, which have been discussed at some
length on the bugtraq list recently. In combination with flink(), it
can be used to replace a file atomically, without having any time
window where the new version isn't what you want it to be, or where a
temporary name exists and might be grabbed by a malefactor.

I append an implementation for flink which Works For Me (tm). I
couldn't figure out how to do anon_open; is it even possible to do
i_op->create without a name?

zw

--- ./fs/namei.c.2.1.89 Sat Mar 7 17:37:34 1998
+++ ./fs/namei.c Sat Mar 7 23:10:23 1998
@@ -1010,17 +1010,12 @@
return error;
}

-static inline int do_link(const char * oldname, const char * newname)
+static int do_link(struct dentry *old_dentry, const char * newname)
{
- struct dentry *old_dentry, *new_dentry, *dir;
+ struct dentry *new_dentry, *dir;
struct inode *inode;
int error;

- old_dentry = lookup_dentry(oldname, NULL, 1);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit;
-
/*
* Hardlinks are often used in delicate situations. We avoid
* security-related surprises by not following symlinks on the
@@ -1033,7 +1028,7 @@
new_dentry = lookup_dentry(newname, NULL, 0);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
- goto exit_old;
+ goto exit;

dir = lock_parent(new_dentry);
error = PTR_ERR(dir);
@@ -1080,8 +1075,6 @@
unlock_dir(dir);
exit_new:
dput(new_dentry);
-exit_old:
- dput(old_dentry);
exit:
return error;
}
@@ -1097,15 +1090,49 @@
if (!IS_ERR(from)) {
char * to;
to = getname(newname);
+
error = PTR_ERR(to);
if (!IS_ERR(to)) {
- error = do_link(from,to);
+ struct dentry * from_dentry;
+ from_dentry = lookup_dentry(from, NULL, 1);
+
+ error = PTR_ERR(from_dentry);
+ if (!IS_ERR(from_dentry)) {
+ error = do_link(from_dentry, to);
+ dput(from_dentry);
+ }
+
putname(to);
}
putname(from);
}
unlock_kernel();
return error;
+}
+
+asmlinkage int sys_flink(unsigned int from_fd, const char *toname)
+{
+ struct file * file;
+ struct dentry * dentry;
+ char * to;
+ int err = -EBADF;
+
+ lock_kernel();
+ if (from_fd >= NR_OPEN || !(file = current->files->fd[from_fd]))
+ goto out;
+ err = -ENOENT;
+ if (!(dentry = file->f_dentry))
+ goto out;
+
+ to = getname(toname);
+ err = PTR_ERR(to);
+ if (!IS_ERR(to))
+ err = do_link(dentry, to);
+
+ putname(to);
+out:
+ unlock_kernel();
+ return err;
}

/*
--- ./include/asm-i386/unistd.h.2.1.89 Sat Mar 7 17:54:22 1998
+++ ./include/asm-i386/unistd.h Sat Mar 7 17:54:49 1998
@@ -188,6 +188,7 @@
#define __NR_pread 180
#define __NR_pwrite 181
#define __NR_chown 182
+#define __NR_flink 183

/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */

--- ./arch/i386/kernel/entry.S.2.1.89 Sat Mar 7 17:56:13 1998
+++ ./arch/i386/kernel/entry.S Sat Mar 7 17:56:41 1998
@@ -533,7 +533,8 @@
.long SYMBOL_NAME(sys_pread) /* 180 */
.long SYMBOL_NAME(sys_pwrite)
.long SYMBOL_NAME(sys_chown)
+ .long SYMBOL_NAME(sys_flink)

- .rept NR_syscalls-182
+ .rept NR_syscalls-183
.long SYMBOL_NAME(sys_ni_syscall)
.endr
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu

\
 
 \ /
  Last update: 2005-03-22 13:41    [W:0.348 / U:1.660 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site