Update to 3.16.7-ckt4

- Drop various patches that were applied upstream
- Refresh "add sysctl to disallow unprivileged CLONE_NEWUSER by default"
- Fix/ignore ABI changes as appropriate
- Explicitly disable the new CONFIG_IWLWIFI_UAPSD symbol

svn path=/dists/sid/linux/; revision=22261
This commit is contained in:
Ben Hutchings 2015-01-16 00:04:09 +00:00
parent e50021ff04
commit 167d9fdacc
18 changed files with 212 additions and 1713 deletions

174
debian/changelog vendored
View File

@ -1,4 +1,4 @@
linux (3.16.7-ckt3-1) UNRELEASED; urgency=medium
linux (3.16.7-ckt4-1) UNRELEASED; urgency=medium
* New upstream stable update:
http://kernel.ubuntu.com/stable/ChangeLog-3.16.7-ckt3
@ -83,6 +83,159 @@ linux (3.16.7-ckt3-1) UNRELEASED; urgency=medium
- bond: Check length of IFLA_BOND_ARP_IP_TARGET attributes
- gre: Set inner mac header in gro complete (regression in 3.16.7-ckt1)
- [mips*] bpf: Fix broken BPF_MOD
http://kernel.ubuntu.com/stable/ChangeLog-3.16.7-ckt4
- [x86] drm/i915: don't warn if backlight unexpectedly enabled
(Closes: #757805)
- [x86] drm/i915/dp: only use training pattern 3 on platforms that
support it (regression in 3.15)
- btrfs: don't go readonly on existing qgroup items
- writeback: fix a subtle race condition in I_DIRTY clearing
- [s390*] KVM: flush CPU on load control
- UBI: Fix double free after do_sync_erase()
- [x86] Drivers: hv: util: make struct hv_do_fcopy match Hyper-V host
messages (regression for amd64 in 3.16.7)
- Drivers: hv: vmbus: Fix a race condition when unregistering a device
- misc: genwqe: check for error from get_user_pages_fast()
- drbd: merge_bvec_fn: properly remap bvm->bi_bdev
- PCI: Restore detection of read-only BARs
- scsi: correct return values for .eh_abort_handler implementations
- genhd: check for int overflow in disk_expand_part_tbl()
- Btrfs: make sure we wait on logged extents when fsycning two subvols
- Btrfs: make sure logged extents complete in the current transaction V3
- Btrfs: do not move em to modified list when unpinning
- [armhf] mvebu: disable I/O coherency on non-SMP situations on
Armada 370/375/38x/XP
- nfs41: fix nfs4_proc_layoutget error handling
- USB: cdc-acm: check for valid interfaces
- HID: i2c-hid: fix race condition reading reports
- [armhf] mfd: twl4030-power: Fix regression with missing compatible flag
(regression in 3.16)
- [armhf] serial: samsung: wait for transfer completion before clock
disable
- n_tty: Fix read_buf race condition, increment read_head after pushing
data (regression in 3.12)
- dm cache: only use overwrite optimisation for promotion when in
writeback mode
- dm cache: dirty flag was mistakenly being cleared when promoting via
overwrite
- dm bufio: fix memleak when using a dm_buffer's inline bio
- iwlwifi: dvm: fix flush support for old firmware (regression in
3.16.7-ckt1)
- iwlwifi: mvm: update values for Smart Fifo (regression in 3.14)
- iommu/vt-d: Fix an off-by-one bug in __domain_mapping()
- dm crypt: use memzero_explicit for on-stack buffer
- mnt: Implicitly add MNT_NODEV on remount when it was implicitly added by
mount (regression in 3.16.3)
- umount: Disallow unprivileged mount force
- md/raid5: fetch_block must fetch all the blocks handle_stripe_dirtying
wants.
- [x86] drm/i915: Only warn the first time we attempt to mmio whilst
suspended (regression in 3.15)
- drm/vmwgfx: Fix error printout on signals pending
- drm/radeon: check the right ring in radeon_evict_flags()
- swiotlb-xen: pass dev_addr to xen_dma_unmap_page and
xen_dma_sync_single_for_cpu
- [armhf/armmp] swiotlb-xen: remove BUG_ON in xen_bus_to_phys
- swiotlb-xen: call xen_dma_sync_single_for_device when appropriate
- swiotlb-xen: pass dev_addr to swiotlb_tbl_unmap_single
- [powerpc] book3s: Fix partial invalidation of TLBs in MCE code.
- [armhf] clocksource: arch_timer: Fix code to use physical timers when
requested (regression in 3.11)
- userns: Prevent evasion of group negative permissions through a userns
(CVE-2014-8989):
+ Don't allow setgroups until a gid mapping has been setablished
+ Don't allow unprivileged creation of gid mappings
+ Add a knob to disable setgroups on a per user namespace basis
+ Allow setting gid_maps without privilege when setgroups is disabled
- KEYS: Fix stale key registration at error path
- blk-mq: Fix a use-after-free
- blk-mq: Fix a race between bt_clear_tag() and bt_get()
- nfsd4: fix xdr4 count of server in fs_location4 (regression in 3.16)
- [x86] drm/i915: Don't complain about stolen conflicts on gen3
(regression in 3.12)
- [x86] kvm: Clear paravirt_enabled on KVM guests for espfix32's benefit
(CVE-2014-8134)
- blk-mq: Fix uninitialized kobject at CPU hotplugging
- ncpfs: return proper error from NCP_IOC_SETROOT ioctl
- [armhf] rtc: omap: fix clock-source configuration (regression in 3.16)
- exit: pidns: alloc_pid() leaks pid_namespace if child_reaper is exiting
- [amd64] switch_to(): Load TLS descriptors before switching DS and ES
(CVE-2014-9419)
- [x86] KVM: nVMX: Disable unrestricted mode if ept=0 (regression in 3.13)
- [x86] KVM: em_ret_far overrides cpl (follow-up to CVE-2014-3647 fix)
- pstore-ram: Fix hangs by using write-combine mappings
- HID: i2c-hid: prevent buffer overflow in early IRQ
- mac80211: fix multicast LED blinking and counter (regression in
3.16.7-ckt2)
- cfg80211: avoid mem leak on driver hint set
- nl80211: check matches array length before acessing it
- cfg80211: don't WARN about two consecutive Country IE hint
(regression in 3.14)
- tracing/sched: Check preempt_count() for current when reading task->state
(regression in 3.13)
- [x86] tls: Validate TLS entries to protect espfix (CVE-2014-8133)
- [x86] tls: Disallow unusual TLS segments
- isofs: Fix infinite looping over CE entries (CVE-2014-9420)
- mac80211: free management frame keys when removing station
- ceph: do_sync is never initialized (regression in 3.12)
- mnt: Fix a memory stomp in umount (regression in 3.14)
- ocfs2: fix journal commit deadlock
- md/bitmap: always wait for writes on unplug.
- [armhf] mmc: omap_hsmmc: Fix UHS card with DDR50 support (regression in
3.16)
- [x86] mmc: sdhci-pci-o2micro: Fix Dell E5440 issue (regression in 3.14)
- dm space map metadata: fix sm_bootstrap_get_nr_blocks()
- dm thin: fix a race in thin_dtr
- eCryptfs: Force RO mount when encrypted view is enabled
- eCryptfs: Remove buggy and unnecessary write in file name decode routine
- tcm_loop: Fix wrong I_T nexus association
- Btrfs: fix fs corruption on transaction abort if device supports discard
- [x86] perf/intel/uncore: Make sure only uncore events are collected
- perf: Fix events installation during moving group
- iscsi,iser-target: Initiate termination only once (regression in 3.16.4)
- iser-target: Fix flush + disconnect completion handling
- iser-target: Parallelize CM connection establishment
- iser-target: Fix connected_handler + teardown flow race
- iser-target: Handle ADDR_CHANGE event for listener cm_id
- iser-target: Fix implicit termination of connections
- iser-target: Allocate PI contexts dynamically
- iser-target: Fix NULL dereference in SW mode DIF
- iscsi,iser-target: Expose supported protection ops according to t10_pi
- genirq: Prevent proc race against freeing of irq descriptors
- [powerpc] powernv: Switch off MMU before entering nap/sleep/rvwinkle mode
- [x86] storvsc: ring buffer failures may result in I/O freeze
- iscsi-target: Fail connection on short sendmsg writes
- [x86] drm/i915: Invalidate media caches on gen7
- [x86] drm/i915: Force the CS stall for invalidate flushes
- dm thin: fix inability to discard blocks when in out-of-data-space mode
- dm thin: fix missing out-of-data-space to write mode transition if blocks
are released
- dm: fix missed error code if .end_io isn't implemented by target_type
- [armhf] i2c: mv64xxx: rework offload support to fix several problems
(regression in 3.12)
- [x86] tls: Don't validate lm in set_thread_area() after all
- ALSA: usb-audio: extend KEF X300A FU 10 tweak to Arcam rPAC
- tick/powerclamp: Remove tick_nohz_idle abuse
- audit: don't attempt to lookup PIDs when changing PID filtering audit
rules (regression in 3.15)
- audit: use supplied gfp_mask from audit_buffer in
kauditd_send_multicast_skb (regression in 3.16)
- [arm64] kernel: fix __cpu_suspend mm switch on warm-boot
- audit: restore AUDIT_LOGINUID unset ABI (regression in 3.10)
- Btrfs: fix loop writing of async reclaim
- isofs: Fix unchecked printing of ER records (CVE-2014-9584)
- crypto: af_alg - fix backlog handling
- udf: Check path length when reading symlink
- udf: Verify i_size when loading inode
- udf: Verify symlink size before loading it
- udf: Check component length before reading it
- [x86] platform/chrome: chromeos_laptop - Add support for Acer C720
(Closes: #774209)
- batman-adv: Calculate extra tail size based on queued fragments
(Closes: #774155) (CVE-2014-9428)
- vfs: move d_rcu from overlapping d_child to overlapping d_alias
- vfs: deal with deadlock in d_walk() (CVE-2014-8559)
- KEYS: close race between key lookup and freeing (CVE-2014-9529)
[ Ben Hutchings ]
* [sh4] Build with gcc-4.8 (Closes: #772602)
@ -93,13 +246,11 @@ linux (3.16.7-ckt3-1) UNRELEASED; urgency=medium
* PCI: Fix ABI change in 3.16.7-ckt3
* Ignore some ABI changes that don't appear to affect OOT modules:
- Removal of __add_pages(), __remove_pages(), of_device_is_stdout_path(),
clk_divider_ro_ops
clk_divider_ro_ops, tick_nohz_idle_enter, tick_nohz_idle_exit
- Changes to ASoC functions
* [arm64] Enable PSTORE as built-in and EFI_VARS_PSTORE as module;
ensure efivars and efi-pstore are loaded on EFI systems (Closes: #773309)
* hwmon: Enable SENSORS_NCT6683 as module (Closes: #774372)
* [x86] platform/chrome: chromeos_laptop - Add support for Acer C720
(Closes: #774209)
* udeb: Add i2c-designware-{core,platform} to i2c-modules and i2c-hid to
input-modules (Closes: #772578)
* [x86] ACPI / video: Run _BCL before deciding registering backlight
@ -107,24 +258,13 @@ linux (3.16.7-ckt3-1) UNRELEASED; urgency=medium
* [amd64] Enable EFI_MIXED to support Bay Trail systems
* efi: Expose underlying UEFI firmware platform size to userland, to
support installation on Bay Trail systems (Closes: #775191)
* [x86] tls: Validate TLS entries to protect espfix (CVE-2014-8133)
* [x86] kvm: Clear paravirt_enabled on KVM guests for espfix32's benefit
(CVE-2014-8134)
* [amd64] switch_to(): Load TLS descriptors before switching DS and ES
(CVE-2014-9419)
* isofs: Fix infinite looping over CE entries (CVE-2014-9420)
* batman-adv: Calculate extra tail size based on queued fragments
(Closes: #774155) (CVE-2014-9428)
* KEYS: close race between key lookup and freeing (CVE-2014-9529)
* isofs: Fix unchecked printing of ER records (CVE-2014-9584)
* vfs: Fix potential deadlock in dcache (CVE-2014-8559)
- move d_rcu from overlapping d_child to overlapping d_alias
* vfs: Changes for compatibility with CVE-2014-8559 fix:
- aufs: move d_rcu from overlapping d_child to overlapping d_alias
- vfs: Avoid ABI change for dentry union changes
- deal with deadlock in d_walk()
* [powerpc/powerpc{,-smp}] video/fb: Change FB_RADEON back to module
(Closes: #748398) (thanks to John Paul Adrian Glaubitz for thoroughly
testing this change)
* userns: Fix ABI change in 3.16.7-ckt4
[ Ian Campbell ]
* [armhf] Enable support for support OMAP5432 uEVM by enabling:

View File

@ -3051,6 +3051,7 @@ CONFIG_IWLWIFI=m
CONFIG_IWLDVM=m
CONFIG_IWLMVM=m
# CONFIG_IWLWIFI_BCAST_FILTERING is not set
# CONFIG_IWLWIFI_UAPSD is not set
# CONFIG_IWLWIFI_DEBUG is not set
# CONFIG_IWLWIFI_DEVICE_TRACING is not set

View File

@ -12,6 +12,8 @@ ignore-changes:
module:sound/soc/*
# Not needed by modules at all
clk_divider_ro_ops
tick_nohz_idle_enter
tick_nohz_idle_exit
[base]
arches:

View File

@ -1,58 +0,0 @@
From: Sven Eckelmann <sven@narfation.org>
Date: Sat, 20 Dec 2014 13:48:55 +0100
Subject: batman-adv: Calculate extra tail size based on queued fragments
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Origin: https://git.kernel.org/linus/5b6698b0e4a37053de35cc24ee695b98a7eb712b
The fragmentation code was replaced in 610bfc6bc99bc83680d190ebc69359a05fc7f605
("batman-adv: Receive fragmented packets and merge"). The new code provided a
mostly unused parameter skb for the merging function. It is used inside the
function to calculate the additionally needed skb tailroom. But instead of
increasing its own tailroom, it is only increasing the tailroom of the first
queued skb. This is not correct in some situations because the first queued
entry can be a different one than the parameter.
An observed problem was:
1. packet with size 104, total_size 1464, fragno 1 was received
- packet is queued
2. packet with size 1400, total_size 1464, fragno 0 was received
- packet is queued at the end of the list
3. enough data was received and can be given to the merge function
(1464 == (1400 - 20) + (104 - 20))
- merge functions gets 1400 byte large packet as skb argument
4. merge function gets first entry in queue (104 byte)
- stored as skb_out
5. merge function calculates the required extra tail as total_size - skb->len
- pskb_expand_head tail of skb_out with 64 bytes
6. merge function tries to squeeze the extra 1380 bytes from the second queued
skb (1400 byte aka skb parameter) in the 64 extra tail bytes of skb_out
Instead calculate the extra required tail bytes for skb_out also using skb_out
instead of using the parameter skb. The skb parameter is only used to get the
total_size from the last received packet. This is also the total_size used to
decide that all fragments were received.
Reported-by: Philipp Psurek <philipp.psurek@gmail.com>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Acked-by: Martin Hundebøll <martin@hundeboll.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/batman-adv/fragmentation.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index fc1835c..8af3461 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -251,7 +251,7 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb)
kfree(entry);
/* Make room for the rest of the fragments. */
- if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) {
+ if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) {
kfree_skb(skb_out);
skb_out = NULL;
goto free;

View File

@ -1,82 +0,0 @@
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 26 Oct 2014 19:31:10 -0400
Subject: deal with deadlock in d_walk()
Origin: https://git.kernel.org/linus/ca5358ef75fc69fee5322a38a340f5739d997c10
... by not hitting rename_retry for reasons other than rename having
happened. In other words, do _not_ restart when finding that
between unlocking the child and locking the parent the former got
into __dentry_kill(). Skip the killed siblings instead...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/dcache.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -484,7 +484,7 @@ static void __dentry_kill(struct dentry
}
/* if it was on the hash then remove it */
__d_drop(dentry);
- list_del(&dentry->d_child);
+ __list_del_entry(&dentry->d_child);
/*
* Inform d_walk() that we are no longer attached to the
* dentry tree
@@ -1138,33 +1138,31 @@ resume:
/*
* All done at this level ... ascend and resume the search.
*/
+ rcu_read_lock();
+ascend:
if (this_parent != parent) {
struct dentry *child = this_parent;
this_parent = child->d_parent;
- rcu_read_lock();
spin_unlock(&child->d_lock);
spin_lock(&this_parent->d_lock);
- /*
- * might go back up the wrong parent if we have had a rename
- * or deletion
- */
- if (this_parent != child->d_parent ||
- (child->d_flags & DCACHE_DENTRY_KILLED) ||
- need_seqretry(&rename_lock, seq)) {
- spin_unlock(&this_parent->d_lock);
- rcu_read_unlock();
+ /* might go back up the wrong parent if we have had a rename. */
+ if (need_seqretry(&rename_lock, seq))
goto rename_retry;
+ next = child->d_child.next;
+ while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+ if (next == &this_parent->d_subdirs)
+ goto ascend;
+ child = list_entry(next, struct dentry, d_child);
+ next = next->next;
}
rcu_read_unlock();
- next = child->d_child.next;
goto resume;
}
- if (need_seqretry(&rename_lock, seq)) {
- spin_unlock(&this_parent->d_lock);
+ if (need_seqretry(&rename_lock, seq))
goto rename_retry;
- }
+ rcu_read_unlock();
if (finish)
finish(data);
@@ -1174,6 +1172,9 @@ out_unlock:
return;
rename_retry:
+ spin_unlock(&this_parent->d_lock);
+ rcu_read_unlock();
+ BUG_ON(seq & 1);
if (!retry)
return;
seq = 1;

View File

@ -1,52 +0,0 @@
From: Jan Kara <jack@suse.cz>
Date: Mon, 15 Dec 2014 14:22:46 +0100
Subject: isofs: Fix infinite looping over CE entries
Origin: https://git.kernel.org/linus/f54e18f1b831c92f6512d2eedb224cd63d607d3d
Rock Ridge extensions define so called Continuation Entries (CE) which
define where is further space with Rock Ridge data. Corrupted isofs
image can contain arbitrarily long chain of these, including a one
containing loop and thus causing kernel to end in an infinite loop when
traversing these entries.
Limit the traversal to 32 entries which should be more than enough space
to store all the Rock Ridge data.
Reported-by: P J P <ppandit@redhat.com>
CC: stable@vger.kernel.org
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/isofs/rock.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index f488bba..bb63254 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -30,6 +30,7 @@ struct rock_state {
int cont_size;
int cont_extent;
int cont_offset;
+ int cont_loops;
struct inode *inode;
};
@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode)
rs->inode = inode;
}
+/* Maximum number of Rock Ridge continuation entries */
+#define RR_MAX_CE_ENTRIES 32
+
/*
* Returns 0 if the caller should continue scanning, 1 if the scan must end
* and -ve on error.
@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs)
goto out;
}
ret = -EIO;
+ if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
+ goto out;
bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
if (bh) {
memcpy(rs->buffer, bh->b_data + rs->cont_offset,

View File

@ -1,30 +0,0 @@
From: Jan Kara <jack@suse.cz>
Date: Thu, 18 Dec 2014 17:26:10 +0100
Subject: isofs: Fix unchecked printing of ER records
Origin: https://git.kernel.org/linus/4e2024624e678f0ebb916e6192bd23c1f9fdf696
We didn't check length of rock ridge ER records before printing them.
Thus corrupted isofs image can cause us to access and print some memory
behind the buffer with obvious consequences.
Reported-and-tested-by: Carl Henrik Lunde <chlunde@ping.uio.no>
CC: stable@vger.kernel.org
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/isofs/rock.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index bb63254..735d752 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -362,6 +362,9 @@ repeat:
rs.cont_size = isonum_733(rr->u.CE.size);
break;
case SIG('E', 'R'):
+ /* Invalid length of ER tag id? */
+ if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len)
+ goto out;
ISOFS_SB(inode->i_sb)->s_rock = 1;
printk(KERN_DEBUG "ISO 9660 Extensions: ");
{

View File

@ -1,42 +0,0 @@
From: Sasha Levin <sasha.levin@oracle.com>
Date: Mon, 29 Dec 2014 09:39:01 -0500
Subject: KEYS: close race between key lookup and freeing
Origin: https://git.kernel.org/linus/a3a8784454692dd72e5d5d34dcdab17b4420e74c
When a key is being garbage collected, it's key->user would get put before
the ->destroy() callback is called, where the key is removed from it's
respective tracking structures.
This leaves a key hanging in a semi-invalid state which leaves a window open
for a different task to try an access key->user. An example is
find_keyring_by_name() which would dereference key->user for a key that is
in the process of being garbage collected (where key->user was freed but
->destroy() wasn't called yet - so it's still present in the linked list).
This would cause either a panic, or corrupt memory.
Fixes CVE-2014-9529.
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/gc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -157,12 +157,12 @@ static noinline void key_gc_unused_keys(
if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
atomic_dec(&key->user->nikeys);
- key_user_put(key->user);
-
/* now throw away the key memory */
if (key->type->destroy)
key->type->destroy(key);
+ key_user_put(key->user);
+
kfree(key->description);
#ifdef KEY_DEBUGGING

View File

@ -1,714 +0,0 @@
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 26 Oct 2014 19:19:16 -0400
Subject: move d_rcu from overlapping d_child to overlapping d_alias
Origin: https://git.kernel.org/linus/946e51f2bf37f1656916eb75bd0742ba33983c28
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
[bwh: Backported to 3.16:
- Apply name changes in all the different places we use d_alias and d_child
- Adjust context]
---
arch/powerpc/platforms/cell/spufs/inode.c | 2 +-
drivers/staging/lustre/lustre/llite/dcache.c | 2 +-
drivers/staging/lustre/lustre/llite/llite_lib.c | 2 +-
drivers/staging/lustre/lustre/llite/namei.c | 8 ++--
fs/affs/amigaffs.c | 2 +-
fs/autofs4/expire.c | 12 +++---
fs/autofs4/root.c | 2 +-
fs/ceph/dir.c | 8 ++--
fs/ceph/inode.c | 2 +-
fs/cifs/inode.c | 2 +-
fs/coda/cache.c | 2 +-
fs/dcache.c | 53 ++++++++++++-------------
fs/debugfs/inode.c | 2 +-
fs/exportfs/expfs.c | 2 +-
fs/libfs.c | 12 +++---
fs/ncpfs/dir.c | 2 +-
fs/ncpfs/ncplib_kernel.h | 4 +-
fs/nfs/getroot.c | 2 +-
fs/notify/fsnotify.c | 4 +-
fs/ocfs2/dcache.c | 2 +-
include/linux/dcache.h | 8 ++--
kernel/trace/trace.c | 4 +-
kernel/trace/trace_events.c | 2 +-
security/selinux/selinuxfs.c | 6 +--
24 files changed, 73 insertions(+), 74 deletions(-)
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -164,7 +164,7 @@ static void spufs_prune_dir(struct dentr
struct dentry *dentry, *tmp;
mutex_lock(&dir->d_inode->i_mutex);
- list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+ list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
spin_lock(&dentry->d_lock);
if (!(d_unhashed(dentry)) && dentry->d_inode) {
dget_dlock(dentry);
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -258,7 +258,7 @@ void ll_invalidate_aliases(struct inode
inode->i_ino, inode->i_generation, inode);
ll_lock_dcache(inode);
- ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
+ ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) {
CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p "
"inode %p flags %d\n", dentry->d_name.len,
dentry->d_name.name, dentry, dentry->d_parent,
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -704,7 +704,7 @@ void lustre_dump_dentry(struct dentry *d
return;
list_for_each(tmp, &dentry->d_subdirs) {
- struct dentry *d = list_entry(tmp, struct dentry, d_u.d_child);
+ struct dentry *d = list_entry(tmp, struct dentry, d_child);
lustre_dump_dentry(d, recur - 1);
}
}
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -167,14 +167,14 @@ static void ll_invalidate_negative_child
struct ll_d_hlist_node *p;
ll_lock_dcache(dir);
- ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_alias) {
+ ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) {
spin_lock(&dentry->d_lock);
if (!list_empty(&dentry->d_subdirs)) {
struct dentry *child;
list_for_each_entry_safe(child, tmp_subdir,
&dentry->d_subdirs,
- d_u.d_child) {
+ d_child) {
if (child->d_inode == NULL)
d_lustre_invalidate(child, 1);
}
@@ -362,7 +362,7 @@ static struct dentry *ll_find_alias(stru
discon_alias = invalid_alias = NULL;
ll_lock_dcache(inode);
- ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
+ ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) {
LASSERT(alias != dentry);
spin_lock(&alias->d_lock);
@@ -943,7 +943,7 @@ static void ll_get_child_fid(struct inod
{
struct dentry *parent, *child;
- parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_alias);
+ parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_u.d_alias);
child = d_lookup(parent, name);
if (child) {
if (child->d_inode)
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -127,7 +127,7 @@ affs_fix_dcache(struct inode *inode, u32
{
struct dentry *dentry;
spin_lock(&inode->i_lock);
- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
if (entry_ino == (u32)(long)dentry->d_fsdata) {
dentry->d_fsdata = (void *)inode->i_ino;
break;
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -91,7 +91,7 @@ static struct dentry *get_next_positive_
spin_lock(&root->d_lock);
if (prev)
- next = prev->d_u.d_child.next;
+ next = prev->d_child.next;
else {
prev = dget_dlock(root);
next = prev->d_subdirs.next;
@@ -105,13 +105,13 @@ cont:
return NULL;
}
- q = list_entry(next, struct dentry, d_u.d_child);
+ q = list_entry(next, struct dentry, d_child);
spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
/* Already gone or negative dentry (under construction) - try next */
if (!d_count(q) || !simple_positive(q)) {
spin_unlock(&q->d_lock);
- next = q->d_u.d_child.next;
+ next = q->d_child.next;
goto cont;
}
dget_dlock(q);
@@ -161,13 +161,13 @@ again:
goto relock;
}
spin_unlock(&p->d_lock);
- next = p->d_u.d_child.next;
+ next = p->d_child.next;
p = parent;
if (next != &parent->d_subdirs)
break;
}
}
- ret = list_entry(next, struct dentry, d_u.d_child);
+ ret = list_entry(next, struct dentry, d_child);
spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
/* Negative dentry - try next */
@@ -461,7 +461,7 @@ found:
spin_lock(&sbi->lookup_lock);
spin_lock(&expired->d_parent->d_lock);
spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
- list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
+ list_move(&expired->d_parent->d_subdirs, &expired->d_child);
spin_unlock(&expired->d_lock);
spin_unlock(&expired->d_parent->d_lock);
spin_unlock(&sbi->lookup_lock);
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -655,7 +655,7 @@ static void autofs_clear_leaf_automount_
/* only consider parents below dentrys in the root */
if (IS_ROOT(parent->d_parent))
return;
- d_child = &dentry->d_u.d_child;
+ d_child = &dentry->d_child;
/* Set parent managed if it's becoming empty */
if (d_child->next == &parent->d_subdirs &&
d_child->prev == &parent->d_subdirs)
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -111,7 +111,7 @@ static int fpos_cmp(loff_t l, loff_t r)
/*
* When possible, we try to satisfy a readdir by peeking at the
* dcache. We make this work by carefully ordering dentries on
- * d_u.d_child when we initially get results back from the MDS, and
+ * d_child when we initially get results back from the MDS, and
* falling back to a "normal" sync readdir if any dentries in the dir
* are dropped.
*
@@ -147,11 +147,11 @@ static int __dcache_readdir(struct file
p = parent->d_subdirs.prev;
dout(" initial p %p/%p\n", p->prev, p->next);
} else {
- p = last->d_u.d_child.prev;
+ p = last->d_child.prev;
}
more:
- dentry = list_entry(p, struct dentry, d_u.d_child);
+ dentry = list_entry(p, struct dentry, d_child);
di = ceph_dentry(dentry);
while (1) {
dout(" p %p/%p %s d_subdirs %p/%p\n", p->prev, p->next,
@@ -174,7 +174,7 @@ more:
!dentry->d_inode ? " null" : "");
spin_unlock(&dentry->d_lock);
p = p->prev;
- dentry = list_entry(p, struct dentry, d_u.d_child);
+ dentry = list_entry(p, struct dentry, d_child);
di = ceph_dentry(dentry);
}
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1399,7 +1399,7 @@ retry_lookup:
/* reorder parent's d_subdirs */
spin_lock(&parent->d_lock);
spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
- list_move(&dn->d_u.d_child, &parent->d_subdirs);
+ list_move(&dn->d_child, &parent->d_subdirs);
spin_unlock(&dn->d_lock);
spin_unlock(&parent->d_lock);
}
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -887,7 +887,7 @@ inode_has_hashed_dentries(struct inode *
struct dentry *dentry;
spin_lock(&inode->i_lock);
- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
spin_unlock(&inode->i_lock);
return true;
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -92,7 +92,7 @@ static void coda_flag_children(struct de
struct dentry *de;
spin_lock(&parent->d_lock);
- list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) {
+ list_for_each_entry(de, &parent->d_subdirs, d_child) {
/* don't know what to do with negative dentries */
if (de->d_inode )
coda_flag_inode(de->d_inode, flag);
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -44,7 +44,7 @@
/*
* Usage:
* dcache->d_inode->i_lock protects:
- * - i_dentry, d_alias, d_inode of aliases
+ * - i_dentry, d_u.d_alias, d_inode of aliases
* dcache_hash_bucket lock protects:
* - the dcache hash table
* s_anon bl list spinlock protects:
@@ -59,7 +59,7 @@
* - d_unhashed()
* - d_parent and d_subdirs
* - childrens' d_child and d_parent
- * - d_alias, d_inode
+ * - d_u.d_alias, d_inode
*
* Ordering:
* dentry->d_inode->i_lock
@@ -239,7 +239,6 @@ static void __d_free(struct rcu_head *he
{
struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
- WARN_ON(!hlist_unhashed(&dentry->d_alias));
if (dname_external(dentry))
kfree(dentry->d_name.name);
kmem_cache_free(dentry_cache, dentry);
@@ -247,6 +246,8 @@ static void __d_free(struct rcu_head *he
static void dentry_free(struct dentry *dentry)
{
+ WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias));
+
/* if dentry was never visible to RCU, immediate free is OK */
if (!(dentry->d_flags & DCACHE_RCUACCESS))
__d_free(&dentry->d_u.d_rcu);
@@ -280,7 +281,7 @@ static void dentry_iput(struct dentry *
struct inode *inode = dentry->d_inode;
if (inode) {
dentry->d_inode = NULL;
- hlist_del_init(&dentry->d_alias);
+ hlist_del_init(&dentry->d_u.d_alias);
spin_unlock(&dentry->d_lock);
spin_unlock(&inode->i_lock);
if (!inode->i_nlink)
@@ -305,7 +306,7 @@ static void dentry_unlink_inode(struct d
struct inode *inode = dentry->d_inode;
__d_clear_type(dentry);
dentry->d_inode = NULL;
- hlist_del_init(&dentry->d_alias);
+ hlist_del_init(&dentry->d_u.d_alias);
dentry_rcuwalk_barrier(dentry);
spin_unlock(&dentry->d_lock);
spin_unlock(&inode->i_lock);
@@ -465,7 +466,7 @@ static void __dentry_kill(struct dentry
}
/* if it was on the hash then remove it */
__d_drop(dentry);
- list_del(&dentry->d_u.d_child);
+ list_del(&dentry->d_child);
/*
* Inform d_walk() that we are no longer attached to the
* dentry tree
@@ -749,7 +750,7 @@ static struct dentry *__d_find_alias(str
again:
discon_alias = NULL;
- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
spin_lock(&alias->d_lock);
if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
if (IS_ROOT(alias) &&
@@ -802,7 +803,7 @@ void d_prune_aliases(struct inode *inode
struct dentry *dentry;
restart:
spin_lock(&inode->i_lock);
- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
spin_lock(&dentry->d_lock);
if (!dentry->d_lockref.count) {
/*
@@ -1087,7 +1088,7 @@ repeat:
resume:
while (next != &this_parent->d_subdirs) {
struct list_head *tmp = next;
- struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
+ struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
next = tmp->next;
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -1139,7 +1140,7 @@ resume:
goto rename_retry;
}
rcu_read_unlock();
- next = child->d_u.d_child.next;
+ next = child->d_child.next;
goto resume;
}
if (need_seqretry(&rename_lock, seq)) {
@@ -1474,8 +1475,8 @@ struct dentry *__d_alloc(struct super_bl
INIT_HLIST_BL_NODE(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_lru);
INIT_LIST_HEAD(&dentry->d_subdirs);
- INIT_HLIST_NODE(&dentry->d_alias);
- INIT_LIST_HEAD(&dentry->d_u.d_child);
+ INIT_HLIST_NODE(&dentry->d_u.d_alias);
+ INIT_LIST_HEAD(&dentry->d_child);
d_set_d_op(dentry, dentry->d_sb->s_d_op);
this_cpu_inc(nr_dentry);
@@ -1505,7 +1506,7 @@ struct dentry *d_alloc(struct dentry * p
*/
__dget_dlock(parent);
dentry->d_parent = parent;
- list_add(&dentry->d_u.d_child, &parent->d_subdirs);
+ list_add(&dentry->d_child, &parent->d_subdirs);
spin_unlock(&parent->d_lock);
return dentry;
@@ -1598,7 +1599,7 @@ static void __d_instantiate(struct dentr
spin_lock(&dentry->d_lock);
__d_set_type(dentry, add_flags);
if (inode)
- hlist_add_head(&dentry->d_alias, &inode->i_dentry);
+ hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
dentry->d_inode = inode;
dentry_rcuwalk_barrier(dentry);
spin_unlock(&dentry->d_lock);
@@ -1622,7 +1623,7 @@ static void __d_instantiate(struct dentr
void d_instantiate(struct dentry *entry, struct inode * inode)
{
- BUG_ON(!hlist_unhashed(&entry->d_alias));
+ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
if (inode)
spin_lock(&inode->i_lock);
__d_instantiate(entry, inode);
@@ -1661,7 +1662,7 @@ static struct dentry *__d_instantiate_un
return NULL;
}
- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
/*
* Don't need alias->d_lock here, because aliases with
* d_parent == entry->d_parent are not subject to name or
@@ -1687,7 +1688,7 @@ struct dentry *d_instantiate_unique(stru
{
struct dentry *result;
- BUG_ON(!hlist_unhashed(&entry->d_alias));
+ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
if (inode)
spin_lock(&inode->i_lock);
@@ -1718,7 +1719,7 @@ EXPORT_SYMBOL(d_instantiate_unique);
*/
int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode)
{
- BUG_ON(!hlist_unhashed(&entry->d_alias));
+ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
spin_lock(&inode->i_lock);
if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) {
@@ -1757,7 +1758,7 @@ static struct dentry * __d_find_any_alia
if (hlist_empty(&inode->i_dentry))
return NULL;
- alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+ alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
__dget(alias);
return alias;
}
@@ -1834,7 +1835,7 @@ struct dentry *d_obtain_alias(struct ino
spin_lock(&tmp->d_lock);
tmp->d_inode = inode;
tmp->d_flags |= add_flags;
- hlist_add_head(&tmp->d_alias, &inode->i_dentry);
+ hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry);
hlist_bl_lock(&tmp->d_sb->s_anon);
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
hlist_bl_unlock(&tmp->d_sb->s_anon);
@@ -2277,7 +2278,7 @@ int d_validate(struct dentry *dentry, st
struct dentry *child;
spin_lock(&dparent->d_lock);
- list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) {
+ list_for_each_entry(child, &dparent->d_subdirs, d_child) {
if (dentry == child) {
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
__dget_dlock(dentry);
@@ -2545,8 +2546,8 @@ static void __d_move(struct dentry *dent
d_hash(dentry->d_parent, dentry->d_name.hash));
}
- list_del(&dentry->d_u.d_child);
- list_del(&target->d_u.d_child);
+ list_del(&dentry->d_child);
+ list_del(&target->d_child);
/* Switch the names.. */
switch_names(dentry, target, exchange);
@@ -2555,15 +2556,15 @@ static void __d_move(struct dentry *dent
if (IS_ROOT(dentry)) {
dentry->d_parent = target->d_parent;
target->d_parent = target;
- INIT_LIST_HEAD(&target->d_u.d_child);
+ INIT_LIST_HEAD(&target->d_child);
} else {
swap(dentry->d_parent, target->d_parent);
/* And add them back to the (new) parent lists */
- list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
+ list_add(&target->d_child, &target->d_parent->d_subdirs);
}
- list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
+ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
write_seqcount_end(&target->d_seq);
write_seqcount_end(&dentry->d_seq);
@@ -2690,9 +2691,9 @@ static void __d_materialise_dentry(struc
switch_names(dentry, anon, false);
dentry->d_parent = dentry;
- list_del_init(&dentry->d_u.d_child);
+ list_del_init(&dentry->d_child);
anon->d_parent = dparent;
- list_move(&anon->d_u.d_child, &dparent->d_subdirs);
+ list_move(&anon->d_child, &dparent->d_subdirs);
write_seqcount_end(&dentry->d_seq);
write_seqcount_end(&anon->d_seq);
@@ -3324,7 +3325,7 @@ void d_tmpfile(struct dentry *dentry, st
{
inode_dec_link_count(inode);
BUG_ON(dentry->d_name.name != dentry->d_iname ||
- !hlist_unhashed(&dentry->d_alias) ||
+ !hlist_unhashed(&dentry->d_u.d_alias) ||
!d_unlinked(dentry));
spin_lock(&dentry->d_parent->d_lock);
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -553,7 +553,7 @@ void debugfs_remove_recursive(struct den
* use the d_u.d_child as the rcu head and corrupt this list.
*/
spin_lock(&parent->d_lock);
- list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
+ list_for_each_entry(child, &parent->d_subdirs, d_child) {
if (!debugfs_positive(child))
continue;
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -50,7 +50,7 @@ find_acceptable_alias(struct dentry *res
inode = result->d_inode;
spin_lock(&inode->i_lock);
- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
dget(dentry);
spin_unlock(&inode->i_lock);
if (toput)
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -114,18 +114,18 @@ loff_t dcache_dir_lseek(struct file *fil
spin_lock(&dentry->d_lock);
/* d_lock not required for cursor */
- list_del(&cursor->d_u.d_child);
+ list_del(&cursor->d_child);
p = dentry->d_subdirs.next;
while (n && p != &dentry->d_subdirs) {
struct dentry *next;
- next = list_entry(p, struct dentry, d_u.d_child);
+ next = list_entry(p, struct dentry, d_child);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
if (simple_positive(next))
n--;
spin_unlock(&next->d_lock);
p = p->next;
}
- list_add_tail(&cursor->d_u.d_child, p);
+ list_add_tail(&cursor->d_child, p);
spin_unlock(&dentry->d_lock);
}
}
@@ -150,7 +150,7 @@ int dcache_readdir(struct file *file, st
{
struct dentry *dentry = file->f_path.dentry;
struct dentry *cursor = file->private_data;
- struct list_head *p, *q = &cursor->d_u.d_child;
+ struct list_head *p, *q = &cursor->d_child;
if (!dir_emit_dots(file, ctx))
return 0;
@@ -159,7 +159,7 @@ int dcache_readdir(struct file *file, st
list_move(q, &dentry->d_subdirs);
for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
- struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
+ struct dentry *next = list_entry(p, struct dentry, d_child);
spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
if (!simple_positive(next)) {
spin_unlock(&next->d_lock);
@@ -287,7 +287,7 @@ int simple_empty(struct dentry *dentry)
int ret = 0;
spin_lock(&dentry->d_lock);
- list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+ list_for_each_entry(child, &dentry->d_subdirs, d_child) {
spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
if (simple_positive(child)) {
spin_unlock(&child->d_lock);
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -406,7 +406,7 @@ ncp_dget_fpos(struct dentry *dentry, str
spin_lock(&parent->d_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dent = list_entry(next, struct dentry, d_u.d_child);
+ dent = list_entry(next, struct dentry, d_child);
if ((unsigned long)dent->d_fsdata == fpos) {
if (dent->d_inode)
dget(dent);
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -194,7 +194,7 @@ ncp_renew_dentries(struct dentry *parent
spin_lock(&parent->d_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dentry = list_entry(next, struct dentry, d_u.d_child);
+ dentry = list_entry(next, struct dentry, d_child);
if (dentry->d_fsdata == NULL)
ncp_age_dentry(server, dentry);
@@ -216,7 +216,7 @@ ncp_invalidate_dircache_entries(struct d
spin_lock(&parent->d_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dentry = list_entry(next, struct dentry, d_u.d_child);
+ dentry = list_entry(next, struct dentry, d_child);
dentry->d_fsdata = NULL;
ncp_age_dentry(server, dentry);
next = next->next;
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -58,7 +58,7 @@ static int nfs_superblock_set_dummy_root
*/
spin_lock(&sb->s_root->d_inode->i_lock);
spin_lock(&sb->s_root->d_lock);
- hlist_del_init(&sb->s_root->d_alias);
+ hlist_del_init(&sb->s_root->d_u.d_alias);
spin_unlock(&sb->s_root->d_lock);
spin_unlock(&sb->s_root->d_inode->i_lock);
}
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -63,14 +63,14 @@ void __fsnotify_update_child_dentry_flag
spin_lock(&inode->i_lock);
/* run all of the dentries associated with this inode. Since this is a
* directory, there damn well better only be one item on this list */
- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
struct dentry *child;
/* run all of the children of the original inode and fix their
* d_flags to indicate parental interest (their parent is the
* original inode) */
spin_lock(&alias->d_lock);
- list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
+ list_for_each_entry(child, &alias->d_subdirs, d_child) {
if (!child->d_inode)
continue;
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -172,7 +172,7 @@ struct dentry *ocfs2_find_local_alias(st
struct dentry *dentry;
spin_lock(&inode->i_lock);
- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
spin_lock(&dentry->d_lock);
if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
trace_ocfs2_find_local_alias(dentry->d_name.len,
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -124,15 +124,15 @@ struct dentry {
void *d_fsdata; /* fs-specific data */
struct list_head d_lru; /* LRU list */
+ struct list_head d_child; /* child of parent list */
+ struct list_head d_subdirs; /* our children */
/*
- * d_child and d_rcu can share memory
+ * d_alias and d_rcu can share memory
*/
union {
- struct list_head d_child; /* child of parent list */
+ struct hlist_node d_alias; /* inode alias list */
struct rcu_head d_rcu;
} d_u;
- struct list_head d_subdirs; /* our children */
- struct hlist_node d_alias; /* inode alias list */
};
/*
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6384,7 +6384,7 @@ static int instance_mkdir (struct inode
int ret;
/* Paranoid: Make sure the parent is the "instances" directory */
- parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+ parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
if (WARN_ON_ONCE(parent != trace_instance_dir))
return -ENOENT;
@@ -6411,7 +6411,7 @@ static int instance_rmdir(struct inode *
int ret;
/* Paranoid: Make sure the parent is the "instances" directory */
- parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+ parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
if (WARN_ON_ONCE(parent != trace_instance_dir))
return -ENOENT;
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -459,7 +459,7 @@ static void remove_event_file_dir(struct
if (dir) {
spin_lock(&dir->d_lock); /* probably unneeded */
- list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
+ list_for_each_entry(child, &dir->d_subdirs, d_child) {
if (child->d_inode) /* probably unneeded */
child->d_inode->i_private = NULL;
}
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1200,7 +1200,7 @@ static void sel_remove_entries(struct de
spin_lock(&de->d_lock);
node = de->d_subdirs.next;
while (node != &de->d_subdirs) {
- struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+ struct dentry *d = list_entry(node, struct dentry, d_child);
spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
list_del_init(node);
@@ -1674,12 +1674,12 @@ static void sel_remove_classes(void)
list_for_each(class_node, &class_dir->d_subdirs) {
struct dentry *class_subdir = list_entry(class_node,
- struct dentry, d_u.d_child);
+ struct dentry, d_child);
struct list_head *class_subdir_node;
list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
struct dentry *d = list_entry(class_subdir_node,
- struct dentry, d_u.d_child);
+ struct dentry, d_child);
if (d->d_inode)
if (d->d_inode->i_mode & S_IFDIR)

View File

@ -1,69 +0,0 @@
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
Date: Tue, 15 Jul 2014 17:53:12 +0200
Subject: s390/3215: fix hanging console issue
Origin: https://git.kernel.org/cgit/linux/kernel/git/s390/linux.git/commit?id=26d766c60f4ea08cd14f0f3435a6db3d6cc2ae96
Bug-Debian: https://bugs.debian.org/747922
The ccw_device_start in raw3215_start_io can fail. raw3215_try_io
does not check if the request could be started and removes any
pending timer. This can leave the system in a hanging state.
Check for pending request after raw3215_start_io and start a
timer if necessary.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
drivers/s390/char/con3215.c | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 5af7f0b..a6d47e5 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data)
unsigned long flags;
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
- if (raw->flags & RAW3215_TIMER_RUNS) {
- del_timer(&raw->timer);
- raw->flags &= ~RAW3215_TIMER_RUNS;
- if (!(raw->port.flags & ASYNC_SUSPENDED)) {
- raw3215_mk_write_req(raw);
- raw3215_start_io(raw);
+ raw->flags &= ~RAW3215_TIMER_RUNS;
+ if (!(raw->port.flags & ASYNC_SUSPENDED)) {
+ raw3215_mk_write_req(raw);
+ raw3215_start_io(raw);
+ if ((raw->queued_read || raw->queued_write) &&
+ !(raw->flags & RAW3215_WORKING) &&
+ !(raw->flags & RAW3215_TIMER_RUNS)) {
+ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
+ add_timer(&raw->timer);
+ raw->flags |= RAW3215_TIMER_RUNS;
}
}
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
(raw->flags & RAW3215_FLUSHING)) {
/* execute write requests bigger than minimum size */
raw3215_start_io(raw);
- if (raw->flags & RAW3215_TIMER_RUNS) {
- del_timer(&raw->timer);
- raw->flags &= ~RAW3215_TIMER_RUNS;
- }
- } else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
- /* delay small writes */
- raw->timer.expires = RAW3215_TIMEOUT + jiffies;
- add_timer(&raw->timer);
- raw->flags |= RAW3215_TIMER_RUNS;
}
}
+ if ((raw->queued_read || raw->queued_write) &&
+ !(raw->flags & RAW3215_WORKING) &&
+ !(raw->flags & RAW3215_TIMER_RUNS)) {
+ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
+ add_timer(&raw->timer);
+ raw->flags |= RAW3215_TIMER_RUNS;
+ }
}
/*

View File

@ -1,65 +0,0 @@
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
Date: Wed, 13 Aug 2014 12:01:30 +0200
Subject: s390/3215: fix tty output containing tabs
Origin: https://git.kernel.org/linus/e512d56c799517f33b301d81e9a5e0ebf30c2d1e
git commit 37f81fa1f63ad38e16125526bb2769ae0ea8d332
"n_tty: do O_ONLCR translation as a single write"
surfaced a bug in the 3215 device driver. In combination this
broke tab expansion for tty ouput.
The cause is an asymmetry in the behaviour of tty3215_ops->write
vs tty3215_ops->put_char. The put_char function scans for '\t'
but the write function does not.
As the driver has logic for the '\t' expansion remove XTABS
from c_oflag of the initial termios as well.
Reported-by: Stephen Powell <zlinuxman@wowway.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
drivers/s390/char/con3215.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index a6d47e5..c43aca6 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -1035,12 +1035,26 @@ static int tty3215_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
struct raw3215_info *raw;
+ int i, written;
if (!tty)
return 0;
raw = (struct raw3215_info *) tty->driver_data;
- raw3215_write(raw, buf, count);
- return count;
+ written = count;
+ while (count > 0) {
+ for (i = 0; i < count; i++)
+ if (buf[i] == '\t' || buf[i] == '\n')
+ break;
+ raw3215_write(raw, buf, i);
+ count -= i;
+ buf += i;
+ if (count > 0) {
+ raw3215_putchar(raw, *buf);
+ count--;
+ buf++;
+ }
+ }
+ return written;
}
/*
@@ -1188,7 +1202,7 @@ static int __init tty3215_init(void)
driver->subtype = SYSTEM_TYPE_TTY;
driver->init_termios = tty_std_termios;
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
- driver->init_termios.c_oflag = ONLCR | XTABS;
+ driver->init_termios.c_oflag = ONLCR;
driver->init_termios.c_lflag = ISIG;
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &tty3215_ops);

View File

@ -1,63 +0,0 @@
From: Andy Lutomirski <luto@amacapital.net>
Date: Fri, 5 Dec 2014 19:03:28 -0800
Subject: x86, kvm: Clear paravirt_enabled on KVM guests for espfix32's benefit
Origin: https://git.kernel.org/linus/29fa6825463c97e5157284db80107d1bfac5d77b
paravirt_enabled has the following effects:
- Disables the F00F bug workaround warning. There is no F00F bug
workaround any more because Linux's standard IDT handling already
works around the F00F bug, but the warning still exists. This
is only cosmetic, and, in any event, there is no such thing as
KVM on a CPU with the F00F bug.
- Disables 32-bit APM BIOS detection. On a KVM paravirt system,
there should be no APM BIOS anyway.
- Disables tboot. I think that the tboot code should check the
CPUID hypervisor bit directly if it matters.
- paravirt_enabled disables espfix32. espfix32 should *not* be
disabled under KVM paravirt.
The last point is the purpose of this patch. It fixes a leak of the
high 16 bits of the kernel stack address on 32-bit KVM paravirt
guests. Fixes CVE-2014-8134.
Cc: stable@vger.kernel.org
Suggested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kernel/kvm.c | 9 ++++++++-
arch/x86/kernel/kvmclock.c | 1 -
2 files changed, 8 insertions(+), 2 deletions(-)
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -282,7 +282,14 @@ NOKPROBE_SYMBOL(do_async_page_fault);
static void __init paravirt_ops_setup(void)
{
pv_info.name = "KVM";
- pv_info.paravirt_enabled = 1;
+
+ /*
+ * KVM isn't paravirt in the sense of paravirt_enabled. A KVM
+ * guest kernel works like a bare metal kernel with additional
+ * features, and paravirt_enabled is about features that are
+ * missing.
+ */
+ pv_info.paravirt_enabled = 0;
if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
pv_cpu_ops.io_delay = kvm_io_delay;
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -263,7 +263,6 @@ void __init kvmclock_init(void)
#endif
kvm_get_preset_lpj();
clocksource_register_hz(&kvm_clock, NSEC_PER_SEC);
- pv_info.paravirt_enabled = 1;
pv_info.name = "KVM";
if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT))

View File

@ -1,75 +0,0 @@
From: Andy Lutomirski <luto@amacapital.net>
Date: Thu, 4 Dec 2014 16:48:16 -0800
Subject: x86/tls: Validate TLS entries to protect espfix
Origin: https://git.kernel.org/linus/41bdc78544b8a93a9c6814b8bbbfef966272abbe
Installing a 16-bit RW data segment into the GDT defeats espfix.
AFAICT this will not affect glibc, Wine, or dosemu at all.
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Cc: stable@vger.kernel.org
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: security@kernel.org <security@kernel.org>
Cc: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/tls.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index f7fec09..e7650bd 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -27,6 +27,21 @@ static int get_free_idx(void)
return -ESRCH;
}
+static bool tls_desc_okay(const struct user_desc *info)
+{
+ if (LDT_empty(info))
+ return true;
+
+ /*
+ * espfix is required for 16-bit data segments, but espfix
+ * only works for LDT segments.
+ */
+ if (!info->seg_32bit)
+ return false;
+
+ return true;
+}
+
static void set_tls_desc(struct task_struct *p, int idx,
const struct user_desc *info, int n)
{
@@ -66,6 +81,9 @@ int do_set_thread_area(struct task_struct *p, int idx,
if (copy_from_user(&info, u_info, sizeof(info)))
return -EFAULT;
+ if (!tls_desc_okay(&info))
+ return -EINVAL;
+
if (idx == -1)
idx = info.entry_number;
@@ -192,6 +210,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset,
{
struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
const struct user_desc *info;
+ int i;
if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
(pos % sizeof(struct user_desc)) != 0 ||
@@ -205,6 +224,10 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset,
else
info = infobuf;
+ for (i = 0; i < count / sizeof(struct user_desc); i++)
+ if (!tls_desc_okay(info + i))
+ return -EINVAL;
+
set_tls_desc(target,
GDT_ENTRY_TLS_MIN + (pos / sizeof(struct user_desc)),
info, count / sizeof(struct user_desc));

View File

@ -1,304 +0,0 @@
From: Andy Lutomirski <luto@amacapital.net>
Date: Mon, 8 Dec 2014 13:55:20 -0800
Subject: x86_64, switch_to(): Load TLS descriptors before switching DS and ES
Origin: https://git.kernel.org/linus/f647d7c155f069c1a068030255c300663516420e
Otherwise, if buggy user code points DS or ES into the TLS
array, they would be corrupted after a context switch.
This also significantly improves the comments and documents some
gotchas in the code.
Before this patch, the both tests below failed. With this
patch, the es test passes, although the gsbase test still fails.
----- begin es test -----
/*
* Copyright (c) 2014 Andy Lutomirski
* GPL v2
*/
static unsigned short GDT3(int idx)
{
return (idx << 3) | 3;
}
static int create_tls(int idx, unsigned int base)
{
struct user_desc desc = {
.entry_number = idx,
.base_addr = base,
.limit = 0xfffff,
.seg_32bit = 1,
.contents = 0, /* Data, grow-up */
.read_exec_only = 0,
.limit_in_pages = 1,
.seg_not_present = 0,
.useable = 0,
};
if (syscall(SYS_set_thread_area, &desc) != 0)
err(1, "set_thread_area");
return desc.entry_number;
}
int main()
{
int idx = create_tls(-1, 0);
printf("Allocated GDT index %d\n", idx);
unsigned short orig_es;
asm volatile ("mov %%es,%0" : "=rm" (orig_es));
int errors = 0;
int total = 1000;
for (int i = 0; i < total; i++) {
asm volatile ("mov %0,%%es" : : "rm" (GDT3(idx)));
usleep(100);
unsigned short es;
asm volatile ("mov %%es,%0" : "=rm" (es));
asm volatile ("mov %0,%%es" : : "rm" (orig_es));
if (es != GDT3(idx)) {
if (errors == 0)
printf("[FAIL]\tES changed from 0x%hx to 0x%hx\n",
GDT3(idx), es);
errors++;
}
}
if (errors) {
printf("[FAIL]\tES was corrupted %d/%d times\n", errors, total);
return 1;
} else {
printf("[OK]\tES was preserved\n");
return 0;
}
}
----- end es test -----
----- begin gsbase test -----
/*
* gsbase.c, a gsbase test
* Copyright (c) 2014 Andy Lutomirski
* GPL v2
*/
static unsigned char *testptr, *testptr2;
static unsigned char read_gs_testvals(void)
{
unsigned char ret;
asm volatile ("movb %%gs:%1, %0" : "=r" (ret) : "m" (*testptr));
return ret;
}
int main()
{
int errors = 0;
testptr = mmap((void *)0x200000000UL, 1, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
if (testptr == MAP_FAILED)
err(1, "mmap");
testptr2 = mmap((void *)0x300000000UL, 1, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
if (testptr2 == MAP_FAILED)
err(1, "mmap");
*testptr = 0;
*testptr2 = 1;
if (syscall(SYS_arch_prctl, ARCH_SET_GS,
(unsigned long)testptr2 - (unsigned long)testptr) != 0)
err(1, "ARCH_SET_GS");
usleep(100);
if (read_gs_testvals() == 1) {
printf("[OK]\tARCH_SET_GS worked\n");
} else {
printf("[FAIL]\tARCH_SET_GS failed\n");
errors++;
}
asm volatile ("mov %0,%%gs" : : "r" (0));
if (read_gs_testvals() == 0) {
printf("[OK]\tWriting 0 to gs worked\n");
} else {
printf("[FAIL]\tWriting 0 to gs failed\n");
errors++;
}
usleep(100);
if (read_gs_testvals() == 0) {
printf("[OK]\tgsbase is still zero\n");
} else {
printf("[FAIL]\tgsbase was corrupted\n");
errors++;
}
return errors == 0 ? 0 : 1;
}
----- end gsbase test -----
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Cc: <stable@vger.kernel.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/509d27c9fec78217691c3dad91cec87e1006b34a.1418075657.git.luto@amacapital.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/process_64.c | 101 +++++++++++++++++++++++++++++++------------
1 file changed, 73 insertions(+), 28 deletions(-)
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -286,24 +286,9 @@ __switch_to(struct task_struct *prev_p,
fpu = switch_fpu_prepare(prev_p, next_p, cpu);
- /*
- * Reload esp0, LDT and the page table pointer:
- */
+ /* Reload esp0 and ss1. */
load_sp0(tss, next);
- /*
- * Switch DS and ES.
- * This won't pick up thread selector changes, but I guess that is ok.
- */
- savesegment(es, prev->es);
- if (unlikely(next->es | prev->es))
- loadsegment(es, next->es);
-
- savesegment(ds, prev->ds);
- if (unlikely(next->ds | prev->ds))
- loadsegment(ds, next->ds);
-
-
/* We must save %fs and %gs before load_TLS() because
* %fs and %gs may be cleared by load_TLS().
*
@@ -312,41 +297,101 @@ __switch_to(struct task_struct *prev_p,
savesegment(fs, fsindex);
savesegment(gs, gsindex);
+ /*
+ * Load TLS before restoring any segments so that segment loads
+ * reference the correct GDT entries.
+ */
load_TLS(next, cpu);
/*
- * Leave lazy mode, flushing any hypercalls made here.
- * This must be done before restoring TLS segments so
- * the GDT and LDT are properly updated, and must be
- * done before math_state_restore, so the TS bit is up
- * to date.
+ * Leave lazy mode, flushing any hypercalls made here. This
+ * must be done after loading TLS entries in the GDT but before
+ * loading segments that might reference them, and and it must
+ * be done before math_state_restore, so the TS bit is up to
+ * date.
*/
arch_end_context_switch(next_p);
+ /* Switch DS and ES.
+ *
+ * Reading them only returns the selectors, but writing them (if
+ * nonzero) loads the full descriptor from the GDT or LDT. The
+ * LDT for next is loaded in switch_mm, and the GDT is loaded
+ * above.
+ *
+ * We therefore need to write new values to the segment
+ * registers on every context switch unless both the new and old
+ * values are zero.
+ *
+ * Note that we don't need to do anything for CS and SS, as
+ * those are saved and restored as part of pt_regs.
+ */
+ savesegment(es, prev->es);
+ if (unlikely(next->es | prev->es))
+ loadsegment(es, next->es);
+
+ savesegment(ds, prev->ds);
+ if (unlikely(next->ds | prev->ds))
+ loadsegment(ds, next->ds);
+
/*
* Switch FS and GS.
*
- * Segment register != 0 always requires a reload. Also
- * reload when it has changed. When prev process used 64bit
- * base always reload to avoid an information leak.
+ * These are even more complicated than FS and GS: they have
+ * 64-bit bases are that controlled by arch_prctl. Those bases
+ * only differ from the values in the GDT or LDT if the selector
+ * is 0.
+ *
+ * Loading the segment register resets the hidden base part of
+ * the register to 0 or the value from the GDT / LDT. If the
+ * next base address zero, writing 0 to the segment register is
+ * much faster than using wrmsr to explicitly zero the base.
+ *
+ * The thread_struct.fs and thread_struct.gs values are 0
+ * if the fs and gs bases respectively are not overridden
+ * from the values implied by fsindex and gsindex. They
+ * are nonzero, and store the nonzero base addresses, if
+ * the bases are overridden.
+ *
+ * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should
+ * be impossible.
+ *
+ * Therefore we need to reload the segment registers if either
+ * the old or new selector is nonzero, and we need to override
+ * the base address if next thread expects it to be overridden.
+ *
+ * This code is unnecessarily slow in the case where the old and
+ * new indexes are zero and the new base is nonzero -- it will
+ * unnecessarily write 0 to the selector before writing the new
+ * base address.
+ *
+ * Note: This all depends on arch_prctl being the only way that
+ * user code can override the segment base. Once wrfsbase and
+ * wrgsbase are enabled, most of this code will need to change.
*/
if (unlikely(fsindex | next->fsindex | prev->fs)) {
loadsegment(fs, next->fsindex);
+
/*
- * Check if the user used a selector != 0; if yes
- * clear 64bit base, since overloaded base is always
- * mapped to the Null selector
+ * If user code wrote a nonzero value to FS, then it also
+ * cleared the overridden base address.
+ *
+ * XXX: if user code wrote 0 to FS and cleared the base
+ * address itself, we won't notice and we'll incorrectly
+ * restore the prior base address next time we reschdule
+ * the process.
*/
if (fsindex)
prev->fs = 0;
}
- /* when next process has a 64bit base use it */
if (next->fs)
wrmsrl(MSR_FS_BASE, next->fs);
prev->fsindex = fsindex;
if (unlikely(gsindex | next->gsindex | prev->gs)) {
load_gs_index(next->gsindex);
+
+ /* This works (and fails) the same way as fsindex above. */
if (gsindex)
prev->gs = 0;
}

View File

@ -15,7 +15,7 @@ Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
---
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -83,6 +83,11 @@
@@ -86,6 +86,11 @@
#define CREATE_TRACE_POINTS
#include <trace/events/task.h>
@ -27,7 +27,7 @@ Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
/*
* Protected counters by write_lock_irq(&tasklist_lock)
@@ -1144,6 +1149,10 @@ static struct task_struct *copy_process(
@@ -1149,6 +1154,10 @@ static struct task_struct *copy_process(
if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
return ERR_PTR(-EINVAL);
@ -38,7 +38,7 @@ Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
/*
* Thread groups must share signals as well, and detached threads
* can only be started up within the thread group.
@@ -1831,6 +1840,12 @@ SYSCALL_DEFINE1(unshare, unsigned long,
@@ -1843,6 +1852,12 @@ SYSCALL_DEFINE1(unshare, unsigned long,
if (unshare_flags & CLONE_NEWNS)
unshare_flags |= CLONE_FS;
@ -53,7 +53,7 @@ Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
goto bad_unshare_out;
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -104,6 +104,9 @@ extern int core_uses_pid;
@@ -103,6 +103,9 @@ extern int core_uses_pid;
extern char core_pattern[];
extern unsigned int core_pipe_limit;
#endif
@ -63,7 +63,7 @@ Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
extern int pid_max;
extern int pid_max_min, pid_max_max;
extern int percpu_pagelist_fraction;
@@ -482,6 +485,15 @@ static struct ctl_table kern_table[] = {
@@ -489,6 +492,15 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
@ -89,5 +89,5 @@ Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
+int unprivileged_userns_clone;
+
static struct kmem_cache *user_ns_cachep __read_mostly;
static DEFINE_MUTEX(userns_state_mutex);
static bool new_idmap_permitted(const struct file *file,

View File

@ -0,0 +1,45 @@
From: Ben Hutchings <ben@decadent.org.uk>
Date: Thu, 15 Jan 2015 23:16:35 +0000
Subject: userns: Fix ABI change in 3.16.7-ckt4
Forwarded: not-needed
The fix for CVE-2014-8989 added a new member to struct user_namespace.
This is always allocated, and the new member is always used, in
non-modular code. Move it to the end of the structure and hide it
from genksyms.
Also hide the new #include in kernel/groups.c.
---
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -31,13 +31,16 @@ struct user_namespace {
kuid_t owner;
kgid_t group;
unsigned int proc_inum;
- unsigned long flags;
/* Register of per-UID persistent keyrings for this namespace */
#ifdef CONFIG_PERSISTENT_KEYRINGS
struct key *persistent_keyring_register;
struct rw_semaphore persistent_keyring_register_sem;
#endif
+
+#ifndef __GENKSYMS__
+ unsigned long flags;
+#endif
};
extern struct user_namespace init_user_ns;
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -6,7 +6,9 @@
#include <linux/slab.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#ifndef __GENKSYMS__
#include <linux/user_namespace.h>
+#endif
#include <asm/uaccess.h>
/* init to 2 - one for init_task, one to ensure it is never freed */

View File

@ -1,124 +0,0 @@
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Date: Tue, 17 Jun 2014 14:02:00 -0700
Subject: platform/chrome: chromeos_laptop - Add support for Acer C720
Origin: https://git.kernel.org/linus/da3b0ab75aadab63d1ffd5563100c9386e444dad
Acer C720 has touchpad and light sensor connected to a separate I2C buses.
Since the designware I2C host controller driver has two instances on this
particular machine we need a way to match the correct instance. Add support
for this and then register both C720 touchpad and light sensor.
This code is based on following patch from Benson Leung:
https://patchwork.kernel.org/patch/3074411/
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Benson Leung <bleung@chromium.org>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/platform/chrome/chromeos_laptop.c | 45 ++++++++++++++++++++++++++-----
1 file changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index 7f1a2e2..a241e5f 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -45,6 +45,8 @@ static const char *i2c_adapter_names[] = {
"SMBus I801 adapter",
"i915 gmbus vga",
"i915 gmbus panel",
+ "i2c-designware-pci",
+ "i2c-designware-pci",
};
/* Keep this enum consistent with i2c_adapter_names */
@@ -52,6 +54,8 @@ enum i2c_adapter_type {
I2C_ADAPTER_SMBUS = 0,
I2C_ADAPTER_VGADDC,
I2C_ADAPTER_PANEL,
+ I2C_ADAPTER_DESIGNWARE_0,
+ I2C_ADAPTER_DESIGNWARE_1,
};
struct i2c_peripheral {
@@ -172,29 +176,42 @@ static struct i2c_client *__add_probed_i2c_device(
return client;
}
+struct i2c_lookup {
+ const char *name;
+ int instance;
+ int n;
+};
+
static int __find_i2c_adap(struct device *dev, void *data)
{
- const char *name = data;
+ struct i2c_lookup *lookup = data;
static const char *prefix = "i2c-";
struct i2c_adapter *adapter;
if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0)
return 0;
adapter = to_i2c_adapter(dev);
- return (strncmp(adapter->name, name, strlen(name)) == 0);
+ if (strncmp(adapter->name, lookup->name, strlen(lookup->name)) == 0 &&
+ lookup->n++ == lookup->instance)
+ return 1;
+ return 0;
}
static int find_i2c_adapter_num(enum i2c_adapter_type type)
{
struct device *dev = NULL;
struct i2c_adapter *adapter;
- const char *name = i2c_adapter_names[type];
+ struct i2c_lookup lookup;
+
+ memset(&lookup, 0, sizeof(lookup));
+ lookup.name = i2c_adapter_names[type];
+ lookup.instance = (type == I2C_ADAPTER_DESIGNWARE_1) ? 1 : 0;
+
/* find the adapter by name */
- dev = bus_find_device(&i2c_bus_type, NULL, (void *)name,
- __find_i2c_adap);
+ dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap);
if (!dev) {
/* Adapters may appear later. Deferred probing will retry */
pr_notice("%s: i2c adapter %s not found on system.\n", __func__,
- name);
+ lookup.name);
return -ENODEV;
}
adapter = to_i2c_adapter(dev);
@@ -377,6 +394,15 @@ static struct chromeos_laptop acer_ac700 = {
},
};
+static struct chromeos_laptop acer_c720 = {
+ .i2c_peripherals = {
+ /* Touchpad. */
+ { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+ /* Light Sensor. */
+ { .add = setup_isl29018_als, I2C_ADAPTER_DESIGNWARE_1 },
+ },
+};
+
static struct chromeos_laptop hp_pavilion_14_chromebook = {
.i2c_peripherals = {
/* Touchpad. */
@@ -434,6 +460,13 @@ static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = {
_CBDD(acer_ac700),
},
{
+ .ident = "Acer C720",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
+ },
+ _CBDD(acer_c720),
+ },
+ {
.ident = "HP Pavilion 14 Chromebook",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),

13
debian/patches/series vendored
View File

@ -51,17 +51,12 @@ bugfix/arm/omap-musb-choice.patch
bugfix/mips/disable-advansys.patch
bugfix/arm/ixp4xx_iobe.patch
bugfix/m68k/ethernat-kconfig.patch
bugfix/s390/s390-3215-fix-hanging-console-issue.patch
bugfix/s390/s390-3215-fix-tty-output-containing-tabs.patch
bugfix/x86/drm-i915-initialise-userptr-mmu_notifier-serial-to-1.patch
bugfix/x86/drm-i915-Add-some-L3-registers-to-the-parser-whiteli.patch
bugfix/parisc/parisc-reduce-sigrtmin-from-37-to-32-to-behave-like-.patch
bugfix/arm64/arm64-add-missing-dts-entry-for-X-Gene-platform.patch
bugfix/arm64/arm64-removed-using-of-the-mask-attribute-in-the-dts.patch
bugfix/x86/acpi-video-run-_bcl-before-deciding-registering-back.patch
bugfix/x86/x86-tls-validate-tls-entries-to-protect-espfix.patch
bugfix/x86/x86-kvm-clear-paravirt_enabled-on-kvm-guests-for-esp.patch
bugfix/x86/x86_64-switch_to-load-tls-descriptors-before-switchi.patch
# Arch features
features/mips/MIPS-Support-hard-limit-of-cpu-count-nr_cpu_ids.patch
@ -128,7 +123,6 @@ features/arm64/drivers-net-xgene-fix-Use-separate-resources.patch
features/arm64/dtb-Add-10GbE-node-to-APM-X-Gene-SoC-device-tree.patch
features/arm64/dtb-Add-SGMII-based-1GbE-node-to-APM-X-Gene-SoC-devi.patch
features/arm64/dtb-xgene-fix-Backward-compatibility-with-older-firm.patch
features/x86/platform-chrome-chromeos_laptop-add-support-for-acer.patch
# Miscellaneous bug fixes
bugfix/all/misc-bmp085-Enable-building-as-a-module.patch
@ -156,13 +150,7 @@ bugfix/all/xen-netback-Disable-NAPI-after-disabling-interrupts.patch
bugfix/all/xen-netback-do-not-report-success-if-backend_create_.patch
bugfix/all/netback-don-t-store-invalid-vif-pointer.patch
bugfix/all/xen-netback-support-frontends-without-feature-rx-not.patch
bugfix/all/isofs-fix-infinite-looping-over-ce-entries.patch
bugfix/all/batman-adv-calculate-extra-tail-size-based-on-queued.patch
bugfix/all/keys-close-race-between-key-lookup-and-freeing.patch
bugfix/all/isofs-fix-unchecked-printing-of-er-records.patch
bugfix/all/move-d_rcu-from-overlapping-d_child-to-overlapping-d.patch
bugfix/all/aufs-move-d_rcu-from-overlapping-d_child-to-overlapping-d.patch
bugfix/all/deal-with-deadlock-in-d_walk.patch
bugfix/all/net-mv643xx-disable-tso-by-default.patch
# memfd_create() & kdbus backport
@ -497,3 +485,4 @@ debian/perf-fix-abi-change-in-3.16.7-ckt2.patch
debian/arm-thread_info-fix-abi-change-in-3.16.7-ckt3.patch
debian/pci-fix-abi-change-in-3.16.7-ckt3.patch
debian/vfs-avoid-abi-change-for-dentry-union-changes.patch
debian/userns-fix-abi-change-in-3.16.7-ckt4.patch