Linux v3.8.3

This commit is contained in:
Justin M. Forbes 2013-03-14 16:03:05 -05:00
parent f330a83bcb
commit f7c0765d63
9 changed files with 7 additions and 1320 deletions

View File

@ -1,127 +0,0 @@
arch/arm/kernel/traps.c | 34 +++++++---------------------------
arch/arm/mm/alignment.c | 11 ++++-------
2 files changed, 11 insertions(+), 34 deletions(-)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index b0179b8..62f429e 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -89,17 +89,8 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
unsigned long top)
{
unsigned long first;
- mm_segment_t fs;
int i;
- /*
- * We need to switch to kernel mode so that we can use __get_user
- * to safely read from kernel space. Note that we now dump the
- * code first, just in case the backtrace kills us.
- */
- fs = get_fs();
- set_fs(KERNEL_DS);
-
printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top);
for (first = bottom & ~31; first < top; first += 32) {
@@ -112,7 +103,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
if (p >= bottom && p < top) {
unsigned long val;
- if (__get_user(val, (unsigned long *)p) == 0)
+ if (probe_kernel_address(p, val) == 0)
sprintf(str + i * 9, " %08lx", val);
else
sprintf(str + i * 9, " ????????");
@@ -120,8 +111,6 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
}
printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
}
-
- set_fs(fs);
}
static void dump_instr(const char *lvl, struct pt_regs *regs)
@@ -129,25 +118,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
unsigned long addr = instruction_pointer(regs);
const int thumb = thumb_mode(regs);
const int width = thumb ? 4 : 8;
- mm_segment_t fs;
char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
int i;
- /*
- * We need to switch to kernel mode so that we can use __get_user
- * to safely read from kernel space. Note that we now dump the
- * code first, just in case the backtrace kills us.
- */
- fs = get_fs();
- set_fs(KERNEL_DS);
-
for (i = -4; i < 1 + !!thumb; i++) {
unsigned int val, bad;
- if (thumb)
- bad = __get_user(val, &((u16 *)addr)[i]);
- else
- bad = __get_user(val, &((u32 *)addr)[i]);
+ if (thumb) {
+ u16 instr;
+ bad = probe_kernel_address(addr, instr);
+ val = instr;
+ } else
+ bad = probe_kernel_address(addr, val);
if (!bad)
p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
@@ -158,8 +140,6 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
}
}
printk("%sCode: %s\n", lvl, str);
-
- set_fs(fs);
}
#ifdef CONFIG_ARM_UNWIND
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index b9f60eb..f8f14fc 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -749,7 +749,6 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
unsigned long instr = 0, instrptr;
int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
unsigned int type;
- mm_segment_t fs;
unsigned int fault;
u16 tinstr = 0;
int isize = 4;
@@ -760,16 +759,15 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
instrptr = instruction_pointer(regs);
- fs = get_fs();
- set_fs(KERNEL_DS);
if (thumb_mode(regs)) {
- fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
+ unsigned long ptr = instrptr;
+ fault = probe_kernel_address(ptr, tinstr);
if (!fault) {
if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
IS_T32(tinstr)) {
/* Thumb-2 32-bit */
u16 tinst2 = 0;
- fault = __get_user(tinst2, (u16 *)(instrptr+2));
+ fault = probe_kernel_address(ptr + 2, tinst2);
instr = (tinstr << 16) | tinst2;
thumb2_32b = 1;
} else {
@@ -778,8 +776,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
}
}
} else
- fault = __get_user(instr, (u32 *)instrptr);
- set_fs(fs);
+ fault = probe_kernel_address(instrptr, instr);
if (fault) {
type = TYPE_FAULT;

View File

@ -1,223 +0,0 @@
From 9a5467bf7b6e9e02ec9c3da4e23747c05faeaac6 Mon Sep 17 00:00:00 2001
From: Mathias Krause <minipli@googlemail.com>
Date: Tue, 5 Feb 2013 18:19:13 +0100
Subject: [PATCH] crypto: user - fix info leaks in report API
Three errors resulting in kernel memory disclosure:
1/ The structures used for the netlink based crypto algorithm report API
are located on the stack. As snprintf() does not fill the remainder of
the buffer with null bytes, those stack bytes will be disclosed to users
of the API. Switch to strncpy() to fix this.
2/ crypto_report_one() does not initialize all field of struct
crypto_user_alg. Fix this to fix the heap info leak.
3/ For the module name we should copy only as many bytes as
module_name() returns -- not as much as the destination buffer could
hold. But the current code does not and therefore copies random data
from behind the end of the module name, as the module name is always
shorter than CRYPTO_MAX_ALG_NAME.
Also switch to use strncpy() to copy the algorithm's name and
driver_name. They are strings, after all.
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/ablkcipher.c | 12 ++++++------
crypto/aead.c | 9 ++++-----
crypto/ahash.c | 2 +-
crypto/blkcipher.c | 6 +++---
crypto/crypto_user.c | 22 +++++++++++-----------
crypto/pcompress.c | 3 +--
crypto/rng.c | 2 +-
crypto/shash.c | 3 ++-
8 files changed, 29 insertions(+), 30 deletions(-)
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 533de95..7d4a8d2 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -388,9 +388,9 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_blkcipher rblkcipher;
- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
- alg->cra_ablkcipher.geniv ?: "<default>");
+ strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type));
+ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "<default>",
+ sizeof(rblkcipher.geniv));
rblkcipher.blocksize = alg->cra_blocksize;
rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
@@ -469,9 +469,9 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_blkcipher rblkcipher;
- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
- alg->cra_ablkcipher.geniv ?: "<built-in>");
+ strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type));
+ strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "<built-in>",
+ sizeof(rblkcipher.geniv));
rblkcipher.blocksize = alg->cra_blocksize;
rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
diff --git a/crypto/aead.c b/crypto/aead.c
index 4d04e12..547491e 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -117,9 +117,8 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
struct crypto_report_aead raead;
struct aead_alg *aead = &alg->cra_aead;
- snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
- snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
- aead->geniv ?: "<built-in>");
+ strncpy(raead.type, "aead", sizeof(raead.type));
+ strncpy(raead.geniv, aead->geniv ?: "<built-in>", sizeof(raead.geniv));
raead.blocksize = alg->cra_blocksize;
raead.maxauthsize = aead->maxauthsize;
@@ -203,8 +202,8 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
struct crypto_report_aead raead;
struct aead_alg *aead = &alg->cra_aead;
- snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
- snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
+ strncpy(raead.type, "nivaead", sizeof(raead.type));
+ strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv));
raead.blocksize = alg->cra_blocksize;
raead.maxauthsize = aead->maxauthsize;
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 3887856..793a27f 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -404,7 +404,7 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_hash rhash;
- snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
+ strncpy(rhash.type, "ahash", sizeof(rhash.type));
rhash.blocksize = alg->cra_blocksize;
rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index e9e7244..a79e7e9 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -499,9 +499,9 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_blkcipher rblkcipher;
- snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
- snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
- alg->cra_blkcipher.geniv ?: "<default>");
+ strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type));
+ strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "<default>",
+ sizeof(rblkcipher.geniv));
rblkcipher.blocksize = alg->cra_blocksize;
rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 35d700a..f6d9baf 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -75,7 +75,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_cipher rcipher;
- snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
+ strncpy(rcipher.type, "cipher", sizeof(rcipher.type));
rcipher.blocksize = alg->cra_blocksize;
rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
@@ -94,8 +94,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_comp rcomp;
- snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
-
+ strncpy(rcomp.type, "compression", sizeof(rcomp.type));
if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
sizeof(struct crypto_report_comp), &rcomp))
goto nla_put_failure;
@@ -108,12 +107,14 @@ nla_put_failure:
static int crypto_report_one(struct crypto_alg *alg,
struct crypto_user_alg *ualg, struct sk_buff *skb)
{
- memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
- memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
- sizeof(ualg->cru_driver_name));
- memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
- CRYPTO_MAX_ALG_NAME);
-
+ strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
+ strncpy(ualg->cru_driver_name, alg->cra_driver_name,
+ sizeof(ualg->cru_driver_name));
+ strncpy(ualg->cru_module_name, module_name(alg->cra_module),
+ sizeof(ualg->cru_module_name));
+
+ ualg->cru_type = 0;
+ ualg->cru_mask = 0;
ualg->cru_flags = alg->cra_flags;
ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
@@ -122,8 +123,7 @@ static int crypto_report_one(struct crypto_alg *alg,
if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
struct crypto_report_larval rl;
- snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
-
+ strncpy(rl.type, "larval", sizeof(rl.type));
if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
sizeof(struct crypto_report_larval), &rl))
goto nla_put_failure;
diff --git a/crypto/pcompress.c b/crypto/pcompress.c
index 04e083f..7140fe7 100644
--- a/crypto/pcompress.c
+++ b/crypto/pcompress.c
@@ -53,8 +53,7 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_comp rpcomp;
- snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
-
+ strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type));
if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
sizeof(struct crypto_report_comp), &rpcomp))
goto nla_put_failure;
diff --git a/crypto/rng.c b/crypto/rng.c
index f3b7894..e0a25c2 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -65,7 +65,7 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_rng rrng;
- snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
+ strncpy(rrng.type, "rng", sizeof(rrng.type));
rrng.seedsize = alg->cra_rng.seedsize;
diff --git a/crypto/shash.c b/crypto/shash.c
index f426330f..929058a 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -530,7 +530,8 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
struct crypto_report_hash rhash;
struct shash_alg *salg = __crypto_shash_alg(alg);
- snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
+ strncpy(rhash.type, "shash", sizeof(rhash.type));
+
rhash.blocksize = alg->cra_blocksize;
rhash.digestsize = salg->digestsize;
--
1.8.1.2

View File

@ -1,47 +0,0 @@
From: Ben Hutchings <ben@decadent.org.uk>
Subject: dmi_scan: fix missing check for _DMI_ signature in smbios_present()
Commit 9f9c9cbb6057 ('drivers/firmware/dmi_scan.c: fetch dmi version from
SMBIOS if it exists') hoisted the check for "_DMI_" into
dmi_scan_machine(), which means that we don't bother to check for "_DMI_"
at offset 16 in an SMBIOS entry. smbios_present() may also call
dmi_present() for an address where we found "_SM_", if it failed further
validation.
Check for "_DMI_" in smbios_present() before calling dmi_present().
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Reported-by: Tim McGrath <tmhikaru@gmail.com>
Tested-by: Tim Mcgrath <tmhikaru@gmail.com>
Cc: Zhenzhong Duan <zhenzhong.duan@oracle.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/firmware/dmi_scan.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff -puN drivers/firmware/dmi_scan.c~dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present drivers/firmware/dmi_scan.c
--- a/drivers/firmware/dmi_scan.c~dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present
+++ a/drivers/firmware/dmi_scan.c
@@ -442,7 +442,6 @@ static int __init dmi_present(const char
static int __init smbios_present(const char __iomem *p)
{
u8 buf[32];
- int offset = 0;
memcpy_fromio(buf, p, 32);
if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
@@ -461,9 +460,9 @@ static int __init smbios_present(const c
dmi_ver = 0x0206;
break;
}
- offset = 16;
+ return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16);
}
- return dmi_present(buf + offset);
+ return 1;
}
void __init dmi_scan_machine(void)
_

View File

@ -1,736 +0,0 @@
From 27857f8a3240e35c61dedb88cbdbfbaabbd8ad2b Mon Sep 17 00:00:00 2001
From: Seiji Aguchi <seiji.aguchi@hds.com>
Date: Tue, 12 Feb 2013 12:59:07 -0800
Subject: [PATCH 1/4] efivars: Disable external interrupt while holding
efivars->lock
[Problem]
There is a scenario which efi_pstore fails to log messages in a panic case.
- CPUA holds an efi_var->lock in either efivarfs parts
or efi_pstore with interrupt enabled.
- CPUB panics and sends IPI to CPUA in smp_send_stop().
- CPUA stops with holding the lock.
- CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC)
but it returns without logging messages.
[Patch Description]
This patch disables an external interruption while holding efivars->lock
as follows.
In efi_pstore_write() and get_var_data(), spin_lock/spin_unlock is
replaced by spin_lock_irqsave/spin_unlock_irqrestore because they may
be called in an interrupt context.
In other functions, they are replaced by spin_lock_irq/spin_unlock_irq.
because they are all called from a process context.
By applying this patch, we can avoid the problem above with
a following senario.
- CPUA holds an efi_var->lock with interrupt disabled.
- CPUB panics and sends IPI to CPUA in smp_send_stop().
- CPUA receives the IPI after releasing the lock because it is
disabling interrupt while holding the lock.
- CPUB waits for one sec until CPUA releases the lock.
- CPUB kicks efi_pstore_write() via kmsg_dump(KSMG_DUMP_PANIC)
And it can hold the lock successfully.
Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
Acked-by: Mike Waychison <mikew@google.com>
Acked-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
drivers/firmware/efivars.c | 84 ++++++++++++++++++++++++----------------------
1 file changed, 43 insertions(+), 41 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index bcb201c..a9277cc 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -406,10 +406,11 @@ static efi_status_t
get_var_data(struct efivars *efivars, struct efi_variable *var)
{
efi_status_t status;
+ unsigned long flags;
- spin_lock(&efivars->lock);
+ spin_lock_irqsave(&efivars->lock, flags);
status = get_var_data_locked(efivars, var);
- spin_unlock(&efivars->lock);
+ spin_unlock_irqrestore(&efivars->lock, flags);
if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
@@ -538,14 +539,14 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
return -EINVAL;
}
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid,
new_var->Attributes,
new_var->DataSize,
new_var->Data);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
@@ -714,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file,
* amounts of memory. Pick a default size of 64K if
* QueryVariableInfo() isn't supported by the firmware.
*/
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
if (!efivars->ops->query_variable_info)
status = EFI_UNSUPPORTED;
@@ -724,7 +725,7 @@ static ssize_t efivarfs_file_write(struct file *file,
&remaining_size, &max_size);
}
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
if (status != EFI_SUCCESS) {
if (status != EFI_UNSUPPORTED)
@@ -755,7 +756,7 @@ static ssize_t efivarfs_file_write(struct file *file,
* set_variable call, and removal of the variable from the efivars
* list (in the case of an authenticated delete).
*/
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
status = efivars->ops->set_variable(var->var.VariableName,
&var->var.VendorGuid,
@@ -763,7 +764,7 @@ static ssize_t efivarfs_file_write(struct file *file,
data);
if (status != EFI_SUCCESS) {
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
kfree(data);
return efi_status_to_err(status);
@@ -784,21 +785,21 @@ static ssize_t efivarfs_file_write(struct file *file,
NULL);
if (status == EFI_BUFFER_TOO_SMALL) {
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
mutex_lock(&inode->i_mutex);
i_size_write(inode, newdatasize + sizeof(attributes));
mutex_unlock(&inode->i_mutex);
} else if (status == EFI_NOT_FOUND) {
list_del(&var->list);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
efivar_unregister(var);
drop_nlink(inode);
d_delete(file->f_dentry);
dput(file->f_dentry);
} else {
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
pr_warn("efivarfs: inconsistent EFI variable implementation? "
"status = %lx\n", status);
}
@@ -820,11 +821,11 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
void *data;
ssize_t size = 0;
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
status = efivars->ops->get_variable(var->var.VariableName,
&var->var.VendorGuid,
&attributes, &datasize, NULL);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
if (status != EFI_BUFFER_TOO_SMALL)
return efi_status_to_err(status);
@@ -834,12 +835,12 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
if (!data)
return -ENOMEM;
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
status = efivars->ops->get_variable(var->var.VariableName,
&var->var.VendorGuid,
&attributes, &datasize,
(data + sizeof(attributes)));
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
if (status != EFI_SUCCESS) {
size = efi_status_to_err(status);
@@ -1005,9 +1006,9 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
goto out;
kobject_uevent(&var->kobj, KOBJ_ADD);
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
list_add(&var->list, &efivars->list);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
d_instantiate(dentry, inode);
dget(dentry);
out:
@@ -1024,7 +1025,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
struct efivars *efivars = var->efivars;
efi_status_t status;
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
status = efivars->ops->set_variable(var->var.VariableName,
&var->var.VendorGuid,
@@ -1032,14 +1033,14 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
if (status == EFI_SUCCESS || status == EFI_NOT_FOUND) {
list_del(&var->list);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
efivar_unregister(var);
drop_nlink(dentry->d_inode);
dput(dentry);
return 0;
}
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
return -EINVAL;
};
@@ -1184,13 +1185,13 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
/* copied by the above to local storage in the dentry. */
kfree(name);
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
efivars->ops->get_variable(entry->var.VariableName,
&entry->var.VendorGuid,
&entry->var.Attributes,
&size,
NULL);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
mutex_lock(&inode->i_mutex);
inode->i_private = entry;
@@ -1253,7 +1254,7 @@ static int efi_pstore_open(struct pstore_info *psi)
{
struct efivars *efivars = psi->data;
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
efivars->walk_entry = list_first_entry(&efivars->list,
struct efivar_entry, list);
return 0;
@@ -1263,7 +1264,7 @@ static int efi_pstore_close(struct pstore_info *psi)
{
struct efivars *efivars = psi->data;
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
return 0;
}
@@ -1339,8 +1340,9 @@ static int efi_pstore_write(enum pstore_type_id type,
int i, ret = 0;
u64 storage_space, remaining_space, max_variable_size;
efi_status_t status = EFI_NOT_FOUND;
+ unsigned long flags;
- spin_lock(&efivars->lock);
+ spin_lock_irqsave(&efivars->lock, flags);
/*
* Check if there is a space enough to log.
@@ -1352,7 +1354,7 @@ static int efi_pstore_write(enum pstore_type_id type,
&remaining_space,
&max_variable_size);
if (status || remaining_space < size + DUMP_NAME_LEN * 2) {
- spin_unlock(&efivars->lock);
+ spin_unlock_irqrestore(&efivars->lock, flags);
*id = part;
return -ENOSPC;
}
@@ -1366,7 +1368,7 @@ static int efi_pstore_write(enum pstore_type_id type,
efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
size, psi->buf);
- spin_unlock(&efivars->lock);
+ spin_unlock_irqrestore(&efivars->lock, flags);
if (size)
ret = efivar_create_sysfs_entry(efivars,
@@ -1393,7 +1395,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
time.tv_sec);
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name[i] = name[i];
@@ -1437,7 +1439,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
if (found)
list_del(&found->list);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
if (found)
efivar_unregister(found);
@@ -1507,7 +1509,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
return -EINVAL;
}
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
/*
* Does this variable already exist?
@@ -1525,7 +1527,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
}
}
if (found) {
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
return -EINVAL;
}
@@ -1539,10 +1541,10 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
status);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
return -EIO;
}
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
/* Create the entry in sysfs. Locking is not required here */
status = efivar_create_sysfs_entry(efivars,
@@ -1570,7 +1572,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
/*
* Does this variable already exist?
@@ -1588,7 +1590,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
}
}
if (!found) {
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
return -EINVAL;
}
/* force the Attributes/DataSize to 0 to ensure deletion */
@@ -1604,12 +1606,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
status);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
return -EIO;
}
list_del(&search_efivar->list);
/* We need to release this lock before unregistering. */
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
efivar_unregister(search_efivar);
/* It's dead Jim.... */
@@ -1724,9 +1726,9 @@ efivar_create_sysfs_entry(struct efivars *efivars,
kfree(short_name);
short_name = NULL;
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
list_add(&new_efivar->list, &efivars->list);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
return 0;
}
@@ -1795,9 +1797,9 @@ void unregister_efivars(struct efivars *efivars)
struct efivar_entry *entry, *n;
list_for_each_entry_safe(entry, n, &efivars->list, list) {
- spin_lock(&efivars->lock);
+ spin_lock_irq(&efivars->lock);
list_del(&entry->list);
- spin_unlock(&efivars->lock);
+ spin_unlock_irq(&efivars->lock);
efivar_unregister(entry);
}
if (efivars->new_var)
--
1.8.1.2
From 19adc04301476eaa15e035b66e92cb333223c352 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Sat, 2 Mar 2013 19:40:17 -0500
Subject: [PATCH 2/4] efi: be more paranoid about available space when creating
variables
UEFI variables are typically stored in flash. For various reasons, avaiable
space is typically not reclaimed immediately upon the deletion of a
variable - instead, the system will garbage collect during initialisation
after a reboot.
Some systems appear to handle this garbage collection extremely poorly,
failing if more than 50% of the system flash is in use. This can result in
the machine refusing to boot. The safest thing to do for the moment is to
forbid writes if they'd end up using more than half of the storage space.
We can make this more finegrained later if we come up with a method for
identifying the broken machines.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
---
drivers/firmware/efivars.c | 106 +++++++++++++++++++++++++++++++++------------
1 file changed, 79 insertions(+), 27 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index a9277cc..919862b 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -419,6 +419,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var)
return status;
}
+static efi_status_t
+check_var_size_locked(struct efivars *efivars, u32 attributes,
+ unsigned long size)
+{
+ u64 storage_size, remaining_size, max_size;
+ efi_status_t status;
+ const struct efivar_operations *fops = efivars->ops;
+
+ if (!efivars->ops->query_variable_info)
+ return EFI_UNSUPPORTED;
+
+ status = fops->query_variable_info(attributes, &storage_size,
+ &remaining_size, &max_size);
+
+ if (status != EFI_SUCCESS)
+ return status;
+
+ if (!storage_size || size > remaining_size || size > max_size ||
+ (remaining_size - size) < (storage_size / 2))
+ return EFI_OUT_OF_RESOURCES;
+
+ return status;
+}
+
+
+static efi_status_t
+check_var_size(struct efivars *efivars, u32 attributes, unsigned long size)
+{
+ efi_status_t status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&efivars->lock, flags);
+ status = check_var_size_locked(efivars, attributes, size);
+ spin_unlock_irqrestore(&efivars->lock, flags);
+
+ return status;
+}
+
static ssize_t
efivar_guid_read(struct efivar_entry *entry, char *buf)
{
@@ -540,11 +578,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
}
spin_lock_irq(&efivars->lock);
- status = efivars->ops->set_variable(new_var->VariableName,
- &new_var->VendorGuid,
- new_var->Attributes,
- new_var->DataSize,
- new_var->Data);
+
+ status = check_var_size_locked(efivars, new_var->Attributes,
+ new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+
+ if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
+ status = efivars->ops->set_variable(new_var->VariableName,
+ &new_var->VendorGuid,
+ new_var->Attributes,
+ new_var->DataSize,
+ new_var->Data);
spin_unlock_irq(&efivars->lock);
@@ -695,8 +738,7 @@ static ssize_t efivarfs_file_write(struct file *file,
u32 attributes;
struct inode *inode = file->f_mapping->host;
unsigned long datasize = count - sizeof(attributes);
- unsigned long newdatasize;
- u64 storage_size, remaining_size, max_size;
+ unsigned long newdatasize, varsize;
ssize_t bytes = 0;
if (count < sizeof(attributes))
@@ -715,28 +757,18 @@ static ssize_t efivarfs_file_write(struct file *file,
* amounts of memory. Pick a default size of 64K if
* QueryVariableInfo() isn't supported by the firmware.
*/
- spin_lock_irq(&efivars->lock);
- if (!efivars->ops->query_variable_info)
- status = EFI_UNSUPPORTED;
- else {
- const struct efivar_operations *fops = efivars->ops;
- status = fops->query_variable_info(attributes, &storage_size,
- &remaining_size, &max_size);
- }
-
- spin_unlock_irq(&efivars->lock);
+ varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
+ status = check_var_size(efivars, attributes, varsize);
if (status != EFI_SUCCESS) {
if (status != EFI_UNSUPPORTED)
return efi_status_to_err(status);
- remaining_size = 65536;
+ if (datasize > 65536)
+ return -ENOSPC;
}
- if (datasize > remaining_size)
- return -ENOSPC;
-
data = kmalloc(datasize, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -758,6 +790,19 @@ static ssize_t efivarfs_file_write(struct file *file,
*/
spin_lock_irq(&efivars->lock);
+ /*
+ * Ensure that the available space hasn't shrunk below the safe level
+ */
+
+ status = check_var_size_locked(efivars, attributes, varsize);
+
+ if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
+ spin_unlock_irq(&efivars->lock);
+ kfree(data);
+
+ return efi_status_to_err(status);
+ }
+
status = efivars->ops->set_variable(var->var.VariableName,
&var->var.VendorGuid,
attributes, datasize,
@@ -1338,7 +1383,6 @@ static int efi_pstore_write(enum pstore_type_id type,
efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
struct efivars *efivars = psi->data;
int i, ret = 0;
- u64 storage_space, remaining_space, max_variable_size;
efi_status_t status = EFI_NOT_FOUND;
unsigned long flags;
@@ -1349,11 +1393,11 @@ static int efi_pstore_write(enum pstore_type_id type,
* size: a size of logging data
* DUMP_NAME_LEN * 2: a maximum size of variable name
*/
- status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES,
- &storage_space,
- &remaining_space,
- &max_variable_size);
- if (status || remaining_space < size + DUMP_NAME_LEN * 2) {
+
+ status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES,
+ size + DUMP_NAME_LEN * 2);
+
+ if (status) {
spin_unlock_irqrestore(&efivars->lock, flags);
*id = part;
return -ENOSPC;
@@ -1531,6 +1575,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
return -EINVAL;
}
+ status = check_var_size_locked(efivars, new_var->Attributes,
+ new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+
+ if (status && status != EFI_UNSUPPORTED) {
+ spin_unlock_irq(&efivars->lock);
+ return efi_status_to_err(status);
+ }
+
/* now *really* create the variable via EFI */
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid,
--
1.8.1.2
From 46b6e1db3a81203deaf4615637616a0266a2e6e6 Mon Sep 17 00:00:00 2001
From: Matt Fleming <matt.fleming@intel.com>
Date: Tue, 5 Mar 2013 07:40:16 +0000
Subject: [PATCH 3/4] efivars: efivarfs_valid_name() should handle pstore
syntax
Stricter validation was introduced with commit da27a24383b2b
("efivarfs: guid part of filenames are case-insensitive") and commit
47f531e8ba3b ("efivarfs: Validate filenames much more aggressively"),
which is necessary for the guid portion of efivarfs filenames, but we
don't need to be so strict with the first part, the variable name. The
UEFI specification doesn't impose any constraints on variable names
other than they be a NULL-terminated string.
The above commits caused a regression that resulted in users seeing
the following message,
$ sudo mount -v /sys/firmware/efi/efivars mount: Cannot allocate memory
whenever pstore EFI variables were present in the variable store,
since their variable names failed to pass the following check,
/* GUID should be right after the first '-' */
if (s - 1 != strchr(str, '-'))
as a typical pstore filename is of the form, dump-type0-10-1-<guid>.
The fix is trivial since the guid portion of the filename is GUID_LEN
bytes, we can use (len - GUID_LEN) to ensure the '-' character is
where we expect it to be.
(The bogus ENOMEM error value will be fixed in a separate patch.)
Reported-by: Joseph Yasi <joe.yasi@gmail.com>
Reported-by: Lingzhu Xiang <lxiang@redhat.com>
Cc: Josh Boyer <jwboyer@redhat.com>
Cc: Jeremy Kerr <jk@ozlabs.org>
Cc: Matthew Garrett <mjg59@srcf.ucam.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
---
drivers/firmware/efivars.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 919862b..fc54ddd 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -967,8 +967,8 @@ static bool efivarfs_valid_name(const char *str, int len)
if (len < GUID_LEN + 2)
return false;
- /* GUID should be right after the first '-' */
- if (s - 1 != strchr(str, '-'))
+ /* GUID must be preceded by a '-' */
+ if (*(s - 1) != '-')
return false;
/*
--
1.8.1.2
From f751b6c973fe5a480ff12c97df4b8ac4e9a666a7 Mon Sep 17 00:00:00 2001
From: Matt Fleming <matt.fleming@intel.com>
Date: Tue, 5 Mar 2013 12:46:30 +0000
Subject: [PATCH 4/4] efivarfs: return accurate error code in
efivarfs_fill_super()
Joseph was hitting a failure case when mounting efivarfs which
resulted in an incorrect error message,
$ sudo mount -v /sys/firmware/efi/efivars mount: Cannot allocate memory
triggered when efivarfs_valid_name() returned -EINVAL.
Make sure we pass accurate return values up the stack if
efivarfs_fill_super() fails to build inodes for EFI variables.
Reported-by: Joseph Yasi <joe.yasi@gmail.com>
Reported-by: Lingzhu Xiang <lxiang@redhat.com>
Cc: Josh Boyer <jwboyer@redhat.com>
Cc: Jeremy Kerr <jk@ozlabs.org>
Cc: Matthew Garrett <mjg59@srcf.ucam.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
---
drivers/firmware/efivars.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index fc54ddd..2a2e145 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -1156,15 +1156,22 @@ static struct dentry_operations efivarfs_d_ops = {
static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
{
+ struct dentry *d;
struct qstr q;
+ int err;
q.name = name;
q.len = strlen(name);
- if (efivarfs_d_hash(NULL, NULL, &q))
- return NULL;
+ err = efivarfs_d_hash(NULL, NULL, &q);
+ if (err)
+ return ERR_PTR(err);
+
+ d = d_alloc(parent, &q);
+ if (d)
+ return d;
- return d_alloc(parent, &q);
+ return ERR_PTR(-ENOMEM);
}
static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -1174,6 +1181,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
struct efivar_entry *entry, *n;
struct efivars *efivars = &__efivars;
char *name;
+ int err = -ENOMEM;
efivarfs_sb = sb;
@@ -1224,8 +1232,10 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
goto fail_name;
dentry = efivarfs_alloc_dentry(root, name);
- if (!dentry)
+ if (IS_ERR(dentry)) {
+ err = PTR_ERR(dentry);
goto fail_inode;
+ }
/* copied by the above to local storage in the dentry. */
kfree(name);
@@ -1252,7 +1262,7 @@ fail_inode:
fail_name:
kfree(name);
fail:
- return -ENOMEM;
+ return err;
}
static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
--
1.8.1.2

View File

@ -62,7 +62,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
%global baserelease 210
%global baserelease 201
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@ -74,7 +74,7 @@ Summary: The Linux kernel
%if 0%{?released_kernel}
# Do we have a -stable update to apply?
%define stable_update 2
%define stable_update 3
# Is it a -stable RC?
%define stable_rc 0
# Set rpm version accordingly
@ -95,7 +95,7 @@ Summary: The Linux kernel
# The rc snapshot level
%define rcrev 0
# The git snapshot level
%define gitrev 0
%define gitrev 100
# Set rpm version accordingly
%define rpmversion 3.%{upstream_sublevel}.0
%endif
@ -718,8 +718,6 @@ Patch20000: 0001-efifb-Skip-DMI-checks-if-the-bootloader-knows-what-i.patch
Patch20001: 0002-x86-EFI-Calculate-the-EFI-framebuffer-size-instead-o.patch
# ARM
# http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/137164.html
Patch21002: arm-alignment-faults.patch
# ARM tegra
Patch21004: arm-tegra-nvec-kconfig.patch
@ -756,21 +754,6 @@ Patch22262: x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch
#rhbz 916544
Patch22263: 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch
#rhbz 917984
Patch22264: efi-fixes-3.8.patch
#rhbz 918512 918521
Patch22265: crypto-user-fix-info-leaks-in-report-API.patch
# CVE-2013-1792 rhbz 916646,919021
Patch22266: keys-fix-race-with-concurrent-install_user_keyrings.patch
#rhbz 840391
Patch22267: logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch
#rhbz 916444
Patch22268: dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch
#CVE-2013-1828 rhbz 919315 919316
Patch22269: net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch
@ -804,7 +787,6 @@ Patch24108: signal-always-clear-sa_restorer-on-execve.patch
Patch24109: drm-i915-bounds-check-execbuffer-relocation-count.patch
#rhbz 856863 892599
Patch24110: mac80211-Fix-crash-due-to-un-canceled-work-items.patch
Patch24111: cfg80211-mac80211-disconnect-on-suspend.patch
Patch24112: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch
@ -1380,7 +1362,6 @@ ApplyPatch vmbugon-warnon.patch
#ApplyPatch arm-tegra-nvec-kconfig.patch
ApplyPatch arm-tegra-usb-no-reset-linux33.patch
#ApplyPatch arm-tegra-sdhci-module-fix.patch
ApplyPatch arm-alignment-faults.patch
#
# bugfixes to drivers and filesystems
@ -1522,26 +1503,11 @@ ApplyPatch x86-mm-Fix-vmalloc_fault-oops-during-lazy-MMU-updates.patch
#rhbz 916544
ApplyPatch 0001-drivers-crypto-nx-fix-init-race-alignmasks-and-GCM-b.patch
#rhbz 917984
ApplyPatch efi-fixes-3.8.patch
#rhbz 918512 918521
ApplyPatch crypto-user-fix-info-leaks-in-report-API.patch
ApplyPatch userns-avoid-recursion-in-put_user_ns.patch
#rhbz 859346
ApplyPatch fix-destroy_conntrack-GPF.patch
# CVE-2013-1792 rhbz 916646,919021
ApplyPatch keys-fix-race-with-concurrent-install_user_keyrings.patch
#rhbz 840391
ApplyPatch logitech-dj-do-not-directly-call-hid_output_raw_report-during-probe.patch
#rhbz 916444
ApplyPatch dmi_scan-fix-missing-check-for-_dmi_-signature-in-smbios_present.patch
#CVE-2013-1828 rhbz 919315 919316
ApplyPatch net-sctp-Validate-parameter-size-for-SCTP_GET_ASSOC_.patch
@ -1576,7 +1542,6 @@ ApplyPatch signal-always-clear-sa_restorer-on-execve.patch
ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch
#rhbz 856863 892599
ApplyPatch mac80211-Fix-crash-due-to-un-canceled-work-items.patch
ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch
ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.8.patch
@ -2440,6 +2405,9 @@ fi
# ||----w |
# || ||
%changelog
* Thu Mar 14 2013 Justin M. Forbes <jforbes@redhat.com> 3.8.3-201
- Linux v3.8.3
* Thu Mar 14 2013 Josh Boyer <jwboyer@redhat.com>
- Fix divide by zero on host TSC calibration failure (rhbz 859282)

View File

@ -1,15 +0,0 @@
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 58dfe08..c5ec083 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -57,7 +57,7 @@ int install_user_keyrings(void)
kenter("%p{%u}", user, uid);
- if (user->uid_keyring) {
+ if (user->uid_keyring && user->session_keyring) {
kleave(" = 0 [exist]");
return 0;
}

View File

@ -1,66 +0,0 @@
From dcd9006b1b053c7b1cebe81333261d4fd492ffeb Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Tue, 05 Mar 2013 16:09:00 +0000
Subject: HID: logitech-dj: do not directly call hid_output_raw_report() during probe
hid_output_raw_report() makes a direct call to usb_control_msg(). However,
some USB3 boards have shown that the usb device is not ready during the
.probe(). This blocks the entire usb device, and the paired mice, keyboards
are not functional. The dmesg output is the following:
[ 11.912287] logitech-djreceiver 0003:046D:C52B.0003: hiddev0,hidraw0: USB HID v1.11 Device [Logitech USB Receiver] on usb-0000:00:14.0-2/input2
[ 11.912537] logitech-djreceiver 0003:046D:C52B.0003: logi_dj_probe:logi_dj_recv_query_paired_devices error:-32
[ 11.912636] logitech-djreceiver: probe of 0003:046D:C52B.0003 failed with error -32
Relying on the scheduled call to usbhid_submit_report() fixes the problem.
related bugs:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1072082
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1039143
https://bugzilla.redhat.com/show_bug.cgi?id=840391
https://bugzilla.kernel.org/show_bug.cgi?id=49781
Reported-and-tested-by: Bob Bowles <bobjohnbowles@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 9500f2f..8758f38c 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -459,19 +459,25 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
struct dj_report *dj_report)
{
struct hid_device *hdev = djrcv_dev->hdev;
- int sent_bytes;
+ struct hid_report *report;
+ struct hid_report_enum *output_report_enum;
+ u8 *data = (u8 *)(&dj_report->device_index);
+ int i;
- if (!hdev->hid_output_raw_report) {
- dev_err(&hdev->dev, "%s:"
- "hid_output_raw_report is null\n", __func__);
+ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
+ report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+
+ if (!report) {
+ dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__);
return -ENODEV;
}
- sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
- sizeof(struct dj_report),
- HID_OUTPUT_REPORT);
+ for (i = 0; i < report->field[0]->report_count; i++)
+ report->field[0]->value[i] = data[i];
+
+ usbhid_submit_report(hdev, report, USB_DIR_OUT);
- return (sent_bytes < 0) ? sent_bytes : 0;
+ return 0;
}
static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
--
cgit v0.9.1

View File

@ -1,67 +0,0 @@
From 499218595a2e8296b7492af32fcca141b7b8184a Mon Sep 17 00:00:00 2001
From: Ben Greear <greearb@candelatech.com>
Date: Wed, 20 Feb 2013 09:41:09 -0800
Subject: [PATCH] mac80211: Fix crash due to un-canceled work-items
Some mlme work structs are not cancelled on disassociation
nor interface deletion, which leads to them running after
the memory has been freed
There is not a clean way to cancel these in the disassociation
logic because they must be canceled outside of the ifmgd->mtx
lock, so just cancel them in mgd_stop logic that tears down
the station.
This fixes the crashes we see in 3.7.9+. The crash stack
trace itself isn't so helpful, but this warning gives
more useful info:
WARNING: at /home/greearb/git/linux-3.7.dev.y/lib/debugobjects.c:261 debug_print_object+0x7c/0x8d()
ODEBUG: free active (active state 0) object type: work_struct hint: ieee80211_sta_monitor_work+0x0/0x14 [mac80211]
Modules linked in: [...]
Pid: 14743, comm: iw Tainted: G C O 3.7.9+ #11
Call Trace:
[<ffffffff81087ef8>] warn_slowpath_common+0x80/0x98
[<ffffffff81087fa4>] warn_slowpath_fmt+0x41/0x43
[<ffffffff812a2608>] debug_print_object+0x7c/0x8d
[<ffffffff812a2bca>] debug_check_no_obj_freed+0x95/0x1c3
[<ffffffff8114cc69>] slab_free_hook+0x70/0x79
[<ffffffff8114ea3e>] kfree+0x62/0xb7
[<ffffffff8149f465>] netdev_release+0x39/0x3e
[<ffffffff8136ad67>] device_release+0x52/0x8a
[<ffffffff812937db>] kobject_release+0x121/0x158
[<ffffffff81293612>] kobject_put+0x4c/0x50
[<ffffffff8148f0d7>] netdev_run_todo+0x25c/0x27e
Cc: stable@vger.kernel.org
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/mlme.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6044c6d..b756d29 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4319,6 +4319,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ /*
+ * Make sure some work items will not run after this,
+ * they will not do anything but might not have been
+ * cancelled when disconnecting.
+ */
+ cancel_work_sync(&ifmgd->monitor_work);
+ cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+ cancel_work_sync(&ifmgd->request_smps_work);
+ cancel_work_sync(&ifmgd->csa_connection_drop_work);
+ cancel_work_sync(&ifmgd->chswitch_work);
+
mutex_lock(&ifmgd->mtx);
if (ifmgd->assoc_data)
ieee80211_destroy_assoc_data(sdata, false);
--
1.8.1.2

View File

@ -1,2 +1,2 @@
1c738edfc54e7c65faeb90c436104e2f linux-3.8.tar.xz
e282fcff76e975e121e0636018e31a56 patch-3.8.2.xz
ba18b5d27ed303f5e5a9cda32a451031 patch-3.8.3.xz