From: zohar@linux.vnet.ibm.com (Mimi Zohar)
To: linux-security-module@vger.kernel.org
Subject: [PATCH v1] shebang: restrict python interactive prompt/interpreter
Date: Fri, 09 Jun 2017 11:06:06 -0400 [thread overview]
Message-ID: <1497020766.21594.239.camel@linux.vnet.ibm.com> (raw)
In-Reply-To: <201706092302.HCE57804.OSFJFVtMLOQHFO@I-love.SAKURA.ne.jp>
On Fri, 2017-06-09 at 23:02 +0900, Tetsuo Handa wrote:
> Mimi Zohar wrote:
> > This patch defines a new, minor LSM named "shebang", that restricts
> > python such that scripts are allowed to execute, while the interactive
> > prompt/interpreter is not available. When used in conjunction with an
> > IMA appraise execute policy requiring files signatures, only signed
> > python scripts would be allowed to execute. (A separate method for
> > identifying "imported" code would need to be defined in order to verify
> > their file signatures.)
>
> Below case is blocked by IMA?
>
> $ cp -p /usr/bin/python2 /tmp
> $ /tmp/python2
>
> Below case is also blocked by IMA?
>
> $ echo '#!/usr/bin/python2 -' > /tmp/run-python
> $ chmod +x /tmp/run-python
> $ /tmp/run-python
>
> What about execution via ld-linux ?
>
> $ /lib64/ld-linux-x86-64.so.2 /usr/bin/python2
Assuming that you require file signatures on anything that is
executed, then only signed binaries, with the public key loaded on to
the IMA keyring, would be executed.
> > +#define MAX_INODES 6
> > +static char *pathnames;
> > +static int pathnames_len;
> > +static unsigned long inode_list[MAX_INODES];
> > +static int total;
> > +
> > +/*
> > + * Get the inodes associated with the list of pathnames, as specified
> > + * on CONFIG_SECURITY_SHEBANG_PATHNAME.
> > + */
> > +static void init_inode_list(void)
> > +{
> > + char *tmp_pathnames = pathnames;
> > + char *p;
> > + struct path path;
> > + int i;
> > + int ret;
> > +
> > + total = 0;
> > + while ((p = strsep(&tmp_pathnames, " ,")) != NULL) {
> > + if ((*p == '\0') || (*p == ' ') || (*p == ','))
> > + continue;
> > +
> > + if (total > MAX_INODES - 1) {
> > + pr_info("too many interpreters\n");
> > + break;
> > + }
> > +
> > + ret = kern_path(p, LOOKUP_FOLLOW, &path);
> > + if (!ret) {
> > + struct inode *inode = d_backing_inode(path.dentry);
> > +
> > + inode_list[total] = inode->i_ino;
> > + pr_info("pathname:%s i_ino: %lu\n",
> > + p, inode_list[total]);
>
> Leaking reference to "struct path".
kern_path() is calling "getname_kernel(name)", but that is later
freed. ?I'm not seeing it. ?What are you referring to?
??
> > + initialized = 1;
> > + total++;
> > + }
> > + }
> > +
> > + /* cleanup in case we need to lookup the inodes again. */
> > + tmp_pathnames = pathnames;
> > + for (i = 0; i < pathnames_len; i++)
> > + if (tmp_pathnames[i] == '\0')
> > + tmp_pathnames[i] = ' ';
>
> Why need to restore?
The patch description just mentions replacing the list of pathnames
with a set of inodes, but doesn't go into the implications of this
change. ?When the interpreter package is updated, the list of inodes
would need to be updated as well.
Some method for updating the list of inodes would be needed. ?Probably
the security_inode_unlink and security_inode_rename hooks would be a
good place to trigger the inode list update.
> > +}
> > +
> > +/**
> > + * shebang_bprm_check - prevent python interactive prompt/interpreter
> > + * @bprm: contains the linux_binprm structure
> > + *
> > + * Restrict python such that scripts are allowed to execute, while the
> > + * interactive prompt/interpreter is not available.
> > + */
> > +static int shebang_bprm_check(struct linux_binprm *bprm)
> > +{
> > + struct inode *inode = file_inode(bprm->file);
> > + int i = 0;
> > +
> > + if (bprm->interp != bprm->filename) /* allow scripts */
> > + return 0;
> > +
> > + if (!initialized)
> > + init_inode_list();
>
> init_inode_list() can be called concurrently.
Good catch. ?Thank you.
Mimi
>
> > +
> > + while (i < total) {
> > + if (inode_list[i++] != inode->i_ino)
> > + continue;
> > +
> > + pr_info("prevent executing %s (ino=%lu)\n",
> > + bprm->interp, inode->i_ino);
> > + return -EPERM;
> > + }
> > + return 0;
> > +}
> > +
> > +static struct security_hook_list shebang_hooks[] = {
> > + LSM_HOOK_INIT(bprm_check_security, shebang_bprm_check)
> > +};
> > +
> > +static int __init init_shebang(void)
> > +{
> > + pathnames = kstrdup(CONFIG_SECURITY_SHEBANG_PATHNAME, GFP_KERNEL);
> > + if (!pathnames)
> > + return -ENOMEM;
> > + pathnames_len = strlen(pathnames);
>
> Why need to kstrdup()?
>
> static char pathnames[] = CONFIG_SECURITY_SHEBANG_PATHNAME;
> static int pathnames_len = sizeof(pathnames) - 1;
>
> will be fine.
>
> > +
> > + security_add_hooks(shebang_hooks, ARRAY_SIZE(shebang_hooks), "shebang");
> > + pr_info("initialized\n");
> > + return 0;
> > +}
> > +
> > +late_initcall(init_shebang);
> > +MODULE_LICENSE("GPL");
>
> Nice example for loading as a LKM-based LSM. ;-)
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2017-06-09 15:06 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-09 13:22 [PATCH v1] shebang: restrict python interactive prompt/interpreter Mimi Zohar
2017-06-09 14:02 ` Tetsuo Handa
2017-06-09 14:50 ` Matt Brown
2017-06-09 15:41 ` Tetsuo Handa
2017-06-09 16:37 ` Matt Brown
2017-06-09 16:43 ` Jason Zaman
2017-06-09 17:23 ` Matt Brown
2017-06-09 23:04 ` Tetsuo Handa
2017-06-10 1:56 ` Kees Cook
2017-06-10 5:27 ` Tetsuo Handa
2017-06-12 0:34 ` Matt Brown
[not found] ` <d9aca46b-97c6-4faf-b559-484feb4aa640@digikod.net>
2017-06-12 2:32 ` Mimi Zohar
2017-06-12 14:27 ` Mimi Zohar
2017-06-14 14:10 ` Alan Cox
2017-06-14 20:37 ` [kernel-hardening] " Boris Lukashev
[not found] ` <8a2300ef-1462-0e1f-2d6a-81e6020bc71f@digikod.net>
2017-06-13 21:44 ` Casey Schaufler
2017-06-10 1:49 ` Tetsuo Handa
2017-06-09 15:06 ` Mimi Zohar [this message]
2017-06-09 15:23 ` Tetsuo Handa
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=1497020766.21594.239.camel@linux.vnet.ibm.com \
--to=zohar@linux.vnet.ibm.com \
--cc=linux-security-module@vger.kernel.org \
/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).