summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/binfmt_misc.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 3a3ced779fc7..8a108c435bc6 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -26,6 +26,8 @@
26#include <linux/fs.h> 26#include <linux/fs.h>
27#include <linux/uaccess.h> 27#include <linux/uaccess.h>
28 28
29#include "internal.h"
30
29#ifdef DEBUG 31#ifdef DEBUG
30# define USE_DEBUG 1 32# define USE_DEBUG 1
31#else 33#else
@@ -43,6 +45,7 @@ enum {Enabled, Magic};
43#define MISC_FMT_PRESERVE_ARGV0 (1 << 31) 45#define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
44#define MISC_FMT_OPEN_BINARY (1 << 30) 46#define MISC_FMT_OPEN_BINARY (1 << 30)
45#define MISC_FMT_CREDENTIALS (1 << 29) 47#define MISC_FMT_CREDENTIALS (1 << 29)
48#define MISC_FMT_OPEN_FILE (1 << 28)
46 49
47typedef struct { 50typedef struct {
48 struct list_head list; 51 struct list_head list;
@@ -54,6 +57,7 @@ typedef struct {
54 char *interpreter; /* filename of interpreter */ 57 char *interpreter; /* filename of interpreter */
55 char *name; 58 char *name;
56 struct dentry *dentry; 59 struct dentry *dentry;
60 struct file *interp_file;
57} Node; 61} Node;
58 62
59static DEFINE_RWLOCK(entries_lock); 63static DEFINE_RWLOCK(entries_lock);
@@ -201,7 +205,13 @@ static int load_misc_binary(struct linux_binprm *bprm)
201 if (retval < 0) 205 if (retval < 0)
202 goto error; 206 goto error;
203 207
204 interp_file = open_exec(iname); 208 if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) {
209 interp_file = filp_clone_open(fmt->interp_file);
210 if (!IS_ERR(interp_file))
211 deny_write_access(interp_file);
212 } else {
213 interp_file = open_exec(iname);
214 }
205 retval = PTR_ERR(interp_file); 215 retval = PTR_ERR(interp_file);
206 if (IS_ERR(interp_file)) 216 if (IS_ERR(interp_file))
207 goto error; 217 goto error;
@@ -285,6 +295,11 @@ static char *check_special_flags(char *sfs, Node *e)
285 e->flags |= (MISC_FMT_CREDENTIALS | 295 e->flags |= (MISC_FMT_CREDENTIALS |
286 MISC_FMT_OPEN_BINARY); 296 MISC_FMT_OPEN_BINARY);
287 break; 297 break;
298 case 'F':
299 pr_debug("register: flag: F: open interpreter file now\n");
300 p++;
301 e->flags |= MISC_FMT_OPEN_FILE;
302 break;
288 default: 303 default:
289 cont = 0; 304 cont = 0;
290 } 305 }
@@ -543,6 +558,8 @@ static void entry_status(Node *e, char *page)
543 *dp++ = 'O'; 558 *dp++ = 'O';
544 if (e->flags & MISC_FMT_CREDENTIALS) 559 if (e->flags & MISC_FMT_CREDENTIALS)
545 *dp++ = 'C'; 560 *dp++ = 'C';
561 if (e->flags & MISC_FMT_OPEN_FILE)
562 *dp++ = 'F';
546 *dp++ = '\n'; 563 *dp++ = '\n';
547 564
548 if (!test_bit(Magic, &e->flags)) { 565 if (!test_bit(Magic, &e->flags)) {
@@ -590,6 +607,11 @@ static void kill_node(Node *e)
590 } 607 }
591 write_unlock(&entries_lock); 608 write_unlock(&entries_lock);
592 609
610 if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) {
611 filp_close(e->interp_file, NULL);
612 e->interp_file = NULL;
613 }
614
593 if (dentry) { 615 if (dentry) {
594 drop_nlink(d_inode(dentry)); 616 drop_nlink(d_inode(dentry));
595 d_drop(dentry); 617 d_drop(dentry);
@@ -698,6 +720,21 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
698 goto out2; 720 goto out2;
699 } 721 }
700 722
723 if (e->flags & MISC_FMT_OPEN_FILE) {
724 struct file *f;
725
726 f = open_exec(e->interpreter);
727 if (IS_ERR(f)) {
728 err = PTR_ERR(f);
729 pr_notice("register: failed to install interpreter file %s\n", e->interpreter);
730 simple_release_fs(&bm_mnt, &entry_count);
731 iput(inode);
732 inode = NULL;
733 goto out2;
734 }
735 e->interp_file = f;
736 }
737
701 e->dentry = dget(dentry); 738 e->dentry = dget(dentry);
702 inode->i_private = e; 739 inode->i_private = e;
703 inode->i_fop = &bm_entry_operations; 740 inode->i_fop = &bm_entry_operations;
@@ -716,7 +753,7 @@ out:
716 753
717 if (err) { 754 if (err) {
718 kfree(e); 755 kfree(e);
719 return -EINVAL; 756 return err;
720 } 757 }
721 return count; 758 return count;
722} 759}