aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/capability.h6
-rw-r--r--security/commoncap.c23
2 files changed, 17 insertions, 12 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 7a8d7ade28a0..bb017edffd56 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -56,10 +56,8 @@ 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 struct { 59 __u32 permitted; /* Little endian */
60 __u32 permitted; /* Little endian */ 60 __u32 inheritable; /* Little endian */
61 __u32 inheritable; /* Little endian */
62 } data[1];
63}; 61};
64 62
65#ifdef __KERNEL__ 63#ifdef __KERNEL__
diff --git a/security/commoncap.c b/security/commoncap.c
index 43f902750a1b..bf67871173ef 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -190,7 +190,8 @@ int cap_inode_killpriv(struct dentry *dentry)
190 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); 190 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
191} 191}
192 192
193static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, 193static inline int cap_from_disk(struct vfs_cap_data *caps,
194 struct linux_binprm *bprm,
194 int size) 195 int size)
195{ 196{
196 __u32 magic_etc; 197 __u32 magic_etc;
@@ -198,7 +199,7 @@ static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm,
198 if (size != XATTR_CAPS_SZ) 199 if (size != XATTR_CAPS_SZ)
199 return -EINVAL; 200 return -EINVAL;
200 201
201 magic_etc = le32_to_cpu(caps[0]); 202 magic_etc = le32_to_cpu(caps->magic_etc);
202 203
203 switch ((magic_etc & VFS_CAP_REVISION_MASK)) { 204 switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
204 case VFS_CAP_REVISION: 205 case VFS_CAP_REVISION:
@@ -206,8 +207,8 @@ static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm,
206 bprm->cap_effective = true; 207 bprm->cap_effective = true;
207 else 208 else
208 bprm->cap_effective = false; 209 bprm->cap_effective = false;
209 bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) ); 210 bprm->cap_permitted = to_cap_t(le32_to_cpu(caps->permitted));
210 bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) ); 211 bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps->inheritable));
211 return 0; 212 return 0;
212 default: 213 default:
213 return -EINVAL; 214 return -EINVAL;
@@ -219,7 +220,7 @@ static int get_file_caps(struct linux_binprm *bprm)
219{ 220{
220 struct dentry *dentry; 221 struct dentry *dentry;
221 int rc = 0; 222 int rc = 0;
222 __le32 v1caps[XATTR_CAPS_SZ]; 223 struct vfs_cap_data incaps;
223 struct inode *inode; 224 struct inode *inode;
224 225
225 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { 226 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
@@ -232,8 +233,14 @@ static int get_file_caps(struct linux_binprm *bprm)
232 if (!inode->i_op || !inode->i_op->getxattr) 233 if (!inode->i_op || !inode->i_op->getxattr)
233 goto out; 234 goto out;
234 235
235 rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps, 236 rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0);
236 XATTR_CAPS_SZ); 237 if (rc > 0) {
238 if (rc == XATTR_CAPS_SZ)
239 rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS,
240 &incaps, XATTR_CAPS_SZ);
241 else
242 rc = -EINVAL;
243 }
237 if (rc == -ENODATA || rc == -EOPNOTSUPP) { 244 if (rc == -ENODATA || rc == -EOPNOTSUPP) {
238 /* no data, that's ok */ 245 /* no data, that's ok */
239 rc = 0; 246 rc = 0;
@@ -242,7 +249,7 @@ static int get_file_caps(struct linux_binprm *bprm)
242 if (rc < 0) 249 if (rc < 0)
243 goto out; 250 goto out;
244 251
245 rc = cap_from_disk(v1caps, bprm, rc); 252 rc = cap_from_disk(&incaps, bprm, rc);
246 if (rc) 253 if (rc)
247 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",
248 __FUNCTION__, rc, bprm->filename); 255 __FUNCTION__, rc, bprm->filename);