From: Greg Kroah-Hartman Date: Sat, 18 Sep 2010 17:50:47 +0000 (-0700) Subject: .32 patches X-Git-Tag: v2.6.27.54~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6796b2287b90d914920b6cc4b4c4cf6e5f9d7f93;p=thirdparty%2Fkernel%2Fstable-queue.git .32 patches --- diff --git a/queue-2.6.32/apm_power-add-missing-break-statement.patch b/queue-2.6.32/apm_power-add-missing-break-statement.patch new file mode 100644 index 00000000000..0ff6f973787 --- /dev/null +++ b/queue-2.6.32/apm_power-add-missing-break-statement.patch @@ -0,0 +1,30 @@ +From 1d220334d6a8a711149234dc5f98d34ae02226b8 Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov +Date: Wed, 8 Sep 2010 00:10:26 +0400 +Subject: apm_power: Add missing break statement + +From: Anton Vorontsov + +commit 1d220334d6a8a711149234dc5f98d34ae02226b8 upstream. + +The missing break statement causes wrong capacity calculation for +batteries that report energy. + +Reported-by: d binderman +Signed-off-by: Anton Vorontsov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/power/apm_power.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/power/apm_power.c ++++ b/drivers/power/apm_power.c +@@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_s + empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; + now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; + avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; ++ break; + case SOURCE_VOLTAGE: + full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; + empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; diff --git a/queue-2.6.32/arm-fix-really-nasty-sigreturn-bug.patch b/queue-2.6.32/arm-fix-really-nasty-sigreturn-bug.patch new file mode 100644 index 00000000000..6a95ffa415b --- /dev/null +++ b/queue-2.6.32/arm-fix-really-nasty-sigreturn-bug.patch @@ -0,0 +1,95 @@ +From 653d48b22166db2d8b1515ebe6f9f0f7c95dfc86 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 17 Sep 2010 14:34:39 +0100 +Subject: arm: fix really nasty sigreturn bug + +From: Al Viro + +commit 653d48b22166db2d8b1515ebe6f9f0f7c95dfc86 upstream. + +If a signal hits us outside of a syscall and another gets delivered +when we are in sigreturn (e.g. because it had been in sa_mask for +the first one and got sent to us while we'd been in the first handler), +we have a chance of returning from the second handler to location one +insn prior to where we ought to return. If r0 happens to contain -513 +(-ERESTARTNOINTR), sigreturn will get confused into doing restart +syscall song and dance. + +Incredible joy to debug, since it manifests as random, infrequent and +very hard to reproduce double execution of instructions in userland +code... + +The fix is simple - mark it "don't bother with restarts" in wrapper, +i.e. set r8 to 0 in sys_sigreturn and sys_rt_sigreturn wrappers, +suppressing the syscall restart handling on return from these guys. +They can't legitimately return a restart-worthy error anyway. + +Testcase: + #include + #include + #include + #include + #include + + void f(int n) + { + __asm__ __volatile__( + "ldr r0, [%0]\n" + "b 1f\n" + "b 2f\n" + "1:b .\n" + "2:\n" : : "r"(&n)); + } + + void handler1(int sig) { } + void handler2(int sig) { raise(1); } + void handler3(int sig) { exit(0); } + + main() + { + struct sigaction s = {.sa_handler = handler2}; + struct itimerval t1 = { .it_value = {1} }; + struct itimerval t2 = { .it_value = {2} }; + + signal(1, handler1); + + sigemptyset(&s.sa_mask); + sigaddset(&s.sa_mask, 1); + sigaction(SIGALRM, &s, NULL); + + signal(SIGVTALRM, handler3); + + setitimer(ITIMER_REAL, &t1, NULL); + setitimer(ITIMER_VIRTUAL, &t2, NULL); + + f(-513); /* -ERESTARTNOINTR */ + + write(1, "buggered\n", 9); + return 1; + } + +Signed-off-by: Al Viro +Acked-by: Russell King +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/kernel/entry-common.S | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -382,11 +382,13 @@ ENDPROC(sys_clone_wrapper) + + sys_sigreturn_wrapper: + add r0, sp, #S_OFF ++ mov why, #0 @ prevent syscall restart handling + b sys_sigreturn + ENDPROC(sys_sigreturn_wrapper) + + sys_rt_sigreturn_wrapper: + add r0, sp, #S_OFF ++ mov why, #0 @ prevent syscall restart handling + b sys_rt_sigreturn + ENDPROC(sys_rt_sigreturn_wrapper) + diff --git a/queue-2.6.32/hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch b/queue-2.6.32/hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch new file mode 100644 index 00000000000..2161d5cea3a --- /dev/null +++ b/queue-2.6.32/hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch @@ -0,0 +1,42 @@ +From c3b327d60bbba3f5ff8fd87d1efc0e95eb6c121b Mon Sep 17 00:00:00 2001 +From: Guillem Jover +Date: Fri, 17 Sep 2010 17:24:12 +0200 +Subject: hwmon: (f75375s) Do not overwrite values read from registers + +From: Guillem Jover + +commit c3b327d60bbba3f5ff8fd87d1efc0e95eb6c121b upstream. + +All bits in the values read from registers to be used for the next +write were getting overwritten, avoid doing so to not mess with the +current configuration. + +Signed-off-by: Guillem Jover +Cc: Riku Voipio +Signed-off-by: Jean Delvare +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/f75375s.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/f75375s.c ++++ b/drivers/hwmon/f75375s.c +@@ -298,7 +298,7 @@ static int set_pwm_enable_direct(struct + return -EINVAL; + + fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); +- fanmode = ~(3 << FAN_CTRL_MODE(nr)); ++ fanmode &= ~(3 << FAN_CTRL_MODE(nr)); + + switch (val) { + case 0: /* Full speed */ +@@ -350,7 +350,7 @@ static ssize_t set_pwm_mode(struct devic + + mutex_lock(&data->update_lock); + conf = f75375_read8(client, F75375_REG_CONFIG1); +- conf = ~(1 << FAN_CTRL_LINEAR(nr)); ++ conf &= ~(1 << FAN_CTRL_LINEAR(nr)); + + if (val == 0) + conf |= (1 << FAN_CTRL_LINEAR(nr)) ; diff --git a/queue-2.6.32/hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch b/queue-2.6.32/hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch new file mode 100644 index 00000000000..f8cb520bd77 --- /dev/null +++ b/queue-2.6.32/hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch @@ -0,0 +1,33 @@ +From 96f3640894012be7dd15a384566bfdc18297bc6c Mon Sep 17 00:00:00 2001 +From: Guillem Jover +Date: Fri, 17 Sep 2010 17:24:11 +0200 +Subject: hwmon: (f75375s) Shift control mode to the correct bit position + +From: Guillem Jover + +commit 96f3640894012be7dd15a384566bfdc18297bc6c upstream. + +The spec notes that fan0 and fan1 control mode bits are located in bits +7-6 and 5-4 respectively, but the FAN_CTRL_MODE macro was making the +bits shift by 5 instead of by 4. + +Signed-off-by: Guillem Jover +Cc: Riku Voipio +Signed-off-by: Jean Delvare +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/f75375s.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hwmon/f75375s.c ++++ b/drivers/hwmon/f75375s.c +@@ -79,7 +79,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); + #define F75375_REG_PWM2_DROP_DUTY 0x6C + + #define FAN_CTRL_LINEAR(nr) (4 + nr) +-#define FAN_CTRL_MODE(nr) (5 + ((nr) * 2)) ++#define FAN_CTRL_MODE(nr) (4 + ((nr) * 2)) + + /* + * Data structures and manipulation thereof diff --git a/queue-2.6.32/nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch b/queue-2.6.32/nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch new file mode 100644 index 00000000000..8bbdc3a1341 --- /dev/null +++ b/queue-2.6.32/nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch @@ -0,0 +1,28 @@ +From b20d37ca9561711c6a3c4b859c2855f49565e061 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Sun, 12 Sep 2010 19:55:26 -0400 +Subject: NFS: Fix a typo in nfs_sockaddr_match_ipaddr6 + +From: Trond Myklebust + +commit b20d37ca9561711c6a3c4b859c2855f49565e061 upstream. + +Reported-by: Ben Greear +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/client.c ++++ b/fs/nfs/client.c +@@ -273,7 +273,7 @@ static int nfs_sockaddr_match_ipaddr6(co + sin1->sin6_scope_id != sin2->sin6_scope_id) + return 0; + +- return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); ++ return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); + } + #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ + static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, diff --git a/queue-2.6.32/series b/queue-2.6.32/series index 25be1b6d192..55fe7dedce1 100644 --- a/queue-2.6.32/series +++ b/queue-2.6.32/series @@ -111,3 +111,10 @@ sched-fix-select_idle_sibling-logic-in-select_task_rq_fair.patch sched-cpuacct-use-bigger-percpu-counter-batch-values-for-stats-counters.patch alsa-hda-handle-missing-nid-0x1b-on-alc259-codec.patch alsa-hda-handle-pin-nid-0x1a-on-alc259-269.patch +arm-fix-really-nasty-sigreturn-bug.patch +hwmon-f75375s-shift-control-mode-to-the-correct-bit-position.patch +hwmon-f75375s-do-not-overwrite-values-read-from-registers.patch +apm_power-add-missing-break-statement.patch +nfs-fix-a-typo-in-nfs_sockaddr_match_ipaddr6.patch +sunrpc-fix-race-corrupting-rpc-upcall.patch +sunrpc-fix-a-race-in-rpc_info_open.patch diff --git a/queue-2.6.32/sunrpc-fix-a-race-in-rpc_info_open.patch b/queue-2.6.32/sunrpc-fix-a-race-in-rpc_info_open.patch new file mode 100644 index 00000000000..fdc1cb6db79 --- /dev/null +++ b/queue-2.6.32/sunrpc-fix-a-race-in-rpc_info_open.patch @@ -0,0 +1,154 @@ +From 006abe887c5e637d059c44310de6c92f36aded3b Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Sun, 12 Sep 2010 19:55:25 -0400 +Subject: SUNRPC: Fix a race in rpc_info_open + +From: Trond Myklebust + +commit 006abe887c5e637d059c44310de6c92f36aded3b upstream. + +There is a race between rpc_info_open and rpc_release_client() +in that nothing stops a process from opening the file after +the clnt->cl_kref goes to zero. + +Fix this by using atomic_inc_unless_zero()... + +Reported-by: J. Bruce Fields +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- a/include/linux/sunrpc/clnt.h ++++ b/include/linux/sunrpc/clnt.h +@@ -30,7 +30,7 @@ struct rpc_inode; + * The high-level client handle + */ + struct rpc_clnt { +- struct kref cl_kref; /* Number of references */ ++ atomic_t cl_count; /* Number of references */ + struct list_head cl_clients; /* Global list of clients */ + struct list_head cl_tasks; /* List of tasks */ + spinlock_t cl_lock; /* spinlock */ +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 657aac6..3a8f53e 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru + goto out_no_principal; + } + +- kref_init(&clnt->cl_kref); ++ atomic_set(&clnt->cl_count, 1); + + err = rpc_setup_pipedir(clnt, program->pipe_dir_name); + if (err < 0) +@@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt) + if (new->cl_principal == NULL) + goto out_no_principal; + } +- kref_init(&new->cl_kref); ++ atomic_set(&new->cl_count, 1); + err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); + if (err != 0) + goto out_no_path; + if (new->cl_auth) + atomic_inc(&new->cl_auth->au_count); + xprt_get(clnt->cl_xprt); +- kref_get(&clnt->cl_kref); ++ atomic_inc(&clnt->cl_count); + rpc_register_client(new); + rpciod_up(); + return new; +@@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); + * Free an RPC client + */ + static void +-rpc_free_client(struct kref *kref) ++rpc_free_client(struct rpc_clnt *clnt) + { +- struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); +- + dprintk("RPC: destroying %s client for %s\n", + clnt->cl_protname, clnt->cl_server); + if (!IS_ERR(clnt->cl_path.dentry)) { +@@ -495,12 +493,10 @@ out_free: + * Free an RPC client + */ + static void +-rpc_free_auth(struct kref *kref) ++rpc_free_auth(struct rpc_clnt *clnt) + { +- struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); +- + if (clnt->cl_auth == NULL) { +- rpc_free_client(kref); ++ rpc_free_client(clnt); + return; + } + +@@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref) + * release remaining GSS contexts. This mechanism ensures + * that it can do so safely. + */ +- kref_init(kref); ++ atomic_inc(&clnt->cl_count); + rpcauth_release(clnt->cl_auth); + clnt->cl_auth = NULL; +- kref_put(kref, rpc_free_client); ++ if (atomic_dec_and_test(&clnt->cl_count)) ++ rpc_free_client(clnt); + } + + /* +@@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt) + + if (list_empty(&clnt->cl_tasks)) + wake_up(&destroy_wait); +- kref_put(&clnt->cl_kref, rpc_free_auth); ++ if (atomic_dec_and_test(&clnt->cl_count)) ++ rpc_free_auth(clnt); + } + + /** +@@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) + if (clnt != NULL) { + rpc_task_release_client(task); + task->tk_client = clnt; +- kref_get(&clnt->cl_kref); ++ atomic_inc(&clnt->cl_count); + if (clnt->cl_softrtry) + task->tk_flags |= RPC_TASK_SOFT; + /* Add to the client's list of all tasks */ +diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c +index 41a762f..8c8eef2 100644 +--- a/net/sunrpc/rpc_pipe.c ++++ b/net/sunrpc/rpc_pipe.c +@@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) + static int + rpc_info_open(struct inode *inode, struct file *file) + { +- struct rpc_clnt *clnt; ++ struct rpc_clnt *clnt = NULL; + int ret = single_open(file, rpc_show_info, NULL); + + if (!ret) { + struct seq_file *m = file->private_data; +- mutex_lock(&inode->i_mutex); +- clnt = RPC_I(inode)->private; +- if (clnt) { +- kref_get(&clnt->cl_kref); ++ ++ spin_lock(&file->f_path.dentry->d_lock); ++ if (!d_unhashed(file->f_path.dentry)) ++ clnt = RPC_I(inode)->private; ++ if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { ++ spin_unlock(&file->f_path.dentry->d_lock); + m->private = clnt; + } else { ++ spin_unlock(&file->f_path.dentry->d_lock); + single_release(inode, file); + ret = -EINVAL; + } +- mutex_unlock(&inode->i_mutex); + } + return ret; + } diff --git a/queue-2.6.32/sunrpc-fix-race-corrupting-rpc-upcall.patch b/queue-2.6.32/sunrpc-fix-race-corrupting-rpc-upcall.patch new file mode 100644 index 00000000000..f70349fd240 --- /dev/null +++ b/queue-2.6.32/sunrpc-fix-race-corrupting-rpc-upcall.patch @@ -0,0 +1,81 @@ +From 5a67657a2e90c9e4a48518f95d4ba7777aa20fbb Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Sun, 12 Sep 2010 19:55:25 -0400 +Subject: SUNRPC: Fix race corrupting rpc upcall + +From: Trond Myklebust + +commit 5a67657a2e90c9e4a48518f95d4ba7777aa20fbb upstream. + +If rpc_queue_upcall() adds a new upcall to the rpci->pipe list just +after rpc_pipe_release calls rpc_purge_list(), but before it calls +gss_pipe_release (as rpci->ops->release_pipe(inode)), then the latter +will free a message without deleting it from the rpci->pipe list. + +We will be left with a freed object on the rpc->pipe list. Most +frequent symptoms are kernel crashes in rpc.gssd system calls on the +pipe in question. + +Reported-by: J. Bruce Fields +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/auth_gss/auth_gss.c | 9 +++++---- + net/sunrpc/rpc_pipe.c | 6 +++--- + 2 files changed, 8 insertions(+), 7 deletions(-) + +--- a/net/sunrpc/auth_gss/auth_gss.c ++++ b/net/sunrpc/auth_gss/auth_gss.c +@@ -717,17 +717,18 @@ gss_pipe_release(struct inode *inode) + struct rpc_inode *rpci = RPC_I(inode); + struct gss_upcall_msg *gss_msg; + ++restart: + spin_lock(&inode->i_lock); +- while (!list_empty(&rpci->in_downcall)) { ++ list_for_each_entry(gss_msg, &rpci->in_downcall, list) { + +- gss_msg = list_entry(rpci->in_downcall.next, +- struct gss_upcall_msg, list); ++ if (!list_empty(&gss_msg->msg.list)) ++ continue; + gss_msg->msg.errno = -EPIPE; + atomic_inc(&gss_msg->count); + __gss_unhash_msg(gss_msg); + spin_unlock(&inode->i_lock); + gss_release_msg(gss_msg); +- spin_lock(&inode->i_lock); ++ goto restart; + } + spin_unlock(&inode->i_lock); + +--- a/net/sunrpc/rpc_pipe.c ++++ b/net/sunrpc/rpc_pipe.c +@@ -47,7 +47,7 @@ static void rpc_purge_list(struct rpc_in + return; + do { + msg = list_entry(head->next, struct rpc_pipe_msg, list); +- list_del(&msg->list); ++ list_del_init(&msg->list); + msg->errno = err; + destroy_msg(msg); + } while (!list_empty(head)); +@@ -207,7 +207,7 @@ rpc_pipe_release(struct inode *inode, st + if (msg != NULL) { + spin_lock(&inode->i_lock); + msg->errno = -EAGAIN; +- list_del(&msg->list); ++ list_del_init(&msg->list); + spin_unlock(&inode->i_lock); + rpci->ops->destroy_msg(msg); + } +@@ -267,7 +267,7 @@ rpc_pipe_read(struct file *filp, char __ + if (res < 0 || msg->len == msg->copied) { + filp->private_data = NULL; + spin_lock(&inode->i_lock); +- list_del(&msg->list); ++ list_del_init(&msg->list); + spin_unlock(&inode->i_lock); + rpci->ops->destroy_msg(msg); + }