diff options
9 files changed, 2186 insertions, 2 deletions
diff --git a/freed-ora/current/f16/be2net-non-member-vlan-pkts-not-received-in-promisco.patch b/freed-ora/current/f16/be2net-non-member-vlan-pkts-not-received-in-promisco.patch new file mode 100644 index 000000000..866473efd --- /dev/null +++ b/freed-ora/current/f16/be2net-non-member-vlan-pkts-not-received-in-promisco.patch @@ -0,0 +1,63 @@ +From c0e64ef4899df4cedc872871e54e2c069d29e519 Mon Sep 17 00:00:00 2001 +From: Sathya Perla <sathya.perla@emulex.com> +Date: Tue, 2 Aug 2011 19:57:43 +0000 +Subject: [PATCH] be2net: non-member vlan pkts not received in promiscous mode + +While configuring promiscous mode, explicitly set the +VLAN_PROMISCOUS bit to make this happen. When switching off +promiscous mode, re-program the vids. + +Signed-off-by: Xavier Selvin <xavier.selvin@emulex.com> +Signed-off-by: Sathya Perla <sathya.perla@emulex.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/benet/be_cmds.c | 6 ++++-- + drivers/net/benet/be_main.c | 7 +++++++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c +index 1c25dbd..73fd949 100644 +--- a/drivers/net/benet/be_cmds.c ++++ b/drivers/net/benet/be_cmds.c +@@ -1586,9 +1586,11 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en) + OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req)); + + req->if_id = cpu_to_le32(adapter->if_handle); +- req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); ++ req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS ++ | BE_IF_FLAGS_VLAN_PROMISCUOUS); + if (en) +- req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); ++ req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS ++ | BE_IF_FLAGS_VLAN_PROMISCUOUS); + + sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma)); + sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF); +diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c +index 3b2c5e6..32a5b11 100644 +--- a/drivers/net/benet/be_main.c ++++ b/drivers/net/benet/be_main.c +@@ -728,6 +728,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) + status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); + } + ++ /* No need to further configure vids if in promiscuous mode */ ++ if (adapter->promiscuous) ++ return 0; ++ + if (adapter->vlans_added <= adapter->max_vlans) { + /* Construct VLAN Table to give to HW */ + for (i = 0; i < VLAN_N_VID; i++) { +@@ -787,6 +791,9 @@ static void be_set_multicast_list(struct net_device *netdev) + if (adapter->promiscuous) { + adapter->promiscuous = false; + be_cmd_promiscuous_config(adapter, false); ++ ++ if (adapter->vlans_added) ++ be_vid_config(adapter, false, 0); + } + + /* Enable multicast promisc if num configured exceeds what we support */ +-- +1.7.6.4 + diff --git a/freed-ora/current/f16/benet-remove-bogus-unlikely-on-vlan-check.patch b/freed-ora/current/f16/benet-remove-bogus-unlikely-on-vlan-check.patch new file mode 100644 index 000000000..08c00817e --- /dev/null +++ b/freed-ora/current/f16/benet-remove-bogus-unlikely-on-vlan-check.patch @@ -0,0 +1,39 @@ +From 82f15998fafe683add83f7a11b2e25f919b3cd2d Mon Sep 17 00:00:00 2001 +From: Jiri Pirko <jpirko@redhat.com> +Date: Tue, 25 Oct 2011 13:47:16 -0400 +Subject: [PATCH] benet: remove bogus "unlikely" on vlan check + +Use of unlikely in this place is wrong. Remove it. + +Signed-off-by: Jiri Pirko <jpirko@redhat.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Backported-by: Josh Boyer <jwboyer@redhat.com> +--- + drivers/net/benet/be_main.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c +index c411bb1..6df0c7e 100644 +--- a/drivers/net/benet/be_main.c ++++ b/drivers/net/benet/be_main.c +@@ -1192,7 +1192,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, + skb->rxhash = rxcp->rss_hash; + + +- if (unlikely(rxcp->vlanf)) ++ if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + + netif_receive_skb(skb); +@@ -1249,7 +1249,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, + if (adapter->netdev->features & NETIF_F_RXHASH) + skb->rxhash = rxcp->rss_hash; + +- if (unlikely(rxcp->vlanf)) ++ if (rxcp->vlanf) + __vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + + napi_gro_frags(&eq_obj->napi); +-- +1.7.6.4 + diff --git a/freed-ora/current/f16/deblob-check b/freed-ora/current/f16/deblob-check index 2be51658b..9da954f55 100755 --- a/freed-ora/current/f16/deblob-check +++ b/freed-ora/current/f16/deblob-check @@ -1,6 +1,6 @@ #! /bin/sh -# deblob-check version 2011-10-09 +# deblob-check version 2011-10-24 # Inspired in gNewSense's find-firmware script. # Written by Alexandre Oliva <lxoliva@fsfla.org> @@ -2922,6 +2922,10 @@ set_except () { accept 'P[13]\([\n]#[^\n]*\)*[\n]*\([\n][0-9 ]*\)\+' drivers/video/logo/logo_libre_clut224.ppm ;; + */media-DiBcom*.patch) + accept '[ ]\+request_firmware[(][)][ ]will[ ]hit[ ]an[ ]OOPS' drivers/media/dvb/frontends/dib7000p.c + ;; + */patch*-3.1-rc*) defsnc '[ ]static[ ]const[ ]u8[ ]t\[\][ ]=' drivers/bcma/sprom.c accept '[ ]\+request_firmware[(][)][ ]will[ ]hit[ ]an[ ]OOPS' drivers/media/dvb/frontends/dib7000p.c diff --git a/freed-ora/current/f16/epoll-limit-paths.patch b/freed-ora/current/f16/epoll-limit-paths.patch new file mode 100644 index 000000000..440db27b9 --- /dev/null +++ b/freed-ora/current/f16/epoll-limit-paths.patch @@ -0,0 +1,465 @@ +From 6a4ca79652219cf22da800d990e5b46feaea1ad9 Mon Sep 17 00:00:00 2001 +From: Jason Baron <jbaron@redhat.com> +Date: Mon, 24 Oct 2011 14:59:02 +1100 +Subject: [PATCH] epoll: limit paths + +epoll: limit paths + +The current epoll code can be tickled to run basically indefinitely in +both loop detection path check (on ep_insert()), and in the wakeup paths. +The programs that tickle this behavior set up deeply linked networks of +epoll file descriptors that cause the epoll algorithms to traverse them +indefinitely. A couple of these sample programs have been previously +posted in this thread: https://lkml.org/lkml/2011/2/25/297. + +To fix the loop detection path check algorithms, I simply keep track of +the epoll nodes that have been already visited. Thus, the loop detection +becomes proportional to the number of epoll file descriptor and links. +This dramatically decreases the run-time of the loop check algorithm. In +one diabolical case I tried it reduced the run-time from 15 mintues (all +in kernel time) to .3 seconds. + +Fixing the wakeup paths could be done at wakeup time in a similar manner +by keeping track of nodes that have already been visited, but the +complexity is harder, since there can be multiple wakeups on different +cpus...Thus, I've opted to limit the number of possible wakeup paths when +the paths are created. + +This is accomplished, by noting that the end file descriptor points that +are found during the loop detection pass (from the newly added link), are +actually the sources for wakeup events. I keep a list of these file +descriptors and limit the number and length of these paths that emanate +from these 'source file descriptors'. In the current implemetation I +allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of +length 4 and 10 of length 5. Note that it is sufficient to check the +'source file descriptors' reachable from the newly added link, since no +other 'source file descriptors' will have newly added links. This allows +us to check only the wakeup paths that may have gotten too long, and not +re-check all possible wakeup paths on the system. + +In terms of the path limit selection, I think its first worth noting that +the most common case for epoll, is probably the model where you have 1 +epoll file descriptor that is monitoring n number of 'source file +descriptors'. In this case, each 'source file descriptor' has a 1 path of +length 1. Thus, I believe that the limits I'm proposing are quite +reasonable and in fact may be too generous. Thus, I'm hoping that the +proposed limits will not prevent any workloads that currently work to +fail. + +In terms of locking, I have extended the use of the 'epmutex' to all +epoll_ctl add and remove operations. Currently its only used in a subset +of the add paths. I need to hold the epmutex, so that we can correctly +traverse a coherent graph, to check the number of paths. I believe that +this additional locking is probably ok, since its in the setup/teardown +paths, and doesn't affect the running paths, but it certainly is going to +add some extra overhead. Also, worth noting is that the epmuex was +recently added to the ep_ctl add operations in the initial path loop +detection code using the argument that it was not on a critical path. + +Another thing to note here, is the length of epoll chains that is allowed. +Currently, eventpoll.c defines: + +/* Maximum number of nesting allowed inside epoll sets */ +#define EP_MAX_NESTS 4 + +This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS ++ 1). However, this limit is currently only enforced during the loop +check detection code, and only when the epoll file descriptors are added +in a certain order. Thus, this limit is currently easily bypassed. The +newly added check for wakeup paths, stricly limits the wakeup paths to a +length of 5, regardless of the order in which ep's are linked together. +Thus, a side-effect of the new code is a more consistent enforcement of +the graph depth. + +Thus far, I've tested this, using the sample programs previously +mentioned, which now either return quickly or return -EINVAL. I've also +testing using the piptest.c epoll tester, which showed no difference in +performance. I've also created a number of different epoll networks and +tested that they behave as expectded. + +I believe this solves the original diabolical test cases, while still +preserving the sane epoll nesting. + +Signed-off-by: Jason Baron <jbaron@redhat.com> +Cc: Nelson Elhage <nelhage@ksplice.com> +Cc: Davide Libenzi <davidel@xmailserver.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +--- + fs/eventpoll.c | 226 ++++++++++++++++++++++++++++++++++++++++----- + include/linux/eventpoll.h | 1 + + include/linux/fs.h | 1 + + 3 files changed, 203 insertions(+), 25 deletions(-) + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 4a53743..414ac74 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -197,6 +197,12 @@ struct eventpoll { + + /* The user that created the eventpoll descriptor */ + struct user_struct *user; ++ ++ struct file *file; ++ ++ /* used to optimize loop detection check */ ++ int visited; ++ struct list_head visitedllink; + }; + + /* Wait structure used by the poll hooks */ +@@ -255,6 +261,12 @@ static struct kmem_cache *epi_cache __read_mostly; + /* Slab cache used to allocate "struct eppoll_entry" */ + static struct kmem_cache *pwq_cache __read_mostly; + ++/* Visited nodes during ep_loop_check(), so we can unset them when we finish */ ++LIST_HEAD(visited_list); ++ ++/* Files with newly added links, which need a limit on emanating paths */ ++LIST_HEAD(tfile_check_list); ++ + #ifdef CONFIG_SYSCTL + + #include <linux/sysctl.h> +@@ -276,6 +288,12 @@ ctl_table epoll_table[] = { + }; + #endif /* CONFIG_SYSCTL */ + ++static const struct file_operations eventpoll_fops; ++ ++static inline int is_file_epoll(struct file *f) ++{ ++ return f->f_op == &eventpoll_fops; ++} + + /* Setup the structure that is used as key for the RB tree */ + static inline void ep_set_ffd(struct epoll_filefd *ffd, +@@ -711,12 +729,6 @@ static const struct file_operations eventpoll_fops = { + .llseek = noop_llseek, + }; + +-/* Fast test to see if the file is an evenpoll file */ +-static inline int is_file_epoll(struct file *f) +-{ +- return f->f_op == &eventpoll_fops; +-} +- + /* + * This is called from eventpoll_release() to unlink files from the eventpoll + * interface. We need to have this facility to cleanup correctly files that are +@@ -926,6 +938,96 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) + rb_insert_color(&epi->rbn, &ep->rbr); + } + ++ ++ ++#define PATH_ARR_SIZE 5 ++/* These are the number paths of length 1 to 5, that we are allowing to emanate ++ * from a single file of interest. For example, we allow 1000 paths of length ++ * 1, to emanate from each file of interest. This essentially represents the ++ * potential wakeup paths, which need to be limited in order to avoid massive ++ * uncontrolled wakeup storms. The common use case should be a single ep which ++ * is connected to n file sources. In this case each file source has 1 path ++ * of length 1. Thus, the numbers below should be more than sufficient. ++ */ ++int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 }; ++int path_count[PATH_ARR_SIZE]; ++ ++static int path_count_inc(int nests) ++{ ++ if (++path_count[nests] > path_limits[nests]) ++ return -1; ++ return 0; ++} ++ ++static void path_count_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < PATH_ARR_SIZE; i++) ++ path_count[i] = 0; ++} ++ ++static int reverse_path_check_proc(void *priv, void *cookie, int call_nests) ++{ ++ int error = 0; ++ struct file *file = priv; ++ struct file *child_file; ++ struct epitem *epi; ++ ++ list_for_each_entry(epi, &file->f_ep_links, fllink) { ++ child_file = epi->ep->file; ++ if (is_file_epoll(child_file)) { ++ if (list_empty(&child_file->f_ep_links)) { ++ if (path_count_inc(call_nests)) { ++ error = -1; ++ break; ++ } ++ } else { ++ error = ep_call_nested(&poll_loop_ncalls, ++ EP_MAX_NESTS, ++ reverse_path_check_proc, ++ child_file, child_file, ++ current); ++ } ++ if (error != 0) ++ break; ++ } else { ++ printk(KERN_ERR "reverse_path_check_proc: " ++ "file is not an ep!\n"); ++ } ++ } ++ return error; ++} ++ ++/** ++ * reverse_path_check - The tfile_check_list is list of file *, which have ++ * links that are proposed to be newly added. We need to ++ * make sure that those added links don't add too many ++ * paths such that we will spend all our time waking up ++ * eventpoll objects. ++ * ++ * Returns: Returns zero if the proposed links don't create too many paths, ++ * -1 otherwise. ++ */ ++static int reverse_path_check(void) ++{ ++ int length = 0; ++ int error = 0; ++ struct file *current_file; ++ ++ /* let's call this for all tfiles */ ++ list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) { ++ length++; ++ path_count_init(); ++ error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, ++ reverse_path_check_proc, current_file, ++ current_file, current); ++ if (error) ++ break; ++ } ++ return error; ++} ++ + /* + * Must be called with "mtx" held. + */ +@@ -987,6 +1089,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + */ + ep_rbtree_insert(ep, epi); + ++ /* now check if we've created too many backpaths */ ++ error = -EINVAL; ++ if (reverse_path_check()) ++ goto error_remove_epi; ++ + /* We have to drop the new item inside our item list to keep track of it */ + spin_lock_irqsave(&ep->lock, flags); + +@@ -1011,6 +1118,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, + + return 0; + ++error_remove_epi: ++ spin_lock(&tfile->f_lock); ++ if (ep_is_linked(&epi->fllink)) ++ list_del_init(&epi->fllink); ++ spin_unlock(&tfile->f_lock); ++ ++ rb_erase(&epi->rbn, &ep->rbr); ++ + error_unregister: + ep_unregister_pollwait(ep, epi); + +@@ -1275,18 +1390,35 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + int error = 0; + struct file *file = priv; + struct eventpoll *ep = file->private_data; ++ struct eventpoll *ep_tovisit; + struct rb_node *rbp; + struct epitem *epi; + + mutex_lock_nested(&ep->mtx, call_nests + 1); ++ ep->visited = 1; ++ list_add(&ep->visitedllink, &visited_list); + for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); + if (unlikely(is_file_epoll(epi->ffd.file))) { ++ ep_tovisit = epi->ffd.file->private_data; ++ if (ep_tovisit->visited) ++ continue; + error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, +- ep_loop_check_proc, epi->ffd.file, +- epi->ffd.file->private_data, current); ++ ep_loop_check_proc, epi->ffd.file, ++ ep_tovisit, current); + if (error != 0) + break; ++ } else { ++ /* if we've reached a file that is not associated with ++ * an ep, then then we need to check if the newly added ++ * links are going to add too many wakeup paths. We do ++ * this by adding it to the tfile_check_list, if it's ++ * not already there, and calling reverse_path_check() ++ * during ep_insert() ++ */ ++ if (list_empty(&epi->ffd.file->f_tfile_llink)) ++ list_add(&epi->ffd.file->f_tfile_llink, ++ &tfile_check_list); + } + } + mutex_unlock(&ep->mtx); +@@ -1307,8 +1439,30 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) + */ + static int ep_loop_check(struct eventpoll *ep, struct file *file) + { +- return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, ++ int ret; ++ struct eventpoll *ep_cur, *ep_next; ++ ++ ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS, + ep_loop_check_proc, file, ep, current); ++ /* clear visited list */ ++ list_for_each_entry_safe(ep_cur, ep_next, &visited_list, visitedllink) { ++ ep_cur->visited = 0; ++ list_del(&ep_cur->visitedllink); ++ } ++ return ret; ++} ++ ++static void clear_tfile_check_list(void) ++{ ++ struct file *file; ++ ++ /* first clear the tfile_check_list */ ++ while (!list_empty(&tfile_check_list)) { ++ file = list_first_entry(&tfile_check_list, struct file, ++ f_tfile_llink); ++ list_del_init(&file->f_tfile_llink); ++ } ++ INIT_LIST_HEAD(&tfile_check_list); + } + + /* +@@ -1316,8 +1470,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file) + */ + SYSCALL_DEFINE1(epoll_create1, int, flags) + { +- int error; ++ int error, fd; + struct eventpoll *ep = NULL; ++ struct file *file; + + /* Check the EPOLL_* constant for consistency. */ + BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC); +@@ -1334,11 +1489,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) + * Creates all the items needed to setup an eventpoll file. That is, + * a file structure and a free file descriptor. + */ +- error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, ++ fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC)); ++ if (fd < 0) { ++ error = fd; ++ goto out_free_ep; ++ } ++ file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep, + O_RDWR | (flags & O_CLOEXEC)); +- if (error < 0) +- ep_free(ep); +- ++ if (IS_ERR(file)) { ++ error = PTR_ERR(file); ++ goto out_free_fd; ++ } ++ fd_install(fd, file); ++ ep->file = file; ++ return fd; ++ ++out_free_fd: ++ put_unused_fd(fd); ++out_free_ep: ++ ep_free(ep); + return error; + } + +@@ -1404,21 +1573,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + /* + * When we insert an epoll file descriptor, inside another epoll file + * descriptor, there is the change of creating closed loops, which are +- * better be handled here, than in more critical paths. ++ * better be handled here, than in more critical paths. While we are ++ * checking for loops we also determine the list of files reachable ++ * and hang them on the tfile_check_list, so we can check that we ++ * haven't created too many possible wakeup paths. + * +- * We hold epmutex across the loop check and the insert in this case, in +- * order to prevent two separate inserts from racing and each doing the +- * insert "at the same time" such that ep_loop_check passes on both +- * before either one does the insert, thereby creating a cycle. ++ * We need to hold the epmutex across both ep_insert and ep_remove ++ * b/c we want to make sure we are looking at a coherent view of ++ * epoll network. + */ +- if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) { ++ if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) { + mutex_lock(&epmutex); + did_lock_epmutex = 1; +- error = -ELOOP; +- if (ep_loop_check(ep, tfile) != 0) +- goto error_tgt_fput; + } +- ++ if (op == EPOLL_CTL_ADD) { ++ if (is_file_epoll(tfile)) { ++ error = -ELOOP; ++ if (ep_loop_check(ep, tfile) != 0) ++ goto error_tgt_fput; ++ } else ++ list_add(&tfile->f_tfile_llink, &tfile_check_list); ++ } + + mutex_lock_nested(&ep->mtx, 0); + +@@ -1437,6 +1612,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + error = ep_insert(ep, &epds, tfile, fd); + } else + error = -EEXIST; ++ clear_tfile_check_list(); + break; + case EPOLL_CTL_DEL: + if (epi) +@@ -1455,7 +1631,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + mutex_unlock(&ep->mtx); + + error_tgt_fput: +- if (unlikely(did_lock_epmutex)) ++ if (did_lock_epmutex) + mutex_unlock(&epmutex); + + fput(tfile); +diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h +index f362733..657ab55 100644 +--- a/include/linux/eventpoll.h ++++ b/include/linux/eventpoll.h +@@ -61,6 +61,7 @@ struct file; + static inline void eventpoll_init_file(struct file *file) + { + INIT_LIST_HEAD(&file->f_ep_links); ++ INIT_LIST_HEAD(&file->f_tfile_llink); + } + + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 277f497..93778e0 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -985,6 +985,7 @@ struct file { + #ifdef CONFIG_EPOLL + /* Used by fs/eventpoll.c to link all the hooks to this file */ + struct list_head f_ep_links; ++ struct list_head f_tfile_llink; + #endif /* #ifdef CONFIG_EPOLL */ + struct address_space *f_mapping; + #ifdef CONFIG_DEBUG_WRITECOUNT +-- +1.7.6.4 + diff --git a/freed-ora/current/f16/kernel.spec b/freed-ora/current/f16/kernel.spec index 00fa26afc..051f067ab 100644 --- a/freed-ora/current/f16/kernel.spec +++ b/freed-ora/current/f16/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -727,6 +727,10 @@ Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch +Patch2903: media-DiBcom-protect-the-I2C-bufer-access.patch +Patch2904: media-dib0700-protect-the-dib0700-buffer-access.patch +Patch2905: media-dib0700-correct-error-message.patch + Patch3000: rcutree-avoid-false-quiescent-states.patch # fs fixes @@ -747,6 +751,7 @@ Patch12025: rcu-avoid-just-onlined-cpu-resched.patch Patch12026: block-stray-block-put-after-teardown.patch Patch12027: usb-add-quirk-for-logitech-webcams.patch Patch12029: crypto-register-cryptd-first.patch +Patch12030: epoll-limit-paths.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -774,6 +779,13 @@ Patch21002: mmc-Always-check-for-lower-base-frequency-quirk-for-.patch Patch21020: 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch Patch21021: 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +#rhbz 748691 +Patch21030: be2net-non-member-vlan-pkts-not-received-in-promisco.patch +Patch21031: benet-remove-bogus-unlikely-on-vlan-check.patch + +#rhbz 749166 +Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1304,6 +1316,7 @@ ApplyPatch linux-2.6-i386-nx-emulation.patch # ext4 # xfs +ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch # btrfs @@ -1410,6 +1423,7 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch udlfb-bind-framebuffer-to-interface.patch ApplyPatch ums-realtek-driver-uses-stack-memory-for-DMA.patch ApplyPatch epoll-fix-spurious-lockdep-warnings.patch +ApplyPatch epoll-limit-paths.patch ApplyPatch rcu-avoid-just-onlined-cpu-resched.patch ApplyPatch block-stray-block-put-after-teardown.patch ApplyPatch usb-add-quirk-for-logitech-webcams.patch @@ -1435,6 +1449,10 @@ ApplyPatch iwlagn-fix-ht_params-NULL-pointer-dereference.patch #rhbz #722509 ApplyPatch mmc-Always-check-for-lower-base-frequency-quirk-for-.patch +ApplyPatch media-DiBcom-protect-the-I2C-bufer-access.patch +ApplyPatch media-dib0700-protect-the-dib0700-buffer-access.patch +ApplyPatch media-dib0700-correct-error-message.patch + # utrace. ApplyPatch utrace.patch @@ -1442,6 +1460,10 @@ ApplyPatch utrace.patch ApplyPatch 0001-mm-vmscan-Limit-direct-reclaim-for-higher-order-allo.patch ApplyPatch 0002-mm-Abort-reclaim-compaction-if-compaction-can-procee.patch +#rhbz 748691 +ApplyPatch be2net-non-member-vlan-pkts-not-received-in-promisco.patch +ApplyPatch benet-remove-bogus-unlikely-on-vlan-check.patch + # END OF PATCH APPLICATIONS %endif @@ -2143,6 +2165,19 @@ fi # and build. %changelog +* Wed Oct 26 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.1.0-5 +- Rebuilt for glibc bug#747377 + +* Wed Oct 26 2011 Josh Boyer <jwboyer@redhat.com> +- CVE-2011-4077: xfs: potential buffer overflow in xfs_readlink() (rhbz 749166) + +* Tue Oct 25 2011 Josh Boyer <jwboyer@redhat.com> +- CVE-2011-3347: be2net: promiscuous mode and non-member VLAN packets DoS (rhbz 748691) +- CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668) + +* Mon Oct 24 2011 Josh Boyer <jwboyer@redhat.com> +- Backport 3 fixed from linux-next to fix dib0700 playback (rhbz 733827) + * Mon Oct 24 2011 Alexandre Oliva <lxoliva@fsfla.org> -libre - Linux-libre 3.1-libre diff --git a/freed-ora/current/f16/media-DiBcom-protect-the-I2C-bufer-access.patch b/freed-ora/current/f16/media-DiBcom-protect-the-I2C-bufer-access.patch new file mode 100644 index 000000000..1b2a54b86 --- /dev/null +++ b/freed-ora/current/f16/media-DiBcom-protect-the-I2C-bufer-access.patch @@ -0,0 +1,1150 @@ +From: Patrick Boettcher <Patrick.Boettcher@dibcom.fr> +Date: Wed, 3 Aug 2011 15:08:21 +0000 (-0300) +Subject: [media] DiBcom: protect the I2C bufer access +X-Git-Tag: next-20110927~67^2~4^2~225 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=79fcce3230b140f7675f8529ee53fe2f9644f902 + +[media] DiBcom: protect the I2C bufer access + +This patch protects the I2C buffer access in order to manage concurrent +access. This protection is done using mutex. +Furthermore, for the dib9000, if a pid filtering command is +received during the tuning, this pid filtering command is delayed to +avoid any concurrent access issue. + +Cc: Mauro Carvalho Chehab <mchehab@redhat.com> +Cc: Florian Mickler <florian@mickler.org> +Cc: stable@kernel.org +Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr> +Signed-off-by: Patrick Boettcher <Patrick.Boettcher@dibcom.fr> +Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> +--- + +diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c +index 1d47d4d..dc1cb17 100644 +--- a/drivers/media/dvb/frontends/dib0070.c ++++ b/drivers/media/dvb/frontends/dib0070.c +@@ -27,6 +27,7 @@ + #include <linux/kernel.h> + #include <linux/slab.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> + + #include "dvb_frontend.h" + +@@ -78,10 +79,18 @@ struct dib0070_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[3]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + +-static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) ++static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); +@@ -96,13 +105,23 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) + + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { + printk(KERN_WARNING "DiB0070 I2C read failed\n"); +- return 0; +- } +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } + state->i2c_write_buffer[0] = reg; + state->i2c_write_buffer[1] = val >> 8; + state->i2c_write_buffer[2] = val & 0xff; +@@ -115,9 +134,12 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) + + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0070 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + #define HARD_RESET(state) do { \ +@@ -734,6 +756,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter + state->cfg = cfg; + state->i2c = i2c; + state->fe = fe; ++ mutex_init(&state->i2c_buffer_lock); + fe->tuner_priv = state; + + if (dib0070_reset(fe) != 0) +diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c +index c9c935a..b174d1c 100644 +--- a/drivers/media/dvb/frontends/dib0090.c ++++ b/drivers/media/dvb/frontends/dib0090.c +@@ -27,6 +27,7 @@ + #include <linux/kernel.h> + #include <linux/slab.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> + + #include "dvb_frontend.h" + +@@ -196,6 +197,7 @@ struct dib0090_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[3]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + struct dib0090_fw_state { +@@ -208,10 +210,18 @@ struct dib0090_fw_state { + struct i2c_msg msg; + u8 i2c_write_buffer[2]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); +@@ -226,14 +236,24 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) + + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { + printk(KERN_WARNING "DiB0090 I2C read failed\n"); +- return 0; +- } ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = reg & 0xff; + state->i2c_write_buffer[1] = val >> 8; + state->i2c_write_buffer[2] = val & 0xff; +@@ -246,13 +266,23 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) + + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg; + + memset(&state->msg, 0, sizeof(struct i2c_msg)); +@@ -262,13 +292,24 @@ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) + state->msg.len = 2; + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C read failed\n"); +- return 0; +- } +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = 0; ++ } else ++ ret = (state->i2c_read_buffer[0] << 8) ++ | state->i2c_read_buffer[1]; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = val >> 8; + state->i2c_write_buffer[1] = val & 0xff; + +@@ -279,9 +320,12 @@ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) + state->msg.len = 2; + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C write failed\n"); +- return -EREMOTEIO; +- } +- return 0; ++ ret = -EREMOTEIO; ++ } else ++ ret = 0; ++ ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) +@@ -2440,6 +2484,7 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte + st->config = config; + st->i2c = i2c; + st->fe = fe; ++ mutex_init(&st->i2c_buffer_lock); + fe->tuner_priv = st; + + if (config->wbd == NULL) +@@ -2471,6 +2516,7 @@ struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_ada + st->config = config; + st->i2c = i2c; + st->fe = fe; ++ mutex_init(&st->i2c_buffer_lock); + fe->tuner_priv = st; + + if (dib0090_fw_reset_digital(fe, st->config) != 0) +diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c +index 79cb1c2..dbb76d7 100644 +--- a/drivers/media/dvb/frontends/dib7000m.c ++++ b/drivers/media/dvb/frontends/dib7000m.c +@@ -11,6 +11,7 @@ + #include <linux/kernel.h> + #include <linux/slab.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> + + #include "dvb_frontend.h" + +@@ -55,6 +56,7 @@ struct dib7000m_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib7000m_power_mode { +@@ -69,6 +71,13 @@ enum dib7000m_power_mode { + + static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) | 0x80; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -85,11 +94,21 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) + dprintk("i2c read error on %d",reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -101,7 +120,10 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) + { +@@ -1385,6 +1407,7 @@ struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); ++ mutex_init(&st->i2c_buffer_lock); + + st->timf_default = cfg->bw->timf; + +diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c +index a64a538..4eb9c2b 100644 +--- a/drivers/media/dvb/frontends/dib7000p.c ++++ b/drivers/media/dvb/frontends/dib7000p.c +@@ -10,6 +10,7 @@ + #include <linux/kernel.h> + #include <linux/slab.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> + + #include "dvb_math.h" + #include "dvb_frontend.h" +@@ -68,6 +69,7 @@ struct dib7000p_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib7000p_power_mode { +@@ -81,6 +83,13 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); + + static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg >> 8; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -97,11 +106,20 @@ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -113,7 +131,10 @@ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ return ret; + } + + static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) +@@ -1646,6 +1667,7 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau + return -ENOMEM; + + dpst->i2c_adap = i2c; ++ mutex_init(&dpst->i2c_buffer_lock); + + for (k = no_of_demods - 1; k >= 0; k--) { + dpst->cfg = cfg[k]; +@@ -2324,6 +2346,7 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); ++ mutex_init(&st->i2c_buffer_lock); + + dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */ + +@@ -2333,8 +2356,9 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + st->version = dib7000p_read_word(st, 897); + + /* FIXME: make sure the dev.parent field is initialized, or else +- request_firmware() will hit an OOPS (this should be moved somewhere +- more common) */ ++ request_firmware() will hit an OOPS (this should be moved somewhere ++ more common) */ ++ st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; + + /* FIXME: make sure the dev.parent field is initialized, or else + request_firmware() will hit an OOPS (this should be moved somewhere +diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c +index 7d2ea11..fe284d5 100644 +--- a/drivers/media/dvb/frontends/dib8000.c ++++ b/drivers/media/dvb/frontends/dib8000.c +@@ -10,6 +10,8 @@ + #include <linux/kernel.h> + #include <linux/slab.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> ++ + #include "dvb_math.h" + + #include "dvb_frontend.h" +@@ -37,6 +39,7 @@ struct i2c_device { + u8 addr; + u8 *i2c_write_buffer; + u8 *i2c_read_buffer; ++ struct mutex *i2c_buffer_lock; + }; + + struct dib8000_state { +@@ -77,6 +80,7 @@ struct dib8000_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[4]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + enum dib8000_power_mode { +@@ -86,24 +90,39 @@ enum dib8000_power_mode { + + static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) + { ++ u16 ret; + struct i2c_msg msg[2] = { +- {.addr = i2c->addr >> 1, .flags = 0, +- .buf = i2c->i2c_write_buffer, .len = 2}, +- {.addr = i2c->addr >> 1, .flags = I2C_M_RD, +- .buf = i2c->i2c_read_buffer, .len = 2}, ++ {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, ++ {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, + }; + ++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ ++ msg[0].buf = i2c->i2c_write_buffer; + msg[0].buf[0] = reg >> 8; + msg[0].buf[1] = reg & 0xff; ++ msg[1].buf = i2c->i2c_read_buffer; + + if (i2c_transfer(i2c->adap, msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (msg[1].buf[0] << 8) | msg[1].buf[1]; ++ ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; ++ mutex_unlock(i2c->i2c_buffer_lock); ++ return ret; + } + + static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + state->i2c_write_buffer[0] = reg >> 8; + state->i2c_write_buffer[1] = reg & 0xff; + +@@ -120,7 +139,10 @@ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) + if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static u32 dib8000_read32(struct dib8000_state *state, u16 reg) +@@ -135,22 +157,35 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) + + static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) + { +- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, +- .buf = i2c->i2c_write_buffer, .len = 4}; ++ struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; + int ret = 0; + ++ if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ ++ msg.buf = i2c->i2c_write_buffer; + msg.buf[0] = (reg >> 8) & 0xff; + msg.buf[1] = reg & 0xff; + msg.buf[2] = (val >> 8) & 0xff; + msg.buf[3] = val & 0xff; + + ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; ++ mutex_unlock(i2c->i2c_buffer_lock); + + return ret; + } + + static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; + state->i2c_write_buffer[1] = reg & 0xff; + state->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -162,7 +197,11 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) + state->msg[0].buf = state->i2c_write_buffer; + state->msg[0].len = 4; + +- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? ++ -EREMOTEIO : 0); ++ mutex_unlock(&state->i2c_buffer_lock); ++ ++ return ret; + } + + static const s16 coeff_2k_sb_1seg_dqpsk[8] = { +@@ -2434,8 +2473,15 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau + if (!client.i2c_read_buffer) { + dprintk("%s: not enough memory", __func__); + ret = -ENOMEM; +- goto error_memory; ++ goto error_memory_read; ++ } ++ client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); ++ if (!client.i2c_buffer_lock) { ++ dprintk("%s: not enough memory", __func__); ++ ret = -ENOMEM; ++ goto error_memory_lock; + } ++ mutex_init(client.i2c_buffer_lock); + + for (k = no_of_demods - 1; k >= 0; k--) { + /* designated i2c address */ +@@ -2476,8 +2522,10 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau + } + + error: ++ kfree(client.i2c_buffer_lock); ++error_memory_lock: + kfree(client.i2c_read_buffer); +-error_memory: ++error_memory_read: + kfree(client.i2c_write_buffer); + + return ret; +@@ -2581,6 +2629,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s + state->i2c.addr = i2c_addr; + state->i2c.i2c_write_buffer = state->i2c_write_buffer; + state->i2c.i2c_read_buffer = state->i2c_read_buffer; ++ mutex_init(&state->i2c_buffer_lock); ++ state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; + state->gpio_val = cfg->gpio_val; + state->gpio_dir = cfg->gpio_dir; + +diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c +index a085588..b931074 100644 +--- a/drivers/media/dvb/frontends/dib9000.c ++++ b/drivers/media/dvb/frontends/dib9000.c +@@ -38,6 +38,15 @@ struct i2c_device { + #define DibInitLock(lock) mutex_init(lock) + #define DibFreeLock(lock) + ++struct dib9000_pid_ctrl { ++#define DIB9000_PID_FILTER_CTRL 0 ++#define DIB9000_PID_FILTER 1 ++ u8 cmd; ++ u8 id; ++ u16 pid; ++ u8 onoff; ++}; ++ + struct dib9000_state { + struct i2c_device i2c; + +@@ -99,6 +108,10 @@ struct dib9000_state { + struct i2c_msg msg[2]; + u8 i2c_write_buffer[255]; + u8 i2c_read_buffer[255]; ++ DIB_LOCK demod_lock; ++ u8 get_frontend_internal; ++ struct dib9000_pid_ctrl pid_ctrl[10]; ++ s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */ + }; + + static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +@@ -1743,19 +1756,56 @@ EXPORT_SYMBOL(dib9000_set_gpio); + int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) + { + struct dib9000_state *state = fe->demodulator_priv; +- u16 val = dib9000_read_word(state, 294 + 1) & 0xffef; ++ u16 val; ++ int ret; ++ ++ if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) { ++ /* postpone the pid filtering cmd */ ++ dprintk("pid filter cmd postpone"); ++ state->pid_ctrl_index++; ++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL; ++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; ++ return 0; ++ } ++ ++ DibAcquireLock(&state->demod_lock); ++ ++ val = dib9000_read_word(state, 294 + 1) & 0xffef; + val |= (onoff & 0x1) << 4; + + dprintk("PID filter enabled %d", onoff); +- return dib9000_write_word(state, 294 + 1, val); ++ ret = dib9000_write_word(state, 294 + 1, val); ++ DibReleaseLock(&state->demod_lock); ++ return ret; ++ + } + EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl); + + int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) + { + struct dib9000_state *state = fe->demodulator_priv; ++ int ret; ++ ++ if (state->pid_ctrl_index != -2) { ++ /* postpone the pid filtering cmd */ ++ dprintk("pid filter postpone"); ++ if (state->pid_ctrl_index < 9) { ++ state->pid_ctrl_index++; ++ state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER; ++ state->pid_ctrl[state->pid_ctrl_index].id = id; ++ state->pid_ctrl[state->pid_ctrl_index].pid = pid; ++ state->pid_ctrl[state->pid_ctrl_index].onoff = onoff; ++ } else ++ dprintk("can not add any more pid ctrl cmd"); ++ return 0; ++ } ++ ++ DibAcquireLock(&state->demod_lock); + dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff); +- return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0); ++ ret = dib9000_write_word(state, 300 + 1 + id, ++ onoff ? (1 << 13) | pid : 0); ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + EXPORT_SYMBOL(dib9000_fw_pid_filter); + +@@ -1778,6 +1828,7 @@ static void dib9000_release(struct dvb_frontend *demod) + DibFreeLock(&state->platform.risc.mbx_lock); + DibFreeLock(&state->platform.risc.mem_lock); + DibFreeLock(&state->platform.risc.mem_mbx_lock); ++ DibFreeLock(&state->demod_lock); + dibx000_exit_i2c_master(&st->i2c_master); + + i2c_del_adapter(&st->tuner_adap); +@@ -1795,14 +1846,19 @@ static int dib9000_sleep(struct dvb_frontend *fe) + { + struct dib9000_state *state = fe->demodulator_priv; + u8 index_frontend; +- int ret; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); + if (ret < 0) +- return ret; ++ goto error; + } +- return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); ++ ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0); ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) +@@ -1816,7 +1872,10 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + struct dib9000_state *state = fe->demodulator_priv; + u8 index_frontend, sub_index_frontend; + fe_status_t stat; +- int ret; ++ int ret = 0; ++ ++ if (state->get_frontend_internal == 0) ++ DibAcquireLock(&state->demod_lock); + + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); +@@ -1846,14 +1905,15 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + state->fe[index_frontend]->dtv_property_cache.rolloff; + } + } +- return 0; ++ ret = 0; ++ goto return_value; + } + } + + /* get the channel from master chip */ + ret = dib9000_fw_get_channel(fe, fep); + if (ret != 0) +- return ret; ++ goto return_value; + + /* synchronize the cache with the other frontends */ + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { +@@ -1866,8 +1926,12 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; + state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; + } ++ ret = 0; + +- return 0; ++return_value: ++ if (state->get_frontend_internal == 0) ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) +@@ -1912,6 +1976,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + dprintk("dib9000: must specify bandwidth "); + return 0; + } ++ ++ state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */ ++ DibAcquireLock(&state->demod_lock); ++ + fe->dtv_property_cache.delivery_system = SYS_DVBT; + + /* set the master status */ +@@ -1974,13 +2042,18 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + /* check the tune result */ + if (exit_condition == 1) { /* tune failed */ + dprintk("tune failed"); ++ DibReleaseLock(&state->demod_lock); ++ /* tune failed; put all the pid filtering cmd to junk */ ++ state->pid_ctrl_index = -1; + return 0; + } + + dprintk("tune success on frontend%i", index_frontend_success); + + /* synchronize all the channel cache */ ++ state->get_frontend_internal = 1; + dib9000_get_frontend(state->fe[0], fep); ++ state->get_frontend_internal = 0; + + /* retune the other frontends with the found channel */ + channel_status.status = CHANNEL_STATUS_PARAMETERS_SET; +@@ -2025,6 +2098,28 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par + /* turn off the diversity for the last frontend */ + dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0); + ++ DibReleaseLock(&state->demod_lock); ++ if (state->pid_ctrl_index >= 0) { ++ u8 index_pid_filter_cmd; ++ u8 pid_ctrl_index = state->pid_ctrl_index; ++ ++ state->pid_ctrl_index = -2; ++ for (index_pid_filter_cmd = 0; ++ index_pid_filter_cmd <= pid_ctrl_index; ++ index_pid_filter_cmd++) { ++ if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL) ++ dib9000_fw_pid_filter_ctrl(state->fe[0], ++ state->pid_ctrl[index_pid_filter_cmd].onoff); ++ else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER) ++ dib9000_fw_pid_filter(state->fe[0], ++ state->pid_ctrl[index_pid_filter_cmd].id, ++ state->pid_ctrl[index_pid_filter_cmd].pid, ++ state->pid_ctrl[index_pid_filter_cmd].onoff); ++ } ++ } ++ /* do not postpone any more the pid filtering */ ++ state->pid_ctrl_index = -2; ++ + return 0; + } + +@@ -2041,6 +2136,7 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) + u8 index_frontend; + u16 lock = 0, lock_slave = 0; + ++ DibAcquireLock(&state->demod_lock); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + lock_slave |= dib9000_read_lock(state->fe[index_frontend]); + +@@ -2059,6 +2155,8 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) + if ((lock & 0x0008) || (lock_slave & 0x0008)) + *stat |= FE_HAS_LOCK; + ++ DibReleaseLock(&state->demod_lock); ++ + return 0; + } + +@@ -2066,10 +2164,14 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) + { + struct dib9000_state *state = fe->demodulator_priv; + u16 *c; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, + state->i2c_read_buffer, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); +@@ -2077,7 +2179,10 @@ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) + c = (u16 *)state->i2c_read_buffer; + + *ber = c[10] << 16 | c[11]; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) +@@ -2086,7 +2191,9 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + u8 index_frontend; + u16 *c = (u16 *)state->i2c_read_buffer; + u16 val; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + *strength = 0; + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { + state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); +@@ -2097,8 +2204,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + } + + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + +@@ -2107,7 +2216,10 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) + *strength = 65535; + else + *strength += val; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + static u32 dib9000_get_snr(struct dvb_frontend *fe) +@@ -2151,6 +2263,7 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) + u8 index_frontend; + u32 snr_master; + ++ DibAcquireLock(&state->demod_lock); + snr_master = dib9000_get_snr(fe); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) + snr_master += dib9000_get_snr(state->fe[index_frontend]); +@@ -2161,6 +2274,8 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) + } else + *snr = 0; + ++ DibReleaseLock(&state->demod_lock); ++ + return 0; + } + +@@ -2168,15 +2283,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) + { + struct dib9000_state *state = fe->demodulator_priv; + u16 *c = (u16 *)state->i2c_read_buffer; ++ int ret = 0; + ++ DibAcquireLock(&state->demod_lock); + DibAcquireLock(&state->platform.risc.mem_mbx_lock); +- if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) +- return -EIO; ++ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) { ++ ret = -EIO; ++ goto error; ++ } + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); + DibReleaseLock(&state->platform.risc.mem_mbx_lock); + + *unc = c[12]; +- return 0; ++ ++error: ++ DibReleaseLock(&state->demod_lock); ++ return ret; + } + + int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) +@@ -2322,6 +2444,10 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c + DibInitLock(&st->platform.risc.mbx_lock); + DibInitLock(&st->platform.risc.mem_lock); + DibInitLock(&st->platform.risc.mem_mbx_lock); ++ DibInitLock(&st->demod_lock); ++ st->get_frontend_internal = 0; ++ ++ st->pid_ctrl_index = -2; + + st->fe[0] = fe; + fe->demodulator_priv = st; +diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c +index dc5d17a..774d507 100644 +--- a/drivers/media/dvb/frontends/dibx000_common.c ++++ b/drivers/media/dvb/frontends/dibx000_common.c +@@ -1,4 +1,5 @@ + #include <linux/i2c.h> ++#include <linux/mutex.h> + + #include "dibx000_common.h" + +@@ -10,6 +11,13 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); + + static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) + { ++ int ret; ++ ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ + mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; + mst->i2c_write_buffer[1] = reg & 0xff; + mst->i2c_write_buffer[2] = (val >> 8) & 0xff; +@@ -21,11 +29,21 @@ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) + mst->msg[0].buf = mst->i2c_write_buffer; + mst->msg[0].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; ++ ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; ++ mutex_unlock(&mst->i2c_buffer_lock); ++ ++ return ret; + } + + static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) + { ++ u16 ret; ++ ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return 0; ++ } ++ + mst->i2c_write_buffer[0] = reg >> 8; + mst->i2c_write_buffer[1] = reg & 0xff; + +@@ -42,7 +60,10 @@ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) + if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) + dprintk("i2c read error on %d", reg); + +- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; ++ ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; ++ mutex_unlock(&mst->i2c_buffer_lock); ++ ++ return ret; + } + + static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) +@@ -257,6 +278,7 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) + { + struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); ++ int ret; + + if (num > 32) { + dprintk("%s: too much I2C message to be transmitted (%i).\ +@@ -264,10 +286,15 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + return -ENOMEM; + } + +- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); +- + dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); + ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ ++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); ++ + /* open the gate */ + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); + mst->msg[0].addr = mst->i2c_addr; +@@ -282,7 +309,11 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; + mst->msg[num + 1].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; ++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? ++ num : -EIO); ++ ++ mutex_unlock(&mst->i2c_buffer_lock); ++ return ret; + } + + static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { +@@ -294,6 +325,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) + { + struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); ++ int ret; + + if (num > 32) { + dprintk("%s: too much I2C message to be transmitted (%i).\ +@@ -301,10 +333,14 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + return -ENOMEM; + } + +- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); +- + dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); + ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); ++ + /* open the gate */ + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); + mst->msg[0].addr = mst->i2c_addr; +@@ -319,7 +355,10 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; + mst->msg[num + 1].len = 4; + +- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; ++ ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? ++ num : -EIO); ++ mutex_unlock(&mst->i2c_buffer_lock); ++ return ret; + } + + static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { +@@ -390,8 +429,18 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap, + int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, + struct i2c_adapter *i2c_adap, u8 i2c_addr) + { +- u8 tx[4]; +- struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 }; ++ int ret; ++ ++ mutex_init(&mst->i2c_buffer_lock); ++ if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { ++ dprintk("could not acquire lock"); ++ return -EINVAL; ++ } ++ memset(mst->msg, 0, sizeof(struct i2c_msg)); ++ mst->msg[0].addr = i2c_addr >> 1; ++ mst->msg[0].flags = 0; ++ mst->msg[0].buf = mst->i2c_write_buffer; ++ mst->msg[0].len = 4; + + mst->device_rev = device_rev; + mst->i2c_adap = i2c_adap; +@@ -431,9 +480,12 @@ int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, + "DiBX000: could not initialize the master i2c_adapter\n"); + + /* initialize the i2c-master by closing the gate */ +- dibx000_i2c_gate_ctrl(mst, tx, 0, 0); ++ dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0); ++ ++ ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1); ++ mutex_unlock(&mst->i2c_buffer_lock); + +- return i2c_transfer(i2c_adap, &m, 1) == 1; ++ return ret; + } + + EXPORT_SYMBOL(dibx000_init_i2c_master); +diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h +index f031165..5e01147 100644 +--- a/drivers/media/dvb/frontends/dibx000_common.h ++++ b/drivers/media/dvb/frontends/dibx000_common.h +@@ -33,6 +33,7 @@ struct dibx000_i2c_master { + struct i2c_msg msg[34]; + u8 i2c_write_buffer[8]; + u8 i2c_read_buffer[2]; ++ struct mutex i2c_buffer_lock; + }; + + extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, diff --git a/freed-ora/current/f16/media-dib0700-correct-error-message.patch b/freed-ora/current/f16/media-dib0700-correct-error-message.patch new file mode 100644 index 000000000..5e5d3bfa2 --- /dev/null +++ b/freed-ora/current/f16/media-dib0700-correct-error-message.patch @@ -0,0 +1,103 @@ +From: Olivier Grenie <olivier.grenie@dibcom.fr> +Date: Thu, 4 Aug 2011 16:10:03 +0000 (-0300) +Subject: [media] dib0700: correct error message +X-Git-Tag: next-20110927~67^2~4^2~223 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=680417bb318adc5f1f8f392730776176fbcdedd8 + +[media] dib0700: correct error message + +The goal of this patch is to correct a previous patch. In case of error, +the err() function should be used instead of dprintk() function. + +[mchehab@redhat.com: as I've replaced dprintk by deb_info, on the the + previous patch, to avoid breaking bisect, I had to fix a merge conflict + on this one] +Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr> +Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> +--- + +diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c +index a224e94..b693ed1 100644 +--- a/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -31,7 +31,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -117,7 +117,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -138,7 +138,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + + if (st->fw_version >= 0x10201) { + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -227,7 +227,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + } else { + /* Write request */ + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + st->buf[0] = REQUEST_NEW_I2C_WRITE; +@@ -273,7 +273,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -368,7 +368,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + int ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -400,7 +400,7 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + return -EINVAL; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -560,7 +560,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + } + + if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + +@@ -610,7 +610,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + int new_proto, ret; + + if (mutex_lock_interruptible(&d->usb_mutex) < 0) { +- deb_info("could not acquire lock"); ++ err("could not acquire lock"); + return 0; + } + diff --git a/freed-ora/current/f16/media-dib0700-protect-the-dib0700-buffer-access.patch b/freed-ora/current/f16/media-dib0700-protect-the-dib0700-buffer-access.patch new file mode 100644 index 000000000..109cab8ec --- /dev/null +++ b/freed-ora/current/f16/media-dib0700-protect-the-dib0700-buffer-access.patch @@ -0,0 +1,248 @@ +From: Olivier Grenie <olivier.grenie@dibcom.fr> +Date: Mon, 1 Aug 2011 15:45:58 +0000 (-0300) +Subject: [media] dib0700: protect the dib0700 buffer access +X-Git-Tag: next-20110927~67^2~4^2~224 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=bff469f4167fdabfe15294f375577d7eadbaa1bb + +[media] dib0700: protect the dib0700 buffer access + +This patch protects the common buffer access inside the dib0700 in order +to manage concurrent access. This protection is done using mutex. + +Cc: Mauro Carvalho Chehab <mchehab@redhat.com> +Cc: Florian Mickler <florian@mickler.org> +Cc: stable@kernel.org +Signed-off-by: Javier Marcet <javier@marcet.info> +Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr> +Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr> +[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info] +Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> +--- + +diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c +index 5eb91b4..a224e94 100644 +--- a/drivers/media/dvb/dvb-usb/dib0700_core.c ++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c +@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + struct dib0700_state *st = d->priv; + int ret; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), + REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, +@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + if (fwtype != NULL) + *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | + (st->buf[14] << 8) | st->buf[15]; ++ mutex_unlock(&d->usb_mutex); + return ret; + } + +@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen + int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) + { + struct dib0700_state *st = d->priv; +- s16 ret; ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + st->buf[0] = REQUEST_SET_GPIO; + st->buf[1] = gpio; +@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ + + ret = dib0700_ctrl_wr(d, st->buf, 3); + ++ mutex_unlock(&d->usb_mutex); + return ret; + } + +@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + int ret; + + if (st->fw_version >= 0x10201) { ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_USB_XFER_LEN; + st->buf[1] = (nb_ts_packets >> 8) & 0xff; + st->buf[2] = nb_ts_packets & 0xff; +@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) + deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); + + ret = dib0700_ctrl_wr(d, st->buf, 3); ++ mutex_unlock(&d->usb_mutex); + } else { + deb_info("this firmware does not allow to change the USB xfer len\n"); + ret = -EIO; +@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + + } else { + /* Write request */ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + st->buf[0] = REQUEST_NEW_I2C_WRITE; + st->buf[1] = msg[i].addr << 1; + st->buf[2] = (en_start << 7) | (en_stop << 6) | +@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + USB_TYPE_VENDOR | USB_DIR_OUT, + 0, 0, st->buf, msg[i].len + 4, + USB_CTRL_GET_TIMEOUT); ++ mutex_unlock(&d->usb_mutex); + if (result < 0) { + deb_info("i2c write error (status = %d)\n", result); + break; +@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + for (i = 0; i < num; i++) { + /* fill in the address */ +@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + break; + } + } ++ mutex_unlock(&d->usb_mutex); + mutex_unlock(&d->i2c_mutex); + + return i; +@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + u16 pll_loopdiv, u16 free_div, u16 dsuScaler) + { + struct dib0700_state *st = d->priv; +- s16 ret; ++ int ret; ++ ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } + + st->buf[0] = REQUEST_SET_CLOCK; + st->buf[1] = (en_pll << 7) | (pll_src << 6) | +@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + st->buf[9] = dsuScaler & 0xff; /* LSB */ + + ret = dib0700_ctrl_wr(d, st->buf, 10); ++ mutex_unlock(&d->usb_mutex); + + return ret; + } +@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + { + struct dib0700_state *st = d->priv; + u16 divider; ++ int ret; + + if (scl_kHz == 0) + return -EINVAL; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_I2C_PARAM; + divider = (u16) (30000 / scl_kHz); + st->buf[1] = 0; +@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) + deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", + (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | + st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); +- return dib0700_ctrl_wr(d, st->buf, 8); ++ ++ ret = dib0700_ctrl_wr(d, st->buf, 8); ++ mutex_unlock(&d->usb_mutex); ++ ++ return ret; + } + + +@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + } + } + ++ if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_ENABLE_VIDEO; + /* this bit gives a kind of command, + * rather than enabling something or not */ +@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + + deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); + +- return dib0700_ctrl_wr(adap->dev, st->buf, 4); ++ ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); ++ mutex_unlock(&adap->dev->usb_mutex); ++ ++ return ret; + } + + int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) +@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + struct dib0700_state *st = d->priv; + int new_proto, ret; + ++ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { ++ deb_info("could not acquire lock"); ++ return 0; ++ } ++ + st->buf[0] = REQUEST_SET_RC; + st->buf[1] = 0; + st->buf[2] = 0; +@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) + else if (rc_type == RC_TYPE_NEC) + new_proto = 0; + else if (rc_type == RC_TYPE_RC6) { +- if (st->fw_version < 0x10200) +- return -EINVAL; ++ if (st->fw_version < 0x10200) { ++ ret = -EINVAL; ++ goto out; ++ } + + new_proto = 2; +- } else +- return -EINVAL; ++ } else { ++ ret = -EINVAL; ++ goto out; ++ } + + st->buf[1] = new_proto; + + ret = dib0700_ctrl_wr(d, st->buf, 3); + if (ret < 0) { + err("ir protocol setup failed"); +- return ret; ++ goto out; + } + + d->props.rc.core.protocol = rc_type; + ++out: ++ mutex_unlock(&d->usb_mutex); + return ret; + } + diff --git a/freed-ora/current/f16/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch b/freed-ora/current/f16/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch new file mode 100644 index 000000000..9e810dba8 --- /dev/null +++ b/freed-ora/current/f16/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch @@ -0,0 +1,77 @@ +X-Spam-Checker-Version: SpamAssassin 3.4.0-r929098 (2010-03-30) on oss.sgi.com +X-Spam-Level: +X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,J_CHICKENPOX_64 + autolearn=no version=3.4.0-r929098 +Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) + by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id p9I1KBVD036341 + for <xfs@oss.sgi.com>; Mon, 17 Oct 2011 20:20:11 -0500 +X-ASG-Debug-ID: 1318901280-3911029d0000-NocioJ +X-Barracuda-URL: http://cuda.sgi.com:80/cgi-bin/mark.cgi +Received: from hades.usersys.redhat.com (localhost [127.0.0.1]) + by cuda.sgi.com (Spam Firewall) with ESMTP id B9D1DF75F0A + for <xfs@oss.sgi.com>; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) +Received: from hades.usersys.redhat.com ([187.60.101.4]) by cuda.sgi.com with ESMTP id 81CuyNdYBqrtvtnD for <xfs@oss.sgi.com>; Mon, 17 Oct 2011 18:28:01 -0700 (PDT) +Received: by hades.usersys.redhat.com (Postfix, from userid 500) + id 5B763E089B; Tue, 18 Oct 2011 02:18:59 -0200 (BRST) +From: Carlos Maiolino <cmaiolino@redhat.com> +To: xfs@oss.sgi.com +Cc: Carlos Maiolino <cmaiolino@redhat.com> +X-ASG-Orig-Subj: [PATCH] Fix possible memory corruption in xfs_readlink +Subject: [PATCH] Fix possible memory corruption in xfs_readlink +Date: Tue, 18 Oct 2011 02:18:58 -0200 +Message-Id: <1318911538-9174-1-git-send-email-cmaiolino@redhat.com> +X-Mailer: git-send-email 1.7.6.2 +X-Barracuda-Connect: UNKNOWN[187.60.101.4] +X-Barracuda-Start-Time: 1318901282 +X-Barracuda-Bayes: INNOCENT GLOBAL 0.0000 1.0000 -2.0210 +X-Barracuda-Virus-Scanned: by cuda.sgi.com at sgi.com +X-Barracuda-Spam-Score: -1.42 +X-Barracuda-Spam-Status: No, SCORE=-1.42 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests=BSF_SC5_MJ1963, RDNS_NONE +X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.77645 + Rule breakdown below + pts rule name description + ---- ---------------------- -------------------------------------------------- + 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS + 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 +X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com +X-Virus-Status: Clean + +Fixes a possible memory corruption when the link is larger than +MAXPATHLEN and XFS_DEBUG is not enabled. This also remove the +S_ISLNK assert, since the inode mode is checked previously in +xfs_readlink_by_handle() and via VFS. + +Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> +--- + fs/xfs/xfs_vnodeops.c | 11 ++++++++--- + 1 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c +index 51fc429..c3288be 100644 +--- a/fs/xfs/xfs_vnodeops.c ++++ b/fs/xfs/xfs_vnodeops.c +@@ -123,13 +123,18 @@ xfs_readlink( + + xfs_ilock(ip, XFS_ILOCK_SHARED); + +- ASSERT(S_ISLNK(ip->i_d.di_mode)); +- ASSERT(ip->i_d.di_size <= MAXPATHLEN); +- + pathlen = ip->i_d.di_size; + if (!pathlen) + goto out; + ++ if (pathlen > MAXPATHLEN) { ++ xfs_alert(mp, "%s: inode (%llu) symlink length (%d) too long", ++ __func__, (unsigned long long)ip->i_ino, pathlen); ++ ASSERT(0); ++ return XFS_ERROR(EFSCORRUPTED); ++ } ++ ++ + if (ip->i_df.if_flags & XFS_IFINLINE) { + memcpy(link, ip->i_df.if_u1.if_data, pathlen); + link[pathlen] = '\0'; +-- +1.7.6.2 + |