diff options
-rw-r--r-- | fs/exec.c | 10 | ||||
-rw-r--r-- | fs/open.c | 2 | ||||
-rw-r--r-- | fs/proc/root.c | 2 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 4 | ||||
-rw-r--r-- | include/linux/fs.h | 3 | ||||
-rw-r--r-- | kernel/sys.c | 3 | ||||
-rw-r--r-- | mm/mmap.c | 4 | ||||
-rw-r--r-- | mm/nommu.c | 2 | ||||
-rw-r--r-- | security/security.c | 2 |
9 files changed, 23 insertions, 9 deletions
@@ -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 | ||
101 | bool 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); |
@@ -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 */ |
1249 | enum { | 1250 | enum { |
@@ -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 | ||
3034 | extern 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); |
@@ -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); |