Annotation of /trunk/kernel-alx/patches-5.4/0266-5.4.167-all-fixes.patch
Parent Directory | Revision Log
Revision 3635 -
(hide annotations)
(download)
Mon Oct 24 12:34:12 2022 UTC (19 months, 1 week ago) by niro
File size: 20385 byte(s)
Mon Oct 24 12:34:12 2022 UTC (19 months, 1 week ago) by niro
File size: 20385 byte(s)
-sync kernel patches
1 | niro | 3635 | diff --git a/Makefile b/Makefile |
2 | index b1e5f7c6206ed..1045f7fc08503 100644 | ||
3 | --- a/Makefile | ||
4 | +++ b/Makefile | ||
5 | @@ -1,7 +1,7 @@ | ||
6 | # SPDX-License-Identifier: GPL-2.0 | ||
7 | VERSION = 5 | ||
8 | PATCHLEVEL = 4 | ||
9 | -SUBLEVEL = 166 | ||
10 | +SUBLEVEL = 167 | ||
11 | EXTRAVERSION = | ||
12 | NAME = Kleptomaniac Octopus | ||
13 | |||
14 | diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c | ||
15 | index 5a3641b5ec2cd..ff2cd985d20e0 100644 | ||
16 | --- a/arch/arm/mm/init.c | ||
17 | +++ b/arch/arm/mm/init.c | ||
18 | @@ -176,11 +176,22 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max_low, | ||
19 | int pfn_valid(unsigned long pfn) | ||
20 | { | ||
21 | phys_addr_t addr = __pfn_to_phys(pfn); | ||
22 | + unsigned long pageblock_size = PAGE_SIZE * pageblock_nr_pages; | ||
23 | |||
24 | if (__phys_to_pfn(addr) != pfn) | ||
25 | return 0; | ||
26 | |||
27 | - return memblock_is_map_memory(__pfn_to_phys(pfn)); | ||
28 | + /* | ||
29 | + * If address less than pageblock_size bytes away from a present | ||
30 | + * memory chunk there still will be a memory map entry for it | ||
31 | + * because we round freed memory map to the pageblock boundaries. | ||
32 | + */ | ||
33 | + if (memblock_overlaps_region(&memblock.memory, | ||
34 | + ALIGN_DOWN(addr, pageblock_size), | ||
35 | + pageblock_size)) | ||
36 | + return 1; | ||
37 | + | ||
38 | + return 0; | ||
39 | } | ||
40 | EXPORT_SYMBOL(pfn_valid); | ||
41 | #endif | ||
42 | @@ -371,14 +382,14 @@ static void __init free_unused_memmap(void) | ||
43 | */ | ||
44 | start = min(start, | ||
45 | ALIGN(prev_end, PAGES_PER_SECTION)); | ||
46 | -#else | ||
47 | +#endif | ||
48 | /* | ||
49 | - * Align down here since the VM subsystem insists that the | ||
50 | - * memmap entries are valid from the bank start aligned to | ||
51 | - * MAX_ORDER_NR_PAGES. | ||
52 | + * Align down here since many operations in VM subsystem | ||
53 | + * presume that there are no holes in the memory map inside | ||
54 | + * a pageblock | ||
55 | */ | ||
56 | - start = round_down(start, MAX_ORDER_NR_PAGES); | ||
57 | -#endif | ||
58 | + start = round_down(start, pageblock_nr_pages); | ||
59 | + | ||
60 | /* | ||
61 | * If we had a previous bank, and there is a space | ||
62 | * between the current bank and the previous, free it. | ||
63 | @@ -387,18 +398,20 @@ static void __init free_unused_memmap(void) | ||
64 | free_memmap(prev_end, start); | ||
65 | |||
66 | /* | ||
67 | - * Align up here since the VM subsystem insists that the | ||
68 | - * memmap entries are valid from the bank end aligned to | ||
69 | - * MAX_ORDER_NR_PAGES. | ||
70 | + * Align up here since many operations in VM subsystem | ||
71 | + * presume that there are no holes in the memory map inside | ||
72 | + * a pageblock | ||
73 | */ | ||
74 | prev_end = ALIGN(memblock_region_memory_end_pfn(reg), | ||
75 | - MAX_ORDER_NR_PAGES); | ||
76 | + pageblock_nr_pages); | ||
77 | } | ||
78 | |||
79 | #ifdef CONFIG_SPARSEMEM | ||
80 | - if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION)) | ||
81 | + if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION)) { | ||
82 | + prev_end = ALIGN(prev_end, pageblock_nr_pages); | ||
83 | free_memmap(prev_end, | ||
84 | ALIGN(prev_end, PAGES_PER_SECTION)); | ||
85 | + } | ||
86 | #endif | ||
87 | } | ||
88 | |||
89 | diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c | ||
90 | index d42b933161832..513c26b46db35 100644 | ||
91 | --- a/arch/arm/mm/ioremap.c | ||
92 | +++ b/arch/arm/mm/ioremap.c | ||
93 | @@ -27,6 +27,7 @@ | ||
94 | #include <linux/vmalloc.h> | ||
95 | #include <linux/io.h> | ||
96 | #include <linux/sizes.h> | ||
97 | +#include <linux/memblock.h> | ||
98 | |||
99 | #include <asm/cp15.h> | ||
100 | #include <asm/cputype.h> | ||
101 | @@ -301,7 +302,8 @@ static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, | ||
102 | * Don't allow RAM to be mapped with mismatched attributes - this | ||
103 | * causes problems with ARMv6+ | ||
104 | */ | ||
105 | - if (WARN_ON(pfn_valid(pfn) && mtype != MT_MEMORY_RW)) | ||
106 | + if (WARN_ON(memblock_is_map_memory(PFN_PHYS(pfn)) && | ||
107 | + mtype != MT_MEMORY_RW)) | ||
108 | return NULL; | ||
109 | |||
110 | area = get_vm_area_caller(size, VM_IOREMAP, caller); | ||
111 | diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c | ||
112 | index 26408434b9bcf..be92e8dccda3d 100644 | ||
113 | --- a/arch/x86/kvm/hyperv.c | ||
114 | +++ b/arch/x86/kvm/hyperv.c | ||
115 | @@ -1501,11 +1501,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *current_vcpu, u64 ingpa, u64 outgpa, | ||
116 | |||
117 | all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL; | ||
118 | |||
119 | + if (all_cpus) | ||
120 | + goto check_and_send_ipi; | ||
121 | + | ||
122 | if (!sparse_banks_len) | ||
123 | goto ret_success; | ||
124 | |||
125 | - if (!all_cpus && | ||
126 | - kvm_read_guest(kvm, | ||
127 | + if (kvm_read_guest(kvm, | ||
128 | ingpa + offsetof(struct hv_send_ipi_ex, | ||
129 | vp_set.bank_contents), | ||
130 | sparse_banks, | ||
131 | @@ -1513,6 +1515,7 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *current_vcpu, u64 ingpa, u64 outgpa, | ||
132 | return HV_STATUS_INVALID_HYPERCALL_INPUT; | ||
133 | } | ||
134 | |||
135 | +check_and_send_ipi: | ||
136 | if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) | ||
137 | return HV_STATUS_INVALID_HYPERCALL_INPUT; | ||
138 | |||
139 | diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c | ||
140 | index ed3c4c42fc23b..d68d05d5d3838 100644 | ||
141 | --- a/drivers/char/agp/parisc-agp.c | ||
142 | +++ b/drivers/char/agp/parisc-agp.c | ||
143 | @@ -281,7 +281,7 @@ agp_ioc_init(void __iomem *ioc_regs) | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | -static int | ||
148 | +static int __init | ||
149 | lba_find_capability(int cap) | ||
150 | { | ||
151 | struct _parisc_agp_info *info = &parisc_agp_info; | ||
152 | @@ -366,7 +366,7 @@ fail: | ||
153 | return error; | ||
154 | } | ||
155 | |||
156 | -static int | ||
157 | +static int __init | ||
158 | find_quicksilver(struct device *dev, void *data) | ||
159 | { | ||
160 | struct parisc_device **lba = data; | ||
161 | @@ -378,7 +378,7 @@ find_quicksilver(struct device *dev, void *data) | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | -static int | ||
166 | +static int __init | ||
167 | parisc_agp_init(void) | ||
168 | { | ||
169 | extern struct sba_device *sba_list; | ||
170 | diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | ||
171 | index f0b001b3af578..883ee517673bd 100644 | ||
172 | --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | ||
173 | +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | ||
174 | @@ -221,6 +221,14 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) | ||
175 | ret = -EINVAL; | ||
176 | goto cleanup; | ||
177 | } | ||
178 | + | ||
179 | + if ((aconn->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) && | ||
180 | + (aconn->base.connector_type != DRM_MODE_CONNECTOR_eDP)) { | ||
181 | + DRM_DEBUG_DRIVER("No DP connector available for CRC source\n"); | ||
182 | + ret = -EINVAL; | ||
183 | + goto cleanup; | ||
184 | + } | ||
185 | + | ||
186 | } | ||
187 | |||
188 | if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source)) { | ||
189 | diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c | ||
190 | index f25ac17f47fa9..95a5310e9e661 100644 | ||
191 | --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c | ||
192 | +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c | ||
193 | @@ -1546,6 +1546,10 @@ bool dc_is_stream_unchanged( | ||
194 | if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) | ||
195 | return false; | ||
196 | |||
197 | + // Only Have Audio left to check whether it is same or not. This is a corner case for Tiled sinks | ||
198 | + if (old_stream->audio_info.mode_count != stream->audio_info.mode_count) | ||
199 | + return false; | ||
200 | + | ||
201 | return true; | ||
202 | } | ||
203 | |||
204 | diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c | ||
205 | index 5613234823f7d..423c4ae2be10d 100644 | ||
206 | --- a/drivers/gpu/drm/msm/dsi/dsi_host.c | ||
207 | +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c | ||
208 | @@ -1669,6 +1669,8 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host, | ||
209 | if (!prop) { | ||
210 | DRM_DEV_DEBUG(dev, | ||
211 | "failed to find data lane mapping, using default\n"); | ||
212 | + /* Set the number of date lanes to 4 by default. */ | ||
213 | + msm_host->num_data_lanes = 4; | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c | ||
218 | index 35c00420d855b..2eaed0008f376 100644 | ||
219 | --- a/drivers/hwmon/dell-smm-hwmon.c | ||
220 | +++ b/drivers/hwmon/dell-smm-hwmon.c | ||
221 | @@ -588,15 +588,18 @@ static const struct file_operations i8k_fops = { | ||
222 | .unlocked_ioctl = i8k_ioctl, | ||
223 | }; | ||
224 | |||
225 | +static struct proc_dir_entry *entry; | ||
226 | + | ||
227 | static void __init i8k_init_procfs(void) | ||
228 | { | ||
229 | /* Register the proc entry */ | ||
230 | - proc_create("i8k", 0, NULL, &i8k_fops); | ||
231 | + entry = proc_create("i8k", 0, NULL, &i8k_fops); | ||
232 | } | ||
233 | |||
234 | static void __exit i8k_exit_procfs(void) | ||
235 | { | ||
236 | - remove_proc_entry("i8k", NULL); | ||
237 | + if (entry) | ||
238 | + remove_proc_entry("i8k", NULL); | ||
239 | } | ||
240 | |||
241 | #else | ||
242 | diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c | ||
243 | index 1a33007b03e9e..1107a5e7229e4 100644 | ||
244 | --- a/drivers/i2c/busses/i2c-rk3x.c | ||
245 | +++ b/drivers/i2c/busses/i2c-rk3x.c | ||
246 | @@ -422,8 +422,8 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) | ||
247 | if (!(ipd & REG_INT_MBRF)) | ||
248 | return; | ||
249 | |||
250 | - /* ack interrupt */ | ||
251 | - i2c_writel(i2c, REG_INT_MBRF, REG_IPD); | ||
252 | + /* ack interrupt (read also produces a spurious START flag, clear it too) */ | ||
253 | + i2c_writel(i2c, REG_INT_MBRF | REG_INT_START, REG_IPD); | ||
254 | |||
255 | /* Can only handle a maximum of 32 bytes at a time */ | ||
256 | if (len > 32) | ||
257 | diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | ||
258 | index 426786a349c3c..dd029d91bbc2d 100644 | ||
259 | --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | ||
260 | +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | ||
261 | @@ -663,7 +663,7 @@ void __init mlx4_en_init_ptys2ethtool_map(void) | ||
262 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_T, SPEED_1000, | ||
263 | ETHTOOL_LINK_MODE_1000baseT_Full_BIT); | ||
264 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_CX_SGMII, SPEED_1000, | ||
265 | - ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); | ||
266 | + ETHTOOL_LINK_MODE_1000baseX_Full_BIT); | ||
267 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_KX, SPEED_1000, | ||
268 | ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); | ||
269 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_T, SPEED_10000, | ||
270 | @@ -675,9 +675,9 @@ void __init mlx4_en_init_ptys2ethtool_map(void) | ||
271 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_KR, SPEED_10000, | ||
272 | ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); | ||
273 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_CR, SPEED_10000, | ||
274 | - ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); | ||
275 | + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT); | ||
276 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_SR, SPEED_10000, | ||
277 | - ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); | ||
278 | + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT); | ||
279 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_20GBASE_KR2, SPEED_20000, | ||
280 | ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT, | ||
281 | ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT); | ||
282 | diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c | ||
283 | index 6684696fa4571..4b2819b0a05ab 100644 | ||
284 | --- a/kernel/bpf/devmap.c | ||
285 | +++ b/kernel/bpf/devmap.c | ||
286 | @@ -94,7 +94,7 @@ static struct hlist_head *dev_map_create_hash(unsigned int entries, | ||
287 | int i; | ||
288 | struct hlist_head *hash; | ||
289 | |||
290 | - hash = bpf_map_area_alloc(entries * sizeof(*hash), numa_node); | ||
291 | + hash = bpf_map_area_alloc((u64) entries * sizeof(*hash), numa_node); | ||
292 | if (hash != NULL) | ||
293 | for (i = 0; i < entries; i++) | ||
294 | INIT_HLIST_HEAD(&hash[i]); | ||
295 | @@ -159,7 +159,7 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) | ||
296 | |||
297 | spin_lock_init(&dtab->index_lock); | ||
298 | } else { | ||
299 | - dtab->netdev_map = bpf_map_area_alloc(dtab->map.max_entries * | ||
300 | + dtab->netdev_map = bpf_map_area_alloc((u64) dtab->map.max_entries * | ||
301 | sizeof(struct bpf_dtab_netdev *), | ||
302 | dtab->map.numa_node); | ||
303 | if (!dtab->netdev_map) | ||
304 | diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c | ||
305 | index 10657b8dc2c2d..83c2a0598c648 100644 | ||
306 | --- a/kernel/trace/tracing_map.c | ||
307 | +++ b/kernel/trace/tracing_map.c | ||
308 | @@ -15,6 +15,7 @@ | ||
309 | #include <linux/jhash.h> | ||
310 | #include <linux/slab.h> | ||
311 | #include <linux/sort.h> | ||
312 | +#include <linux/kmemleak.h> | ||
313 | |||
314 | #include "tracing_map.h" | ||
315 | #include "trace.h" | ||
316 | @@ -307,6 +308,7 @@ void tracing_map_array_free(struct tracing_map_array *a) | ||
317 | for (i = 0; i < a->n_pages; i++) { | ||
318 | if (!a->pages[i]) | ||
319 | break; | ||
320 | + kmemleak_free(a->pages[i]); | ||
321 | free_page((unsigned long)a->pages[i]); | ||
322 | } | ||
323 | |||
324 | @@ -342,6 +344,7 @@ struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts, | ||
325 | a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL); | ||
326 | if (!a->pages[i]) | ||
327 | goto free; | ||
328 | + kmemleak_alloc(a->pages[i], PAGE_SIZE, 1, GFP_KERNEL); | ||
329 | } | ||
330 | out: | ||
331 | return a; | ||
332 | diff --git a/mm/memblock.c b/mm/memblock.c | ||
333 | index 11f6ae37d6699..38cef8b6df050 100644 | ||
334 | --- a/mm/memblock.c | ||
335 | +++ b/mm/memblock.c | ||
336 | @@ -164,6 +164,8 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type, | ||
337 | { | ||
338 | unsigned long i; | ||
339 | |||
340 | + memblock_cap_size(base, &size); | ||
341 | + | ||
342 | for (i = 0; i < type->cnt; i++) | ||
343 | if (memblock_addrs_overlap(base, size, type->regions[i].base, | ||
344 | type->regions[i].size)) | ||
345 | @@ -1760,7 +1762,6 @@ bool __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t siz | ||
346 | */ | ||
347 | bool __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size) | ||
348 | { | ||
349 | - memblock_cap_size(base, &size); | ||
350 | return memblock_overlaps_region(&memblock.reserved, base, size); | ||
351 | } | ||
352 | |||
353 | diff --git a/net/core/sock_map.c b/net/core/sock_map.c | ||
354 | index df52061f99f76..2646e8f98f67d 100644 | ||
355 | --- a/net/core/sock_map.c | ||
356 | +++ b/net/core/sock_map.c | ||
357 | @@ -48,7 +48,7 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr) | ||
358 | if (err) | ||
359 | goto free_stab; | ||
360 | |||
361 | - stab->sks = bpf_map_area_alloc(stab->map.max_entries * | ||
362 | + stab->sks = bpf_map_area_alloc((u64) stab->map.max_entries * | ||
363 | sizeof(struct sock *), | ||
364 | stab->map.numa_node); | ||
365 | if (stab->sks) | ||
366 | diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c | ||
367 | index cb35680db9b29..891e029ad0f89 100644 | ||
368 | --- a/net/netlink/af_netlink.c | ||
369 | +++ b/net/netlink/af_netlink.c | ||
370 | @@ -1862,6 +1862,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) | ||
371 | if (msg->msg_flags&MSG_OOB) | ||
372 | return -EOPNOTSUPP; | ||
373 | |||
374 | + if (len == 0) { | ||
375 | + pr_warn_once("Zero length message leads to an empty skb\n"); | ||
376 | + return -ENODATA; | ||
377 | + } | ||
378 | + | ||
379 | err = scm_send(sock, msg, &scm, true); | ||
380 | if (err < 0) | ||
381 | return err; | ||
382 | diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c | ||
383 | index 0f61dad7256b8..4d90cbdc083b5 100644 | ||
384 | --- a/net/nfc/netlink.c | ||
385 | +++ b/net/nfc/netlink.c | ||
386 | @@ -644,8 +644,10 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) | ||
387 | { | ||
388 | struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; | ||
389 | |||
390 | - nfc_device_iter_exit(iter); | ||
391 | - kfree(iter); | ||
392 | + if (iter) { | ||
393 | + nfc_device_iter_exit(iter); | ||
394 | + kfree(iter); | ||
395 | + } | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c | ||
400 | index f62adf3cfce89..a0afe49309c88 100644 | ||
401 | --- a/security/selinux/ss/services.c | ||
402 | +++ b/security/selinux/ss/services.c | ||
403 | @@ -2250,6 +2250,43 @@ size_t security_policydb_len(struct selinux_state *state) | ||
404 | return len; | ||
405 | } | ||
406 | |||
407 | +/** | ||
408 | + * ocontext_to_sid - Helper to safely get sid for an ocontext | ||
409 | + * @sidtab: SID table | ||
410 | + * @c: ocontext structure | ||
411 | + * @index: index of the context entry (0 or 1) | ||
412 | + * @out_sid: pointer to the resulting SID value | ||
413 | + * | ||
414 | + * For all ocontexts except OCON_ISID the SID fields are populated | ||
415 | + * on-demand when needed. Since updating the SID value is an SMP-sensitive | ||
416 | + * operation, this helper must be used to do that safely. | ||
417 | + * | ||
418 | + * WARNING: This function may return -ESTALE, indicating that the caller | ||
419 | + * must retry the operation after re-acquiring the policy pointer! | ||
420 | + */ | ||
421 | +static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c, | ||
422 | + size_t index, u32 *out_sid) | ||
423 | +{ | ||
424 | + int rc; | ||
425 | + u32 sid; | ||
426 | + | ||
427 | + /* Ensure the associated sidtab entry is visible to this thread. */ | ||
428 | + sid = smp_load_acquire(&c->sid[index]); | ||
429 | + if (!sid) { | ||
430 | + rc = sidtab_context_to_sid(sidtab, &c->context[index], &sid); | ||
431 | + if (rc) | ||
432 | + return rc; | ||
433 | + | ||
434 | + /* | ||
435 | + * Ensure the new sidtab entry is visible to other threads | ||
436 | + * when they see the SID. | ||
437 | + */ | ||
438 | + smp_store_release(&c->sid[index], sid); | ||
439 | + } | ||
440 | + *out_sid = sid; | ||
441 | + return 0; | ||
442 | +} | ||
443 | + | ||
444 | /** | ||
445 | * security_port_sid - Obtain the SID for a port. | ||
446 | * @protocol: protocol number | ||
447 | @@ -2262,10 +2299,12 @@ int security_port_sid(struct selinux_state *state, | ||
448 | struct policydb *policydb; | ||
449 | struct sidtab *sidtab; | ||
450 | struct ocontext *c; | ||
451 | - int rc = 0; | ||
452 | + int rc; | ||
453 | |||
454 | read_lock(&state->ss->policy_rwlock); | ||
455 | |||
456 | +retry: | ||
457 | + rc = 0; | ||
458 | policydb = &state->ss->policydb; | ||
459 | sidtab = state->ss->sidtab; | ||
460 | |||
461 | @@ -2279,14 +2318,11 @@ int security_port_sid(struct selinux_state *state, | ||
462 | } | ||
463 | |||
464 | if (c) { | ||
465 | - if (!c->sid[0]) { | ||
466 | - rc = sidtab_context_to_sid(sidtab, | ||
467 | - &c->context[0], | ||
468 | - &c->sid[0]); | ||
469 | - if (rc) | ||
470 | - goto out; | ||
471 | - } | ||
472 | - *out_sid = c->sid[0]; | ||
473 | + rc = ocontext_to_sid(sidtab, c, 0, out_sid); | ||
474 | + if (rc == -ESTALE) | ||
475 | + goto retry; | ||
476 | + if (rc) | ||
477 | + goto out; | ||
478 | } else { | ||
479 | *out_sid = SECINITSID_PORT; | ||
480 | } | ||
481 | @@ -2308,10 +2344,12 @@ int security_ib_pkey_sid(struct selinux_state *state, | ||
482 | struct policydb *policydb; | ||
483 | struct sidtab *sidtab; | ||
484 | struct ocontext *c; | ||
485 | - int rc = 0; | ||
486 | + int rc; | ||
487 | |||
488 | read_lock(&state->ss->policy_rwlock); | ||
489 | |||
490 | +retry: | ||
491 | + rc = 0; | ||
492 | policydb = &state->ss->policydb; | ||
493 | sidtab = state->ss->sidtab; | ||
494 | |||
495 | @@ -2326,14 +2364,11 @@ int security_ib_pkey_sid(struct selinux_state *state, | ||
496 | } | ||
497 | |||
498 | if (c) { | ||
499 | - if (!c->sid[0]) { | ||
500 | - rc = sidtab_context_to_sid(sidtab, | ||
501 | - &c->context[0], | ||
502 | - &c->sid[0]); | ||
503 | - if (rc) | ||
504 | - goto out; | ||
505 | - } | ||
506 | - *out_sid = c->sid[0]; | ||
507 | + rc = ocontext_to_sid(sidtab, c, 0, out_sid); | ||
508 | + if (rc == -ESTALE) | ||
509 | + goto retry; | ||
510 | + if (rc) | ||
511 | + goto out; | ||
512 | } else | ||
513 | *out_sid = SECINITSID_UNLABELED; | ||
514 | |||
515 | @@ -2354,10 +2389,12 @@ int security_ib_endport_sid(struct selinux_state *state, | ||
516 | struct policydb *policydb; | ||
517 | struct sidtab *sidtab; | ||
518 | struct ocontext *c; | ||
519 | - int rc = 0; | ||
520 | + int rc; | ||
521 | |||
522 | read_lock(&state->ss->policy_rwlock); | ||
523 | |||
524 | +retry: | ||
525 | + rc = 0; | ||
526 | policydb = &state->ss->policydb; | ||
527 | sidtab = state->ss->sidtab; | ||
528 | |||
529 | @@ -2373,14 +2410,11 @@ int security_ib_endport_sid(struct selinux_state *state, | ||
530 | } | ||
531 | |||
532 | if (c) { | ||
533 | - if (!c->sid[0]) { | ||
534 | - rc = sidtab_context_to_sid(sidtab, | ||
535 | - &c->context[0], | ||
536 | - &c->sid[0]); | ||
537 | - if (rc) | ||
538 | - goto out; | ||
539 | - } | ||
540 | - *out_sid = c->sid[0]; | ||
541 | + rc = ocontext_to_sid(sidtab, c, 0, out_sid); | ||
542 | + if (rc == -ESTALE) | ||
543 | + goto retry; | ||
544 | + if (rc) | ||
545 | + goto out; | ||
546 | } else | ||
547 | *out_sid = SECINITSID_UNLABELED; | ||
548 | |||
549 | @@ -2399,11 +2433,13 @@ int security_netif_sid(struct selinux_state *state, | ||
550 | { | ||
551 | struct policydb *policydb; | ||
552 | struct sidtab *sidtab; | ||
553 | - int rc = 0; | ||
554 | + int rc; | ||
555 | struct ocontext *c; | ||
556 | |||
557 | read_lock(&state->ss->policy_rwlock); | ||
558 | |||
559 | +retry: | ||
560 | + rc = 0; | ||
561 | policydb = &state->ss->policydb; | ||
562 | sidtab = state->ss->sidtab; | ||
563 | |||
564 | @@ -2415,19 +2451,11 @@ int security_netif_sid(struct selinux_state *state, | ||
565 | } | ||
566 | |||
567 | if (c) { | ||
568 | - if (!c->sid[0] || !c->sid[1]) { | ||
569 | - rc = sidtab_context_to_sid(sidtab, | ||
570 | - &c->context[0], | ||
571 | - &c->sid[0]); | ||
572 | - if (rc) | ||
573 | - goto out; | ||
574 | - rc = sidtab_context_to_sid(sidtab, | ||
575 | - &c->context[1], | ||
576 | - &c->sid[1]); | ||
577 | - if (rc) | ||
578 | - goto out; | ||
579 | - } | ||
580 | - *if_sid = c->sid[0]; | ||
581 | + rc = ocontext_to_sid(sidtab, c, 0, if_sid); | ||
582 | + if (rc == -ESTALE) | ||
583 | + goto retry; | ||
584 | + if (rc) | ||
585 | + goto out; | ||
586 | } else | ||
587 | *if_sid = SECINITSID_NETIF; | ||
588 | |||
589 | @@ -2469,6 +2497,7 @@ int security_node_sid(struct selinux_state *state, | ||
590 | |||
591 | read_lock(&state->ss->policy_rwlock); | ||
592 | |||
593 | +retry: | ||
594 | policydb = &state->ss->policydb; | ||
595 | sidtab = state->ss->sidtab; | ||
596 | |||
597 | @@ -2511,14 +2540,11 @@ int security_node_sid(struct selinux_state *state, | ||
598 | } | ||
599 | |||
600 | if (c) { | ||
601 | - if (!c->sid[0]) { | ||
602 | - rc = sidtab_context_to_sid(sidtab, | ||
603 | - &c->context[0], | ||
604 | - &c->sid[0]); | ||
605 | - if (rc) | ||
606 | - goto out; | ||
607 | - } | ||
608 | - *out_sid = c->sid[0]; | ||
609 | + rc = ocontext_to_sid(sidtab, c, 0, out_sid); | ||
610 | + if (rc == -ESTALE) | ||
611 | + goto retry; | ||
612 | + if (rc) | ||
613 | + goto out; | ||
614 | } else { | ||
615 | *out_sid = SECINITSID_NODE; | ||
616 | } | ||
617 | @@ -2677,7 +2703,7 @@ static inline int __security_genfs_sid(struct selinux_state *state, | ||
618 | u16 sclass; | ||
619 | struct genfs *genfs; | ||
620 | struct ocontext *c; | ||
621 | - int rc, cmp = 0; | ||
622 | + int cmp = 0; | ||
623 | |||
624 | while (path[0] == '/' && path[1] == '/') | ||
625 | path++; | ||
626 | @@ -2691,9 +2717,8 @@ static inline int __security_genfs_sid(struct selinux_state *state, | ||
627 | break; | ||
628 | } | ||
629 | |||
630 | - rc = -ENOENT; | ||
631 | if (!genfs || cmp) | ||
632 | - goto out; | ||
633 | + return -ENOENT; | ||
634 | |||
635 | for (c = genfs->head; c; c = c->next) { | ||
636 | len = strlen(c->u.name); | ||
637 | @@ -2702,20 +2727,10 @@ static inline int __security_genfs_sid(struct selinux_state *state, | ||
638 | break; | ||
639 | } | ||
640 | |||
641 | - rc = -ENOENT; | ||
642 | if (!c) | ||
643 | - goto out; | ||
644 | - | ||
645 | - if (!c->sid[0]) { | ||
646 | - rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); | ||
647 | - if (rc) | ||
648 | - goto out; | ||
649 | - } | ||
650 | + return -ENOENT; | ||
651 | |||
652 | - *sid = c->sid[0]; | ||
653 | - rc = 0; | ||
654 | -out: | ||
655 | - return rc; | ||
656 | + return ocontext_to_sid(sidtab, c, 0, sid); | ||
657 | } | ||
658 | |||
659 | /** | ||
660 | @@ -2750,13 +2765,15 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) | ||
661 | { | ||
662 | struct policydb *policydb; | ||
663 | struct sidtab *sidtab; | ||
664 | - int rc = 0; | ||
665 | + int rc; | ||
666 | struct ocontext *c; | ||
667 | struct superblock_security_struct *sbsec = sb->s_security; | ||
668 | const char *fstype = sb->s_type->name; | ||
669 | |||
670 | read_lock(&state->ss->policy_rwlock); | ||
671 | |||
672 | +retry: | ||
673 | + rc = 0; | ||
674 | policydb = &state->ss->policydb; | ||
675 | sidtab = state->ss->sidtab; | ||
676 | |||
677 | @@ -2769,13 +2786,11 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) | ||
678 | |||
679 | if (c) { | ||
680 | sbsec->behavior = c->v.behavior; | ||
681 | - if (!c->sid[0]) { | ||
682 | - rc = sidtab_context_to_sid(sidtab, &c->context[0], | ||
683 | - &c->sid[0]); | ||
684 | - if (rc) | ||
685 | - goto out; | ||
686 | - } | ||
687 | - sbsec->sid = c->sid[0]; | ||
688 | + rc = ocontext_to_sid(sidtab, c, 0, &sbsec->sid); | ||
689 | + if (rc == -ESTALE) | ||
690 | + goto retry; | ||
691 | + if (rc) | ||
692 | + goto out; | ||
693 | } else { | ||
694 | rc = __security_genfs_sid(state, fstype, "/", SECCLASS_DIR, | ||
695 | &sbsec->sid); |