1 |
Author: mpagano |
2 |
Date: 2014-01-29 14:40:30 +0000 (Wed, 29 Jan 2014) |
3 |
New Revision: 2659 |
4 |
|
5 |
Added: |
6 |
genpatches-2.6/trunk/3.4/1077_linux-3.4.78.patch |
7 |
Modified: |
8 |
genpatches-2.6/trunk/3.4/0000_README |
9 |
Log: |
10 |
Linux patch 3.4.78 |
11 |
|
12 |
Modified: genpatches-2.6/trunk/3.4/0000_README |
13 |
=================================================================== |
14 |
--- genpatches-2.6/trunk/3.4/0000_README 2014-01-29 14:10:57 UTC (rev 2658) |
15 |
+++ genpatches-2.6/trunk/3.4/0000_README 2014-01-29 14:40:30 UTC (rev 2659) |
16 |
@@ -347,6 +347,10 @@ |
17 |
From: http://www.kernel.org |
18 |
Desc: Linux 3.4.77 |
19 |
|
20 |
+Patch: 1077_linux-3.4.78.patch |
21 |
+From: http://www.kernel.org |
22 |
+Desc: Linux 3.4.78 |
23 |
+ |
24 |
Patch: 1500_XATTR_USER_PREFIX.patch |
25 |
From: https://bugs.gentoo.org/show_bug.cgi?id=470644 |
26 |
Desc: Support for namespace user.pax.* on tmpfs. |
27 |
|
28 |
Added: genpatches-2.6/trunk/3.4/1077_linux-3.4.78.patch |
29 |
=================================================================== |
30 |
--- genpatches-2.6/trunk/3.4/1077_linux-3.4.78.patch (rev 0) |
31 |
+++ genpatches-2.6/trunk/3.4/1077_linux-3.4.78.patch 2014-01-29 14:40:30 UTC (rev 2659) |
32 |
@@ -0,0 +1,470 @@ |
33 |
+diff --git a/Makefile b/Makefile |
34 |
+index bbdd7ab3e0e3..e891990fbf1c 100644 |
35 |
+--- a/Makefile |
36 |
++++ b/Makefile |
37 |
+@@ -1,6 +1,6 @@ |
38 |
+ VERSION = 3 |
39 |
+ PATCHLEVEL = 4 |
40 |
+-SUBLEVEL = 77 |
41 |
++SUBLEVEL = 78 |
42 |
+ EXTRAVERSION = |
43 |
+ NAME = Saber-toothed Squirrel |
44 |
+ |
45 |
+diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c |
46 |
+index 3b8a2d30d14e..ea34253cb9c6 100644 |
47 |
+--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c |
48 |
++++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c |
49 |
+@@ -9,6 +9,7 @@ |
50 |
+ #include <linux/perf_event.h> |
51 |
+ #include <linux/module.h> |
52 |
+ #include <linux/pci.h> |
53 |
++#include <linux/syscore_ops.h> |
54 |
+ |
55 |
+ #include <asm/apic.h> |
56 |
+ |
57 |
+@@ -209,6 +210,18 @@ out: |
58 |
+ return ret; |
59 |
+ } |
60 |
+ |
61 |
++static void ibs_eilvt_setup(void) |
62 |
++{ |
63 |
++ /* |
64 |
++ * Force LVT offset assignment for family 10h: The offsets are |
65 |
++ * not assigned by the BIOS for this family, so the OS is |
66 |
++ * responsible for doing it. If the OS assignment fails, fall |
67 |
++ * back to BIOS settings and try to setup this. |
68 |
++ */ |
69 |
++ if (boot_cpu_data.x86 == 0x10) |
70 |
++ force_ibs_eilvt_setup(); |
71 |
++} |
72 |
++ |
73 |
+ static inline int get_ibs_lvt_offset(void) |
74 |
+ { |
75 |
+ u64 val; |
76 |
+@@ -244,6 +257,36 @@ static void clear_APIC_ibs(void *dummy) |
77 |
+ setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); |
78 |
+ } |
79 |
+ |
80 |
++#ifdef CONFIG_PM |
81 |
++ |
82 |
++static int perf_ibs_suspend(void) |
83 |
++{ |
84 |
++ clear_APIC_ibs(NULL); |
85 |
++ return 0; |
86 |
++} |
87 |
++ |
88 |
++static void perf_ibs_resume(void) |
89 |
++{ |
90 |
++ ibs_eilvt_setup(); |
91 |
++ setup_APIC_ibs(NULL); |
92 |
++} |
93 |
++ |
94 |
++static struct syscore_ops perf_ibs_syscore_ops = { |
95 |
++ .resume = perf_ibs_resume, |
96 |
++ .suspend = perf_ibs_suspend, |
97 |
++}; |
98 |
++ |
99 |
++static void perf_ibs_pm_init(void) |
100 |
++{ |
101 |
++ register_syscore_ops(&perf_ibs_syscore_ops); |
102 |
++} |
103 |
++ |
104 |
++#else |
105 |
++ |
106 |
++static inline void perf_ibs_pm_init(void) { } |
107 |
++ |
108 |
++#endif |
109 |
++ |
110 |
+ static int __cpuinit |
111 |
+ perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) |
112 |
+ { |
113 |
+@@ -270,18 +313,12 @@ static __init int amd_ibs_init(void) |
114 |
+ if (!caps) |
115 |
+ return -ENODEV; /* ibs not supported by the cpu */ |
116 |
+ |
117 |
+- /* |
118 |
+- * Force LVT offset assignment for family 10h: The offsets are |
119 |
+- * not assigned by the BIOS for this family, so the OS is |
120 |
+- * responsible for doing it. If the OS assignment fails, fall |
121 |
+- * back to BIOS settings and try to setup this. |
122 |
+- */ |
123 |
+- if (boot_cpu_data.x86 == 0x10) |
124 |
+- force_ibs_eilvt_setup(); |
125 |
++ ibs_eilvt_setup(); |
126 |
+ |
127 |
+ if (!ibs_eilvt_valid()) |
128 |
+ goto out; |
129 |
+ |
130 |
++ perf_ibs_pm_init(); |
131 |
+ get_online_cpus(); |
132 |
+ ibs_caps = caps; |
133 |
+ /* make ibs_caps visible to other cpus: */ |
134 |
+diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c |
135 |
+index 858432287ab6..2bf03a99c2f9 100644 |
136 |
+--- a/arch/x86/kvm/lapic.c |
137 |
++++ b/arch/x86/kvm/lapic.c |
138 |
+@@ -1278,14 +1278,12 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) |
139 |
+ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) |
140 |
+ { |
141 |
+ u32 data; |
142 |
+- void *vapic; |
143 |
+ |
144 |
+ if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr) |
145 |
+ return; |
146 |
+ |
147 |
+- vapic = kmap_atomic(vcpu->arch.apic->vapic_page); |
148 |
+- data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)); |
149 |
+- kunmap_atomic(vapic); |
150 |
++ kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, |
151 |
++ sizeof(u32)); |
152 |
+ |
153 |
+ apic_set_tpr(vcpu->arch.apic, data & 0xff); |
154 |
+ } |
155 |
+@@ -1295,7 +1293,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) |
156 |
+ u32 data, tpr; |
157 |
+ int max_irr, max_isr; |
158 |
+ struct kvm_lapic *apic; |
159 |
+- void *vapic; |
160 |
+ |
161 |
+ if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr) |
162 |
+ return; |
163 |
+@@ -1310,17 +1307,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) |
164 |
+ max_isr = 0; |
165 |
+ data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24); |
166 |
+ |
167 |
+- vapic = kmap_atomic(vcpu->arch.apic->vapic_page); |
168 |
+- *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data; |
169 |
+- kunmap_atomic(vapic); |
170 |
++ kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, |
171 |
++ sizeof(u32)); |
172 |
+ } |
173 |
+ |
174 |
+-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) |
175 |
++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) |
176 |
+ { |
177 |
+ if (!irqchip_in_kernel(vcpu->kvm)) |
178 |
+- return; |
179 |
++ return -EINVAL; |
180 |
++ |
181 |
++ if (vapic_addr) { |
182 |
++ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, |
183 |
++ &vcpu->arch.apic->vapic_cache, |
184 |
++ vapic_addr, sizeof(u32))) |
185 |
++ return -EINVAL; |
186 |
++ } |
187 |
+ |
188 |
+ vcpu->arch.apic->vapic_addr = vapic_addr; |
189 |
++ return 0; |
190 |
+ } |
191 |
+ |
192 |
+ int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) |
193 |
+diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h |
194 |
+index 6f4ce2575d09..6aec0714398e 100644 |
195 |
+--- a/arch/x86/kvm/lapic.h |
196 |
++++ b/arch/x86/kvm/lapic.h |
197 |
+@@ -15,7 +15,7 @@ struct kvm_lapic { |
198 |
+ bool irr_pending; |
199 |
+ void *regs; |
200 |
+ gpa_t vapic_addr; |
201 |
+- struct page *vapic_page; |
202 |
++ struct gfn_to_hva_cache vapic_cache; |
203 |
+ }; |
204 |
+ int kvm_create_lapic(struct kvm_vcpu *vcpu); |
205 |
+ void kvm_free_lapic(struct kvm_vcpu *vcpu); |
206 |
+@@ -46,7 +46,7 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); |
207 |
+ u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu); |
208 |
+ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data); |
209 |
+ |
210 |
+-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); |
211 |
++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); |
212 |
+ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu); |
213 |
+ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu); |
214 |
+ |
215 |
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c |
216 |
+index 3663e0b38976..4b1be290f6e3 100644 |
217 |
+--- a/arch/x86/kvm/x86.c |
218 |
++++ b/arch/x86/kvm/x86.c |
219 |
+@@ -2728,8 +2728,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, |
220 |
+ r = -EFAULT; |
221 |
+ if (copy_from_user(&va, argp, sizeof va)) |
222 |
+ goto out; |
223 |
+- r = 0; |
224 |
+- kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); |
225 |
++ r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); |
226 |
+ break; |
227 |
+ } |
228 |
+ case KVM_X86_SETUP_MCE: { |
229 |
+@@ -5075,33 +5074,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) |
230 |
+ !kvm_event_needs_reinjection(vcpu); |
231 |
+ } |
232 |
+ |
233 |
+-static void vapic_enter(struct kvm_vcpu *vcpu) |
234 |
+-{ |
235 |
+- struct kvm_lapic *apic = vcpu->arch.apic; |
236 |
+- struct page *page; |
237 |
+- |
238 |
+- if (!apic || !apic->vapic_addr) |
239 |
+- return; |
240 |
+- |
241 |
+- page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); |
242 |
+- |
243 |
+- vcpu->arch.apic->vapic_page = page; |
244 |
+-} |
245 |
+- |
246 |
+-static void vapic_exit(struct kvm_vcpu *vcpu) |
247 |
+-{ |
248 |
+- struct kvm_lapic *apic = vcpu->arch.apic; |
249 |
+- int idx; |
250 |
+- |
251 |
+- if (!apic || !apic->vapic_addr) |
252 |
+- return; |
253 |
+- |
254 |
+- idx = srcu_read_lock(&vcpu->kvm->srcu); |
255 |
+- kvm_release_page_dirty(apic->vapic_page); |
256 |
+- mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); |
257 |
+- srcu_read_unlock(&vcpu->kvm->srcu, idx); |
258 |
+-} |
259 |
+- |
260 |
+ static void update_cr8_intercept(struct kvm_vcpu *vcpu) |
261 |
+ { |
262 |
+ int max_irr, tpr; |
263 |
+@@ -5385,7 +5357,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) |
264 |
+ } |
265 |
+ |
266 |
+ vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); |
267 |
+- vapic_enter(vcpu); |
268 |
+ |
269 |
+ r = 1; |
270 |
+ while (r > 0) { |
271 |
+@@ -5442,8 +5413,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) |
272 |
+ |
273 |
+ srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); |
274 |
+ |
275 |
+- vapic_exit(vcpu); |
276 |
+- |
277 |
+ return r; |
278 |
+ } |
279 |
+ |
280 |
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c |
281 |
+index 0f52799973d4..fac07d3ae4f3 100644 |
282 |
+--- a/drivers/hwmon/coretemp.c |
283 |
++++ b/drivers/hwmon/coretemp.c |
284 |
+@@ -53,7 +53,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); |
285 |
+ |
286 |
+ #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ |
287 |
+ #define NUM_REAL_CORES 32 /* Number of Real cores per cpu */ |
288 |
+-#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ |
289 |
++#define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */ |
290 |
+ #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ |
291 |
+ #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) |
292 |
+ #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) |
293 |
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c |
294 |
+index 99a102d186ce..67a8393e3f86 100644 |
295 |
+--- a/drivers/md/raid10.c |
296 |
++++ b/drivers/md/raid10.c |
297 |
+@@ -1117,7 +1117,7 @@ read_again: |
298 |
+ /* Could not read all from this device, so we will |
299 |
+ * need another r10_bio. |
300 |
+ */ |
301 |
+- sectors_handled = (r10_bio->sectors + max_sectors |
302 |
++ sectors_handled = (r10_bio->sector + max_sectors |
303 |
+ - bio->bi_sector); |
304 |
+ r10_bio->sectors = max_sectors; |
305 |
+ spin_lock_irq(&conf->device_lock); |
306 |
+@@ -1125,7 +1125,7 @@ read_again: |
307 |
+ bio->bi_phys_segments = 2; |
308 |
+ else |
309 |
+ bio->bi_phys_segments++; |
310 |
+- spin_unlock(&conf->device_lock); |
311 |
++ spin_unlock_irq(&conf->device_lock); |
312 |
+ /* Cannot call generic_make_request directly |
313 |
+ * as that will be queued in __generic_make_request |
314 |
+ * and subsequent mempool_alloc might block |
315 |
+@@ -2943,10 +2943,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, |
316 |
+ if (j == conf->copies) { |
317 |
+ /* Cannot recover, so abort the recovery or |
318 |
+ * record a bad block */ |
319 |
+- put_buf(r10_bio); |
320 |
+- if (rb2) |
321 |
+- atomic_dec(&rb2->remaining); |
322 |
+- r10_bio = rb2; |
323 |
+ if (any_working) { |
324 |
+ /* problem is that there are bad blocks |
325 |
+ * on other device(s) |
326 |
+@@ -2978,6 +2974,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, |
327 |
+ mirror->recovery_disabled |
328 |
+ = mddev->recovery_disabled; |
329 |
+ } |
330 |
++ put_buf(r10_bio); |
331 |
++ if (rb2) |
332 |
++ atomic_dec(&rb2->remaining); |
333 |
++ r10_bio = rb2; |
334 |
+ break; |
335 |
+ } |
336 |
+ } |
337 |
+diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c |
338 |
+index 8f3215239a15..453ea2d57346 100644 |
339 |
+--- a/drivers/staging/comedi/drivers/cb_pcidio.c |
340 |
++++ b/drivers/staging/comedi/drivers/cb_pcidio.c |
341 |
+@@ -56,10 +56,6 @@ struct pcidio_board { |
342 |
+ const char *name; /* name of the board */ |
343 |
+ int dev_id; |
344 |
+ int n_8255; /* number of 8255 chips on board */ |
345 |
+- |
346 |
+- /* indices of base address regions */ |
347 |
+- int pcicontroler_badrindex; |
348 |
+- int dioregs_badrindex; |
349 |
+ }; |
350 |
+ |
351 |
+ static const struct pcidio_board pcidio_boards[] = { |
352 |
+@@ -67,22 +63,16 @@ static const struct pcidio_board pcidio_boards[] = { |
353 |
+ .name = "pci-dio24", |
354 |
+ .dev_id = 0x0028, |
355 |
+ .n_8255 = 1, |
356 |
+- .pcicontroler_badrindex = 1, |
357 |
+- .dioregs_badrindex = 2, |
358 |
+ }, |
359 |
+ { |
360 |
+ .name = "pci-dio24h", |
361 |
+ .dev_id = 0x0014, |
362 |
+ .n_8255 = 1, |
363 |
+- .pcicontroler_badrindex = 1, |
364 |
+- .dioregs_badrindex = 2, |
365 |
+ }, |
366 |
+ { |
367 |
+ .name = "pci-dio48h", |
368 |
+ .dev_id = 0x000b, |
369 |
+ .n_8255 = 2, |
370 |
+- .pcicontroler_badrindex = 0, |
371 |
+- .dioregs_badrindex = 1, |
372 |
+ }, |
373 |
+ }; |
374 |
+ |
375 |
+@@ -239,10 +229,15 @@ found: |
376 |
+ if (comedi_pci_enable(pcidev, thisboard->name)) |
377 |
+ return -EIO; |
378 |
+ |
379 |
+- devpriv->dio_reg_base |
380 |
+- = |
381 |
++ /* |
382 |
++ * Use PCI BAR 2 region if non-zero length, else use PCI BAR 1 region. |
383 |
++ * PCI BAR 1 is only used for older PCI-DIO48H boards. At some point |
384 |
++ * the PCI-DIO48H was redesigned to use the same PCI interface chip |
385 |
++ * (and same PCI BAR region) as the other boards. |
386 |
++ */ |
387 |
++ devpriv->dio_reg_base = |
388 |
+ pci_resource_start(devpriv->pci_dev, |
389 |
+- pcidio_boards[index].dioregs_badrindex); |
390 |
++ (pci_resource_len(pcidev, 2) ? 2 : 1)); |
391 |
+ |
392 |
+ /* |
393 |
+ * Allocate the subdevice structures. alloc_subdevice() is a |
394 |
+diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c |
395 |
+index 88e11fb346b6..d4ca8925f017 100644 |
396 |
+--- a/fs/nilfs2/segment.c |
397 |
++++ b/fs/nilfs2/segment.c |
398 |
+@@ -1436,17 +1436,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, |
399 |
+ |
400 |
+ nilfs_clear_logs(&sci->sc_segbufs); |
401 |
+ |
402 |
+- err = nilfs_segctor_extend_segments(sci, nilfs, nadd); |
403 |
+- if (unlikely(err)) |
404 |
+- return err; |
405 |
+- |
406 |
+ if (sci->sc_stage.flags & NILFS_CF_SUFREED) { |
407 |
+ err = nilfs_sufile_cancel_freev(nilfs->ns_sufile, |
408 |
+ sci->sc_freesegs, |
409 |
+ sci->sc_nfreesegs, |
410 |
+ NULL); |
411 |
+ WARN_ON(err); /* do not happen */ |
412 |
++ sci->sc_stage.flags &= ~NILFS_CF_SUFREED; |
413 |
+ } |
414 |
++ |
415 |
++ err = nilfs_segctor_extend_segments(sci, nilfs, nadd); |
416 |
++ if (unlikely(err)) |
417 |
++ return err; |
418 |
++ |
419 |
+ nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA); |
420 |
+ sci->sc_stage = prev_stage; |
421 |
+ } |
422 |
+diff --git a/mm/memory-failure.c b/mm/memory-failure.c |
423 |
+index d86fb2057354..7e95698e4139 100644 |
424 |
+--- a/mm/memory-failure.c |
425 |
++++ b/mm/memory-failure.c |
426 |
+@@ -1447,10 +1447,18 @@ static int soft_offline_huge_page(struct page *page, int flags) |
427 |
+ return ret; |
428 |
+ } |
429 |
+ done: |
430 |
+- if (!PageHWPoison(hpage)) |
431 |
+- atomic_long_add(1 << compound_trans_order(hpage), &mce_bad_pages); |
432 |
+- set_page_hwpoison_huge_page(hpage); |
433 |
+- dequeue_hwpoisoned_huge_page(hpage); |
434 |
++ /* overcommit hugetlb page will be freed to buddy */ |
435 |
++ if (PageHuge(hpage)) { |
436 |
++ if (!PageHWPoison(hpage)) |
437 |
++ atomic_long_add(1 << compound_trans_order(hpage), |
438 |
++ &mce_bad_pages); |
439 |
++ set_page_hwpoison_huge_page(hpage); |
440 |
++ dequeue_hwpoisoned_huge_page(hpage); |
441 |
++ } else { |
442 |
++ SetPageHWPoison(page); |
443 |
++ atomic_long_inc(&mce_bad_pages); |
444 |
++ } |
445 |
++ |
446 |
+ /* keep elevated page count for bad page */ |
447 |
+ return ret; |
448 |
+ } |
449 |
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c |
450 |
+index 9f6380ec1305..5b3db436814d 100644 |
451 |
+--- a/security/selinux/hooks.c |
452 |
++++ b/security/selinux/hooks.c |
453 |
+@@ -218,6 +218,14 @@ static int inode_alloc_security(struct inode *inode) |
454 |
+ return 0; |
455 |
+ } |
456 |
+ |
457 |
++static void inode_free_rcu(struct rcu_head *head) |
458 |
++{ |
459 |
++ struct inode_security_struct *isec; |
460 |
++ |
461 |
++ isec = container_of(head, struct inode_security_struct, rcu); |
462 |
++ kmem_cache_free(sel_inode_cache, isec); |
463 |
++} |
464 |
++ |
465 |
+ static void inode_free_security(struct inode *inode) |
466 |
+ { |
467 |
+ struct inode_security_struct *isec = inode->i_security; |
468 |
+@@ -228,8 +236,16 @@ static void inode_free_security(struct inode *inode) |
469 |
+ list_del_init(&isec->list); |
470 |
+ spin_unlock(&sbsec->isec_lock); |
471 |
+ |
472 |
+- inode->i_security = NULL; |
473 |
+- kmem_cache_free(sel_inode_cache, isec); |
474 |
++ /* |
475 |
++ * The inode may still be referenced in a path walk and |
476 |
++ * a call to selinux_inode_permission() can be made |
477 |
++ * after inode_free_security() is called. Ideally, the VFS |
478 |
++ * wouldn't do this, but fixing that is a much harder |
479 |
++ * job. For now, simply free the i_security via RCU, and |
480 |
++ * leave the current inode->i_security pointer intact. |
481 |
++ * The inode will be freed after the RCU grace period too. |
482 |
++ */ |
483 |
++ call_rcu(&isec->rcu, inode_free_rcu); |
484 |
+ } |
485 |
+ |
486 |
+ static int file_alloc_security(struct file *file) |
487 |
+diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h |
488 |
+index 26c7eee1c309..7b1830bde1c8 100644 |
489 |
+--- a/security/selinux/include/objsec.h |
490 |
++++ b/security/selinux/include/objsec.h |
491 |
+@@ -38,7 +38,10 @@ struct task_security_struct { |
492 |
+ |
493 |
+ struct inode_security_struct { |
494 |
+ struct inode *inode; /* back pointer to inode object */ |
495 |
+- struct list_head list; /* list of inode_security_struct */ |
496 |
++ union { |
497 |
++ struct list_head list; /* list of inode_security_struct */ |
498 |
++ struct rcu_head rcu; /* for freeing the inode_security_struct */ |
499 |
++ }; |
500 |
+ u32 task_sid; /* SID of creating task */ |
501 |
+ u32 sid; /* SID of this object */ |
502 |
+ u16 sclass; /* security class of this object */ |