aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/user_namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/user_namespace.c')
-rw-r--r--kernel/user_namespace.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 0d8f6023fd8d..fcc02560fd6b 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -152,7 +152,7 @@ static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
152 152
153 /* Find the matching extent */ 153 /* Find the matching extent */
154 extents = map->nr_extents; 154 extents = map->nr_extents;
155 smp_read_barrier_depends(); 155 smp_rmb();
156 for (idx = 0; idx < extents; idx++) { 156 for (idx = 0; idx < extents; idx++) {
157 first = map->extent[idx].first; 157 first = map->extent[idx].first;
158 last = first + map->extent[idx].count - 1; 158 last = first + map->extent[idx].count - 1;
@@ -176,7 +176,7 @@ static u32 map_id_down(struct uid_gid_map *map, u32 id)
176 176
177 /* Find the matching extent */ 177 /* Find the matching extent */
178 extents = map->nr_extents; 178 extents = map->nr_extents;
179 smp_read_barrier_depends(); 179 smp_rmb();
180 for (idx = 0; idx < extents; idx++) { 180 for (idx = 0; idx < extents; idx++) {
181 first = map->extent[idx].first; 181 first = map->extent[idx].first;
182 last = first + map->extent[idx].count - 1; 182 last = first + map->extent[idx].count - 1;
@@ -199,7 +199,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id)
199 199
200 /* Find the matching extent */ 200 /* Find the matching extent */
201 extents = map->nr_extents; 201 extents = map->nr_extents;
202 smp_read_barrier_depends(); 202 smp_rmb();
203 for (idx = 0; idx < extents; idx++) { 203 for (idx = 0; idx < extents; idx++) {
204 first = map->extent[idx].lower_first; 204 first = map->extent[idx].lower_first;
205 last = first + map->extent[idx].count - 1; 205 last = first + map->extent[idx].count - 1;
@@ -286,7 +286,7 @@ EXPORT_SYMBOL(from_kuid_munged);
286/** 286/**
287 * make_kgid - Map a user-namespace gid pair into a kgid. 287 * make_kgid - Map a user-namespace gid pair into a kgid.
288 * @ns: User namespace that the gid is in 288 * @ns: User namespace that the gid is in
289 * @uid: group identifier 289 * @gid: group identifier
290 * 290 *
291 * Maps a user-namespace gid pair into a kernel internal kgid, 291 * Maps a user-namespace gid pair into a kernel internal kgid,
292 * and returns that kgid. 292 * and returns that kgid.
@@ -482,7 +482,8 @@ static int projid_m_show(struct seq_file *seq, void *v)
482 return 0; 482 return 0;
483} 483}
484 484
485static void *m_start(struct seq_file *seq, loff_t *ppos, struct uid_gid_map *map) 485static void *m_start(struct seq_file *seq, loff_t *ppos,
486 struct uid_gid_map *map)
486{ 487{
487 struct uid_gid_extent *extent = NULL; 488 struct uid_gid_extent *extent = NULL;
488 loff_t pos = *ppos; 489 loff_t pos = *ppos;
@@ -546,7 +547,8 @@ struct seq_operations proc_projid_seq_operations = {
546 .show = projid_m_show, 547 .show = projid_m_show,
547}; 548};
548 549
549static bool mappings_overlap(struct uid_gid_map *new_map, struct uid_gid_extent *extent) 550static bool mappings_overlap(struct uid_gid_map *new_map,
551 struct uid_gid_extent *extent)
550{ 552{
551 u32 upper_first, lower_first, upper_last, lower_last; 553 u32 upper_first, lower_first, upper_last, lower_last;
552 unsigned idx; 554 unsigned idx;
@@ -615,9 +617,8 @@ static ssize_t map_write(struct file *file, const char __user *buf,
615 * were written before the count of the extents. 617 * were written before the count of the extents.
616 * 618 *
617 * To achieve this smp_wmb() is used on guarantee the write 619 * To achieve this smp_wmb() is used on guarantee the write
618 * order and smp_read_barrier_depends() is guaranteed that we 620 * order and smp_rmb() is guaranteed that we don't have crazy
619 * don't have crazy architectures returning stale data. 621 * architectures returning stale data.
620 *
621 */ 622 */
622 mutex_lock(&id_map_mutex); 623 mutex_lock(&id_map_mutex);
623 624
@@ -654,7 +655,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
654 ret = -EINVAL; 655 ret = -EINVAL;
655 pos = kbuf; 656 pos = kbuf;
656 new_map.nr_extents = 0; 657 new_map.nr_extents = 0;
657 for (;pos; pos = next_line) { 658 for (; pos; pos = next_line) {
658 extent = &new_map.extent[new_map.nr_extents]; 659 extent = &new_map.extent[new_map.nr_extents];
659 660
660 /* Find the end of line and ensure I don't look past it */ 661 /* Find the end of line and ensure I don't look past it */
@@ -688,13 +689,16 @@ static ssize_t map_write(struct file *file, const char __user *buf,
688 689
689 /* Verify we have been given valid starting values */ 690 /* Verify we have been given valid starting values */
690 if ((extent->first == (u32) -1) || 691 if ((extent->first == (u32) -1) ||
691 (extent->lower_first == (u32) -1 )) 692 (extent->lower_first == (u32) -1))
692 goto out; 693 goto out;
693 694
694 /* Verify count is not zero and does not cause the extent to wrap */ 695 /* Verify count is not zero and does not cause the
696 * extent to wrap
697 */
695 if ((extent->first + extent->count) <= extent->first) 698 if ((extent->first + extent->count) <= extent->first)
696 goto out; 699 goto out;
697 if ((extent->lower_first + extent->count) <= extent->lower_first) 700 if ((extent->lower_first + extent->count) <=
701 extent->lower_first)
698 goto out; 702 goto out;
699 703
700 /* Do the ranges in extent overlap any previous extents? */ 704 /* Do the ranges in extent overlap any previous extents? */
@@ -752,7 +756,8 @@ out:
752 return ret; 756 return ret;
753} 757}
754 758
755ssize_t proc_uid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) 759ssize_t proc_uid_map_write(struct file *file, const char __user *buf,
760 size_t size, loff_t *ppos)
756{ 761{
757 struct seq_file *seq = file->private_data; 762 struct seq_file *seq = file->private_data;
758 struct user_namespace *ns = seq->private; 763 struct user_namespace *ns = seq->private;
@@ -768,7 +773,8 @@ ssize_t proc_uid_map_write(struct file *file, const char __user *buf, size_t siz
768 &ns->uid_map, &ns->parent->uid_map); 773 &ns->uid_map, &ns->parent->uid_map);
769} 774}
770 775
771ssize_t proc_gid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) 776ssize_t proc_gid_map_write(struct file *file, const char __user *buf,
777 size_t size, loff_t *ppos)
772{ 778{
773 struct seq_file *seq = file->private_data; 779 struct seq_file *seq = file->private_data;
774 struct user_namespace *ns = seq->private; 780 struct user_namespace *ns = seq->private;
@@ -784,7 +790,8 @@ ssize_t proc_gid_map_write(struct file *file, const char __user *buf, size_t siz
784 &ns->gid_map, &ns->parent->gid_map); 790 &ns->gid_map, &ns->parent->gid_map);
785} 791}
786 792
787ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) 793ssize_t proc_projid_map_write(struct file *file, const char __user *buf,
794 size_t size, loff_t *ppos)
788{ 795{
789 struct seq_file *seq = file->private_data; 796 struct seq_file *seq = file->private_data;
790 struct user_namespace *ns = seq->private; 797 struct user_namespace *ns = seq->private;
@@ -801,7 +808,7 @@ ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t
801 &ns->projid_map, &ns->parent->projid_map); 808 &ns->projid_map, &ns->parent->projid_map);
802} 809}
803 810
804static bool new_idmap_permitted(const struct file *file, 811static bool new_idmap_permitted(const struct file *file,
805 struct user_namespace *ns, int cap_setid, 812 struct user_namespace *ns, int cap_setid,
806 struct uid_gid_map *new_map) 813 struct uid_gid_map *new_map)
807{ 814{
@@ -812,8 +819,7 @@ static bool new_idmap_permitted(const struct file *file,
812 kuid_t uid = make_kuid(ns->parent, id); 819 kuid_t uid = make_kuid(ns->parent, id);
813 if (uid_eq(uid, file->f_cred->fsuid)) 820 if (uid_eq(uid, file->f_cred->fsuid))
814 return true; 821 return true;
815 } 822 } else if (cap_setid == CAP_SETGID) {
816 else if (cap_setid == CAP_SETGID) {
817 kgid_t gid = make_kgid(ns->parent, id); 823 kgid_t gid = make_kgid(ns->parent, id);
818 if (gid_eq(gid, file->f_cred->fsgid)) 824 if (gid_eq(gid, file->f_cred->fsgid))
819 return true; 825 return true;