Skip to content

Commit 948b701

Browse files
James BottomleyJames Bottomley
James Bottomley
authored and
James Bottomley
committed
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 <[email protected]> Acked-by: Serge Hallyn <[email protected]>
1 parent 9a08c35 commit 948b701

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

fs/binfmt_misc.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include <linux/fs.h>
2727
#include <linux/uaccess.h>
2828

29+
#include "internal.h"
30+
2931
#ifdef DEBUG
3032
# define USE_DEBUG 1
3133
#else
@@ -43,6 +45,7 @@ enum {Enabled, Magic};
4345
#define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
4446
#define MISC_FMT_OPEN_BINARY (1 << 30)
4547
#define MISC_FMT_CREDENTIALS (1 << 29)
48+
#define MISC_FMT_OPEN_FILE (1 << 28)
4649

4750
typedef struct {
4851
struct list_head list;
@@ -54,6 +57,7 @@ typedef struct {
5457
char *interpreter; /* filename of interpreter */
5558
char *name;
5659
struct dentry *dentry;
60+
struct file *interp_file;
5761
} Node;
5862

5963
static DEFINE_RWLOCK(entries_lock);
@@ -201,7 +205,13 @@ static int load_misc_binary(struct linux_binprm *bprm)
201205
if (retval < 0)
202206
goto error;
203207

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+
}
205215
retval = PTR_ERR(interp_file);
206216
if (IS_ERR(interp_file))
207217
goto error;
@@ -285,6 +295,11 @@ static char *check_special_flags(char *sfs, Node *e)
285295
e->flags |= (MISC_FMT_CREDENTIALS |
286296
MISC_FMT_OPEN_BINARY);
287297
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;
288303
default:
289304
cont = 0;
290305
}
@@ -543,6 +558,8 @@ static void entry_status(Node *e, char *page)
543558
*dp++ = 'O';
544559
if (e->flags & MISC_FMT_CREDENTIALS)
545560
*dp++ = 'C';
561+
if (e->flags & MISC_FMT_OPEN_FILE)
562+
*dp++ = 'F';
546563
*dp++ = '\n';
547564

548565
if (!test_bit(Magic, &e->flags)) {
@@ -590,6 +607,11 @@ static void kill_node(Node *e)
590607
}
591608
write_unlock(&entries_lock);
592609

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+
593615
if (dentry) {
594616
drop_nlink(d_inode(dentry));
595617
d_drop(dentry);
@@ -698,6 +720,21 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
698720
goto out2;
699721
}
700722

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+
701738
e->dentry = dget(dentry);
702739
inode->i_private = e;
703740
inode->i_fop = &bm_entry_operations;
@@ -716,7 +753,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
716753

717754
if (err) {
718755
kfree(e);
719-
return -EINVAL;
756+
return err;
720757
}
721758
return count;
722759
}

0 commit comments

Comments
 (0)