From aa5585d52ddd6fee3fbc64e2985c2acacfc99d7e Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Thu, 8 Jan 2015 17:04:10 -0600 Subject: [PATCH] Linux v3.17.8 --- ...lag-was-mistakenly-being-cleared-whe.patch | 42 --- ...rious-cell_defer-when-dealing-with-p.patch | 40 --- ...e-overwrite-optimisation-for-promoti.patch | 32 -- ...date-the-setgroups-permission-checks.patch | 90 ----- ...Fix-infinite-looping-over-CE-entries.patch | 54 --- kernel.spec | 75 +---- ...dd-MNT_NODEV-on-remount-when-it-was-.patch | 41 --- mnt-Update-unprivileged-remount-test.patch | 280 ---------------- perf-man.tar.gz | Bin 0 -> 33955 bytes sources | 2 +- ...nt-Disallow-unprivileged-mount-force.patch | 33 -- ...b-to-disable-setgroups-on-a-per-user.patch | 280 ---------------- ...ting-gid_maps-without-privilege-when.patch | 40 --- ...d-no-fsuid-when-establishing-an-unpr.patch | 39 --- ...what-the-invariant-required-for-safe.patch | 48 --- ...ow-setgroups-until-a-gid-mapping-has.patch | 98 ------ ...ow-unprivileged-creation-of-gid-mapp.patch | 46 --- ...w-the-creator-of-the-userns-unprivil.patch | 54 --- ...e-id_map_mutex-to-userns_state_mutex.patch | 80 ----- ...break-the-unprivileged-remount-tests.patch | 91 ------ ...ravirt_enabled-on-KVM-guests-for-esp.patch | 72 ---- ...lidate-TLS-entries-to-protect-espfix.patch | 77 ----- ...-Load-TLS-descriptors-before-switchi.patch | 309 ------------------ 23 files changed, 6 insertions(+), 1917 deletions(-) delete mode 100644 dm-cache-dirty-flag-was-mistakenly-being-cleared-whe.patch delete mode 100644 dm-cache-fix-spurious-cell_defer-when-dealing-with-p.patch delete mode 100644 dm-cache-only-use-overwrite-optimisation-for-promoti.patch delete mode 100644 groups-Consolidate-the-setgroups-permission-checks.patch delete mode 100644 isofs-Fix-infinite-looping-over-CE-entries.patch delete mode 100644 mnt-Implicitly-add-MNT_NODEV-on-remount-when-it-was-.patch delete mode 100644 mnt-Update-unprivileged-remount-test.patch create mode 100644 perf-man.tar.gz delete mode 100644 umount-Disallow-unprivileged-mount-force.patch delete mode 100644 userns-Add-a-knob-to-disable-setgroups-on-a-per-user.patch delete mode 100644 userns-Allow-setting-gid_maps-without-privilege-when.patch delete mode 100644 userns-Check-euid-no-fsuid-when-establishing-an-unpr.patch delete mode 100644 userns-Document-what-the-invariant-required-for-safe.patch delete mode 100644 userns-Don-t-allow-setgroups-until-a-gid-mapping-has.patch delete mode 100644 userns-Don-t-allow-unprivileged-creation-of-gid-mapp.patch delete mode 100644 userns-Only-allow-the-creator-of-the-userns-unprivil.patch delete mode 100644 userns-Rename-id_map_mutex-to-userns_state_mutex.patch delete mode 100644 userns-Unbreak-the-unprivileged-remount-tests.patch delete mode 100644 x86-kvm-Clear-paravirt_enabled-on-KVM-guests-for-esp.patch delete mode 100644 x86-tls-Validate-TLS-entries-to-protect-espfix.patch delete mode 100644 x86_64-switch_to-Load-TLS-descriptors-before-switchi.patch diff --git a/dm-cache-dirty-flag-was-mistakenly-being-cleared-whe.patch b/dm-cache-dirty-flag-was-mistakenly-being-cleared-whe.patch deleted file mode 100644 index e64136a27..000000000 --- a/dm-cache-dirty-flag-was-mistakenly-being-cleared-whe.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: Joe Thornber -Date: Thu, 27 Nov 2014 12:26:46 +0000 -Subject: [PATCH] dm cache: dirty flag was mistakenly being cleared when - promoting via overwrite - -If the incoming bio is a WRITE and completely covers a block then we -don't bother to do any copying for a promotion operation. Once this is -done the cache block and origin block will be different, so we need to -set it to 'dirty'. - -Signed-off-by: Joe Thornber -Signed-off-by: Mike Snitzer -Cc: stable@vger.kernel.org ---- - drivers/md/dm-cache-target.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c -index 6f7086355691..387b93d81138 100644 ---- a/drivers/md/dm-cache-target.c -+++ b/drivers/md/dm-cache-target.c -@@ -951,10 +951,14 @@ static void migration_success_post_commit(struct dm_cache_migration *mg) - } - - } else { -- clear_dirty(cache, mg->new_oblock, mg->cblock); -- if (mg->requeue_holder) -+ if (mg->requeue_holder) { -+ clear_dirty(cache, mg->new_oblock, mg->cblock); - cell_defer(cache, mg->new_ocell, true); -- else { -+ } else { -+ /* -+ * The block was promoted via an overwrite, so it's dirty. -+ */ -+ set_dirty(cache, mg->new_oblock, mg->cblock); - bio_endio(mg->new_ocell->holder, 0); - cell_defer(cache, mg->new_ocell, false); - } --- -2.1.0 - diff --git a/dm-cache-fix-spurious-cell_defer-when-dealing-with-p.patch b/dm-cache-fix-spurious-cell_defer-when-dealing-with-p.patch deleted file mode 100644 index 05a6ebdca..000000000 --- a/dm-cache-fix-spurious-cell_defer-when-dealing-with-p.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Joe Thornber -Date: Fri, 28 Nov 2014 09:48:25 +0000 -Subject: [PATCH] dm cache: fix spurious cell_defer when dealing with partial - block at end of device - -We never bother caching a partial block that is at the back end of the -origin device. No cell ever gets locked, but the calling code was -assuming it was and trying to release it. - -Now the code only releases if the cell has been set to a non NULL -value. - -Signed-off-by: Joe Thornber -Signed-off-by: Mike Snitzer -Cc: stable@vger.kernel.org ---- - drivers/md/dm-cache-target.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c -index 387b93d81138..da496cfb458d 100644 ---- a/drivers/md/dm-cache-target.c -+++ b/drivers/md/dm-cache-target.c -@@ -2554,11 +2554,11 @@ static int __cache_map(struct cache *cache, struct bio *bio, struct dm_bio_priso - static int cache_map(struct dm_target *ti, struct bio *bio) - { - int r; -- struct dm_bio_prison_cell *cell; -+ struct dm_bio_prison_cell *cell = NULL; - struct cache *cache = ti->private; - - r = __cache_map(cache, bio, &cell); -- if (r == DM_MAPIO_REMAPPED) { -+ if (r == DM_MAPIO_REMAPPED && cell) { - inc_ds(cache, bio, cell); - cell_defer(cache, cell, false); - } --- -2.1.0 - diff --git a/dm-cache-only-use-overwrite-optimisation-for-promoti.patch b/dm-cache-only-use-overwrite-optimisation-for-promoti.patch deleted file mode 100644 index 12a79113d..000000000 --- a/dm-cache-only-use-overwrite-optimisation-for-promoti.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Joe Thornber -Date: Thu, 27 Nov 2014 12:21:08 +0000 -Subject: [PATCH] dm cache: only use overwrite optimisation for promotion when - in writeback mode - -Overwrite causes the cache block and origin blocks to diverge, which -is only allowed in writeback mode. - -Signed-off-by: Joe Thornber -Signed-off-by: Mike Snitzer -Cc: stable@vger.kernel.org ---- - drivers/md/dm-cache-target.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c -index 7130505c2425..6f7086355691 100644 ---- a/drivers/md/dm-cache-target.c -+++ b/drivers/md/dm-cache-target.c -@@ -1070,7 +1070,8 @@ static void issue_copy(struct dm_cache_migration *mg) - - avoid = is_discarded_oblock(cache, mg->new_oblock); - -- if (!avoid && bio_writes_complete_block(cache, bio)) { -+ if (writeback_mode(&cache->features) && -+ !avoid && bio_writes_complete_block(cache, bio)) { - issue_overwrite(mg, bio); - return; - } --- -2.1.0 - diff --git a/groups-Consolidate-the-setgroups-permission-checks.patch b/groups-Consolidate-the-setgroups-permission-checks.patch deleted file mode 100644 index e65ea2641..000000000 --- a/groups-Consolidate-the-setgroups-permission-checks.patch +++ /dev/null @@ -1,90 +0,0 @@ -From: "Eric W. Biederman" -Date: Fri, 5 Dec 2014 17:19:27 -0600 -Subject: [PATCH] groups: Consolidate the setgroups permission checks - -Today there are 3 instances of setgroups and due to an oversight their -permission checking has diverged. Add a common function so that -they may all share the same permission checking code. - -This corrects the current oversight in the current permission checks -and adds a helper to avoid this in the future. - -A user namespace security fix will update this new helper, shortly. - -Cc: stable@vger.kernel.org -Signed-off-by: "Eric W. Biederman" ---- - arch/s390/kernel/compat_linux.c | 2 +- - include/linux/cred.h | 1 + - kernel/groups.c | 9 ++++++++- - kernel/uid16.c | 2 +- - 4 files changed, 11 insertions(+), 3 deletions(-) - -diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c -index ca38139423ae..437e61159279 100644 ---- a/arch/s390/kernel/compat_linux.c -+++ b/arch/s390/kernel/compat_linux.c -@@ -249,7 +249,7 @@ COMPAT_SYSCALL_DEFINE2(s390_setgroups16, int, gidsetsize, u16 __user *, grouplis - struct group_info *group_info; - int retval; - -- if (!capable(CAP_SETGID)) -+ if (!may_setgroups()) - return -EPERM; - if ((unsigned)gidsetsize > NGROUPS_MAX) - return -EINVAL; -diff --git a/include/linux/cred.h b/include/linux/cred.h -index b2d0820837c4..2fb2ca2127ed 100644 ---- a/include/linux/cred.h -+++ b/include/linux/cred.h -@@ -68,6 +68,7 @@ extern void groups_free(struct group_info *); - extern int set_current_groups(struct group_info *); - extern void set_groups(struct cred *, struct group_info *); - extern int groups_search(const struct group_info *, kgid_t); -+extern bool may_setgroups(void); - - /* access the groups "array" with this macro */ - #define GROUP_AT(gi, i) \ -diff --git a/kernel/groups.c b/kernel/groups.c -index 451698f86cfa..02d8a251c476 100644 ---- a/kernel/groups.c -+++ b/kernel/groups.c -@@ -213,6 +213,13 @@ out: - return i; - } - -+bool may_setgroups(void) -+{ -+ struct user_namespace *user_ns = current_user_ns(); -+ -+ return ns_capable(user_ns, CAP_SETGID); -+} -+ - /* - * SMP: Our groups are copy-on-write. We can set them safely - * without another task interfering. -@@ -223,7 +230,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) - struct group_info *group_info; - int retval; - -- if (!ns_capable(current_user_ns(), CAP_SETGID)) -+ if (!may_setgroups()) - return -EPERM; - if ((unsigned)gidsetsize > NGROUPS_MAX) - return -EINVAL; -diff --git a/kernel/uid16.c b/kernel/uid16.c -index 602e5bbbceff..d58cc4d8f0d1 100644 ---- a/kernel/uid16.c -+++ b/kernel/uid16.c -@@ -176,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) - struct group_info *group_info; - int retval; - -- if (!ns_capable(current_user_ns(), CAP_SETGID)) -+ if (!may_setgroups()) - return -EPERM; - if ((unsigned)gidsetsize > NGROUPS_MAX) - return -EINVAL; --- -2.1.0 - diff --git a/isofs-Fix-infinite-looping-over-CE-entries.patch b/isofs-Fix-infinite-looping-over-CE-entries.patch deleted file mode 100644 index bff25ac27..000000000 --- a/isofs-Fix-infinite-looping-over-CE-entries.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Jan Kara -Date: Mon, 15 Dec 2014 14:22:46 +0100 -Subject: [PATCH] isofs: Fix infinite looping over CE entries - -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 -CC: stable@vger.kernel.org -Signed-off-by: Jan Kara ---- - fs/isofs/rock.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c -index f488bbae541a..bb63254ed848 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, --- -2.1.0 - diff --git a/kernel.spec b/kernel.spec index de88b5202..b5a08182c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 301 +%global baserelease 300 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -54,7 +54,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev %{stable_update} @@ -624,9 +624,6 @@ Patch26058: asus-nb-wmi-Add-wapf4-quirk-for-the-X550VB.patch #rhbz 1135338 Patch26090: HID-add-support-for-MS-Surface-Pro-3-Type-Cover.patch -#CVE-2014-8134 rhbz 1172765 1172769 -Patch26091: x86-kvm-Clear-paravirt_enabled-on-KVM-guests-for-esp.patch - #rhbz 1164945 Patch26092: xhci-Add-broken-streams-quirk-for-Fresco-Logic-FL100.patch Patch26093: uas-Add-US_FL_NO_ATA_1X-for-Seagate-devices-with-usb.patch @@ -635,9 +632,6 @@ Patch26094: uas-Add-US_FL_NO_REPORT_OPCODES-for-JMicron-JMS566-w.patch #rhbz 1172543 Patch26096: cfg80211-don-t-WARN-about-two-consecutive-Country-IE.patch -#CVE-2014-8133 rhbz 1172797 1174374 -Patch26100: x86-tls-Validate-TLS-entries-to-protect-espfix.patch - #rhbz 1173806 Patch26101: powerpc-powernv-force-all-CPUs-to-be-bootable.patch @@ -645,43 +639,15 @@ Patch26101: powerpc-powernv-force-all-CPUs-to-be-bootable.patch Patch26098: move-d_rcu-from-overlapping-d_child-to-overlapping-d.patch Patch26099: deal-with-deadlock-in-d_walk.patch -#CVE-2014-XXXX rhbz 1175235 1175250 -Patch26102: isofs-Fix-infinite-looping-over-CE-entries.patch - #rhbz 1175261 Patch26103: blk-mq-Fix-uninitialized-kobject-at-CPU-hotplugging.patch -#rhbz 1168434 -Patch26104: dm-cache-only-use-overwrite-optimisation-for-promoti.patch -Patch26105: dm-cache-dirty-flag-was-mistakenly-being-cleared-whe.patch -Patch26106: dm-cache-fix-spurious-cell_defer-when-dealing-with-p.patch - -#mount fixes for stable -Patch26108: mnt-Implicitly-add-MNT_NODEV-on-remount-when-it-was-.patch -Patch26109: mnt-Update-unprivileged-remount-test.patch -Patch26110: umount-Disallow-unprivileged-mount-force.patch - -#CVE-2014-8989 rhbz 1170684 1170688 -Patch26111: groups-Consolidate-the-setgroups-permission-checks.patch -Patch26112: userns-Document-what-the-invariant-required-for-safe.patch -Patch26113: userns-Don-t-allow-setgroups-until-a-gid-mapping-has.patch -Patch26114: userns-Don-t-allow-unprivileged-creation-of-gid-mapp.patch -Patch26115: userns-Check-euid-no-fsuid-when-establishing-an-unpr.patch -Patch26116: userns-Only-allow-the-creator-of-the-userns-unprivil.patch -Patch26117: userns-Rename-id_map_mutex-to-userns_state_mutex.patch -Patch26118: userns-Add-a-knob-to-disable-setgroups-on-a-per-user.patch -Patch26119: userns-Allow-setting-gid_maps-without-privilege-when.patch -Patch26120: userns-Unbreak-the-unprivileged-remount-tests.patch - #rhbz 1163927 Patch26121: Set-UID-in-sess_auth_rawntlmssp_authenticate-too.patch #CVE-2014-9428 rhbz 1178826,1178833 Patch26122: batman-adv-Calculate-extra-tail-size-based-on-queued.patch -#CVE-2014-9419 rhbz 1177260,1177263 -Patch26123: x86_64-switch_to-Load-TLS-descriptors-before-switchi.patch - #CVE-2014-9529 rhbz 1179813 1179853 Patch26124: KEYS-close-race-between-key-lookup-and-freeing.patch @@ -1418,9 +1384,6 @@ ApplyPatch asus-nb-wmi-Add-wapf4-quirk-for-the-X550VB.patch #rhbz 1135338 ApplyPatch HID-add-support-for-MS-Surface-Pro-3-Type-Cover.patch -#CVE-2014-8134 rhbz 1172765 1172769 -ApplyPatch x86-kvm-Clear-paravirt_enabled-on-KVM-guests-for-esp.patch - #rhbz 1164945 ApplyPatch xhci-Add-broken-streams-quirk-for-Fresco-Logic-FL100.patch ApplyPatch uas-Add-US_FL_NO_ATA_1X-for-Seagate-devices-with-usb.patch @@ -1429,9 +1392,6 @@ ApplyPatch uas-Add-US_FL_NO_REPORT_OPCODES-for-JMicron-JMS566-w.patch #rhbz 1172543 ApplyPatch cfg80211-don-t-WARN-about-two-consecutive-Country-IE.patch -#CVE-2014-8133 rhbz 1172797 1174374 -ApplyPatch x86-tls-Validate-TLS-entries-to-protect-espfix.patch - #rhbz 1173806 ApplyPatch powerpc-powernv-force-all-CPUs-to-be-bootable.patch @@ -1439,43 +1399,15 @@ ApplyPatch powerpc-powernv-force-all-CPUs-to-be-bootable.patch ApplyPatch move-d_rcu-from-overlapping-d_child-to-overlapping-d.patch ApplyPatch deal-with-deadlock-in-d_walk.patch -#CVE-2014-XXXX rhbz 1175235 1175250 -ApplyPatch isofs-Fix-infinite-looping-over-CE-entries.patch - #rhbz 1175261 ApplyPatch blk-mq-Fix-uninitialized-kobject-at-CPU-hotplugging.patch -#rhbz 1168434 -ApplyPatch dm-cache-only-use-overwrite-optimisation-for-promoti.patch -ApplyPatch dm-cache-dirty-flag-was-mistakenly-being-cleared-whe.patch -ApplyPatch dm-cache-fix-spurious-cell_defer-when-dealing-with-p.patch - -#mount fixes for stable -ApplyPatch mnt-Implicitly-add-MNT_NODEV-on-remount-when-it-was-.patch -ApplyPatch mnt-Update-unprivileged-remount-test.patch -ApplyPatch umount-Disallow-unprivileged-mount-force.patch - -#CVE-2014-8989 rhbz 1170684 1170688 -ApplyPatch groups-Consolidate-the-setgroups-permission-checks.patch -ApplyPatch userns-Document-what-the-invariant-required-for-safe.patch -ApplyPatch userns-Don-t-allow-setgroups-until-a-gid-mapping-has.patch -ApplyPatch userns-Don-t-allow-unprivileged-creation-of-gid-mapp.patch -ApplyPatch userns-Check-euid-no-fsuid-when-establishing-an-unpr.patch -ApplyPatch userns-Only-allow-the-creator-of-the-userns-unprivil.patch -ApplyPatch userns-Rename-id_map_mutex-to-userns_state_mutex.patch -ApplyPatch userns-Add-a-knob-to-disable-setgroups-on-a-per-user.patch -ApplyPatch userns-Allow-setting-gid_maps-without-privilege-when.patch -ApplyPatch userns-Unbreak-the-unprivileged-remount-tests.patch - #rhbz 1163927 ApplyPatch Set-UID-in-sess_auth_rawntlmssp_authenticate-too.patch #CVE-2014-9428 rhbz 1178826,1178833 ApplyPatch batman-adv-Calculate-extra-tail-size-based-on-queued.patch -#CVE-2014-9419 rhbz 1177260,1177263 -ApplyPatch x86_64-switch_to-Load-TLS-descriptors-before-switchi.patch - #CVE-2014-9529 rhbz 1179813 1179853 ApplyPatch KEYS-close-race-between-key-lookup-and-freeing.patch @@ -2353,6 +2285,9 @@ fi # ||----w | # || || %changelog +* Thu Jan 08 2015 Justin M. Forbes - 3.17.8-300 +- Linux v3.17.8 + * Wed Jan 07 2015 Josh Boyer - CVE-2014-9529 memory corruption or panic during key gc (rhbz 1179813 1179853) - Enable POWERCAP and INTEL_RAPL diff --git a/mnt-Implicitly-add-MNT_NODEV-on-remount-when-it-was-.patch b/mnt-Implicitly-add-MNT_NODEV-on-remount-when-it-was-.patch deleted file mode 100644 index 60599029c..000000000 --- a/mnt-Implicitly-add-MNT_NODEV-on-remount-when-it-was-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From: "Eric W. Biederman" -Date: Wed, 13 Aug 2014 01:33:38 -0700 -Subject: [PATCH] mnt: Implicitly add MNT_NODEV on remount when it was - implicitly added by mount - -Now that remount is properly enforcing the rule that you can't remove -nodev at least sandstorm.io is breaking when performing a remount. - -It turns out that there is an easy intuitive solution implicitly -add nodev on remount when nodev was implicitly added on mount. - -Tested-by: Cedric Bosdonnat -Tested-by: Richard Weinberger -Cc: stable@vger.kernel.org -Signed-off-by: "Eric W. Biederman" ---- - fs/namespace.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/fs/namespace.c b/fs/namespace.c -index 550dbff08677..72b41e49772d 100644 ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1955,7 +1955,13 @@ static int do_remount(struct path *path, int flags, int mnt_flags, - } - if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) && - !(mnt_flags & MNT_NODEV)) { -- return -EPERM; -+ /* Was the nodev implicitly added in mount? */ -+ if ((mnt->mnt_ns->user_ns != &init_user_ns) && -+ !(sb->s_type->fs_flags & FS_USERNS_DEV_MOUNT)) { -+ mnt_flags |= MNT_NODEV; -+ } else { -+ return -EPERM; -+ } - } - if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) && - !(mnt_flags & MNT_NOSUID)) { --- -2.1.0 - diff --git a/mnt-Update-unprivileged-remount-test.patch b/mnt-Update-unprivileged-remount-test.patch deleted file mode 100644 index 5913d8272..000000000 --- a/mnt-Update-unprivileged-remount-test.patch +++ /dev/null @@ -1,280 +0,0 @@ -From: "Eric W. Biederman" -Date: Fri, 22 Aug 2014 16:39:03 -0500 -Subject: [PATCH] mnt: Update unprivileged remount test - -- MNT_NODEV should be irrelevant except when reading back mount flags, - no longer specify MNT_NODEV on remount. - -- Test MNT_NODEV on devpts where it is meaningful even for unprivileged mounts. - -- Add a test to verify that remount of a prexisting mount with the same flags - is allowed and does not change those flags. - -- Cleanup up the definitions of MS_REC, MS_RELATIME, MS_STRICTATIME that are used - when the code is built in an environment without them. - -- Correct the test error messages when tests fail. There were not 5 tests - that tested MS_RELATIME. - -Cc: stable@vger.kernel.org -Signed-off-by: Eric W. Biederman ---- - .../selftests/mount/unprivileged-remount-test.c | 172 +++++++++++++++++---- - 1 file changed, 142 insertions(+), 30 deletions(-) - -diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c -index 1b3ff2fda4d0..9669d375625a 100644 ---- a/tools/testing/selftests/mount/unprivileged-remount-test.c -+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c -@@ -6,6 +6,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -32,11 +34,14 @@ - # define CLONE_NEWPID 0x20000000 - #endif - -+#ifndef MS_REC -+# define MS_REC 16384 -+#endif - #ifndef MS_RELATIME --#define MS_RELATIME (1 << 21) -+# define MS_RELATIME (1 << 21) - #endif - #ifndef MS_STRICTATIME --#define MS_STRICTATIME (1 << 24) -+# define MS_STRICTATIME (1 << 24) - #endif - - static void die(char *fmt, ...) -@@ -87,6 +92,45 @@ static void write_file(char *filename, char *fmt, ...) - } - } - -+static int read_mnt_flags(const char *path) -+{ -+ int ret; -+ struct statvfs stat; -+ int mnt_flags; -+ -+ ret = statvfs(path, &stat); -+ if (ret != 0) { -+ die("statvfs of %s failed: %s\n", -+ path, strerror(errno)); -+ } -+ if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | \ -+ ST_NOEXEC | ST_NOATIME | ST_NODIRATIME | ST_RELATIME | \ -+ ST_SYNCHRONOUS | ST_MANDLOCK)) { -+ die("Unrecognized mount flags\n"); -+ } -+ mnt_flags = 0; -+ if (stat.f_flag & ST_RDONLY) -+ mnt_flags |= MS_RDONLY; -+ if (stat.f_flag & ST_NOSUID) -+ mnt_flags |= MS_NOSUID; -+ if (stat.f_flag & ST_NODEV) -+ mnt_flags |= MS_NODEV; -+ if (stat.f_flag & ST_NOEXEC) -+ mnt_flags |= MS_NOEXEC; -+ if (stat.f_flag & ST_NOATIME) -+ mnt_flags |= MS_NOATIME; -+ if (stat.f_flag & ST_NODIRATIME) -+ mnt_flags |= MS_NODIRATIME; -+ if (stat.f_flag & ST_RELATIME) -+ mnt_flags |= MS_RELATIME; -+ if (stat.f_flag & ST_SYNCHRONOUS) -+ mnt_flags |= MS_SYNCHRONOUS; -+ if (stat.f_flag & ST_MANDLOCK) -+ mnt_flags |= ST_MANDLOCK; -+ -+ return mnt_flags; -+} -+ - static void create_and_enter_userns(void) - { - uid_t uid; -@@ -118,7 +162,8 @@ static void create_and_enter_userns(void) - } - - static --bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) -+bool test_unpriv_remount(const char *fstype, const char *mount_options, -+ int mount_flags, int remount_flags, int invalid_flags) - { - pid_t child; - -@@ -151,9 +196,11 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) - strerror(errno)); - } - -- if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) { -- die("mount of /tmp failed: %s\n", -- strerror(errno)); -+ if (mount("testing", "/tmp", fstype, mount_flags, mount_options) != 0) { -+ die("mount of %s with options '%s' on /tmp failed: %s\n", -+ fstype, -+ mount_options? mount_options : "", -+ strerror(errno)); - } - - create_and_enter_userns(); -@@ -181,62 +228,127 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) - - static bool test_unpriv_remount_simple(int mount_flags) - { -- return test_unpriv_remount(mount_flags, mount_flags, 0); -+ return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, 0); - } - - static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) - { -- return test_unpriv_remount(mount_flags, mount_flags, invalid_flags); -+ return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, -+ invalid_flags); -+} -+ -+static bool test_priv_mount_unpriv_remount(void) -+{ -+ pid_t child; -+ int ret; -+ const char *orig_path = "/dev"; -+ const char *dest_path = "/tmp"; -+ int orig_mnt_flags, remount_mnt_flags; -+ -+ child = fork(); -+ if (child == -1) { -+ die("fork failed: %s\n", -+ strerror(errno)); -+ } -+ if (child != 0) { /* parent */ -+ pid_t pid; -+ int status; -+ pid = waitpid(child, &status, 0); -+ if (pid == -1) { -+ die("waitpid failed: %s\n", -+ strerror(errno)); -+ } -+ if (pid != child) { -+ die("waited for %d got %d\n", -+ child, pid); -+ } -+ if (!WIFEXITED(status)) { -+ die("child did not terminate cleanly\n"); -+ } -+ return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false; -+ } -+ -+ orig_mnt_flags = read_mnt_flags(orig_path); -+ -+ create_and_enter_userns(); -+ ret = unshare(CLONE_NEWNS); -+ if (ret != 0) { -+ die("unshare(CLONE_NEWNS) failed: %s\n", -+ strerror(errno)); -+ } -+ -+ ret = mount(orig_path, dest_path, "bind", MS_BIND | MS_REC, NULL); -+ if (ret != 0) { -+ die("recursive bind mount of %s onto %s failed: %s\n", -+ orig_path, dest_path, strerror(errno)); -+ } -+ -+ ret = mount(dest_path, dest_path, "none", -+ MS_REMOUNT | MS_BIND | orig_mnt_flags , NULL); -+ if (ret != 0) { -+ /* system("cat /proc/self/mounts"); */ -+ die("remount of /tmp failed: %s\n", -+ strerror(errno)); -+ } -+ -+ remount_mnt_flags = read_mnt_flags(dest_path); -+ if (orig_mnt_flags != remount_mnt_flags) { -+ die("Mount flags unexpectedly changed during remount of %s originally mounted on %s\n", -+ dest_path, orig_path); -+ } -+ exit(EXIT_SUCCESS); - } - - int main(int argc, char **argv) - { -- if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) { -+ if (!test_unpriv_remount_simple(MS_RDONLY)) { - die("MS_RDONLY malfunctions\n"); - } -- if (!test_unpriv_remount_simple(MS_NODEV)) { -+ if (!test_unpriv_remount("devpts", "newinstance", MS_NODEV, MS_NODEV, 0)) { - die("MS_NODEV malfunctions\n"); - } -- if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) { -+ if (!test_unpriv_remount_simple(MS_NOSUID)) { - die("MS_NOSUID malfunctions\n"); - } -- if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) { -+ if (!test_unpriv_remount_simple(MS_NOEXEC)) { - die("MS_NOEXEC malfunctions\n"); - } -- if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV, -- MS_NOATIME|MS_NODEV)) -+ if (!test_unpriv_remount_atime(MS_RELATIME, -+ MS_NOATIME)) - { - die("MS_RELATIME malfunctions\n"); - } -- if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV, -- MS_NOATIME|MS_NODEV)) -+ if (!test_unpriv_remount_atime(MS_STRICTATIME, -+ MS_NOATIME)) - { - die("MS_STRICTATIME malfunctions\n"); - } -- if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV, -- MS_STRICTATIME|MS_NODEV)) -+ if (!test_unpriv_remount_atime(MS_NOATIME, -+ MS_STRICTATIME)) - { -- die("MS_RELATIME malfunctions\n"); -+ die("MS_NOATIME malfunctions\n"); - } -- if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV, -- MS_NOATIME|MS_NODEV)) -+ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME, -+ MS_NOATIME)) - { -- die("MS_RELATIME malfunctions\n"); -+ die("MS_RELATIME|MS_NODIRATIME malfunctions\n"); - } -- if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV, -- MS_NOATIME|MS_NODEV)) -+ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME, -+ MS_NOATIME)) - { -- die("MS_RELATIME malfunctions\n"); -+ die("MS_STRICTATIME|MS_NODIRATIME malfunctions\n"); - } -- if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV, -- MS_STRICTATIME|MS_NODEV)) -+ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME, -+ MS_STRICTATIME)) - { -- die("MS_RELATIME malfunctions\n"); -+ die("MS_NOATIME|MS_DIRATIME malfunctions\n"); - } -- if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV, -- MS_NOATIME|MS_NODEV)) -+ if (!test_unpriv_remount("ramfs", NULL, MS_STRICTATIME, 0, MS_NOATIME)) - { - die("Default atime malfunctions\n"); - } -+ if (!test_priv_mount_unpriv_remount()) { -+ die("Mount flags unexpectedly changed after remount\n"); -+ } - return EXIT_SUCCESS; - } --- -2.1.0 - diff --git a/perf-man.tar.gz b/perf-man.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..394a99fb29fdee12dc081842234b5620cf8b2a9f GIT binary patch literal 33955 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%0A!Ms)zG4eq04h-r&rC_5sT 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 TXYpBl7N7qg6_qtz0MG&e&rc+0 literal 0 HcmV?d00001 diff --git a/sources b/sources index 396a8ab2c..35129af63 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ fb30d0f29214d75cddd2faa94f73d5cf linux-3.17.tar.xz 159e969cbc27201d8e2fa0f609dc722f perf-man-3.17.tar.gz -96d5959bdc223fa6aa0ed132c93cf814 patch-3.17.7.xz +4ea1c0e18b18406bcd248bf06b95aec3 patch-3.17.8.xz diff --git a/umount-Disallow-unprivileged-mount-force.patch b/umount-Disallow-unprivileged-mount-force.patch deleted file mode 100644 index 3acbe3544..000000000 --- a/umount-Disallow-unprivileged-mount-force.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: "Eric W. Biederman" -Date: Sat, 4 Oct 2014 14:44:03 -0700 -Subject: [PATCH] umount: Disallow unprivileged mount force - -Forced unmount affects not just the mount namespace but the underlying -superblock as well. Restrict forced unmount to the global root user -for now. Otherwise it becomes possible a user in a less privileged -mount namespace to force the shutdown of a superblock of a filesystem -in a more privileged mount namespace, allowing a DOS attack on root. - -Cc: stable@vger.kernel.org -Signed-off-by: "Eric W. Biederman" ---- - fs/namespace.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/fs/namespace.c b/fs/namespace.c -index 72b41e49772d..90707be662f2 100644 ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1430,6 +1430,9 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) - goto dput_and_out; - if (mnt->mnt.mnt_flags & MNT_LOCKED) - goto dput_and_out; -+ retval = -EPERM; -+ if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) -+ goto dput_and_out; - - retval = do_umount(mnt, flags); - dput_and_out: --- -2.1.0 - diff --git a/userns-Add-a-knob-to-disable-setgroups-on-a-per-user.patch b/userns-Add-a-knob-to-disable-setgroups-on-a-per-user.patch deleted file mode 100644 index e87c897a5..000000000 --- a/userns-Add-a-knob-to-disable-setgroups-on-a-per-user.patch +++ /dev/null @@ -1,280 +0,0 @@ -From: "Eric W. Biederman" -Date: Tue, 2 Dec 2014 12:27:26 -0600 -Subject: [PATCH] userns: Add a knob to disable setgroups on a per user - namespace basis - -- Expose the knob to user space through a proc file /proc//setgroups - - A value of "deny" means the setgroups system call is disabled in the - current processes user namespace and can not be enabled in the - future in this user namespace. - - A value of "allow" means the segtoups system call is enabled. - -- Descendant user namespaces inherit the value of setgroups from - their parents. - -- A proc file is used (instead of a sysctl) as sysctls currently do - not allow checking the permissions at open time. - -- Writing to the proc file is restricted to before the gid_map - for the user namespace is set. - - This ensures that disabling setgroups at a user namespace - level will never remove the ability to call setgroups - from a process that already has that ability. - - A process may opt in to the setgroups disable for itself by - creating, entering and configuring a user namespace or by calling - setns on an existing user namespace with setgroups disabled. - Processes without privileges already can not call setgroups so this - is a noop. Prodcess with privilege become processes without - privilege when entering a user namespace and as with any other path - to dropping privilege they would not have the ability to call - setgroups. So this remains within the bounds of what is possible - without a knob to disable setgroups permanently in a user namespace. - -Cc: stable@vger.kernel.org -Signed-off-by: "Eric W. Biederman" ---- - fs/proc/base.c | 53 ++++++++++++++++++++++++++ - include/linux/user_namespace.h | 7 ++++ - kernel/user.c | 1 + - kernel/user_namespace.c | 85 ++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 146 insertions(+) - -diff --git a/fs/proc/base.c b/fs/proc/base.c -index baf852b648ad..3ec60dee75da 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -2493,6 +2493,57 @@ static const struct file_operations proc_projid_map_operations = { - .llseek = seq_lseek, - .release = proc_id_map_release, - }; -+ -+static int proc_setgroups_open(struct inode *inode, struct file *file) -+{ -+ struct user_namespace *ns = NULL; -+ struct task_struct *task; -+ int ret; -+ -+ ret = -ESRCH; -+ task = get_proc_task(inode); -+ if (task) { -+ rcu_read_lock(); -+ ns = get_user_ns(task_cred_xxx(task, user_ns)); -+ rcu_read_unlock(); -+ put_task_struct(task); -+ } -+ if (!ns) -+ goto err; -+ -+ if (file->f_mode & FMODE_WRITE) { -+ ret = -EACCES; -+ if (!ns_capable(ns, CAP_SYS_ADMIN)) -+ goto err_put_ns; -+ } -+ -+ ret = single_open(file, &proc_setgroups_show, ns); -+ if (ret) -+ goto err_put_ns; -+ -+ return 0; -+err_put_ns: -+ put_user_ns(ns); -+err: -+ return ret; -+} -+ -+static int proc_setgroups_release(struct inode *inode, struct file *file) -+{ -+ struct seq_file *seq = file->private_data; -+ struct user_namespace *ns = seq->private; -+ int ret = single_release(inode, file); -+ put_user_ns(ns); -+ return ret; -+} -+ -+static const struct file_operations proc_setgroups_operations = { -+ .open = proc_setgroups_open, -+ .write = proc_setgroups_write, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = proc_setgroups_release, -+}; - #endif /* CONFIG_USER_NS */ - - static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, -@@ -2601,6 +2652,7 @@ static const struct pid_entry tgid_base_stuff[] = { - REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), - REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), - REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), -+ REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), - #endif - #ifdef CONFIG_CHECKPOINT_RESTORE - REG("timers", S_IRUGO, proc_timers_operations), -@@ -2944,6 +2996,7 @@ static const struct pid_entry tid_base_stuff[] = { - REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), - REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), - REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), -+ REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), - #endif - }; - -diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h -index 8d493083486a..9f3579ff543d 100644 ---- a/include/linux/user_namespace.h -+++ b/include/linux/user_namespace.h -@@ -17,6 +17,10 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ - } extent[UID_GID_MAP_MAX_EXTENTS]; - }; - -+#define USERNS_SETGROUPS_ALLOWED 1UL -+ -+#define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED -+ - struct user_namespace { - struct uid_gid_map uid_map; - struct uid_gid_map gid_map; -@@ -27,6 +31,7 @@ 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 -@@ -63,6 +68,8 @@ extern const struct seq_operations proc_projid_seq_operations; - extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); - extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); - extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *); -+extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *); -+extern int proc_setgroups_show(struct seq_file *m, void *v); - extern bool userns_may_setgroups(const struct user_namespace *ns); - #else - -diff --git a/kernel/user.c b/kernel/user.c -index 4efa39350e44..2d09940c9632 100644 ---- a/kernel/user.c -+++ b/kernel/user.c -@@ -51,6 +51,7 @@ struct user_namespace init_user_ns = { - .owner = GLOBAL_ROOT_UID, - .group = GLOBAL_ROOT_GID, - .proc_inum = PROC_USER_INIT_INO, -+ .flags = USERNS_INIT_FLAGS, - #ifdef CONFIG_PERSISTENT_KEYRINGS - .persistent_keyring_register_sem = - __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem), -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 44a555ac6104..6e80f4c1322b 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -100,6 +100,11 @@ int create_user_ns(struct cred *new) - ns->owner = owner; - ns->group = group; - -+ /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ -+ mutex_lock(&userns_state_mutex); -+ ns->flags = parent_ns->flags; -+ mutex_unlock(&userns_state_mutex); -+ - set_cred_user_ns(new, ns); - - #ifdef CONFIG_PERSISTENT_KEYRINGS -@@ -839,6 +844,84 @@ static bool new_idmap_permitted(const struct file *file, - return false; - } - -+int proc_setgroups_show(struct seq_file *seq, void *v) -+{ -+ struct user_namespace *ns = seq->private; -+ unsigned long userns_flags = ACCESS_ONCE(ns->flags); -+ -+ seq_printf(seq, "%s\n", -+ (userns_flags & USERNS_SETGROUPS_ALLOWED) ? -+ "allow" : "deny"); -+ return 0; -+} -+ -+ssize_t proc_setgroups_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct seq_file *seq = file->private_data; -+ struct user_namespace *ns = seq->private; -+ char kbuf[8], *pos; -+ bool setgroups_allowed; -+ ssize_t ret; -+ -+ /* Only allow a very narrow range of strings to be written */ -+ ret = -EINVAL; -+ if ((*ppos != 0) || (count >= sizeof(kbuf))) -+ goto out; -+ -+ /* What was written? */ -+ ret = -EFAULT; -+ if (copy_from_user(kbuf, buf, count)) -+ goto out; -+ kbuf[count] = '\0'; -+ pos = kbuf; -+ -+ /* What is being requested? */ -+ ret = -EINVAL; -+ if (strncmp(pos, "allow", 5) == 0) { -+ pos += 5; -+ setgroups_allowed = true; -+ } -+ else if (strncmp(pos, "deny", 4) == 0) { -+ pos += 4; -+ setgroups_allowed = false; -+ } -+ else -+ goto out; -+ -+ /* Verify there is not trailing junk on the line */ -+ pos = skip_spaces(pos); -+ if (*pos != '\0') -+ goto out; -+ -+ ret = -EPERM; -+ mutex_lock(&userns_state_mutex); -+ if (setgroups_allowed) { -+ /* Enabling setgroups after setgroups has been disabled -+ * is not allowed. -+ */ -+ if (!(ns->flags & USERNS_SETGROUPS_ALLOWED)) -+ goto out_unlock; -+ } else { -+ /* Permanently disabling setgroups after setgroups has -+ * been enabled by writing the gid_map is not allowed. -+ */ -+ if (ns->gid_map.nr_extents != 0) -+ goto out_unlock; -+ ns->flags &= ~USERNS_SETGROUPS_ALLOWED; -+ } -+ mutex_unlock(&userns_state_mutex); -+ -+ /* Report a successful write */ -+ *ppos = count; -+ ret = count; -+out: -+ return ret; -+out_unlock: -+ mutex_unlock(&userns_state_mutex); -+ goto out; -+} -+ - bool userns_may_setgroups(const struct user_namespace *ns) - { - bool allowed; -@@ -848,6 +931,8 @@ bool userns_may_setgroups(const struct user_namespace *ns) - * the user namespace has been established. - */ - allowed = ns->gid_map.nr_extents != 0; -+ /* Is setgroups allowed? */ -+ allowed = allowed && (ns->flags & USERNS_SETGROUPS_ALLOWED); - mutex_unlock(&userns_state_mutex); - - return allowed; --- -2.1.0 - diff --git a/userns-Allow-setting-gid_maps-without-privilege-when.patch b/userns-Allow-setting-gid_maps-without-privilege-when.patch deleted file mode 100644 index 97d3fe69a..000000000 --- a/userns-Allow-setting-gid_maps-without-privilege-when.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: "Eric W. Biederman" -Date: Fri, 5 Dec 2014 19:36:04 -0600 -Subject: [PATCH] userns: Allow setting gid_maps without privilege when - setgroups is disabled - -Now that setgroups can be disabled and not reenabled, setting gid_map -without privielge can now be enabled when setgroups is disabled. - -This restores most of the functionality that was lost when unprivileged -setting of gid_map was removed. Applications that use this functionality -will need to check to see if they use setgroups or init_groups, and if they -don't they can be fixed by simply disabling setgroups before writing to -gid_map. - -Cc: stable@vger.kernel.org -Reviewed-by: Andy Lutomirski -Signed-off-by: "Eric W. Biederman" ---- - kernel/user_namespace.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 6e80f4c1322b..a2e37c5d2f63 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -826,6 +826,11 @@ static bool new_idmap_permitted(const struct file *file, - kuid_t uid = make_kuid(ns->parent, id); - if (uid_eq(uid, cred->euid)) - return true; -+ } else if (cap_setid == CAP_SETGID) { -+ kgid_t gid = make_kgid(ns->parent, id); -+ if (!(ns->flags & USERNS_SETGROUPS_ALLOWED) && -+ gid_eq(gid, cred->egid)) -+ return true; - } - } - --- -2.1.0 - diff --git a/userns-Check-euid-no-fsuid-when-establishing-an-unpr.patch b/userns-Check-euid-no-fsuid-when-establishing-an-unpr.patch deleted file mode 100644 index 50830c30e..000000000 --- a/userns-Check-euid-no-fsuid-when-establishing-an-unpr.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: "Eric W. Biederman" -Date: Fri, 5 Dec 2014 18:26:30 -0600 -Subject: [PATCH] userns: Check euid no fsuid when establishing an unprivileged - uid mapping - -setresuid allows the euid to be set to any of uid, euid, suid, and -fsuid. Therefor it is safe to allow an unprivileged user to map -their euid and use CAP_SETUID privileged with exactly that uid, -as no new credentials can be obtained. - -I can not find a combination of existing system calls that allows setting -uid, euid, suid, and fsuid from the fsuid making the previous use -of fsuid for allowing unprivileged mappings a bug. - -This is part of a fix for CVE-2014-8989. - -Cc: stable@vger.kernel.org -Reviewed-by: Andy Lutomirski -Signed-off-by: "Eric W. Biederman" ---- - kernel/user_namespace.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 1ce6d67c07b7..9451b12a9b6c 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -819,7 +819,7 @@ static bool new_idmap_permitted(const struct file *file, - u32 id = new_map->extent[0].lower_first; - if (cap_setid == CAP_SETUID) { - kuid_t uid = make_kuid(ns->parent, id); -- if (uid_eq(uid, file->f_cred->fsuid)) -+ if (uid_eq(uid, file->f_cred->euid)) - return true; - } - } --- -2.1.0 - diff --git a/userns-Document-what-the-invariant-required-for-safe.patch b/userns-Document-what-the-invariant-required-for-safe.patch deleted file mode 100644 index c364b2bce..000000000 --- a/userns-Document-what-the-invariant-required-for-safe.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: "Eric W. Biederman" -Date: Fri, 5 Dec 2014 17:51:47 -0600 -Subject: [PATCH] userns: Document what the invariant required for safe - unprivileged mappings. - -The rule is simple. Don't allow anything that wouldn't be allowed -without unprivileged mappings. - -It was previously overlooked that establishing gid mappings would -allow dropping groups and potentially gaining permission to files and -directories that had lesser permissions for a specific group than for -all other users. - -This is the rule needed to fix CVE-2014-8989 and prevent any other -security issues with new_idmap_permitted. - -The reason for this rule is that the unix permission model is old and -there are programs out there somewhere that take advantage of every -little corner of it. So allowing a uid or gid mapping to be -established without privielge that would allow anything that would not -be allowed without that mapping will result in expectations from some -code somewhere being violated. Violated expectations about the -behavior of the OS is a long way to say a security issue. - -Cc: stable@vger.kernel.org -Signed-off-by: "Eric W. Biederman" ---- - kernel/user_namespace.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index aa312b0dc3ec..b99c862a2e3f 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -812,7 +812,9 @@ static bool new_idmap_permitted(const struct file *file, - struct user_namespace *ns, int cap_setid, - struct uid_gid_map *new_map) - { -- /* Allow mapping to your own filesystem ids */ -+ /* Don't allow mappings that would allow anything that wouldn't -+ * be allowed without the establishment of unprivileged mappings. -+ */ - if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1)) { - u32 id = new_map->extent[0].lower_first; - if (cap_setid == CAP_SETUID) { --- -2.1.0 - diff --git a/userns-Don-t-allow-setgroups-until-a-gid-mapping-has.patch b/userns-Don-t-allow-setgroups-until-a-gid-mapping-has.patch deleted file mode 100644 index 81217d2a5..000000000 --- a/userns-Don-t-allow-setgroups-until-a-gid-mapping-has.patch +++ /dev/null @@ -1,98 +0,0 @@ -From: "Eric W. Biederman" -Date: Fri, 5 Dec 2014 18:01:11 -0600 -Subject: [PATCH] userns: Don't allow setgroups until a gid mapping has been - setablished - -setgroups is unique in not needing a valid mapping before it can be called, -in the case of setgroups(0, NULL) which drops all supplemental groups. - -The design of the user namespace assumes that CAP_SETGID can not actually -be used until a gid mapping is established. Therefore add a helper function -to see if the user namespace gid mapping has been established and call -that function in the setgroups permission check. - -This is part of the fix for CVE-2014-8989, being able to drop groups -without privilege using user namespaces. - -Cc: stable@vger.kernel.org -Reviewed-by: Andy Lutomirski -Signed-off-by: "Eric W. Biederman" ---- - include/linux/user_namespace.h | 5 +++++ - kernel/groups.c | 4 +++- - kernel/user_namespace.c | 14 ++++++++++++++ - 3 files changed, 22 insertions(+), 1 deletion(-) - -diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h -index e95372654f09..8d493083486a 100644 ---- a/include/linux/user_namespace.h -+++ b/include/linux/user_namespace.h -@@ -63,6 +63,7 @@ extern const struct seq_operations proc_projid_seq_operations; - extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); - extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); - extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *); -+extern bool userns_may_setgroups(const struct user_namespace *ns); - #else - - static inline struct user_namespace *get_user_ns(struct user_namespace *ns) -@@ -87,6 +88,10 @@ static inline void put_user_ns(struct user_namespace *ns) - { - } - -+static inline bool userns_may_setgroups(const struct user_namespace *ns) -+{ -+ return true; -+} - #endif - - #endif /* _LINUX_USER_H */ -diff --git a/kernel/groups.c b/kernel/groups.c -index 02d8a251c476..664411f171b5 100644 ---- a/kernel/groups.c -+++ b/kernel/groups.c -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - - /* init to 2 - one for init_task, one to ensure it is never freed */ -@@ -217,7 +218,8 @@ bool may_setgroups(void) - { - struct user_namespace *user_ns = current_user_ns(); - -- return ns_capable(user_ns, CAP_SETGID); -+ return ns_capable(user_ns, CAP_SETGID) && -+ userns_may_setgroups(user_ns); - } - - /* -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index b99c862a2e3f..27c8dab48c07 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -843,6 +843,20 @@ static bool new_idmap_permitted(const struct file *file, - return false; - } - -+bool userns_may_setgroups(const struct user_namespace *ns) -+{ -+ bool allowed; -+ -+ mutex_lock(&id_map_mutex); -+ /* It is not safe to use setgroups until a gid mapping in -+ * the user namespace has been established. -+ */ -+ allowed = ns->gid_map.nr_extents != 0; -+ mutex_unlock(&id_map_mutex); -+ -+ return allowed; -+} -+ - static void *userns_get(struct task_struct *task) - { - struct user_namespace *user_ns; --- -2.1.0 - diff --git a/userns-Don-t-allow-unprivileged-creation-of-gid-mapp.patch b/userns-Don-t-allow-unprivileged-creation-of-gid-mapp.patch deleted file mode 100644 index b1d53828a..000000000 --- a/userns-Don-t-allow-unprivileged-creation-of-gid-mapp.patch +++ /dev/null @@ -1,46 +0,0 @@ -From: "Eric W. Biederman" -Date: Fri, 5 Dec 2014 18:14:19 -0600 -Subject: [PATCH] userns: Don't allow unprivileged creation of gid mappings - -As any gid mapping will allow and must allow for backwards -compatibility dropping groups don't allow any gid mappings to be -established without CAP_SETGID in the parent user namespace. - -For a small class of applications this change breaks userspace -and removes useful functionality. This small class of applications -includes tools/testing/selftests/mount/unprivilged-remount-test.c - -Most of the removed functionality will be added back with the addition -of a one way knob to disable setgroups. Once setgroups is disabled -setting the gid_map becomes as safe as setting the uid_map. - -For more common applications that set the uid_map and the gid_map -with privilege this change will have no affect. - -This is part of a fix for CVE-2014-8989. - -Cc: stable@vger.kernel.org -Reviewed-by: Andy Lutomirski -Signed-off-by: "Eric W. Biederman" ---- - kernel/user_namespace.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 27c8dab48c07..1ce6d67c07b7 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -821,10 +821,6 @@ static bool new_idmap_permitted(const struct file *file, - kuid_t uid = make_kuid(ns->parent, id); - if (uid_eq(uid, file->f_cred->fsuid)) - return true; -- } else if (cap_setid == CAP_SETGID) { -- kgid_t gid = make_kgid(ns->parent, id); -- if (gid_eq(gid, file->f_cred->fsgid)) -- return true; - } - } - --- -2.1.0 - diff --git a/userns-Only-allow-the-creator-of-the-userns-unprivil.patch b/userns-Only-allow-the-creator-of-the-userns-unprivil.patch deleted file mode 100644 index 8381b14e3..000000000 --- a/userns-Only-allow-the-creator-of-the-userns-unprivil.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: "Eric W. Biederman" -Date: Wed, 26 Nov 2014 23:22:14 -0600 -Subject: [PATCH] userns: Only allow the creator of the userns unprivileged - mappings - -If you did not create the user namespace and are allowed -to write to uid_map or gid_map you should already have the necessary -privilege in the parent user namespace to establish any mapping -you want so this will not affect userspace in practice. - -Limiting unprivileged uid mapping establishment to the creator of the -user namespace makes it easier to verify all credentials obtained with -the uid mapping can be obtained without the uid mapping without -privilege. - -Limiting unprivileged gid mapping establishment (which is temporarily -absent) to the creator of the user namespace also ensures that the -combination of uid and gid can already be obtained without privilege. - -This is part of the fix for CVE-2014-8989. - -Cc: stable@vger.kernel.org -Reviewed-by: Andy Lutomirski -Signed-off-by: "Eric W. Biederman" ---- - kernel/user_namespace.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 9451b12a9b6c..1e34de2fbd60 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -812,14 +812,16 @@ static bool new_idmap_permitted(const struct file *file, - struct user_namespace *ns, int cap_setid, - struct uid_gid_map *new_map) - { -+ const struct cred *cred = file->f_cred; - /* Don't allow mappings that would allow anything that wouldn't - * be allowed without the establishment of unprivileged mappings. - */ -- if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1)) { -+ if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1) && -+ uid_eq(ns->owner, cred->euid)) { - u32 id = new_map->extent[0].lower_first; - if (cap_setid == CAP_SETUID) { - kuid_t uid = make_kuid(ns->parent, id); -- if (uid_eq(uid, file->f_cred->euid)) -+ if (uid_eq(uid, cred->euid)) - return true; - } - } --- -2.1.0 - diff --git a/userns-Rename-id_map_mutex-to-userns_state_mutex.patch b/userns-Rename-id_map_mutex-to-userns_state_mutex.patch deleted file mode 100644 index ce6288ae6..000000000 --- a/userns-Rename-id_map_mutex-to-userns_state_mutex.patch +++ /dev/null @@ -1,80 +0,0 @@ -From: "Eric W. Biederman" -Date: Tue, 9 Dec 2014 14:03:14 -0600 -Subject: [PATCH] userns: Rename id_map_mutex to userns_state_mutex - -Generalize id_map_mutex so it can be used for more state of a user namespace. - -Cc: stable@vger.kernel.org -Reviewed-by: Andy Lutomirski -Signed-off-by: "Eric W. Biederman" ---- - kernel/user_namespace.c | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - -diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index 1e34de2fbd60..44a555ac6104 100644 ---- a/kernel/user_namespace.c -+++ b/kernel/user_namespace.c -@@ -24,6 +24,7 @@ - #include - - static struct kmem_cache *user_ns_cachep __read_mostly; -+static DEFINE_MUTEX(userns_state_mutex); - - static bool new_idmap_permitted(const struct file *file, - struct user_namespace *ns, int cap_setid, -@@ -583,9 +584,6 @@ static bool mappings_overlap(struct uid_gid_map *new_map, - return false; - } - -- --static DEFINE_MUTEX(id_map_mutex); -- - static ssize_t map_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos, - int cap_setid, -@@ -602,7 +600,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, - ssize_t ret = -EINVAL; - - /* -- * The id_map_mutex serializes all writes to any given map. -+ * The userns_state_mutex serializes all writes to any given map. - * - * Any map is only ever written once. - * -@@ -620,7 +618,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, - * order and smp_rmb() is guaranteed that we don't have crazy - * architectures returning stale data. - */ -- mutex_lock(&id_map_mutex); -+ mutex_lock(&userns_state_mutex); - - ret = -EPERM; - /* Only allow one successful write to the map */ -@@ -750,7 +748,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, - *ppos = count; - ret = count; - out: -- mutex_unlock(&id_map_mutex); -+ mutex_unlock(&userns_state_mutex); - if (page) - free_page(page); - return ret; -@@ -845,12 +843,12 @@ bool userns_may_setgroups(const struct user_namespace *ns) - { - bool allowed; - -- mutex_lock(&id_map_mutex); -+ mutex_lock(&userns_state_mutex); - /* It is not safe to use setgroups until a gid mapping in - * the user namespace has been established. - */ - allowed = ns->gid_map.nr_extents != 0; -- mutex_unlock(&id_map_mutex); -+ mutex_unlock(&userns_state_mutex); - - return allowed; - } --- -2.1.0 - diff --git a/userns-Unbreak-the-unprivileged-remount-tests.patch b/userns-Unbreak-the-unprivileged-remount-tests.patch deleted file mode 100644 index 69edd2ed3..000000000 --- a/userns-Unbreak-the-unprivileged-remount-tests.patch +++ /dev/null @@ -1,91 +0,0 @@ -From: "Eric W. Biederman" -Date: Tue, 2 Dec 2014 13:56:30 -0600 -Subject: [PATCH] userns: Unbreak the unprivileged remount tests - -A security fix in caused the way the unprivileged remount tests were -using user namespaces to break. Tweak the way user namespaces are -being used so the test works again. - -Cc: stable@vger.kernel.org -Signed-off-by: "Eric W. Biederman" ---- - .../selftests/mount/unprivileged-remount-test.c | 32 ++++++++++++++++------ - 1 file changed, 24 insertions(+), 8 deletions(-) - -diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c -index 9669d375625a..517785052f1c 100644 ---- a/tools/testing/selftests/mount/unprivileged-remount-test.c -+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c -@@ -53,17 +53,14 @@ static void die(char *fmt, ...) - exit(EXIT_FAILURE); - } - --static void write_file(char *filename, char *fmt, ...) -+static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap) - { - char buf[4096]; - int fd; - ssize_t written; - int buf_len; -- va_list ap; - -- va_start(ap, fmt); - buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); -- va_end(ap); - if (buf_len < 0) { - die("vsnprintf failed: %s\n", - strerror(errno)); -@@ -74,6 +71,8 @@ static void write_file(char *filename, char *fmt, ...) - - fd = open(filename, O_WRONLY); - if (fd < 0) { -+ if ((errno == ENOENT) && enoent_ok) -+ return; - die("open of %s failed: %s\n", - filename, strerror(errno)); - } -@@ -92,6 +91,26 @@ static void write_file(char *filename, char *fmt, ...) - } - } - -+static void maybe_write_file(char *filename, char *fmt, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, fmt); -+ vmaybe_write_file(true, filename, fmt, ap); -+ va_end(ap); -+ -+} -+ -+static void write_file(char *filename, char *fmt, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, fmt); -+ vmaybe_write_file(false, filename, fmt, ap); -+ va_end(ap); -+ -+} -+ - static int read_mnt_flags(const char *path) - { - int ret; -@@ -144,13 +163,10 @@ static void create_and_enter_userns(void) - strerror(errno)); - } - -+ maybe_write_file("/proc/self/setgroups", "deny"); - write_file("/proc/self/uid_map", "0 %d 1", uid); - write_file("/proc/self/gid_map", "0 %d 1", gid); - -- if (setgroups(0, NULL) != 0) { -- die("setgroups failed: %s\n", -- strerror(errno)); -- } - if (setgid(0) != 0) { - die ("setgid(0) failed %s\n", - strerror(errno)); --- -2.1.0 - diff --git a/x86-kvm-Clear-paravirt_enabled-on-KVM-guests-for-esp.patch b/x86-kvm-Clear-paravirt_enabled-on-KVM-guests-for-esp.patch deleted file mode 100644 index cae153cbb..000000000 --- a/x86-kvm-Clear-paravirt_enabled-on-KVM-guests-for-esp.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: Andy Lutomirski -Date: Fri, 5 Dec 2014 19:03:28 -0800 -Subject: [PATCH] x86, kvm: Clear paravirt_enabled on KVM guests for espfix32's - benefit - -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. - -While I'm at it, this removes pv_info setup from kvmclock. That -code seems to serve no purpose. - -Cc: stable@vger.kernel.org -Signed-off-by: Andy Lutomirski ---- - arch/x86/kernel/kvm.c | 9 ++++++++- - arch/x86/kernel/kvmclock.c | 2 -- - 2 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c -index 3dd8e2c4d74a..07de51f66deb 100644 ---- 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; -diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c -index d9156ceecdff..d4d9a8ad7893 100644 ---- a/arch/x86/kernel/kvmclock.c -+++ b/arch/x86/kernel/kvmclock.c -@@ -263,8 +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)) - pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); --- -2.1.0 - diff --git a/x86-tls-Validate-TLS-entries-to-protect-espfix.patch b/x86-tls-Validate-TLS-entries-to-protect-espfix.patch deleted file mode 100644 index 52c049767..000000000 --- a/x86-tls-Validate-TLS-entries-to-protect-espfix.patch +++ /dev/null @@ -1,77 +0,0 @@ -From: Andy Lutomirski -Date: Thu, 4 Dec 2014 16:48:16 -0800 -Subject: [PATCH] x86/tls: Validate TLS entries to protect espfix - -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 -Acked-by: H. Peter Anvin -Cc: stable@vger.kernel.org -Cc: Konrad Rzeszutek Wilk -Cc: Linus Torvalds -Cc: security@kernel.org -Cc: Willy Tarreau -Signed-off-by: Ingo Molnar ---- - 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 f7fec09e3e3a..e7650bd71109 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)); --- -2.1.0 - diff --git a/x86_64-switch_to-Load-TLS-descriptors-before-switchi.patch b/x86_64-switch_to-Load-TLS-descriptors-before-switchi.patch deleted file mode 100644 index 29e57b7f6..000000000 --- a/x86_64-switch_to-Load-TLS-descriptors-before-switchi.patch +++ /dev/null @@ -1,309 +0,0 @@ -From: Andy Lutomirski -Date: Mon, 8 Dec 2014 13:55:20 -0800 -Subject: [PATCH] x86_64, switch_to(): Load TLS descriptors before switching DS - and ES - -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 -Cc: -Cc: Andi Kleen -Cc: Linus Torvalds -Link: http://lkml.kernel.org/r/509d27c9fec78217691c3dad91cec87e1006b34a.1418075657.git.luto@amacapital.net -Signed-off-by: Ingo Molnar ---- - arch/x86/kernel/process_64.c | 101 +++++++++++++++++++++++++++++++------------ - 1 file changed, 73 insertions(+), 28 deletions(-) - -diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c -index ca5b02d405c3..166119618afb 100644 ---- 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, struct task_struct *next_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, struct task_struct *next_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; - } --- -2.1.0 -