aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-16 15:20:15 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-16 15:20:15 -0500
commit758f875848d78148cf9a9cdb3ff1ddf29b234056 (patch)
tree78d6b1b0a1d82376f9dea8d73c2b900cb5b89679
parenta02cd4229e298aadbe8f5cf286edee8058d87116 (diff)
parent3fda0e737e906ce73220b20c27e7f792d0aac6a8 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull user namespace update from Eric Biederman: "The only change that is production ready this round is the work to increase the number of uid and gid mappings a user namespace can support from 5 to 340. This code was carefully benchmarked and it was confirmed that in the existing cases the performance remains the same. In the worst case with 340 mappings an cache cold stat times go from 158ns to 248ns. That is noticable but still quite small, and only the people who are doing crazy things pay the cost. This work uncovered some documentation and cleanup opportunities in the mapping code, and patches to make those cleanups and improve the documentation will be coming in the next merge window" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: userns: Simplify insert_extent userns: Make map_id_down a wrapper for map_id_range_down userns: Don't read extents twice in m_start userns: Simplify the user and group mapping functions userns: Don't special case a count of 0 userns: bump idmap limits to 340 userns: use union in {g,u}idmap struct
-rw-r--r--include/linux/user_namespace.h23
-rw-r--r--kernel/user.c30
-rw-r--r--kernel/user_namespace.c349
3 files changed, 325 insertions, 77 deletions
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 3fe714da7f5a..d6b74b91096b 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -11,15 +11,24 @@
11#include <linux/sysctl.h> 11#include <linux/sysctl.h>
12#include <linux/err.h> 12#include <linux/err.h>
13 13
14#define UID_GID_MAP_MAX_EXTENTS 5 14#define UID_GID_MAP_MAX_BASE_EXTENTS 5
15#define UID_GID_MAP_MAX_EXTENTS 340
15 16
16struct uid_gid_map { /* 64 bytes -- 1 cache line */ 17struct uid_gid_extent {
18 u32 first;
19 u32 lower_first;
20 u32 count;
21};
22
23struct uid_gid_map { /* 64 bytes -- 1 cache line */
17 u32 nr_extents; 24 u32 nr_extents;
18 struct uid_gid_extent { 25 union {
19 u32 first; 26 struct uid_gid_extent extent[UID_GID_MAP_MAX_BASE_EXTENTS];
20 u32 lower_first; 27 struct {
21 u32 count; 28 struct uid_gid_extent *forward;
22 } extent[UID_GID_MAP_MAX_EXTENTS]; 29 struct uid_gid_extent *reverse;
30 };
31 };
23}; 32};
24 33
25#define USERNS_SETGROUPS_ALLOWED 1UL 34#define USERNS_SETGROUPS_ALLOWED 1UL
diff --git a/kernel/user.c b/kernel/user.c
index 00281add65b2..9a20acce460d 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -26,26 +26,32 @@
26struct user_namespace init_user_ns = { 26struct user_namespace init_user_ns = {
27 .uid_map = { 27 .uid_map = {
28 .nr_extents = 1, 28 .nr_extents = 1,
29 .extent[0] = { 29 {
30 .first = 0, 30 .extent[0] = {
31 .lower_first = 0, 31 .first = 0,
32 .count = 4294967295U, 32 .lower_first = 0,
33 .count = 4294967295U,
34 },
33 }, 35 },
34 }, 36 },
35 .gid_map = { 37 .gid_map = {
36 .nr_extents = 1, 38 .nr_extents = 1,
37 .extent[0] = { 39 {
38 .first = 0, 40 .extent[0] = {
39 .lower_first = 0, 41 .first = 0,
40 .count = 4294967295U, 42 .lower_first = 0,
43 .count = 4294967295U,
44 },
41 }, 45 },
42 }, 46 },
43 .projid_map = { 47 .projid_map = {
44 .nr_extents = 1, 48 .nr_extents = 1,
45 .extent[0] = { 49 {
46 .first = 0, 50 .extent[0] = {
47 .lower_first = 0, 51 .first = 0,
48 .count = 4294967295U, 52 .lower_first = 0,
53 .count = 4294967295U,
54 },
49 }, 55 },
50 }, 56 },
51 .count = ATOMIC_INIT(3), 57 .count = ATOMIC_INIT(3),
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index d32b45662fb6..246d4d4ce5c7 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -23,6 +23,8 @@
23#include <linux/ctype.h> 23#include <linux/ctype.h>
24#include <linux/projid.h> 24#include <linux/projid.h>
25#include <linux/fs_struct.h> 25#include <linux/fs_struct.h>
26#include <linux/bsearch.h>
27#include <linux/sort.h>
26 28
27static struct kmem_cache *user_ns_cachep __read_mostly; 29static struct kmem_cache *user_ns_cachep __read_mostly;
28static DEFINE_MUTEX(userns_state_mutex); 30static DEFINE_MUTEX(userns_state_mutex);
@@ -181,6 +183,18 @@ static void free_user_ns(struct work_struct *work)
181 do { 183 do {
182 struct ucounts *ucounts = ns->ucounts; 184 struct ucounts *ucounts = ns->ucounts;
183 parent = ns->parent; 185 parent = ns->parent;
186 if (ns->gid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {
187 kfree(ns->gid_map.forward);
188 kfree(ns->gid_map.reverse);
189 }
190 if (ns->uid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {
191 kfree(ns->uid_map.forward);
192 kfree(ns->uid_map.reverse);
193 }
194 if (ns->projid_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {
195 kfree(ns->projid_map.forward);
196 kfree(ns->projid_map.reverse);
197 }
184 retire_userns_sysctls(ns); 198 retire_userns_sysctls(ns);
185#ifdef CONFIG_PERSISTENT_KEYRINGS 199#ifdef CONFIG_PERSISTENT_KEYRINGS
186 key_put(ns->persistent_keyring_register); 200 key_put(ns->persistent_keyring_register);
@@ -198,26 +212,101 @@ void __put_user_ns(struct user_namespace *ns)
198} 212}
199EXPORT_SYMBOL(__put_user_ns); 213EXPORT_SYMBOL(__put_user_ns);
200 214
201static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count) 215/**
216 * idmap_key struct holds the information necessary to find an idmapping in a
217 * sorted idmap array. It is passed to cmp_map_id() as first argument.
218 */
219struct idmap_key {
220 bool map_up; /* true -> id from kid; false -> kid from id */
221 u32 id; /* id to find */
222 u32 count; /* == 0 unless used with map_id_range_down() */
223};
224
225/**
226 * cmp_map_id - Function to be passed to bsearch() to find the requested
227 * idmapping. Expects struct idmap_key to be passed via @k.
228 */
229static int cmp_map_id(const void *k, const void *e)
202{ 230{
203 unsigned idx, extents; 231 u32 first, last, id2;
232 const struct idmap_key *key = k;
233 const struct uid_gid_extent *el = e;
234
235 id2 = key->id + key->count - 1;
236
237 /* handle map_id_{down,up}() */
238 if (key->map_up)
239 first = el->lower_first;
240 else
241 first = el->first;
242
243 last = first + el->count - 1;
244
245 if (key->id >= first && key->id <= last &&
246 (id2 >= first && id2 <= last))
247 return 0;
248
249 if (key->id < first || id2 < first)
250 return -1;
251
252 return 1;
253}
254
255/**
256 * map_id_range_down_max - Find idmap via binary search in ordered idmap array.
257 * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
258 */
259static struct uid_gid_extent *
260map_id_range_down_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
261{
262 struct idmap_key key;
263
264 key.map_up = false;
265 key.count = count;
266 key.id = id;
267
268 return bsearch(&key, map->forward, extents,
269 sizeof(struct uid_gid_extent), cmp_map_id);
270}
271
272/**
273 * map_id_range_down_base - Find idmap via binary search in static extent array.
274 * Can only be called if number of mappings is equal or less than
275 * UID_GID_MAP_MAX_BASE_EXTENTS.
276 */
277static struct uid_gid_extent *
278map_id_range_down_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
279{
280 unsigned idx;
204 u32 first, last, id2; 281 u32 first, last, id2;
205 282
206 id2 = id + count - 1; 283 id2 = id + count - 1;
207 284
208 /* Find the matching extent */ 285 /* Find the matching extent */
209 extents = map->nr_extents;
210 smp_rmb();
211 for (idx = 0; idx < extents; idx++) { 286 for (idx = 0; idx < extents; idx++) {
212 first = map->extent[idx].first; 287 first = map->extent[idx].first;
213 last = first + map->extent[idx].count - 1; 288 last = first + map->extent[idx].count - 1;
214 if (id >= first && id <= last && 289 if (id >= first && id <= last &&
215 (id2 >= first && id2 <= last)) 290 (id2 >= first && id2 <= last))
216 break; 291 return &map->extent[idx];
217 } 292 }
293 return NULL;
294}
295
296static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
297{
298 struct uid_gid_extent *extent;
299 unsigned extents = map->nr_extents;
300 smp_rmb();
301
302 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
303 extent = map_id_range_down_base(extents, map, id, count);
304 else
305 extent = map_id_range_down_max(extents, map, id, count);
306
218 /* Map the id or note failure */ 307 /* Map the id or note failure */
219 if (idx < extents) 308 if (extent)
220 id = (id - first) + map->extent[idx].lower_first; 309 id = (id - extent->first) + extent->lower_first;
221 else 310 else
222 id = (u32) -1; 311 id = (u32) -1;
223 312
@@ -226,44 +315,61 @@ static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
226 315
227static u32 map_id_down(struct uid_gid_map *map, u32 id) 316static u32 map_id_down(struct uid_gid_map *map, u32 id)
228{ 317{
229 unsigned idx, extents; 318 return map_id_range_down(map, id, 1);
319}
320
321/**
322 * map_id_up_base - Find idmap via binary search in static extent array.
323 * Can only be called if number of mappings is equal or less than
324 * UID_GID_MAP_MAX_BASE_EXTENTS.
325 */
326static struct uid_gid_extent *
327map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id)
328{
329 unsigned idx;
230 u32 first, last; 330 u32 first, last;
231 331
232 /* Find the matching extent */ 332 /* Find the matching extent */
233 extents = map->nr_extents;
234 smp_rmb();
235 for (idx = 0; idx < extents; idx++) { 333 for (idx = 0; idx < extents; idx++) {
236 first = map->extent[idx].first; 334 first = map->extent[idx].lower_first;
237 last = first + map->extent[idx].count - 1; 335 last = first + map->extent[idx].count - 1;
238 if (id >= first && id <= last) 336 if (id >= first && id <= last)
239 break; 337 return &map->extent[idx];
240 } 338 }
241 /* Map the id or note failure */ 339 return NULL;
242 if (idx < extents) 340}
243 id = (id - first) + map->extent[idx].lower_first;
244 else
245 id = (u32) -1;
246 341
247 return id; 342/**
343 * map_id_up_max - Find idmap via binary search in ordered idmap array.
344 * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
345 */
346static struct uid_gid_extent *
347map_id_up_max(unsigned extents, struct uid_gid_map *map, u32 id)
348{
349 struct idmap_key key;
350
351 key.map_up = true;
352 key.count = 1;
353 key.id = id;
354
355 return bsearch(&key, map->reverse, extents,
356 sizeof(struct uid_gid_extent), cmp_map_id);
248} 357}
249 358
250static u32 map_id_up(struct uid_gid_map *map, u32 id) 359static u32 map_id_up(struct uid_gid_map *map, u32 id)
251{ 360{
252 unsigned idx, extents; 361 struct uid_gid_extent *extent;
253 u32 first, last; 362 unsigned extents = map->nr_extents;
254
255 /* Find the matching extent */
256 extents = map->nr_extents;
257 smp_rmb(); 363 smp_rmb();
258 for (idx = 0; idx < extents; idx++) { 364
259 first = map->extent[idx].lower_first; 365 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
260 last = first + map->extent[idx].count - 1; 366 extent = map_id_up_base(extents, map, id);
261 if (id >= first && id <= last) 367 else
262 break; 368 extent = map_id_up_max(extents, map, id);
263 } 369
264 /* Map the id or note failure */ 370 /* Map the id or note failure */
265 if (idx < extents) 371 if (extent)
266 id = (id - first) + map->extent[idx].first; 372 id = (id - extent->lower_first) + extent->first;
267 else 373 else
268 id = (u32) -1; 374 id = (u32) -1;
269 375
@@ -540,13 +646,17 @@ static int projid_m_show(struct seq_file *seq, void *v)
540static void *m_start(struct seq_file *seq, loff_t *ppos, 646static void *m_start(struct seq_file *seq, loff_t *ppos,
541 struct uid_gid_map *map) 647 struct uid_gid_map *map)
542{ 648{
543 struct uid_gid_extent *extent = NULL;
544 loff_t pos = *ppos; 649 loff_t pos = *ppos;
650 unsigned extents = map->nr_extents;
651 smp_rmb();
545 652
546 if (pos < map->nr_extents) 653 if (pos >= extents)
547 extent = &map->extent[pos]; 654 return NULL;
548 655
549 return extent; 656 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
657 return &map->extent[pos];
658
659 return &map->forward[pos];
550} 660}
551 661
552static void *uid_m_start(struct seq_file *seq, loff_t *ppos) 662static void *uid_m_start(struct seq_file *seq, loff_t *ppos)
@@ -618,7 +728,10 @@ static bool mappings_overlap(struct uid_gid_map *new_map,
618 u32 prev_upper_last, prev_lower_last; 728 u32 prev_upper_last, prev_lower_last;
619 struct uid_gid_extent *prev; 729 struct uid_gid_extent *prev;
620 730
621 prev = &new_map->extent[idx]; 731 if (new_map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
732 prev = &new_map->extent[idx];
733 else
734 prev = &new_map->forward[idx];
622 735
623 prev_upper_first = prev->first; 736 prev_upper_first = prev->first;
624 prev_lower_first = prev->lower_first; 737 prev_lower_first = prev->lower_first;
@@ -638,6 +751,101 @@ static bool mappings_overlap(struct uid_gid_map *new_map,
638 return false; 751 return false;
639} 752}
640 753
754/**
755 * insert_extent - Safely insert a new idmap extent into struct uid_gid_map.
756 * Takes care to allocate a 4K block of memory if the number of mappings exceeds
757 * UID_GID_MAP_MAX_BASE_EXTENTS.
758 */
759static int insert_extent(struct uid_gid_map *map, struct uid_gid_extent *extent)
760{
761 struct uid_gid_extent *dest;
762
763 if (map->nr_extents == UID_GID_MAP_MAX_BASE_EXTENTS) {
764 struct uid_gid_extent *forward;
765
766 /* Allocate memory for 340 mappings. */
767 forward = kmalloc(sizeof(struct uid_gid_extent) *
768 UID_GID_MAP_MAX_EXTENTS, GFP_KERNEL);
769 if (!forward)
770 return -ENOMEM;
771
772 /* Copy over memory. Only set up memory for the forward pointer.
773 * Defer the memory setup for the reverse pointer.
774 */
775 memcpy(forward, map->extent,
776 map->nr_extents * sizeof(map->extent[0]));
777
778 map->forward = forward;
779 map->reverse = NULL;
780 }
781
782 if (map->nr_extents < UID_GID_MAP_MAX_BASE_EXTENTS)
783 dest = &map->extent[map->nr_extents];
784 else
785 dest = &map->forward[map->nr_extents];
786
787 *dest = *extent;
788 map->nr_extents++;
789 return 0;
790}
791
792/* cmp function to sort() forward mappings */
793static int cmp_extents_forward(const void *a, const void *b)
794{
795 const struct uid_gid_extent *e1 = a;
796 const struct uid_gid_extent *e2 = b;
797
798 if (e1->first < e2->first)
799 return -1;
800
801 if (e1->first > e2->first)
802 return 1;
803
804 return 0;
805}
806
807/* cmp function to sort() reverse mappings */
808static int cmp_extents_reverse(const void *a, const void *b)
809{
810 const struct uid_gid_extent *e1 = a;
811 const struct uid_gid_extent *e2 = b;
812
813 if (e1->lower_first < e2->lower_first)
814 return -1;
815
816 if (e1->lower_first > e2->lower_first)
817 return 1;
818
819 return 0;
820}
821
822/**
823 * sort_idmaps - Sorts an array of idmap entries.
824 * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
825 */
826static int sort_idmaps(struct uid_gid_map *map)
827{
828 if (map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
829 return 0;
830
831 /* Sort forward array. */
832 sort(map->forward, map->nr_extents, sizeof(struct uid_gid_extent),
833 cmp_extents_forward, NULL);
834
835 /* Only copy the memory from forward we actually need. */
836 map->reverse = kmemdup(map->forward,
837 map->nr_extents * sizeof(struct uid_gid_extent),
838 GFP_KERNEL);
839 if (!map->reverse)
840 return -ENOMEM;
841
842 /* Sort reverse array. */
843 sort(map->reverse, map->nr_extents, sizeof(struct uid_gid_extent),
844 cmp_extents_reverse, NULL);
845
846 return 0;
847}
848
641static ssize_t map_write(struct file *file, const char __user *buf, 849static ssize_t map_write(struct file *file, const char __user *buf,
642 size_t count, loff_t *ppos, 850 size_t count, loff_t *ppos,
643 int cap_setid, 851 int cap_setid,
@@ -648,7 +856,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
648 struct user_namespace *ns = seq->private; 856 struct user_namespace *ns = seq->private;
649 struct uid_gid_map new_map; 857 struct uid_gid_map new_map;
650 unsigned idx; 858 unsigned idx;
651 struct uid_gid_extent *extent = NULL; 859 struct uid_gid_extent extent;
652 char *kbuf = NULL, *pos, *next_line; 860 char *kbuf = NULL, *pos, *next_line;
653 ssize_t ret = -EINVAL; 861 ssize_t ret = -EINVAL;
654 862
@@ -673,6 +881,8 @@ static ssize_t map_write(struct file *file, const char __user *buf,
673 */ 881 */
674 mutex_lock(&userns_state_mutex); 882 mutex_lock(&userns_state_mutex);
675 883
884 memset(&new_map, 0, sizeof(struct uid_gid_map));
885
676 ret = -EPERM; 886 ret = -EPERM;
677 /* Only allow one successful write to the map */ 887 /* Only allow one successful write to the map */
678 if (map->nr_extents != 0) 888 if (map->nr_extents != 0)
@@ -700,9 +910,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
700 /* Parse the user data */ 910 /* Parse the user data */
701 ret = -EINVAL; 911 ret = -EINVAL;
702 pos = kbuf; 912 pos = kbuf;
703 new_map.nr_extents = 0;
704 for (; pos; pos = next_line) { 913 for (; pos; pos = next_line) {
705 extent = &new_map.extent[new_map.nr_extents];
706 914
707 /* Find the end of line and ensure I don't look past it */ 915 /* Find the end of line and ensure I don't look past it */
708 next_line = strchr(pos, '\n'); 916 next_line = strchr(pos, '\n');
@@ -714,17 +922,17 @@ static ssize_t map_write(struct file *file, const char __user *buf,
714 } 922 }
715 923
716 pos = skip_spaces(pos); 924 pos = skip_spaces(pos);
717 extent->first = simple_strtoul(pos, &pos, 10); 925 extent.first = simple_strtoul(pos, &pos, 10);
718 if (!isspace(*pos)) 926 if (!isspace(*pos))
719 goto out; 927 goto out;
720 928
721 pos = skip_spaces(pos); 929 pos = skip_spaces(pos);
722 extent->lower_first = simple_strtoul(pos, &pos, 10); 930 extent.lower_first = simple_strtoul(pos, &pos, 10);
723 if (!isspace(*pos)) 931 if (!isspace(*pos))
724 goto out; 932 goto out;
725 933
726 pos = skip_spaces(pos); 934 pos = skip_spaces(pos);
727 extent->count = simple_strtoul(pos, &pos, 10); 935 extent.count = simple_strtoul(pos, &pos, 10);
728 if (*pos && !isspace(*pos)) 936 if (*pos && !isspace(*pos))
729 goto out; 937 goto out;
730 938
@@ -734,29 +942,31 @@ static ssize_t map_write(struct file *file, const char __user *buf,
734 goto out; 942 goto out;
735 943
736 /* Verify we have been given valid starting values */ 944 /* Verify we have been given valid starting values */
737 if ((extent->first == (u32) -1) || 945 if ((extent.first == (u32) -1) ||
738 (extent->lower_first == (u32) -1)) 946 (extent.lower_first == (u32) -1))
739 goto out; 947 goto out;
740 948
741 /* Verify count is not zero and does not cause the 949 /* Verify count is not zero and does not cause the
742 * extent to wrap 950 * extent to wrap
743 */ 951 */
744 if ((extent->first + extent->count) <= extent->first) 952 if ((extent.first + extent.count) <= extent.first)
745 goto out; 953 goto out;
746 if ((extent->lower_first + extent->count) <= 954 if ((extent.lower_first + extent.count) <=
747 extent->lower_first) 955 extent.lower_first)
748 goto out; 956 goto out;
749 957
750 /* Do the ranges in extent overlap any previous extents? */ 958 /* Do the ranges in extent overlap any previous extents? */
751 if (mappings_overlap(&new_map, extent)) 959 if (mappings_overlap(&new_map, &extent))
752 goto out; 960 goto out;
753 961
754 new_map.nr_extents++; 962 if ((new_map.nr_extents + 1) == UID_GID_MAP_MAX_EXTENTS &&
755
756 /* Fail if the file contains too many extents */
757 if ((new_map.nr_extents == UID_GID_MAP_MAX_EXTENTS) &&
758 (next_line != NULL)) 963 (next_line != NULL))
759 goto out; 964 goto out;
965
966 ret = insert_extent(&new_map, &extent);
967 if (ret < 0)
968 goto out;
969 ret = -EINVAL;
760 } 970 }
761 /* Be very certaint the new map actually exists */ 971 /* Be very certaint the new map actually exists */
762 if (new_map.nr_extents == 0) 972 if (new_map.nr_extents == 0)
@@ -767,16 +977,26 @@ static ssize_t map_write(struct file *file, const char __user *buf,
767 if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) 977 if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
768 goto out; 978 goto out;
769 979
980 ret = sort_idmaps(&new_map);
981 if (ret < 0)
982 goto out;
983
984 ret = -EPERM;
770 /* Map the lower ids from the parent user namespace to the 985 /* Map the lower ids from the parent user namespace to the
771 * kernel global id space. 986 * kernel global id space.
772 */ 987 */
773 for (idx = 0; idx < new_map.nr_extents; idx++) { 988 for (idx = 0; idx < new_map.nr_extents; idx++) {
989 struct uid_gid_extent *e;
774 u32 lower_first; 990 u32 lower_first;
775 extent = &new_map.extent[idx]; 991
992 if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
993 e = &new_map.extent[idx];
994 else
995 e = &new_map.forward[idx];
776 996
777 lower_first = map_id_range_down(parent_map, 997 lower_first = map_id_range_down(parent_map,
778 extent->lower_first, 998 e->lower_first,
779 extent->count); 999 e->count);
780 1000
781 /* Fail if we can not map the specified extent to 1001 /* Fail if we can not map the specified extent to
782 * the kernel global id space. 1002 * the kernel global id space.
@@ -784,18 +1004,31 @@ static ssize_t map_write(struct file *file, const char __user *buf,
784 if (lower_first == (u32) -1) 1004 if (lower_first == (u32) -1)
785 goto out; 1005 goto out;
786 1006
787 extent->lower_first = lower_first; 1007 e->lower_first = lower_first;
788 } 1008 }
789 1009
790 /* Install the map */ 1010 /* Install the map */
791 memcpy(map->extent, new_map.extent, 1011 if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
792 new_map.nr_extents*sizeof(new_map.extent[0])); 1012 memcpy(map->extent, new_map.extent,
1013 new_map.nr_extents * sizeof(new_map.extent[0]));
1014 } else {
1015 map->forward = new_map.forward;
1016 map->reverse = new_map.reverse;
1017 }
793 smp_wmb(); 1018 smp_wmb();
794 map->nr_extents = new_map.nr_extents; 1019 map->nr_extents = new_map.nr_extents;
795 1020
796 *ppos = count; 1021 *ppos = count;
797 ret = count; 1022 ret = count;
798out: 1023out:
1024 if (ret < 0 && new_map.nr_extents > UID_GID_MAP_MAX_BASE_EXTENTS) {
1025 kfree(new_map.forward);
1026 kfree(new_map.reverse);
1027 map->forward = NULL;
1028 map->reverse = NULL;
1029 map->nr_extents = 0;
1030 }
1031
799 mutex_unlock(&userns_state_mutex); 1032 mutex_unlock(&userns_state_mutex);
800 kfree(kbuf); 1033 kfree(kbuf);
801 return ret; 1034 return ret;