]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jan 2014 21:59:23 +0000 (13:59 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jan 2014 21:59:23 +0000 (13:59 -0800)
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

queue-3.12/aio-clean-up-and-fix-aio_setup_ring-page-mapping.patch [new file with mode: 0644]
queue-3.12/aio-migratepages-make-aio-migrate-pages-sane.patch [new file with mode: 0644]
queue-3.12/clocksource-dw_apb_timer_of-fix-read_sched_clock.patch [new file with mode: 0644]
queue-3.12/clocksource-dw_apb_timer_of-fix-support-for-dts-binding-snps-dw-apb-timer.patch [new file with mode: 0644]
queue-3.12/selinux-look-for-ipsec-labels-on-both-inbound-and-outbound-packets.patch [new file with mode: 0644]
queue-3.12/selinux-process-labeled-ipsec-tcp-syn-ack-packets-properly-in-selinux_ip_postroute.patch [new file with mode: 0644]
queue-3.12/series

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 (file)
index 0000000..7bcde98
--- /dev/null
@@ -0,0 +1,136 @@
+From 3dc9acb67600393249a795934ccdfc291a200e6b Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Fri, 20 Dec 2013 05:11:12 +0900
+Subject: aio: clean up and fix aio_setup_ring page mapping
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+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 <bcrl@kvack.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..62b0ae3
--- /dev/null
@@ -0,0 +1,178 @@
+From 8e321fefb0e60bae4e2a28d20fc4fa30758d27c6 Mon Sep 17 00:00:00 2001
+From: Benjamin LaHaise <bcrl@kvack.org>
+Date: Sat, 21 Dec 2013 17:56:08 -0500
+Subject: aio/migratepages: make aio migrate pages sane
+
+From: Benjamin LaHaise <bcrl@kvack.org>
+
+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 <bcrl@kvack.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..2f77092
--- /dev/null
@@ -0,0 +1,32 @@
+From 85dc6ee1237c8a4a7742e6abab96a20389b7d682 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@altera.com>
+Date: Tue, 10 Dec 2013 19:49:18 +0100
+Subject: clocksource: dw_apb_timer_of: Fix read_sched_clock
+
+From: Dinh Nguyen <dinguyen@altera.com>
+
+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 <dinguyen@altera.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..22b9c96
--- /dev/null
@@ -0,0 +1,40 @@
+From 9ab4727c1d41e50b67aecde4bf11879560a3ca78 Mon Sep 17 00:00:00 2001
+From: Dinh Nguyen <dinguyen@altera.com>
+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 <dinguyen@altera.com>
+
+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 <dinguyen@altera.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..7281098
--- /dev/null
@@ -0,0 +1,135 @@
+From 817eff718dca4e54d5721211ddde0914428fbb7c Mon Sep 17 00:00:00 2001
+From: Paul Moore <pmoore@redhat.com>
+Date: Tue, 10 Dec 2013 14:57:54 -0500
+Subject: selinux: look for IPsec labels on both inbound and outbound packets
+
+From: Paul Moore <pmoore@redhat.com>
+
+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 <Janak.Desai@gtri.gatech.edu>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..a4a0b5b
--- /dev/null
@@ -0,0 +1,90 @@
+From c0828e50485932b7e019df377a6b0a8d1ebd3080 Mon Sep 17 00:00:00 2001
+From: Paul Moore <pmoore@redhat.com>
+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 <pmoore@redhat.com>
+
+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 <Janak.Desai@gtri.gatech.edu>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
index c6209ff809d12fdbc50a8c6ebca9c9091e9f63e7..19123220b65906fcb5ff366146f941ddc827a7a4 100644 (file)
@@ -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