| .. | .. |
|---|
| 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); |
|---|