* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Josh Triplett @ 2014-11-16 19:09 UTC (permalink / raw)
To: Theodore Ts'o, Eric W. Biederman, Andy Lutomirski,
Andrew Morton, Kees Cook, Michael Kerrisk-manpages, Linux API,
linux-man, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20141116133230.GA32030-AKGzg7BKzIDYtjvyW6yDsg@public.gmane.org>
On Sun, Nov 16, 2014 at 08:32:30AM -0500, Theodore Ts'o wrote:
> On Sat, Nov 15, 2014 at 09:08:07PM -0600, Eric W. Biederman wrote:
> > That may be a bug with the user namespace permission check. Perhaps we
> > shouldn't allow dropping groups that aren't mapped in the user
> > namespace.
>
> I'm not saying that we can't change the behavior of whether or not a
> user can drop a group permission. I'm just saying that we need to do
> so consciously.
Agreed.
> The setgroups()/getgroups() ABI isn't part of
> POSIX/SuSv3 so we wouldn't be breaking POSIX compatibility, for those
> people who care about that.
POSIX.1-2001 actually specifies getgroups, but not setgroups. In any
case, yes, POSIX doesn't say anything about this behavior.
> The bigger deal is that it's very different from how BSD 4.x has
> handled things, which means there is two decades of history that we're
> looking at here. And there are times when taking away permissions in
> an expected fashion can cause security problems. (As a silly example;
> some architect at Digital wrote a spec that said that setuid must
> return EINVAL for values greater than 32k --- back in the days when
> uid's were a signed short. The junior programmer who implemented this
> for Ultrix made the check for 32,000 decimal. Guess what happened
> when /bin/login got a failure with setuid when it wasn't expecting one
> --- since root could never get an error with that system call, right?
Ignored it and kept going, starting the user's shell as root?
I'd guess that a similar story motivated the note in the Linux manpages
for setuid, setresuid, and similar, saying "Note: there are cases where
setuid() can fail even when the caller is UID 0; it is a grave security
error to omit checking for a failure return from setuid().".
(Also, these days, glibc marks setuid and similar with the
warn_unused_result attribute.)
> And MIT Project Athena started ran out of lower numbered uid's and
> froshlings started getting assigned uid's > 32,000....)
>
> In this particular case, the change is probably a little less likely
> to cause serious problems, although the fact that sudo does allow
> negative group assignments is an example of another potential
> breakage.
>
> OTOH, I'm aware of how this could cause major problems to the concept
> of allowing an untrusted user to set up their own containers to
> constrain what program with a possibly untrusted provinance might be
> able to do. I can see times when I might want to run in a container
> where the user didn't have access to groups that I have access to by
> default --- including groups such as disk, sudo, lpadmin, etc.
>
> If we do want to make such a change, my suggestion is to keep things
> *very* simple. Let it be a boot-time option whether or not users are
> allowed to drop group permissions, and let it affect all possible ways
> that users can drop groups. And we can create a shell script that
> will search for the obvious ways that a user could get screwed by
> enabling this, which we can encourage distributions to package up for
> their end users. And then we document the heck out of the fact that
> this option exists, and when/if we want to make it the default, so
> it's perfectly clear and transparent to all what is happening.
An option sounds sensible to me. I think a sysctl makes more sense,
though. I'll add one in v4.
What did you have in mind about the shell script? Something like:
grep -r !% /etc/sudoers /etc/sudoers.d
?
- Josh Triplett
^ permalink raw reply
* Re: [PATCH v2 net-next 6/7] bpf: allow eBPF programs to use maps
From: David Miller @ 2014-11-16 19:04 UTC (permalink / raw)
To: ast-uqk4Ao+rVK5Wk0Htik3J/w
Cc: mingo-DgEjT+Ai2ygdnm+yROfE0A, luto-kltTT9wpgjJwATOyAt5JVQ,
dborkman-H+wXaHxf7aLQT0dZR+AlfA,
hannes-tFNcAqjVMyqKXQKiL6tip0B+6BGkLq7r,
edumazet-hpIqsD4AKlfQT0dZR+AlfA, linux-api-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1415929010-9361-7-git-send-email-ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org>
From: Alexei Starovoitov <ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org>
Date: Thu, 13 Nov 2014 17:36:49 -0800
> +static u64 bpf_map_lookup_elem(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> +{
> + /* verifier checked that R1 contains a valid pointer to bpf_map
> + * and R2 points to a program stack and map->key_size bytes were
> + * initialized
> + */
> + struct bpf_map *map = (struct bpf_map *) (unsigned long) r1;
> + void *key = (void *) (unsigned long) r2;
> + void *value;
> +
> + WARN_ON_ONCE(!rcu_read_lock_held());
> +
> + value = map->ops->map_lookup_elem(map, key);
> +
> + /* lookup() returns either pointer to element value or NULL
> + * which is the meaning of PTR_TO_MAP_VALUE_OR_NULL type
> + */
> + return (unsigned long) value;
> +}
You should translate this into a true boolean '1' or '0' value so that
kernel pointers don't propagate to the user or his eBPF programs.
^ permalink raw reply
* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Andy Lutomirski @ 2014-11-16 15:42 UTC (permalink / raw)
To: Theodore Ts'o, Eric W. Biederman, Josh Triplett,
Andy Lutomirski, Andrew Morton, Kees Cook,
Michael Kerrisk-manpages, Linux API, linux-man,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20141116133230.GA32030-AKGzg7BKzIDYtjvyW6yDsg@public.gmane.org>
On Sun, Nov 16, 2014 at 5:32 AM, Theodore Ts'o <tytso-3s7WtUTddSA@public.gmane.org> wrote:
> On Sat, Nov 15, 2014 at 09:08:07PM -0600, Eric W. Biederman wrote:
>>
>> That may be a bug with the user namespace permission check. Perhaps we
>> shouldn't allow dropping groups that aren't mapped in the user
>> namespace.
>
> I'm not saying that we can't change the behavior of whether or not a
> user can drop a group permission. I'm just saying that we need to do
> so consciously. The setgroups()/getgroups() ABI isn't part of
> POSIX/SuSv3 so we wouldn't be breaking POSIX compatibility, for those
> people who care about that.
It may make sense to reach out to some place like oss-security.
FWIW, I think we should ask, at the same time, about:
- Dropping supplementary groups.
- Switching gid/egid/sgid to a supplementary group.
- Denying ptrace of a process with supplementary groups that the
tracer doesn't have.
Also, I much prefer a sysctl to a boot option. Boot options are nasty
to configure in many distributions.
--Andy
>
> The bigger deal is that it's very different from how BSD 4.x has
> handled things, which means there is two decades of history that we're
> looking at here. And there are times when taking away permissions in
> an expected fashion can cause security problems. (As a silly example;
> some architect at Digital wrote a spec that said that setuid must
> return EINVAL for values greater than 32k --- back in the days when
> uid's were a signed short. The junior programmer who implemented this
> for Ultrix made the check for 32,000 decimal. Guess what happened
> when /bin/login got a failure with setuid when it wasn't expecting one
> --- since root could never get an error with that system call, right?
> And MIT Project Athena started ran out of lower numbered uid's and
> froshlings started getting assigned uid's > 32,000....)
>
> In this particular case, the change is probably a little less likely
> to cause serious problems, although the fact that sudo does allow
> negative group assignments is an example of another potential
> breakage.
>
> OTOH, I'm aware of how this could cause major problems to the concept
> of allowing an untrusted user to set up their own containers to
> constrain what program with a possibly untrusted provinance might be
> able to do. I can see times when I might want to run in a container
> where the user didn't have access to groups that I have access to by
> default --- including groups such as disk, sudo, lpadmin, etc.
>
> If we do want to make such a change, my suggestion is to keep things
> *very* simple. Let it be a boot-time option whether or not users are
> allowed to drop group permissions, and let it affect all possible ways
> that users can drop groups. And we can create a shell script that
> will search for the obvious ways that a user could get screwed by
> enabling this, which we can encourage distributions to package up for
> their end users. And then we document the heck out of the fact that
> this option exists, and when/if we want to make it the default, so
> it's perfectly clear and transparent to all what is happening.
>
> One of the things that scare me about the addition of the forced
> capability "setuid" binary was that the feature was just silently slid
> in, and we didn't do a good job reaching out to the tripwire and
> rootkit and other such programs out there, such that several years
> after we enabled capability support, most sysadmins and security
> scanning programs are still apparently obivious to the this very
> convenient feature that we gave to rootkit and malware authors. Now
> we can say that we're just adding new features, and we owe no debt
> other parts of the ecosystem --- this is the attitude used by upower
> and other freedesktop.org components when they made incompatible
> changes made available by new features provided by systemd[1].
>
> [1] http://m.memegen.com/u7o1tk.jpg
>
> But as kernel developers, who pride ourselves on not breaking
> userspace, I think we should try for a higher standard than this. And
> perhaps this change with allowing groups to be dropped --- which is
> admittedly a useful thing to be able to allow --- is a good place to
> start trying to model a better way of doing things. We should try to
> be responsible about how we add new features, and think of all of the
> potential downstream consequences to the _all_ of the ecosystem.
>
> - Ted
>
> P.S. And we really should try reaching out to the security scanners
> about capabilities, too....
--
Andy Lutomirski
AMA Capital Management, LLC
^ permalink raw reply
* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Theodore Ts'o @ 2014-11-16 13:32 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Josh Triplett, Andy Lutomirski, Andrew Morton, Kees Cook,
Michael Kerrisk-manpages, Linux API, linux-man,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <87vbmfq1uw.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
On Sat, Nov 15, 2014 at 09:08:07PM -0600, Eric W. Biederman wrote:
>
> That may be a bug with the user namespace permission check. Perhaps we
> shouldn't allow dropping groups that aren't mapped in the user
> namespace.
I'm not saying that we can't change the behavior of whether or not a
user can drop a group permission. I'm just saying that we need to do
so consciously. The setgroups()/getgroups() ABI isn't part of
POSIX/SuSv3 so we wouldn't be breaking POSIX compatibility, for those
people who care about that.
The bigger deal is that it's very different from how BSD 4.x has
handled things, which means there is two decades of history that we're
looking at here. And there are times when taking away permissions in
an expected fashion can cause security problems. (As a silly example;
some architect at Digital wrote a spec that said that setuid must
return EINVAL for values greater than 32k --- back in the days when
uid's were a signed short. The junior programmer who implemented this
for Ultrix made the check for 32,000 decimal. Guess what happened
when /bin/login got a failure with setuid when it wasn't expecting one
--- since root could never get an error with that system call, right?
And MIT Project Athena started ran out of lower numbered uid's and
froshlings started getting assigned uid's > 32,000....)
In this particular case, the change is probably a little less likely
to cause serious problems, although the fact that sudo does allow
negative group assignments is an example of another potential
breakage.
OTOH, I'm aware of how this could cause major problems to the concept
of allowing an untrusted user to set up their own containers to
constrain what program with a possibly untrusted provinance might be
able to do. I can see times when I might want to run in a container
where the user didn't have access to groups that I have access to by
default --- including groups such as disk, sudo, lpadmin, etc.
If we do want to make such a change, my suggestion is to keep things
*very* simple. Let it be a boot-time option whether or not users are
allowed to drop group permissions, and let it affect all possible ways
that users can drop groups. And we can create a shell script that
will search for the obvious ways that a user could get screwed by
enabling this, which we can encourage distributions to package up for
their end users. And then we document the heck out of the fact that
this option exists, and when/if we want to make it the default, so
it's perfectly clear and transparent to all what is happening.
One of the things that scare me about the addition of the forced
capability "setuid" binary was that the feature was just silently slid
in, and we didn't do a good job reaching out to the tripwire and
rootkit and other such programs out there, such that several years
after we enabled capability support, most sysadmins and security
scanning programs are still apparently obivious to the this very
convenient feature that we gave to rootkit and malware authors. Now
we can say that we're just adding new features, and we owe no debt
other parts of the ecosystem --- this is the attitude used by upower
and other freedesktop.org components when they made incompatible
changes made available by new features provided by systemd[1].
[1] http://m.memegen.com/u7o1tk.jpg
But as kernel developers, who pride ourselves on not breaking
userspace, I think we should try for a higher standard than this. And
perhaps this change with allowing groups to be dropped --- which is
admittedly a useful thing to be able to allow --- is a good place to
start trying to model a better way of doing things. We should try to
be responsible about how we add new features, and think of all of the
potential downstream consequences to the _all_ of the ecosystem.
- Ted
P.S. And we really should try reaching out to the security scanners
about capabilities, too....
^ permalink raw reply
* [PATCH v2] [media] Add RGB444_1X12 and RGB565_1X16 media bus formats
From: Boris Brezillon @ 2014-11-16 8:24 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Hans Verkuil, Laurent Pinchart,
linux-media-u79uwXL29TY76Z2rM5mHXA
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, Boris Brezillon
Add RGB444_1X12 and RGB565_1X16 format definitions and update the
documentation.
Signed-off-by: Boris Brezillon <boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Acked-by: Mauro Carvalho Chehab <mchehab-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
---
Changes since v1:
- keep BPP and bits per sample ordering
Documentation/DocBook/media/v4l/subdev-formats.xml | 40 ++++++++++++++++++++++
include/uapi/linux/media-bus-format.h | 4 ++-
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml
index 18730b9..0d6f731 100644
--- a/Documentation/DocBook/media/v4l/subdev-formats.xml
+++ b/Documentation/DocBook/media/v4l/subdev-formats.xml
@@ -176,6 +176,24 @@
</row>
</thead>
<tbody valign="top">
+ <row id="MEDIA-BUS-FMT-RGB444-1X12">
+ <entry>MEDIA_BUS_FMT_RGB444_1X12</entry>
+ <entry>0x100d</entry>
+ <entry></entry>
+ &dash-ent-20;
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ </row>
<row id="MEDIA-BUS-FMT-RGB444-2X8-PADHI-BE">
<entry>MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE</entry>
<entry>0x1001</entry>
@@ -288,6 +306,28 @@
<entry>g<subscript>4</subscript></entry>
<entry>g<subscript>3</subscript></entry>
</row>
+ <row id="MEDIA-BUS-FMT-RGB565-1X16">
+ <entry>MEDIA_BUS_FMT_RGB565_1X16</entry>
+ <entry>0x100d</entry>
+ <entry></entry>
+ &dash-ent-16;
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ </row>
<row id="MEDIA-BUS-FMT-BGR565-2X8-BE">
<entry>MEDIA_BUS_FMT_BGR565_2X8_BE</entry>
<entry>0x1005</entry>
diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
index 23b4090..37091c6 100644
--- a/include/uapi/linux/media-bus-format.h
+++ b/include/uapi/linux/media-bus-format.h
@@ -33,11 +33,13 @@
#define MEDIA_BUS_FMT_FIXED 0x0001
-/* RGB - next is 0x100e */
+/* RGB - next is 0x1010 */
+#define MEDIA_BUS_FMT_RGB444_1X12 0x100e
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE 0x1003
#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE 0x1004
+#define MEDIA_BUS_FMT_RGB565_1X16 0x100f
#define MEDIA_BUS_FMT_BGR565_2X8_BE 0x1005
#define MEDIA_BUS_FMT_BGR565_2X8_LE 0x1006
#define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] [media] Add RGB444_1X12 and RGB565_1X16 media bus formats
From: Boris Brezillon @ 2014-11-16 8:19 UTC (permalink / raw)
To: Sakari Ailus
Cc: Mauro Carvalho Chehab, Hans Verkuil, Laurent Pinchart,
linux-media, linux-api, linux-kernel, linux-doc
In-Reply-To: <546767FD.2080706@iki.fi>
On Sat, 15 Nov 2014 16:49:33 +0200
Sakari Ailus <sakari.ailus@iki.fi> wrote:
> Hi Boris,
>
> Boris Brezillon wrote:
> > Hi Sakari,
> >
> > On Fri, 14 Nov 2014 15:58:31 +0200
> > Sakari Ailus <sakari.ailus@iki.fi> wrote:
> >
> >> Hi Boris,
> >>
> >> On Fri, Nov 14, 2014 at 11:36:00AM +0100, Boris Brezillon wrote:
> ...
> >>> diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
> >>> index 23b4090..cc7b79e 100644
> >>> --- a/include/uapi/linux/media-bus-format.h
> >>> +++ b/include/uapi/linux/media-bus-format.h
> >>> @@ -33,7 +33,7 @@
> >>>
> >>> #define MEDIA_BUS_FMT_FIXED 0x0001
> >>>
> >>> -/* RGB - next is 0x100e */
> >>> +/* RGB - next is 0x1010 */
> >>> #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
> >>> #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
> >>> #define MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE 0x1003
> >>> @@ -47,6 +47,8 @@
> >>> #define MEDIA_BUS_FMT_RGB888_2X12_BE 0x100b
> >>> #define MEDIA_BUS_FMT_RGB888_2X12_LE 0x100c
> >>> #define MEDIA_BUS_FMT_ARGB8888_1X32 0x100d
> >>> +#define MEDIA_BUS_FMT_RGB444_1X12 0x100e
> >>> +#define MEDIA_BUS_FMT_RGB565_1X16 0x100f
> >>
> >> I'd arrange these according to BPP and bits per sample, both in the header
> >> and documentation.
> >
> > I cannot keep both macro values and BPP/bits per sample in incrementing
> > order. Are you sure you prefer to order macros in BPP/bits per sample
> > order ?
>
> If you take a look elsewhere in the header, you'll notice that the
> ordering has preferred the BPP value (and other values with semantic
> significance) over the numeric value of the definition. I'd just prefer
> to keep it that way. This is also why the "next is" comments are there.
>
My bad, I only had a look at RGB formats.
I'll fix that.
Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH] Add supplementary UIDs, and getusers/setusers system calls
From: Josh Triplett @ 2014-11-16 7:41 UTC (permalink / raw)
To: Andrew Morton, Theodore Ts'o, Kees Cook,
mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-man-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <6b6bef0eb7328d466e8deef3d2c186a79633e0a7.1416121601.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
On Sat, Nov 15, 2014 at 11:08:31PM -0800, Josh Triplett wrote:
> asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist);
> +asmlinkage long sys_setusers(int uidsetsize, uid_t __user *grouplist);
Obvious typo here: s/grouplist/userlist/. Will fix in a v2, but I'll
wait for other feedback on v1 first.
- Josh Triplett
^ permalink raw reply
* [PATCH manpages] Document supplementary user IDs
From: Josh Triplett @ 2014-11-16 7:08 UTC (permalink / raw)
To: Andrew Morton, Theodore Ts'o, Kees Cook, mtk.manpages,
linux-api, linux-man, linux-kernel
In-Reply-To: <6b6bef0eb7328d466e8deef3d2c186a79633e0a7.1416121601.git.josh@joshtriplett.org>
Add new manpages for getusers(2) and setusers(2). Discuss supplementary
UIDs in credentials(7). Update manpages for seteuid(2), setfsuid(2),
setresuid(2), setreuid(2), and setuid(2).
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
---
man2/getusers.2 | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++
man2/seteuid.2 | 10 ++-
man2/setfsuid.2 | 4 +-
man2/setresuid.2 | 8 ++-
man2/setreuid.2 | 12 +++-
man2/setuid.2 | 7 ++-
man2/setusers.2 | 1 +
man7/credentials.7 | 21 ++++++-
8 files changed, 229 insertions(+), 11 deletions(-)
create mode 100644 man2/getusers.2
create mode 100644 man2/setusers.2
diff --git a/man2/getusers.2 b/man2/getusers.2
new file mode 100644
index 0000000..e5dd371
--- /dev/null
+++ b/man2/getusers.2
@@ -0,0 +1,177 @@
+.\" Copyright 2014 Josh Triplett <josh@joshtriplett.org>
+.\" Based on getgroups.2:
+.\" Copyright 1993 Rickard E. Faith (faith@cs.unc.edu)
+.\"
+.\" %%%LICENSE_START(VERBATIM)
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\" %%%LICENSE_END
+.\"
+.\" Modified Thu Oct 31 12:04:29 1996 by Eric S. Raymond <esr@thyrsus.com>
+.\" Modified, 27 May 2004, Michael Kerrisk <mtk.manpages@gmail.com>
+.\" Added notes on capability requirements
+.\" 2008-05-03, mtk, expanded and rewrote parts of DESCRIPTION and RETURN
+.\" VALUE, made style of page more consistent with man-pages style.
+.\"
+.TH GETUSERS 2 2014-10-20 "Linux" "Linux Programmer's Manual"
+.SH NAME
+getusers, setusers \- get/set list of supplementary user IDs
+.SH SYNOPSIS
+.B #include <sys/types.h>
+.br
+.B #include <unistd.h>
+.sp
+.BI "int getusers(int " size ", uid_t *" list );
+.sp
+.BI "int setusers(int " size ", const uid_t *" list );
+.sp
+.in -4n
+Feature Test Macro Requirements for glibc (see
+.BR feature_test_macros (7)):
+.in
+.sp
+.BR getusers (),
+.BR setusers ():
+_GNU_SOURCE
+.SH DESCRIPTION
+.PP
+.BR getusers ()
+returns the supplementary user IDs of the calling process in
+.IR list .
+The argument
+.I size
+should be set to the maximum number of items that can be stored in the
+buffer pointed to by
+.IR list .
+If the calling process has more than
+.I size
+supplementary user IDs,
+.BR getusers ()
+returns an error.
+The returned list may or may not include the real, effective, saved, or filesystem user ID of the calling process.
+
+If
+.I size
+is zero,
+.I list
+is not modified, but the total number of supplementary user IDs for the
+process is returned.
+This allows the caller to determine the size of a dynamically allocated
+.I list
+to be used in a further call to
+.BR getusers ().
+.PP
+.BR setusers ()
+sets the supplementary user IDs for the calling process.
+The
+.I size
+argument specifies the number of supplementary user IDs
+in the buffer pointed to by
+.IR list .
+
+Any process may drop user IDs from its supplementary list; however, adding user
+IDs not already present in the supplementary list or in the real, effective, or
+saved user ID requires the
+.B CAP_SETUID
+capability.
+.SH RETURN VALUE
+On success,
+.BR getusers ()
+returns the number of supplementary user IDs.
+On error, \-1 is returned, and
+.I errno
+is set appropriately.
+
+On success,
+.BR setusers ()
+returns 0.
+On error, \-1 is returned, and
+.I errno
+is set appropriately.
+.SH ERRORS
+.TP
+.B EFAULT
+.I list
+has an invalid address.
+.PP
+.BR getusers ()
+can additionally fail with the following error:
+.TP
+.B EINVAL
+.I size
+is less than the number of supplementary user IDs, but is not zero.
+.PP
+.BR setusers ()
+can additionally fail with the following errors:
+.TP
+.B EINVAL
+.I size
+is greater than
+.B NUSERS_MAX
+(65536).
+.TP
+.B ENOMEM
+Out of memory.
+.TP
+.B EPERM
+.I list
+contains user IDs not present in the current supplemental user IDs list,
+and not equal to the real, effective, or saved user ID, and the calling
+process does not have
+.BR CAP_SETUID .
+.SH CONFORMING TO
+.BR getusers (),
+.BR setusers (),
+and supplementary user IDs in general are Linux-specific and should not
+be used in programs intended to be portable.
+.SH NOTES
+A process can have up to
+.B NUSERS_MAX
+supplementary user IDs in addition to the real, effective, and saved
+user IDs.
+The constant
+.B NUSERS_MAX
+is defined in
+.IR <limits.h> .
+The set of supplementary user IDs is inherited from the parent process,
+and preserved across an
+.BR execve (2).
+
+The maximum number of supplementary user IDs can be found at run time
+using
+.BR sysconf (3):
+.nf
+
+ long nusers_max;
+ nusers_max = sysconf(_SC_NUSERS_MAX);
+
+.fi
+The maximum return value of
+.BR getusers ()
+cannot be larger than this value.
+.SH SEE ALSO
+.BR capabilities (7),
+.BR credentials (7),
+.BR getgroups (2),
+.BR getresuid (2),
+.BR getuid (2),
+.BR setgroups (2),
+.BR setresuid (2),
+.BR setuid (2)
diff --git a/man2/seteuid.2 b/man2/seteuid.2
index 4690fd6..1710133 100644
--- a/man2/seteuid.2
+++ b/man2/seteuid.2
@@ -1,4 +1,5 @@
.\" Copyright (C) 2001 Andries Brouwer (aeb@cwi.nl)
+.\" Copyright 2014 Josh Triplett <josh@joshtriplett.org>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
@@ -54,7 +55,8 @@ _BSD_SOURCE || _POSIX_C_SOURCE\ >=\ 200112L || _XOPEN_SOURCE\ >=\ 600
.BR seteuid ()
sets the effective user ID of the calling process.
Unprivileged user processes may only set the effective user ID to the
-real user ID, the effective user ID or the saved set-user-ID.
+real user ID, the effective user ID, the saved set-user-ID, or a supplementary
+user ID.
Precisely the same holds for
.BR setegid ()
@@ -95,9 +97,13 @@ and
(respectively,
.IR egid )
is not the real user (group) ID, the effective user (group) ID,
-or the saved set-user-ID (saved set-group-ID).
+the saved set-user-ID (saved set-group-ID), or one of the supplementary
+user (group) IDs.
.SH CONFORMING TO
4.3BSD, POSIX.1-2001.
+
+Support for supplementary user IDs is Linux-specific and should not be
+used in programs intended to be portable.
.SH NOTES
Setting the effective user (group) ID to the
saved set-user-ID (saved set-group-ID) is
diff --git a/man2/setfsuid.2 b/man2/setfsuid.2
index 57b125e..f15a31c 100644
--- a/man2/setfsuid.2
+++ b/man2/setfsuid.2
@@ -1,4 +1,5 @@
.\" Copyright (C) 1995, Thomas K. Dyas <tdyas@eden.rutgers.edu>
+.\" Copyright 2014 Josh Triplett <josh@joshtriplett.org>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
@@ -64,7 +65,8 @@ is a security hole that can expose it to unwanted signals.
will succeed only if the caller is the superuser or if
.I fsuid
matches either the caller's real user ID, effective user ID,
-saved set-user-ID, or current filesystem user ID.
+saved set-user-ID, current filesystem user ID, or any supplementary
+user ID.
.SH RETURN VALUE
On both success and failure,
this call returns the previous filesystem user ID of the caller.
diff --git a/man2/setresuid.2 b/man2/setresuid.2
index 99ab94f..cc0ba54 100644
--- a/man2/setresuid.2
+++ b/man2/setresuid.2
@@ -1,4 +1,5 @@
.\" Copyright (C) 1997 Andries Brouwer (aeb@cwi.nl)
+.\" Copyright 2014 Josh Triplett <josh@joshtriplett.org>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
@@ -42,8 +43,8 @@ saved set-user-ID of the calling process.
Unprivileged user processes
may change the real UID,
effective UID, and saved set-user-ID, each to one of:
-the current real UID, the current effective UID or the
-current saved set-user-ID.
+the current real UID, the current effective UID, the
+current saved set-user-ID, or any supplementary UID.
Privileged processes (on Linux, those having the \fBCAP_SETUID\fP capability)
may set the real UID, effective UID, and
@@ -109,6 +110,9 @@ These calls are available under Linux since Linux 2.1.44.
.SH CONFORMING TO
These calls are nonstandard;
they also appear on HP-UX and some of the BSDs.
+
+Support for supplementary user IDs is Linux-specific and should not be
+used in programs intended to be portable.
.SH NOTES
Under HP-UX and FreeBSD, the prototype is found in
.IR <unistd.h> .
diff --git a/man2/setreuid.2 b/man2/setreuid.2
index c6597e9..3b19b8d 100644
--- a/man2/setreuid.2
+++ b/man2/setreuid.2
@@ -1,4 +1,5 @@
.\" Copyright (c) 1983, 1991 The Regents of the University of California.
+.\" Copyright 2014 Josh Triplett <josh@joshtriplett.org>
.\" All rights reserved.
.\"
.\" %%%LICENSE_START(BSD_4_CLAUSE_UCB)
@@ -75,10 +76,10 @@ Supplying a value of \-1 for either the real or effective user ID forces
the system to leave that ID unchanged.
Unprivileged processes may only set the effective user ID to the real user ID,
-the effective user ID, or the saved set-user-ID.
+the effective user ID, the saved set-user-ID, or a supplementary user ID.
Unprivileged users may only set the real user ID to
-the real user ID or the effective user ID.
+the real user ID, the effective user ID, or a supplementary user ID.
If the real user ID is set (i.e.,
.I ruid
@@ -144,13 +145,18 @@ and a change other than (i)
swapping the effective user (group) ID with the real user (group) ID,
or (ii) setting one to the value of the other or (iii) setting the
effective user (group) ID to the value of the
-saved set-user-ID (saved set-group-ID) was specified.
+saved set-user-ID (saved set-group-ID) or (iv) setting the real or
+effective user (group) ID to a supplementary user (group) ID was
+specified.
.SH CONFORMING TO
POSIX.1-2001, 4.3BSD (the
.BR setreuid ()
and
.BR setregid ()
function calls first appeared in 4.2BSD).
+
+Support for supplementary user IDs is Linux-specific and should not be
+used in programs intended to be portable.
.SH NOTES
Setting the effective user (group) ID to the
saved set-user-ID (saved set-group-ID) is
diff --git a/man2/setuid.2 b/man2/setuid.2
index c6f870e..e2082be 100644
--- a/man2/setuid.2
+++ b/man2/setuid.2
@@ -1,4 +1,5 @@
.\" Copyright (C), 1994, Graeme W. Wilford (Wilf).
+.\" Copyright 2014 Josh Triplett <josh@joshtriplett.org>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
@@ -113,11 +114,15 @@ The user is not privileged (Linux: does not have the
.B CAP_SETUID
capability) and
.I uid
-does not match the real UID or saved set-user-ID of the calling process.
+does not match the real UID, saved set-user-ID, or any supplementary
+user ID of the calling process.
.SH CONFORMING TO
SVr4, POSIX.1-2001.
Not quite compatible with the 4.4BSD call, which
sets all of the real, saved, and effective user IDs.
+
+Support for supplementary user IDs is Linux-specific and should not be
+used in programs intended to be portable.
.\" SVr4 documents an additional EINVAL error condition.
.SH NOTES
Linux has the concept of the filesystem user ID, normally equal to the
diff --git a/man2/setusers.2 b/man2/setusers.2
new file mode 100644
index 0000000..8044989
--- /dev/null
+++ b/man2/setusers.2
@@ -0,0 +1 @@
+.so man2/getusers.2
diff --git a/man7/credentials.7 b/man7/credentials.7
index acb799d..df601e2 100644
--- a/man7/credentials.7
+++ b/man7/credentials.7
@@ -1,4 +1,5 @@
.\" Copyright (c) 2007 by Michael Kerrisk <mtk.manpages@gmail.com>
+.\" Copyright 2014 Josh Triplett <josh@joshtriplett.org>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
@@ -232,6 +233,19 @@ by calling
and
.BR setfsgid (2).
.IP *
+Supplementary user IDs.
+This is a set of additional user IDs that the process has
+permission to act as.
+A process can have up to 65536 supplementary user IDs.
+The call
+.I sysconf(_SC_NUSERS_MAX)
+can be used to determine the number of supplementary user IDs
+a process may have.
+A process can obtain its set of supplementary user IDs using
+.BR getusers (2),
+and can modify the set using
+.BR setusers (2).
+.IP *
Supplementary group IDs.
This is a set of additional group IDs that are used for permission
checks when accessing files and other shared resources.
@@ -256,7 +270,7 @@ A child process created by
inherits copies of its parent's user and groups IDs.
During an
.BR execve (2),
-a process's real user and group ID and supplementary
+a process's real user and group ID and supplementary user and
group IDs are preserved;
the effective and saved set IDs may be changed, as described in
.BR execve (2).
@@ -289,7 +303,8 @@ Process IDs, parent process IDs, process group IDs, and session IDs
are specified in POSIX.1-2001.
The real, effective, and saved set user and groups IDs,
and the supplementary group IDs, are specified in POSIX.1-2001.
-The filesystem user and group IDs are a Linux extension.
+The filesystem user and group IDs, and the supplementary user IDs, are
+Linux extensions.
.SH NOTES
The POSIX threads specification requires that
credentials are shared by all of the threads in a process.
@@ -314,6 +329,7 @@ is carried through to all of the POSIX threads in a process.
.BR getpid (2),
.BR getppid (2),
.BR getsid (2),
+.BR getusers (2),
.BR kill (2),
.BR killpg (2),
.BR setegid (2),
@@ -325,6 +341,7 @@ is carried through to all of the POSIX threads in a process.
.BR setresgid (2),
.BR setresuid (2),
.BR setuid (2),
+.BR setusers (2),
.BR waitpid (2),
.BR euidaccess (3),
.BR initgroups (3),
--
2.1.3
^ permalink raw reply related
* [PATCH] Add supplementary UIDs, and getusers/setusers system calls
From: Josh Triplett @ 2014-11-16 7:08 UTC (permalink / raw)
To: Andrew Morton, Theodore Ts'o, Kees Cook,
mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-man-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Analogous to the supplementary GID list, the supplementary UID list
provides a set of additional user credentials that a process can act as.
A process with CAP_SETUID can set its UID list arbitrarily; a process
without CAP_SETUID can only reduce its UID list.
This allows each user to have a set of UIDs that they can then use to
further sandbox individual child processes without first escalating to
root to change UIDs. For instance, a PAM module could give each user a
block of UIDs to work with.
Tested via the following test program:
#include <err.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
static int getusers(int count, uid_t *uids)
{
return syscall(322, count, uids);
}
static int setusers(int count, const uid_t *uids)
{
return syscall(323, count, uids);
}
static void show_users(void)
{
uid_t uids[65536];
int i, count = getusers(65536, uids);
if (count < 0)
err(1, "getusers");
printf("UIDs:");
for (i = 0; i < count; i++)
printf(" %u", (unsigned)uids[i]);
printf("\n");
}
int main(void)
{
uid_t list1[] = { 1, 2, 3, 4, 5 };
uid_t list2[] = { 1, 2, 3, 4 };
uid_t list3[] = { 2, 3, 4 };
show_users();
if (setusers(5, list1) < 0)
err(1, "setusers 1");
show_users();
if (setresgid(1, 1, 1) < 0)
err(1, "setresgid");
if (setresuid(1, 1, 1) < 0)
err(1, "setresuid");
if (setusers(4, list2) < 0)
err(1, "setusers 2");
show_users();
if (setusers(3, list3) < 0)
err(1, "setusers 3");
show_users();
if (setusers(4, list2) < 0)
err(1, "setusers 4");
show_users();
if (setresuid(2, 2, 2) < 0)
err(1, "setresuid 2");
if (setusers(5, list1) < 0)
err(1, "setusers 5");
show_users();
return 0;
}
In this test, all but the last call to setusers succeeds; the last call
fails with EPERM because the unprivileged process attempts to add UID 5
to the supplementary UID list, which it does not currently have.
Signed-off-by: Josh Triplett <josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
---
arch/x86/syscalls/syscall_32.tbl | 2 +
arch/x86/syscalls/syscall_64.tbl | 2 +
include/linux/cred.h | 66 +++++++++++++++
include/linux/syscalls.h | 2 +
include/uapi/asm-generic/unistd.h | 6 +-
include/uapi/linux/limits.h | 1 +
init/Kconfig | 9 ++
kernel/cred.c | 4 +
kernel/groups.c | 173 ++++++++++++++++++++++++++++++++++++++
kernel/sys.c | 21 +++--
kernel/sys_ni.c | 2 +
11 files changed, 280 insertions(+), 8 deletions(-)
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index 9fe1b5d..55717d7 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -364,3 +364,5 @@
355 i386 getrandom sys_getrandom
356 i386 memfd_create sys_memfd_create
357 i386 bpf sys_bpf
+358 i386 getusers sys_getusers
+359 i386 setusers sys_setusers
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index 281150b..5572e67 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -328,6 +328,8 @@
319 common memfd_create sys_memfd_create
320 common kexec_file_load sys_kexec_file_load
321 common bpf sys_bpf
+322 common getusers sys_getusers
+323 common setusers sys_setusers
#
# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/include/linux/cred.h b/include/linux/cred.h
index b2d0820..31169fe 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -76,6 +76,8 @@ extern int groups_search(const struct group_info *, kgid_t);
extern int in_group_p(kgid_t);
extern int in_egroup_p(kgid_t);
+struct user_info;
+
/*
* The security context of a task
*
@@ -135,6 +137,12 @@ struct cred {
struct user_struct *user; /* real user ID subscription */
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
struct group_info *group_info; /* supplementary groups for euid/fsgid */
+#ifdef CONFIG_SUPPLEMENTARY_UIDS
+ struct user_info *user_info; /* supplementary users */
+#define INIT_USER_INFO .user_info = &init_users,
+#else
+#define INIT_USER_INFO
+#endif
struct rcu_head rcu; /* RCU deletion hook */
};
@@ -381,4 +389,62 @@ do { \
*(_fsgid) = __cred->fsgid; \
} while(0)
+#ifdef CONFIG_SUPPLEMENTARY_UIDS
+struct user_info {
+ atomic_t usage;
+ int nusers;
+ int nblocks;
+ kuid_t small_block[NGROUPS_SMALL];
+ kuid_t *blocks[0];
+};
+
+#define USER_AT(ui, i) GROUP_AT(ui, i)
+extern struct user_info init_users;
+void users_free(struct user_info *);
+bool has_supplementary_uid(kuid_t);
+
+/**
+ * get_user_info - Get a reference to a user_info structure
+ * @user_info: The user_info to reference
+ *
+ * This gets a reference to a set of supplementary users.
+ *
+ * If the caller is accessing a task's credentials, they must hold the RCU read
+ * lock when reading.
+ */
+static inline struct user_info *get_user_info(struct user_info *ui)
+{
+ atomic_inc(&ui->usage);
+ return ui;
+}
+
+static inline void get_cred_user_info(struct cred *cred)
+{
+ get_user_info(cred->user_info);
+}
+
+/**
+ * put_user_info - Release a reference to a user_info structure
+ * @user_info: The user_info to release
+ */
+static inline void put_user_info(struct user_info *ui)
+{
+ if (atomic_dec_and_test(&ui->usage))
+ users_free(ui);
+}
+
+static inline void put_cred_user_info(struct cred *cred)
+{
+ if (cred->user_info)
+ put_user_info(cred->user_info);
+}
+#else /* CONFIG_SUPPLEMENTARY_UIDS */
+static inline bool has_supplementary_uid(kuid_t uid)
+{
+ return false;
+}
+static inline void get_cred_user_info(struct cred *cred) {}
+static inline void put_cred_user_info(struct cred *cred) {}
+#endif
+
#endif /* _LINUX_CRED_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index bda9b81..3bde665 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -232,6 +232,7 @@ asmlinkage long sys_getpgid(pid_t pid);
asmlinkage long sys_getpgrp(void);
asmlinkage long sys_getsid(pid_t pid);
asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist);
+asmlinkage long sys_getusers(int uidsetsize, uid_t __user *userlist);
asmlinkage long sys_setregid(gid_t rgid, gid_t egid);
asmlinkage long sys_setgid(gid_t gid);
@@ -244,6 +245,7 @@ asmlinkage long sys_setfsgid(gid_t gid);
asmlinkage long sys_setpgid(pid_t pid, pid_t pgid);
asmlinkage long sys_setsid(void);
asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist);
+asmlinkage long sys_setusers(int uidsetsize, uid_t __user *grouplist);
asmlinkage long sys_acct(const char __user *name);
asmlinkage long sys_capget(cap_user_header_t header,
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 22749c1..d6696cf 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -707,9 +707,13 @@ __SYSCALL(__NR_getrandom, sys_getrandom)
__SYSCALL(__NR_memfd_create, sys_memfd_create)
#define __NR_bpf 280
__SYSCALL(__NR_bpf, sys_bpf)
+#define __NR_getusers 281
+__SYSCALL(__NR_getusers, sys_getusers)
+#define __NR_setusers 282
+__SYSCALL(__NR_setusers, sys_setusers)
#undef __NR_syscalls
-#define __NR_syscalls 281
+#define __NR_syscalls 283
/*
* All syscalls below here should go away really,
diff --git a/include/uapi/linux/limits.h b/include/uapi/linux/limits.h
index 2d0f941..bae1b4c 100644
--- a/include/uapi/linux/limits.h
+++ b/include/uapi/linux/limits.h
@@ -4,6 +4,7 @@
#define NR_OPEN 1024
#define NGROUPS_MAX 65536 /* supplemental group IDs are available */
+#define NUSERS_MAX 65536 /* supplemental user IDs available */
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
#define LINK_MAX 127 /* # links a file may have */
#define MAX_CANON 255 /* size of the canonical input queue */
diff --git a/init/Kconfig b/init/Kconfig
index 3ee28ae..d85b159 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1358,6 +1358,15 @@ config UID16
help
This enables the legacy 16-bit UID syscall wrappers.
+config SUPPLEMENTARY_UIDS
+ bool "Enable supplementary UIDs and system calls" if EXPERT
+ default y
+ help
+ This option adds a list of supplementary UIDs to each process, along
+ with system calls to manage that list. If building an embedded
+ system where no applications use this functionality, you can disable
+ this option to save space.
+
config SGETMASK_SYSCALL
bool "sgetmask/ssetmask syscalls support" if EXPERT
def_bool PARISC || MN10300 || BLACKFIN || M68K || PPC || MIPS || X86 || SPARC || CRIS || MICROBLAZE || SUPERH
diff --git a/kernel/cred.c b/kernel/cred.c
index e0573a4..1700a03 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -54,6 +54,7 @@ struct cred init_cred = {
.user = INIT_USER,
.user_ns = &init_user_ns,
.group_info = &init_groups,
+ INIT_USER_INFO
};
static inline void set_cred_subscribers(struct cred *cred, int n)
@@ -112,6 +113,7 @@ static void put_cred_rcu(struct rcu_head *rcu)
key_put(cred->request_key_auth);
if (cred->group_info)
put_group_info(cred->group_info);
+ put_cred_user_info(cred);
free_uid(cred->user);
put_user_ns(cred->user_ns);
kmem_cache_free(cred_jar, cred);
@@ -252,6 +254,7 @@ struct cred *prepare_creds(void)
atomic_set(&new->usage, 1);
set_cred_subscribers(new, 0);
get_group_info(new->group_info);
+ get_cred_user_info(new);
get_uid(new->user);
get_user_ns(new->user_ns);
@@ -607,6 +610,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
get_uid(new->user);
get_user_ns(new->user_ns);
get_group_info(new->group_info);
+ get_cred_user_info(new);
#ifdef CONFIG_KEYS
new->session_keyring = NULL;
diff --git a/kernel/groups.c b/kernel/groups.c
index 451698f..d5de27d 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -269,3 +269,176 @@ int in_egroup_p(kgid_t grp)
}
EXPORT_SYMBOL(in_egroup_p);
+
+#ifdef CONFIG_SUPPLEMENTARY_UIDS
+/* init to 2 - one for init_task, one to ensure it is never freed */
+struct user_info init_users = { .usage = ATOMIC_INIT(2) };
+
+static struct user_info *users_alloc(int uidsetsize)
+{
+ return (struct user_info *)groups_alloc(uidsetsize);
+}
+
+void users_free(struct user_info *user_info)
+{
+ groups_free((struct group_info *)user_info);
+}
+
+/* export the user_info to a user-space array */
+static int users_to_user(uid_t __user *userlist,
+ const struct user_info *user_info)
+{
+ struct user_namespace *user_ns = current_user_ns();
+ int i;
+ unsigned int count = user_info->nusers;
+
+ for (i = 0; i < count; i++) {
+ uid_t uid;
+ uid = from_kuid_munged(user_ns, USER_AT(user_info, i));
+ if (put_user(uid, userlist+i))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+/* fill a user_info from a user-space array - it must be allocated already */
+static int users_from_user(struct user_info *user_info, uid_t __user *userlist)
+{
+ struct user_namespace *user_ns = current_user_ns();
+ int i;
+ unsigned int count = user_info->nusers;
+
+ for (i = 0; i < count; i++) {
+ uid_t uid;
+ kuid_t kuid;
+ if (get_user(uid, userlist+i))
+ return -EFAULT;
+
+ kuid = make_kuid(user_ns, uid);
+ if (!uid_valid(kuid))
+ return -EINVAL;
+
+ USER_AT(user_info, i) = kuid;
+ }
+ return 0;
+}
+
+static void users_sort(struct user_info *user_info)
+{
+ groups_sort((struct group_info *)user_info);
+}
+
+static bool users_search(const struct user_info *user_info, kuid_t uid)
+{
+ return groups_search((const struct group_info *)user_info, *(kgid_t *)&uid);
+}
+
+/* Return true if the user_info is a subset of the user_info of the specified
+ * credentials. Also allow the first user_info to contain the uid, euid, or
+ * suid of the credentials.
+ */
+static bool user_subset(const struct user_info *u1, const struct cred *cred2)
+{
+ const struct user_info *u2 = cred2->user_info;
+ unsigned int i, j;
+
+ for (i = 0, j = 0; i < u1->nusers; i++) {
+ kuid_t uid1 = USER_AT(u1, i);
+ kuid_t uid2;
+ for (; j < u2->nusers; j++) {
+ uid2 = USER_AT(u2, j);
+ if (uid_lte(uid1, uid2))
+ break;
+ }
+ if (j >= u2->nusers || !uid_eq(uid1, uid2)) {
+ if (!uid_eq(uid1, cred2->uid)
+ && !uid_eq(uid1, cred2->euid)
+ && !uid_eq(uid1, cred2->suid))
+ return false;
+ } else {
+ j++;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * set_current_users - Change current's supplementary user list
+ * @user_info: The user list to impose
+ *
+ * Validate a user list and, if valid, impose it upon current's task
+ * security record.
+ */
+int set_current_users(struct user_info *user_info)
+{
+ struct cred *new;
+
+ users_sort(user_info);
+ new = prepare_creds();
+ if (!new)
+ return -ENOMEM;
+ if (!(ns_capable(current_user_ns(), CAP_SETUID)
+ || user_subset(user_info, new))) {
+ abort_creds(new);
+ return -EPERM;
+ }
+
+ put_user_info(new->user_info);
+ get_user_info(user_info);
+ new->user_info = user_info;
+ return commit_creds(new);
+}
+
+SYSCALL_DEFINE2(getusers, int, uidsetsize, uid_t __user *, userlist)
+{
+ const struct cred *cred = current_cred();
+ int i;
+
+ if (uidsetsize < 0)
+ return -EINVAL;
+
+ /* no need to grab task_lock here; it cannot change */
+ i = cred->user_info->nusers;
+ if (uidsetsize) {
+ if (i > uidsetsize) {
+ i = -EINVAL;
+ goto out;
+ }
+ if (users_to_user(userlist, cred->user_info)) {
+ i = -EFAULT;
+ goto out;
+ }
+ }
+out:
+ return i;
+}
+
+SYSCALL_DEFINE2(setusers, int, uidsetsize, uid_t __user *, userlist)
+{
+ struct user_info *user_info;
+ int retval;
+
+ if ((unsigned)uidsetsize > NUSERS_MAX)
+ return -EINVAL;
+
+ user_info = users_alloc(uidsetsize);
+ if (!user_info)
+ return -ENOMEM;
+ retval = users_from_user(user_info, userlist);
+ if (retval) {
+ put_user_info(user_info);
+ return retval;
+ }
+
+ retval = set_current_users(user_info);
+ put_user_info(user_info);
+
+ return retval;
+}
+
+bool has_supplementary_uid(kuid_t uid)
+{
+ return users_search(current_cred()->user_info, uid);
+}
+#endif /* CONFIG_SUPPLEMENTARY_UIDS */
diff --git a/kernel/sys.c b/kernel/sys.c
index 1eaa2f0..412dda9 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -472,7 +472,8 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
new->uid = kruid;
if (!uid_eq(old->uid, kruid) &&
!uid_eq(old->euid, kruid) &&
- !ns_capable(old->user_ns, CAP_SETUID))
+ !ns_capable(old->user_ns, CAP_SETUID) &&
+ !has_supplementary_uid(kruid))
goto error;
}
@@ -481,7 +482,8 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
if (!uid_eq(old->uid, keuid) &&
!uid_eq(old->euid, keuid) &&
!uid_eq(old->suid, keuid) &&
- !ns_capable(old->user_ns, CAP_SETUID))
+ !ns_capable(old->user_ns, CAP_SETUID) &&
+ !has_supplementary_uid(keuid))
goto error;
}
@@ -542,7 +544,8 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
if (retval < 0)
goto error;
}
- } else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) {
+ } else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid) &&
+ !has_supplementary_uid(kuid)) {
goto error;
}
@@ -594,13 +597,16 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
retval = -EPERM;
if (!ns_capable(old->user_ns, CAP_SETUID)) {
if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) &&
- !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
+ !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid) &&
+ !has_supplementary_uid(kruid))
goto error;
if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) &&
- !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid))
+ !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid) &&
+ !has_supplementary_uid(keuid))
goto error;
if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) &&
- !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid))
+ !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid) &&
+ !has_supplementary_uid(ksuid))
goto error;
}
@@ -750,7 +756,8 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) ||
uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||
- ns_capable(old->user_ns, CAP_SETUID)) {
+ ns_capable(old->user_ns, CAP_SETUID) ||
+ has_supplementary_uid(kuid)) {
if (!uid_eq(kuid, old->fsuid)) {
new->fsuid = kuid;
if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 02aa418..a8a8f02 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -159,6 +159,8 @@ cond_syscall(sys_uselib);
cond_syscall(sys_fadvise64);
cond_syscall(sys_fadvise64_64);
cond_syscall(sys_madvise);
+cond_syscall(sys_getusers);
+cond_syscall(sys_setusers);
/* arch-specific weak syscall entries */
cond_syscall(sys_pciconfig_read);
--
2.1.3
^ permalink raw reply related
* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Josh Triplett @ 2014-11-16 5:07 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Theodore Ts'o, Andy Lutomirski, Andrew Morton, Kees Cook,
Michael Kerrisk-manpages, Linux API, linux-man,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <87vbmfq1uw.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
On Sat, Nov 15, 2014 at 09:08:07PM -0600, Eric W. Biederman wrote:
> Josh Triplett <josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org> writes:
> > On November 15, 2014 6:05:11 PM PST, Theodore Ts'o <tytso-3s7WtUTddSA@public.gmane.org> wrote:
> >>On Sat, Nov 15, 2014 at 12:20:42PM -0800, Josh Triplett wrote:
> >>> > However, sudoers seems to allow negative group matches. So maybe
> >>> > allowing this only with no_new_privs already set would make sense.
> >>>
> >>> Sigh, bad sudo. Sure, restricting this to no_new_privs only seems
> >>fine.
> >>> I'll do that in v2, and document that in the manpage.
> >>
> >>I've also seen use cases (generally back in the bad old days of big
> >>timesharing VAX 750's :-) where the system admin might assign someone
> >>to the "games-abusers" group, and then set /usr/games to mode 705
> >>root:games-abusers --- presumably because it's easier to add a few
> >>people to the deny list rather than having to add all of the EECS
> >>department to the games group minus the abusers.
> >>
> >>So arbitrarily anyone to drop groups from their supplemental group
> >>list will result in a change from both existing practice and legacy
> >>Unix systems, and it could potentially lead to a security exposure.
> >
> > As Andy pointed out, you can already do that with a user namespace,
>
> That may be a bug with the user namespace permission check. Perhaps we
> shouldn't allow dropping groups that aren't mapped in the user
> namespace.
Changing that would break containers for users on many common Linux
distributions, which put users in various supplementary groups by
default.
I do actually have another patch planned, to allow users to set up gid
maps for groups they currently have permission for, not just for their
primary group. But even with that change, breaking the ability for
container-root to use setgroups to drop all its supplementary groups
seems very wrong, and seems highly likely to break real-world software
running in containers.
> To add to the discussion there are also sg and newgroup, though I don't
> think they touch supplementary groups.
Both sg and newgrp do prove a different point, though: an unprivileged
user should be able to change their gid to one of their supplementary
groups. That's another patch I planned to submit after this one:
allow setgid/setresgid/etc to a supplementary group ID.
> > for any case not involving a setuid or setgid (or otherwise
> > privilege-gaining) program. And requiring no_new_privs handles that.
>
> Frankly adding a no_new_privs check to allow something/anything scares
> me. That converts no_new_privs from something simple and easy to
> understand to something much more complicated.
no_new_privs already exists in large part to support such use cases,
such as setting seccomp filters, which would be dangerous for
privilege-escalating programs to inherit.
> > Given the combination of those two things, do you still see any
> > problematic cases?
>
> Josh I think it is time to stop and make certain you understand how
> unix groups work in the large.
>
> It seems to me that either supplementary groups can be dropped or
> supplementary groups can not be dropped. If they can be dropped we
> shouldn't need complicated checks to allow them to be dropped in some
> circumstances but not others.
>
> Unix groups are an old interface and they have been used in a lot of
> ways over the years. We need to be careful any change we make is good
> and truly backwards compatible and that we do our darndest not to
> introduce security holes.
Seeking the decades-old precedents and corner cases that might
contradict the most obvious semantics is a large part of what I'm
looking for out of this thread.
However, I don't necessarily think that we must permit unprivileged
setgroups in *all* cases if we permit it in *any*; it may well make
sense to reduce the surface area of the change by limiting the
circumstances in which you can do this. Whether it does end up making
sense to do so depends on the outcome of this discussion.
I added the no_new_privs check at Andy's suggestion, since the use case
I had in mind will work just fine with that restriction. I'm also open
to just allowing setgroups in all cases, if that semantic seems
preferable, or to adding some separate check specific to this case if
that really seems necessary.
- Josh Triplett
^ permalink raw reply
* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Josh Triplett @ 2014-11-16 4:52 UTC (permalink / raw)
To: Theodore Ts'o, Andy Lutomirski, Eric W. Biederman,
Andrew Morton, Kees Cook, Michael Kerrisk-manpages, Linux API,
linux-man, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20141116034005.GC5507-AKGzg7BKzIDYtjvyW6yDsg@public.gmane.org>
On Sat, Nov 15, 2014 at 10:40:06PM -0500, Theodore Ts'o wrote:
> On Sat, Nov 15, 2014 at 06:35:05PM -0800, Josh Triplett wrote:
> > >So arbitrarily anyone to drop groups from their supplemental group
> > >list will result in a change from both existing practice and legacy
> > >Unix systems, and it could potentially lead to a security exposure.
> >
> > As Andy pointed out, you can already do that with a user namespace,
> > for any case not involving a setuid or setgid (or otherwise
> > privilege-gaining) program. And requiring no_new_privs handles
> > that.
>
> Well, it's no worse than what we can do already with the user
> namespace, yes. I'm still worried it's going to come as a surprise
> for some configurations because it's a change from what was allowed
> historically. Then again, pretty much all of the tripwire and rootkit
> scanners won't notice a "setuid" program that uses capabilities
> instead of the traditional setuid bit, and most sysadmins won't think
> to check for an executable with a forced capability mask, so this
> isn't exactly a new problem....
We certainly have introduced orthogonal APIs in various areas before,
such that applications written prior to those APIs may interact
interestingly with them; we don't allow *breaking* those applications,
or introducing security holes, but the existence of applications
designed to block one particular way to do something doesn't
*automatically* rule out the possibility of adding another way to do it.
It does require some careful thought, though.
When we introduced seccomp filters for syscalls, we tied them to
no_new_privs to prevent any possible security holes caused by selective
syscall denial/filtration.
In this case, I'm indifferent about whether unprivileged setgroups works
without no_new_privs; if people are comfortable with that, fine, and if
people would prefer no_new_privs (or for that matter a sysctl, a
compile-time option, or any other means of making the behavior
optional), I can do that too. The security model of "having a group
gives you less privilege than not having it" seems crazy, but
nonetheless I can see a couple of easy ways that we can avoid breaking
that pattern, no_new_privs being one of them. I'd like to make sure
that nobody sees any other real-world corner case that unprivileged
setgroups would break.
- Josh Triplett
^ permalink raw reply
* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Theodore Ts'o @ 2014-11-16 3:40 UTC (permalink / raw)
To: Josh Triplett
Cc: Andy Lutomirski, Eric W. Biederman, Andrew Morton, Kees Cook,
Michael Kerrisk-manpages, Linux API, linux-man,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <6C690A2C-8EB1-421A-94C3-9803AFB95760-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
On Sat, Nov 15, 2014 at 06:35:05PM -0800, Josh Triplett wrote:
> >So arbitrarily anyone to drop groups from their supplemental group
> >list will result in a change from both existing practice and legacy
> >Unix systems, and it could potentially lead to a security exposure.
>
> As Andy pointed out, you can already do that with a user namespace,
> for any case not involving a setuid or setgid (or otherwise
> privilege-gaining) program. And requiring no_new_privs handles
> that.
Well, it's no worse than what we can do already with the user
namespace, yes. I'm still worried it's going to come as a surprise
for some configurations because it's a change from what was allowed
historically. Then again, pretty much all of the tripwire and rootkit
scanners won't notice a "setuid" program that uses capabilities
instead of the traditional setuid bit, and most sysadmins won't think
to check for an executable with a forced capability mask, so this
isn't exactly a new problem....
- Ted
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Eric W. Biederman @ 2014-11-16 3:08 UTC (permalink / raw)
To: Josh Triplett
Cc: Theodore Ts'o, Andy Lutomirski, Andrew Morton, Kees Cook,
Michael Kerrisk-manpages, Linux API, linux-man,
linux-kernel@vger.kernel.org
In-Reply-To: <6C690A2C-8EB1-421A-94C3-9803AFB95760-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
Josh Triplett <josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org> writes:
> On November 15, 2014 6:05:11 PM PST, Theodore Ts'o <tytso-3s7WtUTddSA@public.gmane.org> wrote:
>>On Sat, Nov 15, 2014 at 12:20:42PM -0800, Josh Triplett wrote:
>>> > However, sudoers seems to allow negative group matches. So maybe
>>> > allowing this only with no_new_privs already set would make sense.
>>>
>>> Sigh, bad sudo. Sure, restricting this to no_new_privs only seems
>>fine.
>>> I'll do that in v2, and document that in the manpage.
>>
>>I've also seen use cases (generally back in the bad old days of big
>>timesharing VAX 750's :-) where the system admin might assign someone
>>to the "games-abusers" group, and then set /usr/games to mode 705
>>root:games-abusers --- presumably because it's easier to add a few
>>people to the deny list rather than having to add all of the EECS
>>department to the games group minus the abusers.
>>
>>So arbitrarily anyone to drop groups from their supplemental group
>>list will result in a change from both existing practice and legacy
>>Unix systems, and it could potentially lead to a security exposure.
>
> As Andy pointed out, you can already do that with a user namespace,
That may be a bug with the user namespace permission check. Perhaps we
shouldn't allow dropping groups that aren't mapped in the user
namespace.
To add to the discussion there are also sg and newgroup, though I don't
think they touch supplementary groups.
> for any case not involving a setuid or setgid (or otherwise
> privilege-gaining) program. And requiring no_new_privs handles that.
Frankly adding a no_new_privs check to allow something/anything scares
me. That converts no_new_privs from something simple and easy to
understand to something much more complicated.
> Given the combination of those two things, do you still see any
> problematic cases?
Josh I think it is time to stop and make certain you understand how
unix groups work in the large.
It seems to me that either supplementary groups can be dropped or
supplementary groups can not be dropped. If they can be dropped we
shouldn't need complicated checks to allow them to be dropped in some
circumstances but not others.
Unix groups are an old interface and they have been used in a lot of
ways over the years. We need to be careful any change we make is good
and truly backwards compatible and that we do our darndest not to
introduce security holes.
Eric
^ permalink raw reply
* Re: [PATCH 2/2] groups: Allow unprivileged processes to use setgroups to drop groups
From: Josh Triplett @ 2014-11-16 2:35 UTC (permalink / raw)
To: Theodore Ts'o
Cc: Andy Lutomirski, Eric W. Biederman, Andrew Morton, Kees Cook,
Michael Kerrisk-manpages, Linux API, linux-man,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20141116020511.GB5507-AKGzg7BKzIDYtjvyW6yDsg@public.gmane.org>
On November 15, 2014 6:05:11 PM PST, Theodore Ts'o <tytso-3s7WtUTddSA@public.gmane.org> wrote:
>On Sat, Nov 15, 2014 at 12:20:42PM -0800, Josh Triplett wrote:
>> > However, sudoers seems to allow negative group matches. So maybe
>> > allowing this only with no_new_privs already set would make sense.
>>
>> Sigh, bad sudo. Sure, restricting this to no_new_privs only seems
>fine.
>> I'll do that in v2, and document that in the manpage.
>
>I've also seen use cases (generally back in the bad old days of big
>timesharing VAX 750's :-) where the system admin might assign someone
>to the "games-abusers" group, and then set /usr/games to mode 705
>root:games-abusers --- presumably because it's easier to add a few
>people to the deny list rather than having to add all of the EECS
>department to the games group minus the abusers.
>
>So arbitrarily anyone to drop groups from their supplemental group
>list will result in a change from both existing practice and legacy
>Unix systems, and it could potentially lead to a security exposure.
As Andy pointed out, you can already do that with a user namespace, for any case not involving a setuid or setgid (or otherwise privilege-gaining) program. And requiring no_new_privs handles that.
Given the combination of those two things, do you still see any problematic cases?
- Josh Triplett
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 10/10] crypto: AF_ALG: document the user space interface
From: Stephan Mueller @ 2014-11-16 2:29 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
The extension of the user space interface documentation covers all
aspects of the patchset, including:
* AEAD cipher interface
* RNG cipher interface
* getsockopt interface
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
Documentation/crypto/crypto-API-userspace.txt | 95 ++++++++++++++++++++++++++-
1 file changed, 93 insertions(+), 2 deletions(-)
diff --git a/Documentation/crypto/crypto-API-userspace.txt b/Documentation/crypto/crypto-API-userspace.txt
index ac619cd..5090b05 100644
--- a/Documentation/crypto/crypto-API-userspace.txt
+++ b/Documentation/crypto/crypto-API-userspace.txt
@@ -30,8 +30,9 @@ ciphers are accessible:
* Symmetric ciphers
-Note, AEAD ciphers are currently not supported via the symmetric cipher
-interface.
+ * AEAD ciphers
+
+ * Random number generators
The interface is provided via Netlink using the type AF_ALG. In addition, the
setsockopt option type is SOL_ALG. In case the user space header files do not
@@ -85,6 +86,7 @@ If a consumer on the other hand wants to maintain the plaintext and the
ciphertext in different memory locations, all a consumer needs to do is to
provide different memory pointers for the encryption and decryption operation.
+
Message digest API
==================
@@ -169,6 +171,69 @@ as large as to hold all blocks of the encrypted or decrypted data. If the output
data size is smaller, only as many blocks are returned that fit into that
output buffer size.
+
+AEAD cipher API
+===============
+
+The operation is identical to the symmetric cipher API. However, an AEAD
+cipher requires additional information, such as the authentication tag and
+the associated data. This data is to be supplied in addition to the normal
+symmetric cipher data like key and IV discussed for the symmetric ciphers.
+
+During initialization, the struct sockaddr data structure must be filled as
+follows:
+
+struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "aead", /* this selects the AEAD cipher */
+ .salg_name = "gcm(aes)" /* this is the cipher name */
+};
+
+The discussion about the sendmsg given for the symmetric cipher applies for
+the AEAD interface as well. In addition to the plaintext / ciphertext data and
+the IV, the following data must be supplied with the cmsghdr data structure:
+
+ * The AEAD authentication tag size is set with the flag
+ ALG_SET_AEAD_AUTHSIZE. The integer value of the authentication tag
+ size must be provided in the data field of the cmsghdr structure.
+
+ * The AEAD associated data is set with the flag ALG_SET_AEAD_ASSOC.
+ The data is set the same way as for the IV by supplying the associated
+ data in the data field of the cmsghdr structure.
+
+The authentication tag itself, however, is handled in a different way to comply
+with the specifics of the kernel crypto API and to avoid copying the
+authentication tag around in memory. The authentication tag is added to the
+memory that immediately follows the ciphertext.
+
+ * When performing an encryption operation, the resulting ciphertext
+ buffer will hold the tag as follows: ciphertext || tag. The consumer
+ must ensure that the ciphertext buffer is large enough to hold the
+ ciphertext together with the tag of the size set by the consumer using
+ the ALG_SET_AEAD_AUTHSIZE cmsghdr flag as discussed above.
+
+ * When performing a decryption operation, the initial ciphertext buffer
+ must hold the tag as follows: ciphertext || tag. The resulting
+ plaintext has the same size as the ciphertext.
+
+Note: Authentication errors during decryption are marked with a failing
+read/recv system call whose errno is set to EBADMSG.
+
+
+Random number generator API
+===========================
+
+Compared to the symmetric ciphers, the random number generator API is simple:
+it only supports the system calls of read/recv.
+
+The consumer must observe the returned size of the read/recv system calls and
+potentially make subsequent calls if the returned length of random numbers is
+smaller than the expected length.
+
+When initializing a random number generator instance, the AF_ALG interface
+handler ensures that it is appropriately seeded.
+
+
Setsockopt interface
====================
@@ -190,6 +255,32 @@ optname:
- the hash cipher type (keyed message digests)
+
+Getsockopt interface
+====================
+
+To allow consumers to obtain information about the allocated cipher, the
+following getsockopt calls with the optval set to the listed flags are provided.
+
+The getsockopt system call must be invoked with the file descriptor of the open
+cipher (i.e. the file descriptor returned by the accept system call).
+
+ * ALG_GET_BLOCKSIZE -- Return the block size of the cipher in the
+ optlen field of getsockopt. This call is only applicable to
+ symmetric and AEAD ciphers.
+
+ * ALG_GET_IVSIZE -- Return the IV size of the cipher in the optlen field
+ of getsockopt. This call is only applicable to symmetric and AEAD
+ ciphers.
+
+ * ALG_GET_AEAD_AUTHSIZE -- Return the maximum supported authentication
+ tag size in the optlen field of getsockopt. This call is only
+ applicable to AEAD ciphers.
+
+ * ALG_GET_DIGESTSIZE -- Return the digest size in the optlen field of
+ getsockopt. This call is only applicable to message digests.
+
+
User space API example
======================
--
2.1.0
^ permalink raw reply related
* [PATCH v2 09/10] crypto: AF_ALG: user space interface for hash info
From: Stephan Mueller @ 2014-11-16 2:28 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
The AF_ALG interface allows normal cipher (hash, encrypt, decrypt).
However, it does not allow user space to obtain the following generic
information about the currently active hash:
* digestsize
The patch adds a getsockopt interface for the hash ciphers to
answer such information requests from user space.
The kernel crypto API function calls are used to obtain the real data.
As all data are simple integer values, the getsockopt handler function
uses put_user() to return the integer value to user space in the
*optval parameter of getsockopt.
A fully working example using the digestsize interface is provided at
http://www.chronox.de/libkcapi.html
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/algif_hash.c | 35 ++++++++++++++++++++++++++++++++++-
include/uapi/linux/if_alg.h | 1 +
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index f75db4c..68ae34c 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -216,6 +216,39 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
return err;
}
+static int hash_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
+ struct hash_ctx *ctx = ask->private;
+ const struct af_alg_type *type;
+ int len = 0;
+ int err = -EOPNOTSUPP;
+
+ lock_sock(sk);
+ type = ask->type;
+
+ if (level != SOL_ALG || !type)
+ goto unlock;
+
+ switch (optname) {
+ case ALG_GET_DIGESTSIZE:
+ len = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
+ err = 0;
+ break;
+ default:
+ break;
+ }
+
+unlock:
+ release_sock(sk);
+ if (err >= 0)
+ err = put_user(len, optlen);
+
+ return err;
+}
+
static struct proto_ops algif_hash_ops = {
.family = PF_ALG,
@@ -225,7 +258,6 @@ static struct proto_ops algif_hash_ops = {
.ioctl = sock_no_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
- .getsockopt = sock_no_getsockopt,
.mmap = sock_no_mmap,
.bind = sock_no_bind,
.setsockopt = sock_no_setsockopt,
@@ -236,6 +268,7 @@ static struct proto_ops algif_hash_ops = {
.sendpage = hash_sendpage,
.recvmsg = hash_recvmsg,
.accept = hash_accept,
+ .getsockopt = hash_getsockopt,
};
static void *hash_bind(const char *name, u32 type, u32 mask)
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index b8fb714..3759d3c 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -44,6 +44,7 @@ struct af_alg_aead_assoc {
#define ALG_GET_BLOCKSIZE 1
#define ALG_GET_IVSIZE 2
#define ALG_GET_AEAD_AUTHSIZE 3
+#define ALG_GET_DIGESTSIZE 4
/* Operations */
#define ALG_OP_DECRYPT 0
--
2.1.0
^ permalink raw reply related
* [PATCH v2 08/10] crypto: AF_ALG: enable RNG interface compilation
From: Stephan Mueller @ 2014-11-16 2:28 UTC (permalink / raw)
To: Herbert Xu
Cc: Daniel Borkmann, quentin.gouchet-Re5JQEeQqe8AvxtiuMwx3w, LKML,
linux-crypto-u79uwXL29TY76Z2rM5mHXA, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC-PJstQz4BMNNP20K/wil9xYQuADTiUCJX@public.gmane.org>
Enable compilation of the RNG AF_ALG support and provide a Kconfig
option to compile the RNG AF_ALG support.
Signed-off-by: Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org>
---
crypto/Kconfig | 9 +++++++++
crypto/Makefile | 1 +
2 files changed, 10 insertions(+)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 87bbc9c..e127323 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1505,6 +1505,15 @@ config CRYPTO_USER_API_SKCIPHER
This option enables the user-spaces interface for symmetric
key cipher algorithms.
+config CRYPTO_USER_API_RNG
+ tristate "User-space interface for random number generator algorithms"
+ depends on NET
+ select CRYPTO_RNG
+ select CRYPTO_USER_API
+ help
+ This option enables the user-spaces interface for random
+ number generator algorithms.
+
config CRYPTO_HASH_INFO
bool
diff --git a/crypto/Makefile b/crypto/Makefile
index 1445b91..ba19465 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
+obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o
#
# generic algorithms and the async_tx api
--
2.1.0
^ permalink raw reply related
* [PATCH v2 07/10] crypto: AF_ALG: add random number generator support
From: Stephan Mueller @ 2014-11-16 2:27 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
This patch adds the random number generator support for AF_ALG.
A random number generator's purpose is to generate data without
requiring the caller to provide any data. Therefore, the AF_ALG
interface handler for RNGs only implements a callback handler for
recvmsg.
The following parameters provided with a recvmsg are processed by the
RNG callback handler:
* sock - to resolve the RNG context data structure accessing the
RNG instance private to the socket
* len - this parameter allows userspace callers to specify how
many random bytes the RNG shall produce and return. As the
kernel context for the RNG allocates a buffer of 128 bytes to
store random numbers before copying them to userspace, the len
parameter is checked that it is not larger than 128. If a
caller wants more random numbers, a new request for recvmsg
shall be made.
The size of 128 bytes is chose because of the following considerations:
* to increase the memory footprint of the kernel too much (note,
that would be 128 bytes per open socket)
* 128 is divisible by any typical cryptographic block size an
RNG may have
* A request for random numbers typically only shall supply small
amount of data like for keys or IVs that should only require
one invocation of the recvmsg function.
Note, during instantiation of the RNG, the code checks whether the RNG
implementation requires seeding. If so, the RNG is seeded with output
from get_random_bytes.
A fully working example using all aspects of the RNG interface is
provided at http://www.chronox.de/libkcapi.html
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/algif_rng.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
create mode 100644 crypto/algif_rng.c
diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
new file mode 100644
index 0000000..fc25869
--- /dev/null
+++ b/crypto/algif_rng.c
@@ -0,0 +1,186 @@
+/*
+ * algif_rng: User-space interface for random number generators
+ *
+ * This file provides the user-space API for random number generators.
+ *
+ * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2
+ * are required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <crypto/rng.h>
+#include <linux/random.h>
+#include <crypto/if_alg.h>
+#include <linux/net.h>
+#include <net/sock.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("User-space interface for random number generators");
+
+struct rng_ctx {
+#define MAXSIZE 128
+ u8 result[MAXSIZE];
+ unsigned int len;
+ struct crypto_rng *drng;
+};
+
+static int rng_recvmsg(struct kiocb *unused, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
+ struct rng_ctx *ctx = ask->private;
+ int err = -EFAULT;
+
+ if (len == 0)
+ return 0;
+ if (len > MAXSIZE)
+ len = MAXSIZE;
+
+ lock_sock(sk);
+ len = crypto_rng_get_bytes(ctx->drng, ctx->result, len);
+ if (len < 0)
+ goto unlock;
+
+ err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
+ memzero_explicit(ctx->result, len);
+
+unlock:
+ release_sock(sk);
+
+ return err ? err : len;
+}
+
+static struct proto_ops algif_rng_ops = {
+ .family = PF_ALG,
+
+ .connect = sock_no_connect,
+ .socketpair = sock_no_socketpair,
+ .getname = sock_no_getname,
+ .ioctl = sock_no_ioctl,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .getsockopt = sock_no_getsockopt,
+ .mmap = sock_no_mmap,
+ .bind = sock_no_bind,
+ .accept = sock_no_accept,
+ .setsockopt = sock_no_setsockopt,
+ .poll = sock_no_poll,
+ .sendmsg = sock_no_sendmsg,
+ .sendpage = sock_no_sendpage,
+
+ .release = af_alg_release,
+ .recvmsg = rng_recvmsg,
+};
+
+static void *rng_bind(const char *name, u32 type, u32 mask)
+{
+ return crypto_alloc_rng(name, type, mask);
+}
+
+static void rng_release(void *private)
+{
+ crypto_free_rng(private);
+}
+
+static void rng_sock_destruct(struct sock *sk)
+{
+ struct alg_sock *ask = alg_sk(sk);
+ struct rng_ctx *ctx = ask->private;
+
+ memzero_explicit(ctx->result, sizeof(ctx->result));
+ sock_kfree_s(sk, ctx, ctx->len);
+ af_alg_release_parent(sk);
+}
+
+static int rng_accept_parent(void *private, struct sock *sk)
+{
+ struct rng_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+ unsigned int len = sizeof(*ctx);
+ int seedsize = crypto_rng_seedsize(private);
+ int ret = -ENOMEM;
+
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ memset(ctx->result, 0, sizeof(ctx->result));
+
+ ctx->len = len;
+
+ if (seedsize) {
+ u8 *buf = kmalloc(seedsize, GFP_KERNEL);
+ if (!buf)
+ goto err;
+ get_random_bytes(buf, seedsize);
+ ret = crypto_rng_reset(private, buf, len);
+ kzfree(buf);
+ if (ret)
+ goto err;
+ }
+
+ ctx->drng = private;
+ ask->private = ctx;
+ sk->sk_destruct = rng_sock_destruct;
+
+ return 0;
+
+err:
+ sock_kfree_s(sk, ctx, len);
+ return ret;
+}
+
+static const struct af_alg_type algif_type_rng = {
+ .bind = rng_bind,
+ .release = rng_release,
+ .accept = rng_accept_parent,
+ .ops = &algif_rng_ops,
+ .name = "rng",
+ .owner = THIS_MODULE
+};
+
+static int __init rng_init(void)
+{
+ return af_alg_register_type(&algif_type_rng);
+}
+
+void __exit rng_exit(void)
+{
+ int err = af_alg_unregister_type(&algif_type_rng);
+ BUG_ON(err);
+}
+
+module_init(rng_init);
+module_exit(rng_exit);
--
2.1.0
^ permalink raw reply related
* [PATCH v2 06/10] crypto: AF_ALG: make setkey optional
From: Stephan Mueller @ 2014-11-16 2:26 UTC (permalink / raw)
To: Herbert Xu
Cc: Daniel Borkmann, quentin.gouchet-Re5JQEeQqe8AvxtiuMwx3w, LKML,
linux-crypto-u79uwXL29TY76Z2rM5mHXA, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC-PJstQz4BMNNP20K/wil9xYQuADTiUCJX@public.gmane.org>
The current AF_ALG implementation requires that a userspace interface
implementation must provide a callback for setkey. Such a call is not
appliable to random number generators.
To prepare AF_ALG for the addition of a random number generator user
space interface, this function callback invocation is made optional.
Signed-off-by: Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org>
---
crypto/af_alg.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 635140b..47a199c 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -177,6 +177,9 @@ static int alg_setkey(struct sock *sk, char __user *ukey,
u8 *key;
int err;
+ if (!type->setkey)
+ return -EOPNOTSUPP;
+
key = sock_kmalloc(sk, keylen, GFP_KERNEL);
if (!key)
return -ENOMEM;
--
2.1.0
^ permalink raw reply related
* [PATCH v2 05/10] crypto: AF_ALG: add AEAD support
From: Stephan Mueller @ 2014-11-16 2:26 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
This patch adds the AEAD support for AF_ALG.
The AEAD implementation uses the entire memory handling and
infrastructure of the existing skcipher implementation.
To use AEAD, the user space consumer has to use the salg_type named
"aead". The AEAD extension only uses the bind callback as the key
differentiator. The previously added functions that select whether to
use AEAD or ablkcipher crypto API functions depend on the TFM type
allocated during the bind() call.
The addition of AEAD brings a bit of overhead to calculate the size of
the ciphertext, because the AEAD implementation of the kernel crypto API
makes implied assumption on the location of the authentication tag. When
performing an encryption, the tag will be added to the created
ciphertext (note, the tag is placed adjacent to the ciphertext). For
decryption, the caller must hand in the ciphertext with the tag appended
to the ciphertext. Therefore, the selection of the used memory
needs to add/subtract the tag size from the source/destination buffers
depending on the encryption type. The code is provided with comments
explainint when and how that operation is performed.
Note: The AF_ALG interface does not support zero length plaintext or
zero length ciphertext. Such zero length input data may be used if one
wants to access the hash implementation of an AEAD directly (e.g. the
GHASH of GCM or CMAC for CCM). However, this is a use case that is not
of interest. GHASH or CMAC is directly available via the hash AF_ALG
interface and we therefore do not need to take precautions for this
use case.
A fully working example using all aspects of AEAD is provided at
http://www.chronox.de/libkcapi.html
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/algif_skcipher.c | 155 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 145 insertions(+), 10 deletions(-)
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index d0e31ab..4bb7556 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -49,7 +49,7 @@ struct skcipher_ctx {
bool aead;
void *aead_assoc;
/* define arbitrary maximum length of associated data */
- #define MAX_AEAD_ASSOCLEN 128
+#define MAX_AEAD_ASSOCLEN 128
struct scatterlist sg_aead_assoc;
union {
struct ablkcipher_request ablkcipher_req;
@@ -387,6 +387,17 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
if (con.iv && con.iv->ivlen != ivsize)
return -EINVAL;
+
+ /*
+ * AEAD associated data is limited to a sensible size
+ * Size limit is set to some arbitrary length to avoid
+ * user space eating up memory
+ */
+ if (ctx->aead &&
+ (con.aead_assoc->aead_assoclen > MAX_AEAD_ASSOCLEN ||
+ !con.aead_assoc->aead_assoclen ||
+ !con.aead_assoc || !con.aead_authsize))
+ return -EINVAL;
}
err = -EINVAL;
@@ -399,6 +410,25 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
ctx->enc = enc;
if (con.iv)
memcpy(ctx->iv, con.iv->iv, ivsize);
+ /* AEAD authentication data handling */
+ if (ctx->aead) {
+ if (con.aead_authsize)
+ err = crypto_aead_setauthsize(
+ crypto_aead_reqtfm(&ctx->u.aead_req),
+ con.aead_authsize);
+ if (err)
+ goto unlock;
+ /* set associated data */
+ memcpy(ctx->aead_assoc,
+ con.aead_assoc->aead_assoc,
+ con.aead_assoc->aead_assoclen);
+ sg_init_one(&ctx->sg_aead_assoc,
+ ctx->aead_assoc,
+ con.aead_assoc->aead_assoclen);
+ aead_request_set_assoc(&ctx->u.aead_req,
+ &ctx->sg_aead_assoc,
+ con.aead_assoc->aead_assoclen);
+ }
}
while (size) {
@@ -547,10 +577,41 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
int err = -EAGAIN;
int used;
long copied = 0;
+ unsigned int aead_authsize_enc = 0;
+ unsigned int aead_authsize_dec = 0;
lock_sock(sk);
+ /*
+ * AEAD memory structure: For encryption, the tag is appended to the
+ * ciphertext which implies that the memory allocated for the ciphertext
+ * must be increased by the tag length. For decryption, the tag
+ * is expected to be concatenated to the ciphertext. The plaintext
+ * therefore has a memory size of the ciphertext minus the tag length.
+ *
+ * Note: this memory calculation only works because we require the
+ * user space caller to:
+ * * perform encryption by invoking the recv function with a buffer
+ * length of ciphertext + tag size -- the send function can be
+ * invoked normally with just the plaintext.
+ * * perform a decryption by invoking the the write function with
+ * a buffer holding the ciphertext + tag (and setting the
+ * buffer size accordingly) -- the recv function can be invoked
+ * normally with just the space needed for the ciphertext.
+ * Though, the caller should check for EBADMSG to catch integiry
+ * violations.
+ */
+ if (ctx->aead) {
+ if (ctx->enc)
+ aead_authsize_enc = crypto_aead_authsize(
+ crypto_aead_reqtfm(&ctx->u.aead_req));
+ else
+ aead_authsize_dec = crypto_aead_authsize(
+ crypto_aead_reqtfm(&ctx->u.aead_req));
+ }
+
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
iovlen--, iov++) {
+ /* size of the output data memory */
unsigned long seglen = iov->iov_len;
char __user *from = iov->iov_base;
@@ -562,6 +623,7 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
while (!sg->length)
sg++;
+ /* size of the input data memory */
used = ctx->used;
if (!used) {
err = skcipher_wait_for_data(sk, flags);
@@ -569,7 +631,28 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
goto unlock;
}
- used = min_t(unsigned long, used, seglen);
+ used = min_t(unsigned long,
+ /*
+ * In case of encryption, add
+ * the memory needed for the tag
+ * to the input data length to
+ * give the cipher the necessary
+ * space to add the tag.
+ */
+ used + aead_authsize_enc,
+ /*
+ * In case of decryption, add the
+ * memory needed for the tag
+ * calculations to the output
+ * buffer.
+ */
+ seglen + aead_authsize_dec);
+
+ if (used < aead_authsize_enc ||
+ seglen < aead_authsize_dec) {
+ err = -ENOMEM;
+ goto unlock;
+ }
used = af_alg_make_sg(&ctx->rsgl, from, used, 1);
err = used;
@@ -583,9 +666,16 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
if (!used)
goto free;
- ablkcipher_request_set_crypt(&ctx->req, sg,
- ctx->rsgl.sg, used,
- ctx->iv);
+ /*
+ * See API specification of the AEAD API: for
+ * encryption, we need to tell the encrypt function
+ * what the size of the plaintext is. But we have
+ * ensured that we have sufficient memory allocated for
+ * the operation.
+ */
+ skcipher_crypto_set_crypt(ctx, sg, ctx->rsgl.sg,
+ used - aead_authsize_enc,
+ ctx->iv);
err = af_alg_wait_for_completion(
ctx->enc ?
@@ -599,10 +689,19 @@ free:
if (err)
goto unlock;
- copied += used;
- from += used;
- seglen -= used;
- skcipher_pull_sgl(sk, used);
+ /*
+ * Adjust the output buffer counters by only the size
+ * needed for the plaintext in case of a decryption
+ */
+ copied += (used - aead_authsize_dec);
+ from += (used - aead_authsize_dec);
+ seglen -= (used - aead_authsize_dec);
+ /*
+ * Adjust the input buffer by how much we have encrypted
+ * or decrypted. In case of encryption, we only credit
+ * the memory of the plaintext.
+ */
+ skcipher_pull_sgl(sk, used - aead_authsize_enc);
}
}
@@ -724,6 +823,10 @@ static void skcipher_sock_destruct(struct sock *sk)
unsigned int ivlen = skcipher_crypto_ivsize_ctx(ctx);
skcipher_free_sgl(sk);
+ if (ctx->aead) {
+ memzero_explicit(ctx->aead_assoc, MAX_AEAD_ASSOCLEN);
+ sock_kfree_s(sk, ctx->aead_assoc, MAX_AEAD_ASSOCLEN);
+ }
memzero_explicit(ctx->iv, ivlen);
sock_kfree_s(sk, ctx->iv, ivlen);
sock_kfree_s(sk, ctx, ctx->len);
@@ -749,6 +852,17 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
memset(ctx->iv, 0, ivlen);
+ if (skcipher_is_aead(private)) {
+ ctx->aead_assoc = sock_kmalloc(sk, MAX_AEAD_ASSOCLEN,
+ GFP_KERNEL);
+ if (!ctx->aead_assoc) {
+ sock_kfree_s(sk, ctx->iv, ivlen);
+ sock_kfree_s(sk, ctx, len);
+ return -ENOMEM;
+ }
+ memset(ctx->aead_assoc, 0, MAX_AEAD_ASSOCLEN);
+ }
+
INIT_LIST_HEAD(&ctx->tsgl);
ctx->len = len;
ctx->used = 0;
@@ -779,15 +893,36 @@ static const struct af_alg_type algif_type_skcipher = {
.owner = THIS_MODULE
};
+static void *aead_bind(const char *name, u32 type, u32 mask)
+{
+ return crypto_alloc_aead(name, type, mask);
+}
+
+static const struct af_alg_type algif_type_aead = {
+ .bind = aead_bind,
+ .release = skcipher_release,
+ .setkey = skcipher_setkey,
+ .accept = skcipher_accept_parent,
+ .ops = &algif_skcipher_ops,
+ .name = "aead",
+ .owner = THIS_MODULE
+};
+
static int __init algif_skcipher_init(void)
{
- return af_alg_register_type(&algif_type_skcipher);
+ int ret = af_alg_register_type(&algif_type_skcipher);
+
+ if (ret)
+ return ret;
+ return af_alg_register_type(&algif_type_aead);
}
static void __exit algif_skcipher_exit(void)
{
int err = af_alg_unregister_type(&algif_type_skcipher);
BUG_ON(err);
+ err = af_alg_unregister_type(&algif_type_aead);
+ BUG_ON(err);
}
module_init(algif_skcipher_init);
--
2.1.0
^ permalink raw reply related
* [PATCH v2 04/10] crypto: AF_ALG: crypto API calls to inline functions
From: Stephan Mueller @ 2014-11-16 2:25 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
To avoid excessive branches and cluttering the code, all kernel crypto
API calls are extracted into separate inline functions. These functions
invoke either the ablkcipher or the aead crypto API function calls, as
necessary.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/algif_skcipher.c | 143 ++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 125 insertions(+), 18 deletions(-)
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 483ff97..d0e31ab 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -247,14 +247,121 @@ static void skcipher_data_wakeup(struct sock *sk)
rcu_read_unlock();
}
+static inline bool skcipher_is_aead(struct crypto_tfm *tfm)
+{
+ return ((crypto_tfm_alg_type(tfm) & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_AEAD);
+}
+
+static inline unsigned int skcipher_crypto_ivsize(void *private)
+{
+ if (skcipher_is_aead(private))
+ return crypto_aead_ivsize(private);
+ else
+ return crypto_ablkcipher_ivsize(private);
+}
+
+static inline unsigned int skcipher_crypto_ivsize_ctx(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_ivsize(crypto_aead_reqtfm(&ctx->u.aead_req));
+ else
+ return crypto_ablkcipher_ivsize(
+ crypto_ablkcipher_reqtfm(&ctx->u.ablkcipher_req));
+}
+
+static inline unsigned int skcipher_crypto_blocksize(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_blocksize(
+ crypto_aead_reqtfm(&ctx->u.aead_req));
+ else
+ return crypto_ablkcipher_blocksize(
+ crypto_ablkcipher_reqtfm(&ctx->u.ablkcipher_req));
+}
+
+static inline unsigned int skcipher_crypto_reqsize(void *private)
+{
+ if (skcipher_is_aead(private))
+ return crypto_aead_reqsize(private);
+ else
+ return crypto_ablkcipher_reqsize(private);
+}
+
+static inline unsigned int skcipher_crypto_setkey(void *private, const u8 *key,
+ unsigned int keylen)
+{
+ if (skcipher_is_aead(private))
+ return crypto_aead_setkey(private, key, keylen);
+ else
+ return crypto_ablkcipher_setkey(private, key, keylen);
+}
+
+static inline void skcipher_crypto_free(void *private)
+{
+ if (skcipher_is_aead(private))
+ crypto_free_aead(private);
+ else
+ crypto_free_ablkcipher(private);
+}
+
+static inline void skcipher_request_set_tfm(struct skcipher_ctx *ctx, void *tfm)
+{
+ if (ctx->aead)
+ aead_request_set_tfm(&ctx->u.aead_req, tfm);
+ else
+ ablkcipher_request_set_tfm(&ctx->u.ablkcipher_req, tfm);
+}
+
+static inline int skcipher_crypto_encrypt(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_encrypt(&ctx->u.aead_req);
+ else
+ return crypto_ablkcipher_encrypt(&ctx->u.ablkcipher_req);
+}
+
+static inline int skcipher_crypto_decrypt(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_decrypt(&ctx->u.aead_req);
+ else
+ return crypto_ablkcipher_decrypt(&ctx->u.ablkcipher_req);
+}
+
+static inline void skcipher_crypto_set_crypt(struct skcipher_ctx *ctx,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+ unsigned int cryptlen, u8 *iv)
+{
+ if (ctx->aead)
+ return aead_request_set_crypt(&ctx->u.aead_req, src, dst,
+ cryptlen, iv);
+ else
+ return ablkcipher_request_set_crypt(&ctx->u.ablkcipher_req, src,
+ dst, cryptlen, iv);
+}
+
+static inline void skcipher_request_set_callback(struct skcipher_ctx *ctx,
+ u32 flags,
+ crypto_completion_t complete,
+ void *data)
+{
+ if (ctx->aead)
+ aead_request_set_callback(&ctx->u.aead_req, flags, complete,
+ data);
+ else
+ ablkcipher_request_set_callback(&ctx->u.ablkcipher_req, flags,
+ complete, data);
+}
+
static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
- struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
- unsigned ivsize = crypto_ablkcipher_ivsize(tfm);
+ unsigned ivsize = skcipher_crypto_ivsize_ctx(ctx);
struct skcipher_sg_list *sgl;
struct af_alg_control con = {};
long copied = 0;
@@ -432,8 +539,7 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
- unsigned bs = crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(
- &ctx->req));
+ unsigned bs = skcipher_crypto_blocksize(ctx);
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
unsigned long iovlen;
@@ -483,8 +589,8 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
err = af_alg_wait_for_completion(
ctx->enc ?
- crypto_ablkcipher_encrypt(&ctx->req) :
- crypto_ablkcipher_decrypt(&ctx->req),
+ skcipher_crypto_encrypt(ctx) :
+ skcipher_crypto_decrypt(ctx),
&ctx->completion);
free:
@@ -603,23 +709,23 @@ static void *skcipher_bind(const char *name, u32 type, u32 mask)
static void skcipher_release(void *private)
{
- crypto_free_ablkcipher(private);
+ skcipher_crypto_free(private);
}
static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
{
- return crypto_ablkcipher_setkey(private, key, keylen);
+ return skcipher_crypto_setkey(private, key, keylen);
}
static void skcipher_sock_destruct(struct sock *sk)
{
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
- struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
+ unsigned int ivlen = skcipher_crypto_ivsize_ctx(ctx);
skcipher_free_sgl(sk);
- memzero_explicit(ctx->iv, crypto_ablkcipher_ivsize(tfm));
- sock_kfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm));
+ memzero_explicit(ctx->iv, ivlen);
+ sock_kfree_s(sk, ctx->iv, ivlen);
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
}
@@ -628,20 +734,20 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
{
struct skcipher_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
- unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(private);
+ unsigned int len = sizeof(*ctx) + skcipher_crypto_reqsize(private);
+ unsigned int ivlen = skcipher_crypto_ivsize(private);
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
return -ENOMEM;
- ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private),
- GFP_KERNEL);
+ ctx->iv = sock_kmalloc(sk, ivlen, GFP_KERNEL);
if (!ctx->iv) {
sock_kfree_s(sk, ctx, len);
return -ENOMEM;
}
- memset(ctx->iv, 0, crypto_ablkcipher_ivsize(private));
+ memset(ctx->iv, 0, ivlen);
INIT_LIST_HEAD(&ctx->tsgl);
ctx->len = len;
@@ -649,13 +755,14 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
ctx->more = 0;
ctx->merge = 0;
ctx->enc = 0;
+ ctx->aead = skcipher_is_aead(private);
af_alg_init_completion(&ctx->completion);
ask->private = ctx;
- ablkcipher_request_set_tfm(&ctx->req, private);
- ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- af_alg_complete, &ctx->completion);
+ skcipher_request_set_tfm(ctx, private);
+ skcipher_request_set_callback(ctx, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ af_alg_complete, &ctx->completion);
sk->sk_destruct = skcipher_sock_destruct;
--
2.1.0
^ permalink raw reply related
* [PATCH v2 03/10] crypto: AF_ALG: extend data structuers for AEAD
From: Stephan Mueller @ 2014-11-16 2:25 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
The data structure holding the state of an ongoing symmetric cipher
operation is extended by the data variables needed for AEAD.
The request data structures are encapsulated by a union as the symmetric
cipher implementation is either exclusively used for "normal" symmetric
ciphers or for AEAD ciphers.
The define MAX_AEAD_ASSOCLEN restricts the size of the associated
authentication data. The kernel must allocate memory for this data to be
stored for the cipher operation. To prevent an excessive use of memory,
it is limited to 128 bytes, which is considered to be a sensible size.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/algif_skcipher.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 2f5d663..483ff97 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -46,7 +46,15 @@ struct skcipher_ctx {
bool merge;
bool enc;
- struct ablkcipher_request req;
+ bool aead;
+ void *aead_assoc;
+ /* define arbitrary maximum length of associated data */
+ #define MAX_AEAD_ASSOCLEN 128
+ struct scatterlist sg_aead_assoc;
+ union {
+ struct ablkcipher_request ablkcipher_req;
+ struct aead_request aead_req;
+ } u;
};
#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
--
2.1.0
^ permalink raw reply related
* [PATCH v2 02/10] crypto: AF_ALG: user space interface for cipher info
From: Stephan Mueller @ 2014-11-16 2:24 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
The AF_ALG interface allows normal cipher (hash, encrypt, decrypt).
However, it does not allow user space to obtain the following generic
information about the currently active cipher:
* block size of the cipher
* IV size of the cipher
* for AEAD, the maximum authentication tag size
The patch adds a getsockopt interface for the symmetric ciphers to
answer such information requests from user space.
The kernel crypto API function calls are used to obtain the real data.
As all data are simple integer values, the getsockopt handler function
uses put_user() to return the integer value to user space in the
*optval parameter of getsockopt.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/algif_skcipher.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
include/uapi/linux/if_alg.h | 7 +++++++
2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 85e3bdb..2f5d663 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -522,6 +522,50 @@ static unsigned int skcipher_poll(struct file *file, struct socket *sock,
return mask;
}
+static int skcipher_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
+ struct skcipher_ctx *ctx = ask->private;
+ const struct af_alg_type *type;
+ int len = 0;
+ int err = -EOPNOTSUPP;
+
+ lock_sock(sk);
+ type = ask->type;
+
+ if (level != SOL_ALG || !type)
+ goto unlock;
+
+ switch (optname) {
+ case ALG_GET_BLOCKSIZE:
+ len = skcipher_crypto_blocksize(ctx);
+ err = 0;
+ break;
+ case ALG_GET_IVSIZE:
+ len = skcipher_crypto_ivsize_ctx(ctx);
+ err = 0;
+ break;
+ case ALG_GET_AEAD_AUTHSIZE:
+ if (ctx->aead) {
+ len = crypto_aead_authsize(crypto_aead_reqtfm(
+ &ctx->u.aead_req));
+ err = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+unlock:
+ release_sock(sk);
+ if (err >= 0)
+ err = put_user(len, optlen);
+
+ return err;
+}
+
static struct proto_ops algif_skcipher_ops = {
.family = PF_ALG,
@@ -531,7 +575,6 @@ static struct proto_ops algif_skcipher_ops = {
.ioctl = sock_no_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
- .getsockopt = sock_no_getsockopt,
.mmap = sock_no_mmap,
.bind = sock_no_bind,
.accept = sock_no_accept,
@@ -542,6 +585,7 @@ static struct proto_ops algif_skcipher_ops = {
.sendpage = skcipher_sendpage,
.recvmsg = skcipher_recvmsg,
.poll = skcipher_poll,
+ .getsockopt = skcipher_getsockopt,
};
static void *skcipher_bind(const char *name, u32 type, u32 mask)
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index 64e7008..b8fb714 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -40,8 +40,15 @@ struct af_alg_aead_assoc {
#define ALG_SET_AEAD_ASSOC 4
#define ALG_SET_AEAD_AUTHSIZE 5
+/* getsockopt options */
+#define ALG_GET_BLOCKSIZE 1
+#define ALG_GET_IVSIZE 2
+#define ALG_GET_AEAD_AUTHSIZE 3
+
/* Operations */
#define ALG_OP_DECRYPT 0
#define ALG_OP_ENCRYPT 1
+
+
#endif /* _LINUX_IF_ALG_H */
--
2.1.0
^ permalink raw reply related
* [PATCH v2 01/10] crypto: AF_ALG: add user space interface for AEAD
From: Stephan Mueller @ 2014-11-16 2:23 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
In-Reply-To: <5365136.g8vbXlhRyC@tachyon.chronox.de>
AEAD requires the following data in addition to normal symmetric
ciphers:
* Associated authentication data of arbitrary length
* Authentication tag for decryption
* Length of authentication tag for encryption
The authentication tag data is communicated as part of the actual
ciphertext as mandated by the kernel crypto API. Therefore we only need
to provide a user space interface for the associated authentication data
as well as for the authentication tag length.
This patch adds both as a setsockopt interface that is identical to the
AF_ALG interface for setting an IV and for selecting the cipher
operation type (encrypt or decrypt).
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
crypto/af_alg.c | 17 +++++++++++++++++
include/crypto/if_alg.h | 2 ++
include/uapi/linux/if_alg.h | 7 +++++++
3 files changed, 26 insertions(+)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 6a3ad80..635140b 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -421,6 +421,23 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
con->op = *(u32 *)CMSG_DATA(cmsg);
break;
+
+ case ALG_SET_AEAD_AUTHSIZE:
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
+ return -EINVAL;
+ con->aead_authsize = *(u32 *)CMSG_DATA(cmsg);
+ break;
+
+ case ALG_SET_AEAD_ASSOC:
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->aead_assoc)))
+ return -EINVAL;
+ con->aead_assoc = (void *)CMSG_DATA(cmsg);
+ if (cmsg->cmsg_len <
+ CMSG_LEN(con->aead_assoc->aead_assoclen +
+ sizeof(*con->aead_assoc)))
+ return -EINVAL;
+ break;
+
default:
return -EINVAL;
}
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index d61c111..c741483 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -41,7 +41,9 @@ struct af_alg_completion {
struct af_alg_control {
struct af_alg_iv *iv;
+ struct af_alg_aead_assoc *aead_assoc;
int op;
+ unsigned int aead_authsize;
};
struct af_alg_type {
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index 0f9acce..64e7008 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -28,10 +28,17 @@ struct af_alg_iv {
__u8 iv[0];
};
+struct af_alg_aead_assoc {
+ __u32 aead_assoclen;
+ __u8 aead_assoc[0];
+};
+
/* Socket options */
#define ALG_SET_KEY 1
#define ALG_SET_IV 2
#define ALG_SET_OP 3
+#define ALG_SET_AEAD_ASSOC 4
+#define ALG_SET_AEAD_AUTHSIZE 5
/* Operations */
#define ALG_OP_DECRYPT 0
--
2.1.0
^ permalink raw reply related
* [PATCH v2 00/10] crypto: AF_ALG: add AEAD and RNG support
From: Stephan Mueller @ 2014-11-16 2:23 UTC (permalink / raw)
To: Herbert Xu; +Cc: Daniel Borkmann, quentin.gouchet, LKML, linux-crypto, ABI/API
Hi,
This patch set adds AEAD and RNG support to the AF_ALG interface
exported by the kernel crypto API. By extending AF_ALG with AEAD and RNG
support, all cipher types the kernel crypto API allows access to are
now accessible from userspace.
The RNG support is stand-alone.
The AEAD implementation is added to algif_skcipher.c to prevent
re-implementation of the memory moving logic.
The extension for the AEAD support can be summarized with the following
types of changes:
* select the correct crypto API functions (either the ablkcipher
or the aead functions)
* apply the additional data needed for AEAD at the right time
(associated data, authentication tag) -- this includes the addition
of user space interfaces to allow setting this data.
* add the calculation for the memory size needed for encryption and
decryption.
In addition, the patch set adds a getsockopt implementation to skcipher to
allow user space to inquire about properties of the ciphers (IV size,
block size, authentication data size). This extension would be needed for a
generic user space usage of these ciphers.
The new AEAD and RNG interfaces are fully tested with the test application
provided at [1]. That test application exercises all newly added user space
interfaces.
The patch set was tested on x86_64 and i386.
[1] http://www.chronox.de/libkcapi.html
Changes v2:
* rebase to current cryptodev-2.6 tree
* use memzero_explicit to zeroize AEAD associated data
* use sizeof for determining length of AEAD associated data
* update algif_rng.c covering all suggestions from Daniel Borkmann
<dborkman@redhat.com>
* addition of patch 9: add digestsize interface for hashes
* addition of patch to update documentation covering the userspace interface
* change numbers of getsockopt options: separate them from sendmsg interface
definitions
Stephan Mueller (10):
crypto: AF_ALG: add user space interface for AEAD
crypto: AF_ALG: user space interface for cipher info
crypto: AF_ALG: extend data structuers for AEAD
crypto: AF_ALG: crypto API calls to inline functions
crypto: AF_ALG: add AEAD support
crypto: AF_ALG: make setkey optional
crypto: AF_ALG: add random number generator support
crypto: AF_ALG: enable RNG interface compilation
crypto: AF_ALG: user space interface for hash info
crypto: AF_ALG: document the user space interface
Documentation/crypto/crypto-API-userspace.txt | 95 ++++++-
crypto/Kconfig | 9 +
crypto/Makefile | 1 +
crypto/af_alg.c | 20 ++
crypto/algif_hash.c | 35 ++-
crypto/algif_rng.c | 186 ++++++++++++++
crypto/algif_skcipher.c | 352 +++++++++++++++++++++++---
include/crypto/if_alg.h | 2 +
include/uapi/linux/if_alg.h | 15 ++
9 files changed, 683 insertions(+), 32 deletions(-)
create mode 100644 crypto/algif_rng.c
--
2.1.0
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox