summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2016-02-17 19:51:16 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2016-03-30 17:12:22 -0400
commit948b701a607f123df92ed29084413e5dd8cda2ed (patch)
treea8ec94afaa37da897e283923d20d3bde16897d97
parent9a08c352d05305ca7651540c3b107da1e4e1f40b (diff)
binfmt_misc: add persistent opened binary handler for containers
This patch adds a new flag 'F' to the binfmt handlers. If you pass in 'F' the binary that runs the emulation will be opened immediately and in future, will be cloned from the open file. The net effect is that the handler survives both changeroots and mount namespace changes, making it easy to work with foreign architecture containers without contaminating the container image with the emulator. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
-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}