aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c83
1 files changed, 68 insertions, 15 deletions
diff --git a/fs/open.c b/fs/open.c
index 8e20c1f32563..70e0230d8e77 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -20,6 +20,7 @@
20#include <linux/security.h> 20#include <linux/security.h>
21#include <linux/mount.h> 21#include <linux/mount.h>
22#include <linux/vfs.h> 22#include <linux/vfs.h>
23#include <linux/fcntl.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24#include <linux/fs.h> 25#include <linux/fs.h>
25#include <linux/personality.h> 26#include <linux/personality.h>
@@ -383,7 +384,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
383 384
384 error = get_user(newattrs.ia_atime.tv_sec, &times->actime); 385 error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
385 newattrs.ia_atime.tv_nsec = 0; 386 newattrs.ia_atime.tv_nsec = 0;
386 if (!error) 387 if (!error)
387 error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime); 388 error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime);
388 newattrs.ia_mtime.tv_nsec = 0; 389 newattrs.ia_mtime.tv_nsec = 0;
389 if (error) 390 if (error)
@@ -414,14 +415,14 @@ out:
414 * must be owner or have write permission. 415 * must be owner or have write permission.
415 * Else, update from *times, must be owner or super user. 416 * Else, update from *times, must be owner or super user.
416 */ 417 */
417long do_utimes(char __user * filename, struct timeval * times) 418long do_utimes(int dfd, char __user *filename, struct timeval *times)
418{ 419{
419 int error; 420 int error;
420 struct nameidata nd; 421 struct nameidata nd;
421 struct inode * inode; 422 struct inode * inode;
422 struct iattr newattrs; 423 struct iattr newattrs;
423 424
424 error = user_path_walk(filename, &nd); 425 error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
425 426
426 if (error) 427 if (error)
427 goto out; 428 goto out;
@@ -461,13 +462,18 @@ out:
461 return error; 462 return error;
462} 463}
463 464
464asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utimes) 465asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes)
465{ 466{
466 struct timeval times[2]; 467 struct timeval times[2];
467 468
468 if (utimes && copy_from_user(&times, utimes, sizeof(times))) 469 if (utimes && copy_from_user(&times, utimes, sizeof(times)))
469 return -EFAULT; 470 return -EFAULT;
470 return do_utimes(filename, utimes ? times : NULL); 471 return do_utimes(dfd, filename, utimes ? times : NULL);
472}
473
474asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes)
475{
476 return sys_futimesat(AT_FDCWD, filename, utimes);
471} 477}
472 478
473 479
@@ -476,7 +482,7 @@ asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utime
476 * We do this by temporarily clearing all FS-related capabilities and 482 * We do this by temporarily clearing all FS-related capabilities and
477 * switching the fsuid/fsgid around to the real ones. 483 * switching the fsuid/fsgid around to the real ones.
478 */ 484 */
479asmlinkage long sys_access(const char __user * filename, int mode) 485asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
480{ 486{
481 struct nameidata nd; 487 struct nameidata nd;
482 int old_fsuid, old_fsgid; 488 int old_fsuid, old_fsgid;
@@ -506,7 +512,7 @@ asmlinkage long sys_access(const char __user * filename, int mode)
506 else 512 else
507 current->cap_effective = current->cap_permitted; 513 current->cap_effective = current->cap_permitted;
508 514
509 res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); 515 res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
510 if (!res) { 516 if (!res) {
511 res = vfs_permission(&nd, mode); 517 res = vfs_permission(&nd, mode);
512 /* SuS v2 requires we report a read only fs too */ 518 /* SuS v2 requires we report a read only fs too */
@@ -523,6 +529,11 @@ asmlinkage long sys_access(const char __user * filename, int mode)
523 return res; 529 return res;
524} 530}
525 531
532asmlinkage long sys_access(const char __user *filename, int mode)
533{
534 return sys_faccessat(AT_FDCWD, filename, mode);
535}
536
526asmlinkage long sys_chdir(const char __user * filename) 537asmlinkage long sys_chdir(const char __user * filename)
527{ 538{
528 struct nameidata nd; 539 struct nameidata nd;
@@ -635,14 +646,15 @@ out:
635 return err; 646 return err;
636} 647}
637 648
638asmlinkage long sys_chmod(const char __user * filename, mode_t mode) 649asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
650 mode_t mode)
639{ 651{
640 struct nameidata nd; 652 struct nameidata nd;
641 struct inode * inode; 653 struct inode * inode;
642 int error; 654 int error;
643 struct iattr newattrs; 655 struct iattr newattrs;
644 656
645 error = user_path_walk(filename, &nd); 657 error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
646 if (error) 658 if (error)
647 goto out; 659 goto out;
648 inode = nd.dentry->d_inode; 660 inode = nd.dentry->d_inode;
@@ -669,6 +681,11 @@ out:
669 return error; 681 return error;
670} 682}
671 683
684asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
685{
686 return sys_fchmodat(AT_FDCWD, filename, mode);
687}
688
672static int chown_common(struct dentry * dentry, uid_t user, gid_t group) 689static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
673{ 690{
674 struct inode * inode; 691 struct inode * inode;
@@ -717,6 +734,26 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
717 return error; 734 return error;
718} 735}
719 736
737asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
738 gid_t group, int flag)
739{
740 struct nameidata nd;
741 int error = -EINVAL;
742 int follow;
743
744 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
745 goto out;
746
747 follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
748 error = __user_walk_fd(dfd, filename, follow, &nd);
749 if (!error) {
750 error = chown_common(nd.dentry, user, group);
751 path_release(&nd);
752 }
753out:
754 return error;
755}
756
720asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) 757asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
721{ 758{
722 struct nameidata nd; 759 struct nameidata nd;
@@ -820,7 +857,8 @@ cleanup_file:
820 * for the internal routines (ie open_namei()/follow_link() etc). 00 is 857 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
821 * used by symlinks. 858 * used by symlinks.
822 */ 859 */
823struct file *filp_open(const char * filename, int flags, int mode) 860static struct file *do_filp_open(int dfd, const char *filename, int flags,
861 int mode)
824{ 862{
825 int namei_flags, error; 863 int namei_flags, error;
826 struct nameidata nd; 864 struct nameidata nd;
@@ -829,12 +867,17 @@ struct file *filp_open(const char * filename, int flags, int mode)
829 if ((namei_flags+1) & O_ACCMODE) 867 if ((namei_flags+1) & O_ACCMODE)
830 namei_flags++; 868 namei_flags++;
831 869
832 error = open_namei(filename, namei_flags, mode, &nd); 870 error = open_namei(dfd, filename, namei_flags, mode, &nd);
833 if (!error) 871 if (!error)
834 return nameidata_to_filp(&nd, flags); 872 return nameidata_to_filp(&nd, flags);
835 873
836 return ERR_PTR(error); 874 return ERR_PTR(error);
837} 875}
876
877struct file *filp_open(const char *filename, int flags, int mode)
878{
879 return do_filp_open(AT_FDCWD, filename, flags, mode);
880}
838EXPORT_SYMBOL(filp_open); 881EXPORT_SYMBOL(filp_open);
839 882
840/** 883/**
@@ -991,7 +1034,7 @@ void fastcall put_unused_fd(unsigned int fd)
991EXPORT_SYMBOL(put_unused_fd); 1034EXPORT_SYMBOL(put_unused_fd);
992 1035
993/* 1036/*
994 * Install a file pointer in the fd array. 1037 * Install a file pointer in the fd array.
995 * 1038 *
996 * The VFS is full of places where we drop the files lock between 1039 * The VFS is full of places where we drop the files lock between
997 * setting the open_fds bitmap and installing the file in the file 1040 * setting the open_fds bitmap and installing the file in the file
@@ -1016,7 +1059,7 @@ void fastcall fd_install(unsigned int fd, struct file * file)
1016 1059
1017EXPORT_SYMBOL(fd_install); 1060EXPORT_SYMBOL(fd_install);
1018 1061
1019long do_sys_open(const char __user *filename, int flags, int mode) 1062long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
1020{ 1063{
1021 char *tmp = getname(filename); 1064 char *tmp = getname(filename);
1022 int fd = PTR_ERR(tmp); 1065 int fd = PTR_ERR(tmp);
@@ -1024,7 +1067,7 @@ long do_sys_open(const char __user *filename, int flags, int mode)
1024 if (!IS_ERR(tmp)) { 1067 if (!IS_ERR(tmp)) {
1025 fd = get_unused_fd(); 1068 fd = get_unused_fd();
1026 if (fd >= 0) { 1069 if (fd >= 0) {
1027 struct file *f = filp_open(tmp, flags, mode); 1070 struct file *f = do_filp_open(dfd, tmp, flags, mode);
1028 if (IS_ERR(f)) { 1071 if (IS_ERR(f)) {
1029 put_unused_fd(fd); 1072 put_unused_fd(fd);
1030 fd = PTR_ERR(f); 1073 fd = PTR_ERR(f);
@@ -1043,10 +1086,20 @@ asmlinkage long sys_open(const char __user *filename, int flags, int mode)
1043 if (force_o_largefile()) 1086 if (force_o_largefile())
1044 flags |= O_LARGEFILE; 1087 flags |= O_LARGEFILE;
1045 1088
1046 return do_sys_open(filename, flags, mode); 1089 return do_sys_open(AT_FDCWD, filename, flags, mode);
1047} 1090}
1048EXPORT_SYMBOL_GPL(sys_open); 1091EXPORT_SYMBOL_GPL(sys_open);
1049 1092
1093asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
1094 int mode)
1095{
1096 if (force_o_largefile())
1097 flags |= O_LARGEFILE;
1098
1099 return do_sys_open(dfd, filename, flags, mode);
1100}
1101EXPORT_SYMBOL_GPL(sys_openat);
1102
1050#ifndef __alpha__ 1103#ifndef __alpha__
1051 1104
1052/* 1105/*