summaryrefslogtreecommitdiffstats
path: root/freed-ora/current/f14
diff options
context:
space:
mode:
authorAlexandre Oliva <lxoliva@fsfla.org>2011-10-29 16:47:50 +0000
committerAlexandre Oliva <lxoliva@fsfla.org>2011-10-29 16:47:50 +0000
commit6d1d93d27d758f6fee24ff32c39ab17283f2da9e (patch)
tree7b5b43f13d1b6a3310570f0cf05c10e0bc2a647a /freed-ora/current/f14
parent4a6c13557770948ccfa33a8c3a79b77be797a9db (diff)
downloadlinux-libre-raptor-6d1d93d27d758f6fee24ff32c39ab17283f2da9e.tar.gz
linux-libre-raptor-6d1d93d27d758f6fee24ff32c39ab17283f2da9e.zip
2.6.35.14-103.fc14
Diffstat (limited to 'freed-ora/current/f14')
-rw-r--r--freed-ora/current/f14/crypto-ghash-Avoid-null-pointer-dereference-if-no-ke.patch105
-rw-r--r--freed-ora/current/f14/epoll-fix-spurious-lockdep-warnings.patch116
-rw-r--r--freed-ora/current/f14/epoll-limit-paths.patch465
-rw-r--r--freed-ora/current/f14/ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch103
-rw-r--r--freed-ora/current/f14/kernel.spec39
-rw-r--r--freed-ora/current/f14/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch43
6 files changed, 869 insertions, 2 deletions
diff --git a/freed-ora/current/f14/crypto-ghash-Avoid-null-pointer-dereference-if-no-ke.patch b/freed-ora/current/f14/crypto-ghash-Avoid-null-pointer-dereference-if-no-ke.patch
new file mode 100644
index 000000000..8c56d66b2
--- /dev/null
+++ b/freed-ora/current/f14/crypto-ghash-Avoid-null-pointer-dereference-if-no-ke.patch
@@ -0,0 +1,105 @@
+From 3e65dd9e26cf5ba791f44c5e15e29d07b84824aa Mon Sep 17 00:00:00 2001
+From: Nick Bowler <nbowler@elliptictech.com>
+Date: Thu, 20 Oct 2011 14:16:55 +0200
+Subject: [PATCH] crypto: ghash - Avoid null pointer dereference if no key is
+ set
+
+commit 7ed47b7d142ec99ad6880bbbec51e9f12b3af74c upstream.
+
+The ghash_update function passes a pointer to gf128mul_4k_lle which will
+be NULL if ghash_setkey is not called or if the most recent call to
+ghash_setkey failed to allocate memory. This causes an oops. Fix this
+up by returning an error code in the null case.
+
+This is trivially triggered from unprivileged userspace through the
+AF_ALG interface by simply writing to the socket without setting a key.
+
+The ghash_final function has a similar issue, but triggering it requires
+a memory allocation failure in ghash_setkey _after_ at least one
+successful call to ghash_update.
+
+ BUG: unable to handle kernel NULL pointer dereference at 00000670
+ IP: [<d88c92d4>] gf128mul_4k_lle+0x23/0x60 [gf128mul]
+ *pde = 00000000
+ Oops: 0000 [#1] PREEMPT SMP
+ Modules linked in: ghash_generic gf128mul algif_hash af_alg nfs lockd nfs_acl sunrpc bridge ipv6 stp llc
+
+ Pid: 1502, comm: hashatron Tainted: G W 3.1.0-rc9-00085-ge9308cf #32 Bochs Bochs
+ EIP: 0060:[<d88c92d4>] EFLAGS: 00000202 CPU: 0
+ EIP is at gf128mul_4k_lle+0x23/0x60 [gf128mul]
+ EAX: d69db1f0 EBX: d6b8ddac ECX: 00000004 EDX: 00000000
+ ESI: 00000670 EDI: d6b8ddac EBP: d6b8ddc8 ESP: d6b8dda4
+ DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
+ Process hashatron (pid: 1502, ti=d6b8c000 task=d6810000 task.ti=d6b8c000)
+ Stack:
+ 00000000 d69db1f0 00000163 00000000 d6b8ddc8 c101a520 d69db1f0 d52aa000
+ 00000ff0 d6b8dde8 d88d310f d6b8a3f8 d52aa000 00001000 d88d502c d6b8ddfc
+ 00001000 d6b8ddf4 c11676ed d69db1e8 d6b8de24 c11679ad d52aa000 00000000
+ Call Trace:
+ [<c101a520>] ? kmap_atomic_prot+0x37/0xa6
+ [<d88d310f>] ghash_update+0x85/0xbe [ghash_generic]
+ [<c11676ed>] crypto_shash_update+0x18/0x1b
+ [<c11679ad>] shash_ahash_update+0x22/0x36
+ [<c11679cc>] shash_async_update+0xb/0xd
+ [<d88ce0ba>] hash_sendpage+0xba/0xf2 [algif_hash]
+ [<c121b24c>] kernel_sendpage+0x39/0x4e
+ [<d88ce000>] ? 0xd88cdfff
+ [<c121b298>] sock_sendpage+0x37/0x3e
+ [<c121b261>] ? kernel_sendpage+0x4e/0x4e
+ [<c10b4dbc>] pipe_to_sendpage+0x56/0x61
+ [<c10b4e1f>] splice_from_pipe_feed+0x58/0xcd
+ [<c10b4d66>] ? splice_from_pipe_begin+0x10/0x10
+ [<c10b51f5>] __splice_from_pipe+0x36/0x55
+ [<c10b4d66>] ? splice_from_pipe_begin+0x10/0x10
+ [<c10b6383>] splice_from_pipe+0x51/0x64
+ [<c10b63c2>] ? default_file_splice_write+0x2c/0x2c
+ [<c10b63d5>] generic_splice_sendpage+0x13/0x15
+ [<c10b4d66>] ? splice_from_pipe_begin+0x10/0x10
+ [<c10b527f>] do_splice_from+0x5d/0x67
+ [<c10b6865>] sys_splice+0x2bf/0x363
+ [<c129373b>] ? sysenter_exit+0xf/0x16
+ [<c104dc1e>] ? trace_hardirqs_on_caller+0x10e/0x13f
+ [<c129370c>] sysenter_do_call+0x12/0x32
+ Code: 83 c4 0c 5b 5e 5f c9 c3 55 b9 04 00 00 00 89 e5 57 8d 7d e4 56 53 8d 5d e4 83 ec 18 89 45 e0 89 55 dc 0f b6 70 0f c1 e6 04 01 d6 <f3> a5 be 0f 00 00 00 4e 89 d8 e8 48 ff ff ff 8b 45 e0 89 da 0f
+ EIP: [<d88c92d4>] gf128mul_4k_lle+0x23/0x60 [gf128mul] SS:ESP 0068:d6b8dda4
+ CR2: 0000000000000670
+ ---[ end trace 4eaa2a86a8e2da24 ]---
+ note: hashatron[1502] exited with preempt_count 1
+ BUG: scheduling while atomic: hashatron/1502/0x10000002
+ INFO: lockdep is turned off.
+ [...]
+
+Signed-off-by: Nick Bowler <nbowler@elliptictech.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ crypto/ghash-generic.c | 6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c
+index be44256..7835b8f 100644
+--- a/crypto/ghash-generic.c
++++ b/crypto/ghash-generic.c
+@@ -67,6 +67,9 @@ static int ghash_update(struct shash_desc *desc,
+ struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
+ u8 *dst = dctx->buffer;
+
++ if (!ctx->gf128)
++ return -ENOKEY;
++
+ if (dctx->bytes) {
+ int n = min(srclen, dctx->bytes);
+ u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
+@@ -119,6 +122,9 @@ static int ghash_final(struct shash_desc *desc, u8 *dst)
+ struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
+ u8 *buf = dctx->buffer;
+
++ if (!ctx->gf128)
++ return -ENOKEY;
++
+ ghash_flush(ctx, dctx);
+ memcpy(dst, buf, GHASH_BLOCK_SIZE);
+
+--
+1.7.6.4
+
diff --git a/freed-ora/current/f14/epoll-fix-spurious-lockdep-warnings.patch b/freed-ora/current/f14/epoll-fix-spurious-lockdep-warnings.patch
new file mode 100644
index 000000000..131796af8
--- /dev/null
+++ b/freed-ora/current/f14/epoll-fix-spurious-lockdep-warnings.patch
@@ -0,0 +1,116 @@
+epoll can acquire multiple ep->mutex on multiple "struct eventpoll"s
+at once in the case where one epoll fd is monitoring another epoll
+fd. This is perfectly OK, since we're careful about the lock ordering,
+but causes spurious lockdep warnings. Annotate the recursion using
+mutex_lock_nested, and add a comment explaining the nesting rules for
+good measure.
+
+Reported-by: Paul Bolle <pebolle@tiscali.nl>
+Signed-off-by: Nelson Elhage <nelhage@nelhage.com>
+---
+ I've tested this on a synthetic epoll test case, that just adds e1 to
+ e2 and then does an epoll_wait(). I verified that it caused lockdep
+ problems on 3.0 and that this patch fixed it, but I haven't done more
+ extensive testing. Paul, are you able to test systemd against this?
+
+ fs/eventpoll.c | 25 ++++++++++++++++++-------
+ 1 files changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index f9cfd16..0cb7bc6 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -76,6 +76,15 @@
+ * Events that require holding "epmutex" are very rare, while for
+ * normal operations the epoll private "ep->mtx" will guarantee
+ * a better scalability.
++ * It is possible to acquire multiple "ep->mtx"es at once in the case
++ * when one epoll fd is added to another. In this case, we always
++ * acquire the locks in the order of nesting (i.e. after epoll_ctl(e1,
++ * EPOLL_CTL_ADD, e2), e1->mtx will always be acquired before
++ * e2->mtx). Since we disallow cycles of epoll file descriptors, this
++ * ensures that the mutexes are well-ordered. In order to communicate
++ * this nesting to lockdep, when walking a tree of epoll file
++ * descriptors, we use the current recursion depth as the lockdep
++ * subkey.
+ */
+
+ /* Epoll private bits inside the event mask */
+@@ -464,13 +473,15 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
+ * @ep: Pointer to the epoll private data structure.
+ * @sproc: Pointer to the scan callback.
+ * @priv: Private opaque data passed to the @sproc callback.
++ * @depth: The current depth of recursive f_op->poll calls.
+ *
+ * Returns: The same integer error code returned by the @sproc callback.
+ */
+ static int ep_scan_ready_list(struct eventpoll *ep,
+ int (*sproc)(struct eventpoll *,
+ struct list_head *, void *),
+- void *priv)
++ void *priv,
++ int depth)
+ {
+ int error, pwake = 0;
+ unsigned long flags;
+@@ -481,7 +492,7 @@ static int ep_scan_ready_list(struct eventpoll *ep,
+ * We need to lock this because we could be hit by
+ * eventpoll_release_file() and epoll_ctl().
+ */
+- mutex_lock(&ep->mtx);
++ mutex_lock_nested(&ep->mtx, depth);
+
+ /*
+ * Steal the ready list, and re-init the original one to the
+@@ -670,7 +681,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
+
+ static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests)
+ {
+- return ep_scan_ready_list(priv, ep_read_events_proc, NULL);
++ return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1);
+ }
+
+ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
+@@ -737,7 +748,7 @@ void eventpoll_release_file(struct file *file)
+
+ ep = epi->ep;
+ list_del_init(&epi->fllink);
+- mutex_lock(&ep->mtx);
++ mutex_lock_nested(&ep->mtx, 0);
+ ep_remove(ep, epi);
+ mutex_unlock(&ep->mtx);
+ }
+@@ -1134,7 +1145,7 @@ static int ep_send_events(struct eventpoll *ep,
+ esed.maxevents = maxevents;
+ esed.events = events;
+
+- return ep_scan_ready_list(ep, ep_send_events_proc, &esed);
++ return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0);
+ }
+
+ static inline struct timespec ep_set_mstimeout(long ms)
+@@ -1267,7 +1278,7 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
+ struct rb_node *rbp;
+ struct epitem *epi;
+
+- mutex_lock(&ep->mtx);
++ mutex_lock_nested(&ep->mtx, call_nests + 1);
+ 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))) {
+@@ -1409,7 +1420,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
+ }
+
+
+- mutex_lock(&ep->mtx);
++ mutex_lock_nested(&ep->mtx, 0);
+
+ /*
+ * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
+--
+1.7.4.1
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file
diff --git a/freed-ora/current/f14/epoll-limit-paths.patch b/freed-ora/current/f14/epoll-limit-paths.patch
new file mode 100644
index 000000000..440db27b9
--- /dev/null
+++ b/freed-ora/current/f14/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/f14/ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch b/freed-ora/current/f14/ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch
new file mode 100644
index 000000000..5d6a20f79
--- /dev/null
+++ b/freed-ora/current/f14/ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch
@@ -0,0 +1,103 @@
+From jasowang@redhat.com Sat Oct 8 20:56:54 2011
+Subject: ipv6: fix NULL dereference in udp6_ufo_fragment()
+To: gregkh@suse.de, stable@kernel.org
+From: Jason Wang <jasowang@redhat.com>
+Cc: davem@davemloft.net, eric.dumazet@gmail.com
+Date: Sun, 09 Oct 2011 10:56:44 +0800
+Message-ID: <20111009025644.9437.53281.stgit@dhcp-8-146.nay.redhat.com>
+
+From: Jason Wang <jasowang@redhat.com>
+
+This patch fixes the issue caused by ef81bb40bf15f350fe865f31fa42f1082772a576
+which is a backport of upstream 87c48fa3b4630905f98268dde838ee43626a060c. The
+problem does not exist in upstream.
+
+We do not check whether route is attached before trying to assign ip
+identification through route dest which lead NULL pointer dereference. This
+happens when host bridge transmit a packet from guest.
+
+This patch changes ipv6_select_ident() to accept in6_addr as its paramter and
+fix the issue by using the destination address in ipv6 header when no route is
+attached.
+
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ include/net/ipv6.h | 2 +-
+ net/ipv6/ip6_output.c | 10 +++++-----
+ net/ipv6/udp.c | 4 +++-
+ 3 files changed, 9 insertions(+), 7 deletions(-)
+
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -463,7 +463,7 @@ static inline int ipv6_addr_diff(const s
+ return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
+ }
+
+-extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
++extern void ipv6_select_ident(struct frag_hdr *fhdr, struct in6_addr *addr);
+
+ /*
+ * Prototypes exported by ipv6
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -620,9 +620,9 @@ static u32 __ipv6_select_ident(const str
+ return hash + newid;
+ }
+
+-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
++void ipv6_select_ident(struct frag_hdr *fhdr, struct in6_addr *addr)
+ {
+- fhdr->identification = htonl(__ipv6_select_ident(&rt->rt6i_dst.addr));
++ fhdr->identification = htonl(__ipv6_select_ident(addr));
+ }
+
+ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
+@@ -709,7 +709,7 @@ int ip6_fragment(struct sk_buff *skb, in
+ skb_reset_network_header(skb);
+ memcpy(skb_network_header(skb), tmp_hdr, hlen);
+
+- ipv6_select_ident(fh, rt);
++ ipv6_select_ident(fh, &rt->rt6i_dst.addr);
+ fh->nexthdr = nexthdr;
+ fh->reserved = 0;
+ fh->frag_off = htons(IP6_MF);
+@@ -855,7 +855,7 @@ slow_path:
+ fh->nexthdr = nexthdr;
+ fh->reserved = 0;
+ if (!frag_id) {
+- ipv6_select_ident(fh, rt);
++ ipv6_select_ident(fh, &rt->rt6i_dst.addr);
+ frag_id = fh->identification;
+ } else
+ fh->identification = frag_id;
+@@ -1146,7 +1146,7 @@ static inline int ip6_ufo_append_data(st
+ skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
+ sizeof(struct frag_hdr)) & ~7;
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+- ipv6_select_ident(&fhdr, rt);
++ ipv6_select_ident(&fhdr, &rt->rt6i_dst.addr);
+ skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -1309,6 +1309,7 @@ static struct sk_buff *udp6_ufo_fragment
+ u8 frag_hdr_sz = sizeof(struct frag_hdr);
+ int offset;
+ __wsum csum;
++ struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
+
+ mss = skb_shinfo(skb)->gso_size;
+ if (unlikely(skb->len <= mss))
+@@ -1359,7 +1360,8 @@ static struct sk_buff *udp6_ufo_fragment
+ fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
+ fptr->nexthdr = nexthdr;
+ fptr->reserved = 0;
+- ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
++ ipv6_select_ident(fptr,
++ rt ? &rt->rt6i_dst.addr : &ipv6_hdr(skb)->daddr);
+
+ /* Fragment the skb. ipv6 header and the remaining fields of the
+ * fragment header are updated in ipv6_gso_segment()
diff --git a/freed-ora/current/f14/kernel.spec b/freed-ora/current/f14/kernel.spec
index 8807e8022..3fa677386 100644
--- a/freed-ora/current/f14/kernel.spec
+++ b/freed-ora/current/f14/kernel.spec
@@ -48,7 +48,7 @@ Summary: The Linux kernel
# reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec).
# scripts/rebase.sh should be made to do that for you, actually.
#
-%global baserelease 100
+%global baserelease 103
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@@ -878,6 +878,8 @@ Patch14012: bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch
Patch14013: nl80211-fix-overflow-in-ssid_len.patch.patch
# CVE-2011-2699
Patch14014: ipv6-make-fragment-identifications-less-predictable.patch
+# fix possible null dereference in above fix
+Patch14015: ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch
# RHBZ #699684
Patch14020: x86-mm-fix-pgd_lock-deadlock.patch
@@ -927,6 +929,16 @@ Patch14063: 0002-USB-EHCI-go-back-to-using-the-system-clock-for-QH-un.patch
#rhbz 747948
Patch14064: ext4-fix-BUG_ON-in-ext4_ext_insert_extent.patch
+#rhbz 748668
+Patch14065: epoll-fix-spurious-lockdep-warnings.patch
+Patch14066: epoll-limit-paths.patch
+
+#rhbz 749166
+Patch21050: xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch
+
+#rhbz 749484
+Patch21060: crypto-ghash-Avoid-null-pointer-dereference-if-no-ke.patch
+
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1420,6 +1432,7 @@ ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch
ApplyPatch ext4-always-journal-quota-file-modifications.patch
# xfs
+ApplyPatch xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch
# btrfs
@@ -1709,6 +1722,7 @@ ApplyPatch bluetooth-prevent-buffer-overflow-in-l2cap-config-request.patch
ApplyPatch nl80211-fix-overflow-in-ssid_len.patch.patch
# CVE-2011-2699
ApplyPatch ipv6-make-fragment-identifications-less-predictable.patch
+ApplyPatch ipv6-fix-null-dereference-in-udp6_ufo_fragment.patch
# RHBZ #699684
ApplyPatch x86-mm-fix-pgd_lock-deadlock.patch
@@ -1758,6 +1772,13 @@ ApplyPatch 0002-USB-EHCI-go-back-to-using-the-system-clock-for-QH-un.patch
#rhbz 747948
ApplyPatch ext4-fix-BUG_ON-in-ext4_ext_insert_extent.patch
+#rhbz 748668
+ApplyPatch epoll-fix-spurious-lockdep-warnings.patch
+ApplyPatch epoll-limit-paths.patch
+
+#rhbz 749484
+ApplyPatch crypto-ghash-Avoid-null-pointer-dereference-if-no-ke.patch
+
# END OF PATCH APPLICATIONS
# Linux-libre-specific, added by Koko's request for BLAG.
@@ -2347,7 +2368,21 @@ fi
# and build.
%changelog
-* Fri Oct 21 2011 Dave Jones <davej@redhat.com>
+* Thu Oct 27 2011 Josh Boyer <jwboyer@redhat.com> 2.6.35.14-103
+- Fix backport of xfs patch
+- CVE-2011-4081 crypto: ghash: null pointer deref if no key is set (rhbz 749484)
+
+* Wed Oct 26 2011 Josh Boyer <jwboyer@redhat.com>
+- CVE-2011-4077: Add patch to fix XFS memory corruption (rhbz 749166)
+
+* Tue Oct 25 2011 Josh Boyer <jwboyer@redhat.com>
+- CVE-2011-1083: excessive in kernel CPU consumption when creating large nested epoll structures (rhbz 748668)
+
+* Tue Oct 25 2011 Chuck Ebbert <cebbert@redhat.com>
+- Fix NULL dereference in udp6_ufo_fragment(), caused by
+ fix for CVE-2011-2699.
+
+* Fri Oct 21 2011 Dave Jones <davej@redhat.com> 2.6.35.14-100
- Lower severity of Radeon lockup messages.
* Fri Oct 20 2011 Josh Boyer <jwboyer@redhat.com>
diff --git a/freed-ora/current/f14/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch b/freed-ora/current/f14/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch
new file mode 100644
index 000000000..f22cd4c6d
--- /dev/null
+++ b/freed-ora/current/f14/xfs-Fix-possible-memory-corruption-in-xfs_readlink.patch
@@ -0,0 +1,43 @@
+From fbf6404575f42b383d9607321bd129f0e28fc0d7 Mon Sep 17 00:00:00 2001
+From: Carlos Maiolino <cmaiolino@redhat.com>
+Date: Tue, 18 Oct 2011 02:18:58 -0200
+Subject: [PATCH] Fix possible memory corruption in xfs_readlink
+
+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 | 10 +++++++---
+ 1 files changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
+index c164683..529d983 100644
+--- a/fs/xfs/xfs_vnodeops.c
++++ b/fs/xfs/xfs_vnodeops.c
+@@ -564,13 +564,17 @@ xfs_readlink(
+
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
+
+- ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
+- ASSERT(ip->i_d.di_size <= MAXPATHLEN);
+-
+ pathlen = ip->i_d.di_size;
+ if (!pathlen)
+ goto out;
+
++ if (pathlen > MAXPATHLEN) {
++ xfs_fs_cmn_err(CE_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.4
+
OpenPOWER on IntegriCloud