.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * binfmt_misc.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
22 | 23 | #include <linux/pagemap.h> |
---|
23 | 24 | #include <linux/namei.h> |
---|
24 | 25 | #include <linux/mount.h> |
---|
| 26 | +#include <linux/fs_context.h> |
---|
25 | 27 | #include <linux/syscalls.h> |
---|
26 | 28 | #include <linux/fs.h> |
---|
27 | 29 | #include <linux/uaccess.h> |
---|
.. | .. |
---|
42 | 44 | static int enabled = 1; |
---|
43 | 45 | |
---|
44 | 46 | enum {Enabled, Magic}; |
---|
45 | | -#define MISC_FMT_PRESERVE_ARGV0 (1 << 31) |
---|
46 | | -#define MISC_FMT_OPEN_BINARY (1 << 30) |
---|
47 | | -#define MISC_FMT_CREDENTIALS (1 << 29) |
---|
48 | | -#define MISC_FMT_OPEN_FILE (1 << 28) |
---|
| 47 | +#define MISC_FMT_PRESERVE_ARGV0 (1UL << 31) |
---|
| 48 | +#define MISC_FMT_OPEN_BINARY (1UL << 30) |
---|
| 49 | +#define MISC_FMT_CREDENTIALS (1UL << 29) |
---|
| 50 | +#define MISC_FMT_OPEN_FILE (1UL << 28) |
---|
49 | 51 | |
---|
50 | 52 | typedef struct { |
---|
51 | 53 | struct list_head list; |
---|
.. | .. |
---|
132 | 134 | Node *fmt; |
---|
133 | 135 | struct file *interp_file = NULL; |
---|
134 | 136 | int retval; |
---|
135 | | - int fd_binary = -1; |
---|
136 | 137 | |
---|
137 | 138 | retval = -ENOEXEC; |
---|
138 | 139 | if (!enabled) |
---|
.. | .. |
---|
158 | 159 | goto ret; |
---|
159 | 160 | } |
---|
160 | 161 | |
---|
161 | | - if (fmt->flags & MISC_FMT_OPEN_BINARY) { |
---|
| 162 | + if (fmt->flags & MISC_FMT_OPEN_BINARY) |
---|
| 163 | + bprm->have_execfd = 1; |
---|
162 | 164 | |
---|
163 | | - /* if the binary should be opened on behalf of the |
---|
164 | | - * interpreter than keep it open and assign descriptor |
---|
165 | | - * to it |
---|
166 | | - */ |
---|
167 | | - fd_binary = get_unused_fd_flags(0); |
---|
168 | | - if (fd_binary < 0) { |
---|
169 | | - retval = fd_binary; |
---|
170 | | - goto ret; |
---|
171 | | - } |
---|
172 | | - fd_install(fd_binary, bprm->file); |
---|
173 | | - |
---|
174 | | - /* if the binary is not readable than enforce mm->dumpable=0 |
---|
175 | | - regardless of the interpreter's permissions */ |
---|
176 | | - would_dump(bprm, bprm->file); |
---|
177 | | - |
---|
178 | | - allow_write_access(bprm->file); |
---|
179 | | - bprm->file = NULL; |
---|
180 | | - |
---|
181 | | - /* mark the bprm that fd should be passed to interp */ |
---|
182 | | - bprm->interp_flags |= BINPRM_FLAGS_EXECFD; |
---|
183 | | - bprm->interp_data = fd_binary; |
---|
184 | | - |
---|
185 | | - } else { |
---|
186 | | - allow_write_access(bprm->file); |
---|
187 | | - fput(bprm->file); |
---|
188 | | - bprm->file = NULL; |
---|
189 | | - } |
---|
190 | 165 | /* make argv[1] be the path to the binary */ |
---|
191 | | - retval = copy_strings_kernel(1, &bprm->interp, bprm); |
---|
| 166 | + retval = copy_string_kernel(bprm->interp, bprm); |
---|
192 | 167 | if (retval < 0) |
---|
193 | | - goto error; |
---|
| 168 | + goto ret; |
---|
194 | 169 | bprm->argc++; |
---|
195 | 170 | |
---|
196 | 171 | /* add the interp as argv[0] */ |
---|
197 | | - retval = copy_strings_kernel(1, &fmt->interpreter, bprm); |
---|
| 172 | + retval = copy_string_kernel(fmt->interpreter, bprm); |
---|
198 | 173 | if (retval < 0) |
---|
199 | | - goto error; |
---|
| 174 | + goto ret; |
---|
200 | 175 | bprm->argc++; |
---|
201 | 176 | |
---|
202 | 177 | /* Update interp in case binfmt_script needs it. */ |
---|
203 | 178 | retval = bprm_change_interp(fmt->interpreter, bprm); |
---|
204 | 179 | if (retval < 0) |
---|
205 | | - goto error; |
---|
| 180 | + goto ret; |
---|
206 | 181 | |
---|
207 | 182 | if (fmt->flags & MISC_FMT_OPEN_FILE) { |
---|
208 | 183 | interp_file = file_clone_open(fmt->interp_file); |
---|
.. | .. |
---|
213 | 188 | } |
---|
214 | 189 | retval = PTR_ERR(interp_file); |
---|
215 | 190 | if (IS_ERR(interp_file)) |
---|
216 | | - goto error; |
---|
| 191 | + goto ret; |
---|
217 | 192 | |
---|
218 | | - bprm->file = interp_file; |
---|
219 | | - if (fmt->flags & MISC_FMT_CREDENTIALS) { |
---|
220 | | - loff_t pos = 0; |
---|
| 193 | + bprm->interpreter = interp_file; |
---|
| 194 | + if (fmt->flags & MISC_FMT_CREDENTIALS) |
---|
| 195 | + bprm->execfd_creds = 1; |
---|
221 | 196 | |
---|
222 | | - /* |
---|
223 | | - * No need to call prepare_binprm(), it's already been |
---|
224 | | - * done. bprm->buf is stale, update from interp_file. |
---|
225 | | - */ |
---|
226 | | - memset(bprm->buf, 0, BINPRM_BUF_SIZE); |
---|
227 | | - retval = kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, |
---|
228 | | - &pos); |
---|
229 | | - } else |
---|
230 | | - retval = prepare_binprm(bprm); |
---|
231 | | - |
---|
232 | | - if (retval < 0) |
---|
233 | | - goto error; |
---|
234 | | - |
---|
235 | | - retval = search_binary_handler(bprm); |
---|
236 | | - if (retval < 0) |
---|
237 | | - goto error; |
---|
238 | | - |
---|
| 197 | + retval = 0; |
---|
239 | 198 | ret: |
---|
240 | 199 | dput(fmt->dentry); |
---|
241 | 200 | return retval; |
---|
242 | | -error: |
---|
243 | | - if (fd_binary > 0) |
---|
244 | | - ksys_close(fd_binary); |
---|
245 | | - bprm->interp_flags = 0; |
---|
246 | | - bprm->interp_data = 0; |
---|
247 | | - goto ret; |
---|
248 | 201 | } |
---|
249 | 202 | |
---|
250 | 203 | /* Command parsers */ |
---|
.. | .. |
---|
819 | 772 | .evict_inode = bm_evict_inode, |
---|
820 | 773 | }; |
---|
821 | 774 | |
---|
822 | | -static int bm_fill_super(struct super_block *sb, void *data, int silent) |
---|
| 775 | +static int bm_fill_super(struct super_block *sb, struct fs_context *fc) |
---|
823 | 776 | { |
---|
824 | 777 | int err; |
---|
825 | 778 | static const struct tree_descr bm_files[] = { |
---|
.. | .. |
---|
834 | 787 | return err; |
---|
835 | 788 | } |
---|
836 | 789 | |
---|
837 | | -static struct dentry *bm_mount(struct file_system_type *fs_type, |
---|
838 | | - int flags, const char *dev_name, void *data) |
---|
| 790 | +static int bm_get_tree(struct fs_context *fc) |
---|
839 | 791 | { |
---|
840 | | - return mount_single(fs_type, flags, data, bm_fill_super); |
---|
| 792 | + return get_tree_single(fc, bm_fill_super); |
---|
| 793 | +} |
---|
| 794 | + |
---|
| 795 | +static const struct fs_context_operations bm_context_ops = { |
---|
| 796 | + .get_tree = bm_get_tree, |
---|
| 797 | +}; |
---|
| 798 | + |
---|
| 799 | +static int bm_init_fs_context(struct fs_context *fc) |
---|
| 800 | +{ |
---|
| 801 | + fc->ops = &bm_context_ops; |
---|
| 802 | + return 0; |
---|
841 | 803 | } |
---|
842 | 804 | |
---|
843 | 805 | static struct linux_binfmt misc_format = { |
---|
.. | .. |
---|
848 | 810 | static struct file_system_type bm_fs_type = { |
---|
849 | 811 | .owner = THIS_MODULE, |
---|
850 | 812 | .name = "binfmt_misc", |
---|
851 | | - .mount = bm_mount, |
---|
| 813 | + .init_fs_context = bm_init_fs_context, |
---|
852 | 814 | .kill_sb = kill_litter_super, |
---|
853 | 815 | }; |
---|
854 | 816 | MODULE_ALIAS_FS("binfmt_misc"); |
---|
.. | .. |
---|
870 | 832 | core_initcall(init_misc_binfmt); |
---|
871 | 833 | module_exit(exit_misc_binfmt); |
---|
872 | 834 | MODULE_LICENSE("GPL"); |
---|
| 835 | +MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY); |
---|