aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c130
1 files changed, 30 insertions, 100 deletions
diff --git a/fs/open.c b/fs/open.c
index b0bae3a41825..44da0feeca2c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -132,27 +132,27 @@ SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
132 132
133static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) 133static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
134{ 134{
135 struct inode * inode; 135 struct inode *inode;
136 struct dentry *dentry; 136 struct dentry *dentry;
137 struct file * file; 137 struct fd f;
138 int error; 138 int error;
139 139
140 error = -EINVAL; 140 error = -EINVAL;
141 if (length < 0) 141 if (length < 0)
142 goto out; 142 goto out;
143 error = -EBADF; 143 error = -EBADF;
144 file = fget(fd); 144 f = fdget(fd);
145 if (!file) 145 if (!f.file)
146 goto out; 146 goto out;
147 147
148 /* explicitly opened as large or we are on 64-bit box */ 148 /* explicitly opened as large or we are on 64-bit box */
149 if (file->f_flags & O_LARGEFILE) 149 if (f.file->f_flags & O_LARGEFILE)
150 small = 0; 150 small = 0;
151 151
152 dentry = file->f_path.dentry; 152 dentry = f.file->f_path.dentry;
153 inode = dentry->d_inode; 153 inode = dentry->d_inode;
154 error = -EINVAL; 154 error = -EINVAL;
155 if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) 155 if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
156 goto out_putf; 156 goto out_putf;
157 157
158 error = -EINVAL; 158 error = -EINVAL;
@@ -165,14 +165,14 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
165 goto out_putf; 165 goto out_putf;
166 166
167 sb_start_write(inode->i_sb); 167 sb_start_write(inode->i_sb);
168 error = locks_verify_truncate(inode, file, length); 168 error = locks_verify_truncate(inode, f.file, length);
169 if (!error) 169 if (!error)
170 error = security_path_truncate(&file->f_path); 170 error = security_path_truncate(&f.file->f_path);
171 if (!error) 171 if (!error)
172 error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); 172 error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
173 sb_end_write(inode->i_sb); 173 sb_end_write(inode->i_sb);
174out_putf: 174out_putf:
175 fput(file); 175 fdput(f);
176out: 176out:
177 return error; 177 return error;
178} 178}
@@ -276,15 +276,13 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
276 276
277SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len) 277SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len)
278{ 278{
279 struct file *file; 279 struct fd f = fdget(fd);
280 int error = -EBADF; 280 int error = -EBADF;
281 281
282 file = fget(fd); 282 if (f.file) {
283 if (file) { 283 error = do_fallocate(f.file, mode, offset, len);
284 error = do_fallocate(file, mode, offset, len); 284 fdput(f);
285 fput(file);
286 } 285 }
287
288 return error; 286 return error;
289} 287}
290 288
@@ -400,16 +398,15 @@ out:
400 398
401SYSCALL_DEFINE1(fchdir, unsigned int, fd) 399SYSCALL_DEFINE1(fchdir, unsigned int, fd)
402{ 400{
403 struct file *file; 401 struct fd f = fdget_raw(fd);
404 struct inode *inode; 402 struct inode *inode;
405 int error, fput_needed; 403 int error = -EBADF;
406 404
407 error = -EBADF; 405 error = -EBADF;
408 file = fget_raw_light(fd, &fput_needed); 406 if (!f.file)
409 if (!file)
410 goto out; 407 goto out;
411 408
412 inode = file->f_path.dentry->d_inode; 409 inode = f.file->f_path.dentry->d_inode;
413 410
414 error = -ENOTDIR; 411 error = -ENOTDIR;
415 if (!S_ISDIR(inode->i_mode)) 412 if (!S_ISDIR(inode->i_mode))
@@ -417,9 +414,9 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
417 414
418 error = inode_permission(inode, MAY_EXEC | MAY_CHDIR); 415 error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
419 if (!error) 416 if (!error)
420 set_fs_pwd(current->fs, &file->f_path); 417 set_fs_pwd(current->fs, &f.file->f_path);
421out_putf: 418out_putf:
422 fput_light(file, fput_needed); 419 fdput(f);
423out: 420out:
424 return error; 421 return error;
425} 422}
@@ -582,23 +579,20 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group
582 579
583SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) 580SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
584{ 581{
585 struct file * file; 582 struct fd f = fdget(fd);
586 int error = -EBADF; 583 int error = -EBADF;
587 struct dentry * dentry;
588 584
589 file = fget(fd); 585 if (!f.file)
590 if (!file)
591 goto out; 586 goto out;
592 587
593 error = mnt_want_write_file(file); 588 error = mnt_want_write_file(f.file);
594 if (error) 589 if (error)
595 goto out_fput; 590 goto out_fput;
596 dentry = file->f_path.dentry; 591 audit_inode(NULL, f.file->f_path.dentry);
597 audit_inode(NULL, dentry); 592 error = chown_common(&f.file->f_path, user, group);
598 error = chown_common(&file->f_path, user, group); 593 mnt_drop_write_file(f.file);
599 mnt_drop_write_file(file);
600out_fput: 594out_fput:
601 fput(file); 595 fdput(f);
602out: 596out:
603 return error; 597 return error;
604} 598}
@@ -803,50 +797,6 @@ struct file *dentry_open(const struct path *path, int flags,
803} 797}
804EXPORT_SYMBOL(dentry_open); 798EXPORT_SYMBOL(dentry_open);
805 799
806static void __put_unused_fd(struct files_struct *files, unsigned int fd)
807{
808 struct fdtable *fdt = files_fdtable(files);
809 __clear_open_fd(fd, fdt);
810 if (fd < files->next_fd)
811 files->next_fd = fd;
812}
813
814void put_unused_fd(unsigned int fd)
815{
816 struct files_struct *files = current->files;
817 spin_lock(&files->file_lock);
818 __put_unused_fd(files, fd);
819 spin_unlock(&files->file_lock);
820}
821
822EXPORT_SYMBOL(put_unused_fd);
823
824/*
825 * Install a file pointer in the fd array.
826 *
827 * The VFS is full of places where we drop the files lock between
828 * setting the open_fds bitmap and installing the file in the file
829 * array. At any such point, we are vulnerable to a dup2() race
830 * installing a file in the array before us. We need to detect this and
831 * fput() the struct file we are about to overwrite in this case.
832 *
833 * It should never happen - if we allow dup2() do it, _really_ bad things
834 * will follow.
835 */
836
837void fd_install(unsigned int fd, struct file *file)
838{
839 struct files_struct *files = current->files;
840 struct fdtable *fdt;
841 spin_lock(&files->file_lock);
842 fdt = files_fdtable(files);
843 BUG_ON(fdt->fd[fd] != NULL);
844 rcu_assign_pointer(fdt->fd[fd], file);
845 spin_unlock(&files->file_lock);
846}
847
848EXPORT_SYMBOL(fd_install);
849
850static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op) 800static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
851{ 801{
852 int lookup_flags = 0; 802 int lookup_flags = 0;
@@ -858,7 +808,7 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
858 op->mode = 0; 808 op->mode = 0;
859 809
860 /* Must never be set by userspace */ 810 /* Must never be set by userspace */
861 flags &= ~FMODE_NONOTIFY; 811 flags &= ~FMODE_NONOTIFY & ~O_CLOEXEC;
862 812
863 /* 813 /*
864 * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only 814 * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
@@ -1038,23 +988,7 @@ EXPORT_SYMBOL(filp_close);
1038 */ 988 */
1039SYSCALL_DEFINE1(close, unsigned int, fd) 989SYSCALL_DEFINE1(close, unsigned int, fd)
1040{ 990{
1041 struct file * filp; 991 int retval = __close_fd(current->files, fd);
1042 struct files_struct *files = current->files;
1043 struct fdtable *fdt;
1044 int retval;
1045
1046 spin_lock(&files->file_lock);
1047 fdt = files_fdtable(files);
1048 if (fd >= fdt->max_fds)
1049 goto out_unlock;
1050 filp = fdt->fd[fd];
1051 if (!filp)
1052 goto out_unlock;
1053 rcu_assign_pointer(fdt->fd[fd], NULL);
1054 __clear_close_on_exec(fd, fdt);
1055 __put_unused_fd(files, fd);
1056 spin_unlock(&files->file_lock);
1057 retval = filp_close(filp, files);
1058 992
1059 /* can't restart close syscall because file table entry was cleared */ 993 /* can't restart close syscall because file table entry was cleared */
1060 if (unlikely(retval == -ERESTARTSYS || 994 if (unlikely(retval == -ERESTARTSYS ||
@@ -1064,10 +998,6 @@ SYSCALL_DEFINE1(close, unsigned int, fd)
1064 retval = -EINTR; 998 retval = -EINTR;
1065 999
1066 return retval; 1000 return retval;
1067
1068out_unlock:
1069 spin_unlock(&files->file_lock);
1070 return -EBADF;
1071} 1001}
1072EXPORT_SYMBOL(sys_close); 1002EXPORT_SYMBOL(sys_close);
1073 1003