diff options
| -rw-r--r-- | fs/xattr.c | 14 | ||||
| -rw-r--r-- | include/linux/security.h | 11 | ||||
| -rw-r--r-- | security/dummy.c | 2 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 46 |
4 files changed, 49 insertions, 24 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index 3f9c64bea151..f6e00c0e114f 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
| @@ -143,7 +143,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) | |||
| 143 | if (size) { | 143 | if (size) { |
| 144 | if (size > XATTR_SIZE_MAX) | 144 | if (size > XATTR_SIZE_MAX) |
| 145 | size = XATTR_SIZE_MAX; | 145 | size = XATTR_SIZE_MAX; |
| 146 | kvalue = kmalloc(size, GFP_KERNEL); | 146 | kvalue = kzalloc(size, GFP_KERNEL); |
| 147 | if (!kvalue) | 147 | if (!kvalue) |
| 148 | return -ENOMEM; | 148 | return -ENOMEM; |
| 149 | } | 149 | } |
| @@ -154,11 +154,15 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) | |||
| 154 | error = -EOPNOTSUPP; | 154 | error = -EOPNOTSUPP; |
| 155 | if (d->d_inode->i_op && d->d_inode->i_op->getxattr) | 155 | if (d->d_inode->i_op && d->d_inode->i_op->getxattr) |
| 156 | error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); | 156 | error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); |
| 157 | else if (!strncmp(kname, XATTR_SECURITY_PREFIX, | 157 | |
| 158 | sizeof XATTR_SECURITY_PREFIX - 1)) { | 158 | if (!strncmp(kname, XATTR_SECURITY_PREFIX, |
| 159 | sizeof XATTR_SECURITY_PREFIX - 1)) { | ||
| 159 | const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; | 160 | const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; |
| 160 | error = security_inode_getsecurity(d->d_inode, suffix, kvalue, | 161 | int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue, |
| 161 | size); | 162 | size, error); |
| 163 | /* Security module active: overwrite error value */ | ||
| 164 | if (rv != -EOPNOTSUPP) | ||
| 165 | error = rv; | ||
| 162 | } | 166 | } |
| 163 | if (error > 0) { | 167 | if (error > 0) { |
| 164 | if (size && copy_to_user(value, kvalue, error)) | 168 | if (size && copy_to_user(value, kvalue, error)) |
diff --git a/include/linux/security.h b/include/linux/security.h index dac956ed98f0..607ee209ea3b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -385,6 +385,9 @@ struct swap_info_struct; | |||
| 385 | * NULL to request the size of the buffer required. @size indicates | 385 | * NULL to request the size of the buffer required. @size indicates |
| 386 | * the size of @buffer in bytes. Note that @name is the remainder | 386 | * the size of @buffer in bytes. Note that @name is the remainder |
| 387 | * of the attribute name after the security. prefix has been removed. | 387 | * of the attribute name after the security. prefix has been removed. |
| 388 | * @err is the return value from the preceding fs getxattr call, | ||
| 389 | * and can be used by the security module to determine whether it | ||
| 390 | * should try and canonicalize the attribute value. | ||
| 388 | * Return number of bytes used/required on success. | 391 | * Return number of bytes used/required on success. |
| 389 | * @inode_setsecurity: | 392 | * @inode_setsecurity: |
| 390 | * Set the security label associated with @name for @inode from the | 393 | * Set the security label associated with @name for @inode from the |
| @@ -1091,7 +1094,7 @@ struct security_operations { | |||
| 1091 | int (*inode_getxattr) (struct dentry *dentry, char *name); | 1094 | int (*inode_getxattr) (struct dentry *dentry, char *name); |
| 1092 | int (*inode_listxattr) (struct dentry *dentry); | 1095 | int (*inode_listxattr) (struct dentry *dentry); |
| 1093 | int (*inode_removexattr) (struct dentry *dentry, char *name); | 1096 | int (*inode_removexattr) (struct dentry *dentry, char *name); |
| 1094 | int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size); | 1097 | int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size, int err); |
| 1095 | int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); | 1098 | int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); |
| 1096 | int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size); | 1099 | int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size); |
| 1097 | 1100 | ||
| @@ -1580,11 +1583,11 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name) | |||
| 1580 | return security_ops->inode_removexattr (dentry, name); | 1583 | return security_ops->inode_removexattr (dentry, name); |
| 1581 | } | 1584 | } |
| 1582 | 1585 | ||
| 1583 | static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) | 1586 | static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) |
| 1584 | { | 1587 | { |
| 1585 | if (unlikely (IS_PRIVATE (inode))) | 1588 | if (unlikely (IS_PRIVATE (inode))) |
| 1586 | return 0; | 1589 | return 0; |
| 1587 | return security_ops->inode_getsecurity(inode, name, buffer, size); | 1590 | return security_ops->inode_getsecurity(inode, name, buffer, size, err); |
| 1588 | } | 1591 | } |
| 1589 | 1592 | ||
| 1590 | static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) | 1593 | static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) |
| @@ -2222,7 +2225,7 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name) | |||
| 2222 | return cap_inode_removexattr(dentry, name); | 2225 | return cap_inode_removexattr(dentry, name); |
| 2223 | } | 2226 | } |
| 2224 | 2227 | ||
| 2225 | static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) | 2228 | static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) |
| 2226 | { | 2229 | { |
| 2227 | return -EOPNOTSUPP; | 2230 | return -EOPNOTSUPP; |
| 2228 | } | 2231 | } |
diff --git a/security/dummy.c b/security/dummy.c index 3d34f3de7e82..2a0337a52d32 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
| @@ -377,7 +377,7 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name) | |||
| 377 | return 0; | 377 | return 0; |
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) | 380 | static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) |
| 381 | { | 381 | { |
| 382 | return -EOPNOTSUPP; | 382 | return -EOPNOTSUPP; |
| 383 | } | 383 | } |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8cd33b2cd865..d9ec85292e1c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -2208,9 +2208,6 @@ static int selinux_inode_getxattr (struct dentry *dentry, char *name) | |||
| 2208 | struct inode *inode = dentry->d_inode; | 2208 | struct inode *inode = dentry->d_inode; |
| 2209 | struct superblock_security_struct *sbsec = inode->i_sb->s_security; | 2209 | struct superblock_security_struct *sbsec = inode->i_sb->s_security; |
| 2210 | 2210 | ||
| 2211 | if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) | ||
| 2212 | return -EOPNOTSUPP; | ||
| 2213 | |||
| 2214 | return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); | 2211 | return dentry_has_perm(current, NULL, dentry, FILE__GETATTR); |
| 2215 | } | 2212 | } |
| 2216 | 2213 | ||
| @@ -2241,33 +2238,54 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name) | |||
| 2241 | return -EACCES; | 2238 | return -EACCES; |
| 2242 | } | 2239 | } |
| 2243 | 2240 | ||
| 2244 | static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size) | 2241 | /* |
| 2242 | * Copy the in-core inode security context value to the user. If the | ||
| 2243 | * getxattr() prior to this succeeded, check to see if we need to | ||
| 2244 | * canonicalize the value to be finally returned to the user. | ||
| 2245 | * | ||
| 2246 | * Permission check is handled by selinux_inode_getxattr hook. | ||
| 2247 | */ | ||
| 2248 | static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) | ||
| 2245 | { | 2249 | { |
| 2246 | struct inode_security_struct *isec = inode->i_security; | 2250 | struct inode_security_struct *isec = inode->i_security; |
| 2247 | char *context; | 2251 | char *context; |
| 2248 | unsigned len; | 2252 | unsigned len; |
| 2249 | int rc; | 2253 | int rc; |
| 2250 | 2254 | ||
| 2251 | /* Permission check handled by selinux_inode_getxattr hook.*/ | 2255 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) { |
| 2252 | 2256 | rc = -EOPNOTSUPP; | |
| 2253 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) | 2257 | goto out; |
| 2254 | return -EOPNOTSUPP; | 2258 | } |
| 2255 | 2259 | ||
| 2256 | rc = security_sid_to_context(isec->sid, &context, &len); | 2260 | rc = security_sid_to_context(isec->sid, &context, &len); |
| 2257 | if (rc) | 2261 | if (rc) |
| 2258 | return rc; | 2262 | goto out; |
| 2259 | 2263 | ||
| 2264 | /* Probe for required buffer size */ | ||
| 2260 | if (!buffer || !size) { | 2265 | if (!buffer || !size) { |
| 2261 | kfree(context); | 2266 | rc = len; |
| 2262 | return len; | 2267 | goto out_free; |
| 2263 | } | 2268 | } |
| 2269 | |||
| 2264 | if (size < len) { | 2270 | if (size < len) { |
| 2265 | kfree(context); | 2271 | rc = -ERANGE; |
| 2266 | return -ERANGE; | 2272 | goto out_free; |
| 2273 | } | ||
| 2274 | |||
| 2275 | if (err > 0) { | ||
| 2276 | if ((len == err) && !(memcmp(context, buffer, len))) { | ||
| 2277 | /* Don't need to canonicalize value */ | ||
| 2278 | rc = err; | ||
| 2279 | goto out_free; | ||
| 2280 | } | ||
| 2281 | memset(buffer, 0, size); | ||
| 2267 | } | 2282 | } |
| 2268 | memcpy(buffer, context, len); | 2283 | memcpy(buffer, context, len); |
| 2284 | rc = len; | ||
| 2285 | out_free: | ||
| 2269 | kfree(context); | 2286 | kfree(context); |
| 2270 | return len; | 2287 | out: |
| 2288 | return rc; | ||
| 2271 | } | 2289 | } |
| 2272 | 2290 | ||
| 2273 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, | 2291 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, |
