diff options
author | Andrew Morton <akpm@linux-foundation.org> | 2008-02-05 01:29:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-05 12:44:20 -0500 |
commit | 8f6936f4d29aa14e54a2470b954a2e1f96322988 (patch) | |
tree | 63e1bca33b783cf819b356f3ffd45cfe7b226654 | |
parent | 4bea58053f206be9a89ca35850f9ad295dac2042 (diff) |
revert "capabilities: clean up file capability reading"
Revert b68680e4731abbd78863063aaa0dca2a6d8cc723 to make way for the next
patch: "Add 64-bit capability support to the kernel".
We want to keep the vfs_cap_data.data[] structure, using two 'data's for
64-bit caps (and later three for 96-bit caps), whereas
b68680e4731abbd78863063aaa0dca2a6d8cc723 had gotten rid of the 'data' struct
made its members inline.
The 64-bit caps patch keeps the stack abuse fix at get_file_caps(), which was
the more important part of that patch.
[akpm@linux-foundation.org: coding-style fixes]
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Serge Hallyn <serue@us.ibm.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: James Morris <jmorris@namei.org>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Cc: Andrew Morgan <morgan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/capability.h | 6 | ||||
-rw-r--r-- | security/commoncap.c | 23 |
2 files changed, 12 insertions, 17 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h index bb017edffd56..7a8d7ade28a0 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h | |||
@@ -56,8 +56,10 @@ typedef struct __user_cap_data_struct { | |||
56 | 56 | ||
57 | struct vfs_cap_data { | 57 | struct vfs_cap_data { |
58 | __u32 magic_etc; /* Little endian */ | 58 | __u32 magic_etc; /* Little endian */ |
59 | __u32 permitted; /* Little endian */ | 59 | struct { |
60 | __u32 inheritable; /* Little endian */ | 60 | __u32 permitted; /* Little endian */ |
61 | __u32 inheritable; /* Little endian */ | ||
62 | } data[1]; | ||
61 | }; | 63 | }; |
62 | 64 | ||
63 | #ifdef __KERNEL__ | 65 | #ifdef __KERNEL__ |
diff --git a/security/commoncap.c b/security/commoncap.c index ea61bc73f6d3..b06617b35b93 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -197,8 +197,7 @@ int cap_inode_killpriv(struct dentry *dentry) | |||
197 | return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); | 197 | return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); |
198 | } | 198 | } |
199 | 199 | ||
200 | static inline int cap_from_disk(struct vfs_cap_data *caps, | 200 | static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, |
201 | struct linux_binprm *bprm, | ||
202 | int size) | 201 | int size) |
203 | { | 202 | { |
204 | __u32 magic_etc; | 203 | __u32 magic_etc; |
@@ -206,7 +205,7 @@ static inline int cap_from_disk(struct vfs_cap_data *caps, | |||
206 | if (size != XATTR_CAPS_SZ) | 205 | if (size != XATTR_CAPS_SZ) |
207 | return -EINVAL; | 206 | return -EINVAL; |
208 | 207 | ||
209 | magic_etc = le32_to_cpu(caps->magic_etc); | 208 | magic_etc = le32_to_cpu(caps[0]); |
210 | 209 | ||
211 | switch ((magic_etc & VFS_CAP_REVISION_MASK)) { | 210 | switch ((magic_etc & VFS_CAP_REVISION_MASK)) { |
212 | case VFS_CAP_REVISION: | 211 | case VFS_CAP_REVISION: |
@@ -214,8 +213,8 @@ static inline int cap_from_disk(struct vfs_cap_data *caps, | |||
214 | bprm->cap_effective = true; | 213 | bprm->cap_effective = true; |
215 | else | 214 | else |
216 | bprm->cap_effective = false; | 215 | bprm->cap_effective = false; |
217 | bprm->cap_permitted = to_cap_t(le32_to_cpu(caps->permitted)); | 216 | bprm->cap_permitted = to_cap_t(le32_to_cpu(caps[1])); |
218 | bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps->inheritable)); | 217 | bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps[2])); |
219 | return 0; | 218 | return 0; |
220 | default: | 219 | default: |
221 | return -EINVAL; | 220 | return -EINVAL; |
@@ -227,7 +226,7 @@ static int get_file_caps(struct linux_binprm *bprm) | |||
227 | { | 226 | { |
228 | struct dentry *dentry; | 227 | struct dentry *dentry; |
229 | int rc = 0; | 228 | int rc = 0; |
230 | struct vfs_cap_data incaps; | 229 | __le32 v1caps[XATTR_CAPS_SZ]; |
231 | struct inode *inode; | 230 | struct inode *inode; |
232 | 231 | ||
233 | if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { | 232 | if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { |
@@ -240,14 +239,8 @@ static int get_file_caps(struct linux_binprm *bprm) | |||
240 | if (!inode->i_op || !inode->i_op->getxattr) | 239 | if (!inode->i_op || !inode->i_op->getxattr) |
241 | goto out; | 240 | goto out; |
242 | 241 | ||
243 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0); | 242 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps, |
244 | if (rc > 0) { | 243 | XATTR_CAPS_SZ); |
245 | if (rc == XATTR_CAPS_SZ) | ||
246 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, | ||
247 | &incaps, XATTR_CAPS_SZ); | ||
248 | else | ||
249 | rc = -EINVAL; | ||
250 | } | ||
251 | if (rc == -ENODATA || rc == -EOPNOTSUPP) { | 244 | if (rc == -ENODATA || rc == -EOPNOTSUPP) { |
252 | /* no data, that's ok */ | 245 | /* no data, that's ok */ |
253 | rc = 0; | 246 | rc = 0; |
@@ -256,7 +249,7 @@ static int get_file_caps(struct linux_binprm *bprm) | |||
256 | if (rc < 0) | 249 | if (rc < 0) |
257 | goto out; | 250 | goto out; |
258 | 251 | ||
259 | rc = cap_from_disk(&incaps, bprm, rc); | 252 | rc = cap_from_disk(v1caps, bprm, rc); |
260 | if (rc) | 253 | if (rc) |
261 | printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", | 254 | printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", |
262 | __FUNCTION__, rc, bprm->filename); | 255 | __FUNCTION__, rc, bprm->filename); |