diff options
| author | Alexandre Oliva <lxoliva@fsfla.org> | 2011-10-29 16:47:50 +0000 |
|---|---|---|
| committer | Alexandre Oliva <lxoliva@fsfla.org> | 2011-10-29 16:47:50 +0000 |
| commit | 6d1d93d27d758f6fee24ff32c39ab17283f2da9e (patch) | |
| tree | 7b5b43f13d1b6a3310570f0cf05c10e0bc2a647a /freed-ora/current/f14 | |
| parent | 4a6c13557770948ccfa33a8c3a79b77be797a9db (diff) | |
| download | linux-libre-raptor-6d1d93d27d758f6fee24ff32c39ab17283f2da9e.tar.gz linux-libre-raptor-6d1d93d27d758f6fee24ff32c39ab17283f2da9e.zip | |
2.6.35.14-103.fc14
Diffstat (limited to 'freed-ora/current/f14')
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 + |

