From: ebiederm@xmission.com (Eric W. Biederman)
To: Christian Brauner <christian.brauner@ubuntu.com>
Cc: linux-kernel@vger.kernel.org, serge@hallyn.com, tycho@tycho.ws,
Linux Containers <containers@lists.linux-foundation.org>
Subject: [PATCH 2/5] userns: Simplify the user and group mapping functions
Date: Tue, 31 Oct 2017 18:47:43 -0500 [thread overview]
Message-ID: <87po92swv4.fsf_-_@xmission.com> (raw)
In-Reply-To: <871sliubhj.fsf_-_@xmission.com> (Eric W. Biederman's message of "Tue, 31 Oct 2017 18:46:32 -0500")
Consolidate reading the number of extents and computing the return
value in the map_id_down, map_id_range_down and map_id_range.
This removal of one read of extents makes one smp_rmb unnecessary
and makes the code safe it is executed during the map write. Reading
the number of extents twice and depending on the result being the same
is not safe, as it could be 0 the first time and > 5 the second time,
which would lead to misinterpreting the union fields.
The consolidation of the return value just removes a duplicate
caluculation which should make it easier to understand and maintain
the code.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
kernel/user_namespace.c | 132 +++++++++++++++++++++---------------------------
1 file changed, 58 insertions(+), 74 deletions(-)
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index c9904ee084c4..563a2981d7c7 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -256,28 +256,17 @@ static int cmp_map_id(const void *k, const void *e)
* map_id_range_down_max - Find idmap via binary search in ordered idmap array.
* Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
*/
-static u32 map_id_range_down_max(struct uid_gid_map *map, u32 id, u32 count)
+static struct uid_gid_extent *
+map_id_range_down_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
{
- u32 extents;
- struct uid_gid_extent *extent;
struct idmap_key key;
key.map_up = false;
key.count = count;
key.id = id;
- extents = map->nr_extents;
- smp_rmb();
-
- extent = bsearch(&key, map->forward, extents,
- sizeof(struct uid_gid_extent), cmp_map_id);
- /* Map the id or note failure */
- if (extent)
- id = (id - extent->first) + extent->lower_first;
- else
- id = (u32) -1;
-
- return id;
+ return bsearch(&key, map->forward, extents,
+ sizeof(struct uid_gid_extent), cmp_map_id);
}
/**
@@ -285,41 +274,43 @@ static u32 map_id_range_down_max(struct uid_gid_map *map, u32 id, u32 count)
* Can only be called if number of mappings is equal or less than
* UID_GID_MAP_MAX_BASE_EXTENTS.
*/
-static u32 map_id_range_down_base(struct uid_gid_map *map, u32 id, u32 count)
+static struct uid_gid_extent *
+map_id_range_down_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
{
- unsigned idx, extents;
+ unsigned idx;
u32 first, last, id2;
id2 = id + count - 1;
/* Find the matching extent */
- extents = map->nr_extents;
- smp_rmb();
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].first;
last = first + map->extent[idx].count - 1;
if (id >= first && id <= last &&
(id2 >= first && id2 <= last))
- break;
+ return &map->extent[idx];
}
- /* Map the id or note failure */
- if (idx < extents)
- id = (id - first) + map->extent[idx].lower_first;
- else
- id = (u32) -1;
-
- return id;
+ return NULL;
}
static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
{
- u32 extents = map->nr_extents;
+ struct uid_gid_extent *extent;
+ unsigned extents = map->nr_extents;
smp_rmb();
if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
- return map_id_range_down_base(map, id, count);
+ extent = map_id_range_down_base(extents, map, id, count);
+ else
+ extent = map_id_range_down_max(extents, map, id, count);
- return map_id_range_down_max(map, id, count);
+ /* Map the id or note failure */
+ if (extent)
+ id = (id - extent->first) + extent->lower_first;
+ else
+ id = (u32) -1;
+
+ return id;
}
/**
@@ -327,38 +318,40 @@ static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
* Can only be called if number of mappings is equal or less than
* UID_GID_MAP_MAX_BASE_EXTENTS.
*/
-static u32 map_id_down_base(struct uid_gid_map *map, u32 id)
+static struct uid_gid_extent *
+map_id_down_base(unsigned extents, struct uid_gid_map *map, u32 id)
{
- unsigned idx, extents;
+ unsigned idx;
u32 first, last;
/* Find the matching extent */
- extents = map->nr_extents;
- smp_rmb();
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].first;
last = first + map->extent[idx].count - 1;
if (id >= first && id <= last)
- break;
+ return &map->extent[idx];
}
- /* Map the id or note failure */
- if (idx < extents)
- id = (id - first) + map->extent[idx].lower_first;
- else
- id = (u32) -1;
-
- return id;
+ return NULL;
}
static u32 map_id_down(struct uid_gid_map *map, u32 id)
{
- u32 extents = map->nr_extents;
+ struct uid_gid_extent *extent;
+ unsigned extents = map->nr_extents;
smp_rmb();
if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
- return map_id_down_base(map, id);
+ extent = map_id_down_base(extents, map, id);
+ else
+ extent = map_id_range_down_max(extents, map, id, 1);
- return map_id_range_down_max(map, id, 1);
+ /* Map the id or note failure */
+ if (extent)
+ id = (id - extent->first) + extent->lower_first;
+ else
+ id = (u32) -1;
+
+ return id;
}
/**
@@ -366,48 +359,50 @@ static u32 map_id_down(struct uid_gid_map *map, u32 id)
* Can only be called if number of mappings is equal or less than
* UID_GID_MAP_MAX_BASE_EXTENTS.
*/
-static u32 map_id_up_base(struct uid_gid_map *map, u32 id)
+static struct uid_gid_extent *
+map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id)
{
- unsigned idx, extents;
+ unsigned idx;
u32 first, last;
/* Find the matching extent */
- extents = map->nr_extents;
- smp_rmb();
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].lower_first;
last = first + map->extent[idx].count - 1;
if (id >= first && id <= last)
- break;
+ return &map->extent[idx];
}
- /* Map the id or note failure */
- if (idx < extents)
- id = (id - first) + map->extent[idx].first;
- else
- id = (u32) -1;
-
- return id;
+ return NULL;
}
/**
* map_id_up_max - Find idmap via binary search in ordered idmap array.
* Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
*/
-static u32 map_id_up_max(struct uid_gid_map *map, u32 id)
+static struct uid_gid_extent *
+map_id_up_max(unsigned extents, struct uid_gid_map *map, u32 id)
{
- u32 extents;
- struct uid_gid_extent *extent;
struct idmap_key key;
key.map_up = true;
key.count = 1;
key.id = id;
- extents = map->nr_extents;
+ return bsearch(&key, map->reverse, extents,
+ sizeof(struct uid_gid_extent), cmp_map_id);
+}
+
+static u32 map_id_up(struct uid_gid_map *map, u32 id)
+{
+ struct uid_gid_extent *extent;
+ unsigned extents = map->nr_extents;
smp_rmb();
- extent = bsearch(&key, map->reverse, extents,
- sizeof(struct uid_gid_extent), cmp_map_id);
+ if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
+ extent = map_id_up_base(extents, map, id);
+ else
+ extent = map_id_up_max(extents, map, id);
+
/* Map the id or note failure */
if (extent)
id = (id - extent->lower_first) + extent->first;
@@ -417,17 +412,6 @@ static u32 map_id_up_max(struct uid_gid_map *map, u32 id)
return id;
}
-static u32 map_id_up(struct uid_gid_map *map, u32 id)
-{
- u32 extents = map->nr_extents;
- smp_rmb();
-
- if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
- return map_id_up_base(map, id);
-
- return map_id_up_max(map, id);
-}
-
/**
* make_kuid - Map a user-namespace uid pair into a kuid.
* @ns: User namespace that the uid is in
--
2.14.1
next prev parent reply other threads:[~2017-10-31 23:47 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-24 22:04 [PATCH 1/2 v6] user namespace: use union in {g,u}idmap struct Christian Brauner
2017-10-24 22:04 ` [PATCH 2/2 v6] user namespaces: bump idmap limits to 340 Christian Brauner
2017-10-31 23:46 ` [PATCH 0/5] userns: bump idmap limits, fixes & tweaks Eric W. Biederman
2017-10-31 23:47 ` [PATCH 1/5] userns: Don't special case a count of 0 Eric W. Biederman
2017-10-31 23:47 ` Eric W. Biederman [this message]
2017-10-31 23:48 ` [PATCH 3/5] userns: Don't read extents twice in m_start Eric W. Biederman
2017-11-01 8:31 ` Nikolay Borisov
2017-11-01 11:08 ` Eric W. Biederman
2017-11-01 13:05 ` Nikolay Borisov
2017-11-01 13:05 ` Peter Zijlstra
2017-11-01 14:01 ` Christian Brauner
2017-11-01 14:16 ` Peter Zijlstra
2017-11-01 16:29 ` Christian Brauner
2017-11-01 16:31 ` Christian Brauner
2017-11-01 17:00 ` Joe Perches
2017-11-01 17:20 ` Eric W. Biederman
2017-11-01 18:15 ` Peter Zijlstra
2017-10-31 23:48 ` [PATCH 4/5] userns: Make map_id_down a wrapper for map_id_range_down Eric W. Biederman
2017-10-31 23:49 ` [PATCH 5/5] userns: Simplify insert_extent Eric W. Biederman
2017-11-01 10:51 ` [PATCH 0/5] userns: bump idmap limits, fixes & tweaks Christian Brauner
2017-11-01 11:15 ` Eric W. Biederman
2017-11-01 13:31 ` Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87po92swv4.fsf_-_@xmission.com \
--to=ebiederm@xmission.com \
--cc=christian.brauner@ubuntu.com \
--cc=containers@lists.linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=serge@hallyn.com \
--cc=tycho@tycho.ws \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox