aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/capability.h6
-rw-r--r--security/commoncap.c23
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
57struct vfs_cap_data { 57struct 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
200static inline int cap_from_disk(struct vfs_cap_data *caps, 200static 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);