diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-18 15:02:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-18 15:02:52 -0500 |
commit | 5c69bed266adadf9fd334e68a7ac586b625e9547 (patch) | |
tree | 54cb73524cf5ed886cd176665cf30a320014d8ac /drivers/xen/grant-table.c | |
parent | b814469ad515c70d9269d5268607bd6fbfb32533 (diff) | |
parent | 9174adbee4a9a49d0139f5d71969852b36720809 (diff) |
Merge tag 'stable/for-linus-3.8-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
Pull Xen fixes from Konrad Rzeszutek Wilk:
- CVE-2013-0190/XSA-40 (or stack corruption for 32-bit PV kernels)
- Fix racy vma access spotted by Al Viro
- Fix mmap batch ioctl potentially resulting in large O(n) page allcations.
- Fix vcpu online/offline BUG:scheduling while atomic..
- Fix unbound buffer scanning for more than 32 vCPUs.
- Fix grant table being incorrectly initialized
- Fix incorrect check in pciback
- Allow privcmd in backend domains.
Fix up whitespace conflict due to ugly merge resolution in Xen tree in
arch/arm/xen/enlighten.c
* tag 'stable/for-linus-3.8-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
xen: Fix stack corruption in xen_failsafe_callback for 32bit PVOPS guests.
Revert "xen/smp: Fix CPU online/offline bug triggering a BUG: scheduling while atomic."
xen/gntdev: remove erronous use of copy_to_user
xen/gntdev: correctly unmap unlinked maps in mmu notifier
xen/gntdev: fix unsafe vma access
xen/privcmd: Fix mmap batch ioctl.
Xen: properly bound buffer access when parsing cpu/*/availability
xen/grant-table: correctly initialize grant table version 1
x86/xen : Fix the wrong check in pciback
xen/privcmd: Relax access control in privcmd_ioctl_mmap
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r-- | drivers/xen/grant-table.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7038de53652b..157c0ccda3ef 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -56,10 +56,6 @@ | |||
56 | /* External tools reserve first few grant table entries. */ | 56 | /* External tools reserve first few grant table entries. */ |
57 | #define NR_RESERVED_ENTRIES 8 | 57 | #define NR_RESERVED_ENTRIES 8 |
58 | #define GNTTAB_LIST_END 0xffffffff | 58 | #define GNTTAB_LIST_END 0xffffffff |
59 | #define GREFS_PER_GRANT_FRAME \ | ||
60 | (grant_table_version == 1 ? \ | ||
61 | (PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ | ||
62 | (PAGE_SIZE / sizeof(union grant_entry_v2))) | ||
63 | 59 | ||
64 | static grant_ref_t **gnttab_list; | 60 | static grant_ref_t **gnttab_list; |
65 | static unsigned int nr_grant_frames; | 61 | static unsigned int nr_grant_frames; |
@@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface; | |||
154 | static grant_status_t *grstatus; | 150 | static grant_status_t *grstatus; |
155 | 151 | ||
156 | static int grant_table_version; | 152 | static int grant_table_version; |
153 | static int grefs_per_grant_frame; | ||
157 | 154 | ||
158 | static struct gnttab_free_callback *gnttab_free_callback_list; | 155 | static struct gnttab_free_callback *gnttab_free_callback_list; |
159 | 156 | ||
@@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
767 | unsigned int new_nr_grant_frames, extra_entries, i; | 764 | unsigned int new_nr_grant_frames, extra_entries, i; |
768 | unsigned int nr_glist_frames, new_nr_glist_frames; | 765 | unsigned int nr_glist_frames, new_nr_glist_frames; |
769 | 766 | ||
767 | BUG_ON(grefs_per_grant_frame == 0); | ||
768 | |||
770 | new_nr_grant_frames = nr_grant_frames + more_frames; | 769 | new_nr_grant_frames = nr_grant_frames + more_frames; |
771 | extra_entries = more_frames * GREFS_PER_GRANT_FRAME; | 770 | extra_entries = more_frames * grefs_per_grant_frame; |
772 | 771 | ||
773 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 772 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
774 | new_nr_glist_frames = | 773 | new_nr_glist_frames = |
775 | (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 774 | (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
776 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { | 775 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { |
777 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); | 776 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); |
778 | if (!gnttab_list[i]) | 777 | if (!gnttab_list[i]) |
@@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
780 | } | 779 | } |
781 | 780 | ||
782 | 781 | ||
783 | for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 782 | for (i = grefs_per_grant_frame * nr_grant_frames; |
784 | i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) | 783 | i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) |
785 | gnttab_entry(i) = i + 1; | 784 | gnttab_entry(i) = i + 1; |
786 | 785 | ||
787 | gnttab_entry(i) = gnttab_free_head; | 786 | gnttab_entry(i) = gnttab_free_head; |
788 | gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 787 | gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; |
789 | gnttab_free_count += extra_entries; | 788 | gnttab_free_count += extra_entries; |
790 | 789 | ||
791 | nr_grant_frames = new_nr_grant_frames; | 790 | nr_grant_frames = new_nr_grant_frames; |
@@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | |||
957 | 956 | ||
958 | static unsigned nr_status_frames(unsigned nr_grant_frames) | 957 | static unsigned nr_status_frames(unsigned nr_grant_frames) |
959 | { | 958 | { |
960 | return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; | 959 | BUG_ON(grefs_per_grant_frame == 0); |
960 | return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; | ||
961 | } | 961 | } |
962 | 962 | ||
963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) | 963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) |
@@ -1115,6 +1115,7 @@ static void gnttab_request_version(void) | |||
1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); | 1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); |
1116 | if (rc == 0 && gsv.version == 2) { | 1116 | if (rc == 0 && gsv.version == 2) { |
1117 | grant_table_version = 2; | 1117 | grant_table_version = 2; |
1118 | grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); | ||
1118 | gnttab_interface = &gnttab_v2_ops; | 1119 | gnttab_interface = &gnttab_v2_ops; |
1119 | } else if (grant_table_version == 2) { | 1120 | } else if (grant_table_version == 2) { |
1120 | /* | 1121 | /* |
@@ -1127,17 +1128,17 @@ static void gnttab_request_version(void) | |||
1127 | panic("we need grant tables version 2, but only version 1 is available"); | 1128 | panic("we need grant tables version 2, but only version 1 is available"); |
1128 | } else { | 1129 | } else { |
1129 | grant_table_version = 1; | 1130 | grant_table_version = 1; |
1131 | grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); | ||
1130 | gnttab_interface = &gnttab_v1_ops; | 1132 | gnttab_interface = &gnttab_v1_ops; |
1131 | } | 1133 | } |
1132 | printk(KERN_INFO "Grant tables using version %d layout.\n", | 1134 | printk(KERN_INFO "Grant tables using version %d layout.\n", |
1133 | grant_table_version); | 1135 | grant_table_version); |
1134 | } | 1136 | } |
1135 | 1137 | ||
1136 | int gnttab_resume(void) | 1138 | static int gnttab_setup(void) |
1137 | { | 1139 | { |
1138 | unsigned int max_nr_gframes; | 1140 | unsigned int max_nr_gframes; |
1139 | 1141 | ||
1140 | gnttab_request_version(); | ||
1141 | max_nr_gframes = gnttab_max_grant_frames(); | 1142 | max_nr_gframes = gnttab_max_grant_frames(); |
1142 | if (max_nr_gframes < nr_grant_frames) | 1143 | if (max_nr_gframes < nr_grant_frames) |
1143 | return -ENOSYS; | 1144 | return -ENOSYS; |
@@ -1160,6 +1161,12 @@ int gnttab_resume(void) | |||
1160 | return 0; | 1161 | return 0; |
1161 | } | 1162 | } |
1162 | 1163 | ||
1164 | int gnttab_resume(void) | ||
1165 | { | ||
1166 | gnttab_request_version(); | ||
1167 | return gnttab_setup(); | ||
1168 | } | ||
1169 | |||
1163 | int gnttab_suspend(void) | 1170 | int gnttab_suspend(void) |
1164 | { | 1171 | { |
1165 | gnttab_interface->unmap_frames(); | 1172 | gnttab_interface->unmap_frames(); |
@@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries) | |||
1171 | int rc; | 1178 | int rc; |
1172 | unsigned int cur, extra; | 1179 | unsigned int cur, extra; |
1173 | 1180 | ||
1181 | BUG_ON(grefs_per_grant_frame == 0); | ||
1174 | cur = nr_grant_frames; | 1182 | cur = nr_grant_frames; |
1175 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / | 1183 | extra = ((req_entries + (grefs_per_grant_frame-1)) / |
1176 | GREFS_PER_GRANT_FRAME); | 1184 | grefs_per_grant_frame); |
1177 | if (cur + extra > gnttab_max_grant_frames()) | 1185 | if (cur + extra > gnttab_max_grant_frames()) |
1178 | return -ENOSPC; | 1186 | return -ENOSPC; |
1179 | 1187 | ||
@@ -1191,21 +1199,23 @@ int gnttab_init(void) | |||
1191 | unsigned int nr_init_grefs; | 1199 | unsigned int nr_init_grefs; |
1192 | int ret; | 1200 | int ret; |
1193 | 1201 | ||
1202 | gnttab_request_version(); | ||
1194 | nr_grant_frames = 1; | 1203 | nr_grant_frames = 1; |
1195 | boot_max_nr_grant_frames = __max_nr_grant_frames(); | 1204 | boot_max_nr_grant_frames = __max_nr_grant_frames(); |
1196 | 1205 | ||
1197 | /* Determine the maximum number of frames required for the | 1206 | /* Determine the maximum number of frames required for the |
1198 | * grant reference free list on the current hypervisor. | 1207 | * grant reference free list on the current hypervisor. |
1199 | */ | 1208 | */ |
1209 | BUG_ON(grefs_per_grant_frame == 0); | ||
1200 | max_nr_glist_frames = (boot_max_nr_grant_frames * | 1210 | max_nr_glist_frames = (boot_max_nr_grant_frames * |
1201 | GREFS_PER_GRANT_FRAME / RPP); | 1211 | grefs_per_grant_frame / RPP); |
1202 | 1212 | ||
1203 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), | 1213 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), |
1204 | GFP_KERNEL); | 1214 | GFP_KERNEL); |
1205 | if (gnttab_list == NULL) | 1215 | if (gnttab_list == NULL) |
1206 | return -ENOMEM; | 1216 | return -ENOMEM; |
1207 | 1217 | ||
1208 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 1218 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
1209 | for (i = 0; i < nr_glist_frames; i++) { | 1219 | for (i = 0; i < nr_glist_frames; i++) { |
1210 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); | 1220 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); |
1211 | if (gnttab_list[i] == NULL) { | 1221 | if (gnttab_list[i] == NULL) { |
@@ -1214,12 +1224,12 @@ int gnttab_init(void) | |||
1214 | } | 1224 | } |
1215 | } | 1225 | } |
1216 | 1226 | ||
1217 | if (gnttab_resume() < 0) { | 1227 | if (gnttab_setup() < 0) { |
1218 | ret = -ENODEV; | 1228 | ret = -ENODEV; |
1219 | goto ini_nomem; | 1229 | goto ini_nomem; |
1220 | } | 1230 | } |
1221 | 1231 | ||
1222 | nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; | 1232 | nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; |
1223 | 1233 | ||
1224 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) | 1234 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) |
1225 | gnttab_entry(i) = i + 1; | 1235 | gnttab_entry(i) = i + 1; |