aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2017-10-31 17:27:29 -0400
committerEric W. Biederman <ebiederm@xmission.com>2017-10-31 18:23:12 -0400
commit3edf652fa16562fb57a5a4b996ba72e2d7cdc38b (patch)
treee4eeee3cab3552207c36eac2ff9ae94f5e1b6134
parent11a8b9270e16e36d5fb607ba4b60db2958b7c625 (diff)
userns: Simplify the user and group mapping functions
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>
-rw-r--r--kernel/user_namespace.c132
1 files 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)
256 * map_id_range_down_max - Find idmap via binary search in ordered idmap array. 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. 257 * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
258 */ 258 */
259static u32 map_id_range_down_max(struct uid_gid_map *map, u32 id, u32 count) 259static struct uid_gid_extent *
260map_id_range_down_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
260{ 261{
261 u32 extents;
262 struct uid_gid_extent *extent;
263 struct idmap_key key; 262 struct idmap_key key;
264 263
265 key.map_up = false; 264 key.map_up = false;
266 key.count = count; 265 key.count = count;
267 key.id = id; 266 key.id = id;
268 267
269 extents = map->nr_extents; 268 return bsearch(&key, map->forward, extents,
270 smp_rmb(); 269 sizeof(struct uid_gid_extent), cmp_map_id);
271
272 extent = bsearch(&key, map->forward, extents,
273 sizeof(struct uid_gid_extent), cmp_map_id);
274 /* Map the id or note failure */
275 if (extent)
276 id = (id - extent->first) + extent->lower_first;
277 else
278 id = (u32) -1;
279
280 return id;
281} 270}
282 271
283/** 272/**
@@ -285,41 +274,43 @@ static u32 map_id_range_down_max(struct uid_gid_map *map, u32 id, u32 count)
285 * Can only be called if number of mappings is equal or less than 274 * Can only be called if number of mappings is equal or less than
286 * UID_GID_MAP_MAX_BASE_EXTENTS. 275 * UID_GID_MAP_MAX_BASE_EXTENTS.
287 */ 276 */
288static u32 map_id_range_down_base(struct uid_gid_map *map, u32 id, u32 count) 277static struct uid_gid_extent *
278map_id_range_down_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
289{ 279{
290 unsigned idx, extents; 280 unsigned idx;
291 u32 first, last, id2; 281 u32 first, last, id2;
292 282
293 id2 = id + count - 1; 283 id2 = id + count - 1;
294 284
295 /* Find the matching extent */ 285 /* Find the matching extent */
296 extents = map->nr_extents;
297 smp_rmb();
298 for (idx = 0; idx < extents; idx++) { 286 for (idx = 0; idx < extents; idx++) {
299 first = map->extent[idx].first; 287 first = map->extent[idx].first;
300 last = first + map->extent[idx].count - 1; 288 last = first + map->extent[idx].count - 1;
301 if (id >= first && id <= last && 289 if (id >= first && id <= last &&
302 (id2 >= first && id2 <= last)) 290 (id2 >= first && id2 <= last))
303 break; 291 return &map->extent[idx];
304 } 292 }
305 /* Map the id or note failure */ 293 return NULL;
306 if (idx < extents)
307 id = (id - first) + map->extent[idx].lower_first;
308 else
309 id = (u32) -1;
310
311 return id;
312} 294}
313 295
314static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count) 296static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
315{ 297{
316 u32 extents = map->nr_extents; 298 struct uid_gid_extent *extent;
299 unsigned extents = map->nr_extents;
317 smp_rmb(); 300 smp_rmb();
318 301
319 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS) 302 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
320 return map_id_range_down_base(map, id, count); 303 extent = map_id_range_down_base(extents, map, id, count);
304 else
305 extent = map_id_range_down_max(extents, map, id, count);
321 306
322 return map_id_range_down_max(map, id, count); 307 /* Map the id or note failure */
308 if (extent)
309 id = (id - extent->first) + extent->lower_first;
310 else
311 id = (u32) -1;
312
313 return id;
323} 314}
324 315
325/** 316/**
@@ -327,38 +318,40 @@ static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
327 * Can only be called if number of mappings is equal or less than 318 * Can only be called if number of mappings is equal or less than
328 * UID_GID_MAP_MAX_BASE_EXTENTS. 319 * UID_GID_MAP_MAX_BASE_EXTENTS.
329 */ 320 */
330static u32 map_id_down_base(struct uid_gid_map *map, u32 id) 321static struct uid_gid_extent *
322map_id_down_base(unsigned extents, struct uid_gid_map *map, u32 id)
331{ 323{
332 unsigned idx, extents; 324 unsigned idx;
333 u32 first, last; 325 u32 first, last;
334 326
335 /* Find the matching extent */ 327 /* Find the matching extent */
336 extents = map->nr_extents;
337 smp_rmb();
338 for (idx = 0; idx < extents; idx++) { 328 for (idx = 0; idx < extents; idx++) {
339 first = map->extent[idx].first; 329 first = map->extent[idx].first;
340 last = first + map->extent[idx].count - 1; 330 last = first + map->extent[idx].count - 1;
341 if (id >= first && id <= last) 331 if (id >= first && id <= last)
342 break; 332 return &map->extent[idx];
343 } 333 }
344 /* Map the id or note failure */ 334 return NULL;
345 if (idx < extents)
346 id = (id - first) + map->extent[idx].lower_first;
347 else
348 id = (u32) -1;
349
350 return id;
351} 335}
352 336
353static u32 map_id_down(struct uid_gid_map *map, u32 id) 337static u32 map_id_down(struct uid_gid_map *map, u32 id)
354{ 338{
355 u32 extents = map->nr_extents; 339 struct uid_gid_extent *extent;
340 unsigned extents = map->nr_extents;
356 smp_rmb(); 341 smp_rmb();
357 342
358 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS) 343 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
359 return map_id_down_base(map, id); 344 extent = map_id_down_base(extents, map, id);
345 else
346 extent = map_id_range_down_max(extents, map, id, 1);
360 347
361 return map_id_range_down_max(map, id, 1); 348 /* Map the id or note failure */
349 if (extent)
350 id = (id - extent->first) + extent->lower_first;
351 else
352 id = (u32) -1;
353
354 return id;
362} 355}
363 356
364/** 357/**
@@ -366,48 +359,50 @@ static u32 map_id_down(struct uid_gid_map *map, u32 id)
366 * Can only be called if number of mappings is equal or less than 359 * Can only be called if number of mappings is equal or less than
367 * UID_GID_MAP_MAX_BASE_EXTENTS. 360 * UID_GID_MAP_MAX_BASE_EXTENTS.
368 */ 361 */
369static u32 map_id_up_base(struct uid_gid_map *map, u32 id) 362static struct uid_gid_extent *
363map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id)
370{ 364{
371 unsigned idx, extents; 365 unsigned idx;
372 u32 first, last; 366 u32 first, last;
373 367
374 /* Find the matching extent */ 368 /* Find the matching extent */
375 extents = map->nr_extents;
376 smp_rmb();
377 for (idx = 0; idx < extents; idx++) { 369 for (idx = 0; idx < extents; idx++) {
378 first = map->extent[idx].lower_first; 370 first = map->extent[idx].lower_first;
379 last = first + map->extent[idx].count - 1; 371 last = first + map->extent[idx].count - 1;
380 if (id >= first && id <= last) 372 if (id >= first && id <= last)
381 break; 373 return &map->extent[idx];
382 } 374 }
383 /* Map the id or note failure */ 375 return NULL;
384 if (idx < extents)
385 id = (id - first) + map->extent[idx].first;
386 else
387 id = (u32) -1;
388
389 return id;
390} 376}
391 377
392/** 378/**
393 * map_id_up_max - Find idmap via binary search in ordered idmap array. 379 * map_id_up_max - Find idmap via binary search in ordered idmap array.
394 * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS. 380 * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
395 */ 381 */
396static u32 map_id_up_max(struct uid_gid_map *map, u32 id) 382static struct uid_gid_extent *
383map_id_up_max(unsigned extents, struct uid_gid_map *map, u32 id)
397{ 384{
398 u32 extents;
399 struct uid_gid_extent *extent;
400 struct idmap_key key; 385 struct idmap_key key;
401 386
402 key.map_up = true; 387 key.map_up = true;
403 key.count = 1; 388 key.count = 1;
404 key.id = id; 389 key.id = id;
405 390
406 extents = map->nr_extents; 391 return bsearch(&key, map->reverse, extents,
392 sizeof(struct uid_gid_extent), cmp_map_id);
393}
394
395static u32 map_id_up(struct uid_gid_map *map, u32 id)
396{
397 struct uid_gid_extent *extent;
398 unsigned extents = map->nr_extents;
407 smp_rmb(); 399 smp_rmb();
408 400
409 extent = bsearch(&key, map->reverse, extents, 401 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
410 sizeof(struct uid_gid_extent), cmp_map_id); 402 extent = map_id_up_base(extents, map, id);
403 else
404 extent = map_id_up_max(extents, map, id);
405
411 /* Map the id or note failure */ 406 /* Map the id or note failure */
412 if (extent) 407 if (extent)
413 id = (id - extent->lower_first) + extent->first; 408 id = (id - extent->lower_first) + extent->first;
@@ -417,17 +412,6 @@ static u32 map_id_up_max(struct uid_gid_map *map, u32 id)
417 return id; 412 return id;
418} 413}
419 414
420static u32 map_id_up(struct uid_gid_map *map, u32 id)
421{
422 u32 extents = map->nr_extents;
423 smp_rmb();
424
425 if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
426 return map_id_up_base(map, id);
427
428 return map_id_up_max(map, id);
429}
430
431/** 415/**
432 * make_kuid - Map a user-namespace uid pair into a kuid. 416 * make_kuid - Map a user-namespace uid pair into a kuid.
433 * @ns: User namespace that the uid is in 417 * @ns: User namespace that the uid is in