diff options
-rw-r--r-- | fs/xattr.c | 30 | ||||
-rw-r--r-- | include/linux/security.h | 21 | ||||
-rw-r--r-- | include/linux/xattr.h | 1 | ||||
-rw-r--r-- | mm/shmem.c | 3 | ||||
-rw-r--r-- | security/dummy.c | 2 | ||||
-rw-r--r-- | security/security.c | 4 | ||||
-rw-r--r-- | security/selinux/hooks.c | 43 |
7 files changed, 57 insertions, 47 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index 6645b7313b33..1858552a6a1a 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -105,6 +105,33 @@ out: | |||
105 | EXPORT_SYMBOL_GPL(vfs_setxattr); | 105 | EXPORT_SYMBOL_GPL(vfs_setxattr); |
106 | 106 | ||
107 | ssize_t | 107 | ssize_t |
108 | xattr_getsecurity(struct inode *inode, const char *name, void *value, | ||
109 | size_t size) | ||
110 | { | ||
111 | void *buffer = NULL; | ||
112 | ssize_t len; | ||
113 | |||
114 | if (!value || !size) { | ||
115 | len = security_inode_getsecurity(inode, name, &buffer, false); | ||
116 | goto out_noalloc; | ||
117 | } | ||
118 | |||
119 | len = security_inode_getsecurity(inode, name, &buffer, true); | ||
120 | if (len < 0) | ||
121 | return len; | ||
122 | if (size < len) { | ||
123 | len = -ERANGE; | ||
124 | goto out; | ||
125 | } | ||
126 | memcpy(value, buffer, len); | ||
127 | out: | ||
128 | security_release_secctx(buffer, len); | ||
129 | out_noalloc: | ||
130 | return len; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(xattr_getsecurity); | ||
133 | |||
134 | ssize_t | ||
108 | vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size) | 135 | vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size) |
109 | { | 136 | { |
110 | struct inode *inode = dentry->d_inode; | 137 | struct inode *inode = dentry->d_inode; |
@@ -126,8 +153,7 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size) | |||
126 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 153 | if (!strncmp(name, XATTR_SECURITY_PREFIX, |
127 | XATTR_SECURITY_PREFIX_LEN)) { | 154 | XATTR_SECURITY_PREFIX_LEN)) { |
128 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; | 155 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; |
129 | int ret = security_inode_getsecurity(inode, suffix, value, | 156 | int ret = xattr_getsecurity(inode, suffix, value, size); |
130 | size, error); | ||
131 | /* | 157 | /* |
132 | * Only overwrite the return value if a security module | 158 | * Only overwrite the return value if a security module |
133 | * is actually active. | 159 | * is actually active. |
diff --git a/include/linux/security.h b/include/linux/security.h index d24974262dc6..9d289e726fd8 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -423,15 +423,12 @@ struct request_sock; | |||
423 | * identified by @name for @dentry. | 423 | * identified by @name for @dentry. |
424 | * Return 0 if permission is granted. | 424 | * Return 0 if permission is granted. |
425 | * @inode_getsecurity: | 425 | * @inode_getsecurity: |
426 | * Copy the extended attribute representation of the security label | 426 | * Retrieve a copy of the extended attribute representation of the |
427 | * associated with @name for @inode into @buffer. @buffer may be | 427 | * security label associated with @name for @inode via @buffer. Note that |
428 | * NULL to request the size of the buffer required. @size indicates | 428 | * @name is the remainder of the attribute name after the security prefix |
429 | * the size of @buffer in bytes. Note that @name is the remainder | 429 | * has been removed. @alloc is used to specify of the call should return a |
430 | * of the attribute name after the security. prefix has been removed. | 430 | * value via the buffer or just the value length Return size of buffer on |
431 | * @err is the return value from the preceding fs getxattr call, | 431 | * success. |
432 | * and can be used by the security module to determine whether it | ||
433 | * should try and canonicalize the attribute value. | ||
434 | * Return number of bytes used/required on success. | ||
435 | * @inode_setsecurity: | 432 | * @inode_setsecurity: |
436 | * Set the security label associated with @name for @inode from the | 433 | * Set the security label associated with @name for @inode from the |
437 | * extended attribute value @value. @size indicates the size of the | 434 | * extended attribute value @value. @size indicates the size of the |
@@ -1304,7 +1301,7 @@ struct security_operations { | |||
1304 | int (*inode_removexattr) (struct dentry *dentry, char *name); | 1301 | int (*inode_removexattr) (struct dentry *dentry, char *name); |
1305 | int (*inode_need_killpriv) (struct dentry *dentry); | 1302 | int (*inode_need_killpriv) (struct dentry *dentry); |
1306 | int (*inode_killpriv) (struct dentry *dentry); | 1303 | int (*inode_killpriv) (struct dentry *dentry); |
1307 | int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err); | 1304 | int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc); |
1308 | int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); | 1305 | int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); |
1309 | int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size); | 1306 | int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size); |
1310 | 1307 | ||
@@ -1565,7 +1562,7 @@ int security_inode_listxattr(struct dentry *dentry); | |||
1565 | int security_inode_removexattr(struct dentry *dentry, char *name); | 1562 | int security_inode_removexattr(struct dentry *dentry, char *name); |
1566 | int security_inode_need_killpriv(struct dentry *dentry); | 1563 | int security_inode_need_killpriv(struct dentry *dentry); |
1567 | int security_inode_killpriv(struct dentry *dentry); | 1564 | int security_inode_killpriv(struct dentry *dentry); |
1568 | int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err); | 1565 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc); |
1569 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); | 1566 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); |
1570 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); | 1567 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); |
1571 | int security_file_permission(struct file *file, int mask); | 1568 | int security_file_permission(struct file *file, int mask); |
@@ -1967,7 +1964,7 @@ static inline int security_inode_killpriv(struct dentry *dentry) | |||
1967 | return cap_inode_killpriv(dentry); | 1964 | return cap_inode_killpriv(dentry); |
1968 | } | 1965 | } |
1969 | 1966 | ||
1970 | static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) | 1967 | static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
1971 | { | 1968 | { |
1972 | return -EOPNOTSUPP; | 1969 | return -EOPNOTSUPP; |
1973 | } | 1970 | } |
diff --git a/include/linux/xattr.h b/include/linux/xattr.h index def131a5ac70..df6b95d2218e 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h | |||
@@ -46,6 +46,7 @@ struct xattr_handler { | |||
46 | size_t size, int flags); | 46 | size_t size, int flags); |
47 | }; | 47 | }; |
48 | 48 | ||
49 | ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t); | ||
49 | ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t); | 50 | ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t); |
50 | ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); | 51 | ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); |
51 | int vfs_setxattr(struct dentry *, char *, void *, size_t, int); | 52 | int vfs_setxattr(struct dentry *, char *, void *, size_t, int); |
diff --git a/mm/shmem.c b/mm/shmem.c index ee9024483f60..0f246c44a574 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1955,8 +1955,7 @@ static int shmem_xattr_security_get(struct inode *inode, const char *name, | |||
1955 | { | 1955 | { |
1956 | if (strcmp(name, "") == 0) | 1956 | if (strcmp(name, "") == 0) |
1957 | return -EINVAL; | 1957 | return -EINVAL; |
1958 | return security_inode_getsecurity(inode, name, buffer, size, | 1958 | return xattr_getsecurity(inode, name, buffer, size); |
1959 | -EOPNOTSUPP); | ||
1960 | } | 1959 | } |
1961 | 1960 | ||
1962 | static int shmem_xattr_security_set(struct inode *inode, const char *name, | 1961 | static int shmem_xattr_security_set(struct inode *inode, const char *name, |
diff --git a/security/dummy.c b/security/dummy.c index 48d4b0a52737..c505122e22db 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -402,7 +402,7 @@ static int dummy_inode_killpriv(struct dentry *dentry) | |||
402 | return 0; | 402 | return 0; |
403 | } | 403 | } |
404 | 404 | ||
405 | static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) | 405 | static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
406 | { | 406 | { |
407 | return -EOPNOTSUPP; | 407 | return -EOPNOTSUPP; |
408 | } | 408 | } |
diff --git a/security/security.c b/security/security.c index ca475ca206e4..b6c57a6b2ff5 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -493,11 +493,11 @@ int security_inode_killpriv(struct dentry *dentry) | |||
493 | return security_ops->inode_killpriv(dentry); | 493 | return security_ops->inode_killpriv(dentry); |
494 | } | 494 | } |
495 | 495 | ||
496 | int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) | 496 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
497 | { | 497 | { |
498 | if (unlikely(IS_PRIVATE(inode))) | 498 | if (unlikely(IS_PRIVATE(inode))) |
499 | return 0; | 499 | return 0; |
500 | return security_ops->inode_getsecurity(inode, name, buffer, size, err); | 500 | return security_ops->inode_getsecurity(inode, name, buffer, alloc); |
501 | } | 501 | } |
502 | 502 | ||
503 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) | 503 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index be6de0b8734f..e5ed07510309 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -136,32 +136,6 @@ static DEFINE_SPINLOCK(sb_security_lock); | |||
136 | 136 | ||
137 | static struct kmem_cache *sel_inode_cache; | 137 | static struct kmem_cache *sel_inode_cache; |
138 | 138 | ||
139 | /* Return security context for a given sid or just the context | ||
140 | length if the buffer is null or length is 0 */ | ||
141 | static int selinux_getsecurity(u32 sid, void *buffer, size_t size) | ||
142 | { | ||
143 | char *context; | ||
144 | unsigned len; | ||
145 | int rc; | ||
146 | |||
147 | rc = security_sid_to_context(sid, &context, &len); | ||
148 | if (rc) | ||
149 | return rc; | ||
150 | |||
151 | if (!buffer || !size) | ||
152 | goto getsecurity_exit; | ||
153 | |||
154 | if (size < len) { | ||
155 | len = -ERANGE; | ||
156 | goto getsecurity_exit; | ||
157 | } | ||
158 | memcpy(buffer, context, len); | ||
159 | |||
160 | getsecurity_exit: | ||
161 | kfree(context); | ||
162 | return len; | ||
163 | } | ||
164 | |||
165 | /** | 139 | /** |
166 | * selinux_secmark_enabled - Check to see if SECMARK is currently enabled | 140 | * selinux_secmark_enabled - Check to see if SECMARK is currently enabled |
167 | * | 141 | * |
@@ -2675,14 +2649,27 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name) | |||
2675 | * | 2649 | * |
2676 | * Permission check is handled by selinux_inode_getxattr hook. | 2650 | * Permission check is handled by selinux_inode_getxattr hook. |
2677 | */ | 2651 | */ |
2678 | static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) | 2652 | static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
2679 | { | 2653 | { |
2654 | u32 size; | ||
2655 | int error; | ||
2656 | char *context = NULL; | ||
2680 | struct inode_security_struct *isec = inode->i_security; | 2657 | struct inode_security_struct *isec = inode->i_security; |
2681 | 2658 | ||
2682 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) | 2659 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) |
2683 | return -EOPNOTSUPP; | 2660 | return -EOPNOTSUPP; |
2684 | 2661 | ||
2685 | return selinux_getsecurity(isec->sid, buffer, size); | 2662 | error = security_sid_to_context(isec->sid, &context, &size); |
2663 | if (error) | ||
2664 | return error; | ||
2665 | error = size; | ||
2666 | if (alloc) { | ||
2667 | *buffer = context; | ||
2668 | goto out_nofree; | ||
2669 | } | ||
2670 | kfree(context); | ||
2671 | out_nofree: | ||
2672 | return error; | ||
2686 | } | 2673 | } |
2687 | 2674 | ||
2688 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, | 2675 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, |