diff options
Diffstat (limited to 'kernel/user_namespace.c')
| -rw-r--r-- | kernel/user_namespace.c | 44 |
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 | ||
| 485 | static void *m_start(struct seq_file *seq, loff_t *ppos, struct uid_gid_map *map) | 485 | static 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 | ||
| 549 | static bool mappings_overlap(struct uid_gid_map *new_map, struct uid_gid_extent *extent) | 550 | static 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 | ||
| 755 | ssize_t proc_uid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) | 759 | ssize_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 | ||
| 771 | ssize_t proc_gid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) | 776 | ssize_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 | ||
| 787 | ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) | 793 | ssize_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 | ||
| 804 | static bool new_idmap_permitted(const struct file *file, | 811 | static 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; |
