Messages in this thread Patch in this message | | | Subject | Idea: flink() and anon_open() | Date | Sun, 08 Mar 1998 00:40:42 -0500 | From | Zack Weinberg <> |
| |
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
| |