diff options
author | LCPD Auto Merger | 2016-12-29 08:18:19 -0600 |
---|---|---|
committer | LCPD Auto Merger | 2016-12-29 08:18:19 -0600 |
commit | ea9d02d53d2e605ef872379e311ceb35fcd3100e (patch) | |
tree | e07f8df74574c82f2c7fd0659c1a984e8a58f924 | |
parent | 7f655674db9f3a80c99a8e29c0a6046ec14a7d27 (diff) | |
parent | b56fa3bd73d45ef31478b7e3ab97570a0dd79c44 (diff) | |
download | ti-linux-kernel-ea9d02d53d2e605ef872379e311ceb35fcd3100e.tar.gz ti-linux-kernel-ea9d02d53d2e605ef872379e311ceb35fcd3100e.tar.xz ti-linux-kernel-ea9d02d53d2e605ef872379e311ceb35fcd3100e.zip |
Merge branch 'ti-linux-4.1.y' of git.ti.com:ti-linux-kernel/ti-linux-kernel into ti-lsk-linux-4.1.yti-lsk-linux-4.1.y
TI-Feature: ti_linux_base_lsk
TI-Tree: git@git.ti.com:ti-linux-kernel/ti-linux-kernel.git
TI-Branch: ti-linux-4.1.y
* 'ti-linux-4.1.y' of git.ti.com:ti-linux-kernel/ti-linux-kernel: (29 commits)
Linux 4.1.37
scsi: megaraid_sas: fix macro MEGASAS_IS_LOGICAL to avoid regression
tipc: check minimum bearer MTU
net: ping: check minimum size on ICMP header length
packet: fix race condition in packet_set_ring
net: add recursion limit to GRO
Bluetooth: Fix potential NULL dereference in RFCOMM bind callback
ptrace: being capable wrt a process requires mapped uids/gids
scsi: arcmsr: Buffer overflow in arcmsr_iop_message_xfer()
mnt: Add a per mount namespace limit on the number of mounts
posix_acl: Clear SGID bit when setting file permissions
fs: Avoid premature clearing of capabilities
fs: Give dentry to inode_change_ok() instead of inode
nfsd: Disable NFSv2 timestamp workaround for NFSv3+
fuse: Propagate dentry down to inode_change_ok()
xfs: Propagate dentry down to inode_change_ok()
xattr: Option to disable meta-data block cache
tcp: fix use after free in tcp_xmit_retransmit_queue()
x86/kexec: add -fno-PIE
scripts/has-stack-protector: add -fno-PIE
...
Signed-off-by: LCPD Auto Merger <lcpd_integration@list.ti.com>
115 files changed, 604 insertions, 308 deletions
diff --git a/Documentation/arm/CCN.txt b/Documentation/arm/CCN.txt index 0632b3aad83e..715776f06df6 100644 --- a/Documentation/arm/CCN.txt +++ b/Documentation/arm/CCN.txt | |||
@@ -38,7 +38,7 @@ Example of perf tool use: | |||
38 | / # perf list | grep ccn | 38 | / # perf list | grep ccn |
39 | ccn/cycles/ [Kernel PMU event] | 39 | ccn/cycles/ [Kernel PMU event] |
40 | <...> | 40 | <...> |
41 | ccn/xp_valid_flit/ [Kernel PMU event] | 41 | ccn/xp_valid_flit,xp=?,port=?,vc=?,dir=?/ [Kernel PMU event] |
42 | <...> | 42 | <...> |
43 | 43 | ||
44 | / # perf stat -C 0 -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \ | 44 | / # perf stat -C 0 -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \ |
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index e69274de8d0c..0500895b768f 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting | |||
@@ -287,8 +287,8 @@ implementing on-disk size changes. Start with a copy of the old inode_setattr | |||
287 | and vmtruncate, and the reorder the vmtruncate + foofs_vmtruncate sequence to | 287 | and vmtruncate, and the reorder the vmtruncate + foofs_vmtruncate sequence to |
288 | be in order of zeroing blocks using block_truncate_page or similar helpers, | 288 | be in order of zeroing blocks using block_truncate_page or similar helpers, |
289 | size update and on finally on-disk truncation which should not fail. | 289 | size update and on finally on-disk truncation which should not fail. |
290 | inode_change_ok now includes the size checks for ATTR_SIZE and must be called | 290 | setattr_prepare (which used to be inode_change_ok) now includes the size checks |
291 | in the beginning of ->setattr unconditionally. | 291 | for ATTR_SIZE and must be called in the beginning of ->setattr unconditionally. |
292 | 292 | ||
293 | [mandatory] | 293 | [mandatory] |
294 | 294 | ||
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index 302b5ed616a6..35e17f748ca7 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt | |||
@@ -265,6 +265,13 @@ aio-nr can grow to. | |||
265 | 265 | ||
266 | ============================================================== | 266 | ============================================================== |
267 | 267 | ||
268 | mount-max: | ||
269 | |||
270 | This denotes the maximum number of mounts that may exist | ||
271 | in a mount namespace. | ||
272 | |||
273 | ============================================================== | ||
274 | |||
268 | 275 | ||
269 | 2. /proc/sys/fs/binfmt_misc | 276 | 2. /proc/sys/fs/binfmt_misc |
270 | ---------------------------------------------------------- | 277 | ---------------------------------------------------------- |
@@ -1,6 +1,6 @@ | |||
1 | VERSION = 4 | 1 | VERSION = 4 |
2 | PATCHLEVEL = 1 | 2 | PATCHLEVEL = 1 |
3 | SUBLEVEL = 36 | 3 | SUBLEVEL = 37 |
4 | EXTRAVERSION = | 4 | EXTRAVERSION = |
5 | NAME = Series 4800 | 5 | NAME = Series 4800 |
6 | 6 | ||
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index b52101d37ec7..ee21eecbe0d2 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -117,7 +117,7 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) | |||
117 | /* The ARM override for dma_max_pfn() */ | 117 | /* The ARM override for dma_max_pfn() */ |
118 | static inline unsigned long dma_max_pfn(struct device *dev) | 118 | static inline unsigned long dma_max_pfn(struct device *dev) |
119 | { | 119 | { |
120 | return PHYS_PFN_OFFSET + dma_to_pfn(dev, *dev->dma_mask); | 120 | return dma_to_pfn(dev, *dev->dma_mask); |
121 | } | 121 | } |
122 | #define dma_max_pfn(dev) dma_max_pfn(dev) | 122 | #define dma_max_pfn(dev) dma_max_pfn(dev) |
123 | 123 | ||
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index cd791948b286..7e459b7ee708 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h | |||
@@ -32,7 +32,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); | |||
32 | /* Initialize cr4 shadow for this CPU. */ | 32 | /* Initialize cr4 shadow for this CPU. */ |
33 | static inline void cr4_init_shadow(void) | 33 | static inline void cr4_init_shadow(void) |
34 | { | 34 | { |
35 | this_cpu_write(cpu_tlbstate.cr4, __read_cr4()); | 35 | this_cpu_write(cpu_tlbstate.cr4, __read_cr4_safe()); |
36 | } | 36 | } |
37 | 37 | ||
38 | /* Set in this cpu's CR4. */ | 38 | /* Set in this cpu's CR4. */ |
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index 2c835e356349..d445c5f1aeb1 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile | |||
@@ -12,6 +12,7 @@ targets += purgatory.ro | |||
12 | 12 | ||
13 | KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large | 13 | KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large |
14 | KBUILD_CFLAGS += -m$(BITS) | 14 | KBUILD_CFLAGS += -m$(BITS) |
15 | KBUILD_CFLAGS += $(call cc-option,-fno-PIE) | ||
15 | 16 | ||
16 | $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE | 17 | $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE |
17 | $(call if_changed,ld) | 18 | $(call if_changed,ld) |
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c index 27fd0dacad5f..4d523cfe51ce 100644 --- a/drivers/bus/arm-ccn.c +++ b/drivers/bus/arm-ccn.c | |||
@@ -183,6 +183,7 @@ struct arm_ccn { | |||
183 | struct arm_ccn_component *xp; | 183 | struct arm_ccn_component *xp; |
184 | 184 | ||
185 | struct arm_ccn_dt dt; | 185 | struct arm_ccn_dt dt; |
186 | int mn_id; | ||
186 | }; | 187 | }; |
187 | 188 | ||
188 | 189 | ||
@@ -322,6 +323,7 @@ struct arm_ccn_pmu_event { | |||
322 | static ssize_t arm_ccn_pmu_event_show(struct device *dev, | 323 | static ssize_t arm_ccn_pmu_event_show(struct device *dev, |
323 | struct device_attribute *attr, char *buf) | 324 | struct device_attribute *attr, char *buf) |
324 | { | 325 | { |
326 | struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev)); | ||
325 | struct arm_ccn_pmu_event *event = container_of(attr, | 327 | struct arm_ccn_pmu_event *event = container_of(attr, |
326 | struct arm_ccn_pmu_event, attr); | 328 | struct arm_ccn_pmu_event, attr); |
327 | ssize_t res; | 329 | ssize_t res; |
@@ -336,6 +338,26 @@ static ssize_t arm_ccn_pmu_event_show(struct device *dev, | |||
336 | if (event->mask) | 338 | if (event->mask) |
337 | res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x", | 339 | res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x", |
338 | event->mask); | 340 | event->mask); |
341 | |||
342 | /* Arguments required by an event */ | ||
343 | switch (event->type) { | ||
344 | case CCN_TYPE_CYCLES: | ||
345 | break; | ||
346 | case CCN_TYPE_XP: | ||
347 | res += snprintf(buf + res, PAGE_SIZE - res, | ||
348 | ",xp=?,port=?,vc=?,dir=?"); | ||
349 | if (event->event == CCN_EVENT_WATCHPOINT) | ||
350 | res += snprintf(buf + res, PAGE_SIZE - res, | ||
351 | ",cmp_l=?,cmp_h=?,mask=?"); | ||
352 | break; | ||
353 | case CCN_TYPE_MN: | ||
354 | res += snprintf(buf + res, PAGE_SIZE - res, ",node=%d", ccn->mn_id); | ||
355 | break; | ||
356 | default: | ||
357 | res += snprintf(buf + res, PAGE_SIZE - res, ",node=?"); | ||
358 | break; | ||
359 | } | ||
360 | |||
339 | res += snprintf(buf + res, PAGE_SIZE - res, "\n"); | 361 | res += snprintf(buf + res, PAGE_SIZE - res, "\n"); |
340 | 362 | ||
341 | return res; | 363 | return res; |
@@ -360,9 +382,9 @@ static umode_t arm_ccn_pmu_events_is_visible(struct kobject *kobj, | |||
360 | } | 382 | } |
361 | 383 | ||
362 | static struct arm_ccn_pmu_event arm_ccn_pmu_events[] = { | 384 | static struct arm_ccn_pmu_event arm_ccn_pmu_events[] = { |
363 | CCN_EVENT_MN(eobarrier, "dir=0,vc=0,cmp_h=0x1c00", CCN_IDX_MASK_OPCODE), | 385 | CCN_EVENT_MN(eobarrier, "dir=1,vc=0,cmp_h=0x1c00", CCN_IDX_MASK_OPCODE), |
364 | CCN_EVENT_MN(ecbarrier, "dir=0,vc=0,cmp_h=0x1e00", CCN_IDX_MASK_OPCODE), | 386 | CCN_EVENT_MN(ecbarrier, "dir=1,vc=0,cmp_h=0x1e00", CCN_IDX_MASK_OPCODE), |
365 | CCN_EVENT_MN(dvmop, "dir=0,vc=0,cmp_h=0x2800", CCN_IDX_MASK_OPCODE), | 387 | CCN_EVENT_MN(dvmop, "dir=1,vc=0,cmp_h=0x2800", CCN_IDX_MASK_OPCODE), |
366 | CCN_EVENT_HNI(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY), | 388 | CCN_EVENT_HNI(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY), |
367 | CCN_EVENT_HNI(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY), | 389 | CCN_EVENT_HNI(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY), |
368 | CCN_EVENT_HNI(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY), | 390 | CCN_EVENT_HNI(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY), |
@@ -649,6 +671,12 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) | |||
649 | 671 | ||
650 | /* Validate node/xp vs topology */ | 672 | /* Validate node/xp vs topology */ |
651 | switch (type) { | 673 | switch (type) { |
674 | case CCN_TYPE_MN: | ||
675 | if (node_xp != ccn->mn_id) { | ||
676 | dev_warn(ccn->dev, "Invalid MN ID %d!\n", node_xp); | ||
677 | return -EINVAL; | ||
678 | } | ||
679 | break; | ||
652 | case CCN_TYPE_XP: | 680 | case CCN_TYPE_XP: |
653 | if (node_xp >= ccn->num_xps) { | 681 | if (node_xp >= ccn->num_xps) { |
654 | dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp); | 682 | dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp); |
@@ -1214,6 +1242,8 @@ static int arm_ccn_init_nodes(struct arm_ccn *ccn, int region, | |||
1214 | 1242 | ||
1215 | switch (type) { | 1243 | switch (type) { |
1216 | case CCN_TYPE_MN: | 1244 | case CCN_TYPE_MN: |
1245 | ccn->mn_id = id; | ||
1246 | return 0; | ||
1217 | case CCN_TYPE_DT: | 1247 | case CCN_TYPE_DT: |
1218 | return 0; | 1248 | return 0; |
1219 | case CCN_TYPE_XP: | 1249 | case CCN_TYPE_XP: |
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index cd0554f68316..4ff8c334e7c8 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c | |||
@@ -55,6 +55,14 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, | |||
55 | return submit; | 55 | return submit; |
56 | } | 56 | } |
57 | 57 | ||
58 | static inline unsigned long __must_check | ||
59 | copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) | ||
60 | { | ||
61 | if (access_ok(VERIFY_READ, from, n)) | ||
62 | return __copy_from_user_inatomic(to, from, n); | ||
63 | return -EFAULT; | ||
64 | } | ||
65 | |||
58 | static int submit_lookup_objects(struct msm_gem_submit *submit, | 66 | static int submit_lookup_objects(struct msm_gem_submit *submit, |
59 | struct drm_msm_gem_submit *args, struct drm_file *file) | 67 | struct drm_msm_gem_submit *args, struct drm_file *file) |
60 | { | 68 | { |
@@ -62,6 +70,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, | |||
62 | int ret = 0; | 70 | int ret = 0; |
63 | 71 | ||
64 | spin_lock(&file->table_lock); | 72 | spin_lock(&file->table_lock); |
73 | pagefault_disable(); | ||
65 | 74 | ||
66 | for (i = 0; i < args->nr_bos; i++) { | 75 | for (i = 0; i < args->nr_bos; i++) { |
67 | struct drm_msm_gem_submit_bo submit_bo; | 76 | struct drm_msm_gem_submit_bo submit_bo; |
@@ -70,10 +79,15 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, | |||
70 | void __user *userptr = | 79 | void __user *userptr = |
71 | to_user_ptr(args->bos + (i * sizeof(submit_bo))); | 80 | to_user_ptr(args->bos + (i * sizeof(submit_bo))); |
72 | 81 | ||
73 | ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo)); | 82 | ret = copy_from_user_inatomic(&submit_bo, userptr, sizeof(submit_bo)); |
74 | if (ret) { | 83 | if (unlikely(ret)) { |
75 | ret = -EFAULT; | 84 | pagefault_enable(); |
76 | goto out_unlock; | 85 | spin_unlock(&file->table_lock); |
86 | ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo)); | ||
87 | if (ret) | ||
88 | goto out; | ||
89 | spin_lock(&file->table_lock); | ||
90 | pagefault_disable(); | ||
77 | } | 91 | } |
78 | 92 | ||
79 | if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) { | 93 | if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) { |
@@ -113,9 +127,12 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, | |||
113 | } | 127 | } |
114 | 128 | ||
115 | out_unlock: | 129 | out_unlock: |
116 | submit->nr_bos = i; | 130 | pagefault_enable(); |
117 | spin_unlock(&file->table_lock); | 131 | spin_unlock(&file->table_lock); |
118 | 132 | ||
133 | out: | ||
134 | submit->nr_bos = i; | ||
135 | |||
119 | return ret; | 136 | return ret; |
120 | } | 137 | } |
121 | 138 | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 0f88e25123a0..4ead0cc5bac4 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -241,6 +241,9 @@ static void nand_davinci_hwctl_4bit(struct mtd_info *mtd, int mode) | |||
241 | unsigned long flags; | 241 | unsigned long flags; |
242 | u32 val; | 242 | u32 val; |
243 | 243 | ||
244 | /* Reset ECC hardware */ | ||
245 | davinci_nand_readl(info, NAND_4BIT_ECC1_OFFSET); | ||
246 | |||
244 | spin_lock_irqsave(&davinci_nand_lock, flags); | 247 | spin_lock_irqsave(&davinci_nand_lock, flags); |
245 | 248 | ||
246 | /* Start 4-bit ECC calculation for read/write */ | 249 | /* Start 4-bit ECC calculation for read/write */ |
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index ad535a854e5c..eab132778e67 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <linux/if_arp.h> | 23 | #include <linux/if_arp.h> |
24 | #include <linux/workqueue.h> | ||
24 | #include <linux/can.h> | 25 | #include <linux/can.h> |
25 | #include <linux/can/dev.h> | 26 | #include <linux/can/dev.h> |
26 | #include <linux/can/skb.h> | 27 | #include <linux/can/skb.h> |
@@ -471,9 +472,8 @@ EXPORT_SYMBOL_GPL(can_free_echo_skb); | |||
471 | /* | 472 | /* |
472 | * CAN device restart for bus-off recovery | 473 | * CAN device restart for bus-off recovery |
473 | */ | 474 | */ |
474 | static void can_restart(unsigned long data) | 475 | static void can_restart(struct net_device *dev) |
475 | { | 476 | { |
476 | struct net_device *dev = (struct net_device *)data; | ||
477 | struct can_priv *priv = netdev_priv(dev); | 477 | struct can_priv *priv = netdev_priv(dev); |
478 | struct net_device_stats *stats = &dev->stats; | 478 | struct net_device_stats *stats = &dev->stats; |
479 | struct sk_buff *skb; | 479 | struct sk_buff *skb; |
@@ -513,6 +513,14 @@ restart: | |||
513 | netdev_err(dev, "Error %d during restart", err); | 513 | netdev_err(dev, "Error %d during restart", err); |
514 | } | 514 | } |
515 | 515 | ||
516 | static void can_restart_work(struct work_struct *work) | ||
517 | { | ||
518 | struct delayed_work *dwork = to_delayed_work(work); | ||
519 | struct can_priv *priv = container_of(dwork, struct can_priv, restart_work); | ||
520 | |||
521 | can_restart(priv->dev); | ||
522 | } | ||
523 | |||
516 | int can_restart_now(struct net_device *dev) | 524 | int can_restart_now(struct net_device *dev) |
517 | { | 525 | { |
518 | struct can_priv *priv = netdev_priv(dev); | 526 | struct can_priv *priv = netdev_priv(dev); |
@@ -526,8 +534,8 @@ int can_restart_now(struct net_device *dev) | |||
526 | if (priv->state != CAN_STATE_BUS_OFF) | 534 | if (priv->state != CAN_STATE_BUS_OFF) |
527 | return -EBUSY; | 535 | return -EBUSY; |
528 | 536 | ||
529 | /* Runs as soon as possible in the timer context */ | 537 | cancel_delayed_work_sync(&priv->restart_work); |
530 | mod_timer(&priv->restart_timer, jiffies); | 538 | can_restart(dev); |
531 | 539 | ||
532 | return 0; | 540 | return 0; |
533 | } | 541 | } |
@@ -548,8 +556,8 @@ void can_bus_off(struct net_device *dev) | |||
548 | netif_carrier_off(dev); | 556 | netif_carrier_off(dev); |
549 | 557 | ||
550 | if (priv->restart_ms) | 558 | if (priv->restart_ms) |
551 | mod_timer(&priv->restart_timer, | 559 | schedule_delayed_work(&priv->restart_work, |
552 | jiffies + (priv->restart_ms * HZ) / 1000); | 560 | msecs_to_jiffies(priv->restart_ms)); |
553 | } | 561 | } |
554 | EXPORT_SYMBOL_GPL(can_bus_off); | 562 | EXPORT_SYMBOL_GPL(can_bus_off); |
555 | 563 | ||
@@ -658,6 +666,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) | |||
658 | return NULL; | 666 | return NULL; |
659 | 667 | ||
660 | priv = netdev_priv(dev); | 668 | priv = netdev_priv(dev); |
669 | priv->dev = dev; | ||
661 | 670 | ||
662 | if (echo_skb_max) { | 671 | if (echo_skb_max) { |
663 | priv->echo_skb_max = echo_skb_max; | 672 | priv->echo_skb_max = echo_skb_max; |
@@ -667,7 +676,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) | |||
667 | 676 | ||
668 | priv->state = CAN_STATE_STOPPED; | 677 | priv->state = CAN_STATE_STOPPED; |
669 | 678 | ||
670 | init_timer(&priv->restart_timer); | 679 | INIT_DELAYED_WORK(&priv->restart_work, can_restart_work); |
671 | 680 | ||
672 | return dev; | 681 | return dev; |
673 | } | 682 | } |
@@ -748,8 +757,6 @@ int open_candev(struct net_device *dev) | |||
748 | if (!netif_carrier_ok(dev)) | 757 | if (!netif_carrier_ok(dev)) |
749 | netif_carrier_on(dev); | 758 | netif_carrier_on(dev); |
750 | 759 | ||
751 | setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); | ||
752 | |||
753 | return 0; | 760 | return 0; |
754 | } | 761 | } |
755 | EXPORT_SYMBOL_GPL(open_candev); | 762 | EXPORT_SYMBOL_GPL(open_candev); |
@@ -764,7 +771,7 @@ void close_candev(struct net_device *dev) | |||
764 | { | 771 | { |
765 | struct can_priv *priv = netdev_priv(dev); | 772 | struct can_priv *priv = netdev_priv(dev); |
766 | 773 | ||
767 | del_timer_sync(&priv->restart_timer); | 774 | cancel_delayed_work_sync(&priv->restart_work); |
768 | can_flush_echo_skb(dev); | 775 | can_flush_echo_skb(dev); |
769 | } | 776 | } |
770 | EXPORT_SYMBOL_GPL(close_candev); | 777 | EXPORT_SYMBOL_GPL(close_candev); |
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 940f78e41993..d9e873c3a273 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -635,7 +635,7 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, | |||
635 | } | 635 | } |
636 | } | 636 | } |
637 | 637 | ||
638 | pp = eth_gro_receive(head, skb); | 638 | pp = call_gro_receive(eth_gro_receive, head, skb); |
639 | 639 | ||
640 | out: | 640 | out: |
641 | skb_gro_remcsum_cleanup(skb, &grc); | 641 | skb_gro_remcsum_cleanup(skb, &grc); |
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 2926295a936d..c9f87cdc85c1 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -2300,7 +2300,8 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, | |||
2300 | } | 2300 | } |
2301 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { | 2301 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { |
2302 | unsigned char *ver_addr; | 2302 | unsigned char *ver_addr; |
2303 | int32_t user_len, cnt2end; | 2303 | uint32_t user_len; |
2304 | int32_t cnt2end; | ||
2304 | uint8_t *pQbuffer, *ptmpuserbuffer; | 2305 | uint8_t *pQbuffer, *ptmpuserbuffer; |
2305 | ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); | 2306 | ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); |
2306 | if (!ver_addr) { | 2307 | if (!ver_addr) { |
@@ -2309,6 +2310,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, | |||
2309 | } | 2310 | } |
2310 | ptmpuserbuffer = ver_addr; | 2311 | ptmpuserbuffer = ver_addr; |
2311 | user_len = pcmdmessagefld->cmdmessage.Length; | 2312 | user_len = pcmdmessagefld->cmdmessage.Length; |
2313 | if (user_len > ARCMSR_API_DATA_BUFLEN) { | ||
2314 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
2315 | kfree(ver_addr); | ||
2316 | goto message_out; | ||
2317 | } | ||
2312 | memcpy(ptmpuserbuffer, | 2318 | memcpy(ptmpuserbuffer, |
2313 | pcmdmessagefld->messagedatabuffer, user_len); | 2319 | pcmdmessagefld->messagedatabuffer, user_len); |
2314 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); | 2320 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 14e5c7cea929..1fcd31c6b37b 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -1862,7 +1862,7 @@ struct megasas_instance_template { | |||
1862 | }; | 1862 | }; |
1863 | 1863 | ||
1864 | #define MEGASAS_IS_LOGICAL(scp) \ | 1864 | #define MEGASAS_IS_LOGICAL(scp) \ |
1865 | (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1 | 1865 | ((scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1) |
1866 | 1866 | ||
1867 | #define MEGASAS_DEV_INDEX(inst, scp) \ | 1867 | #define MEGASAS_DEV_INDEX(inst, scp) \ |
1868 | ((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \ | 1868 | ((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \ |
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index a27af7882170..d60425996948 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c | |||
@@ -1323,7 +1323,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) | |||
1323 | attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; | 1323 | attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | /* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */ | 1326 | /* POSIX: check before ATTR_*TIME_SET set (from setattr_prepare) */ |
1327 | if (attr->ia_valid & TIMES_SET_FLAGS) { | 1327 | if (attr->ia_valid & TIMES_SET_FLAGS) { |
1328 | if ((!uid_eq(current_fsuid(), inode->i_uid)) && | 1328 | if ((!uid_eq(current_fsuid(), inode->i_uid)) && |
1329 | !capable(CFS_CAP_FOWNER)) | 1329 | !capable(CFS_CAP_FOWNER)) |
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 31c010372660..de59b4892bfb 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c | |||
@@ -320,32 +320,26 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, | |||
320 | case ACL_TYPE_ACCESS: | 320 | case ACL_TYPE_ACCESS: |
321 | name = POSIX_ACL_XATTR_ACCESS; | 321 | name = POSIX_ACL_XATTR_ACCESS; |
322 | if (acl) { | 322 | if (acl) { |
323 | umode_t mode = inode->i_mode; | 323 | struct iattr iattr; |
324 | retval = posix_acl_equiv_mode(acl, &mode); | 324 | |
325 | if (retval < 0) | 325 | retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); |
326 | if (retval) | ||
326 | goto err_out; | 327 | goto err_out; |
327 | else { | 328 | if (!acl) { |
328 | struct iattr iattr; | 329 | /* |
329 | if (retval == 0) { | 330 | * ACL can be represented |
330 | /* | 331 | * by the mode bits. So don't |
331 | * ACL can be represented | 332 | * update ACL. |
332 | * by the mode bits. So don't | ||
333 | * update ACL. | ||
334 | */ | ||
335 | acl = NULL; | ||
336 | value = NULL; | ||
337 | size = 0; | ||
338 | } | ||
339 | /* Updte the mode bits */ | ||
340 | iattr.ia_mode = ((mode & S_IALLUGO) | | ||
341 | (inode->i_mode & ~S_IALLUGO)); | ||
342 | iattr.ia_valid = ATTR_MODE; | ||
343 | /* FIXME should we update ctime ? | ||
344 | * What is the following setxattr update the | ||
345 | * mode ? | ||
346 | */ | 333 | */ |
347 | v9fs_vfs_setattr_dotl(dentry, &iattr); | 334 | value = NULL; |
335 | size = 0; | ||
348 | } | 336 | } |
337 | iattr.ia_valid = ATTR_MODE; | ||
338 | /* FIXME should we update ctime ? | ||
339 | * What is the following setxattr update the | ||
340 | * mode ? | ||
341 | */ | ||
342 | v9fs_vfs_setattr_dotl(dentry, &iattr); | ||
349 | } | 343 | } |
350 | break; | 344 | break; |
351 | case ACL_TYPE_DEFAULT: | 345 | case ACL_TYPE_DEFAULT: |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 53f1e8a21707..99c3c4ffe1d9 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -1094,7 +1094,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
1094 | struct p9_wstat wstat; | 1094 | struct p9_wstat wstat; |
1095 | 1095 | ||
1096 | p9_debug(P9_DEBUG_VFS, "\n"); | 1096 | p9_debug(P9_DEBUG_VFS, "\n"); |
1097 | retval = inode_change_ok(d_inode(dentry), iattr); | 1097 | retval = setattr_prepare(dentry, iattr); |
1098 | if (retval) | 1098 | if (retval) |
1099 | return retval; | 1099 | return retval; |
1100 | 1100 | ||
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 4d3ecfb55fcf..ce7ab92f7e84 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -560,7 +560,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) | |||
560 | 560 | ||
561 | p9_debug(P9_DEBUG_VFS, "\n"); | 561 | p9_debug(P9_DEBUG_VFS, "\n"); |
562 | 562 | ||
563 | retval = inode_change_ok(inode, iattr); | 563 | retval = setattr_prepare(dentry, iattr); |
564 | if (retval) | 564 | if (retval) |
565 | return retval; | 565 | return retval; |
566 | 566 | ||
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 335055d828e4..f57baaa511aa 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c | |||
@@ -303,7 +303,7 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr) | |||
303 | unsigned int ia_valid = attr->ia_valid; | 303 | unsigned int ia_valid = attr->ia_valid; |
304 | int error; | 304 | int error; |
305 | 305 | ||
306 | error = inode_change_ok(inode, attr); | 306 | error = setattr_prepare(dentry, attr); |
307 | 307 | ||
308 | /* | 308 | /* |
309 | * we can't change the UID or GID of any file - | 309 | * we can't change the UID or GID of any file - |
diff --git a/fs/affs/inode.c b/fs/affs/inode.c index a022f4accd76..87953b94a5ae 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c | |||
@@ -218,7 +218,7 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr) | |||
218 | 218 | ||
219 | pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid); | 219 | pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid); |
220 | 220 | ||
221 | error = inode_change_ok(inode,attr); | 221 | error = setattr_prepare(dentry, attr); |
222 | if (error) | 222 | if (error) |
223 | goto out; | 223 | goto out; |
224 | 224 | ||
@@ -17,19 +17,22 @@ | |||
17 | #include <linux/ima.h> | 17 | #include <linux/ima.h> |
18 | 18 | ||
19 | /** | 19 | /** |
20 | * inode_change_ok - check if attribute changes to an inode are allowed | 20 | * setattr_prepare - check if attribute changes to a dentry are allowed |
21 | * @inode: inode to check | 21 | * @dentry: dentry to check |
22 | * @attr: attributes to change | 22 | * @attr: attributes to change |
23 | * | 23 | * |
24 | * Check if we are allowed to change the attributes contained in @attr | 24 | * Check if we are allowed to change the attributes contained in @attr |
25 | * in the given inode. This includes the normal unix access permission | 25 | * in the given dentry. This includes the normal unix access permission |
26 | * checks, as well as checks for rlimits and others. | 26 | * checks, as well as checks for rlimits and others. The function also clears |
27 | * SGID bit from mode if user is not allowed to set it. Also file capabilities | ||
28 | * and IMA extended attributes are cleared if ATTR_KILL_PRIV is set. | ||
27 | * | 29 | * |
28 | * Should be called as the first thing in ->setattr implementations, | 30 | * Should be called as the first thing in ->setattr implementations, |
29 | * possibly after taking additional locks. | 31 | * possibly after taking additional locks. |
30 | */ | 32 | */ |
31 | int inode_change_ok(const struct inode *inode, struct iattr *attr) | 33 | int setattr_prepare(struct dentry *dentry, struct iattr *attr) |
32 | { | 34 | { |
35 | struct inode *inode = d_inode(dentry); | ||
33 | unsigned int ia_valid = attr->ia_valid; | 36 | unsigned int ia_valid = attr->ia_valid; |
34 | 37 | ||
35 | /* | 38 | /* |
@@ -44,7 +47,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) | |||
44 | 47 | ||
45 | /* If force is set do it anyway. */ | 48 | /* If force is set do it anyway. */ |
46 | if (ia_valid & ATTR_FORCE) | 49 | if (ia_valid & ATTR_FORCE) |
47 | return 0; | 50 | goto kill_priv; |
48 | 51 | ||
49 | /* Make sure a caller can chown. */ | 52 | /* Make sure a caller can chown. */ |
50 | if ((ia_valid & ATTR_UID) && | 53 | if ((ia_valid & ATTR_UID) && |
@@ -77,9 +80,19 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) | |||
77 | return -EPERM; | 80 | return -EPERM; |
78 | } | 81 | } |
79 | 82 | ||
83 | kill_priv: | ||
84 | /* User has permission for the change */ | ||
85 | if (ia_valid & ATTR_KILL_PRIV) { | ||
86 | int error; | ||
87 | |||
88 | error = security_inode_killpriv(dentry); | ||
89 | if (error) | ||
90 | return error; | ||
91 | } | ||
92 | |||
80 | return 0; | 93 | return 0; |
81 | } | 94 | } |
82 | EXPORT_SYMBOL(inode_change_ok); | 95 | EXPORT_SYMBOL(setattr_prepare); |
83 | 96 | ||
84 | /** | 97 | /** |
85 | * inode_newsize_ok - may this inode be truncated to a given size | 98 | * inode_newsize_ok - may this inode be truncated to a given size |
@@ -217,13 +230,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de | |||
217 | if (!(ia_valid & ATTR_MTIME_SET)) | 230 | if (!(ia_valid & ATTR_MTIME_SET)) |
218 | attr->ia_mtime = now; | 231 | attr->ia_mtime = now; |
219 | if (ia_valid & ATTR_KILL_PRIV) { | 232 | if (ia_valid & ATTR_KILL_PRIV) { |
220 | attr->ia_valid &= ~ATTR_KILL_PRIV; | ||
221 | ia_valid &= ~ATTR_KILL_PRIV; | ||
222 | error = security_inode_need_killpriv(dentry); | 233 | error = security_inode_need_killpriv(dentry); |
223 | if (error > 0) | 234 | if (error < 0) |
224 | error = security_inode_killpriv(dentry); | ||
225 | if (error) | ||
226 | return error; | 235 | return error; |
236 | if (error == 0) | ||
237 | ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV; | ||
227 | } | 238 | } |
228 | 239 | ||
229 | /* | 240 | /* |
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 9a0124a95851..fb3e64d37cb4 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -83,11 +83,9 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, | |||
83 | case ACL_TYPE_ACCESS: | 83 | case ACL_TYPE_ACCESS: |
84 | name = POSIX_ACL_XATTR_ACCESS; | 84 | name = POSIX_ACL_XATTR_ACCESS; |
85 | if (acl) { | 85 | if (acl) { |
86 | ret = posix_acl_equiv_mode(acl, &inode->i_mode); | 86 | ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
87 | if (ret < 0) | 87 | if (ret) |
88 | return ret; | 88 | return ret; |
89 | if (ret == 0) | ||
90 | acl = NULL; | ||
91 | } | 89 | } |
92 | ret = 0; | 90 | ret = 0; |
93 | break; | 91 | break; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c4771af7fd6f..757a34bdd2b9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4975,7 +4975,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
4975 | if (btrfs_root_readonly(root)) | 4975 | if (btrfs_root_readonly(root)) |
4976 | return -EROFS; | 4976 | return -EROFS; |
4977 | 4977 | ||
4978 | err = inode_change_ok(inode, attr); | 4978 | err = setattr_prepare(dentry, attr); |
4979 | if (err) | 4979 | if (err) |
4980 | return err; | 4980 | return err; |
4981 | 4981 | ||
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 64fa248343f6..d7496e3dbfc4 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c | |||
@@ -94,11 +94,9 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
94 | case ACL_TYPE_ACCESS: | 94 | case ACL_TYPE_ACCESS: |
95 | name = POSIX_ACL_XATTR_ACCESS; | 95 | name = POSIX_ACL_XATTR_ACCESS; |
96 | if (acl) { | 96 | if (acl) { |
97 | ret = posix_acl_equiv_mode(acl, &new_mode); | 97 | ret = posix_acl_update_mode(inode, &new_mode, &acl); |
98 | if (ret < 0) | 98 | if (ret) |
99 | goto out; | 99 | goto out; |
100 | if (ret == 0) | ||
101 | acl = NULL; | ||
102 | } | 100 | } |
103 | break; | 101 | break; |
104 | case ACL_TYPE_DEFAULT: | 102 | case ACL_TYPE_DEFAULT: |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index e876e1944519..4484aaf5c478 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -1728,7 +1728,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1728 | if (ceph_snap(inode) != CEPH_NOSNAP) | 1728 | if (ceph_snap(inode) != CEPH_NOSNAP) |
1729 | return -EROFS; | 1729 | return -EROFS; |
1730 | 1730 | ||
1731 | err = inode_change_ok(inode, attr); | 1731 | err = setattr_prepare(dentry, attr); |
1732 | if (err != 0) | 1732 | if (err != 0) |
1733 | return err; | 1733 | return err; |
1734 | 1734 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9fb3bc26a2ab..f82dfe7ae3e8 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -2134,7 +2134,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
2134 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) | 2134 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
2135 | attrs->ia_valid |= ATTR_FORCE; | 2135 | attrs->ia_valid |= ATTR_FORCE; |
2136 | 2136 | ||
2137 | rc = inode_change_ok(inode, attrs); | 2137 | rc = setattr_prepare(direntry, attrs); |
2138 | if (rc < 0) | 2138 | if (rc < 0) |
2139 | goto out; | 2139 | goto out; |
2140 | 2140 | ||
@@ -2274,7 +2274,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
2274 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) | 2274 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
2275 | attrs->ia_valid |= ATTR_FORCE; | 2275 | attrs->ia_valid |= ATTR_FORCE; |
2276 | 2276 | ||
2277 | rc = inode_change_ok(inode, attrs); | 2277 | rc = setattr_prepare(direntry, attrs); |
2278 | if (rc < 0) { | 2278 | if (rc < 0) { |
2279 | free_xid(xid); | 2279 | free_xid(xid); |
2280 | return rc; | 2280 | return rc; |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index fc850b55db67..661dd53f0040 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -942,7 +942,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
942 | } | 942 | } |
943 | mutex_unlock(&crypt_stat->cs_mutex); | 943 | mutex_unlock(&crypt_stat->cs_mutex); |
944 | 944 | ||
945 | rc = inode_change_ok(inode, ia); | 945 | rc = setattr_prepare(dentry, ia); |
946 | if (rc) | 946 | if (rc) |
947 | goto out; | 947 | goto out; |
948 | if (ia->ia_valid & ATTR_SIZE) { | 948 | if (ia->ia_valid & ATTR_SIZE) { |
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 786e4cc8c889..159c30c18395 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
@@ -1038,7 +1038,7 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
1038 | if (unlikely(error)) | 1038 | if (unlikely(error)) |
1039 | return error; | 1039 | return error; |
1040 | 1040 | ||
1041 | error = inode_change_ok(inode, iattr); | 1041 | error = setattr_prepare(dentry, iattr); |
1042 | if (unlikely(error)) | 1042 | if (unlikely(error)) |
1043 | return error; | 1043 | return error; |
1044 | 1044 | ||
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 27695e6f4e46..d6aeb84e90b6 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c | |||
@@ -193,15 +193,11 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
193 | case ACL_TYPE_ACCESS: | 193 | case ACL_TYPE_ACCESS: |
194 | name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; | 194 | name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; |
195 | if (acl) { | 195 | if (acl) { |
196 | error = posix_acl_equiv_mode(acl, &inode->i_mode); | 196 | error = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
197 | if (error < 0) | 197 | if (error) |
198 | return error; | 198 | return error; |
199 | else { | 199 | inode->i_ctime = CURRENT_TIME_SEC; |
200 | inode->i_ctime = CURRENT_TIME_SEC; | 200 | mark_inode_dirty(inode); |
201 | mark_inode_dirty(inode); | ||
202 | if (error == 0) | ||
203 | acl = NULL; | ||
204 | } | ||
205 | } | 201 | } |
206 | break; | 202 | break; |
207 | 203 | ||
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index fd13c959958c..7841d71421aa 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -1548,7 +1548,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr) | |||
1548 | struct inode *inode = d_inode(dentry); | 1548 | struct inode *inode = d_inode(dentry); |
1549 | int error; | 1549 | int error; |
1550 | 1550 | ||
1551 | error = inode_change_ok(inode, iattr); | 1551 | error = setattr_prepare(dentry, iattr); |
1552 | if (error) | 1552 | if (error) |
1553 | return error; | 1553 | return error; |
1554 | 1554 | ||
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 2ee2dc4351d1..3613e87c688f 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -3244,7 +3244,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr) | |||
3244 | int error, rc = 0; | 3244 | int error, rc = 0; |
3245 | const unsigned int ia_valid = attr->ia_valid; | 3245 | const unsigned int ia_valid = attr->ia_valid; |
3246 | 3246 | ||
3247 | error = inode_change_ok(inode, attr); | 3247 | error = setattr_prepare(dentry, attr); |
3248 | if (error) | 3248 | if (error) |
3249 | return error; | 3249 | return error; |
3250 | 3250 | ||
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 69b1e73026a5..c3fe1e323951 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c | |||
@@ -196,15 +196,11 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type, | |||
196 | case ACL_TYPE_ACCESS: | 196 | case ACL_TYPE_ACCESS: |
197 | name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; | 197 | name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; |
198 | if (acl) { | 198 | if (acl) { |
199 | error = posix_acl_equiv_mode(acl, &inode->i_mode); | 199 | error = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
200 | if (error < 0) | 200 | if (error) |
201 | return error; | 201 | return error; |
202 | else { | 202 | inode->i_ctime = ext4_current_time(inode); |
203 | inode->i_ctime = ext4_current_time(inode); | 203 | ext4_mark_inode_dirty(handle, inode); |
204 | ext4_mark_inode_dirty(handle, inode); | ||
205 | if (error == 0) | ||
206 | acl = NULL; | ||
207 | } | ||
208 | } | 204 | } |
209 | break; | 205 | break; |
210 | 206 | ||
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index e6e2f99c1e5b..a03ffdbebd1a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1008,6 +1008,7 @@ struct ext4_inode_info { | |||
1008 | /* | 1008 | /* |
1009 | * Mount flags set via mount options or defaults | 1009 | * Mount flags set via mount options or defaults |
1010 | */ | 1010 | */ |
1011 | #define EXT4_MOUNT_NO_MBCACHE 0x00001 /* Disable mbcache */ | ||
1011 | #define EXT4_MOUNT_GRPID 0x00004 /* Create files with directory's group */ | 1012 | #define EXT4_MOUNT_GRPID 0x00004 /* Create files with directory's group */ |
1012 | #define EXT4_MOUNT_DEBUG 0x00008 /* Some debugging messages */ | 1013 | #define EXT4_MOUNT_DEBUG 0x00008 /* Some debugging messages */ |
1013 | #define EXT4_MOUNT_ERRORS_CONT 0x00010 /* Continue on errors */ | 1014 | #define EXT4_MOUNT_ERRORS_CONT 0x00010 /* Continue on errors */ |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 3715bd69b3a6..55fe18a700d0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4763,7 +4763,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
4763 | int orphan = 0; | 4763 | int orphan = 0; |
4764 | const unsigned int ia_valid = attr->ia_valid; | 4764 | const unsigned int ia_valid = attr->ia_valid; |
4765 | 4765 | ||
4766 | error = inode_change_ok(inode, attr); | 4766 | error = setattr_prepare(dentry, attr); |
4767 | if (error) | 4767 | if (error) |
4768 | return error; | 4768 | return error; |
4769 | 4769 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9bde825fb2d2..29e1be6c68cc 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1145,6 +1145,7 @@ enum { | |||
1145 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, | 1145 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, |
1146 | Opt_inode_readahead_blks, Opt_journal_ioprio, | 1146 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
1147 | Opt_dioread_nolock, Opt_dioread_lock, | 1147 | Opt_dioread_nolock, Opt_dioread_lock, |
1148 | Opt_no_mbcache, | ||
1148 | Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, | 1149 | Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, |
1149 | Opt_max_dir_size_kb, Opt_nojournal_checksum, | 1150 | Opt_max_dir_size_kb, Opt_nojournal_checksum, |
1150 | }; | 1151 | }; |
@@ -1223,6 +1224,7 @@ static const match_table_t tokens = { | |||
1223 | {Opt_discard, "discard"}, | 1224 | {Opt_discard, "discard"}, |
1224 | {Opt_nodiscard, "nodiscard"}, | 1225 | {Opt_nodiscard, "nodiscard"}, |
1225 | {Opt_init_itable, "init_itable=%u"}, | 1226 | {Opt_init_itable, "init_itable=%u"}, |
1227 | {Opt_no_mbcache, "no_mbcache"}, | ||
1226 | {Opt_init_itable, "init_itable"}, | 1228 | {Opt_init_itable, "init_itable"}, |
1227 | {Opt_noinit_itable, "noinit_itable"}, | 1229 | {Opt_noinit_itable, "noinit_itable"}, |
1228 | {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, | 1230 | {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, |
@@ -1386,6 +1388,7 @@ static const struct mount_opts { | |||
1386 | {Opt_noauto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_SET}, | 1388 | {Opt_noauto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_SET}, |
1387 | {Opt_auto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_CLEAR}, | 1389 | {Opt_auto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_CLEAR}, |
1388 | {Opt_noinit_itable, EXT4_MOUNT_INIT_INODE_TABLE, MOPT_CLEAR}, | 1390 | {Opt_noinit_itable, EXT4_MOUNT_INIT_INODE_TABLE, MOPT_CLEAR}, |
1391 | {Opt_no_mbcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET}, | ||
1389 | {Opt_commit, 0, MOPT_GTE0}, | 1392 | {Opt_commit, 0, MOPT_GTE0}, |
1390 | {Opt_max_batch_time, 0, MOPT_GTE0}, | 1393 | {Opt_max_batch_time, 0, MOPT_GTE0}, |
1391 | {Opt_min_batch_time, 0, MOPT_GTE0}, | 1394 | {Opt_min_batch_time, 0, MOPT_GTE0}, |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 16e28c08d1e8..cdc26e54400f 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -80,7 +80,7 @@ | |||
80 | # define ea_bdebug(bh, fmt, ...) no_printk(fmt, ##__VA_ARGS__) | 80 | # define ea_bdebug(bh, fmt, ...) no_printk(fmt, ##__VA_ARGS__) |
81 | #endif | 81 | #endif |
82 | 82 | ||
83 | static void ext4_xattr_cache_insert(struct mb_cache *, struct buffer_head *); | 83 | static void ext4_xattr_cache_insert(struct inode *, struct buffer_head *); |
84 | static struct buffer_head *ext4_xattr_cache_find(struct inode *, | 84 | static struct buffer_head *ext4_xattr_cache_find(struct inode *, |
85 | struct ext4_xattr_header *, | 85 | struct ext4_xattr_header *, |
86 | struct mb_cache_entry **); | 86 | struct mb_cache_entry **); |
@@ -278,7 +278,6 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, | |||
278 | struct ext4_xattr_entry *entry; | 278 | struct ext4_xattr_entry *entry; |
279 | size_t size; | 279 | size_t size; |
280 | int error; | 280 | int error; |
281 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
282 | 281 | ||
283 | ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", | 282 | ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", |
284 | name_index, name, buffer, (long)buffer_size); | 283 | name_index, name, buffer, (long)buffer_size); |
@@ -300,7 +299,7 @@ bad_block: | |||
300 | error = -EIO; | 299 | error = -EIO; |
301 | goto cleanup; | 300 | goto cleanup; |
302 | } | 301 | } |
303 | ext4_xattr_cache_insert(ext4_mb_cache, bh); | 302 | ext4_xattr_cache_insert(inode, bh); |
304 | entry = BFIRST(bh); | 303 | entry = BFIRST(bh); |
305 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); | 304 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); |
306 | if (error == -EIO) | 305 | if (error == -EIO) |
@@ -426,7 +425,6 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
426 | struct inode *inode = d_inode(dentry); | 425 | struct inode *inode = d_inode(dentry); |
427 | struct buffer_head *bh = NULL; | 426 | struct buffer_head *bh = NULL; |
428 | int error; | 427 | int error; |
429 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
430 | 428 | ||
431 | ea_idebug(inode, "buffer=%p, buffer_size=%ld", | 429 | ea_idebug(inode, "buffer=%p, buffer_size=%ld", |
432 | buffer, (long)buffer_size); | 430 | buffer, (long)buffer_size); |
@@ -448,7 +446,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
448 | error = -EIO; | 446 | error = -EIO; |
449 | goto cleanup; | 447 | goto cleanup; |
450 | } | 448 | } |
451 | ext4_xattr_cache_insert(ext4_mb_cache, bh); | 449 | ext4_xattr_cache_insert(inode, bh); |
452 | error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); | 450 | error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); |
453 | 451 | ||
454 | cleanup: | 452 | cleanup: |
@@ -547,7 +545,8 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
547 | int error = 0; | 545 | int error = 0; |
548 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | 546 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); |
549 | 547 | ||
550 | ce = mb_cache_entry_get(ext4_mb_cache, bh->b_bdev, bh->b_blocknr); | 548 | if (!test_opt(inode->i_sb, NO_MBCACHE)) |
549 | ce = mb_cache_entry_get(ext4_mb_cache, bh->b_bdev, bh->b_blocknr); | ||
551 | BUFFER_TRACE(bh, "get_write_access"); | 550 | BUFFER_TRACE(bh, "get_write_access"); |
552 | error = ext4_journal_get_write_access(handle, bh); | 551 | error = ext4_journal_get_write_access(handle, bh); |
553 | if (error) | 552 | if (error) |
@@ -788,8 +787,9 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
788 | if (i->value && i->value_len > sb->s_blocksize) | 787 | if (i->value && i->value_len > sb->s_blocksize) |
789 | return -ENOSPC; | 788 | return -ENOSPC; |
790 | if (s->base) { | 789 | if (s->base) { |
791 | ce = mb_cache_entry_get(ext4_mb_cache, bs->bh->b_bdev, | 790 | if (!test_opt(inode->i_sb, NO_MBCACHE)) |
792 | bs->bh->b_blocknr); | 791 | ce = mb_cache_entry_get(ext4_mb_cache, bs->bh->b_bdev, |
792 | bs->bh->b_blocknr); | ||
793 | BUFFER_TRACE(bs->bh, "get_write_access"); | 793 | BUFFER_TRACE(bs->bh, "get_write_access"); |
794 | error = ext4_journal_get_write_access(handle, bs->bh); | 794 | error = ext4_journal_get_write_access(handle, bs->bh); |
795 | if (error) | 795 | if (error) |
@@ -807,7 +807,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
807 | if (!IS_LAST_ENTRY(s->first)) | 807 | if (!IS_LAST_ENTRY(s->first)) |
808 | ext4_xattr_rehash(header(s->base), | 808 | ext4_xattr_rehash(header(s->base), |
809 | s->here); | 809 | s->here); |
810 | ext4_xattr_cache_insert(ext4_mb_cache, | 810 | ext4_xattr_cache_insert(inode, |
811 | bs->bh); | 811 | bs->bh); |
812 | } | 812 | } |
813 | unlock_buffer(bs->bh); | 813 | unlock_buffer(bs->bh); |
@@ -892,7 +892,8 @@ inserted: | |||
892 | if (error) | 892 | if (error) |
893 | goto cleanup_dquot; | 893 | goto cleanup_dquot; |
894 | } | 894 | } |
895 | mb_cache_entry_release(ce); | 895 | if (ce) |
896 | mb_cache_entry_release(ce); | ||
896 | ce = NULL; | 897 | ce = NULL; |
897 | } else if (bs->bh && s->base == bs->bh->b_data) { | 898 | } else if (bs->bh && s->base == bs->bh->b_data) { |
898 | /* We were modifying this block in-place. */ | 899 | /* We were modifying this block in-place. */ |
@@ -939,7 +940,7 @@ getblk_failed: | |||
939 | memcpy(new_bh->b_data, s->base, new_bh->b_size); | 940 | memcpy(new_bh->b_data, s->base, new_bh->b_size); |
940 | set_buffer_uptodate(new_bh); | 941 | set_buffer_uptodate(new_bh); |
941 | unlock_buffer(new_bh); | 942 | unlock_buffer(new_bh); |
942 | ext4_xattr_cache_insert(ext4_mb_cache, new_bh); | 943 | ext4_xattr_cache_insert(inode, new_bh); |
943 | error = ext4_handle_dirty_xattr_block(handle, | 944 | error = ext4_handle_dirty_xattr_block(handle, |
944 | inode, new_bh); | 945 | inode, new_bh); |
945 | if (error) | 946 | if (error) |
@@ -1529,12 +1530,17 @@ ext4_xattr_put_super(struct super_block *sb) | |||
1529 | * Returns 0, or a negative error number on failure. | 1530 | * Returns 0, or a negative error number on failure. |
1530 | */ | 1531 | */ |
1531 | static void | 1532 | static void |
1532 | ext4_xattr_cache_insert(struct mb_cache *ext4_mb_cache, struct buffer_head *bh) | 1533 | ext4_xattr_cache_insert(struct inode *inode, struct buffer_head *bh) |
1533 | { | 1534 | { |
1535 | struct super_block *sb = inode->i_sb; | ||
1536 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | ||
1534 | __u32 hash = le32_to_cpu(BHDR(bh)->h_hash); | 1537 | __u32 hash = le32_to_cpu(BHDR(bh)->h_hash); |
1535 | struct mb_cache_entry *ce; | 1538 | struct mb_cache_entry *ce; |
1536 | int error; | 1539 | int error; |
1537 | 1540 | ||
1541 | if (test_opt(sb, NO_MBCACHE)) | ||
1542 | return; | ||
1543 | |||
1538 | ce = mb_cache_entry_alloc(ext4_mb_cache, GFP_NOFS); | 1544 | ce = mb_cache_entry_alloc(ext4_mb_cache, GFP_NOFS); |
1539 | if (!ce) { | 1545 | if (!ce) { |
1540 | ea_bdebug(bh, "out of memory"); | 1546 | ea_bdebug(bh, "out of memory"); |
@@ -1609,6 +1615,8 @@ ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header, | |||
1609 | struct mb_cache_entry *ce; | 1615 | struct mb_cache_entry *ce; |
1610 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); | 1616 | struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); |
1611 | 1617 | ||
1618 | if (test_opt(inode->i_sb, NO_MBCACHE)) | ||
1619 | return NULL; | ||
1612 | if (!header->h_hash) | 1620 | if (!header->h_hash) |
1613 | return NULL; /* never share */ | 1621 | return NULL; /* never share */ |
1614 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); | 1622 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); |
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index 4320ffab3495..c5e4a1856a0f 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c | |||
@@ -214,12 +214,10 @@ static int __f2fs_set_acl(struct inode *inode, int type, | |||
214 | case ACL_TYPE_ACCESS: | 214 | case ACL_TYPE_ACCESS: |
215 | name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; | 215 | name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; |
216 | if (acl) { | 216 | if (acl) { |
217 | error = posix_acl_equiv_mode(acl, &inode->i_mode); | 217 | error = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
218 | if (error < 0) | 218 | if (error) |
219 | return error; | 219 | return error; |
220 | set_acl_inode(fi, inode->i_mode); | 220 | set_acl_inode(fi, inode->i_mode); |
221 | if (error == 0) | ||
222 | acl = NULL; | ||
223 | } | 221 | } |
224 | break; | 222 | break; |
225 | 223 | ||
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 2b52e48d7482..85e40c0fdcc4 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -617,7 +617,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr) | |||
617 | struct f2fs_inode_info *fi = F2FS_I(inode); | 617 | struct f2fs_inode_info *fi = F2FS_I(inode); |
618 | int err; | 618 | int err; |
619 | 619 | ||
620 | err = inode_change_ok(inode, attr); | 620 | err = setattr_prepare(dentry, attr); |
621 | if (err) | 621 | if (err) |
622 | return err; | 622 | return err; |
623 | 623 | ||
diff --git a/fs/fat/file.c b/fs/fat/file.c index a08f1039909a..1254f8438f20 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -389,7 +389,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
389 | attr->ia_valid &= ~TIMES_SET_FLAGS; | 389 | attr->ia_valid &= ~TIMES_SET_FLAGS; |
390 | } | 390 | } |
391 | 391 | ||
392 | error = inode_change_ok(inode, attr); | 392 | error = setattr_prepare(dentry, attr); |
393 | attr->ia_valid = ia_valid; | 393 | attr->ia_valid = ia_valid; |
394 | if (error) { | 394 | if (error) { |
395 | if (sbi->options.quiet) | 395 | if (sbi->options.quiet) |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 0572bca49f15..88b09a33d117 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1602,9 +1602,10 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff) | |||
1602 | * vmtruncate() doesn't allow for this case, so do the rlimit checking | 1602 | * vmtruncate() doesn't allow for this case, so do the rlimit checking |
1603 | * and the actual truncation by hand. | 1603 | * and the actual truncation by hand. |
1604 | */ | 1604 | */ |
1605 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | 1605 | int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, |
1606 | struct file *file) | 1606 | struct file *file) |
1607 | { | 1607 | { |
1608 | struct inode *inode = d_inode(dentry); | ||
1608 | struct fuse_conn *fc = get_fuse_conn(inode); | 1609 | struct fuse_conn *fc = get_fuse_conn(inode); |
1609 | struct fuse_inode *fi = get_fuse_inode(inode); | 1610 | struct fuse_inode *fi = get_fuse_inode(inode); |
1610 | FUSE_ARGS(args); | 1611 | FUSE_ARGS(args); |
@@ -1619,7 +1620,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1619 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | 1620 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
1620 | attr->ia_valid |= ATTR_FORCE; | 1621 | attr->ia_valid |= ATTR_FORCE; |
1621 | 1622 | ||
1622 | err = inode_change_ok(inode, attr); | 1623 | err = setattr_prepare(dentry, attr); |
1623 | if (err) | 1624 | if (err) |
1624 | return err; | 1625 | return err; |
1625 | 1626 | ||
@@ -1718,9 +1719,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) | |||
1718 | return -EACCES; | 1719 | return -EACCES; |
1719 | 1720 | ||
1720 | if (attr->ia_valid & ATTR_FILE) | 1721 | if (attr->ia_valid & ATTR_FILE) |
1721 | return fuse_do_setattr(inode, attr, attr->ia_file); | 1722 | return fuse_do_setattr(entry, attr, attr->ia_file); |
1722 | else | 1723 | else |
1723 | return fuse_do_setattr(inode, attr, NULL); | 1724 | return fuse_do_setattr(entry, attr, NULL); |
1724 | } | 1725 | } |
1725 | 1726 | ||
1726 | static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | 1727 | static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index e84bb862f92d..8d25109929b4 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -2797,7 +2797,7 @@ static void fuse_do_truncate(struct file *file) | |||
2797 | attr.ia_file = file; | 2797 | attr.ia_file = file; |
2798 | attr.ia_valid |= ATTR_FILE; | 2798 | attr.ia_valid |= ATTR_FILE; |
2799 | 2799 | ||
2800 | fuse_do_setattr(inode, &attr, file); | 2800 | fuse_do_setattr(file->f_path.dentry, &attr, file); |
2801 | } | 2801 | } |
2802 | 2802 | ||
2803 | static inline loff_t fuse_round_up(loff_t off) | 2803 | static inline loff_t fuse_round_up(loff_t off) |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 85f9d8273455..30d2bde45f68 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -913,7 +913,7 @@ bool fuse_write_update_size(struct inode *inode, loff_t pos); | |||
913 | int fuse_flush_times(struct inode *inode, struct fuse_file *ff); | 913 | int fuse_flush_times(struct inode *inode, struct fuse_file *ff); |
914 | int fuse_write_inode(struct inode *inode, struct writeback_control *wbc); | 914 | int fuse_write_inode(struct inode *inode, struct writeback_control *wbc); |
915 | 915 | ||
916 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | 916 | int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, |
917 | struct file *file); | 917 | struct file *file); |
918 | 918 | ||
919 | void fuse_set_initialized(struct fuse_conn *fc); | 919 | void fuse_set_initialized(struct fuse_conn *fc); |
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 1be3b061c05c..ff0ac96a8e7b 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c | |||
@@ -79,17 +79,11 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
79 | if (type == ACL_TYPE_ACCESS) { | 79 | if (type == ACL_TYPE_ACCESS) { |
80 | umode_t mode = inode->i_mode; | 80 | umode_t mode = inode->i_mode; |
81 | 81 | ||
82 | error = posix_acl_equiv_mode(acl, &mode); | 82 | error = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
83 | if (error < 0) | 83 | if (error) |
84 | return error; | 84 | return error; |
85 | 85 | if (mode != inode->i_mode) | |
86 | if (error == 0) | ||
87 | acl = NULL; | ||
88 | |||
89 | if (mode != inode->i_mode) { | ||
90 | inode->i_mode = mode; | ||
91 | mark_inode_dirty(inode); | 86 | mark_inode_dirty(inode); |
92 | } | ||
93 | } | 87 | } |
94 | 88 | ||
95 | if (acl) { | 89 | if (acl) { |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 1b3ca7a2e3fc..6f7f848a3c4e 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -1759,7 +1759,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
1759 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 1759 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
1760 | goto out; | 1760 | goto out; |
1761 | 1761 | ||
1762 | error = inode_change_ok(inode, attr); | 1762 | error = setattr_prepare(dentry, attr); |
1763 | if (error) | 1763 | if (error) |
1764 | goto out; | 1764 | goto out; |
1765 | 1765 | ||
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index b99ebddb10cb..6409b8b4afd4 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
@@ -604,7 +604,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr) | |||
604 | struct hfs_sb_info *hsb = HFS_SB(inode->i_sb); | 604 | struct hfs_sb_info *hsb = HFS_SB(inode->i_sb); |
605 | int error; | 605 | int error; |
606 | 606 | ||
607 | error = inode_change_ok(inode, attr); /* basic permission checks */ | 607 | error = setattr_prepare(dentry, attr); /* basic permission checks */ |
608 | if (error) | 608 | if (error) |
609 | return error; | 609 | return error; |
610 | 610 | ||
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 6dd107d7421e..d87c8a27e063 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -246,7 +246,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr) | |||
246 | struct inode *inode = d_inode(dentry); | 246 | struct inode *inode = d_inode(dentry); |
247 | int error; | 247 | int error; |
248 | 248 | ||
249 | error = inode_change_ok(inode, attr); | 249 | error = setattr_prepare(dentry, attr); |
250 | if (error) | 250 | if (error) |
251 | return error; | 251 | return error; |
252 | 252 | ||
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c index df0c9af68d05..71b3087b7e32 100644 --- a/fs/hfsplus/posix_acl.c +++ b/fs/hfsplus/posix_acl.c | |||
@@ -68,8 +68,8 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, | |||
68 | case ACL_TYPE_ACCESS: | 68 | case ACL_TYPE_ACCESS: |
69 | xattr_name = POSIX_ACL_XATTR_ACCESS; | 69 | xattr_name = POSIX_ACL_XATTR_ACCESS; |
70 | if (acl) { | 70 | if (acl) { |
71 | err = posix_acl_equiv_mode(acl, &inode->i_mode); | 71 | err = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
72 | if (err < 0) | 72 | if (err) |
73 | return err; | 73 | return err; |
74 | } | 74 | } |
75 | err = 0; | 75 | err = 0; |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index f895a85d9304..81ce4e4ad0f9 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -812,7 +812,7 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
812 | 812 | ||
813 | int fd = HOSTFS_I(inode)->fd; | 813 | int fd = HOSTFS_I(inode)->fd; |
814 | 814 | ||
815 | err = inode_change_ok(inode, attr); | 815 | err = setattr_prepare(dentry, attr); |
816 | if (err) | 816 | if (err) |
817 | return err; | 817 | return err; |
818 | 818 | ||
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 933c73780813..efbed9520fdc 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c | |||
@@ -272,7 +272,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
272 | if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) | 272 | if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) |
273 | goto out_unlock; | 273 | goto out_unlock; |
274 | 274 | ||
275 | error = inode_change_ok(inode, attr); | 275 | error = setattr_prepare(dentry, attr); |
276 | if (error) | 276 | if (error) |
277 | goto out_unlock; | 277 | goto out_unlock; |
278 | 278 | ||
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 87724c1d7be6..a533d8c66489 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -400,7 +400,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
400 | 400 | ||
401 | BUG_ON(!inode); | 401 | BUG_ON(!inode); |
402 | 402 | ||
403 | error = inode_change_ok(inode, attr); | 403 | error = setattr_prepare(dentry, attr); |
404 | if (error) | 404 | if (error) |
405 | return error; | 405 | return error; |
406 | 406 | ||
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 2f7a3c090489..f9f86f87d32b 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c | |||
@@ -235,9 +235,10 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
235 | case ACL_TYPE_ACCESS: | 235 | case ACL_TYPE_ACCESS: |
236 | xprefix = JFFS2_XPREFIX_ACL_ACCESS; | 236 | xprefix = JFFS2_XPREFIX_ACL_ACCESS; |
237 | if (acl) { | 237 | if (acl) { |
238 | umode_t mode = inode->i_mode; | 238 | umode_t mode; |
239 | rc = posix_acl_equiv_mode(acl, &mode); | 239 | |
240 | if (rc < 0) | 240 | rc = posix_acl_update_mode(inode, &mode, &acl); |
241 | if (rc) | ||
241 | return rc; | 242 | return rc; |
242 | if (inode->i_mode != mode) { | 243 | if (inode->i_mode != mode) { |
243 | struct iattr attr; | 244 | struct iattr attr; |
@@ -249,8 +250,6 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
249 | if (rc < 0) | 250 | if (rc < 0) |
250 | return rc; | 251 | return rc; |
251 | } | 252 | } |
252 | if (rc == 0) | ||
253 | acl = NULL; | ||
254 | } | 253 | } |
255 | break; | 254 | break; |
256 | case ACL_TYPE_DEFAULT: | 255 | case ACL_TYPE_DEFAULT: |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index fe5ea080b4ec..6273abad377f 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -193,7 +193,7 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) | |||
193 | struct inode *inode = d_inode(dentry); | 193 | struct inode *inode = d_inode(dentry); |
194 | int rc; | 194 | int rc; |
195 | 195 | ||
196 | rc = inode_change_ok(inode, iattr); | 196 | rc = setattr_prepare(dentry, iattr); |
197 | if (rc) | 197 | if (rc) |
198 | return rc; | 198 | return rc; |
199 | 199 | ||
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 0c8ca830b113..9fad9f4fe883 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c | |||
@@ -84,13 +84,11 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, | |||
84 | case ACL_TYPE_ACCESS: | 84 | case ACL_TYPE_ACCESS: |
85 | ea_name = POSIX_ACL_XATTR_ACCESS; | 85 | ea_name = POSIX_ACL_XATTR_ACCESS; |
86 | if (acl) { | 86 | if (acl) { |
87 | rc = posix_acl_equiv_mode(acl, &inode->i_mode); | 87 | rc = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
88 | if (rc < 0) | 88 | if (rc) |
89 | return rc; | 89 | return rc; |
90 | inode->i_ctime = CURRENT_TIME; | 90 | inode->i_ctime = CURRENT_TIME; |
91 | mark_inode_dirty(inode); | 91 | mark_inode_dirty(inode); |
92 | if (rc == 0) | ||
93 | acl = NULL; | ||
94 | } | 92 | } |
95 | break; | 93 | break; |
96 | case ACL_TYPE_DEFAULT: | 94 | case ACL_TYPE_DEFAULT: |
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index e98d39d75cf4..66d6362a9007 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
@@ -103,7 +103,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
103 | struct inode *inode = d_inode(dentry); | 103 | struct inode *inode = d_inode(dentry); |
104 | int rc; | 104 | int rc; |
105 | 105 | ||
106 | rc = inode_change_ok(inode, iattr); | 106 | rc = setattr_prepare(dentry, iattr); |
107 | if (rc) | 107 | if (rc) |
108 | return rc; | 108 | return rc; |
109 | 109 | ||
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 756dd56aaf60..a17c850a4958 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c | |||
@@ -119,7 +119,7 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr) | |||
119 | return -EINVAL; | 119 | return -EINVAL; |
120 | 120 | ||
121 | mutex_lock(&kernfs_mutex); | 121 | mutex_lock(&kernfs_mutex); |
122 | error = inode_change_ok(inode, iattr); | 122 | error = setattr_prepare(dentry, iattr); |
123 | if (error) | 123 | if (error) |
124 | goto out; | 124 | goto out; |
125 | 125 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index f4641fd27bda..50edbdc23cef 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -371,7 +371,7 @@ int simple_setattr(struct dentry *dentry, struct iattr *iattr) | |||
371 | struct inode *inode = d_inode(dentry); | 371 | struct inode *inode = d_inode(dentry); |
372 | int error; | 372 | int error; |
373 | 373 | ||
374 | error = inode_change_ok(inode, iattr); | 374 | error = setattr_prepare(dentry, iattr); |
375 | if (error) | 375 | if (error) |
376 | return error; | 376 | return error; |
377 | 377 | ||
diff --git a/fs/logfs/file.c b/fs/logfs/file.c index 1a6f0167b16a..3abe1414c3f4 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c | |||
@@ -244,7 +244,7 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
244 | struct inode *inode = d_inode(dentry); | 244 | struct inode *inode = d_inode(dentry); |
245 | int err = 0; | 245 | int err = 0; |
246 | 246 | ||
247 | err = inode_change_ok(inode, attr); | 247 | err = setattr_prepare(dentry, attr); |
248 | if (err) | 248 | if (err) |
249 | return err; | 249 | return err; |
250 | 250 | ||
diff --git a/fs/minix/file.c b/fs/minix/file.c index 94f0eb9a6e2c..a6a4797aa0d4 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c | |||
@@ -26,7 +26,7 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr) | |||
26 | struct inode *inode = d_inode(dentry); | 26 | struct inode *inode = d_inode(dentry); |
27 | int error; | 27 | int error; |
28 | 28 | ||
29 | error = inode_change_ok(inode, attr); | 29 | error = setattr_prepare(dentry, attr); |
30 | if (error) | 30 | if (error) |
31 | return error; | 31 | return error; |
32 | 32 | ||
diff --git a/fs/mount.h b/fs/mount.h index 6a61c2b3e385..2152c16ddf74 100644 --- a/fs/mount.h +++ b/fs/mount.h | |||
@@ -13,6 +13,8 @@ struct mnt_namespace { | |||
13 | u64 seq; /* Sequence number to prevent loops */ | 13 | u64 seq; /* Sequence number to prevent loops */ |
14 | wait_queue_head_t poll; | 14 | wait_queue_head_t poll; |
15 | u64 event; | 15 | u64 event; |
16 | unsigned int mounts; /* # of mounts in the namespace */ | ||
17 | unsigned int pending_mounts; | ||
16 | }; | 18 | }; |
17 | 19 | ||
18 | struct mnt_pcp { | 20 | struct mnt_pcp { |
diff --git a/fs/namespace.c b/fs/namespace.c index 556721fb0cf6..f853aaf92ec9 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include "pnode.h" | 27 | #include "pnode.h" |
28 | #include "internal.h" | 28 | #include "internal.h" |
29 | 29 | ||
30 | /* Maximum number of mounts in a mount namespace */ | ||
31 | unsigned int sysctl_mount_max __read_mostly = 100000; | ||
32 | |||
30 | static unsigned int m_hash_mask __read_mostly; | 33 | static unsigned int m_hash_mask __read_mostly; |
31 | static unsigned int m_hash_shift __read_mostly; | 34 | static unsigned int m_hash_shift __read_mostly; |
32 | static unsigned int mp_hash_mask __read_mostly; | 35 | static unsigned int mp_hash_mask __read_mostly; |
@@ -888,6 +891,9 @@ static void commit_tree(struct mount *mnt, struct mount *shadows) | |||
888 | 891 | ||
889 | list_splice(&head, n->list.prev); | 892 | list_splice(&head, n->list.prev); |
890 | 893 | ||
894 | n->mounts += n->pending_mounts; | ||
895 | n->pending_mounts = 0; | ||
896 | |||
891 | attach_shadowed(mnt, parent, shadows); | 897 | attach_shadowed(mnt, parent, shadows); |
892 | touch_mnt_namespace(n); | 898 | touch_mnt_namespace(n); |
893 | } | 899 | } |
@@ -1408,11 +1414,16 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) | |||
1408 | propagate_umount(&tmp_list); | 1414 | propagate_umount(&tmp_list); |
1409 | 1415 | ||
1410 | while (!list_empty(&tmp_list)) { | 1416 | while (!list_empty(&tmp_list)) { |
1417 | struct mnt_namespace *ns; | ||
1411 | bool disconnect; | 1418 | bool disconnect; |
1412 | p = list_first_entry(&tmp_list, struct mount, mnt_list); | 1419 | p = list_first_entry(&tmp_list, struct mount, mnt_list); |
1413 | list_del_init(&p->mnt_expire); | 1420 | list_del_init(&p->mnt_expire); |
1414 | list_del_init(&p->mnt_list); | 1421 | list_del_init(&p->mnt_list); |
1415 | __touch_mnt_namespace(p->mnt_ns); | 1422 | ns = p->mnt_ns; |
1423 | if (ns) { | ||
1424 | ns->mounts--; | ||
1425 | __touch_mnt_namespace(ns); | ||
1426 | } | ||
1416 | p->mnt_ns = NULL; | 1427 | p->mnt_ns = NULL; |
1417 | if (how & UMOUNT_SYNC) | 1428 | if (how & UMOUNT_SYNC) |
1418 | p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; | 1429 | p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; |
@@ -1821,6 +1832,28 @@ static int invent_group_ids(struct mount *mnt, bool recurse) | |||
1821 | return 0; | 1832 | return 0; |
1822 | } | 1833 | } |
1823 | 1834 | ||
1835 | int count_mounts(struct mnt_namespace *ns, struct mount *mnt) | ||
1836 | { | ||
1837 | unsigned int max = READ_ONCE(sysctl_mount_max); | ||
1838 | unsigned int mounts = 0, old, pending, sum; | ||
1839 | struct mount *p; | ||
1840 | |||
1841 | for (p = mnt; p; p = next_mnt(p, mnt)) | ||
1842 | mounts++; | ||
1843 | |||
1844 | old = ns->mounts; | ||
1845 | pending = ns->pending_mounts; | ||
1846 | sum = old + pending; | ||
1847 | if ((old > sum) || | ||
1848 | (pending > sum) || | ||
1849 | (max < sum) || | ||
1850 | (mounts > (max - sum))) | ||
1851 | return -ENOSPC; | ||
1852 | |||
1853 | ns->pending_mounts = pending + mounts; | ||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1824 | /* | 1857 | /* |
1825 | * @source_mnt : mount tree to be attached | 1858 | * @source_mnt : mount tree to be attached |
1826 | * @nd : place the mount tree @source_mnt is attached | 1859 | * @nd : place the mount tree @source_mnt is attached |
@@ -1890,10 +1923,18 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
1890 | struct path *parent_path) | 1923 | struct path *parent_path) |
1891 | { | 1924 | { |
1892 | HLIST_HEAD(tree_list); | 1925 | HLIST_HEAD(tree_list); |
1926 | struct mnt_namespace *ns = dest_mnt->mnt_ns; | ||
1893 | struct mount *child, *p; | 1927 | struct mount *child, *p; |
1894 | struct hlist_node *n; | 1928 | struct hlist_node *n; |
1895 | int err; | 1929 | int err; |
1896 | 1930 | ||
1931 | /* Is there space to add these mounts to the mount namespace? */ | ||
1932 | if (!parent_path) { | ||
1933 | err = count_mounts(ns, source_mnt); | ||
1934 | if (err) | ||
1935 | goto out; | ||
1936 | } | ||
1937 | |||
1897 | if (IS_MNT_SHARED(dest_mnt)) { | 1938 | if (IS_MNT_SHARED(dest_mnt)) { |
1898 | err = invent_group_ids(source_mnt, true); | 1939 | err = invent_group_ids(source_mnt, true); |
1899 | if (err) | 1940 | if (err) |
@@ -1930,11 +1971,13 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
1930 | out_cleanup_ids: | 1971 | out_cleanup_ids: |
1931 | while (!hlist_empty(&tree_list)) { | 1972 | while (!hlist_empty(&tree_list)) { |
1932 | child = hlist_entry(tree_list.first, struct mount, mnt_hash); | 1973 | child = hlist_entry(tree_list.first, struct mount, mnt_hash); |
1974 | child->mnt_parent->mnt_ns->pending_mounts = 0; | ||
1933 | umount_tree(child, UMOUNT_SYNC); | 1975 | umount_tree(child, UMOUNT_SYNC); |
1934 | } | 1976 | } |
1935 | unlock_mount_hash(); | 1977 | unlock_mount_hash(); |
1936 | cleanup_group_ids(source_mnt, NULL); | 1978 | cleanup_group_ids(source_mnt, NULL); |
1937 | out: | 1979 | out: |
1980 | ns->pending_mounts = 0; | ||
1938 | return err; | 1981 | return err; |
1939 | } | 1982 | } |
1940 | 1983 | ||
@@ -2758,6 +2801,8 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns) | |||
2758 | init_waitqueue_head(&new_ns->poll); | 2801 | init_waitqueue_head(&new_ns->poll); |
2759 | new_ns->event = 0; | 2802 | new_ns->event = 0; |
2760 | new_ns->user_ns = get_user_ns(user_ns); | 2803 | new_ns->user_ns = get_user_ns(user_ns); |
2804 | new_ns->mounts = 0; | ||
2805 | new_ns->pending_mounts = 0; | ||
2761 | return new_ns; | 2806 | return new_ns; |
2762 | } | 2807 | } |
2763 | 2808 | ||
@@ -2807,6 +2852,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, | |||
2807 | q = new; | 2852 | q = new; |
2808 | while (p) { | 2853 | while (p) { |
2809 | q->mnt_ns = new_ns; | 2854 | q->mnt_ns = new_ns; |
2855 | new_ns->mounts++; | ||
2810 | if (new_fs) { | 2856 | if (new_fs) { |
2811 | if (&p->mnt == new_fs->root.mnt) { | 2857 | if (&p->mnt == new_fs->root.mnt) { |
2812 | new_fs->root.mnt = mntget(&q->mnt); | 2858 | new_fs->root.mnt = mntget(&q->mnt); |
@@ -2845,6 +2891,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m) | |||
2845 | struct mount *mnt = real_mount(m); | 2891 | struct mount *mnt = real_mount(m); |
2846 | mnt->mnt_ns = new_ns; | 2892 | mnt->mnt_ns = new_ns; |
2847 | new_ns->root = mnt; | 2893 | new_ns->root = mnt; |
2894 | new_ns->mounts++; | ||
2848 | list_add(&mnt->mnt_list, &new_ns->list); | 2895 | list_add(&mnt->mnt_list, &new_ns->list); |
2849 | } else { | 2896 | } else { |
2850 | mntput(m); | 2897 | mntput(m); |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 9605a2f63549..7b1261bc2dee 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -884,7 +884,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) | |||
884 | /* ageing the dentry to force validation */ | 884 | /* ageing the dentry to force validation */ |
885 | ncp_age_dentry(server, dentry); | 885 | ncp_age_dentry(server, dentry); |
886 | 886 | ||
887 | result = inode_change_ok(inode, attr); | 887 | result = setattr_prepare(dentry, attr); |
888 | if (result < 0) | 888 | if (result < 0) |
889 | goto out; | 889 | goto out; |
890 | 890 | ||
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index aecbcd34d336..44f6f4f5eee0 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
@@ -59,13 +59,59 @@ static __be32 | |||
59 | nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, | 59 | nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp, |
60 | struct nfsd_attrstat *resp) | 60 | struct nfsd_attrstat *resp) |
61 | { | 61 | { |
62 | struct iattr *iap = &argp->attrs; | ||
63 | struct svc_fh *fhp; | ||
62 | __be32 nfserr; | 64 | __be32 nfserr; |
65 | |||
63 | dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", | 66 | dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", |
64 | SVCFH_fmt(&argp->fh), | 67 | SVCFH_fmt(&argp->fh), |
65 | argp->attrs.ia_valid, (long) argp->attrs.ia_size); | 68 | argp->attrs.ia_valid, (long) argp->attrs.ia_size); |
66 | 69 | ||
67 | fh_copy(&resp->fh, &argp->fh); | 70 | fhp = fh_copy(&resp->fh, &argp->fh); |
68 | nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0); | 71 | |
72 | /* | ||
73 | * NFSv2 does not differentiate between "set-[ac]time-to-now" | ||
74 | * which only requires access, and "set-[ac]time-to-X" which | ||
75 | * requires ownership. | ||
76 | * So if it looks like it might be "set both to the same time which | ||
77 | * is close to now", and if setattr_prepare fails, then we | ||
78 | * convert to "set to now" instead of "set to explicit time" | ||
79 | * | ||
80 | * We only call setattr_prepare as the last test as technically | ||
81 | * it is not an interface that we should be using. | ||
82 | */ | ||
83 | #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) | ||
84 | #define MAX_TOUCH_TIME_ERROR (30*60) | ||
85 | if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET && | ||
86 | iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) { | ||
87 | /* | ||
88 | * Looks probable. | ||
89 | * | ||
90 | * Now just make sure time is in the right ballpark. | ||
91 | * Solaris, at least, doesn't seem to care what the time | ||
92 | * request is. We require it be within 30 minutes of now. | ||
93 | */ | ||
94 | time_t delta = iap->ia_atime.tv_sec - get_seconds(); | ||
95 | |||
96 | nfserr = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP); | ||
97 | if (nfserr) | ||
98 | goto done; | ||
99 | |||
100 | if (delta < 0) | ||
101 | delta = -delta; | ||
102 | if (delta < MAX_TOUCH_TIME_ERROR && | ||
103 | setattr_prepare(fhp->fh_dentry, iap) != 0) { | ||
104 | /* | ||
105 | * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME. | ||
106 | * This will cause notify_change to set these times | ||
107 | * to "now" | ||
108 | */ | ||
109 | iap->ia_valid &= ~BOTH_TIME_SET; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | nfserr = nfsd_setattr(rqstp, fhp, iap, 0, (time_t)0); | ||
114 | done: | ||
69 | return nfsd_return_attrs(nfserr, resp); | 115 | return nfsd_return_attrs(nfserr, resp); |
70 | } | 116 | } |
71 | 117 | ||
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 84d770be056e..92de3747ea8b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -302,42 +302,6 @@ commit_metadata(struct svc_fh *fhp) | |||
302 | static void | 302 | static void |
303 | nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) | 303 | nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) |
304 | { | 304 | { |
305 | /* | ||
306 | * NFSv2 does not differentiate between "set-[ac]time-to-now" | ||
307 | * which only requires access, and "set-[ac]time-to-X" which | ||
308 | * requires ownership. | ||
309 | * So if it looks like it might be "set both to the same time which | ||
310 | * is close to now", and if inode_change_ok fails, then we | ||
311 | * convert to "set to now" instead of "set to explicit time" | ||
312 | * | ||
313 | * We only call inode_change_ok as the last test as technically | ||
314 | * it is not an interface that we should be using. | ||
315 | */ | ||
316 | #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) | ||
317 | #define MAX_TOUCH_TIME_ERROR (30*60) | ||
318 | if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET && | ||
319 | iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) { | ||
320 | /* | ||
321 | * Looks probable. | ||
322 | * | ||
323 | * Now just make sure time is in the right ballpark. | ||
324 | * Solaris, at least, doesn't seem to care what the time | ||
325 | * request is. We require it be within 30 minutes of now. | ||
326 | */ | ||
327 | time_t delta = iap->ia_atime.tv_sec - get_seconds(); | ||
328 | if (delta < 0) | ||
329 | delta = -delta; | ||
330 | if (delta < MAX_TOUCH_TIME_ERROR && | ||
331 | inode_change_ok(inode, iap) != 0) { | ||
332 | /* | ||
333 | * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME. | ||
334 | * This will cause notify_change to set these times | ||
335 | * to "now" | ||
336 | */ | ||
337 | iap->ia_valid &= ~BOTH_TIME_SET; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /* sanitize the mode change */ | 305 | /* sanitize the mode change */ |
342 | if (iap->ia_valid & ATTR_MODE) { | 306 | if (iap->ia_valid & ATTR_MODE) { |
343 | iap->ia_mode &= S_IALLUGO; | 307 | iap->ia_mode &= S_IALLUGO; |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 258d9fe2521a..b40df2bb5ee4 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -839,7 +839,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
839 | struct super_block *sb = inode->i_sb; | 839 | struct super_block *sb = inode->i_sb; |
840 | int err; | 840 | int err; |
841 | 841 | ||
842 | err = inode_change_ok(inode, iattr); | 842 | err = setattr_prepare(dentry, iattr); |
843 | if (err) | 843 | if (err) |
844 | return err; | 844 | return err; |
845 | 845 | ||
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index d284f07eda77..c178763893f3 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -2893,7 +2893,7 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
2893 | int err; | 2893 | int err; |
2894 | unsigned int ia_valid = attr->ia_valid; | 2894 | unsigned int ia_valid = attr->ia_valid; |
2895 | 2895 | ||
2896 | err = inode_change_ok(vi, attr); | 2896 | err = setattr_prepare(dentry, attr); |
2897 | if (err) | 2897 | if (err) |
2898 | goto out; | 2898 | goto out; |
2899 | /* We do not support NTFS ACLs yet. */ | 2899 | /* We do not support NTFS ACLs yet. */ |
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 762e5a3aecd3..c7641f656494 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c | |||
@@ -241,13 +241,11 @@ int ocfs2_set_acl(handle_t *handle, | |||
241 | case ACL_TYPE_ACCESS: | 241 | case ACL_TYPE_ACCESS: |
242 | name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; | 242 | name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; |
243 | if (acl) { | 243 | if (acl) { |
244 | umode_t mode = inode->i_mode; | 244 | umode_t mode; |
245 | ret = posix_acl_equiv_mode(acl, &mode); | ||
246 | if (ret < 0) | ||
247 | return ret; | ||
248 | 245 | ||
249 | if (ret == 0) | 246 | ret = posix_acl_update_mode(inode, &mode, &acl); |
250 | acl = NULL; | 247 | if (ret) |
248 | return ret; | ||
251 | 249 | ||
252 | ret = ocfs2_acl_set_mode(inode, di_bh, | 250 | ret = ocfs2_acl_set_mode(inode, di_bh, |
253 | handle, mode); | 251 | handle, mode); |
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c index b5cf27dcb18a..43ac2289c613 100644 --- a/fs/ocfs2/dlmfs/dlmfs.c +++ b/fs/ocfs2/dlmfs/dlmfs.c | |||
@@ -211,7 +211,7 @@ static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr) | |||
211 | struct inode *inode = d_inode(dentry); | 211 | struct inode *inode = d_inode(dentry); |
212 | 212 | ||
213 | attr->ia_valid &= ~ATTR_SIZE; | 213 | attr->ia_valid &= ~ATTR_SIZE; |
214 | error = inode_change_ok(inode, attr); | 214 | error = setattr_prepare(dentry, attr); |
215 | if (error) | 215 | if (error) |
216 | return error; | 216 | return error; |
217 | 217 | ||
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 8cb409d840dd..79e79164c6cd 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -1151,7 +1151,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
1151 | if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) | 1151 | if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) |
1152 | return 0; | 1152 | return 0; |
1153 | 1153 | ||
1154 | status = inode_change_ok(inode, attr); | 1154 | status = setattr_prepare(dentry, attr); |
1155 | if (status) | 1155 | if (status) |
1156 | return status; | 1156 | return status; |
1157 | 1157 | ||
diff --git a/fs/omfs/file.c b/fs/omfs/file.c index d9e26cfbb793..bf83e6644333 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c | |||
@@ -349,7 +349,7 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
349 | struct inode *inode = d_inode(dentry); | 349 | struct inode *inode = d_inode(dentry); |
350 | int error; | 350 | int error; |
351 | 351 | ||
352 | error = inode_change_ok(inode, attr); | 352 | error = setattr_prepare(dentry, attr); |
353 | if (error) | 353 | if (error) |
354 | return error; | 354 | return error; |
355 | 355 | ||
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 0bb8347c0d8b..d293034ae2cb 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -54,7 +54,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) | |||
54 | * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not | 54 | * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not |
55 | * check for a swapfile (which this won't be anyway). | 55 | * check for a swapfile (which this won't be anyway). |
56 | */ | 56 | */ |
57 | err = inode_change_ok(dentry->d_inode, attr); | 57 | err = setattr_prepare(dentry, attr); |
58 | if (err) | 58 | if (err) |
59 | return err; | 59 | return err; |
60 | 60 | ||
diff --git a/fs/pnode.c b/fs/pnode.c index 99899705b105..234a9ac49958 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -259,7 +259,7 @@ static int propagate_one(struct mount *m) | |||
259 | read_sequnlock_excl(&mount_lock); | 259 | read_sequnlock_excl(&mount_lock); |
260 | } | 260 | } |
261 | hlist_add_head(&child->mnt_hash, list); | 261 | hlist_add_head(&child->mnt_hash, list); |
262 | return 0; | 262 | return count_mounts(m->mnt_ns, child); |
263 | } | 263 | } |
264 | 264 | ||
265 | /* | 265 | /* |
diff --git a/fs/pnode.h b/fs/pnode.h index 0fcdbe7ca648..550f5a8b4fcf 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
@@ -52,4 +52,5 @@ void mnt_set_mountpoint(struct mount *, struct mountpoint *, | |||
52 | struct mount *copy_tree(struct mount *, struct dentry *, int); | 52 | struct mount *copy_tree(struct mount *, struct dentry *, int); |
53 | bool is_path_reachable(struct mount *, struct dentry *, | 53 | bool is_path_reachable(struct mount *, struct dentry *, |
54 | const struct path *root); | 54 | const struct path *root); |
55 | int count_mounts(struct mnt_namespace *ns, struct mount *mnt); | ||
55 | #endif /* _LINUX_PNODE_H */ | 56 | #endif /* _LINUX_PNODE_H */ |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index a9dafa83678c..0ef1c3722504 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -598,6 +598,37 @@ no_mem: | |||
598 | } | 598 | } |
599 | EXPORT_SYMBOL_GPL(posix_acl_create); | 599 | EXPORT_SYMBOL_GPL(posix_acl_create); |
600 | 600 | ||
601 | /** | ||
602 | * posix_acl_update_mode - update mode in set_acl | ||
603 | * | ||
604 | * Update the file mode when setting an ACL: compute the new file permission | ||
605 | * bits based on the ACL. In addition, if the ACL is equivalent to the new | ||
606 | * file mode, set *acl to NULL to indicate that no ACL should be set. | ||
607 | * | ||
608 | * As with chmod, clear the setgit bit if the caller is not in the owning group | ||
609 | * or capable of CAP_FSETID (see inode_change_ok). | ||
610 | * | ||
611 | * Called from set_acl inode operations. | ||
612 | */ | ||
613 | int posix_acl_update_mode(struct inode *inode, umode_t *mode_p, | ||
614 | struct posix_acl **acl) | ||
615 | { | ||
616 | umode_t mode = inode->i_mode; | ||
617 | int error; | ||
618 | |||
619 | error = posix_acl_equiv_mode(*acl, &mode); | ||
620 | if (error < 0) | ||
621 | return error; | ||
622 | if (error == 0) | ||
623 | *acl = NULL; | ||
624 | if (!in_group_p(inode->i_gid) && | ||
625 | !capable_wrt_inode_uidgid(inode, CAP_FSETID)) | ||
626 | mode &= ~S_ISGID; | ||
627 | *mode_p = mode; | ||
628 | return 0; | ||
629 | } | ||
630 | EXPORT_SYMBOL(posix_acl_update_mode); | ||
631 | |||
601 | /* | 632 | /* |
602 | * Fix up the uids and gids in posix acl extended attributes in place. | 633 | * Fix up the uids and gids in posix acl extended attributes in place. |
603 | */ | 634 | */ |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 239dca3fb676..fab32ad5d96d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -517,7 +517,7 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) | |||
517 | if (attr->ia_valid & ATTR_MODE) | 517 | if (attr->ia_valid & ATTR_MODE) |
518 | return -EPERM; | 518 | return -EPERM; |
519 | 519 | ||
520 | error = inode_change_ok(inode, attr); | 520 | error = setattr_prepare(dentry, attr); |
521 | if (error) | 521 | if (error) |
522 | return error; | 522 | return error; |
523 | 523 | ||
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index e5dee5c3188e..d99099fe62d4 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -105,7 +105,7 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) | |||
105 | struct proc_dir_entry *de = PDE(inode); | 105 | struct proc_dir_entry *de = PDE(inode); |
106 | int error; | 106 | int error; |
107 | 107 | ||
108 | error = inode_change_ok(inode, iattr); | 108 | error = setattr_prepare(dentry, iattr); |
109 | if (error) | 109 | if (error) |
110 | return error; | 110 | return error; |
111 | 111 | ||
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index fdda62e6115e..0dea606074c7 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -753,7 +753,7 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) | |||
753 | if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) | 753 | if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) |
754 | return -EPERM; | 754 | return -EPERM; |
755 | 755 | ||
756 | error = inode_change_ok(inode, attr); | 756 | error = setattr_prepare(dentry, attr); |
757 | if (error) | 757 | if (error) |
758 | return error; | 758 | return error; |
759 | 759 | ||
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index ba1323a94924..aab2593f3179 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
@@ -168,7 +168,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) | |||
168 | int ret = 0; | 168 | int ret = 0; |
169 | 169 | ||
170 | /* POSIX UID/GID verification for setting inode attributes */ | 170 | /* POSIX UID/GID verification for setting inode attributes */ |
171 | ret = inode_change_ok(inode, ia); | 171 | ret = setattr_prepare(dentry, ia); |
172 | if (ret) | 172 | if (ret) |
173 | return ret; | 173 | return ret; |
174 | 174 | ||
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index f6f2fbad9777..7da1232a78e3 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -3312,7 +3312,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
3312 | unsigned int ia_valid; | 3312 | unsigned int ia_valid; |
3313 | int error; | 3313 | int error; |
3314 | 3314 | ||
3315 | error = inode_change_ok(inode, attr); | 3315 | error = setattr_prepare(dentry, attr); |
3316 | if (error) | 3316 | if (error) |
3317 | return error; | 3317 | return error; |
3318 | 3318 | ||
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 4b34b9dc03dd..9b1824f35501 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
@@ -246,13 +246,9 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, | |||
246 | case ACL_TYPE_ACCESS: | 246 | case ACL_TYPE_ACCESS: |
247 | name = POSIX_ACL_XATTR_ACCESS; | 247 | name = POSIX_ACL_XATTR_ACCESS; |
248 | if (acl) { | 248 | if (acl) { |
249 | error = posix_acl_equiv_mode(acl, &inode->i_mode); | 249 | error = posix_acl_update_mode(inode, &inode->i_mode, &acl); |
250 | if (error < 0) | 250 | if (error) |
251 | return error; | 251 | return error; |
252 | else { | ||
253 | if (error == 0) | ||
254 | acl = NULL; | ||
255 | } | ||
256 | } | 252 | } |
257 | break; | 253 | break; |
258 | case ACL_TYPE_DEFAULT: | 254 | case ACL_TYPE_DEFAULT: |
diff --git a/fs/sysv/file.c b/fs/sysv/file.c index 82ddc09061e2..7ba997e31aeb 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c | |||
@@ -33,7 +33,7 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr) | |||
33 | struct inode *inode = d_inode(dentry); | 33 | struct inode *inode = d_inode(dentry); |
34 | int error; | 34 | int error; |
35 | 35 | ||
36 | error = inode_change_ok(inode, attr); | 36 | error = setattr_prepare(dentry, attr); |
37 | if (error) | 37 | if (error) |
38 | return error; | 38 | return error; |
39 | 39 | ||
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 75e9b2db14ab..2dc8ce485c51 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
@@ -1263,7 +1263,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr) | |||
1263 | 1263 | ||
1264 | dbg_gen("ino %lu, mode %#x, ia_valid %#x", | 1264 | dbg_gen("ino %lu, mode %#x, ia_valid %#x", |
1265 | inode->i_ino, inode->i_mode, attr->ia_valid); | 1265 | inode->i_ino, inode->i_mode, attr->ia_valid); |
1266 | err = inode_change_ok(inode, attr); | 1266 | err = setattr_prepare(dentry, attr); |
1267 | if (err) | 1267 | if (err) |
1268 | return err; | 1268 | return err; |
1269 | 1269 | ||
diff --git a/fs/udf/file.c b/fs/udf/file.c index 7a95b8fed302..889f1e5da507 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -252,7 +252,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr) | |||
252 | struct inode *inode = d_inode(dentry); | 252 | struct inode *inode = d_inode(dentry); |
253 | int error; | 253 | int error; |
254 | 254 | ||
255 | error = inode_change_ok(inode, attr); | 255 | error = setattr_prepare(dentry, attr); |
256 | if (error) | 256 | if (error) |
257 | return error; | 257 | return error; |
258 | 258 | ||
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 21154704c168..a958b36f40bb 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c | |||
@@ -496,7 +496,7 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr) | |||
496 | unsigned int ia_valid = attr->ia_valid; | 496 | unsigned int ia_valid = attr->ia_valid; |
497 | int error; | 497 | int error; |
498 | 498 | ||
499 | error = inode_change_ok(inode, attr); | 499 | error = setattr_prepare(dentry, attr); |
500 | if (error) | 500 | if (error) |
501 | return error; | 501 | return error; |
502 | 502 | ||
diff --git a/fs/utimes.c b/fs/utimes.c index aa138d64560a..61abc3051377 100644 --- a/fs/utimes.c +++ b/fs/utimes.c | |||
@@ -81,7 +81,7 @@ static int utimes_common(struct path *path, struct timespec *times) | |||
81 | newattrs.ia_valid |= ATTR_MTIME_SET; | 81 | newattrs.ia_valid |= ATTR_MTIME_SET; |
82 | } | 82 | } |
83 | /* | 83 | /* |
84 | * Tell inode_change_ok(), that this is an explicit time | 84 | * Tell setattr_prepare(), that this is an explicit time |
85 | * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET | 85 | * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET |
86 | * were used. | 86 | * were used. |
87 | */ | 87 | */ |
@@ -90,7 +90,7 @@ static int utimes_common(struct path *path, struct timespec *times) | |||
90 | /* | 90 | /* |
91 | * If times is NULL (or both times are UTIME_NOW), | 91 | * If times is NULL (or both times are UTIME_NOW), |
92 | * then we need to check permissions, because | 92 | * then we need to check permissions, because |
93 | * inode_change_ok() won't do it. | 93 | * setattr_prepare() won't do it. |
94 | */ | 94 | */ |
95 | error = -EACCES; | 95 | error = -EACCES; |
96 | if (IS_IMMUTABLE(inode)) | 96 | if (IS_IMMUTABLE(inode)) |
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 4b641676f258..e80dbfa2a7b9 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c | |||
@@ -284,16 +284,11 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
284 | return error; | 284 | return error; |
285 | 285 | ||
286 | if (type == ACL_TYPE_ACCESS) { | 286 | if (type == ACL_TYPE_ACCESS) { |
287 | umode_t mode = inode->i_mode; | 287 | umode_t mode; |
288 | error = posix_acl_equiv_mode(acl, &mode); | ||
289 | |||
290 | if (error <= 0) { | ||
291 | acl = NULL; | ||
292 | |||
293 | if (error < 0) | ||
294 | return error; | ||
295 | } | ||
296 | 288 | ||
289 | error = posix_acl_update_mode(inode, &mode, &acl); | ||
290 | if (error) | ||
291 | return error; | ||
297 | error = xfs_set_mode(inode, mode); | 292 | error = xfs_set_mode(inode, mode); |
298 | if (error) | 293 | if (error) |
299 | return error; | 294 | return error; |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 7c62fca53e2f..a90a950b4c45 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -974,7 +974,7 @@ xfs_file_fallocate( | |||
974 | 974 | ||
975 | iattr.ia_valid = ATTR_SIZE; | 975 | iattr.ia_valid = ATTR_SIZE; |
976 | iattr.ia_size = new_size; | 976 | iattr.ia_size = new_size; |
977 | error = xfs_setattr_size(ip, &iattr); | 977 | error = xfs_vn_setattr_size(file->f_path.dentry, &iattr); |
978 | if (error) | 978 | if (error) |
979 | goto out_unlock; | 979 | goto out_unlock; |
980 | } | 980 | } |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c29f34253e2b..6b67d617c092 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1766,7 +1766,7 @@ xfs_inactive_truncate( | |||
1766 | /* | 1766 | /* |
1767 | * Log the inode size first to prevent stale data exposure in the event | 1767 | * Log the inode size first to prevent stale data exposure in the event |
1768 | * of a system crash before the truncate completes. See the related | 1768 | * of a system crash before the truncate completes. See the related |
1769 | * comment in xfs_setattr_size() for details. | 1769 | * comment in xfs_vn_setattr_size() for details. |
1770 | */ | 1770 | */ |
1771 | ip->i_d.di_size = 0; | 1771 | ip->i_d.di_size = 0; |
1772 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 1772 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 87f67c6b654c..82e49109d0b6 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -720,7 +720,7 @@ xfs_ioc_space( | |||
720 | iattr.ia_valid = ATTR_SIZE; | 720 | iattr.ia_valid = ATTR_SIZE; |
721 | iattr.ia_size = bf->l_start; | 721 | iattr.ia_size = bf->l_start; |
722 | 722 | ||
723 | error = xfs_setattr_size(ip, &iattr); | 723 | error = xfs_vn_setattr_size(filp->f_path.dentry, &iattr); |
724 | break; | 724 | break; |
725 | default: | 725 | default: |
726 | ASSERT(0); | 726 | ASSERT(0); |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f4cd7204e236..4e4d6511185b 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -537,6 +537,30 @@ xfs_setattr_time( | |||
537 | } | 537 | } |
538 | } | 538 | } |
539 | 539 | ||
540 | static int | ||
541 | xfs_vn_change_ok( | ||
542 | struct dentry *dentry, | ||
543 | struct iattr *iattr) | ||
544 | { | ||
545 | struct inode *inode = d_inode(dentry); | ||
546 | struct xfs_inode *ip = XFS_I(inode); | ||
547 | struct xfs_mount *mp = ip->i_mount; | ||
548 | |||
549 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
550 | return -EROFS; | ||
551 | |||
552 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
553 | return -EIO; | ||
554 | |||
555 | return setattr_prepare(dentry, iattr); | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * Set non-size attributes of an inode. | ||
560 | * | ||
561 | * Caution: The caller of this function is responsible for calling | ||
562 | * setattr_prepare() or otherwise verifying the change is fine. | ||
563 | */ | ||
540 | int | 564 | int |
541 | xfs_setattr_nonsize( | 565 | xfs_setattr_nonsize( |
542 | struct xfs_inode *ip, | 566 | struct xfs_inode *ip, |
@@ -553,21 +577,6 @@ xfs_setattr_nonsize( | |||
553 | struct xfs_dquot *udqp = NULL, *gdqp = NULL; | 577 | struct xfs_dquot *udqp = NULL, *gdqp = NULL; |
554 | struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL; | 578 | struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL; |
555 | 579 | ||
556 | trace_xfs_setattr(ip); | ||
557 | |||
558 | /* If acls are being inherited, we already have this checked */ | ||
559 | if (!(flags & XFS_ATTR_NOACL)) { | ||
560 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
561 | return -EROFS; | ||
562 | |||
563 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
564 | return -EIO; | ||
565 | |||
566 | error = inode_change_ok(inode, iattr); | ||
567 | if (error) | ||
568 | return error; | ||
569 | } | ||
570 | |||
571 | ASSERT((mask & ATTR_SIZE) == 0); | 580 | ASSERT((mask & ATTR_SIZE) == 0); |
572 | 581 | ||
573 | /* | 582 | /* |
@@ -741,8 +750,27 @@ out_dqrele: | |||
741 | return error; | 750 | return error; |
742 | } | 751 | } |
743 | 752 | ||
753 | int | ||
754 | xfs_vn_setattr_nonsize( | ||
755 | struct dentry *dentry, | ||
756 | struct iattr *iattr) | ||
757 | { | ||
758 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | ||
759 | int error; | ||
760 | |||
761 | trace_xfs_setattr(ip); | ||
762 | |||
763 | error = xfs_vn_change_ok(dentry, iattr); | ||
764 | if (error) | ||
765 | return error; | ||
766 | return xfs_setattr_nonsize(ip, iattr, 0); | ||
767 | } | ||
768 | |||
744 | /* | 769 | /* |
745 | * Truncate file. Must have write permission and not be a directory. | 770 | * Truncate file. Must have write permission and not be a directory. |
771 | * | ||
772 | * Caution: The caller of this function is responsible for calling | ||
773 | * setattr_prepare() or otherwise verifying the change is fine. | ||
746 | */ | 774 | */ |
747 | int | 775 | int |
748 | xfs_setattr_size( | 776 | xfs_setattr_size( |
@@ -758,18 +786,6 @@ xfs_setattr_size( | |||
758 | uint commit_flags = 0; | 786 | uint commit_flags = 0; |
759 | bool did_zeroing = false; | 787 | bool did_zeroing = false; |
760 | 788 | ||
761 | trace_xfs_setattr(ip); | ||
762 | |||
763 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
764 | return -EROFS; | ||
765 | |||
766 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
767 | return -EIO; | ||
768 | |||
769 | error = inode_change_ok(inode, iattr); | ||
770 | if (error) | ||
771 | return error; | ||
772 | |||
773 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | 789 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); |
774 | ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); | 790 | ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); |
775 | ASSERT(S_ISREG(ip->i_d.di_mode)); | 791 | ASSERT(S_ISREG(ip->i_d.di_mode)); |
@@ -941,16 +957,32 @@ out_trans_cancel: | |||
941 | goto out_unlock; | 957 | goto out_unlock; |
942 | } | 958 | } |
943 | 959 | ||
960 | int | ||
961 | xfs_vn_setattr_size( | ||
962 | struct dentry *dentry, | ||
963 | struct iattr *iattr) | ||
964 | { | ||
965 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | ||
966 | int error; | ||
967 | |||
968 | trace_xfs_setattr(ip); | ||
969 | |||
970 | error = xfs_vn_change_ok(dentry, iattr); | ||
971 | if (error) | ||
972 | return error; | ||
973 | return xfs_setattr_size(ip, iattr); | ||
974 | } | ||
975 | |||
944 | STATIC int | 976 | STATIC int |
945 | xfs_vn_setattr( | 977 | xfs_vn_setattr( |
946 | struct dentry *dentry, | 978 | struct dentry *dentry, |
947 | struct iattr *iattr) | 979 | struct iattr *iattr) |
948 | { | 980 | { |
949 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | ||
950 | int error; | 981 | int error; |
951 | 982 | ||
952 | if (iattr->ia_valid & ATTR_SIZE) { | 983 | if (iattr->ia_valid & ATTR_SIZE) { |
953 | uint iolock = XFS_IOLOCK_EXCL; | 984 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); |
985 | uint iolock = XFS_IOLOCK_EXCL; | ||
954 | 986 | ||
955 | xfs_ilock(ip, iolock); | 987 | xfs_ilock(ip, iolock); |
956 | error = xfs_break_layouts(d_inode(dentry), &iolock, true); | 988 | error = xfs_break_layouts(d_inode(dentry), &iolock, true); |
@@ -958,11 +990,11 @@ xfs_vn_setattr( | |||
958 | xfs_ilock(ip, XFS_MMAPLOCK_EXCL); | 990 | xfs_ilock(ip, XFS_MMAPLOCK_EXCL); |
959 | iolock |= XFS_MMAPLOCK_EXCL; | 991 | iolock |= XFS_MMAPLOCK_EXCL; |
960 | 992 | ||
961 | error = xfs_setattr_size(ip, iattr); | 993 | error = xfs_vn_setattr_size(dentry, iattr); |
962 | } | 994 | } |
963 | xfs_iunlock(ip, iolock); | 995 | xfs_iunlock(ip, iolock); |
964 | } else { | 996 | } else { |
965 | error = xfs_setattr_nonsize(ip, iattr, 0); | 997 | error = xfs_vn_setattr_nonsize(dentry, iattr); |
966 | } | 998 | } |
967 | 999 | ||
968 | return error; | 1000 | return error; |
diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index a0f84abb0d09..0259a383721a 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h | |||
@@ -33,6 +33,7 @@ extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); | |||
33 | extern void xfs_setattr_time(struct xfs_inode *ip, struct iattr *iattr); | 33 | extern void xfs_setattr_time(struct xfs_inode *ip, struct iattr *iattr); |
34 | extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, | 34 | extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, |
35 | int flags); | 35 | int flags); |
36 | extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap); | 36 | extern int xfs_vn_setattr_nonsize(struct dentry *dentry, struct iattr *vap); |
37 | extern int xfs_vn_setattr_size(struct dentry *dentry, struct iattr *vap); | ||
37 | 38 | ||
38 | #endif /* __XFS_IOPS_H__ */ | 39 | #endif /* __XFS_IOPS_H__ */ |
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 5e13b987d9e2..678e97fa3869 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h | |||
@@ -31,6 +31,7 @@ enum can_mode { | |||
31 | * CAN common private data | 31 | * CAN common private data |
32 | */ | 32 | */ |
33 | struct can_priv { | 33 | struct can_priv { |
34 | struct net_device *dev; | ||
34 | struct can_device_stats can_stats; | 35 | struct can_device_stats can_stats; |
35 | 36 | ||
36 | struct can_bittiming bittiming, data_bittiming; | 37 | struct can_bittiming bittiming, data_bittiming; |
@@ -46,7 +47,7 @@ struct can_priv { | |||
46 | u32 ctrlmode_static; /* static enabled options for driver/hardware */ | 47 | u32 ctrlmode_static; /* static enabled options for driver/hardware */ |
47 | 48 | ||
48 | int restart_ms; | 49 | int restart_ms; |
49 | struct timer_list restart_timer; | 50 | struct delayed_work restart_work; |
50 | 51 | ||
51 | int (*do_set_bittiming)(struct net_device *dev); | 52 | int (*do_set_bittiming)(struct net_device *dev); |
52 | int (*do_set_data_bittiming)(struct net_device *dev); | 53 | int (*do_set_data_bittiming)(struct net_device *dev); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 8ccb136c3980..96fb3242cde7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2829,7 +2829,7 @@ extern int buffer_migrate_page(struct address_space *, | |||
2829 | #define buffer_migrate_page NULL | 2829 | #define buffer_migrate_page NULL |
2830 | #endif | 2830 | #endif |
2831 | 2831 | ||
2832 | extern int inode_change_ok(const struct inode *, struct iattr *); | 2832 | extern int setattr_prepare(struct dentry *, struct iattr *); |
2833 | extern int inode_newsize_ok(const struct inode *, loff_t offset); | 2833 | extern int inode_newsize_ok(const struct inode *, loff_t offset); |
2834 | extern void setattr_copy(struct inode *inode, const struct iattr *attr); | 2834 | extern void setattr_copy(struct inode *inode, const struct iattr *attr); |
2835 | 2835 | ||
diff --git a/include/linux/mount.h b/include/linux/mount.h index f822c3c11377..dc6cd800cd5d 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
@@ -95,4 +95,6 @@ extern void mark_mounts_for_expiry(struct list_head *mounts); | |||
95 | 95 | ||
96 | extern dev_t name_to_dev_t(const char *name); | 96 | extern dev_t name_to_dev_t(const char *name); |
97 | 97 | ||
98 | extern unsigned int sysctl_mount_max; | ||
99 | |||
98 | #endif /* _LINUX_MOUNT_H */ | 100 | #endif /* _LINUX_MOUNT_H */ |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 6c86c7edafa7..ddd47c3a757d 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1957,7 +1957,10 @@ struct napi_gro_cb { | |||
1957 | /* Used in foo-over-udp, set in udp[46]_gro_receive */ | 1957 | /* Used in foo-over-udp, set in udp[46]_gro_receive */ |
1958 | u8 is_ipv6:1; | 1958 | u8 is_ipv6:1; |
1959 | 1959 | ||
1960 | /* 7 bit hole */ | 1960 | /* Number of gro_receive callbacks this packet already went through */ |
1961 | u8 recursion_counter:4; | ||
1962 | |||
1963 | /* 3 bit hole */ | ||
1961 | 1964 | ||
1962 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ | 1965 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ |
1963 | __wsum csum; | 1966 | __wsum csum; |
@@ -1968,6 +1971,25 @@ struct napi_gro_cb { | |||
1968 | 1971 | ||
1969 | #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) | 1972 | #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) |
1970 | 1973 | ||
1974 | #define GRO_RECURSION_LIMIT 15 | ||
1975 | static inline int gro_recursion_inc_test(struct sk_buff *skb) | ||
1976 | { | ||
1977 | return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT; | ||
1978 | } | ||
1979 | |||
1980 | typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *); | ||
1981 | static inline struct sk_buff **call_gro_receive(gro_receive_t cb, | ||
1982 | struct sk_buff **head, | ||
1983 | struct sk_buff *skb) | ||
1984 | { | ||
1985 | if (gro_recursion_inc_test(skb)) { | ||
1986 | NAPI_GRO_CB(skb)->flush |= 1; | ||
1987 | return NULL; | ||
1988 | } | ||
1989 | |||
1990 | return cb(head, skb); | ||
1991 | } | ||
1992 | |||
1971 | struct packet_type { | 1993 | struct packet_type { |
1972 | __be16 type; /* This is really htons(ether_type). */ | 1994 | __be16 type; /* This is really htons(ether_type). */ |
1973 | struct net_device *dev; /* NULL is wildcarded here */ | 1995 | struct net_device *dev; /* NULL is wildcarded here */ |
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 3e96a6a76103..d1a8ad7e5ae4 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h | |||
@@ -95,6 +95,7 @@ extern int set_posix_acl(struct inode *, int, struct posix_acl *); | |||
95 | extern int posix_acl_chmod(struct inode *, umode_t); | 95 | extern int posix_acl_chmod(struct inode *, umode_t); |
96 | extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, | 96 | extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, |
97 | struct posix_acl **); | 97 | struct posix_acl **); |
98 | extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **); | ||
98 | 99 | ||
99 | extern int simple_set_acl(struct inode *, struct posix_acl *, int); | 100 | extern int simple_set_acl(struct inode *, struct posix_acl *, int); |
100 | extern int simple_acl_create(struct inode *, struct inode *); | 101 | extern int simple_acl_create(struct inode *, struct inode *); |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 6d204f3f9df8..3d3a365233f0 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1434,6 +1434,8 @@ static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unli | |||
1434 | { | 1434 | { |
1435 | if (sk->sk_send_head == skb_unlinked) | 1435 | if (sk->sk_send_head == skb_unlinked) |
1436 | sk->sk_send_head = NULL; | 1436 | sk->sk_send_head = NULL; |
1437 | if (tcp_sk(sk)->highest_sack == skb_unlinked) | ||
1438 | tcp_sk(sk)->highest_sack = NULL; | ||
1437 | } | 1439 | } |
1438 | 1440 | ||
1439 | static inline void tcp_init_send_head(struct sock *sk) | 1441 | static inline void tcp_init_send_head(struct sock *sk) |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 89ba25b164db..74cb623bc0d3 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -323,8 +323,7 @@ static struct file_system_type cpuset_fs_type = { | |||
323 | /* | 323 | /* |
324 | * Return in pmask the portion of a cpusets's cpus_allowed that | 324 | * Return in pmask the portion of a cpusets's cpus_allowed that |
325 | * are online. If none are online, walk up the cpuset hierarchy | 325 | * are online. If none are online, walk up the cpuset hierarchy |
326 | * until we find one that does have some online cpus. The top | 326 | * until we find one that does have some online cpus. |
327 | * cpuset always has some cpus online. | ||
328 | * | 327 | * |
329 | * One way or another, we guarantee to return some non-empty subset | 328 | * One way or another, we guarantee to return some non-empty subset |
330 | * of cpu_online_mask. | 329 | * of cpu_online_mask. |
@@ -333,8 +332,20 @@ static struct file_system_type cpuset_fs_type = { | |||
333 | */ | 332 | */ |
334 | static void guarantee_online_cpus(struct cpuset *cs, struct cpumask *pmask) | 333 | static void guarantee_online_cpus(struct cpuset *cs, struct cpumask *pmask) |
335 | { | 334 | { |
336 | while (!cpumask_intersects(cs->effective_cpus, cpu_online_mask)) | 335 | while (!cpumask_intersects(cs->effective_cpus, cpu_online_mask)) { |
337 | cs = parent_cs(cs); | 336 | cs = parent_cs(cs); |
337 | if (unlikely(!cs)) { | ||
338 | /* | ||
339 | * The top cpuset doesn't have any online cpu as a | ||
340 | * consequence of a race between cpuset_hotplug_work | ||
341 | * and cpu hotplug notifier. But we know the top | ||
342 | * cpuset's effective_cpus is on its way to to be | ||
343 | * identical to cpu_online_mask. | ||
344 | */ | ||
345 | cpumask_copy(pmask, cpu_online_mask); | ||
346 | return; | ||
347 | } | ||
348 | } | ||
338 | cpumask_and(pmask, cs->effective_cpus, cpu_online_mask); | 349 | cpumask_and(pmask, cs->effective_cpus, cpu_online_mask); |
339 | } | 350 | } |
340 | 351 | ||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 261ee21e62db..9650e7aee267 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/uio.h> | 20 | #include <linux/uio.h> |
21 | #include <linux/audit.h> | 21 | #include <linux/audit.h> |
22 | #include <linux/pid_namespace.h> | 22 | #include <linux/pid_namespace.h> |
23 | #include <linux/user_namespace.h> | ||
23 | #include <linux/syscalls.h> | 24 | #include <linux/syscalls.h> |
24 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
25 | #include <linux/regset.h> | 26 | #include <linux/regset.h> |
@@ -207,12 +208,34 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state) | |||
207 | return ret; | 208 | return ret; |
208 | } | 209 | } |
209 | 210 | ||
210 | static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) | 211 | static bool ptrace_has_cap(const struct cred *tcred, unsigned int mode) |
211 | { | 212 | { |
213 | struct user_namespace *tns = tcred->user_ns; | ||
214 | |||
215 | /* When a root-owned process enters a user namespace created by a | ||
216 | * malicious user, the user shouldn't be able to execute code under | ||
217 | * uid 0 by attaching to the root-owned process via ptrace. | ||
218 | * Therefore, similar to the capable_wrt_inode_uidgid() check, | ||
219 | * verify that all the uids and gids of the target process are | ||
220 | * mapped into a namespace below the current one in which the caller | ||
221 | * is capable. | ||
222 | * No fsuid/fsgid check because __ptrace_may_access doesn't do it | ||
223 | * either. | ||
224 | */ | ||
225 | while ( | ||
226 | !kuid_has_mapping(tns, tcred->euid) || | ||
227 | !kuid_has_mapping(tns, tcred->suid) || | ||
228 | !kuid_has_mapping(tns, tcred->uid) || | ||
229 | !kgid_has_mapping(tns, tcred->egid) || | ||
230 | !kgid_has_mapping(tns, tcred->sgid) || | ||
231 | !kgid_has_mapping(tns, tcred->gid)) { | ||
232 | tns = tns->parent; | ||
233 | } | ||
234 | |||
212 | if (mode & PTRACE_MODE_NOAUDIT) | 235 | if (mode & PTRACE_MODE_NOAUDIT) |
213 | return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE); | 236 | return has_ns_capability_noaudit(current, tns, CAP_SYS_PTRACE); |
214 | else | 237 | else |
215 | return has_ns_capability(current, ns, CAP_SYS_PTRACE); | 238 | return has_ns_capability(current, tns, CAP_SYS_PTRACE); |
216 | } | 239 | } |
217 | 240 | ||
218 | /* Returns 0 on success, -errno on denial. */ | 241 | /* Returns 0 on success, -errno on denial. */ |
@@ -264,7 +287,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |||
264 | gid_eq(caller_gid, tcred->sgid) && | 287 | gid_eq(caller_gid, tcred->sgid) && |
265 | gid_eq(caller_gid, tcred->gid)) | 288 | gid_eq(caller_gid, tcred->gid)) |
266 | goto ok; | 289 | goto ok; |
267 | if (ptrace_has_cap(tcred->user_ns, mode)) | 290 | if (ptrace_has_cap(tcred, mode)) |
268 | goto ok; | 291 | goto ok; |
269 | rcu_read_unlock(); | 292 | rcu_read_unlock(); |
270 | return -EPERM; | 293 | return -EPERM; |
@@ -275,7 +298,7 @@ ok: | |||
275 | dumpable = get_dumpable(task->mm); | 298 | dumpable = get_dumpable(task->mm); |
276 | rcu_read_lock(); | 299 | rcu_read_lock(); |
277 | if (dumpable != SUID_DUMP_USER && | 300 | if (dumpable != SUID_DUMP_USER && |
278 | !ptrace_has_cap(__task_cred(task)->user_ns, mode)) { | 301 | !ptrace_has_cap(__task_cred(task), mode)) { |
279 | rcu_read_unlock(); | 302 | rcu_read_unlock(); |
280 | return -EPERM; | 303 | return -EPERM; |
281 | } | 304 | } |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 7d4900404c94..cebbff5f34fe 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/binfmts.h> | 64 | #include <linux/binfmts.h> |
65 | #include <linux/sched/sysctl.h> | 65 | #include <linux/sched/sysctl.h> |
66 | #include <linux/kexec.h> | 66 | #include <linux/kexec.h> |
67 | #include <linux/mount.h> | ||
67 | 68 | ||
68 | #include <asm/uaccess.h> | 69 | #include <asm/uaccess.h> |
69 | #include <asm/processor.h> | 70 | #include <asm/processor.h> |
@@ -1709,6 +1710,14 @@ static struct ctl_table fs_table[] = { | |||
1709 | .mode = 0644, | 1710 | .mode = 0644, |
1710 | .proc_handler = proc_doulongvec_minmax, | 1711 | .proc_handler = proc_doulongvec_minmax, |
1711 | }, | 1712 | }, |
1713 | { | ||
1714 | .procname = "mount-max", | ||
1715 | .data = &sysctl_mount_max, | ||
1716 | .maxlen = sizeof(unsigned int), | ||
1717 | .mode = 0644, | ||
1718 | .proc_handler = proc_dointvec_minmax, | ||
1719 | .extra1 = &one, | ||
1720 | }, | ||
1712 | { } | 1721 | { } |
1713 | }; | 1722 | }; |
1714 | 1723 | ||
@@ -283,7 +283,8 @@ static inline struct rmap_item *alloc_rmap_item(void) | |||
283 | { | 283 | { |
284 | struct rmap_item *rmap_item; | 284 | struct rmap_item *rmap_item; |
285 | 285 | ||
286 | rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL); | 286 | rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL | |
287 | __GFP_NORETRY | __GFP_NOWARN); | ||
287 | if (rmap_item) | 288 | if (rmap_item) |
288 | ksm_rmap_items++; | 289 | ksm_rmap_items++; |
289 | return rmap_item; | 290 | return rmap_item; |
diff --git a/mm/shmem.c b/mm/shmem.c index 46511ad90bc5..feaaf6ea1b86 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -548,7 +548,7 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr) | |||
548 | struct shmem_inode_info *info = SHMEM_I(inode); | 548 | struct shmem_inode_info *info = SHMEM_I(inode); |
549 | int error; | 549 | int error; |
550 | 550 | ||
551 | error = inode_change_ok(inode, attr); | 551 | error = setattr_prepare(dentry, attr); |
552 | if (error) | 552 | if (error) |
553 | return error; | 553 | return error; |
554 | 554 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 825e8fb5114b..f9e9a8148a43 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -334,16 +334,19 @@ static int rfcomm_sock_create(struct net *net, struct socket *sock, | |||
334 | 334 | ||
335 | static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) | 335 | static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) |
336 | { | 336 | { |
337 | struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; | 337 | struct sockaddr_rc sa; |
338 | struct sock *sk = sock->sk; | 338 | struct sock *sk = sock->sk; |
339 | int chan = sa->rc_channel; | 339 | int len, err = 0; |
340 | int err = 0; | ||
341 | |||
342 | BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); | ||
343 | 340 | ||
344 | if (!addr || addr->sa_family != AF_BLUETOOTH) | 341 | if (!addr || addr->sa_family != AF_BLUETOOTH) |
345 | return -EINVAL; | 342 | return -EINVAL; |
346 | 343 | ||
344 | memset(&sa, 0, sizeof(sa)); | ||
345 | len = min_t(unsigned int, sizeof(sa), addr_len); | ||
346 | memcpy(&sa, addr, len); | ||
347 | |||
348 | BT_DBG("sk %p %pMR", sk, &sa.rc_bdaddr); | ||
349 | |||
347 | lock_sock(sk); | 350 | lock_sock(sk); |
348 | 351 | ||
349 | if (sk->sk_state != BT_OPEN) { | 352 | if (sk->sk_state != BT_OPEN) { |
@@ -358,12 +361,13 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr | |||
358 | 361 | ||
359 | write_lock(&rfcomm_sk_list.lock); | 362 | write_lock(&rfcomm_sk_list.lock); |
360 | 363 | ||
361 | if (chan && __rfcomm_get_listen_sock_by_addr(chan, &sa->rc_bdaddr)) { | 364 | if (sa.rc_channel && |
365 | __rfcomm_get_listen_sock_by_addr(sa.rc_channel, &sa.rc_bdaddr)) { | ||
362 | err = -EADDRINUSE; | 366 | err = -EADDRINUSE; |
363 | } else { | 367 | } else { |
364 | /* Save source address */ | 368 | /* Save source address */ |
365 | bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr); | 369 | bacpy(&rfcomm_pi(sk)->src, &sa.rc_bdaddr); |
366 | rfcomm_pi(sk)->channel = chan; | 370 | rfcomm_pi(sk)->channel = sa.rc_channel; |
367 | sk->sk_state = BT_BOUND; | 371 | sk->sk_state = BT_BOUND; |
368 | } | 372 | } |
369 | 373 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index 185a3398c651..56d820fc2707 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4060,6 +4060,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
4060 | NAPI_GRO_CB(skb)->flush = 0; | 4060 | NAPI_GRO_CB(skb)->flush = 0; |
4061 | NAPI_GRO_CB(skb)->free = 0; | 4061 | NAPI_GRO_CB(skb)->free = 0; |
4062 | NAPI_GRO_CB(skb)->udp_mark = 0; | 4062 | NAPI_GRO_CB(skb)->udp_mark = 0; |
4063 | NAPI_GRO_CB(skb)->recursion_counter = 0; | ||
4063 | NAPI_GRO_CB(skb)->gro_remcsum_start = 0; | 4064 | NAPI_GRO_CB(skb)->gro_remcsum_start = 0; |
4064 | 4065 | ||
4065 | /* Setup for GRO checksum validation */ | 4066 | /* Setup for GRO checksum validation */ |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index f3bad41d725f..76f8389eacd2 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -434,7 +434,7 @@ struct sk_buff **eth_gro_receive(struct sk_buff **head, | |||
434 | 434 | ||
435 | skb_gro_pull(skb, sizeof(*eh)); | 435 | skb_gro_pull(skb, sizeof(*eh)); |
436 | skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); | 436 | skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); |
437 | pp = ptype->callbacks.gro_receive(head, skb); | 437 | pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); |
438 | 438 | ||
439 | out_unlock: | 439 | out_unlock: |
440 | rcu_read_unlock(); | 440 | rcu_read_unlock(); |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 0cc98b135b8f..2095cd6c31fd 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1377,7 +1377,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1377 | skb_gro_pull(skb, sizeof(*iph)); | 1377 | skb_gro_pull(skb, sizeof(*iph)); |
1378 | skb_set_transport_header(skb, skb_gro_offset(skb)); | 1378 | skb_set_transport_header(skb, skb_gro_offset(skb)); |
1379 | 1379 | ||
1380 | pp = ops->callbacks.gro_receive(head, skb); | 1380 | pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); |
1381 | 1381 | ||
1382 | out_unlock: | 1382 | out_unlock: |
1383 | rcu_read_unlock(); | 1383 | rcu_read_unlock(); |
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 4b67937692c9..b22a75c0a3d9 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c | |||
@@ -188,7 +188,7 @@ static struct sk_buff **fou_gro_receive(struct sk_buff **head, | |||
188 | if (!ops || !ops->callbacks.gro_receive) | 188 | if (!ops || !ops->callbacks.gro_receive) |
189 | goto out_unlock; | 189 | goto out_unlock; |
190 | 190 | ||
191 | pp = ops->callbacks.gro_receive(head, skb); | 191 | pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); |
192 | 192 | ||
193 | out_unlock: | 193 | out_unlock: |
194 | rcu_read_unlock(); | 194 | rcu_read_unlock(); |
@@ -355,7 +355,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, | |||
355 | if (WARN_ON(!ops || !ops->callbacks.gro_receive)) | 355 | if (WARN_ON(!ops || !ops->callbacks.gro_receive)) |
356 | goto out_unlock; | 356 | goto out_unlock; |
357 | 357 | ||
358 | pp = ops->callbacks.gro_receive(head, skb); | 358 | pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); |
359 | 359 | ||
360 | out_unlock: | 360 | out_unlock: |
361 | rcu_read_unlock(); | 361 | rcu_read_unlock(); |
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 5a8ee3282550..53300b88d569 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
@@ -214,7 +214,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, | |||
214 | /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/ | 214 | /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/ |
215 | skb_gro_postpull_rcsum(skb, greh, grehlen); | 215 | skb_gro_postpull_rcsum(skb, greh, grehlen); |
216 | 216 | ||
217 | pp = ptype->callbacks.gro_receive(head, skb); | 217 | pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); |
218 | 218 | ||
219 | out_unlock: | 219 | out_unlock: |
220 | rcu_read_unlock(); | 220 | rcu_read_unlock(); |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index f6ee0d561aab..3dac3d4aa26f 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -659,6 +659,10 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, | |||
659 | if (len > 0xFFFF) | 659 | if (len > 0xFFFF) |
660 | return -EMSGSIZE; | 660 | return -EMSGSIZE; |
661 | 661 | ||
662 | /* Must have at least a full ICMP header. */ | ||
663 | if (len < icmph_len) | ||
664 | return -EINVAL; | ||
665 | |||
662 | /* | 666 | /* |
663 | * Check the flags. | 667 | * Check the flags. |
664 | */ | 668 | */ |
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index f9386160cbee..2af7b7e1a0f6 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -339,8 +339,13 @@ unflush: | |||
339 | skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */ | 339 | skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */ |
340 | skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr)); | 340 | skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr)); |
341 | NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto; | 341 | NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto; |
342 | pp = uo_priv->offload->callbacks.gro_receive(head, skb, | 342 | |
343 | uo_priv->offload); | 343 | if (gro_recursion_inc_test(skb)) { |
344 | pp = NULL; | ||
345 | } else { | ||
346 | pp = uo_priv->offload->callbacks.gro_receive(head, skb, | ||
347 | uo_priv->offload); | ||
348 | } | ||
344 | 349 | ||
345 | out_unlock: | 350 | out_unlock: |
346 | rcu_read_unlock(); | 351 | rcu_read_unlock(); |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 08b62047c67f..db0b8428d248 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -247,7 +247,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
247 | 247 | ||
248 | skb_gro_postpull_rcsum(skb, iph, nlen); | 248 | skb_gro_postpull_rcsum(skb, iph, nlen); |
249 | 249 | ||
250 | pp = ops->callbacks.gro_receive(head, skb); | 250 | pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); |
251 | 251 | ||
252 | out_unlock: | 252 | out_unlock: |
253 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index a3654d929814..b9d1baaa8bdc 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -3344,19 +3344,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
3344 | 3344 | ||
3345 | if (optlen != sizeof(val)) | 3345 | if (optlen != sizeof(val)) |
3346 | return -EINVAL; | 3346 | return -EINVAL; |
3347 | if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) | ||
3348 | return -EBUSY; | ||
3349 | if (copy_from_user(&val, optval, sizeof(val))) | 3347 | if (copy_from_user(&val, optval, sizeof(val))) |
3350 | return -EFAULT; | 3348 | return -EFAULT; |
3351 | switch (val) { | 3349 | switch (val) { |
3352 | case TPACKET_V1: | 3350 | case TPACKET_V1: |
3353 | case TPACKET_V2: | 3351 | case TPACKET_V2: |
3354 | case TPACKET_V3: | 3352 | case TPACKET_V3: |
3355 | po->tp_version = val; | 3353 | break; |
3356 | return 0; | ||
3357 | default: | 3354 | default: |
3358 | return -EINVAL; | 3355 | return -EINVAL; |
3359 | } | 3356 | } |
3357 | lock_sock(sk); | ||
3358 | if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { | ||
3359 | ret = -EBUSY; | ||
3360 | } else { | ||
3361 | po->tp_version = val; | ||
3362 | ret = 0; | ||
3363 | } | ||
3364 | release_sock(sk); | ||
3365 | return ret; | ||
3360 | } | 3366 | } |
3361 | case PACKET_RESERVE: | 3367 | case PACKET_RESERVE: |
3362 | { | 3368 | { |
@@ -3819,6 +3825,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
3819 | /* Added to avoid minimal code churn */ | 3825 | /* Added to avoid minimal code churn */ |
3820 | struct tpacket_req *req = &req_u->req; | 3826 | struct tpacket_req *req = &req_u->req; |
3821 | 3827 | ||
3828 | lock_sock(sk); | ||
3822 | /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ | 3829 | /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ |
3823 | if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { | 3830 | if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { |
3824 | WARN(1, "Tx-ring is not supported.\n"); | 3831 | WARN(1, "Tx-ring is not supported.\n"); |
@@ -3900,7 +3907,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
3900 | goto out; | 3907 | goto out; |
3901 | } | 3908 | } |
3902 | 3909 | ||
3903 | lock_sock(sk); | ||
3904 | 3910 | ||
3905 | /* Detach socket from network */ | 3911 | /* Detach socket from network */ |
3906 | spin_lock(&po->bind_lock); | 3912 | spin_lock(&po->bind_lock); |
@@ -3949,11 +3955,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
3949 | if (!tx_ring) | 3955 | if (!tx_ring) |
3950 | prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue); | 3956 | prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue); |
3951 | } | 3957 | } |
3952 | release_sock(sk); | ||
3953 | 3958 | ||
3954 | if (pg_vec) | 3959 | if (pg_vec) |
3955 | free_pg_vec(pg_vec, order, req->tp_block_nr); | 3960 | free_pg_vec(pg_vec, order, req->tp_block_nr); |
3956 | out: | 3961 | out: |
3962 | release_sock(sk); | ||
3957 | return err; | 3963 | return err; |
3958 | } | 3964 | } |
3959 | 3965 | ||
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 70e3dacbf84a..bf7d6a44c6f2 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -386,6 +386,10 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, | |||
386 | dev = dev_get_by_name(net, driver_name); | 386 | dev = dev_get_by_name(net, driver_name); |
387 | if (!dev) | 387 | if (!dev) |
388 | return -ENODEV; | 388 | return -ENODEV; |
389 | if (tipc_mtu_bad(dev, 0)) { | ||
390 | dev_put(dev); | ||
391 | return -EINVAL; | ||
392 | } | ||
389 | 393 | ||
390 | /* Associate TIPC bearer with L2 bearer */ | 394 | /* Associate TIPC bearer with L2 bearer */ |
391 | rcu_assign_pointer(b->media_ptr, dev); | 395 | rcu_assign_pointer(b->media_ptr, dev); |
@@ -524,14 +528,17 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
524 | if (!b_ptr) | 528 | if (!b_ptr) |
525 | return NOTIFY_DONE; | 529 | return NOTIFY_DONE; |
526 | 530 | ||
527 | b_ptr->mtu = dev->mtu; | ||
528 | |||
529 | switch (evt) { | 531 | switch (evt) { |
530 | case NETDEV_CHANGE: | 532 | case NETDEV_CHANGE: |
531 | if (netif_carrier_ok(dev)) | 533 | if (netif_carrier_ok(dev)) |
532 | break; | 534 | break; |
533 | case NETDEV_DOWN: | 535 | case NETDEV_DOWN: |
534 | case NETDEV_CHANGEMTU: | 536 | case NETDEV_CHANGEMTU: |
537 | if (tipc_mtu_bad(dev, 0)) { | ||
538 | bearer_disable(net, b_ptr, false); | ||
539 | break; | ||
540 | } | ||
541 | b_ptr->mtu = dev->mtu; | ||
535 | tipc_reset_bearer(net, b_ptr); | 542 | tipc_reset_bearer(net, b_ptr); |
536 | break; | 543 | break; |
537 | case NETDEV_CHANGEADDR: | 544 | case NETDEV_CHANGEADDR: |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 5cad243ee8fc..b7302b012624 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #define _TIPC_BEARER_H | 38 | #define _TIPC_BEARER_H |
39 | 39 | ||
40 | #include "netlink.h" | 40 | #include "netlink.h" |
41 | #include "msg.h" | ||
41 | #include <net/genetlink.h> | 42 | #include <net/genetlink.h> |
42 | 43 | ||
43 | #define MAX_BEARERS 2 | 44 | #define MAX_BEARERS 2 |
@@ -61,6 +62,9 @@ | |||
61 | #define TIPC_MEDIA_TYPE_IB 2 | 62 | #define TIPC_MEDIA_TYPE_IB 2 |
62 | #define TIPC_MEDIA_TYPE_UDP 3 | 63 | #define TIPC_MEDIA_TYPE_UDP 3 |
63 | 64 | ||
65 | /* minimum bearer MTU */ | ||
66 | #define TIPC_MIN_BEARER_MTU (MAX_H_SIZE + INT_H_SIZE) | ||
67 | |||
64 | /** | 68 | /** |
65 | * struct tipc_node_map - set of node identifiers | 69 | * struct tipc_node_map - set of node identifiers |
66 | * @count: # of nodes in set | 70 | * @count: # of nodes in set |
@@ -218,4 +222,13 @@ void tipc_bearer_stop(struct net *net); | |||
218 | void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, | 222 | void tipc_bearer_send(struct net *net, u32 bearer_id, struct sk_buff *buf, |
219 | struct tipc_media_addr *dest); | 223 | struct tipc_media_addr *dest); |
220 | 224 | ||
225 | /* check if device MTU is too low for tipc headers */ | ||
226 | static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve) | ||
227 | { | ||
228 | if (dev->mtu >= TIPC_MIN_BEARER_MTU + reserve) | ||
229 | return false; | ||
230 | netdev_warn(dev, "MTU too low for tipc bearer\n"); | ||
231 | return true; | ||
232 | } | ||
233 | |||
221 | #endif /* _TIPC_BEARER_H */ | 234 | #endif /* _TIPC_BEARER_H */ |
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index f8dfee5072c0..e14f23542a1a 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c | |||
@@ -374,6 +374,11 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, | |||
374 | udp_conf.local_ip.s_addr = htonl(INADDR_ANY); | 374 | udp_conf.local_ip.s_addr = htonl(INADDR_ANY); |
375 | udp_conf.use_udp_checksums = false; | 375 | udp_conf.use_udp_checksums = false; |
376 | ub->ifindex = dev->ifindex; | 376 | ub->ifindex = dev->ifindex; |
377 | if (tipc_mtu_bad(dev, sizeof(struct iphdr) + | ||
378 | sizeof(struct udphdr))) { | ||
379 | err = -EINVAL; | ||
380 | goto err; | ||
381 | } | ||
377 | b->mtu = dev->mtu - sizeof(struct iphdr) | 382 | b->mtu = dev->mtu - sizeof(struct iphdr) |
378 | - sizeof(struct udphdr); | 383 | - sizeof(struct udphdr); |
379 | #if IS_ENABLED(CONFIG_IPV6) | 384 | #if IS_ENABLED(CONFIG_IPV6) |
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh index 973e8c141567..17867e723a51 100755 --- a/scripts/gcc-x86_64-has-stack-protector.sh +++ b/scripts/gcc-x86_64-has-stack-protector.sh | |||
@@ -1,6 +1,6 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" | 3 | echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fno-PIE -fstack-protector - -o - 2> /dev/null | grep -q "%gs" |
4 | if [ "$?" -eq "0" ] ; then | 4 | if [ "$?" -eq "0" ] ; then |
5 | echo y | 5 | echo y |
6 | else | 6 | else |