From: Kees Cook <keescook@google.com>
To: Djalal Harouni <tixxdz@gmail.com>
Cc: "Serge E. Hallyn" <serge@hallyn.com>,
Rusty Russell <rusty@rustcorp.com.au>,
"David S . Miller" <davem@davemloft.net>,
Jessica Yu <jeyu@redhat.com>, LKML <linux-kernel@vger.kernel.org>,
Network Development <netdev@vger.kernel.org>,
linux-security-module <linux-security-module@vger.kernel.org>,
"kernel-hardening@lists.openwall.com"
<kernel-hardening@lists.openwall.com>,
Andy Lutomirski <luto@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
James Morris <james.l.morris@oracle.com>,
Paul Moore <paul@paul-moore.com>,
Stephen Smalley <sds@tycho.nsa.gov>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>,
Ingo Molnar <mingo@kernel.org>,
Linux API <linux-api@vger.kernel.org>, Dongsu Park <dpar>
Subject: Re: [PATCH v4 next 1/3] modules:capabilities: allow __request_module() to take a capability argument
Date: Tue, 30 May 2017 10:59:06 -0700 [thread overview]
Message-ID: <CAGXu5jK5exWBV+ub8ys86Ubu1vKwN=miOZxwp3zdWaWEfuJddQ@mail.gmail.com> (raw)
In-Reply-To: <CAEiveUeZhHtPyLv8=3BsPh5Anr2ynnzD0bprUkeKUGygtRQKsw@mail.gmail.com>
On Wed, May 24, 2017 at 7:16 AM, Djalal Harouni <tixxdz@gmail.com> wrote:
> On Tue, May 23, 2017 at 9:19 PM, Kees Cook <keescook@google.com> wrote:
>> On Tue, May 23, 2017 at 3:29 AM, Djalal Harouni <tixxdz@gmail.com> wrote:
>> Even in the existing code, there is a sense about CAP_NET_ADMIN and
>> CAP_SYS_MODULE having different privilege levels, in that
>> CAP_NET_ADMIN can only load netdev-%s modules, but CAP_SYS_MODULE can
>> load any module. What about refining request_module_cap() to _require_
>> an explicit string prefix instead of an arbitrary format string? e.g.
>> request_module_cap(CAP_NET_ADMIN, "netdev", "%s", name) which would
>> make requests for ("netdev-%s", name)
>>
>> I see a few options:
>>
>> 1) keep what you have for v4, and hope other places don't use
>> __request_module. (I'm not a fan of this.)
>
> Yes even if it is documented I wouldn't bet on it, though. :-)
Okay, we seem to agree: we'll not use #1.
>> 2) switch the logic on autoload==1 from OR to AND: both the specified
>> caps _and_ CAP_SYS_MODULE are required. (This seems like it might make
>> autoload==1 less useful.)
>
> That will restrict some userspace that works only with CAP_NET_ADMIN.
Nor #2.
>> 3) use the request_module_cap() outlined above, which requires that
>> modules being loaded under a CAP_SYS_MODULE-aliased capability are at
>> least restricted to a subset of kernel module names.
>
> This one tends to allow usability.
Right, discussed below...
>> 4) same as 3 but also insert autoload==2 level that switches from OR
>> to AND (bumping existing ==2 to ==3).
>
> I wouldn't expose autoload to callers, I think it is better if it
> stays a property of the module subsystem. But lets use the bump idea,
> please see below.
If we can't agree below, I think #4 would be a good way to allow for
both states.
>> What do you think?
>
> Ok so given that we already have modules_autoload_mode=2 disabled,
> maybe we go with 3) like this ?
>
> int __request_module(bool wait, int required_cap, const char *prefix,
> const char *name, ...);
> #define request_module(mod...) \
> __request_module(true, -1, NULL, mod)
> #define request_module_cap(required_cap, prefix, mod...) \
> __request_module(true, required_cap, prefix, mod)
>
> and we require allow_cap and prefix to be set.
>
> request_module_cap(CAP_NET_ADMIN, "netdev-", "%s", name) for
> net/core/dev_ioctl.c:dev_load()
>
> request_module_cap(CAP_NET_ADMIN, "tcp_", "%s", name) for
> net/ipv4/tcp_cong.c functions.
>
>
> Then
> __request_module()
> -> security_kernel_module_request(module_name, required_cap, prefix)
> -> may_autoload_module(current, module_name, required_cap, prefix)
>
>
> And update may_autoload_module() as below ? we hard code CAP_NET_ADMIN
> and CAP_SYS_MODULE inside and make them the only capabilities needed
> for a privileged auto-load operation.
I still think making a specific exception for CAP_NET_ADMIN is not the
right solution, instead allowing for non-CAP_SYS_MODULE caps when
using a distinct prefix.
> request_module_cap(CAP_SYS_MODULE, ...) or
> request_module_cap(CAP_NET_ADMIN, ...) if the autoload should be a
> privileged operation.
>
> Kees will this work ?
>
> Jessica, Rusty, Serge. What do you think ? I definitively think that
> module_autoload should be contained only inside the module subsystem..
I'd change it like this:
> +int may_autoload_module(struct task_struct *task, char *kmod_name,
> + int require_cap, char *prefix)
> +{
> + unsigned int autoload;
> + int module_require_cap = 0;
I'd initialize this to module_require_cap = CAP_SYS_MODULE;
> +
> + if (require_cap > 0) {
> + if (prefix == NULL || *prefix == '\0')
> + return -EPERM;
Since an unprefixed module load should only be CAP_SYS_MODULE, change
the above "if" to:
if (require_cap > 0 && prefix != NULL && *prefix != '\0')
> +
> + /*
> + * We only allow CAP_SYS_MODULE or CAP_NET_ADMIN for
> + * 'netdev-%s' modules for backward compatibility.
> + * Please do not overload capabilities.
> + */
> + if (require_cap == CAP_SYS_MODULE ||
> + require_cap == CAP_NET_ADMIN)
> + module_require_cap = require_cap;
> + else
> + return -EPERM;
> + }
And then drop all these checks, leaving only:
module_require_cap = require_cap;
> +
> + /* Get max value of sysctl and task "modules_autoload_mode" */
> + autoload = max_t(unsigned int, modules_autoload_mode,
> + task->modules_autoload_mode);
> +
> + /*
> + * If autoload is disabled then fail here and not bother at all
> + */
> + if (autoload == MODULES_AUTOLOAD_DISABLED)
> + return -EPERM;
> +
> + /*
> + * If caller require capabilities then we may not allow
> + * automatic module loading. We should not bypass callers.
> + * This allows to support networking code that uses CAP_NET_ADMIN
> + * for some aliased 'netdev-%s' modules.
> + *
> + * Explicitly bump autoload here if necessary
> + */
> + if (module_require_cap && autoload == MODULES_AUTOLOAD_ALLOWED)
> + autoload = MODULES_AUTOLOAD_PRIVILEGED;
I don't see a reason to bump the autoload level.
> +
> + if (autoload == MODULES_AUTOLOAD_ALLOWED)
> + return 0;
This test can be moved to above the AUTOLOAD_DISABLED test.
> + else if(autoload == MODULES_AUTOLOAD_PRIVILEGED) {
> + /*
> + * If module auto-load is a privileged operation then check
> + * if capabilities are set.
> + */
> + if (capable(CAP_SYS_MODULE) ||
> + (module_require_cap && capable(module_require_cap)))
> + return 0;
> + }
This test could drop the explicit CAP_SYS_MODULE test and just rely on
module_require_cap.
> +
> + return -EPERM;
> +}
> +
So, I would suggest:
int may_autoload_module(struct task_struct *task, char *kmod_name,
int require_cap, char *prefix)
{
unsigned int autoload;
int module_require_cap;
if (autoload == MODULES_AUTOLOAD_DISABLED)
return -EPERM;
/* Get max value of sysctl and task "modules_autoload_mode" */
autoload = max_t(unsigned int, modules_autoload_mode,
task->modules_autoload_mode);
if (autoload == MODULES_AUTOLOAD_ALLOWED)
return 0;
/*
* It should be impossible for autoload to have any other
* value at this point, so explicitly reject all other states.
*/
if (autoload != MODULES_AUTOLOAD_PRIVILEGED)
return -EPERM;
/* Verify that alternate capabilities requirements had a prefix. */
if (require_cap > 0 && prefix != NULL && *prefix != '\0')
module_require_cap = require_cap;
else
module_require_cap = CAP_SYS_MODULE;
return capable(module_require_cap);
}
-Kees
--
Kees Cook
Pixel Security
next prev parent reply other threads:[~2017-05-30 17:59 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-22 11:57 [PATCH v4 next 0/3] modules: automatic module loading restrictions Djalal Harouni
2017-05-22 11:57 ` [PATCH v4 next 1/3] modules:capabilities: allow __request_module() to take a capability argument Djalal Harouni
2017-05-22 22:20 ` Kees Cook
2017-05-23 10:29 ` Djalal Harouni
2017-05-23 19:19 ` Kees Cook
2017-05-24 14:16 ` Djalal Harouni
2017-05-30 17:59 ` Kees Cook [this message]
2017-06-01 14:56 ` Djalal Harouni
2017-06-01 19:10 ` Kees Cook
2017-09-02 6:31 ` Djalal Harouni
2017-05-22 11:57 ` [PATCH v4 next 2/3] modules:capabilities: automatic module loading restriction Djalal Harouni
2017-05-22 22:28 ` Kees Cook
2017-05-22 11:57 ` [PATCH v4 next 3/3] modules:capabilities: add a per-task modules auto-load mode Djalal Harouni
2017-05-23 14:18 ` kbuild test robot
2017-05-22 12:08 ` [PATCH v4 next 0/3] modules: automatic module loading restrictions Solar Designer
[not found] ` <20170522120848.GA3003-cxoSlKxDwOJWk0Htik3J/w@public.gmane.org>
2017-05-22 13:49 ` [kernel-hardening] " Djalal Harouni
[not found] ` <CAEiveUdqfMk4+vLg6TaEJNSGwoQHxYq0P4aqZoL4i9GgR3Vdtw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-05-22 16:43 ` Solar Designer
[not found] ` <20170522164323.GA2048-cxoSlKxDwOJWk0Htik3J/w@public.gmane.org>
2017-05-22 19:55 ` Djalal Harouni
2017-05-22 23:07 ` Kees Cook
2017-05-22 23:38 ` Andy Lutomirski
2017-05-22 23:52 ` Kees Cook
2017-05-23 13:02 ` Djalal Harouni
2017-05-23 7:48 ` [kernel-hardening] " Solar Designer
[not found] ` <20170523074808.GA4562-cxoSlKxDwOJWk0Htik3J/w@public.gmane.org>
2017-05-23 18:36 ` Kees Cook
2017-05-23 19:50 ` Andy Lutomirski
2017-05-24 18:06 ` Djalal Harouni
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='CAGXu5jK5exWBV+ub8ys86Ubu1vKwN=miOZxwp3zdWaWEfuJddQ@mail.gmail.com' \
--to=keescook@google.com \
--cc=akpm@linux-foundation.org \
--cc=davem@davemloft.net \
--cc=gregkh@linuxfoundation.org \
--cc=james.l.morris@oracle.com \
--cc=jeyu@redhat.com \
--cc=kernel-hardening@lists.openwall.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=penguin-kernel@i-love.sakura.ne.jp \
--cc=rusty@rustcorp.com.au \
--cc=sds@tycho.nsa.gov \
--cc=serge@hallyn.com \
--cc=tixxdz@gmail.com \
/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).