aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c166
1 files changed, 20 insertions, 146 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 887b5ba8c9b5..8f704291d4ed 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -26,124 +26,6 @@
26#include <asm/siginfo.h> 26#include <asm/siginfo.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28 28
29void set_close_on_exec(unsigned int fd, int flag)
30{
31 struct files_struct *files = current->files;
32 struct fdtable *fdt;
33 spin_lock(&files->file_lock);
34 fdt = files_fdtable(files);
35 if (flag)
36 __set_close_on_exec(fd, fdt);
37 else
38 __clear_close_on_exec(fd, fdt);
39 spin_unlock(&files->file_lock);
40}
41
42static bool get_close_on_exec(unsigned int fd)
43{
44 struct files_struct *files = current->files;
45 struct fdtable *fdt;
46 bool res;
47 rcu_read_lock();
48 fdt = files_fdtable(files);
49 res = close_on_exec(fd, fdt);
50 rcu_read_unlock();
51 return res;
52}
53
54SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
55{
56 int err = -EBADF;
57 struct file * file, *tofree;
58 struct files_struct * files = current->files;
59 struct fdtable *fdt;
60
61 if ((flags & ~O_CLOEXEC) != 0)
62 return -EINVAL;
63
64 if (unlikely(oldfd == newfd))
65 return -EINVAL;
66
67 spin_lock(&files->file_lock);
68 err = expand_files(files, newfd);
69 file = fcheck(oldfd);
70 if (unlikely(!file))
71 goto Ebadf;
72 if (unlikely(err < 0)) {
73 if (err == -EMFILE)
74 goto Ebadf;
75 goto out_unlock;
76 }
77 /*
78 * We need to detect attempts to do dup2() over allocated but still
79 * not finished descriptor. NB: OpenBSD avoids that at the price of
80 * extra work in their equivalent of fget() - they insert struct
81 * file immediately after grabbing descriptor, mark it larval if
82 * more work (e.g. actual opening) is needed and make sure that
83 * fget() treats larval files as absent. Potentially interesting,
84 * but while extra work in fget() is trivial, locking implications
85 * and amount of surgery on open()-related paths in VFS are not.
86 * FreeBSD fails with -EBADF in the same situation, NetBSD "solution"
87 * deadlocks in rather amusing ways, AFAICS. All of that is out of
88 * scope of POSIX or SUS, since neither considers shared descriptor
89 * tables and this condition does not arise without those.
90 */
91 err = -EBUSY;
92 fdt = files_fdtable(files);
93 tofree = fdt->fd[newfd];
94 if (!tofree && fd_is_open(newfd, fdt))
95 goto out_unlock;
96 get_file(file);
97 rcu_assign_pointer(fdt->fd[newfd], file);
98 __set_open_fd(newfd, fdt);
99 if (flags & O_CLOEXEC)
100 __set_close_on_exec(newfd, fdt);
101 else
102 __clear_close_on_exec(newfd, fdt);
103 spin_unlock(&files->file_lock);
104
105 if (tofree)
106 filp_close(tofree, files);
107
108 return newfd;
109
110Ebadf:
111 err = -EBADF;
112out_unlock:
113 spin_unlock(&files->file_lock);
114 return err;
115}
116
117SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
118{
119 if (unlikely(newfd == oldfd)) { /* corner case */
120 struct files_struct *files = current->files;
121 int retval = oldfd;
122
123 rcu_read_lock();
124 if (!fcheck_files(files, oldfd))
125 retval = -EBADF;
126 rcu_read_unlock();
127 return retval;
128 }
129 return sys_dup3(oldfd, newfd, 0);
130}
131
132SYSCALL_DEFINE1(dup, unsigned int, fildes)
133{
134 int ret = -EBADF;
135 struct file *file = fget_raw(fildes);
136
137 if (file) {
138 ret = get_unused_fd();
139 if (ret >= 0)
140 fd_install(ret, file);
141 else
142 fput(file);
143 }
144 return ret;
145}
146
147#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) 29#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
148 30
149static int setfl(int fd, struct file * filp, unsigned long arg) 31static int setfl(int fd, struct file * filp, unsigned long arg)
@@ -267,7 +149,7 @@ pid_t f_getown(struct file *filp)
267 149
268static int f_setown_ex(struct file *filp, unsigned long arg) 150static int f_setown_ex(struct file *filp, unsigned long arg)
269{ 151{
270 struct f_owner_ex * __user owner_p = (void * __user)arg; 152 struct f_owner_ex __user *owner_p = (void __user *)arg;
271 struct f_owner_ex owner; 153 struct f_owner_ex owner;
272 struct pid *pid; 154 struct pid *pid;
273 int type; 155 int type;
@@ -307,7 +189,7 @@ static int f_setown_ex(struct file *filp, unsigned long arg)
307 189
308static int f_getown_ex(struct file *filp, unsigned long arg) 190static int f_getown_ex(struct file *filp, unsigned long arg)
309{ 191{
310 struct f_owner_ex * __user owner_p = (void * __user)arg; 192 struct f_owner_ex __user *owner_p = (void __user *)arg;
311 struct f_owner_ex owner; 193 struct f_owner_ex owner;
312 int ret = 0; 194 int ret = 0;
313 195
@@ -345,7 +227,7 @@ static int f_getown_ex(struct file *filp, unsigned long arg)
345static int f_getowner_uids(struct file *filp, unsigned long arg) 227static int f_getowner_uids(struct file *filp, unsigned long arg)
346{ 228{
347 struct user_namespace *user_ns = current_user_ns(); 229 struct user_namespace *user_ns = current_user_ns();
348 uid_t * __user dst = (void * __user)arg; 230 uid_t __user *dst = (void __user *)arg;
349 uid_t src[2]; 231 uid_t src[2];
350 int err; 232 int err;
351 233
@@ -373,14 +255,10 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
373 255
374 switch (cmd) { 256 switch (cmd) {
375 case F_DUPFD: 257 case F_DUPFD:
258 err = f_dupfd(arg, filp, 0);
259 break;
376 case F_DUPFD_CLOEXEC: 260 case F_DUPFD_CLOEXEC:
377 if (arg >= rlimit(RLIMIT_NOFILE)) 261 err = f_dupfd(arg, filp, FD_CLOEXEC);
378 break;
379 err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0);
380 if (err >= 0) {
381 get_file(filp);
382 fd_install(err, filp);
383 }
384 break; 262 break;
385 case F_GETFD: 263 case F_GETFD:
386 err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; 264 err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;
@@ -470,25 +348,23 @@ static int check_fcntl_cmd(unsigned cmd)
470 348
471SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) 349SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
472{ 350{
473 struct file *filp; 351 struct fd f = fdget_raw(fd);
474 int fput_needed;
475 long err = -EBADF; 352 long err = -EBADF;
476 353
477 filp = fget_raw_light(fd, &fput_needed); 354 if (!f.file)
478 if (!filp)
479 goto out; 355 goto out;
480 356
481 if (unlikely(filp->f_mode & FMODE_PATH)) { 357 if (unlikely(f.file->f_mode & FMODE_PATH)) {
482 if (!check_fcntl_cmd(cmd)) 358 if (!check_fcntl_cmd(cmd))
483 goto out1; 359 goto out1;
484 } 360 }
485 361
486 err = security_file_fcntl(filp, cmd, arg); 362 err = security_file_fcntl(f.file, cmd, arg);
487 if (!err) 363 if (!err)
488 err = do_fcntl(fd, cmd, arg, filp); 364 err = do_fcntl(fd, cmd, arg, f.file);
489 365
490out1: 366out1:
491 fput_light(filp, fput_needed); 367 fdput(f);
492out: 368out:
493 return err; 369 return err;
494} 370}
@@ -497,38 +373,36 @@ out:
497SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, 373SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
498 unsigned long, arg) 374 unsigned long, arg)
499{ 375{
500 struct file * filp; 376 struct fd f = fdget_raw(fd);
501 long err = -EBADF; 377 long err = -EBADF;
502 int fput_needed;
503 378
504 filp = fget_raw_light(fd, &fput_needed); 379 if (!f.file)
505 if (!filp)
506 goto out; 380 goto out;
507 381
508 if (unlikely(filp->f_mode & FMODE_PATH)) { 382 if (unlikely(f.file->f_mode & FMODE_PATH)) {
509 if (!check_fcntl_cmd(cmd)) 383 if (!check_fcntl_cmd(cmd))
510 goto out1; 384 goto out1;
511 } 385 }
512 386
513 err = security_file_fcntl(filp, cmd, arg); 387 err = security_file_fcntl(f.file, cmd, arg);
514 if (err) 388 if (err)
515 goto out1; 389 goto out1;
516 390
517 switch (cmd) { 391 switch (cmd) {
518 case F_GETLK64: 392 case F_GETLK64:
519 err = fcntl_getlk64(filp, (struct flock64 __user *) arg); 393 err = fcntl_getlk64(f.file, (struct flock64 __user *) arg);
520 break; 394 break;
521 case F_SETLK64: 395 case F_SETLK64:
522 case F_SETLKW64: 396 case F_SETLKW64:
523 err = fcntl_setlk64(fd, filp, cmd, 397 err = fcntl_setlk64(fd, f.file, cmd,
524 (struct flock64 __user *) arg); 398 (struct flock64 __user *) arg);
525 break; 399 break;
526 default: 400 default:
527 err = do_fcntl(fd, cmd, arg, filp); 401 err = do_fcntl(fd, cmd, arg, f.file);
528 break; 402 break;
529 } 403 }
530out1: 404out1:
531 fput_light(filp, fput_needed); 405 fdput(f);
532out: 406out:
533 return err; 407 return err;
534} 408}