Author: mpagano
Date: 2014-06-18 17:59:27 +0000 (Wed, 18 Jun 2014)
New Revision: 2844

Added:
   genpatches-2.6/trunk/3.10/1043_linux-3.10.44.patch
Modified:
   genpatches-2.6/trunk/3.10/0000_README
Log:
Linux patch 3.10.44

Modified: genpatches-2.6/trunk/3.10/0000_README
===================================================================
--- genpatches-2.6/trunk/3.10/0000_README       2014-06-18 15:46:37 UTC (rev 
2843)
+++ genpatches-2.6/trunk/3.10/0000_README       2014-06-18 17:59:27 UTC (rev 
2844)
@@ -214,6 +214,10 @@
 From:   http://www.kernel.org
 Desc:   Linux 3.10.43
 
+Patch:  1043_linux-3.10.44.patch
+From:   http://www.kernel.org
+Desc:   Linux 3.10.44
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

Added: genpatches-2.6/trunk/3.10/1043_linux-3.10.44.patch
===================================================================
--- genpatches-2.6/trunk/3.10/1043_linux-3.10.44.patch                          
(rev 0)
+++ genpatches-2.6/trunk/3.10/1043_linux-3.10.44.patch  2014-06-18 17:59:27 UTC 
(rev 2844)
@@ -0,0 +1,755 @@
+diff --git a/Makefile b/Makefile
+index 9cf513828341..e55476c4aef0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 3
+ PATCHLEVEL = 10
+-SUBLEVEL = 43
++SUBLEVEL = 44
+ EXTRAVERSION =
+ NAME = TOSSUG Baby Fish
+ 
+diff --git a/arch/arm/boot/dts/armada-xp-gp.dts 
b/arch/arm/boot/dts/armada-xp-gp.dts
+index 76db557adbe7..f97550420fcc 100644
+--- a/arch/arm/boot/dts/armada-xp-gp.dts
++++ b/arch/arm/boot/dts/armada-xp-gp.dts
+@@ -124,7 +124,7 @@
+                               /* Device Bus parameters are required */
+ 
+                               /* Read parameters */
+-                              devbus,bus-width    = <8>;
++                              devbus,bus-width    = <16>;
+                               devbus,turn-off-ps  = <60000>;
+                               devbus,badr-skew-ps = <0>;
+                               devbus,acc-first-ps = <124000>;
+diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts 
b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
+index fdea75c73411..9746d0e7fcb4 100644
+--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
++++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
+@@ -152,7 +152,7 @@
+                               /* Device Bus parameters are required */
+ 
+                               /* Read parameters */
+-                              devbus,bus-width    = <8>;
++                              devbus,bus-width    = <16>;
+                               devbus,turn-off-ps  = <60000>;
+                               devbus,badr-skew-ps = <0>;
+                               devbus,acc-first-ps = <124000>;
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 4942058402a4..b0d33d9533aa 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -444,10 +444,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9172 on 
some Gigabyte */
++      { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0),
++        .driver_data = board_ahci_yes_fbs },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
+         .driver_data = board_ahci_yes_fbs },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
+         .driver_data = board_ahci_yes_fbs },
++      { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642),
++        .driver_data = board_ahci_yes_fbs },
+ 
+       /* Promise */
+       { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },   /* PDC42819 */
+diff --git a/drivers/infiniband/ulp/isert/ib_isert.c 
b/drivers/infiniband/ulp/isert/ib_isert.c
+index bae20f8bb034..144999918022 100644
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -382,6 +382,14 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct 
rdma_cm_event *event)
+       struct ib_device *ib_dev = cma_id->device;
+       int ret = 0;
+ 
++      spin_lock_bh(&np->np_thread_lock);
++      if (!np->enabled) {
++              spin_unlock_bh(&np->np_thread_lock);
++              pr_debug("iscsi_np is not enabled, reject connect request\n");
++              return rdma_reject(cma_id, NULL, 0);
++      }
++      spin_unlock_bh(&np->np_thread_lock);
++
+       pr_debug("Entering isert_connect_request cma_id: %p, context: %p\n",
+                cma_id, cma_id->context);
+ 
+diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
+index 1bf3f8b5ce3a..06311c5ada36 100644
+--- a/drivers/misc/mei/hw-me.c
++++ b/drivers/misc/mei/hw-me.c
+@@ -183,6 +183,7 @@ static void mei_me_hw_reset(struct mei_device *dev, bool 
intr_enable)
+       else
+               hcsr &= ~H_IE;
+ 
++      dev->recvd_hw_ready = false;
+       mei_me_reg_write(hw, H_CSR, hcsr);
+ 
+       if (dev->dev_state == MEI_DEV_POWER_DOWN)
+@@ -233,10 +234,7 @@ static bool mei_me_hw_is_ready(struct mei_device *dev)
+ static int mei_me_hw_ready_wait(struct mei_device *dev)
+ {
+       int err;
+-      if (mei_me_hw_is_ready(dev))
+-              return 0;
+ 
+-      dev->recvd_hw_ready = false;
+       mutex_unlock(&dev->device_lock);
+       err = wait_event_interruptible_timeout(dev->wait_hw_ready,
+                       dev->recvd_hw_ready,
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c 
b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+index 1e6c594d6d04..58c18d3a4880 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+@@ -55,7 +55,6 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
+ 
+       cq->ring = ring;
+       cq->is_tx = mode;
+-      spin_lock_init(&cq->lock);
+ 
+       err = mlx4_alloc_hwq_res(mdev->dev, &cq->wqres,
+                               cq->buf_size, 2 * PAGE_SIZE);
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c 
b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+index 89c47ea84b50..063f3f4d4867 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+@@ -1190,15 +1190,11 @@ static void mlx4_en_netpoll(struct net_device *dev)
+ {
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct mlx4_en_cq *cq;
+-      unsigned long flags;
+       int i;
+ 
+       for (i = 0; i < priv->rx_ring_num; i++) {
+               cq = &priv->rx_cq[i];
+-              spin_lock_irqsave(&cq->lock, flags);
+-              napi_synchronize(&cq->napi);
+-              mlx4_en_process_rx_cq(dev, cq, 0);
+-              spin_unlock_irqrestore(&cq->lock, flags);
++              napi_schedule(&cq->napi);
+       }
+ }
+ #endif
+diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h 
b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+index b1d7657b2bf5..628e1f9355a8 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
++++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+@@ -299,7 +299,6 @@ struct mlx4_en_cq {
+       struct mlx4_cq          mcq;
+       struct mlx4_hwq_resources wqres;
+       int                     ring;
+-      spinlock_t              lock;
+       struct net_device      *dev;
+       struct napi_struct      napi;
+       int size;
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h 
b/drivers/scsi/megaraid/megaraid_sas.h
+index 684cc343cf09..b52121358385 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -1295,7 +1295,6 @@ struct megasas_instance {
+       u32 *reply_queue;
+       dma_addr_t reply_queue_h;
+ 
+-      unsigned long base_addr;
+       struct megasas_register_set __iomem *reg_set;
+ 
+       struct megasas_pd_list          pd_list[MEGASAS_MAX_PD];
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c 
b/drivers/scsi/megaraid/megaraid_sas_base.c
+index b3e5c1787876..4956c99ed90e 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -3461,6 +3461,7 @@ static int megasas_init_fw(struct megasas_instance 
*instance)
+       u32 max_sectors_1;
+       u32 max_sectors_2;
+       u32 tmp_sectors, msix_enable;
++      resource_size_t base_addr;
+       struct megasas_register_set __iomem *reg_set;
+       struct megasas_ctrl_info *ctrl_info;
+       unsigned long bar_list;
+@@ -3469,14 +3470,14 @@ static int megasas_init_fw(struct megasas_instance 
*instance)
+       /* Find first memory bar */
+       bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
+       instance->bar = find_first_bit(&bar_list, sizeof(unsigned long));
+-      instance->base_addr = pci_resource_start(instance->pdev, instance->bar);
+       if (pci_request_selected_regions(instance->pdev, instance->bar,
+                                        "megasas: LSI")) {
+               printk(KERN_DEBUG "megasas: IO memory region busy!\n");
+               return -EBUSY;
+       }
+ 
+-      instance->reg_set = ioremap_nocache(instance->base_addr, 8192);
++      base_addr = pci_resource_start(instance->pdev, instance->bar);
++      instance->reg_set = ioremap_nocache(base_addr, 8192);
+ 
+       if (!instance->reg_set) {
+               printk(KERN_DEBUG "megasas: Failed to map IO mem\n");
+diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
+index 58c479d13b57..68dbd88babbd 100644
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -460,6 +460,7 @@ int iscsit_del_np(struct iscsi_np *np)
+       spin_lock_bh(&np->np_thread_lock);
+       np->np_exports--;
+       if (np->np_exports) {
++              np->enabled = true;
+               spin_unlock_bh(&np->np_thread_lock);
+               return 0;
+       }
+diff --git a/drivers/target/iscsi/iscsi_target_core.h 
b/drivers/target/iscsi/iscsi_target_core.h
+index 8907dcdc0db9..e117870eb445 100644
+--- a/drivers/target/iscsi/iscsi_target_core.h
++++ b/drivers/target/iscsi/iscsi_target_core.h
+@@ -760,6 +760,7 @@ struct iscsi_np {
+       int                     np_ip_proto;
+       int                     np_sock_type;
+       enum np_thread_state_table np_thread_state;
++      bool                    enabled;
+       enum iscsi_timer_flags_table np_login_timer_flags;
+       u32                     np_exports;
+       enum np_flags_table     np_flags;
+diff --git a/drivers/target/iscsi/iscsi_target_login.c 
b/drivers/target/iscsi/iscsi_target_login.c
+index bc788c52b6cc..0d6c3dd25679 100644
+--- a/drivers/target/iscsi/iscsi_target_login.c
++++ b/drivers/target/iscsi/iscsi_target_login.c
+@@ -250,6 +250,28 @@ static void iscsi_login_set_conn_values(
+       mutex_unlock(&auth_id_lock);
+ }
+ 
++static __printf(2, 3) int iscsi_change_param_sprintf(
++      struct iscsi_conn *conn,
++      const char *fmt, ...)
++{
++      va_list args;
++      unsigned char buf[64];
++
++      memset(buf, 0, sizeof buf);
++
++      va_start(args, fmt);
++      vsnprintf(buf, sizeof buf, fmt, args);
++      va_end(args);
++
++      if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
++              iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
++                              ISCSI_LOGIN_STATUS_NO_RESOURCES);
++              return -1;
++      }
++
++      return 0;
++}
++
+ /*
+  *    This is the leading connection of a new session,
+  *    or session reinstatement.
+@@ -339,7 +361,6 @@ static int iscsi_login_zero_tsih_s2(
+ {
+       struct iscsi_node_attrib *na;
+       struct iscsi_session *sess = conn->sess;
+-      unsigned char buf[32];
+       bool iser = false;
+ 
+       sess->tpg = conn->tpg;
+@@ -380,26 +401,16 @@ static int iscsi_login_zero_tsih_s2(
+        *
+        * In our case, we have already located the struct iscsi_tiqn at this 
point.
+        */
+-      memset(buf, 0, 32);
+-      sprintf(buf, "TargetPortalGroupTag=%hu", ISCSI_TPG_S(sess)->tpgt);
+-      if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+-              iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+-                              ISCSI_LOGIN_STATUS_NO_RESOURCES);
++      if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", 
sess->tpg->tpgt))
+               return -1;
+-      }
+ 
+       /*
+        * Workaround for Initiators that have broken connection recovery logic.
+        *
+        * "We would really like to get rid of this." Linux-iSCSI.org team
+        */
+-      memset(buf, 0, 32);
+-      sprintf(buf, "ErrorRecoveryLevel=%d", na->default_erl);
+-      if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+-              iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+-                              ISCSI_LOGIN_STATUS_NO_RESOURCES);
++      if (iscsi_change_param_sprintf(conn, "ErrorRecoveryLevel=%d", 
na->default_erl))
+               return -1;
+-      }
+ 
+       if (iscsi_login_disable_FIM_keys(conn->param_list, conn) < 0)
+               return -1;
+@@ -411,12 +422,9 @@ static int iscsi_login_zero_tsih_s2(
+               unsigned long mrdsl, off;
+               int rc;
+ 
+-              sprintf(buf, "RDMAExtensions=Yes");
+-              if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+-                      iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+-                              ISCSI_LOGIN_STATUS_NO_RESOURCES);
++              if (iscsi_change_param_sprintf(conn, "RDMAExtensions=Yes"))
+                       return -1;
+-              }
++
+               /*
+                * Make MaxRecvDataSegmentLength PAGE_SIZE aligned for
+                * Immediate Data + Unsolicitied Data-OUT if necessary..
+@@ -446,12 +454,8 @@ static int iscsi_login_zero_tsih_s2(
+               pr_warn("Aligning ISER MaxRecvDataSegmentLength: %lu down"
+                       " to PAGE_SIZE\n", mrdsl);
+ 
+-              sprintf(buf, "MaxRecvDataSegmentLength=%lu\n", mrdsl);
+-              if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+-                      iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+-                              ISCSI_LOGIN_STATUS_NO_RESOURCES);
++              if (iscsi_change_param_sprintf(conn, 
"MaxRecvDataSegmentLength=%lu\n", mrdsl))
+                       return -1;
+-              }
+       }
+ 
+       return 0;
+@@ -984,6 +988,7 @@ int iscsi_target_setup_login_socket(
+       }
+ 
+       np->np_transport = t;
++      np->enabled = true;
+       return 0;
+ }
+ 
+diff --git a/drivers/target/iscsi/iscsi_target_tpg.c 
b/drivers/target/iscsi/iscsi_target_tpg.c
+index f31b4c5cdf3f..75a4e83842c2 100644
+--- a/drivers/target/iscsi/iscsi_target_tpg.c
++++ b/drivers/target/iscsi/iscsi_target_tpg.c
+@@ -175,13 +175,16 @@ void iscsit_put_tpg(struct iscsi_portal_group *tpg)
+ 
+ static void iscsit_clear_tpg_np_login_thread(
+       struct iscsi_tpg_np *tpg_np,
+-      struct iscsi_portal_group *tpg)
++      struct iscsi_portal_group *tpg,
++      bool shutdown)
+ {
+       if (!tpg_np->tpg_np) {
+               pr_err("struct iscsi_tpg_np->tpg_np is NULL!\n");
+               return;
+       }
+ 
++      if (shutdown)
++              tpg_np->tpg_np->enabled = false;
+       iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg);
+ }
+ 
+@@ -197,7 +200,7 @@ void iscsit_clear_tpg_np_login_threads(
+                       continue;
+               }
+               spin_unlock(&tpg->tpg_np_lock);
+-              iscsit_clear_tpg_np_login_thread(tpg_np, tpg);
++              iscsit_clear_tpg_np_login_thread(tpg_np, tpg, false);
+               spin_lock(&tpg->tpg_np_lock);
+       }
+       spin_unlock(&tpg->tpg_np_lock);
+@@ -520,7 +523,7 @@ static int iscsit_tpg_release_np(
+       struct iscsi_portal_group *tpg,
+       struct iscsi_np *np)
+ {
+-      iscsit_clear_tpg_np_login_thread(tpg_np, tpg);
++      iscsit_clear_tpg_np_login_thread(tpg_np, tpg, true);
+ 
+       pr_debug("CORE[%s] - Removed Network Portal: %s:%hu,%hu on %s\n",
+               tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt,
+diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
+index f608fbc14a27..df58a67f81e0 100644
+--- a/drivers/target/target_core_alua.c
++++ b/drivers/target/target_core_alua.c
+@@ -409,7 +409,16 @@ static inline int core_alua_state_standby(
+       case REPORT_LUNS:
+       case RECEIVE_DIAGNOSTIC:
+       case SEND_DIAGNOSTIC:
++      case READ_CAPACITY:
+               return 0;
++      case SERVICE_ACTION_IN:
++              switch (cdb[1] & 0x1f) {
++              case SAI_READ_CAPACITY_16:
++                      return 0;
++              default:
++                      *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY;
++                      return 1;
++              }
+       case MAINTENANCE_IN:
+               switch (cdb[1] & 0x1f) {
+               case MI_REPORT_TARGET_PGS:
+diff --git a/drivers/target/target_core_configfs.c 
b/drivers/target/target_core_configfs.c
+index 4a8bd36d3958..8cda4080b597 100644
+--- a/drivers/target/target_core_configfs.c
++++ b/drivers/target/target_core_configfs.c
+@@ -2034,6 +2034,11 @@ static ssize_t 
target_core_alua_tg_pt_gp_store_attr_alua_access_state(
+                       " tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id);
+               return -EINVAL;
+       }
++      if (!(dev->dev_flags & DF_CONFIGURED)) {
++              pr_err("Unable to set alua_access_state while device is"
++                     " not configured\n");
++              return -ENODEV;
++      }
+ 
+       ret = strict_strtoul(page, 0, &tmp);
+       if (ret < 0) {
+diff --git a/fs/attr.c b/fs/attr.c
+index 8dd5825ec708..66fa6251c398 100644
+--- a/fs/attr.c
++++ b/fs/attr.c
+@@ -50,14 +50,14 @@ int inode_change_ok(const struct inode *inode, struct 
iattr *attr)
+       if ((ia_valid & ATTR_UID) &&
+           (!uid_eq(current_fsuid(), inode->i_uid) ||
+            !uid_eq(attr->ia_uid, inode->i_uid)) &&
+-          !inode_capable(inode, CAP_CHOWN))
++          !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+               return -EPERM;
+ 
+       /* Make sure caller can chgrp. */
+       if ((ia_valid & ATTR_GID) &&
+           (!uid_eq(current_fsuid(), inode->i_uid) ||
+           (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) 
&&
+-          !inode_capable(inode, CAP_CHOWN))
++          !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
+               return -EPERM;
+ 
+       /* Make sure a caller can chmod. */
+@@ -67,7 +67,7 @@ int inode_change_ok(const struct inode *inode, struct iattr 
*attr)
+               /* Also check the setgid bit! */
+               if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
+                               inode->i_gid) &&
+-                  !inode_capable(inode, CAP_FSETID))
++                  !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+                       attr->ia_mode &= ~S_ISGID;
+       }
+ 
+@@ -160,7 +160,7 @@ void setattr_copy(struct inode *inode, const struct iattr 
*attr)
+               umode_t mode = attr->ia_mode;
+ 
+               if (!in_group_p(inode->i_gid) &&
+-                  !inode_capable(inode, CAP_FSETID))
++                  !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+                       mode &= ~S_ISGID;
+               inode->i_mode = mode;
+       }
+diff --git a/fs/inode.c b/fs/inode.c
+index 00d5fc3b86e1..1b300a06b8be 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1837,14 +1837,18 @@ EXPORT_SYMBOL(inode_init_owner);
+  * inode_owner_or_capable - check current task permissions to inode
+  * @inode: inode being checked
+  *
+- * Return true if current either has CAP_FOWNER to the inode, or
+- * owns the file.
++ * Return true if current either has CAP_FOWNER in a namespace with the
++ * inode owner uid mapped, or owns the file.
+  */
+ bool inode_owner_or_capable(const struct inode *inode)
+ {
++      struct user_namespace *ns;
++
+       if (uid_eq(current_fsuid(), inode->i_uid))
+               return true;
+-      if (inode_capable(inode, CAP_FOWNER))
++
++      ns = current_user_ns();
++      if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, inode->i_uid))
+               return true;
+       return false;
+ }
+diff --git a/fs/namei.c b/fs/namei.c
+index 1211ee5a1cb3..6ac16a37ded2 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -321,10 +321,11 @@ int generic_permission(struct inode *inode, int mask)
+ 
+       if (S_ISDIR(inode->i_mode)) {
+               /* DACs are overridable for directories */
+-              if (inode_capable(inode, CAP_DAC_OVERRIDE))
++              if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
+                       return 0;
+               if (!(mask & MAY_WRITE))
+-                      if (inode_capable(inode, CAP_DAC_READ_SEARCH))
++                      if (capable_wrt_inode_uidgid(inode,
++                                                   CAP_DAC_READ_SEARCH))
+                               return 0;
+               return -EACCES;
+       }
+@@ -334,7 +335,7 @@ int generic_permission(struct inode *inode, int mask)
+        * at least one exec bit set.
+        */
+       if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
+-              if (inode_capable(inode, CAP_DAC_OVERRIDE))
++              if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
+                       return 0;
+ 
+       /*
+@@ -342,7 +343,7 @@ int generic_permission(struct inode *inode, int mask)
+        */
+       mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
+       if (mask == MAY_READ)
+-              if (inode_capable(inode, CAP_DAC_READ_SEARCH))
++              if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH))
+                       return 0;
+ 
+       return -EACCES;
+@@ -2199,7 +2200,7 @@ static inline int check_sticky(struct inode *dir, struct 
inode *inode)
+               return 0;
+       if (uid_eq(dir->i_uid, fsuid))
+               return 0;
+-      return !inode_capable(inode, CAP_FOWNER);
++      return !capable_wrt_inode_uidgid(inode, CAP_FOWNER);
+ }
+ 
+ /*
+diff --git a/include/linux/capability.h b/include/linux/capability.h
+index d9a4f7f40f32..15f90929fb51 100644
+--- a/include/linux/capability.h
++++ b/include/linux/capability.h
+@@ -211,7 +211,7 @@ extern bool has_ns_capability_noaudit(struct task_struct 
*t,
+ extern bool capable(int cap);
+ extern bool ns_capable(struct user_namespace *ns, int cap);
+ extern bool nsown_capable(int cap);
+-extern bool inode_capable(const struct inode *inode, int cap);
++extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
+ extern bool file_ns_capable(const struct file *file, struct user_namespace 
*ns, int cap);
+ 
+ /* audit system wants to get cap info from files as well */
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index 9845cb32b60a..03a3af8538bd 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -733,6 +733,22 @@ static enum audit_state audit_filter_task(struct 
task_struct *tsk, char **key)
+       return AUDIT_BUILD_CONTEXT;
+ }
+ 
++static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
++{
++      int word, bit;
++
++      if (val > 0xffffffff)
++              return false;
++
++      word = AUDIT_WORD(val);
++      if (word >= AUDIT_BITMASK_SIZE)
++              return false;
++
++      bit = AUDIT_BIT(val);
++
++      return rule->mask[word] & bit;
++}
++
+ /* At syscall entry and exit time, this filter is called if the
+  * audit_state is not low enough that auditing cannot take place, but is
+  * also not high enough that we already know we have to write an audit
+@@ -750,11 +766,8 @@ static enum audit_state audit_filter_syscall(struct 
task_struct *tsk,
+ 
+       rcu_read_lock();
+       if (!list_empty(list)) {
+-              int word = AUDIT_WORD(ctx->major);
+-              int bit  = AUDIT_BIT(ctx->major);
+-
+               list_for_each_entry_rcu(e, list, list) {
+-                      if ((e->rule.mask[word] & bit) == bit &&
++                      if (audit_in_mask(&e->rule, ctx->major) &&
+                           audit_filter_rules(tsk, &e->rule, ctx, NULL,
+                                              &state, false)) {
+                               rcu_read_unlock();
+@@ -774,20 +787,16 @@ static enum audit_state audit_filter_syscall(struct 
task_struct *tsk,
+ static int audit_filter_inode_name(struct task_struct *tsk,
+                                  struct audit_names *n,
+                                  struct audit_context *ctx) {
+-      int word, bit;
+       int h = audit_hash_ino((u32)n->ino);
+       struct list_head *list = &audit_inode_hash[h];
+       struct audit_entry *e;
+       enum audit_state state;
+ 
+-      word = AUDIT_WORD(ctx->major);
+-      bit  = AUDIT_BIT(ctx->major);
+-
+       if (list_empty(list))
+               return 0;
+ 
+       list_for_each_entry_rcu(e, list, list) {
+-              if ((e->rule.mask[word] & bit) == bit &&
++              if (audit_in_mask(&e->rule, ctx->major) &&
+                   audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
+                       ctx->current_state = state;
+                       return 1;
+diff --git a/kernel/capability.c b/kernel/capability.c
+index f6c2ce5701e1..d52eecc0942b 100644
+--- a/kernel/capability.c
++++ b/kernel/capability.c
+@@ -445,22 +445,18 @@ bool nsown_capable(int cap)
+ }
+ 
+ /**
+- * inode_capable - Check superior capability over inode
++ * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped
+  * @inode: The inode in question
+  * @cap: The capability in question
+  *
+- * Return true if the current task has the given superior capability
+- * targeted at it's own user namespace and that the given inode is owned
+- * by the current user namespace or a child namespace.
+- *
+- * Currently we check to see if an inode is owned by the current
+- * user namespace by seeing if the inode's owner maps into the
+- * current user namespace.
+- *
++ * Return true if the current task has the given capability targeted at
++ * its own user namespace and that the given inode's uid and gid are
++ * mapped into the current user namespace.
+  */
+-bool inode_capable(const struct inode *inode, int cap)
++bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
+ {
+       struct user_namespace *ns = current_user_ns();
+ 
+-      return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid);
++      return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) &&
++              kgid_has_mapping(ns, inode->i_gid);
+ }
+diff --git a/mm/compaction.c b/mm/compaction.c
+index 18a90b4d0bfc..fb797a32362f 100644
+--- a/mm/compaction.c
++++ b/mm/compaction.c
+@@ -657,17 +657,21 @@ static void isolate_freepages(struct zone *zone,
+                               struct compact_control *cc)
+ {
+       struct page *page;
+-      unsigned long high_pfn, low_pfn, pfn, z_end_pfn, end_pfn;
++      unsigned long high_pfn, low_pfn, pfn, z_end_pfn;
+       int nr_freepages = cc->nr_freepages;
+       struct list_head *freelist = &cc->freepages;
+ 
+       /*
+        * Initialise the free scanner. The starting point is where we last
+-       * scanned from (or the end of the zone if starting). The low point
+-       * is the end of the pageblock the migration scanner is using.
++       * successfully isolated from, zone-cached value, or the end of the
++       * zone when isolating for the first time. We need this aligned to
++       * the pageblock boundary, because we do pfn -= pageblock_nr_pages
++       * in the for loop.
++       * The low boundary is the end of the pageblock the migration scanner
++       * is using.
+        */
+-      pfn = cc->free_pfn;
+-      low_pfn = cc->migrate_pfn + pageblock_nr_pages;
++      pfn = cc->free_pfn & ~(pageblock_nr_pages-1);
++      low_pfn = ALIGN(cc->migrate_pfn + 1, pageblock_nr_pages);
+ 
+       /*
+        * Take care that if the migration scanner is at the end of the zone
+@@ -683,9 +687,10 @@ static void isolate_freepages(struct zone *zone,
+        * pages on cc->migratepages. We stop searching if the migrate
+        * and free page scanners meet or enough free pages are isolated.
+        */
+-      for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
++      for (; pfn >= low_pfn && cc->nr_migratepages > nr_freepages;
+                                       pfn -= pageblock_nr_pages) {
+               unsigned long isolated;
++              unsigned long end_pfn;
+ 
+               if (!pfn_valid(pfn))
+                       continue;
+@@ -713,13 +718,10 @@ static void isolate_freepages(struct zone *zone,
+               isolated = 0;
+ 
+               /*
+-               * As pfn may not start aligned, pfn+pageblock_nr_page
+-               * may cross a MAX_ORDER_NR_PAGES boundary and miss
+-               * a pfn_valid check. Ensure isolate_freepages_block()
+-               * only scans within a pageblock
++               * Take care when isolating in last pageblock of a zone which
++               * ends in the middle of a pageblock.
+                */
+-              end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
+-              end_pfn = min(end_pfn, z_end_pfn);
++              end_pfn = min(pfn + pageblock_nr_pages, z_end_pfn);
+               isolated = isolate_freepages_block(cc, pfn, end_pfn,
+                                                  freelist, false);
+               nr_freepages += isolated;
+@@ -738,7 +740,14 @@ static void isolate_freepages(struct zone *zone,
+       /* split_free_page does not map the pages */
+       map_pages(freelist);
+ 
+-      cc->free_pfn = high_pfn;
++      /*
++       * If we crossed the migrate scanner, we want to keep it that way
++       * so that compact_finished() may detect this
++       */
++      if (pfn < low_pfn)
++              cc->free_pfn = max(pfn, zone->zone_start_pfn);
++      else
++              cc->free_pfn = high_pfn;
+       cc->nr_freepages = nr_freepages;
+ }
+ 
+@@ -947,6 +956,14 @@ static int compact_zone(struct zone *zone, struct 
compact_control *cc)
+       }
+ 
+       /*
++       * Clear pageblock skip if there were failures recently and compaction
++       * is about to be retried after being deferred. kswapd does not do
++       * this reset as it'll reset the cached information when going to sleep.
++       */
++      if (compaction_restarting(zone, cc->order) && !current_is_kswapd())
++              __reset_isolation_suitable(zone);
++
++      /*
+        * Setup to move all movable pages to the end of the zone. Used cached
+        * information on where the scanners should start but check that it
+        * is initialised by ensuring the values are within zone boundaries.
+@@ -962,14 +979,6 @@ static int compact_zone(struct zone *zone, struct 
compact_control *cc)
+               zone->compact_cached_migrate_pfn = cc->migrate_pfn;
+       }
+ 
+-      /*
+-       * Clear pageblock skip if there were failures recently and compaction
+-       * is about to be retried after being deferred. kswapd does not do
+-       * this reset as it'll reset the cached information when going to sleep.
+-       */
+-      if (compaction_restarting(zone, cc->order) && !current_is_kswapd())
+-              __reset_isolation_suitable(zone);
+-
+       migrate_prep_local();
+ 
+       while ((ret = compact_finished(zone, cc)) == COMPACT_CONTINUE) {
+@@ -1003,7 +1012,11 @@ static int compact_zone(struct zone *zone, struct 
compact_control *cc)
+               if (err) {
+                       putback_movable_pages(&cc->migratepages);
+                       cc->nr_migratepages = 0;
+-                      if (err == -ENOMEM) {
++                      /*
++                       * migrate_pages() may return -ENOMEM when scanners meet
++                       * and we want compact_finished() to detect it
++                       */
++                      if (err == -ENOMEM && cc->free_pfn > cc->migrate_pfn) {
+                               ret = COMPACT_PARTIAL;
+                               goto out;
+                       }
+diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c 
b/net/ipv4/netfilter/nf_defrag_ipv4.c
+index 742815518b0f..4cfb3bd1677c 100644
+--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
++++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
+@@ -22,7 +22,6 @@
+ #endif
+ #include <net/netfilter/nf_conntrack_zones.h>
+ 
+-/* Returns new sk_buff, or NULL */
+ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
+ {
+       int err;
+@@ -33,8 +32,10 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, 
u_int32_t user)
+       err = ip_defrag(skb, user);
+       local_bh_enable();
+ 
+-      if (!err)
++      if (!err) {
+               ip_send_check(ip_hdr(skb));
++              skb->local_df = 1;
++      }
+ 
+       return err;
+ }


Reply via email to