aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 23:23:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 23:23:44 -0400
commit4836e3007882984279ca63d3c42bf0b14616eb78 (patch)
tree28bf22726964e068b825491d71a141eefedbe5f8 /fs/exec.c
parent5c7c204aeca51ccfad63caab4fcdc5d8026c0fd8 (diff)
parent4e1e018ecc6f7bfd10fc75b3ff9715cc8164e0a2 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (39 commits) [PATCH] fix RLIM_NOFILE handling [PATCH] get rid of corner case in dup3() entirely [PATCH] remove remaining namei_{32,64}.h crap [PATCH] get rid of indirect users of namei.h [PATCH] get rid of __user_path_lookup_open [PATCH] f_count may wrap around [PATCH] dup3 fix [PATCH] don't pass nameidata to __ncp_lookup_validate() [PATCH] don't pass nameidata to gfs2_lookupi() [PATCH] new (local) helper: user_path_parent() [PATCH] sanitize __user_walk_fd() et.al. [PATCH] preparation to __user_walk_fd cleanup [PATCH] kill nameidata passing to permission(), rename to inode_permission() [PATCH] take noexec checks to very few callers that care Re: [PATCH 3/6] vfs: open_exec cleanup [patch 4/4] vfs: immutable inode checking cleanup [patch 3/4] fat: dont call notify_change [patch 2/4] vfs: utimes cleanup [patch 1/4] vfs: utimes: move owner check into inode_change_ok() [PATCH] vfs: use kstrdup() and check failing allocation ...
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c81
1 files changed, 48 insertions, 33 deletions
diff --git a/fs/exec.c b/fs/exec.c
index b8792a131533..9696bbf0f0b1 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -106,11 +106,17 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
106 */ 106 */
107asmlinkage long sys_uselib(const char __user * library) 107asmlinkage long sys_uselib(const char __user * library)
108{ 108{
109 struct file * file; 109 struct file *file;
110 struct nameidata nd; 110 struct nameidata nd;
111 int error; 111 char *tmp = getname(library);
112 112 int error = PTR_ERR(tmp);
113 error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); 113
114 if (!IS_ERR(tmp)) {
115 error = path_lookup_open(AT_FDCWD, tmp,
116 LOOKUP_FOLLOW, &nd,
117 FMODE_READ|FMODE_EXEC);
118 putname(tmp);
119 }
114 if (error) 120 if (error)
115 goto out; 121 goto out;
116 122
@@ -118,7 +124,11 @@ asmlinkage long sys_uselib(const char __user * library)
118 if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) 124 if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
119 goto exit; 125 goto exit;
120 126
121 error = vfs_permission(&nd, MAY_READ | MAY_EXEC); 127 error = -EACCES;
128 if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
129 goto exit;
130
131 error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN);
122 if (error) 132 if (error)
123 goto exit; 133 goto exit;
124 134
@@ -656,38 +666,43 @@ EXPORT_SYMBOL(setup_arg_pages);
656struct file *open_exec(const char *name) 666struct file *open_exec(const char *name)
657{ 667{
658 struct nameidata nd; 668 struct nameidata nd;
659 int err;
660 struct file *file; 669 struct file *file;
670 int err;
661 671
662 err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC); 672 err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd,
663 file = ERR_PTR(err); 673 FMODE_READ|FMODE_EXEC);
664 674 if (err)
665 if (!err) { 675 goto out;
666 struct inode *inode = nd.path.dentry->d_inode; 676
667 file = ERR_PTR(-EACCES); 677 err = -EACCES;
668 if (S_ISREG(inode->i_mode)) { 678 if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
669 int err = vfs_permission(&nd, MAY_EXEC); 679 goto out_path_put;
670 file = ERR_PTR(err); 680
671 if (!err) { 681 if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
672 file = nameidata_to_filp(&nd, 682 goto out_path_put;
673 O_RDONLY|O_LARGEFILE); 683
674 if (!IS_ERR(file)) { 684 err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN);
675 err = deny_write_access(file); 685 if (err)
676 if (err) { 686 goto out_path_put;
677 fput(file); 687
678 file = ERR_PTR(err); 688 file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
679 } 689 if (IS_ERR(file))
680 } 690 return file;
681out: 691
682 return file; 692 err = deny_write_access(file);
683 } 693 if (err) {
684 } 694 fput(file);
685 release_open_intent(&nd); 695 goto out;
686 path_put(&nd.path);
687 } 696 }
688 goto out;
689}
690 697
698 return file;
699
700 out_path_put:
701 release_open_intent(&nd);
702 path_put(&nd.path);
703 out:
704 return ERR_PTR(err);
705}
691EXPORT_SYMBOL(open_exec); 706EXPORT_SYMBOL(open_exec);
692 707
693int kernel_read(struct file *file, unsigned long offset, 708int kernel_read(struct file *file, unsigned long offset,