diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-10-09 03:02:35 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-10-09 03:02:35 -0400 |
commit | 1236d6bb6e19fc72ffc6bbcdeb1bfefe450e54ee (patch) | |
tree | 47da3feee8e263e8c9352c85cf518e624be3c211 /fs/binfmt_misc.c | |
parent | 750b1a6894ecc9b178c6e3d0a1170122971b2036 (diff) | |
parent | 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (diff) |
Merge 4.14-rc4 into staging-next
We want the staging/iio fixes in here as well to handle merge issues.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/binfmt_misc.c')
-rw-r--r-- | fs/binfmt_misc.c | 56 |
1 files changed, 26 insertions, 30 deletions
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index ce7181ea60fa..2a46762def31 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -54,7 +54,7 @@ typedef struct { | |||
54 | int size; /* size of magic/mask */ | 54 | int size; /* size of magic/mask */ |
55 | char *magic; /* magic or filename extension */ | 55 | char *magic; /* magic or filename extension */ |
56 | char *mask; /* mask, NULL for exact match */ | 56 | char *mask; /* mask, NULL for exact match */ |
57 | char *interpreter; /* filename of interpreter */ | 57 | const char *interpreter; /* filename of interpreter */ |
58 | char *name; | 58 | char *name; |
59 | struct dentry *dentry; | 59 | struct dentry *dentry; |
60 | struct file *interp_file; | 60 | struct file *interp_file; |
@@ -131,27 +131,26 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
131 | { | 131 | { |
132 | Node *fmt; | 132 | Node *fmt; |
133 | struct file *interp_file = NULL; | 133 | struct file *interp_file = NULL; |
134 | char iname[BINPRM_BUF_SIZE]; | ||
135 | const char *iname_addr = iname; | ||
136 | int retval; | 134 | int retval; |
137 | int fd_binary = -1; | 135 | int fd_binary = -1; |
138 | 136 | ||
139 | retval = -ENOEXEC; | 137 | retval = -ENOEXEC; |
140 | if (!enabled) | 138 | if (!enabled) |
141 | goto ret; | 139 | return retval; |
142 | 140 | ||
143 | /* to keep locking time low, we copy the interpreter string */ | 141 | /* to keep locking time low, we copy the interpreter string */ |
144 | read_lock(&entries_lock); | 142 | read_lock(&entries_lock); |
145 | fmt = check_file(bprm); | 143 | fmt = check_file(bprm); |
146 | if (fmt) | 144 | if (fmt) |
147 | strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE); | 145 | dget(fmt->dentry); |
148 | read_unlock(&entries_lock); | 146 | read_unlock(&entries_lock); |
149 | if (!fmt) | 147 | if (!fmt) |
150 | goto ret; | 148 | return retval; |
151 | 149 | ||
152 | /* Need to be able to load the file after exec */ | 150 | /* Need to be able to load the file after exec */ |
151 | retval = -ENOENT; | ||
153 | if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE) | 152 | if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE) |
154 | return -ENOENT; | 153 | goto ret; |
155 | 154 | ||
156 | if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { | 155 | if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { |
157 | retval = remove_arg_zero(bprm); | 156 | retval = remove_arg_zero(bprm); |
@@ -195,22 +194,22 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
195 | bprm->argc++; | 194 | bprm->argc++; |
196 | 195 | ||
197 | /* add the interp as argv[0] */ | 196 | /* add the interp as argv[0] */ |
198 | retval = copy_strings_kernel(1, &iname_addr, bprm); | 197 | retval = copy_strings_kernel(1, &fmt->interpreter, bprm); |
199 | if (retval < 0) | 198 | if (retval < 0) |
200 | goto error; | 199 | goto error; |
201 | bprm->argc++; | 200 | bprm->argc++; |
202 | 201 | ||
203 | /* Update interp in case binfmt_script needs it. */ | 202 | /* Update interp in case binfmt_script needs it. */ |
204 | retval = bprm_change_interp(iname, bprm); | 203 | retval = bprm_change_interp(fmt->interpreter, bprm); |
205 | if (retval < 0) | 204 | if (retval < 0) |
206 | goto error; | 205 | goto error; |
207 | 206 | ||
208 | if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) { | 207 | if (fmt->flags & MISC_FMT_OPEN_FILE) { |
209 | interp_file = filp_clone_open(fmt->interp_file); | 208 | interp_file = filp_clone_open(fmt->interp_file); |
210 | if (!IS_ERR(interp_file)) | 209 | if (!IS_ERR(interp_file)) |
211 | deny_write_access(interp_file); | 210 | deny_write_access(interp_file); |
212 | } else { | 211 | } else { |
213 | interp_file = open_exec(iname); | 212 | interp_file = open_exec(fmt->interpreter); |
214 | } | 213 | } |
215 | retval = PTR_ERR(interp_file); | 214 | retval = PTR_ERR(interp_file); |
216 | if (IS_ERR(interp_file)) | 215 | if (IS_ERR(interp_file)) |
@@ -238,6 +237,7 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
238 | goto error; | 237 | goto error; |
239 | 238 | ||
240 | ret: | 239 | ret: |
240 | dput(fmt->dentry); | ||
241 | return retval; | 241 | return retval; |
242 | error: | 242 | error: |
243 | if (fd_binary > 0) | 243 | if (fd_binary > 0) |
@@ -594,8 +594,13 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode) | |||
594 | 594 | ||
595 | static void bm_evict_inode(struct inode *inode) | 595 | static void bm_evict_inode(struct inode *inode) |
596 | { | 596 | { |
597 | Node *e = inode->i_private; | ||
598 | |||
599 | if (e->flags & MISC_FMT_OPEN_FILE) | ||
600 | filp_close(e->interp_file, NULL); | ||
601 | |||
597 | clear_inode(inode); | 602 | clear_inode(inode); |
598 | kfree(inode->i_private); | 603 | kfree(e); |
599 | } | 604 | } |
600 | 605 | ||
601 | static void kill_node(Node *e) | 606 | static void kill_node(Node *e) |
@@ -603,24 +608,14 @@ static void kill_node(Node *e) | |||
603 | struct dentry *dentry; | 608 | struct dentry *dentry; |
604 | 609 | ||
605 | write_lock(&entries_lock); | 610 | write_lock(&entries_lock); |
606 | dentry = e->dentry; | 611 | list_del_init(&e->list); |
607 | if (dentry) { | ||
608 | list_del_init(&e->list); | ||
609 | e->dentry = NULL; | ||
610 | } | ||
611 | write_unlock(&entries_lock); | 612 | write_unlock(&entries_lock); |
612 | 613 | ||
613 | if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) { | 614 | dentry = e->dentry; |
614 | filp_close(e->interp_file, NULL); | 615 | drop_nlink(d_inode(dentry)); |
615 | e->interp_file = NULL; | 616 | d_drop(dentry); |
616 | } | 617 | dput(dentry); |
617 | 618 | simple_release_fs(&bm_mnt, &entry_count); | |
618 | if (dentry) { | ||
619 | drop_nlink(d_inode(dentry)); | ||
620 | d_drop(dentry); | ||
621 | dput(dentry); | ||
622 | simple_release_fs(&bm_mnt, &entry_count); | ||
623 | } | ||
624 | } | 619 | } |
625 | 620 | ||
626 | /* /<entry> */ | 621 | /* /<entry> */ |
@@ -665,7 +660,8 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, | |||
665 | root = file_inode(file)->i_sb->s_root; | 660 | root = file_inode(file)->i_sb->s_root; |
666 | inode_lock(d_inode(root)); | 661 | inode_lock(d_inode(root)); |
667 | 662 | ||
668 | kill_node(e); | 663 | if (!list_empty(&e->list)) |
664 | kill_node(e); | ||
669 | 665 | ||
670 | inode_unlock(d_inode(root)); | 666 | inode_unlock(d_inode(root)); |
671 | break; | 667 | break; |
@@ -794,7 +790,7 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer, | |||
794 | inode_lock(d_inode(root)); | 790 | inode_lock(d_inode(root)); |
795 | 791 | ||
796 | while (!list_empty(&entries)) | 792 | while (!list_empty(&entries)) |
797 | kill_node(list_entry(entries.next, Node, list)); | 793 | kill_node(list_first_entry(&entries, Node, list)); |
798 | 794 | ||
799 | inode_unlock(d_inode(root)); | 795 | inode_unlock(d_inode(root)); |
800 | break; | 796 | break; |