aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c10
-rw-r--r--fs/open.c2
-rw-r--r--fs/proc/root.c2
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--include/linux/fs.h3
-rw-r--r--kernel/sys.c3
-rw-r--r--mm/mmap.c4
-rw-r--r--mm/nommu.c2
-rw-r--r--security/security.c2
9 files changed, 23 insertions, 9 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 1977c2a553ac..b06623a9347f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -98,6 +98,12 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
98 module_put(fmt->module); 98 module_put(fmt->module);
99} 99}
100 100
101bool path_noexec(const struct path *path)
102{
103 return (path->mnt->mnt_flags & MNT_NOEXEC) ||
104 (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
105}
106
101#ifdef CONFIG_USELIB 107#ifdef CONFIG_USELIB
102/* 108/*
103 * Note that a shared library must be both readable and executable due to 109 * Note that a shared library must be both readable and executable due to
@@ -132,7 +138,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
132 goto exit; 138 goto exit;
133 139
134 error = -EACCES; 140 error = -EACCES;
135 if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) 141 if (path_noexec(&file->f_path))
136 goto exit; 142 goto exit;
137 143
138 fsnotify_open(file); 144 fsnotify_open(file);
@@ -777,7 +783,7 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
777 if (!S_ISREG(file_inode(file)->i_mode)) 783 if (!S_ISREG(file_inode(file)->i_mode))
778 goto exit; 784 goto exit;
779 785
780 if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) 786 if (path_noexec(&file->f_path))
781 goto exit; 787 goto exit;
782 788
783 err = deny_write_access(file); 789 err = deny_write_access(file);
diff --git a/fs/open.c b/fs/open.c
index e33dab287fa0..b6f1e96a7c0b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -377,7 +377,7 @@ retry:
377 * with the "noexec" flag. 377 * with the "noexec" flag.
378 */ 378 */
379 res = -EACCES; 379 res = -EACCES;
380 if (path.mnt->mnt_flags & MNT_NOEXEC) 380 if (path_noexec(&path))
381 goto out_path_release; 381 goto out_path_release;
382 } 382 }
383 383
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 68feb0f70e63..361ab4ee42fc 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -134,6 +134,8 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
134 } 134 }
135 135
136 sb->s_flags |= MS_ACTIVE; 136 sb->s_flags |= MS_ACTIVE;
137 /* User space would break if executables appear on proc */
138 sb->s_iflags |= SB_I_NOEXEC;
137 } 139 }
138 140
139 return dget(sb->s_root); 141 return dget(sb->s_root);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 1c6ac6fcee9f..f3db82071cfb 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -40,6 +40,10 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
40 SYSFS_MAGIC, &new_sb, ns); 40 SYSFS_MAGIC, &new_sb, ns);
41 if (IS_ERR(root) || !new_sb) 41 if (IS_ERR(root) || !new_sb)
42 kobj_ns_drop(KOBJ_NS_TYPE_NET, ns); 42 kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
43 else if (new_sb)
44 /* Userspace would break if executables appear on sysfs */
45 root->d_sb->s_iflags |= SB_I_NOEXEC;
46
43 return root; 47 return root;
44} 48}
45 49
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a0653e560c26..42912f8d286e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1244,6 +1244,7 @@ struct mm_struct;
1244 1244
1245/* sb->s_iflags */ 1245/* sb->s_iflags */
1246#define SB_I_CGROUPWB 0x00000001 /* cgroup-aware writeback enabled */ 1246#define SB_I_CGROUPWB 0x00000001 /* cgroup-aware writeback enabled */
1247#define SB_I_NOEXEC 0x00000002 /* Ignore executables on this fs */
1247 1248
1248/* Possible states of 'frozen' field */ 1249/* Possible states of 'frozen' field */
1249enum { 1250enum {
@@ -3030,4 +3031,6 @@ static inline bool dir_relax(struct inode *inode)
3030 return !IS_DEADDIR(inode); 3031 return !IS_DEADDIR(inode);
3031} 3032}
3032 3033
3034extern bool path_noexec(const struct path *path);
3035
3033#endif /* _LINUX_FS_H */ 3036#endif /* _LINUX_FS_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index 259fda25eb6b..fa2f2f671a5c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1668,8 +1668,7 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1668 * overall picture. 1668 * overall picture.
1669 */ 1669 */
1670 err = -EACCES; 1670 err = -EACCES;
1671 if (!S_ISREG(inode->i_mode) || 1671 if (!S_ISREG(inode->i_mode) || path_noexec(&exe.file->f_path))
1672 exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC)
1673 goto exit; 1672 goto exit;
1674 1673
1675 err = inode_permission(inode, MAY_EXEC); 1674 err = inode_permission(inode, MAY_EXEC);
diff --git a/mm/mmap.c b/mm/mmap.c
index aa632ade2be7..f126923ce683 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1268,7 +1268,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
1268 * mounted, in which case we dont add PROT_EXEC.) 1268 * mounted, in which case we dont add PROT_EXEC.)
1269 */ 1269 */
1270 if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC)) 1270 if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
1271 if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC))) 1271 if (!(file && path_noexec(&file->f_path)))
1272 prot |= PROT_EXEC; 1272 prot |= PROT_EXEC;
1273 1273
1274 if (!(flags & MAP_FIXED)) 1274 if (!(flags & MAP_FIXED))
@@ -1337,7 +1337,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
1337 case MAP_PRIVATE: 1337 case MAP_PRIVATE:
1338 if (!(file->f_mode & FMODE_READ)) 1338 if (!(file->f_mode & FMODE_READ))
1339 return -EACCES; 1339 return -EACCES;
1340 if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) { 1340 if (path_noexec(&file->f_path)) {
1341 if (vm_flags & VM_EXEC) 1341 if (vm_flags & VM_EXEC)
1342 return -EPERM; 1342 return -EPERM;
1343 vm_flags &= ~VM_MAYEXEC; 1343 vm_flags &= ~VM_MAYEXEC;
diff --git a/mm/nommu.c b/mm/nommu.c
index 58ea3643b9e9..ce17abf087ff 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1035,7 +1035,7 @@ static int validate_mmap_request(struct file *file,
1035 1035
1036 /* handle executable mappings and implied executable 1036 /* handle executable mappings and implied executable
1037 * mappings */ 1037 * mappings */
1038 if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) { 1038 if (path_noexec(&file->f_path)) {
1039 if (prot & PROT_EXEC) 1039 if (prot & PROT_EXEC)
1040 return -EPERM; 1040 return -EPERM;
1041 } else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) { 1041 } else if ((prot & PROT_READ) && !(prot & PROT_EXEC)) {
diff --git a/security/security.c b/security/security.c
index 595fffab48b0..062f3c997fdc 100644
--- a/security/security.c
+++ b/security/security.c
@@ -776,7 +776,7 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
776 * ditto if it's not on noexec mount, except that on !MMU we need 776 * ditto if it's not on noexec mount, except that on !MMU we need
777 * NOMMU_MAP_EXEC (== VM_MAYEXEC) in this case 777 * NOMMU_MAP_EXEC (== VM_MAYEXEC) in this case
778 */ 778 */
779 if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) { 779 if (!path_noexec(&file->f_path)) {
780#ifndef CONFIG_MMU 780#ifndef CONFIG_MMU
781 if (file->f_op->mmap_capabilities) { 781 if (file->f_op->mmap_capabilities) {
782 unsigned caps = file->f_op->mmap_capabilities(file); 782 unsigned caps = file->f_op->mmap_capabilities(file);