diff options
| -rw-r--r-- | meta-fsl-ppc/recipes-kernel/linux/files/fs-CVE-2014-4014.patch | 210 | ||||
| -rw-r--r-- | meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb | 1 |
2 files changed, 211 insertions, 0 deletions
diff --git a/meta-fsl-ppc/recipes-kernel/linux/files/fs-CVE-2014-4014.patch b/meta-fsl-ppc/recipes-kernel/linux/files/fs-CVE-2014-4014.patch new file mode 100644 index 000000000..a61ae4cb5 --- /dev/null +++ b/meta-fsl-ppc/recipes-kernel/linux/files/fs-CVE-2014-4014.patch | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | From 2246a472bce19c0d373fb5488a0e612e3328ce0a Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Andy Lutomirski <luto@amacapital.net> | ||
| 3 | Date: Tue, 10 Jun 2014 12:45:42 -0700 | ||
| 4 | Subject: [PATCH] fs,userns: Change inode_capable to capable_wrt_inode_uidgid | ||
| 5 | |||
| 6 | commit 23adbe12ef7d3d4195e80800ab36b37bee28cd03 upstream. | ||
| 7 | |||
| 8 | The kernel has no concept of capabilities with respect to inodes; inodes | ||
| 9 | exist independently of namespaces. For example, inode_capable(inode, | ||
| 10 | CAP_LINUX_IMMUTABLE) would be nonsense. | ||
| 11 | |||
| 12 | This patch changes inode_capable to check for uid and gid mappings and | ||
| 13 | renames it to capable_wrt_inode_uidgid, which should make it more | ||
| 14 | obvious what it does. | ||
| 15 | |||
| 16 | Fixes CVE-2014-4014. | ||
| 17 | Upstream-Status: Backport | ||
| 18 | |||
| 19 | Cc: Theodore Ts'o <tytso@mit.edu> | ||
| 20 | Cc: Serge Hallyn <serge.hallyn@ubuntu.com> | ||
| 21 | Cc: "Eric W. Biederman" <ebiederm@xmission.com> | ||
| 22 | Cc: Dave Chinner <david@fromorbit.com> | ||
| 23 | Signed-off-by: Andy Lutomirski <luto@amacapital.net> | ||
| 24 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | ||
| 25 | Signed-off-by: Jiri Slaby <jslaby@suse.cz> | ||
| 26 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
| 27 | --- | ||
| 28 | fs/attr.c | 8 ++++---- | ||
| 29 | fs/inode.c | 10 +++++++--- | ||
| 30 | fs/namei.c | 11 ++++++----- | ||
| 31 | fs/xfs/xfs_ioctl.c | 2 +- | ||
| 32 | include/linux/capability.h | 2 +- | ||
| 33 | kernel/capability.c | 20 ++++++++------------ | ||
| 34 | 6 files changed, 27 insertions(+), 26 deletions(-) | ||
| 35 | |||
| 36 | diff --git a/fs/attr.c b/fs/attr.c | ||
| 37 | index 8dd5825..66fa625 100644 | ||
| 38 | --- a/fs/attr.c | ||
| 39 | +++ b/fs/attr.c | ||
| 40 | @@ -50,14 +50,14 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) | ||
| 41 | if ((ia_valid & ATTR_UID) && | ||
| 42 | (!uid_eq(current_fsuid(), inode->i_uid) || | ||
| 43 | !uid_eq(attr->ia_uid, inode->i_uid)) && | ||
| 44 | - !inode_capable(inode, CAP_CHOWN)) | ||
| 45 | + !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) | ||
| 46 | return -EPERM; | ||
| 47 | |||
| 48 | /* Make sure caller can chgrp. */ | ||
| 49 | if ((ia_valid & ATTR_GID) && | ||
| 50 | (!uid_eq(current_fsuid(), inode->i_uid) || | ||
| 51 | (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && | ||
| 52 | - !inode_capable(inode, CAP_CHOWN)) | ||
| 53 | + !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) | ||
| 54 | return -EPERM; | ||
| 55 | |||
| 56 | /* Make sure a caller can chmod. */ | ||
| 57 | @@ -67,7 +67,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) | ||
| 58 | /* Also check the setgid bit! */ | ||
| 59 | if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : | ||
| 60 | inode->i_gid) && | ||
| 61 | - !inode_capable(inode, CAP_FSETID)) | ||
| 62 | + !capable_wrt_inode_uidgid(inode, CAP_FSETID)) | ||
| 63 | attr->ia_mode &= ~S_ISGID; | ||
| 64 | } | ||
| 65 | |||
| 66 | @@ -160,7 +160,7 @@ void setattr_copy(struct inode *inode, const struct iattr *attr) | ||
| 67 | umode_t mode = attr->ia_mode; | ||
| 68 | |||
| 69 | if (!in_group_p(inode->i_gid) && | ||
| 70 | - !inode_capable(inode, CAP_FSETID)) | ||
| 71 | + !capable_wrt_inode_uidgid(inode, CAP_FSETID)) | ||
| 72 | mode &= ~S_ISGID; | ||
| 73 | inode->i_mode = mode; | ||
| 74 | } | ||
| 75 | diff --git a/fs/inode.c b/fs/inode.c | ||
| 76 | index b33ba8e..1e6e846 100644 | ||
| 77 | --- a/fs/inode.c | ||
| 78 | +++ b/fs/inode.c | ||
| 79 | @@ -1808,14 +1808,18 @@ EXPORT_SYMBOL(inode_init_owner); | ||
| 80 | * inode_owner_or_capable - check current task permissions to inode | ||
| 81 | * @inode: inode being checked | ||
| 82 | * | ||
| 83 | - * Return true if current either has CAP_FOWNER to the inode, or | ||
| 84 | - * owns the file. | ||
| 85 | + * Return true if current either has CAP_FOWNER in a namespace with the | ||
| 86 | + * inode owner uid mapped, or owns the file. | ||
| 87 | */ | ||
| 88 | bool inode_owner_or_capable(const struct inode *inode) | ||
| 89 | { | ||
| 90 | + struct user_namespace *ns; | ||
| 91 | + | ||
| 92 | if (uid_eq(current_fsuid(), inode->i_uid)) | ||
| 93 | return true; | ||
| 94 | - if (inode_capable(inode, CAP_FOWNER)) | ||
| 95 | + | ||
| 96 | + ns = current_user_ns(); | ||
| 97 | + if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, inode->i_uid)) | ||
| 98 | return true; | ||
| 99 | return false; | ||
| 100 | } | ||
| 101 | diff --git a/fs/namei.c b/fs/namei.c | ||
| 102 | index 187cacf..338d08b 100644 | ||
| 103 | --- a/fs/namei.c | ||
| 104 | +++ b/fs/namei.c | ||
| 105 | @@ -321,10 +321,11 @@ int generic_permission(struct inode *inode, int mask) | ||
| 106 | |||
| 107 | if (S_ISDIR(inode->i_mode)) { | ||
| 108 | /* DACs are overridable for directories */ | ||
| 109 | - if (inode_capable(inode, CAP_DAC_OVERRIDE)) | ||
| 110 | + if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) | ||
| 111 | return 0; | ||
| 112 | if (!(mask & MAY_WRITE)) | ||
| 113 | - if (inode_capable(inode, CAP_DAC_READ_SEARCH)) | ||
| 114 | + if (capable_wrt_inode_uidgid(inode, | ||
| 115 | + CAP_DAC_READ_SEARCH)) | ||
| 116 | return 0; | ||
| 117 | return -EACCES; | ||
| 118 | } | ||
| 119 | @@ -334,7 +335,7 @@ int generic_permission(struct inode *inode, int mask) | ||
| 120 | * at least one exec bit set. | ||
| 121 | */ | ||
| 122 | if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) | ||
| 123 | - if (inode_capable(inode, CAP_DAC_OVERRIDE)) | ||
| 124 | + if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) | ||
| 125 | return 0; | ||
| 126 | |||
| 127 | /* | ||
| 128 | @@ -342,7 +343,7 @@ int generic_permission(struct inode *inode, int mask) | ||
| 129 | */ | ||
| 130 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | ||
| 131 | if (mask == MAY_READ) | ||
| 132 | - if (inode_capable(inode, CAP_DAC_READ_SEARCH)) | ||
| 133 | + if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH)) | ||
| 134 | return 0; | ||
| 135 | |||
| 136 | return -EACCES; | ||
| 137 | @@ -2404,7 +2405,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) | ||
| 138 | return 0; | ||
| 139 | if (uid_eq(dir->i_uid, fsuid)) | ||
| 140 | return 0; | ||
| 141 | - return !inode_capable(inode, CAP_FOWNER); | ||
| 142 | + return !capable_wrt_inode_uidgid(inode, CAP_FOWNER); | ||
| 143 | } | ||
| 144 | |||
| 145 | /* | ||
| 146 | diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c | ||
| 147 | index 8c8ef24..52b5375 100644 | ||
| 148 | --- a/fs/xfs/xfs_ioctl.c | ||
| 149 | +++ b/fs/xfs/xfs_ioctl.c | ||
| 150 | @@ -1133,7 +1133,7 @@ xfs_ioctl_setattr( | ||
| 151 | * cleared upon successful return from chown() | ||
| 152 | */ | ||
| 153 | if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) && | ||
| 154 | - !inode_capable(VFS_I(ip), CAP_FSETID)) | ||
| 155 | + !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID)) | ||
| 156 | ip->i_d.di_mode &= ~(S_ISUID|S_ISGID); | ||
| 157 | |||
| 158 | /* | ||
| 159 | diff --git a/include/linux/capability.h b/include/linux/capability.h | ||
| 160 | index a6ee1f9..84b13ad 100644 | ||
| 161 | --- a/include/linux/capability.h | ||
| 162 | +++ b/include/linux/capability.h | ||
| 163 | @@ -210,7 +210,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t, | ||
| 164 | struct user_namespace *ns, int cap); | ||
| 165 | extern bool capable(int cap); | ||
| 166 | extern bool ns_capable(struct user_namespace *ns, int cap); | ||
| 167 | -extern bool inode_capable(const struct inode *inode, int cap); | ||
| 168 | +extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap); | ||
| 169 | extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); | ||
| 170 | |||
| 171 | /* audit system wants to get cap info from files as well */ | ||
| 172 | diff --git a/kernel/capability.c b/kernel/capability.c | ||
| 173 | index 4e66bf9..788653b 100644 | ||
| 174 | --- a/kernel/capability.c | ||
| 175 | +++ b/kernel/capability.c | ||
| 176 | @@ -433,23 +433,19 @@ bool capable(int cap) | ||
| 177 | EXPORT_SYMBOL(capable); | ||
| 178 | |||
| 179 | /** | ||
| 180 | - * inode_capable - Check superior capability over inode | ||
| 181 | + * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped | ||
| 182 | * @inode: The inode in question | ||
| 183 | * @cap: The capability in question | ||
| 184 | * | ||
| 185 | - * Return true if the current task has the given superior capability | ||
| 186 | - * targeted at it's own user namespace and that the given inode is owned | ||
| 187 | - * by the current user namespace or a child namespace. | ||
| 188 | - * | ||
| 189 | - * Currently we check to see if an inode is owned by the current | ||
| 190 | - * user namespace by seeing if the inode's owner maps into the | ||
| 191 | - * current user namespace. | ||
| 192 | - * | ||
| 193 | + * Return true if the current task has the given capability targeted at | ||
| 194 | + * its own user namespace and that the given inode's uid and gid are | ||
| 195 | + * mapped into the current user namespace. | ||
| 196 | */ | ||
| 197 | -bool inode_capable(const struct inode *inode, int cap) | ||
| 198 | +bool capable_wrt_inode_uidgid(const struct inode *inode, int cap) | ||
| 199 | { | ||
| 200 | struct user_namespace *ns = current_user_ns(); | ||
| 201 | |||
| 202 | - return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid); | ||
| 203 | + return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) && | ||
| 204 | + kgid_has_mapping(ns, inode->i_gid); | ||
| 205 | } | ||
| 206 | -EXPORT_SYMBOL(inode_capable); | ||
| 207 | +EXPORT_SYMBOL(capable_wrt_inode_uidgid); | ||
| 208 | -- | ||
| 209 | 1.9.1 | ||
| 210 | |||
diff --git a/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb b/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb index 9727a7341..527daf451 100644 --- a/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb +++ b/meta-fsl-ppc/recipes-kernel/linux/linux-qoriq_3.12.bb | |||
| @@ -34,6 +34,7 @@ SRC_URI = "git://git.freescale.com/ppc/sdk/linux.git;nobranch=1 \ | |||
| 34 | file://0001-shmem-CVE-2014-4171.patch \ | 34 | file://0001-shmem-CVE-2014-4171.patch \ |
| 35 | file://0002-shmem-CVE-2014-4171.patch \ | 35 | file://0002-shmem-CVE-2014-4171.patch \ |
| 36 | file://0003-shmem-CVE-2014-4171.patch \ | 36 | file://0003-shmem-CVE-2014-4171.patch \ |
| 37 | file://fs-CVE-2014-4014.patch \ | ||
| 37 | " | 38 | " |
| 38 | SRCREV = "6619b8b55796cdf0cec04b66a71288edd3057229" | 39 | SRCREV = "6619b8b55796cdf0cec04b66a71288edd3057229" |
| 39 | 40 | ||
