Skip to contentSkip to conversation

3.14.65-stable review

PATCH In review Greg Kroah-Hartman 3 participants 21 messages Mar 14, 2016 – Mar 15, 2016 Stable branch

lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 3.14.65-stable review

This is the start of the stable review cycle for the 3.14.65 release. There are 19 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Wed Mar 16 17:50:23 UTC 2016. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v3.x/stable-review/patch-3.14.65-rc1.gz

and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 3.14.65-rc1

Greg Kroah-Hartman <[email protected]>
Revert: "crypto: af_alg - Disallow bind/setkey/... after accept(2)"

Rusty Russell <[email protected]>
modules: fix longstanding /proc/kallsyms vs module insertion race.

Jason Andryuk <[email protected]>

    lib/ucs2_string: Correct ucs2 -> utf8 conversion

Matt Fleming <[email protected]>
efi: Add pstore variables to the deletion whitelist

Peter Jones <[email protected]>
efi: Make efivarfs entries immutable by default

Peter Jones <[email protected]>
efi: Make our variable validation list include the guid

Peter Jones <[email protected]>
efi: Do variable name validation tests in utf8

Peter Jones <[email protected]>
efi: Use ucs2_as_utf8 in efivarfs instead of open coding a bad version

Peter Jones <[email protected]>

    lib/ucs2_string: Add ucs2 -> utf8 helper functions

Marcelo Tosatti <[email protected]>
KVM: x86: move steal time initialization to vcpu entry time

Andreas Schwab <[email protected]>
powerpc: Fix dedotify for binutils >= 2.26

Felix Fietkau <[email protected]>
mac80211: minstrel_ht: set default tx aggregation timeout to 0

Chris Bainbridge <[email protected]>
mac80211: fix use of uninitialised values in RX aggregation

Johannes Berg <[email protected]>
wext: fix message delay/ordering

Takashi Iwai <[email protected]>
ASoC: wm8958: Fix enum ctl accesses in a wrong type

Takashi Iwai <[email protected]>
ASoC: wm8994: Fix enum ctl accesses in a wrong type

Steven Rostedt (Red Hat) <[email protected]>
tracing: Fix check for cpu online when event is disabled

Paul Mackerras <[email protected]>
KVM: PPC: Book3S HV: Sanitize special-purpose register values on guest exit

Radim Krčmář <[email protected]>
KVM: VMX: disable PEBS before a guest entry

-------------

Diffstat:

 Documentation/filesystems/efivarfs.txt         |   7 ++
 Makefile                                       |   4 +-
 arch/powerpc/kernel/module_64.c                |   2 +-
 arch/powerpc/kvm/book3s_hv_rmhandlers.S        |  14 +++
 arch/x86/kvm/vmx.c                             |   7 ++
 arch/x86/kvm/x86.c                             |   9 +-
 crypto/af_alg.c                                |  35 +-----
 drivers/firmware/efi/efivars.c                 |  34 +++--
 drivers/firmware/efi/vars.c                    | 164 +++++++++++++++++--------
 fs/efivarfs/file.c                             |  71 +++++++++++
 fs/efivarfs/inode.c                            |  30 +++--
 fs/efivarfs/internal.h                         |   3 +-
 fs/efivarfs/super.c                            |  16 ++-
 include/crypto/if_alg.h                        |   8 +-
 include/linux/efi.h                            |   9 +-
 include/linux/module.h                         |  17 +--
 include/linux/tracepoint.h                     |  17 +--
 include/linux/ucs2_string.h                    |   4 +
 kernel/module.c                                | 111 ++++++++++-------
 lib/ucs2_string.c                              |  62 ++++++++++
 net/mac80211/agg-rx.c                          |   2 +-
 net/mac80211/rc80211_minstrel_ht.c             |   2 +-
 net/wireless/wext-core.c                       |  51 ++++++--
 sound/soc/codecs/wm8958-dsp2.c                 |   8 +-
 sound/soc/codecs/wm8994.c                      |   4 +-
 tools/testing/selftests/efivarfs/efivarfs.sh   |  19 ++-
 tools/testing/selftests/efivarfs/open-unlink.c |  72 ++++++++++-
 27 files changed, 567 insertions(+), 215 deletions(-)
author maintainer
#1 lore raw

PATCH 2/19 KVM: PPC: Book3S HV: Sanitize special-purpose register values on guest exit

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Paul Mackerras <[email protected]>

commit ccec44563b18a0ce90e2d4f332784b3cb25c8e9c upstream.

Thomas Huth discovered that a guest could cause a hard hang of a host CPU by setting the Instruction Authority Mask Register (IAMR) to a suitable value. It turns out that this is because when the code was added to context-switch the new special-purpose registers (SPRs) that were added in POWER8, we forgot to add code to ensure that they were restored to a sane value on guest exit.

This adds code to set those registers where a bad value could compromise the execution of the host kernel to a suitable neutral value on guest exit.

---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S |   14 ++++++++++++++
 1 file changed, 14 insertions(+)
arch/powerpc/kvm/book3s_hv_rmhandlers.S +14 -0
@@ -1148,6 +1148,20 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	std	r6, VCPU_ACOP(r9)
 	stw	r7, VCPU_GUEST_PID(r9)
 	std	r8, VCPU_WORT(r9)
+	/*
+	 * Restore various registers to 0, where non-zero values
+	 * set by the guest could disrupt the host.
+	 */
+	li	r0, 0
+	mtspr	SPRN_IAMR, r0
+	mtspr	SPRN_CIABR, r0
+	mtspr	SPRN_DAWRX, r0
+	mtspr	SPRN_TCSCR, r0
+	mtspr	SPRN_WORT, r0
+	/* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
+	li	r0, 1
+	sldi	r0, r0, 31
+	mtspr	SPRN_MMCRS, r0
 8:
 
 	/* Save and reset AMR and UAMOR before turning on the MMU */
author maintainer
#2 lore raw

PATCH 3/19 tracing: Fix check for cpu online when event is disabled

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Steven Rostedt (Red Hat) <[email protected]>

commit dc17147de328a74bbdee67c1bf37d2f1992de756 upstream.

Commit f37755490fe9b ("tracepoints: Do not trace when cpu is offline") added a check to make sure that tracepoints only get called when the cpu is online, as it uses rcu_read_lock_sched() for protection.

Commit 3a630178fd5f3 ("tracing: generate RCU warnings even when tracepoints are disabled") added lockdep checks (including rcu checks) for events that are not enabled to catch possible RCU issues that would only be triggered if a trace event was enabled. Commit f37755490fe9b only stopped the warnings when the trace event was enabled but did not prevent warnings if the trace event was called when disabled.

To fix this, the cpu online check is moved to where the condition is added to the trace event. This will place the cpu online check in all places that it may be used now and in the future.

Fixes f37755490fe9b ("tracepoints: Do not trace when cpu is offline")
Fixes 3a630178fd5f3 ("tracing: generate RCU warnings even when tracepoints are disabled")
---
 include/linux/tracepoint.h |   17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)
include/linux/tracepoint.h +9 -8
@@ -129,9 +129,6 @@ static inline void tracepoint_synchroniz
 		void *it_func;						\
 		void *__data;						\
 									\
-		if (!cpu_online(raw_smp_processor_id()))		\
-			return;						\
-									\
 		if (!(cond))						\
 			return;						\
 		prercu;							\
@@ -265,15 +262,19 @@ static inline void tracepoint_synchroniz
  * "void *__data, proto" as the callback prototype.
  */
 #define DECLARE_TRACE_NOARGS(name)					\
-		__DECLARE_TRACE(name, void, , 1, void *__data, __data)
+	__DECLARE_TRACE(name, void, ,					\
+			cpu_online(raw_smp_processor_id()),		\
+			void *__data, __data)
 
 #define DECLARE_TRACE(name, proto, args)				\
-		__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1,	\
-				PARAMS(void *__data, proto),		\
-				PARAMS(__data, args))
+	__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),		\
+			cpu_online(raw_smp_processor_id()),		\
+			PARAMS(void *__data, proto),			\
+			PARAMS(__data, args))
 
 #define DECLARE_TRACE_CONDITION(name, proto, args, cond)		\
-	__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \
+	__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),		\
+			cpu_online(raw_smp_processor_id()) && (PARAMS(cond)), \
 			PARAMS(void *__data, proto),			\
 			PARAMS(__data, args))
 
author maintainer
#3 lore raw

PATCH 4/19 ASoC: wm8994: Fix enum ctl accesses in a wrong type

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[email protected]>

commit 8019c0b37cd5a87107808300a496388b777225bf upstream.

The DRC Mode like "AIF1DRC1 Mode" and EQ Mode like "AIF1.1 EQ Mode" in wm8994 codec driver are enum ctls, while the current driver accesses wrongly via value.integer.value[]. They have to be via value.enumerated.item[] instead.

---
 sound/soc/codecs/wm8994.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/codecs/wm8994.c +2 -2
@@ -360,7 +360,7 @@ static int wm8994_put_drc_enum(struct sn
 	struct wm8994 *control = wm8994->wm8994;
 	struct wm8994_pdata *pdata = &control->pdata;
 	int drc = wm8994_get_drc(kcontrol->id.name);
-	int value = ucontrol->value.integer.value[0];
+	int value = ucontrol->value.enumerated.item[0];
 
 	if (drc < 0)
 		return drc;
@@ -467,7 +467,7 @@ static int wm8994_put_retune_mobile_enum
 	struct wm8994 *control = wm8994->wm8994;
 	struct wm8994_pdata *pdata = &control->pdata;
 	int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
-	int value = ucontrol->value.integer.value[0];
+	int value = ucontrol->value.enumerated.item[0];
 
 	if (block < 0)
 		return block;
author maintainer
#4 lore raw

PATCH 5/19 ASoC: wm8958: Fix enum ctl accesses in a wrong type

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[email protected]>

commit d0784829ae3b0beeb69b476f017d5c8a2eb95198 upstream.

"MBC Mode", "VSS Mode", "VSS HPF Mode" and "Enhanced EQ Mode" ctls in wm8958 codec driver are enum, while the current driver accesses wrongly via value.integer.value[]. They have to be via value.enumerated.item[] instead.

---
 sound/soc/codecs/wm8958-dsp2.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
sound/soc/codecs/wm8958-dsp2.c +4 -4
@@ -459,7 +459,7 @@ static int wm8958_put_mbc_enum(struct sn
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
-	int value = ucontrol->value.integer.value[0];
+	int value = ucontrol->value.enumerated.item[0];
 	int reg;
 
 	/* Don't allow on the fly reconfiguration */
@@ -549,7 +549,7 @@ static int wm8958_put_vss_enum(struct sn
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
-	int value = ucontrol->value.integer.value[0];
+	int value = ucontrol->value.enumerated.item[0];
 	int reg;
 
 	/* Don't allow on the fly reconfiguration */
@@ -582,7 +582,7 @@ static int wm8958_put_vss_hpf_enum(struc
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
-	int value = ucontrol->value.integer.value[0];
+	int value = ucontrol->value.enumerated.item[0];
 	int reg;
 
 	/* Don't allow on the fly reconfiguration */
@@ -749,7 +749,7 @@ static int wm8958_put_enh_eq_enum(struct
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
-	int value = ucontrol->value.integer.value[0];
+	int value = ucontrol->value.enumerated.item[0];
 	int reg;
 
 	/* Don't allow on the fly reconfiguration */
author maintainer
#5 lore raw

PATCH 6/19 wext: fix message delay/ordering

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johannes Berg <[email protected]>

commit 8bf862739a7786ae72409220914df960a0aa80d8 upstream.

Beniamino reported that he was getting an RTM_NEWLINK message for a given interface, after the RTM_DELLINK for it. It turns out that the message is a wireless extensions message, which was sent because the interface had been connected and disconnection while it was deleted caused a wext message.

For its netlink messages, wext uses RTM_NEWLINK, but the message is without all the regular rtnetlink attributes, so "ip monitor link" prints just rudimentary information:

5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default

    link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff
Deleted 5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default
    link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff

5: wlan1: <BROADCAST,MULTICAST,UP>
link/ether
(from my hwsim reproduction)

This can cause userspace to get confused since it doesn't expect an RTM_NEWLINK message after RTM_DELLINK.

The reason for this is that wext schedules a worker to send out the messages, and the scheduling delay can cause the messages to get out to userspace in different order.

To fix this, have wext register a netdevice notifier and flush out any pending messages when netdevice state changes. This fixes any ordering whenever the original message wasn't sent by a notifier itself.

---
 net/wireless/wext-core.c |   51 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 40 insertions(+), 11 deletions(-)
net/wireless/wext-core.c +40 -11
@@ -342,6 +342,39 @@ static const int compat_event_type_size[
 
 /* IW event code */
 
+static void wireless_nlevent_flush(void)
+{
+	struct sk_buff *skb;
+	struct net *net;
+
+	ASSERT_RTNL();
+
+	for_each_net(net) {
+		while ((skb = skb_dequeue(&net->wext_nlevents)))
+			rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
+				    GFP_KERNEL);
+	}
+}
+
+static int wext_netdev_notifier_call(struct notifier_block *nb,
+				     unsigned long state, void *ptr)
+{
+	/*
+	 * When a netdev changes state in any way, flush all pending messages
+	 * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
+	 * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
+	 * or similar - all of which could otherwise happen due to delays from
+	 * schedule_work().
+	 */
+	wireless_nlevent_flush();
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block wext_netdev_notifier = {
+	.notifier_call = wext_netdev_notifier_call,
+};
+
 static int __net_init wext_pernet_init(struct net *net)
 {
 	skb_queue_head_init(&net->wext_nlevents);
@@ -360,7 +393,12 @@ static struct pernet_operations wext_per
 
 static int __init wireless_nlevent_init(void)
 {
-	return register_pernet_subsys(&wext_pernet_ops);
+	int err = register_pernet_subsys(&wext_pernet_ops);
+
+	if (err)
+		return err;
+
+	return register_netdevice_notifier(&wext_netdev_notifier);
 }
 
 subsys_initcall(wireless_nlevent_init);
@@ -368,17 +406,8 @@ subsys_initcall(wireless_nlevent_init);
 /* Process events generated by the wireless layer or the driver. */
 static void wireless_nlevent_process(struct work_struct *work)
 {
-	struct sk_buff *skb;
-	struct net *net;
-
 	rtnl_lock();
-
-	for_each_net(net) {
-		while ((skb = skb_dequeue(&net->wext_nlevents)))
-			rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
-				    GFP_KERNEL);
-	}
-
+	wireless_nlevent_flush();
 	rtnl_unlock();
 }
 
author maintainer
#6 lore raw

PATCH 7/19 mac80211: fix use of uninitialised values in RX aggregation

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chris Bainbridge <[email protected]>

commit f39ea2690bd61efec97622c48323f40ed6e16317 upstream.

Use kzalloc instead of kmalloc for struct tid_ampdu_rx to initialize the "removed" field (all others are initialized manually). That fixes:

UBSAN: Undefined behaviour in net/mac80211/rx.c:932:29
load of value 2 is not a valid value for type '_Bool'
CPU: 3 PID: 1134 Comm: kworker/u16:7 Not tainted 4.5.0-rc1+ #265
Workqueue: phy0 rt2x00usb_work_rxdone
 0000000000000004 ffff880254a7ba50 ffffffff8181d866 0000000000000007
 ffff880254a7ba78 ffff880254a7ba68 ffffffff8188422d ffffffff8379b500
 ffff880254a7bab8 ffffffff81884747 0000000000000202 0000000348620032
Call Trace:
 [<ffffffff8181d866>] dump_stack+0x45/0x5f
 [<ffffffff8188422d>] ubsan_epilogue+0xd/0x40
 [<ffffffff81884747>] __ubsan_handle_load_invalid_value+0x67/0x70
 [<ffffffff82227b4d>] ieee80211_sta_reorder_release.isra.16+0x5ed/0x730
 [<ffffffff8222ca14>] ieee80211_prepare_and_rx_handle+0xd04/0x1c00
 [<ffffffff8222db03>] __ieee80211_rx_handle_packet+0x1f3/0x750
 [<ffffffff8222e4a7>] ieee80211_rx_napi+0x447/0x990

While at it, convert to use sizeof(*tid_agg_rx) instead.

Fixes 788211d81bfdf ("mac80211: fix RX A-MPDU session reorder timer deletion")
[reword commit message, use sizeof(*tid_agg_rx)]
---
 net/mac80211/agg-rx.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/agg-rx.c +1 -1
@@ -290,7 +290,7 @@ void ieee80211_process_addba_request(str
 	}
 
 	/* prepare A-MPDU MLME for Rx aggregation */
-	tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
+	tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
 	if (!tid_agg_rx)
 		goto end;
 
author maintainer
#7 lore raw

PATCH 8/19 mac80211: minstrel_ht: set default tx aggregation timeout to 0

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Felix Fietkau <[email protected]>

commit 7a36b930e6ed4702c866dc74a5ad07318a57c688 upstream.

The value 5000 was put here with the addition of the timeout field to ieee80211_start_tx_ba_session. It was originally added in mac80211 to save resources for drivers like iwlwifi, which only supports a limited number of concurrent aggregation sessions.

Since iwlwifi does not use minstrel_ht and other drivers don't need this, 0 is a better default - especially since there have been recent reports of aggregation setup related issues reproduced with ath9k. This should improve stability without causing any adverse effects.

---
 net/mac80211/rc80211_minstrel_ht.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/rc80211_minstrel_ht.c +1 -1
@@ -463,7 +463,7 @@ minstrel_aggr_check(struct ieee80211_sta
 	if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
 		return;
 
-	ieee80211_start_tx_ba_session(pubsta, tid, 5000);
+	ieee80211_start_tx_ba_session(pubsta, tid, 0);
 }
 
 static void
author maintainer
#8 lore raw

PATCH 9/19 powerpc: Fix dedotify for binutils >= 2.26

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andreas Schwab <[email protected]>

commit f15838e9cac8f78f0cc506529bb9d3b9fa589c1f upstream.

Since binutils 2.26 BFD is doing suffix merging on STRTAB sections. But dedotify modifies the symbol names in place, which can also modify unrelated symbols with a name that matches a suffix of a dotted name. To remove the leading dot of a symbol name we can just increment the pointer into the STRTAB section instead.

Backport to all stables to avoid breakage when people update their binutils - mpe.

---
 arch/powerpc/kernel/module_64.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/module_64.c +1 -1
@@ -202,7 +202,7 @@ static void dedotify(Elf64_Sym *syms, un
 		if (syms[i].st_shndx == SHN_UNDEF) {
 			char *name = strtab + syms[i].st_name;
 			if (name[0] == '.')
-				memmove(name, name+1, strlen(name));
+				syms[i].st_name++;
 		}
 	}
 }
author maintainer
#9 lore raw

PATCH 10/19 KVM: x86: move steal time initialization to vcpu entry time

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Marcelo Tosatti <[email protected]>

commit 7cae2bedcbd4680b155999655e49c27b9cf020fa upstream.

As reported at https://bugs.launchpad.net/qemu/+bug/1494350,
it is possible to have vcpu->arch.st.last_steal initialized from a thread other than vcpu thread, say the iothread, via KVM_SET_MSRS.

Which can cause an overflow later (when subtracting from vcpu threads sched_info.run_delay).

To avoid that, move steal time accumulation to vcpu entry time, before copying steal time data to guest.

---
 arch/x86/kvm/x86.c |    9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)
arch/x86/kvm/x86.c +2 -7
@@ -1991,6 +1991,8 @@ static void accumulate_steal_time(struct
 
 static void record_steal_time(struct kvm_vcpu *vcpu)
 {
+	accumulate_steal_time(vcpu);
+
 	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
 		return;
 
@@ -2123,12 +2125,6 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		if (!(data & KVM_MSR_ENABLED))
 			break;
 
-		vcpu->arch.st.last_steal = current->sched_info.run_delay;
-
-		preempt_disable();
-		accumulate_steal_time(vcpu);
-		preempt_enable();
-
 		kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
 
 		break;
@@ -2818,7 +2814,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 		vcpu->cpu = cpu;
 	}
 
-	accumulate_steal_time(vcpu);
 	kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
 }
 
author maintainer
#10 lore raw

PATCH 11/19 lib/ucs2_string: Add ucs2 -> utf8 helper functions

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Jones <[email protected]>

commit 73500267c930baadadb0d02284909731baf151f7 upstream.

This adds ucs2_utf8size(), which tells us how big our ucs2 string is in bytes, and ucs2_as_utf8, which translates from ucs2 to utf8..

---
 include/linux/ucs2_string.h |    4 ++
 lib/ucs2_string.c           |   62 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)
include/linux/ucs2_string.h +4 -0
@@ -11,4 +11,8 @@ unsigned long ucs2_strlen(const ucs2_cha
 unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
 int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
 
+unsigned long ucs2_utf8size(const ucs2_char_t *src);
+unsigned long ucs2_as_utf8(u8 *dest, const ucs2_char_t *src,
+			   unsigned long maxlength);
+
 #endif /* _LINUX_UCS2_STRING_H_ */
lib/ucs2_string.c +62 -0

65 lines not on this page · raw message

author maintainer
#11 lore raw

PATCH 12/19 efi: Use ucs2_as_utf8 in efivarfs instead of open coding a bad version

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Jones <[email protected]>

commit e0d64e6a880e64545ad7d55786aa84ab76bac475 upstream.

Translate EFI's UCS-2 variable names to UTF-8 instead of just assuming all variable names fit in ASCII.

---
 drivers/firmware/efi/efivars.c |   28 ++++++++++------------------
 fs/efivarfs/super.c            |    7 +++----
 2 files changed, 13 insertions(+), 22 deletions(-)
drivers/firmware/efi/efivars.c +10 -18
@@ -409,35 +409,27 @@ efivar_create_sysfs_entry(struct efivar_
 {
 	int i, short_name_size;
 	char *short_name;
-	unsigned long variable_name_size;
-	efi_char16_t *variable_name;
-
-	variable_name = new_var->var.VariableName;
-	variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);
+	unsigned long utf8_name_size;
+	efi_char16_t *variable_name = new_var->var.VariableName;
 
 	/*
-	 * Length of the variable bytes in ASCII, plus the '-' separator,
+	 * Length of the variable bytes in UTF8, plus the '-' separator,
 	 * plus the GUID, plus trailing NUL
 	 */
-	short_name_size = variable_name_size / sizeof(efi_char16_t)
-				+ 1 + EFI_VARIABLE_GUID_LEN + 1;
-
-	short_name = kzalloc(short_name_size, GFP_KERNEL);
+	utf8_name_size = ucs2_utf8size(variable_name);
+	short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
 
+	short_name = kmalloc(short_name_size, GFP_KERNEL);
 	if (!short_name)
 		return 1;
 
-	/* Convert Unicode to normal chars (assume top bits are 0),
-	   ala UTF-8 */
-	for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
-		short_name[i] = variable_name[i] & 0xFF;
-	}
+	ucs2_as_utf8(short_name, variable_name, short_name_size);
+
 	/* This is ugly, but necessary to separate one vendor's
 	   private variables from another's.         */
-
-	*(short_name + strlen(short_name)) = '-';
+	short_name[utf8_name_size] = '-';
 	efi_guid_unparse(&new_var->var.VendorGuid,
-			 short_name + strlen(short_name));
+			 short_name + utf8_name_size + 1);
 
 	new_var->kobj.kset = efivars_kset;
 
fs/efivarfs/super.c +3 -4
@@ -118,7 +118,7 @@ static int efivarfs_callback(efi_char16_
 	struct dentry *dentry, *root = sb->s_root;
 	unsigned long size = 0;
 	char *name;
-	int len, i;
+	int len;
 	int err = -ENOMEM;
 
 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
@@ -128,15 +128,14 @@ static int efivarfs_callback(efi_char16_
 	memcpy(entry->var.VariableName, name16, name_size);
 	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
 
-	len = ucs2_strlen(entry->var.VariableName);
+	len = ucs2_utf8size(entry->var.VariableName);
 
 	/* name, plus '-', plus GUID, plus NUL*/
 	name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
 	if (!name)
 		goto fail;
 
-	for (i = 0; i < len; i++)
-		name[i] = entry->var.VariableName[i] & 0xFF;
+	ucs2_as_utf8(name, entry->var.VariableName, len);
 
 	name[len] = '-';
 
author maintainer
#12 lore raw

PATCH 13/19 efi: Do variable name validation tests in utf8

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Jones <[email protected]>

commit 3dcb1f55dfc7631695e69df4a0d589ce5274bd07 upstream.

Actually translate from ucs2 to utf8 before doing the test, and then test against our other utf8 data, instead of fudging it.

---
 drivers/firmware/efi/efivars.c |    4 +-
 drivers/firmware/efi/vars.c    |   58 ++++++++++++++++++++++++-----------------
 include/linux/efi.h            |    6 ++--
 3 files changed, 40 insertions(+), 28 deletions(-)
drivers/firmware/efi/efivars.c +2 -2
@@ -219,7 +219,7 @@ efivar_store_raw(struct efivar_entry *en
 	}
 
 	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
-	    efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
+	    efivar_validate(new_var->VariableName, new_var->Data, new_var->DataSize) == false) {
 		printk(KERN_ERR "efivars: Malformed variable content\n");
 		return -EINVAL;
 	}
@@ -334,7 +334,7 @@ static ssize_t efivar_create(struct file
 		return -EACCES;
 
 	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
-	    efivar_validate(new_var, new_var->Data, new_var->DataSize) == false) {
+	    efivar_validate(new_var->VariableName, new_var->Data, new_var->DataSize) == false) {
 		printk(KERN_ERR "efivars: Malformed variable content\n");
 		return -EINVAL;
 	}
drivers/firmware/efi/vars.c +34 -24

137 lines not on this page · raw message

include/linux/efi.h +4 -2
@@ -792,8 +792,10 @@ struct efivars {
  * and we use a page for reading/writing.
  */
 
+#define EFI_VAR_NAME_LEN	1024
+
 struct efi_variable {
-	efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
+	efi_char16_t  VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
 	efi_guid_t    VendorGuid;
 	unsigned long DataSize;
 	__u8          Data[1024];
@@ -864,7 +866,7 @@ int efivar_entry_iter(int (*func)(struct
 struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
 				       struct list_head *head, bool remove);
 
-bool efivar_validate(struct efi_variable *var, u8 *data, unsigned long len);
+bool efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len);
 
 extern struct work_struct efivar_work;
 void efivar_run_worker(void);
author maintainer
#13 lore raw

PATCH 14/19 efi: Make our variable validation list include the guid

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Jones <[email protected]>

commit 8282f5d9c17fe15a9e658c06e3f343efae1a2a2f upstream.

All the variables in this list so far are defined to be in the global namespace in the UEFI spec, so this just further ensures we're validating the variables we think we are.

Including the guid for entries will become more important in future patches when we decide whether or not to allow deletion of variables based on presence in this list.

---
 drivers/firmware/efi/efivars.c |    6 +++-
 drivers/firmware/efi/vars.c    |   52 ++++++++++++++++++++++++++---------------
 include/linux/efi.h            |    3 +-
 3 files changed, 39 insertions(+), 22 deletions(-)
drivers/firmware/efi/efivars.c +4 -2
@@ -219,7 +219,8 @@ efivar_store_raw(struct efivar_entry *en
 	}
 
 	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
-	    efivar_validate(new_var->VariableName, new_var->Data, new_var->DataSize) == false) {
+	    efivar_validate(new_var->VendorGuid, new_var->VariableName,
+			    new_var->Data, new_var->DataSize) == false) {
 		printk(KERN_ERR "efivars: Malformed variable content\n");
 		return -EINVAL;
 	}
@@ -334,7 +335,8 @@ static ssize_t efivar_create(struct file
 		return -EACCES;
 
 	if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
-	    efivar_validate(new_var->VariableName, new_var->Data, new_var->DataSize) == false) {
+	    efivar_validate(new_var->VendorGuid, new_var->VariableName,
+			    new_var->Data, new_var->DataSize) == false) {
 		printk(KERN_ERR "efivars: Malformed variable content\n");
 		return -EINVAL;
 	}
drivers/firmware/efi/vars.c +33 -19

80 lines not on this page · raw message

include/linux/efi.h +2 -1
@@ -866,7 +866,8 @@ int efivar_entry_iter(int (*func)(struct
 struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
 				       struct list_head *head, bool remove);
 
-bool efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len);
+bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
+		     unsigned long data_size);
 
 extern struct work_struct efivar_work;
 void efivar_run_worker(void);
author maintainer
#14 lore raw

PATCH 15/19 efi: Make efivarfs entries immutable by default

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Jones <[email protected]>

commit ed8b0de5a33d2a2557dce7f9429dca8cb5bc5879 upstream.

"rm -rf" is bricking some peoples' laptops because of variables being used to store non-reinitializable firmware driver data that's required to POST the hardware.

These are 100% bugs, and they need to be fixed, but in the mean time it shouldn't be easy to *accidentally* brick machines.

We have to have delete working, and picking which variables do and don't work for deletion is quite intractable, so instead make everything immutable by default (except for a whitelist), and make tools that aren't quite so broad-spectrum unset the immutable flag.

---
 Documentation/filesystems/efivarfs.txt         |    7 ++
 drivers/firmware/efi/vars.c                    |   87 ++++++++++++++++++-------
 fs/efivarfs/file.c                             |   71 ++++++++++++++++++++
 fs/efivarfs/inode.c                            |   30 +++++---
 fs/efivarfs/internal.h                         |    3 
 fs/efivarfs/super.c                            |    9 ++
 include/linux/efi.h                            |    2 
 tools/testing/selftests/efivarfs/efivarfs.sh   |   19 ++++-
 tools/testing/selftests/efivarfs/open-unlink.c |   72 ++++++++++++++++++++
 9 files changed, 259 insertions(+), 41 deletions(-)
Documentation/filesystems/efivarfs.txt +7 -0
@@ -14,3 +14,10 @@ filesystem.
 efivarfs is typically mounted like this,
 
 	mount -t efivarfs none /sys/firmware/efi/efivars
+
+Due to the presence of numerous firmware bugs where removing non-standard
+UEFI variables causes the system firmware to fail to POST, efivarfs
+files that are not well-known standardized variables are created
+as immutable files.  This doesn't prevent removal - "chattr -i" will work -
+but it does prevent this kind of failure from being accomplished
+accidentally.
drivers/firmware/efi/vars.c +64 -23

120 lines not on this page · raw message

fs/efivarfs/file.c +71 -0

86 lines not on this page · raw message

fs/efivarfs/inode.c +19 -11
@@ -15,7 +15,8 @@
 #include "internal.h"
 
 struct inode *efivarfs_get_inode(struct super_block *sb,
-				const struct inode *dir, int mode, dev_t dev)
+				const struct inode *dir, int mode,
+				dev_t dev, bool is_removable)
 {
 	struct inode *inode = new_inode(sb);
 
@@ -23,6 +24,7 @@ struct inode *efivarfs_get_inode(struct
 		inode->i_ino = get_next_ino();
 		inode->i_mode = mode;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inode->i_flags = is_removable ? 0 : S_IMMUTABLE;
 		switch (mode & S_IFMT) {
 		case S_IFREG:
 			inode->i_fop = &efivarfs_file_operations;
@@ -102,22 +104,17 @@ static void efivarfs_hex_to_guid(const c
 static int efivarfs_create(struct inode *dir, struct dentry *dentry,
 			  umode_t mode, bool excl)
 {
-	struct inode *inode;
+	struct inode *inode = NULL;
 	struct efivar_entry *var;
 	int namelen, i = 0, err = 0;
+	bool is_removable = false;
 
 	if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
 		return -EINVAL;
 
-	inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
-	if (!inode)
-		return -ENOMEM;
-
 	var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
-	if (!var) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!var)
+		return -ENOMEM;
 
 	/* length of the variable name itself: remove GUID and separator */
 	namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1;
@@ -125,6 +122,16 @@ static int efivarfs_create(struct inode
 	efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
 			&var->var.VendorGuid);
 
+	if (efivar_variable_is_removable(var->var.VendorGuid,
+					 dentry->d_name.name, namelen))
+		is_removable = true;
+
+	inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0, is_removable);
+	if (!inode) {
+		err = -ENOMEM;
+		goto out;
+	}
+
 	for (i = 0; i < namelen; i++)
 		var->var.VariableName[i] = dentry->d_name.name[i];
 
@@ -138,7 +145,8 @@ static int efivarfs_create(struct inode
 out:
 	if (err) {
 		kfree(var);
-		iput(inode);
+		if (inode)
+			iput(inode);
 	}
 	return err;
 }
fs/efivarfs/internal.h +2 -1
@@ -15,7 +15,8 @@ extern const struct file_operations efiv
 extern const struct inode_operations efivarfs_dir_inode_operations;
 extern bool efivarfs_valid_name(const char *str, int len);
 extern struct inode *efivarfs_get_inode(struct super_block *sb,
-			const struct inode *dir, int mode, dev_t dev);
+			const struct inode *dir, int mode, dev_t dev,
+			bool is_removable);
 
 extern struct list_head efivarfs_list;
 
fs/efivarfs/super.c +7 -2
@@ -120,6 +120,7 @@ static int efivarfs_callback(efi_char16_
 	char *name;
 	int len;
 	int err = -ENOMEM;
+	bool is_removable = false;
 
 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
@@ -137,13 +138,17 @@ static int efivarfs_callback(efi_char16_
 
 	ucs2_as_utf8(name, entry->var.VariableName, len);
 
+	if (efivar_variable_is_removable(entry->var.VendorGuid, name, len))
+		is_removable = true;
+
 	name[len] = '-';
 
 	efi_guid_unparse(&entry->var.VendorGuid, name + len + 1);
 
 	name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
 
-	inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0);
+	inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0,
+				   is_removable);
 	if (!inode)
 		goto fail_name;
 
@@ -199,7 +204,7 @@ static int efivarfs_fill_super(struct su
 	sb->s_d_op		= &efivarfs_d_ops;
 	sb->s_time_gran         = 1;
 
-	inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
+	inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true);
 	if (!inode)
 		return -ENOMEM;
 	inode->i_op = &efivarfs_dir_inode_operations;
include/linux/efi.h +2 -0
@@ -868,6 +868,8 @@ struct efivar_entry *efivar_entry_find(e
 
 bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
 		     unsigned long data_size);
+bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
+				  size_t len);
 
 extern struct work_struct efivar_work;
 void efivar_run_worker(void);
tools/testing/selftests/efivarfs/efivarfs.sh +16 -3
@@ -88,7 +88,11 @@ test_delete()
 		exit 1
 	fi
 
-	rm $file
+	rm $file 2>/dev/null
+	if [ $? -ne 0 ]; then
+		chattr -i $file
+		rm $file
+	fi
 
 	if [ -e $file ]; then
 		echo "$file couldn't be deleted" >&2
@@ -111,6 +115,7 @@ test_zero_size_delete()
 		exit 1
 	fi
 
+	chattr -i $file
 	printf "$attrs" > $file
 
 	if [ -e $file ]; then
@@ -141,7 +146,11 @@ test_valid_filenames()
 			echo "$file could not be created" >&2
 			ret=1
 		else
-			rm $file
+			rm $file 2>/dev/null
+			if [ $? -ne 0 ]; then
+				chattr -i $file
+				rm $file
+			fi
 		fi
 	done
 
@@ -174,7 +183,11 @@ test_invalid_filenames()
 
 		if [ -e $file ]; then
 			echo "Creating $file should have failed" >&2
-			rm $file
+			rm $file 2>/dev/null
+			if [ $? -ne 0 ]; then
+				chattr -i $file
+				rm $file
+			fi
 			ret=1
 		fi
 	done
tools/testing/selftests/efivarfs/open-unlink.c +71 -1

94 lines not on this page · raw message

author maintainer
#15 lore raw

PATCH 16/19 efi: Add pstore variables to the deletion whitelist

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matt Fleming <[email protected]>

commit e246eb568bc4cbbdd8a30a3c11151ff9b7ca7312 upstream.

Laszlo explains why this is a good idea,

'This is because the pstore filesystem can be backed by UEFI variables,
and (for example) a crash might dump the last kilobytes of the dmesg into a number of pstore entries, each entry backed by a separate UEFI variable in the above GUID namespace, and with a variable name according to the above pattern.

Please see "drivers/firmware/efi/efi-pstore.c".

While this patch series will not prevent the user from deleting those UEFI variables via the pstore filesystem (i.e., deleting a pstore fs entry will continue to delete the backing UEFI variable), I think it would be nice to preserve the possibility for the sysadmin to delete Linux-created UEFI variables that carry portions of the crash log, *without* having to mount the pstore filesystem.'

There's also no chance of causing machines to become bricked by deleting these variables, which is the whole purpose of excluding things from the whitelist.

Use the LINUX_EFI_CRASH_GUID guid and a wildcard '*' for the match so that we don't have to update the string in the future if new variable name formats are created for crash dump variables.

---
 drivers/firmware/efi/vars.c |    1 +
 1 file changed, 1 insertion(+)
drivers/firmware/efi/vars.c +1 -0
@@ -198,6 +198,7 @@ static const struct variable_validate va
 	{ EFI_GLOBAL_VARIABLE_GUID, "OsIndications", NULL },
 	{ EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
 	{ EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
+	{ LINUX_EFI_CRASH_GUID, "*", NULL },
 	{ NULL_GUID, "", NULL },
 };
 
author maintainer
#16 lore raw

PATCH 17/19 lib/ucs2_string: Correct ucs2 -> utf8 conversion

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jason Andryuk <[email protected]>

commit a68075908a37850918ad96b056acc9ac4ce1bd90 upstream.

The comparisons should be >= since 0x800 and 0x80 require an additional bit to store.

For the 3 byte case, the existing shift would drop off 2 more bits than intended.

For the 2 byte case, there should be 5 bits bits in byte 1, and 6 bits in byte 2.

---
 lib/ucs2_string.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
lib/ucs2_string.c +7 -7
@@ -59,9 +59,9 @@ ucs2_utf8size(const ucs2_char_t *src)
 	for (i = 0; i < ucs2_strlen(src); i++) {
 		u16 c = src[i];
 
-		if (c > 0x800)
+		if (c >= 0x800)
 			j += 3;
-		else if (c > 0x80)
+		else if (c >= 0x80)
 			j += 2;
 		else
 			j += 1;
@@ -88,19 +88,19 @@ ucs2_as_utf8(u8 *dest, const ucs2_char_t
 	for (i = 0; maxlength && i < limit; i++) {
 		u16 c = src[i];
 
-		if (c > 0x800) {
+		if (c >= 0x800) {
 			if (maxlength < 3)
 				break;
 			maxlength -= 3;
 			dest[j++] = 0xe0 | (c & 0xf000) >> 12;
-			dest[j++] = 0x80 | (c & 0x0fc0) >> 8;
+			dest[j++] = 0x80 | (c & 0x0fc0) >> 6;
 			dest[j++] = 0x80 | (c & 0x003f);
-		} else if (c > 0x80) {
+		} else if (c >= 0x80) {
 			if (maxlength < 2)
 				break;
 			maxlength -= 2;
-			dest[j++] = 0xc0 | (c & 0xfe0) >> 5;
-			dest[j++] = 0x80 | (c & 0x01f);
+			dest[j++] = 0xc0 | (c & 0x7c0) >> 6;
+			dest[j++] = 0x80 | (c & 0x03f);
 		} else {
 			maxlength -= 1;
 			dest[j++] = c & 0x7f;
author maintainer
#17 lore raw

PATCH 18/19 modules: fix longstanding /proc/kallsyms vs module insertion race.

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

From: Rusty Russell <[email protected]>

commit 8244062ef1e54502ef55f54cced659913f244c3e upstream.

For CONFIG_KALLSYMS, we keep two symbol tables and two string tables. There's one full copy, marked SHF_ALLOC and laid out at the end of the module's init section. There's also a cut-down version that only contains core symbols and strings, and lives in the module's core section.

After module init (and before we free the module memory), we switch the mod->symtab, mod->num_symtab and mod->strtab to point to the core versions. We do this under the module_mutex.

However, kallsyms doesn't take the module_mutex: it uses preempt_disable() and rcu tricks to walk through the modules, because it's used in the oops path. It's also used in /proc/kallsyms. There's nothing atomic about the change of these variables, so we can get the old (larger!) num_symtab and the new symtab pointer; in fact this is what I saw when trying to reproduce.

By grouping these variables together, we can use a carefully-dereferenced pointer to ensure we always get one or the other (the free of the module init section is already done in an RCU callback, so that's safe). We allocate the init one at the end of the module init section, and keep the core one inside the struct module itself (it could also have been allocated at the end of the module core, but that's probably overkill).

[ Rebased for 4.4-stable and older, because the following changes aren't
in the older trees:
- e0224418516b4d8a6c2160574bac18447c354ef0: adds arg to is_core_symbol
- 7523e4dc5057e157212b4741abd6256e03404cf1: module_init/module_core/init_size/core_size become init_layout.base/core_layout.base/init_layout.size/core_layout.size.

Original commit: 8244062ef1e54502ef55f54cced659913f244c3e
]

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=111541

---
 include/linux/module.h |   17 +++----
 kernel/module.c        |  111 ++++++++++++++++++++++++++++++-------------------
 2 files changed, 78 insertions(+), 50 deletions(-)
include/linux/module.h +9 -8
@@ -227,6 +227,12 @@ struct module_ref {
 	unsigned long decs;
 } __attribute((aligned(2 * sizeof(unsigned long))));
 
+struct mod_kallsyms {
+	Elf_Sym *symtab;
+	unsigned int num_symtab;
+	char *strtab;
+};
+
 struct module {
 	enum module_state state;
 
@@ -314,14 +320,9 @@ struct module {
 #endif
 
 #ifdef CONFIG_KALLSYMS
-	/*
-	 * We keep the symbol and string tables for kallsyms.
-	 * The core_* fields below are temporary, loader-only (they
-	 * could really be discarded after module init).
-	 */
-	Elf_Sym *symtab, *core_symtab;
-	unsigned int num_symtab, core_num_syms;
-	char *strtab, *core_strtab;
+	/* Protected by RCU and/or module_mutex: use rcu_dereference() */
+	struct mod_kallsyms *kallsyms;
+	struct mod_kallsyms core_kallsyms;
 
 	/* Section attributes */
 	struct module_sect_attrs *sect_attrs;
kernel/module.c +69 -42

207 lines not on this page · raw message

author maintainer
#18 lore raw

PATCH 19/19 Revert: "crypto: af_alg - Disallow bind/setkey/... after accept(2)"

In reply to Greg Kroah-Hartman

3.14-stable review patch. If anyone has any objections, please let me know.

------------------

This reverts commit 06b4194533ff92ed5888840e3a6beaf29a8fe5d4 which is commit c840ac6af3f8713a71b4d2363419145760bd6044 upstream.

It's been widely reported that this patch breaks existing userspace applications when backported to the stable kernel releases. As no fix seems to be forthcoming, just revert it to let systems work again.

---
 crypto/af_alg.c         |   35 +++--------------------------------
 include/crypto/if_alg.h |    8 +++++---
 2 files changed, 8 insertions(+), 35 deletions(-)
crypto/af_alg.c +3 -32
@@ -125,23 +125,6 @@ int af_alg_release(struct socket *sock)
 }
 EXPORT_SYMBOL_GPL(af_alg_release);
 
-void af_alg_release_parent(struct sock *sk)
-{
-	struct alg_sock *ask = alg_sk(sk);
-	bool last;
-
-	sk = ask->parent;
-	ask = alg_sk(sk);
-
-	lock_sock(sk);
-	last = !--ask->refcnt;
-	release_sock(sk);
-
-	if (last)
-		sock_put(sk);
-}
-EXPORT_SYMBOL_GPL(af_alg_release_parent);
-
 static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk = sock->sk;
@@ -149,7 +132,6 @@ static int alg_bind(struct socket *sock,
 	struct sockaddr_alg *sa = (void *)uaddr;
 	const struct af_alg_type *type;
 	void *private;
-	int err;
 
 	if (sock->state == SS_CONNECTED)
 		return -EINVAL;
@@ -175,22 +157,16 @@ static int alg_bind(struct socket *sock,
 		return PTR_ERR(private);
 	}
 
-	err = -EBUSY;
 	lock_sock(sk);
-	if (ask->refcnt)
-		goto unlock;
 
 	swap(ask->type, type);
 	swap(ask->private, private);
 
-	err = 0;
-
-unlock:
 	release_sock(sk);
 
 	alg_do_release(type, private);
 
-	return err;
+	return 0;
 }
 
 static int alg_setkey(struct sock *sk, char __user *ukey,
@@ -223,15 +199,11 @@ static int alg_setsockopt(struct socket
 	struct sock *sk = sock->sk;
 	struct alg_sock *ask = alg_sk(sk);
 	const struct af_alg_type *type;
-	int err = -EBUSY;
+	int err = -ENOPROTOOPT;
 
 	lock_sock(sk);
-	if (ask->refcnt)
-		goto unlock;
-
 	type = ask->type;
 
-	err = -ENOPROTOOPT;
 	if (level != SOL_ALG || !type)
 		goto unlock;
 
@@ -280,8 +252,7 @@ int af_alg_accept(struct sock *sk, struc
 
 	sk2->sk_family = PF_ALG;
 
-	if (!ask->refcnt++)
-		sock_hold(sk);
+	sock_hold(sk);
 	alg_sk(sk2)->parent = sk;
 	alg_sk(sk2)->type = type;
 
include/crypto/if_alg.h +5 -3
@@ -30,8 +30,6 @@ struct alg_sock {
 
 	struct sock *parent;
 
-	unsigned int refcnt;
-
 	const struct af_alg_type *type;
 	void *private;
 };
@@ -66,7 +64,6 @@ int af_alg_register_type(const struct af
 int af_alg_unregister_type(const struct af_alg_type *type);
 
 int af_alg_release(struct socket *sock);
-void af_alg_release_parent(struct sock *sk);
 int af_alg_accept(struct sock *sk, struct socket *newsock);
 
 int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
@@ -83,6 +80,11 @@ static inline struct alg_sock *alg_sk(st
 	return (struct alg_sock *)sk;
 }
 
+static inline void af_alg_release_parent(struct sock *sk)
+{
+	sock_put(alg_sk(sk)->parent);
+}
+
 static inline void af_alg_init_completion(struct af_alg_completion *completion)
 {
 	init_completion(&completion->completion);
#19 lore raw
In reply to Greg Kroah-Hartman
Quoted 5 lines · Greg Kroah-Hartman

This is the start of the stable review cycle for the 3.14.65 release. There are 19 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Quoted 7 lines

Responses should be made by Wed Mar 16 17:50:23 UTC 2016. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v3.x/stable-review/patch-3.14.65-rc1.gz

and the diffstat can be found below.

Compiled and booted on my test system. No dmesg regressions,

thanks,
-- Shuah

Signature · 5 lines
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
[email protected] | (970) 217-8978
#20 lore raw
In reply to Greg Kroah-Hartman
Quoted 8 lines · Greg Kroah-Hartman

This is the start of the stable review cycle for the 3.14.65 release. There are 19 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Wed Mar 16 17:50:23 UTC 2016. Anything received after that time might be too late.

Build results:

	total: 128 pass: 128 fail: 0
Qemu test results:
	total: 83 pass: 83 fail: 0

Details are available at http://kerneltests.org/builders.

Guenter