diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 81 |
1 files changed, 48 insertions, 33 deletions
@@ -106,11 +106,17 @@ static inline void put_binfmt(struct linux_binfmt * fmt) | |||
106 | */ | 106 | */ |
107 | asmlinkage long sys_uselib(const char __user * library) | 107 | asmlinkage 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); | |||
656 | struct file *open_exec(const char *name) | 666 | struct 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; |
681 | out: | 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 | } | ||
691 | EXPORT_SYMBOL(open_exec); | 706 | EXPORT_SYMBOL(open_exec); |
692 | 707 | ||
693 | int kernel_read(struct file *file, unsigned long offset, | 708 | int kernel_read(struct file *file, unsigned long offset, |