1
2
3
4
5
6
7#include <linux/string.h>
8#include <linux/mm.h>
9#include <linux/utime.h>
10#include <linux/file.h>
11#include <linux/smp_lock.h>
12#include <linux/quotaops.h>
13#include <linux/dnotify.h>
14#include <linux/module.h>
15#include <linux/slab.h>
16#include <linux/tty.h>
17#include <linux/iobuf.h>
18#include <linux/namei.h>
19#include <linux/backing-dev.h>
20#include <linux/security.h>
21
22#include <asm/uaccess.h>
23
24#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
25
26int vfs_statfs(struct super_block *sb, struct statfs *buf)
27{
28 int retval = -ENODEV;
29
30 if (sb) {
31 retval = -ENOSYS;
32 if (sb->s_op && sb->s_op->statfs) {
33 memset(buf, 0, sizeof(struct statfs));
34 retval = security_ops->sb_statfs(sb);
35 if (retval)
36 return retval;
37 retval = sb->s_op->statfs(sb, buf);
38 }
39 }
40 return retval;
41}
42
43
44asmlinkage long sys_statfs(const char * path, struct statfs * buf)
45{
46 struct nameidata nd;
47 int error;
48
49 error = user_path_walk(path, &nd);
50 if (!error) {
51 struct statfs tmp;
52 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
53 if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
54 error = -EFAULT;
55 path_release(&nd);
56 }
57 return error;
58}
59
60asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf)
61{
62 struct file * file;
63 struct statfs tmp;
64 int error;
65
66 error = -EBADF;
67 file = fget(fd);
68 if (!file)
69 goto out;
70 error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
71 if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
72 error = -EFAULT;
73 fput(file);
74out:
75 return error;
76}
77
78int do_truncate(struct dentry *dentry, loff_t length)
79{
80 int err;
81 struct iattr newattrs;
82
83
84 if (length < 0)
85 return -EINVAL;
86
87 newattrs.ia_size = length;
88 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
89 down(&dentry->d_inode->i_sem);
90 err = notify_change(dentry, &newattrs);
91 up(&dentry->d_inode->i_sem);
92 return err;
93}
94
95static inline long do_sys_truncate(const char * path, loff_t length)
96{
97 struct nameidata nd;
98 struct inode * inode;
99 int error;
100
101 error = -EINVAL;
102 if (length < 0)
103 goto out;
104
105 error = user_path_walk(path, &nd);
106 if (error)
107 goto out;
108 inode = nd.dentry->d_inode;
109
110
111 error = -EISDIR;
112 if (S_ISDIR(inode->i_mode))
113 goto dput_and_out;
114
115 error = -EINVAL;
116 if (!S_ISREG(inode->i_mode))
117 goto dput_and_out;
118
119 error = permission(inode,MAY_WRITE);
120 if (error)
121 goto dput_and_out;
122
123 error = -EROFS;
124 if (IS_RDONLY(inode))
125 goto dput_and_out;
126
127 error = -EPERM;
128 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
129 goto dput_and_out;
130
131
132
133
134 error = get_lease(inode, FMODE_WRITE);
135 if (error)
136 goto dput_and_out;
137
138 error = get_write_access(inode);
139 if (error)
140 goto dput_and_out;
141
142 error = locks_verify_truncate(inode, NULL, length);
143 if (!error) {
144 DQUOT_INIT(inode);
145 error = do_truncate(nd.dentry, length);
146 }
147 put_write_access(inode);
148
149dput_and_out:
150 path_release(&nd);
151out:
152 return error;
153}
154
155asmlinkage long sys_truncate(const char * path, unsigned long length)
156{
157
158 return do_sys_truncate(path, (long)length);
159}
160
161static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
162{
163 struct inode * inode;
164 struct dentry *dentry;
165 struct file * file;
166 int error;
167
168 error = -EINVAL;
169 if (length < 0)
170 goto out;
171 error = -EBADF;
172 file = fget(fd);
173 if (!file)
174 goto out;
175
176
177 if (file->f_flags & O_LARGEFILE)
178 small = 0;
179
180 dentry = file->f_dentry;
181 inode = dentry->d_inode;
182 error = -EINVAL;
183 if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
184 goto out_putf;
185
186 error = -EINVAL;
187
188 if (small && length > MAX_NON_LFS)
189 goto out_putf;
190
191 error = -EPERM;
192 if (IS_APPEND(inode))
193 goto out_putf;
194
195 error = locks_verify_truncate(inode, file, length);
196 if (!error)
197 error = do_truncate(dentry, length);
198out_putf:
199 fput(file);
200out:
201 return error;
202}
203
204asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
205{
206 return do_sys_ftruncate(fd, length, 1);
207}
208
209
210#if BITS_PER_LONG == 32
211asmlinkage long sys_truncate64(const char * path, loff_t length)
212{
213 return do_sys_truncate(path, length);
214}
215
216asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
217{
218 return do_sys_ftruncate(fd, length, 0);
219}
220#endif
221
222#if !(defined(__alpha__) || defined(__ia64__))
223
224
225
226
227
228
229
230
231
232
233
234
235asmlinkage long sys_utime(char * filename, struct utimbuf * times)
236{
237 int error;
238 struct nameidata nd;
239 struct inode * inode;
240 struct iattr newattrs;
241
242 error = user_path_walk(filename, &nd);
243 if (error)
244 goto out;
245 inode = nd.dentry->d_inode;
246
247 error = -EROFS;
248 if (IS_RDONLY(inode))
249 goto dput_and_out;
250
251
252 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
253 if (times) {
254 error = get_user(newattrs.ia_atime, ×->actime);
255 if (!error)
256 error = get_user(newattrs.ia_mtime, ×->modtime);
257 if (error)
258 goto dput_and_out;
259
260 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
261 } else {
262 if (current->fsuid != inode->i_uid &&
263 (error = permission(inode,MAY_WRITE)) != 0)
264 goto dput_and_out;
265 }
266 down(&inode->i_sem);
267 error = notify_change(nd.dentry, &newattrs);
268 up(&inode->i_sem);
269dput_and_out:
270 path_release(&nd);
271out:
272 return error;
273}
274
275#endif
276
277
278
279
280
281asmlinkage long sys_utimes(char * filename, struct timeval * utimes)
282{
283 int error;
284 struct nameidata nd;
285 struct inode * inode;
286 struct iattr newattrs;
287
288 error = user_path_walk(filename, &nd);
289
290 if (error)
291 goto out;
292 inode = nd.dentry->d_inode;
293
294 error = -EROFS;
295 if (IS_RDONLY(inode))
296 goto dput_and_out;
297
298
299 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
300 if (utimes) {
301 struct timeval times[2];
302 error = -EFAULT;
303 if (copy_from_user(×, utimes, sizeof(times)))
304 goto dput_and_out;
305 newattrs.ia_atime = times[0].tv_sec;
306 newattrs.ia_mtime = times[1].tv_sec;
307 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
308 } else {
309 if (current->fsuid != inode->i_uid &&
310 (error = permission(inode,MAY_WRITE)) != 0)
311 goto dput_and_out;
312 }
313 down(&inode->i_sem);
314 error = notify_change(nd.dentry, &newattrs);
315 up(&inode->i_sem);
316dput_and_out:
317 path_release(&nd);
318out:
319 return error;
320}
321
322
323
324
325
326
327asmlinkage long sys_access(const char * filename, int mode)
328{
329 struct nameidata nd;
330 int old_fsuid, old_fsgid;
331 kernel_cap_t old_cap;
332 int res;
333
334 if (mode & ~S_IRWXO)
335 return -EINVAL;
336
337 old_fsuid = current->fsuid;
338 old_fsgid = current->fsgid;
339 old_cap = current->cap_effective;
340
341 current->fsuid = current->uid;
342 current->fsgid = current->gid;
343
344
345
346
347
348
349
350
351
352 if (current->uid)
353 cap_clear(current->cap_effective);
354 else
355 current->cap_effective = current->cap_permitted;
356
357 res = user_path_walk(filename, &nd);
358 if (!res) {
359 res = permission(nd.dentry->d_inode, mode);
360
361 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
362 && !special_file(nd.dentry->d_inode->i_mode))
363 res = -EROFS;
364 path_release(&nd);
365 }
366
367 current->fsuid = old_fsuid;
368 current->fsgid = old_fsgid;
369 current->cap_effective = old_cap;
370
371 return res;
372}
373
374asmlinkage long sys_chdir(const char * filename)
375{
376 struct nameidata nd;
377 int error;
378
379 error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
380 if (error)
381 goto out;
382
383 error = permission(nd.dentry->d_inode,MAY_EXEC);
384 if (error)
385 goto dput_and_out;
386
387 set_fs_pwd(current->fs, nd.mnt, nd.dentry);
388
389dput_and_out:
390 path_release(&nd);
391out:
392 return error;
393}
394
395asmlinkage long sys_fchdir(unsigned int fd)
396{
397 struct file *file;
398 struct dentry *dentry;
399 struct inode *inode;
400 struct vfsmount *mnt;
401 int error;
402
403 error = -EBADF;
404 file = fget(fd);
405 if (!file)
406 goto out;
407
408 dentry = file->f_dentry;
409 mnt = file->f_vfsmnt;
410 inode = dentry->d_inode;
411
412 error = -ENOTDIR;
413 if (!S_ISDIR(inode->i_mode))
414 goto out_putf;
415
416 error = permission(inode, MAY_EXEC);
417 if (!error)
418 set_fs_pwd(current->fs, mnt, dentry);
419out_putf:
420 fput(file);
421out:
422 return error;
423}
424
425asmlinkage long sys_chroot(const char * filename)
426{
427 struct nameidata nd;
428 int error;
429
430 error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
431 if (error)
432 goto out;
433
434 error = permission(nd.dentry->d_inode,MAY_EXEC);
435 if (error)
436 goto dput_and_out;
437
438 error = -EPERM;
439 if (!capable(CAP_SYS_CHROOT))
440 goto dput_and_out;
441
442 set_fs_root(current->fs, nd.mnt, nd.dentry);
443 set_fs_altroot();
444 error = 0;
445dput_and_out:
446 path_release(&nd);
447out:
448 return error;
449}
450
451asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
452{
453 struct inode * inode;
454 struct dentry * dentry;
455 struct file * file;
456 int err = -EBADF;
457 struct iattr newattrs;
458
459 file = fget(fd);
460 if (!file)
461 goto out;
462
463 dentry = file->f_dentry;
464 inode = dentry->d_inode;
465
466 err = -EROFS;
467 if (IS_RDONLY(inode))
468 goto out_putf;
469 err = -EPERM;
470 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
471 goto out_putf;
472 down(&inode->i_sem);
473 if (mode == (mode_t) -1)
474 mode = inode->i_mode;
475 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
476 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
477 err = notify_change(dentry, &newattrs);
478 up(&inode->i_sem);
479
480out_putf:
481 fput(file);
482out:
483 return err;
484}
485
486asmlinkage long sys_chmod(const char * filename, mode_t mode)
487{
488 struct nameidata nd;
489 struct inode * inode;
490 int error;
491 struct iattr newattrs;
492
493 error = user_path_walk(filename, &nd);
494 if (error)
495 goto out;
496 inode = nd.dentry->d_inode;
497
498 error = -EROFS;
499 if (IS_RDONLY(inode))
500 goto dput_and_out;
501
502 error = -EPERM;
503 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
504 goto dput_and_out;
505
506 down(&inode->i_sem);
507 if (mode == (mode_t) -1)
508 mode = inode->i_mode;
509 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
510 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
511 error = notify_change(nd.dentry, &newattrs);
512 up(&inode->i_sem);
513
514dput_and_out:
515 path_release(&nd);
516out:
517 return error;
518}
519
520static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
521{
522 struct inode * inode;
523 int error;
524 struct iattr newattrs;
525
526 error = -ENOENT;
527 if (!(inode = dentry->d_inode)) {
528 printk(KERN_ERR "chown_common: NULL inode\n");
529 goto out;
530 }
531 error = -EROFS;
532 if (IS_RDONLY(inode))
533 goto out;
534 error = -EPERM;
535 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
536 goto out;
537 newattrs.ia_valid = ATTR_CTIME;
538 if (user != (uid_t) -1) {
539 newattrs.ia_valid |= ATTR_UID;
540 newattrs.ia_uid = user;
541 }
542 if (group != (gid_t) -1) {
543 newattrs.ia_valid |= ATTR_GID;
544 newattrs.ia_gid = group;
545 }
546 if (!S_ISDIR(inode->i_mode))
547 newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
548 down(&inode->i_sem);
549 error = notify_change(dentry, &newattrs);
550 up(&inode->i_sem);
551out:
552 return error;
553}
554
555asmlinkage long sys_chown(const char * filename, uid_t user, gid_t group)
556{
557 struct nameidata nd;
558 int error;
559
560 error = user_path_walk(filename, &nd);
561 if (!error) {
562 error = chown_common(nd.dentry, user, group);
563 path_release(&nd);
564 }
565 return error;
566}
567
568asmlinkage long sys_lchown(const char * filename, uid_t user, gid_t group)
569{
570 struct nameidata nd;
571 int error;
572
573 error = user_path_walk_link(filename, &nd);
574 if (!error) {
575 error = chown_common(nd.dentry, user, group);
576 path_release(&nd);
577 }
578 return error;
579}
580
581
582asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
583{
584 struct file * file;
585 int error = -EBADF;
586
587 file = fget(fd);
588 if (file) {
589 error = chown_common(file->f_dentry, user, group);
590 fput(file);
591 }
592 return error;
593}
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609struct file *filp_open(const char * filename, int flags, int mode)
610{
611 int namei_flags, error;
612 struct nameidata nd;
613
614 namei_flags = flags;
615 if ((namei_flags+1) & O_ACCMODE)
616 namei_flags++;
617 if (namei_flags & O_TRUNC)
618 namei_flags |= 2;
619
620 error = open_namei(filename, namei_flags, mode, &nd);
621 if (!error)
622 return dentry_open(nd.dentry, nd.mnt, flags);
623
624 return ERR_PTR(error);
625}
626
627struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
628{
629 struct file * f;
630 struct inode *inode;
631 static LIST_HEAD(kill_list);
632 int error;
633
634 error = -ENFILE;
635 f = get_empty_filp();
636 if (!f)
637 goto cleanup_dentry;
638 f->f_flags = flags;
639 f->f_mode = (flags+1) & O_ACCMODE;
640 inode = dentry->d_inode;
641 if (f->f_mode & FMODE_WRITE) {
642 error = get_write_access(inode);
643 if (error)
644 goto cleanup_file;
645 }
646
647 f->f_ra.ra_pages = inode->i_mapping->backing_dev_info->ra_pages;
648 f->f_dentry = dentry;
649 f->f_vfsmnt = mnt;
650 f->f_pos = 0;
651 f->f_op = fops_get(inode->i_fop);
652 file_move(f, &inode->i_sb->s_files);
653
654 if (f->f_op && f->f_op->open) {
655 error = f->f_op->open(inode,f);
656 if (error)
657 goto cleanup_all;
658 }
659 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
660
661
662 if (f->f_flags & O_DIRECT) {
663 if (!inode->i_mapping || !inode->i_mapping->a_ops ||
664 !inode->i_mapping->a_ops->direct_IO) {
665 error = -EINVAL;
666 goto cleanup_all;
667 }
668 }
669
670 return f;
671
672cleanup_all:
673 fops_put(f->f_op);
674 if (f->f_mode & FMODE_WRITE)
675 put_write_access(inode);
676 file_move(f, &kill_list);
677 f->f_dentry = NULL;
678 f->f_vfsmnt = NULL;
679cleanup_file:
680 put_filp(f);
681cleanup_dentry:
682 dput(dentry);
683 mntput(mnt);
684 return ERR_PTR(error);
685}
686
687
688
689
690int get_unused_fd(void)
691{
692 struct files_struct * files = current->files;
693 int fd, error;
694
695 error = -EMFILE;
696 write_lock(&files->file_lock);
697
698repeat:
699 fd = find_next_zero_bit(files->open_fds->fds_bits,
700 files->max_fdset,
701 files->next_fd);
702
703
704
705
706
707 if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
708 goto out;
709
710
711 if (fd >= files->max_fdset) {
712 error = expand_fdset(files, fd);
713 if (!error) {
714 error = -EMFILE;
715 goto repeat;
716 }
717 goto out;
718 }
719
720
721
722
723 if (fd >= files->max_fds) {
724 error = expand_fd_array(files, fd);
725 if (!error) {
726 error = -EMFILE;
727 goto repeat;
728 }
729 goto out;
730 }
731
732 FD_SET(fd, files->open_fds);
733 FD_CLR(fd, files->close_on_exec);
734 files->next_fd = fd + 1;
735#if 1
736
737 if (files->fd[fd] != NULL) {
738 printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
739 files->fd[fd] = NULL;
740 }
741#endif
742 error = fd;
743
744out:
745 write_unlock(&files->file_lock);
746 return error;
747}
748
749static inline void __put_unused_fd(struct files_struct *files, unsigned int fd)
750{
751 __FD_CLR(fd, files->open_fds);
752 if (fd < files->next_fd)
753 files->next_fd = fd;
754}
755
756void put_unused_fd(unsigned int fd)
757{
758 struct files_struct *files = current->files;
759 write_lock(&files->file_lock);
760 __put_unused_fd(files, fd);
761 write_unlock(&files->file_lock);
762}
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777void fd_install(unsigned int fd, struct file * file)
778{
779 struct files_struct *files = current->files;
780 write_lock(&files->file_lock);
781 if (unlikely(files->fd[fd] != NULL))
782 BUG();
783 files->fd[fd] = file;
784 write_unlock(&files->file_lock);
785}
786
787asmlinkage long sys_open(const char * filename, int flags, int mode)
788{
789 char * tmp;
790 int fd, error;
791
792#if BITS_PER_LONG != 32
793 flags |= O_LARGEFILE;
794#endif
795 tmp = getname(filename);
796 fd = PTR_ERR(tmp);
797 if (!IS_ERR(tmp)) {
798 fd = get_unused_fd();
799 if (fd >= 0) {
800 struct file *f = filp_open(tmp, flags, mode);
801 error = PTR_ERR(f);
802 if (IS_ERR(f))
803 goto out_error;
804 fd_install(fd, f);
805 }
806out:
807 putname(tmp);
808 }
809 return fd;
810
811out_error:
812 put_unused_fd(fd);
813 fd = error;
814 goto out;
815}
816
817#ifndef __alpha__
818
819
820
821
822
823asmlinkage long sys_creat(const char * pathname, int mode)
824{
825 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
826}
827
828#endif
829
830
831
832
833
834int filp_close(struct file *filp, fl_owner_t id)
835{
836 int retval;
837
838 if (!file_count(filp)) {
839 printk(KERN_ERR "VFS: Close: file count is 0\n");
840 return 0;
841 }
842 retval = 0;
843 if (filp->f_op && filp->f_op->flush) {
844 lock_kernel();
845 retval = filp->f_op->flush(filp);
846 unlock_kernel();
847 }
848 dnotify_flush(filp, id);
849 locks_remove_posix(filp, id);
850 fput(filp);
851 return retval;
852}
853
854
855
856
857
858
859asmlinkage long sys_close(unsigned int fd)
860{
861 struct file * filp;
862 struct files_struct *files = current->files;
863
864 write_lock(&files->file_lock);
865 if (fd >= files->max_fds)
866 goto out_unlock;
867 filp = files->fd[fd];
868 if (!filp)
869 goto out_unlock;
870 files->fd[fd] = NULL;
871 FD_CLR(fd, files->close_on_exec);
872 __put_unused_fd(files, fd);
873 write_unlock(&files->file_lock);
874 return filp_close(filp, files);
875
876out_unlock:
877 write_unlock(&files->file_lock);
878 return -EBADF;
879}
880
881
882
883
884
885asmlinkage long sys_vhangup(void)
886{
887 if (capable(CAP_SYS_TTY_CONFIG)) {
888 tty_vhangup(current->tty);
889 return 0;
890 }
891 return -EPERM;
892}
893
894
895
896
897
898
899
900int generic_file_open(struct inode * inode, struct file * filp)
901{
902 if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS)
903 return -EFBIG;
904 return 0;
905}
906
907EXPORT_SYMBOL(generic_file_open);
908