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 00000000..a61ae4cb --- /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 9727a734..527daf45 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 | ||