From: Greg Kroah-Hartman Date: Mon, 6 Jan 2014 21:59:23 +0000 (-0800) Subject: 3.12-stable patches X-Git-Tag: v3.4.76~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7fed07b304f3d420a165b84d368c3145a2ade9de;p=thirdparty%2Fkernel%2Fstable-queue.git 3.12-stable patches added patches: aio-clean-up-and-fix-aio_setup_ring-page-mapping.patch aio-migratepages-make-aio-migrate-pages-sane.patch clocksource-dw_apb_timer_of-fix-read_sched_clock.patch clocksource-dw_apb_timer_of-fix-support-for-dts-binding-snps-dw-apb-timer.patch selinux-look-for-ipsec-labels-on-both-inbound-and-outbound-packets.patch selinux-process-labeled-ipsec-tcp-syn-ack-packets-properly-in-selinux_ip_postroute.patch --- diff --git a/queue-3.12/aio-clean-up-and-fix-aio_setup_ring-page-mapping.patch b/queue-3.12/aio-clean-up-and-fix-aio_setup_ring-page-mapping.patch new file mode 100644 index 00000000000..7bcde98308c --- /dev/null +++ b/queue-3.12/aio-clean-up-and-fix-aio_setup_ring-page-mapping.patch @@ -0,0 +1,136 @@ +From 3dc9acb67600393249a795934ccdfc291a200e6b Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 20 Dec 2013 05:11:12 +0900 +Subject: aio: clean up and fix aio_setup_ring page mapping + +From: Linus Torvalds + +commit 3dc9acb67600393249a795934ccdfc291a200e6b upstream. + +Since commit 36bc08cc01709 ("fs/aio: Add support to aio ring pages +migration") the aio ring setup code has used a special per-ring backing +inode for the page allocations, rather than just using random anonymous +pages. + +However, rather than remembering the pages as it allocated them, it +would allocate the pages, insert them into the file mapping (dirty, so +that they couldn't be free'd), and then forget about them. And then to +look them up again, it would mmap the mapping, and then use +"get_user_pages()" to get back an array of the pages we just created. + +Now, not only is that incredibly inefficient, it also leaked all the +pages if the mmap failed (which could happen due to excessive number of +mappings, for example). + +So clean it all up, making it much more straightforward. Also remove +some left-overs of the previous (broken) mm_populate() usage that was +removed in commit d6c355c7dabc ("aio: fix race in ring buffer page +lookup introduced by page migration support") but left the pointless and +now misleading MAP_POPULATE flag around. + +Tested-and-acked-by: Benjamin LaHaise +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/aio.c | 58 +++++++++++++++++++++++----------------------------------- + 1 file changed, 23 insertions(+), 35 deletions(-) + +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -326,7 +326,7 @@ static int aio_setup_ring(struct kioctx + struct aio_ring *ring; + unsigned nr_events = ctx->max_reqs; + struct mm_struct *mm = current->mm; +- unsigned long size, populate; ++ unsigned long size, unused; + int nr_pages; + int i; + struct file *file; +@@ -347,6 +347,20 @@ static int aio_setup_ring(struct kioctx + return -EAGAIN; + } + ++ ctx->aio_ring_file = file; ++ nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) ++ / sizeof(struct io_event); ++ ++ ctx->ring_pages = ctx->internal_pages; ++ if (nr_pages > AIO_RING_PAGES) { ++ ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *), ++ GFP_KERNEL); ++ if (!ctx->ring_pages) { ++ put_aio_ring_file(ctx); ++ return -ENOMEM; ++ } ++ } ++ + for (i = 0; i < nr_pages; i++) { + struct page *page; + page = find_or_create_page(file->f_inode->i_mapping, +@@ -358,19 +372,14 @@ static int aio_setup_ring(struct kioctx + SetPageUptodate(page); + SetPageDirty(page); + unlock_page(page); ++ ++ ctx->ring_pages[i] = page; + } +- ctx->aio_ring_file = file; +- nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) +- / sizeof(struct io_event); ++ ctx->nr_pages = i; + +- ctx->ring_pages = ctx->internal_pages; +- if (nr_pages > AIO_RING_PAGES) { +- ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *), +- GFP_KERNEL); +- if (!ctx->ring_pages) { +- put_aio_ring_file(ctx); +- return -ENOMEM; +- } ++ if (unlikely(i != nr_pages)) { ++ aio_free_ring(ctx); ++ return -EAGAIN; + } + + ctx->mmap_size = nr_pages * PAGE_SIZE; +@@ -379,9 +388,9 @@ static int aio_setup_ring(struct kioctx + down_write(&mm->mmap_sem); + ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size, + PROT_READ | PROT_WRITE, +- MAP_SHARED | MAP_POPULATE, 0, &populate); ++ MAP_SHARED, 0, &unused); ++ up_write(&mm->mmap_sem); + if (IS_ERR((void *)ctx->mmap_base)) { +- up_write(&mm->mmap_sem); + ctx->mmap_size = 0; + aio_free_ring(ctx); + return -EAGAIN; +@@ -389,27 +398,6 @@ static int aio_setup_ring(struct kioctx + + pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base); + +- /* We must do this while still holding mmap_sem for write, as we +- * need to be protected against userspace attempting to mremap() +- * or munmap() the ring buffer. +- */ +- ctx->nr_pages = get_user_pages(current, mm, ctx->mmap_base, nr_pages, +- 1, 0, ctx->ring_pages, NULL); +- +- /* Dropping the reference here is safe as the page cache will hold +- * onto the pages for us. It is also required so that page migration +- * can unmap the pages and get the right reference count. +- */ +- for (i = 0; i < ctx->nr_pages; i++) +- put_page(ctx->ring_pages[i]); +- +- up_write(&mm->mmap_sem); +- +- if (unlikely(ctx->nr_pages != nr_pages)) { +- aio_free_ring(ctx); +- return -EAGAIN; +- } +- + ctx->user_id = ctx->mmap_base; + ctx->nr_events = nr_events; /* trusted copy */ + diff --git a/queue-3.12/aio-migratepages-make-aio-migrate-pages-sane.patch b/queue-3.12/aio-migratepages-make-aio-migrate-pages-sane.patch new file mode 100644 index 00000000000..62b0ae33746 --- /dev/null +++ b/queue-3.12/aio-migratepages-make-aio-migrate-pages-sane.patch @@ -0,0 +1,178 @@ +From 8e321fefb0e60bae4e2a28d20fc4fa30758d27c6 Mon Sep 17 00:00:00 2001 +From: Benjamin LaHaise +Date: Sat, 21 Dec 2013 17:56:08 -0500 +Subject: aio/migratepages: make aio migrate pages sane + +From: Benjamin LaHaise + +commit 8e321fefb0e60bae4e2a28d20fc4fa30758d27c6 upstream. + +The arbitrary restriction on page counts offered by the core +migrate_page_move_mapping() code results in rather suspicious looking +fiddling with page reference counts in the aio_migratepage() operation. +To fix this, make migrate_page_move_mapping() take an extra_count parameter +that allows aio to tell the code about its own reference count on the page +being migrated. + +While cleaning up aio_migratepage(), make it validate that the old page +being passed in is actually what aio_migratepage() expects to prevent +misbehaviour in the case of races. + +Signed-off-by: Benjamin LaHaise +Signed-off-by: Greg Kroah-Hartman + +--- + fs/aio.c | 52 ++++++++++++++++++++++++++++++++++++++++-------- + include/linux/migrate.h | 3 +- + mm/migrate.c | 13 ++++++------ + 3 files changed, 53 insertions(+), 15 deletions(-) + +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -244,9 +244,14 @@ static void aio_free_ring(struct kioctx + int i; + + for (i = 0; i < ctx->nr_pages; i++) { ++ struct page *page; + pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i, + page_count(ctx->ring_pages[i])); +- put_page(ctx->ring_pages[i]); ++ page = ctx->ring_pages[i]; ++ if (!page) ++ continue; ++ ctx->ring_pages[i] = NULL; ++ put_page(page); + } + + put_aio_ring_file(ctx); +@@ -280,18 +285,38 @@ static int aio_migratepage(struct addres + unsigned long flags; + int rc; + ++ rc = 0; ++ ++ /* Make sure the old page hasn't already been changed */ ++ spin_lock(&mapping->private_lock); ++ ctx = mapping->private_data; ++ if (ctx) { ++ pgoff_t idx; ++ spin_lock_irqsave(&ctx->completion_lock, flags); ++ idx = old->index; ++ if (idx < (pgoff_t)ctx->nr_pages) { ++ if (ctx->ring_pages[idx] != old) ++ rc = -EAGAIN; ++ } else ++ rc = -EINVAL; ++ spin_unlock_irqrestore(&ctx->completion_lock, flags); ++ } else ++ rc = -EINVAL; ++ spin_unlock(&mapping->private_lock); ++ ++ if (rc != 0) ++ return rc; ++ + /* Writeback must be complete */ + BUG_ON(PageWriteback(old)); +- put_page(old); ++ get_page(new); + +- rc = migrate_page_move_mapping(mapping, new, old, NULL, mode); ++ rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1); + if (rc != MIGRATEPAGE_SUCCESS) { +- get_page(old); ++ put_page(new); + return rc; + } + +- get_page(new); +- + /* We can potentially race against kioctx teardown here. Use the + * address_space's private data lock to protect the mapping's + * private_data. +@@ -303,13 +328,24 @@ static int aio_migratepage(struct addres + spin_lock_irqsave(&ctx->completion_lock, flags); + migrate_page_copy(new, old); + idx = old->index; +- if (idx < (pgoff_t)ctx->nr_pages) +- ctx->ring_pages[idx] = new; ++ if (idx < (pgoff_t)ctx->nr_pages) { ++ /* And only do the move if things haven't changed */ ++ if (ctx->ring_pages[idx] == old) ++ ctx->ring_pages[idx] = new; ++ else ++ rc = -EAGAIN; ++ } else ++ rc = -EINVAL; + spin_unlock_irqrestore(&ctx->completion_lock, flags); + } else + rc = -EBUSY; + spin_unlock(&mapping->private_lock); + ++ if (rc == MIGRATEPAGE_SUCCESS) ++ put_page(old); ++ else ++ put_page(new); ++ + return rc; + } + #endif +--- a/include/linux/migrate.h ++++ b/include/linux/migrate.h +@@ -55,7 +55,8 @@ extern int migrate_huge_page_move_mappin + struct page *newpage, struct page *page); + extern int migrate_page_move_mapping(struct address_space *mapping, + struct page *newpage, struct page *page, +- struct buffer_head *head, enum migrate_mode mode); ++ struct buffer_head *head, enum migrate_mode mode, ++ int extra_count); + #else + + static inline void putback_lru_pages(struct list_head *l) {} +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -315,14 +315,15 @@ static inline bool buffer_migrate_lock_b + */ + int migrate_page_move_mapping(struct address_space *mapping, + struct page *newpage, struct page *page, +- struct buffer_head *head, enum migrate_mode mode) ++ struct buffer_head *head, enum migrate_mode mode, ++ int extra_count) + { +- int expected_count = 0; ++ int expected_count = 1 + extra_count; + void **pslot; + + if (!mapping) { + /* Anonymous page without mapping */ +- if (page_count(page) != 1) ++ if (page_count(page) != expected_count) + return -EAGAIN; + return MIGRATEPAGE_SUCCESS; + } +@@ -332,7 +333,7 @@ int migrate_page_move_mapping(struct add + pslot = radix_tree_lookup_slot(&mapping->page_tree, + page_index(page)); + +- expected_count = 2 + page_has_private(page); ++ expected_count += 1 + page_has_private(page); + if (page_count(page) != expected_count || + radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) { + spin_unlock_irq(&mapping->tree_lock); +@@ -525,7 +526,7 @@ int migrate_page(struct address_space *m + + BUG_ON(PageWriteback(page)); /* Writeback must be complete */ + +- rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode); ++ rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0); + + if (rc != MIGRATEPAGE_SUCCESS) + return rc; +@@ -552,7 +553,7 @@ int buffer_migrate_page(struct address_s + + head = page_buffers(page); + +- rc = migrate_page_move_mapping(mapping, newpage, page, head, mode); ++ rc = migrate_page_move_mapping(mapping, newpage, page, head, mode, 0); + + if (rc != MIGRATEPAGE_SUCCESS) + return rc; diff --git a/queue-3.12/clocksource-dw_apb_timer_of-fix-read_sched_clock.patch b/queue-3.12/clocksource-dw_apb_timer_of-fix-read_sched_clock.patch new file mode 100644 index 00000000000..2f770924b46 --- /dev/null +++ b/queue-3.12/clocksource-dw_apb_timer_of-fix-read_sched_clock.patch @@ -0,0 +1,32 @@ +From 85dc6ee1237c8a4a7742e6abab96a20389b7d682 Mon Sep 17 00:00:00 2001 +From: Dinh Nguyen +Date: Tue, 10 Dec 2013 19:49:18 +0100 +Subject: clocksource: dw_apb_timer_of: Fix read_sched_clock + +From: Dinh Nguyen + +commit 85dc6ee1237c8a4a7742e6abab96a20389b7d682 upstream. + +The read_sched_clock should return the ~value because the clock is a +countdown implementation. read_sched_clock() should be the same as + __apbt_read_clocksource(). + +Signed-off-by: Dinh Nguyen +Signed-off-by: Daniel Lezcano +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/clocksource/dw_apb_timer_of.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clocksource/dw_apb_timer_of.c ++++ b/drivers/clocksource/dw_apb_timer_of.c +@@ -108,7 +108,7 @@ static void add_clocksource(struct devic + + static u32 read_sched_clock(void) + { +- return __raw_readl(sched_io_base); ++ return ~__raw_readl(sched_io_base); + } + + static const struct of_device_id sptimer_ids[] __initconst = { diff --git a/queue-3.12/clocksource-dw_apb_timer_of-fix-support-for-dts-binding-snps-dw-apb-timer.patch b/queue-3.12/clocksource-dw_apb_timer_of-fix-support-for-dts-binding-snps-dw-apb-timer.patch new file mode 100644 index 00000000000..22b9c960e01 --- /dev/null +++ b/queue-3.12/clocksource-dw_apb_timer_of-fix-support-for-dts-binding-snps-dw-apb-timer.patch @@ -0,0 +1,40 @@ +From 9ab4727c1d41e50b67aecde4bf11879560a3ca78 Mon Sep 17 00:00:00 2001 +From: Dinh Nguyen +Date: Tue, 10 Dec 2013 19:49:18 +0100 +Subject: clocksource: dw_apb_timer_of: Fix support for dts binding "snps,dw-apb-timer" + +From: Dinh Nguyen + +commit 9ab4727c1d41e50b67aecde4bf11879560a3ca78 upstream. + +In commit 620f5e1cbf (dts: Rename DW APB timer compatible strings), both +"snps,dw-apb-timer-sp" and "snps,dw-apb-timer-osc" were deprecated in place +of "snps,dw-apb-timer". But the driver also needs to be udpated in order to +support this new binding "snps,dw-apb-timer". + +Signed-off-by: Dinh Nguyen +Signed-off-by: Daniel Lezcano +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/clocksource/dw_apb_timer_of.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/clocksource/dw_apb_timer_of.c ++++ b/drivers/clocksource/dw_apb_timer_of.c +@@ -113,7 +113,6 @@ static u32 read_sched_clock(void) + + static const struct of_device_id sptimer_ids[] __initconst = { + { .compatible = "picochip,pc3x2-rtc" }, +- { .compatible = "snps,dw-apb-timer-sp" }, + { /* Sentinel */ }, + }; + +@@ -153,4 +152,6 @@ static void __init dw_apb_timer_init(str + num_called++; + } + CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init); +-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init); ++CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init); ++CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init); ++CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init); diff --git a/queue-3.12/selinux-look-for-ipsec-labels-on-both-inbound-and-outbound-packets.patch b/queue-3.12/selinux-look-for-ipsec-labels-on-both-inbound-and-outbound-packets.patch new file mode 100644 index 00000000000..72810989628 --- /dev/null +++ b/queue-3.12/selinux-look-for-ipsec-labels-on-both-inbound-and-outbound-packets.patch @@ -0,0 +1,135 @@ +From 817eff718dca4e54d5721211ddde0914428fbb7c Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Tue, 10 Dec 2013 14:57:54 -0500 +Subject: selinux: look for IPsec labels on both inbound and outbound packets + +From: Paul Moore + +commit 817eff718dca4e54d5721211ddde0914428fbb7c upstream. + +Previously selinux_skb_peerlbl_sid() would only check for labeled +IPsec security labels on inbound packets, this patch enables it to +check both inbound and outbound traffic for labeled IPsec security +labels. + +Reported-by: Janak Desai +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman + +--- + security/selinux/hooks.c | 2 - + security/selinux/include/xfrm.h | 9 +++--- + security/selinux/xfrm.c | 53 +++++++++++++++++++++++++++++++--------- + 3 files changed, 48 insertions(+), 16 deletions(-) + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -3792,7 +3792,7 @@ static int selinux_skb_peerlbl_sid(struc + u32 nlbl_sid; + u32 nlbl_type; + +- selinux_skb_xfrm_sid(skb, &xfrm_sid); ++ selinux_xfrm_skb_sid(skb, &xfrm_sid); + selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); + + err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); +--- a/security/selinux/include/xfrm.h ++++ b/security/selinux/include/xfrm.h +@@ -47,6 +47,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, s + int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, + struct common_audit_data *ad, u8 proto); + int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); ++int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid); + + static inline void selinux_xfrm_notify_policyload(void) + { +@@ -85,12 +86,12 @@ static inline int selinux_xfrm_decode_se + static inline void selinux_xfrm_notify_policyload(void) + { + } +-#endif + +-static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) ++static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) + { +- int err = selinux_xfrm_decode_session(skb, sid, 0); +- BUG_ON(err); ++ *sid = SECSID_NULL; ++ return 0; + } ++#endif + + #endif /* _SELINUX_XFRM_H_ */ +--- a/security/selinux/xfrm.c ++++ b/security/selinux/xfrm.c +@@ -152,21 +152,13 @@ int selinux_xfrm_state_pol_flow_match(st + return rc; + } + +-/* +- * LSM hook implementation that checks and/or returns the xfrm sid for the +- * incoming packet. +- */ +- +-int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) ++static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb, ++ u32 *sid, int ckall) + { +- struct sec_path *sp; ++ struct sec_path *sp = skb->sp; + + *sid = SECSID_NULL; + +- if (skb == NULL) +- return 0; +- +- sp = skb->sp; + if (sp) { + int i, sid_set = 0; + +@@ -190,6 +182,45 @@ int selinux_xfrm_decode_session(struct s + return 0; + } + ++static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) ++{ ++ struct dst_entry *dst = skb_dst(skb); ++ struct xfrm_state *x; ++ ++ if (dst == NULL) ++ return SECSID_NULL; ++ x = dst->xfrm; ++ if (x == NULL || !selinux_authorizable_xfrm(x)) ++ return SECSID_NULL; ++ ++ return x->security->ctx_sid; ++} ++ ++/* ++ * LSM hook implementation that checks and/or returns the xfrm sid for the ++ * incoming packet. ++ */ ++ ++int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) ++{ ++ if (skb == NULL) { ++ *sid = SECSID_NULL; ++ return 0; ++ } ++ return selinux_xfrm_skb_sid_ingress(skb, sid, ckall); ++} ++ ++int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) ++{ ++ int rc; ++ ++ rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0); ++ if (rc == 0 && *sid == SECSID_NULL) ++ *sid = selinux_xfrm_skb_sid_egress(skb); ++ ++ return rc; ++} ++ + /* + * Security blob allocation for xfrm_policy and xfrm_state + * CTX does not have a meaningful value on input diff --git a/queue-3.12/selinux-process-labeled-ipsec-tcp-syn-ack-packets-properly-in-selinux_ip_postroute.patch b/queue-3.12/selinux-process-labeled-ipsec-tcp-syn-ack-packets-properly-in-selinux_ip_postroute.patch new file mode 100644 index 00000000000..a4a0b5bc145 --- /dev/null +++ b/queue-3.12/selinux-process-labeled-ipsec-tcp-syn-ack-packets-properly-in-selinux_ip_postroute.patch @@ -0,0 +1,90 @@ +From c0828e50485932b7e019df377a6b0a8d1ebd3080 Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Tue, 10 Dec 2013 14:58:01 -0500 +Subject: selinux: process labeled IPsec TCP SYN-ACK packets properly in selinux_ip_postroute() + +From: Paul Moore + +commit c0828e50485932b7e019df377a6b0a8d1ebd3080 upstream. + +Due to difficulty in arriving at the proper security label for +TCP SYN-ACK packets in selinux_ip_postroute(), we need to check packets +while/before they are undergoing XFRM transforms instead of waiting +until afterwards so that we can determine the correct security label. + +Reported-by: Janak Desai +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman + +--- + security/selinux/hooks.c | 43 ++++++++++++++++++++++++++++++++++++------- + 1 file changed, 36 insertions(+), 7 deletions(-) + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -4811,22 +4811,32 @@ static unsigned int selinux_ip_postroute + * as fast and as clean as possible. */ + if (!selinux_policycap_netpeer) + return selinux_ip_postroute_compat(skb, ifindex, family); ++ ++ secmark_active = selinux_secmark_enabled(); ++ peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); ++ if (!secmark_active && !peerlbl_active) ++ return NF_ACCEPT; ++ ++ sk = skb->sk; ++ + #ifdef CONFIG_XFRM + /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec + * packet transformation so allow the packet to pass without any checks + * since we'll have another chance to perform access control checks + * when the packet is on it's final way out. + * NOTE: there appear to be some IPv6 multicast cases where skb->dst +- * is NULL, in this case go ahead and apply access control. */ +- if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) ++ * is NULL, in this case go ahead and apply access control. ++ * is NULL, in this case go ahead and apply access control. ++ * NOTE: if this is a local socket (skb->sk != NULL) that is in the ++ * TCP listening state we cannot wait until the XFRM processing ++ * is done as we will miss out on the SA label if we do; ++ * unfortunately, this means more work, but it is only once per ++ * connection. */ ++ if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL && ++ !(sk != NULL && sk->sk_state == TCP_LISTEN)) + return NF_ACCEPT; + #endif +- secmark_active = selinux_secmark_enabled(); +- peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); +- if (!secmark_active && !peerlbl_active) +- return NF_ACCEPT; + +- sk = skb->sk; + if (sk == NULL) { + /* Without an associated socket the packet is either coming + * from the kernel or it is being forwarded; check the packet +@@ -4854,6 +4864,25 @@ static unsigned int selinux_ip_postroute + struct sk_security_struct *sksec = sk->sk_security; + if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) + return NF_DROP; ++ /* At this point, if the returned skb peerlbl is SECSID_NULL ++ * and the packet has been through at least one XFRM ++ * transformation then we must be dealing with the "final" ++ * form of labeled IPsec packet; since we've already applied ++ * all of our access controls on this packet we can safely ++ * pass the packet. */ ++ if (skb_sid == SECSID_NULL) { ++ switch (family) { ++ case PF_INET: ++ if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) ++ return NF_ACCEPT; ++ break; ++ case PF_INET6: ++ if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) ++ return NF_ACCEPT; ++ default: ++ return NF_DROP_ERR(-ECONNREFUSED); ++ } ++ } + if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) + return NF_DROP; + secmark_perm = PACKET__SEND; diff --git a/queue-3.12/series b/queue-3.12/series index c6209ff809d..19123220b65 100644 --- a/queue-3.12/series +++ b/queue-3.12/series @@ -134,3 +134,9 @@ sh-pfc-fix-pinmux_gpio-macro.patch gpio-twl4030-fix-regression-for-twl-gpio-led-output.patch gpio-msm-fix-irq-mask-unmask-by-writing-bits-instead-of-numbers.patch sh-always-link-in-helper-functions-extracted-from-libgcc.patch +selinux-look-for-ipsec-labels-on-both-inbound-and-outbound-packets.patch +selinux-process-labeled-ipsec-tcp-syn-ack-packets-properly-in-selinux_ip_postroute.patch +clocksource-dw_apb_timer_of-fix-read_sched_clock.patch +clocksource-dw_apb_timer_of-fix-support-for-dts-binding-snps-dw-apb-timer.patch +aio-clean-up-and-fix-aio_setup_ring-page-mapping.patch +aio-migratepages-make-aio-migrate-pages-sane.patch