From: Josh Max <JMax@mail.greenriver.edu>
To: <viro@zeniv.linux.org.uk>
Cc: <linux-fsdevel@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
Josh Max <JMax@mail.greenriver.edu>
Subject: [PATCH] binfmt_misc: allow selecting the interpreter based on xattr keywords
Date: Sun, 21 Aug 2016 21:01:34 -0700 [thread overview]
Message-ID: <1471838494-29672-1-git-send-email-JMax@mail.greenriver.edu> (raw)
This patch allows binfmt_misc to select the interpeter for arbitrary
binaries by comparing a specified registered keyword with the value
of a specified binary's extended attribute (user.binfmt.interp),
and then launching the program with the registered interpreter.
This is useful when wanting to launch a collection of binaries under
the same interpreter, even when they do not necessarily share a common
extension or magic bits, or when their magic conflics with the operation
of binfmt_elf. Some examples of its use would be to launch some executables
of various different architectures in a directory, or for running some
native binaries under a sandbox (like firejail) automatically during their
launch.
Signed-off-by: Josh Max <JMax@mail.greenriver.edu>
---
fs/binfmt_misc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 47 insertions(+), 4 deletions(-)
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 6103a63..86d93c7 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -24,6 +24,7 @@
#include <linux/mount.h>
#include <linux/syscalls.h>
#include <linux/fs.h>
+#include <linux/xattr.h>
#include <linux/uaccess.h>
#include "internal.h"
@@ -41,12 +42,17 @@ enum {
static LIST_HEAD(entries);
static int enabled = 1;
-enum {Enabled, Magic};
+enum {Enabled, Magic, Keyword};
#define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
#define MISC_FMT_OPEN_BINARY (1 << 30)
#define MISC_FMT_CREDENTIALS (1 << 29)
#define MISC_FMT_OPEN_FILE (1 << 28)
+#define XATTR_BINFMT_PREFIX XATTR_USER_PREFIX "binfmt."
+#define XATTR_BINFMT_INTERPRETER_SUFFIX "interp"
+#define XATTR_NAME_BINFMT (XATTR_BINFMT_PREFIX XATTR_BINFMT_INTERPRETER_SUFFIX)
+#define XATTR_VALUE_MAX_LENGTH 128
+
typedef struct {
struct list_head list;
unsigned long flags; /* type, status, etc. */
@@ -61,6 +67,7 @@ typedef struct {
} Node;
static DEFINE_RWLOCK(entries_lock);
+static int get_xattr_interp_keyword(struct file *file, char *buf, size_t count);
static struct file_system_type bm_fs_type;
static struct vfsmount *bm_mnt;
static int entry_count;
@@ -87,6 +94,8 @@ static int entry_count;
*/
static Node *check_file(struct linux_binprm *bprm)
{
+ char k[XATTR_VALUE_MAX_LENGTH];
+ int k_len = get_xattr_interp_keyword(bprm->file, k, sizeof(k)-1);
char *p = strrchr(bprm->interp, '.');
struct list_head *l;
@@ -100,6 +109,16 @@ static Node *check_file(struct linux_binprm *bprm)
if (!test_bit(Enabled, &e->flags))
continue;
+ /* Do matching based on xattrs keyword */
+ if (test_bit(Keyword, &e->flags)) {
+ if (k_len <= 0)
+ continue;
+ k[k_len] = 0;
+ if (!strcmp(e->magic, k))
+ return e;
+ continue;
+ }
+
/* Do matching based on extension if applicable. */
if (!test_bit(Magic, &e->flags)) {
if (p && !strcmp(e->magic, p + 1))
@@ -309,6 +328,20 @@ static char *check_special_flags(char *sfs, Node *e)
}
/*
+ * Check to see if the filesystem supports xattrs
+ * and grab the value so it can be checked against
+ * the list of keywords in binfmt_misc for a match
+ */
+static int get_xattr_interp_keyword(struct file *file, char *buf, size_t count)
+{
+
+ if (unlikely(!file->f_inode->i_op->getxattr))
+ return -ENOENT;
+ return file->f_inode->i_op->getxattr(file->f_path.dentry, file->f_inode,
+ XATTR_NAME_BINFMT, buf, count);
+}
+
+/*
* This registers a new binary format, it recognises the syntax
* ':name:type:offset:magic:mask:interpreter:flags'
* where the ':' is the IFS, that can be chosen with the first char
@@ -366,6 +399,10 @@ static Node *create_entry(const char __user *buffer, size_t count)
pr_debug("register: type: E (extension)\n");
e->flags = 1 << Enabled;
break;
+ case 'K':
+ pr_debug("register: type: K (xattrs keyword)\n");
+ e->flags = (1 << Enabled) | (1 << Keyword);
+ break;
case 'M':
pr_debug("register: type: M (magic)\n");
e->flags = (1 << Enabled) | (1 << Magic);
@@ -453,7 +490,7 @@ static Node *create_entry(const char __user *buffer, size_t count)
}
}
} else {
- /* Handle the 'E' (extension) format. */
+ /* Handle the 'E' (extension) and 'K' (keyword) format. */
/* Skip the 'offset' field. */
p = strchr(p, del);
@@ -469,7 +506,10 @@ static Node *create_entry(const char __user *buffer, size_t count)
*p++ = '\0';
if (!e->magic[0] || strchr(e->magic, '/'))
goto einval;
- pr_debug("register: extension: {%s}\n", e->magic);
+ if (test_bit(Keyword, &e->flags))
+ pr_debug("register: keyword: {%s}\n", e->magic);
+ else
+ pr_debug("register: extension: {%s}\n", e->magic);
/* Skip the 'mask' field. */
p = strchr(p, del);
@@ -563,7 +603,10 @@ static void entry_status(Node *e, char *page)
*dp++ = '\n';
if (!test_bit(Magic, &e->flags)) {
- sprintf(dp, "extension .%s\n", e->magic);
+ if (test_bit(Keyword, &e->flags))
+ sprintf(dp, "keyword %s\n", e->magic);
+ else
+ sprintf(dp, "extension .%s\n", e->magic);
} else {
dp += sprintf(dp, "offset %i\nmagic ", e->offset);
dp = bin2hex(dp, e->magic, e->size);
--
2.8.1
next reply other threads:[~2016-08-22 4:01 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-22 4:01 Josh Max [this message]
2016-08-25 16:15 ` [PATCH] binfmt_misc: allow selecting the interpreter based on xattr keywords James Bottomley
2016-08-26 8:00 ` Josh Max
2016-08-26 14:55 ` Florian Weimer
2016-08-26 17:59 ` Carlos O'Donell
2016-08-26 21:38 ` James Bottomley
2016-11-11 10:31 ` Alex Bennée
2016-08-26 21:12 ` One Thousand Gnomes
2016-08-26 21:26 ` James Bottomley
2016-08-27 11:52 ` One Thousand Gnomes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1471838494-29672-1-git-send-email-JMax@mail.greenriver.edu \
--to=jmax@mail.greenriver.edu \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).