diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 98 |
1 files changed, 46 insertions, 52 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ccaf988f3729..b61b9554bc27 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -119,6 +119,32 @@ static DEFINE_SPINLOCK(sb_security_lock); | |||
119 | 119 | ||
120 | static kmem_cache_t *sel_inode_cache; | 120 | static kmem_cache_t *sel_inode_cache; |
121 | 121 | ||
122 | /* Return security context for a given sid or just the context | ||
123 | length if the buffer is null or length is 0 */ | ||
124 | static int selinux_getsecurity(u32 sid, void *buffer, size_t size) | ||
125 | { | ||
126 | char *context; | ||
127 | unsigned len; | ||
128 | int rc; | ||
129 | |||
130 | rc = security_sid_to_context(sid, &context, &len); | ||
131 | if (rc) | ||
132 | return rc; | ||
133 | |||
134 | if (!buffer || !size) | ||
135 | goto getsecurity_exit; | ||
136 | |||
137 | if (size < len) { | ||
138 | len = -ERANGE; | ||
139 | goto getsecurity_exit; | ||
140 | } | ||
141 | memcpy(buffer, context, len); | ||
142 | |||
143 | getsecurity_exit: | ||
144 | kfree(context); | ||
145 | return len; | ||
146 | } | ||
147 | |||
122 | /* Allocate and free functions for each kind of security blob. */ | 148 | /* Allocate and free functions for each kind of security blob. */ |
123 | 149 | ||
124 | static int task_alloc_security(struct task_struct *task) | 150 | static int task_alloc_security(struct task_struct *task) |
@@ -2210,6 +2236,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name) | |||
2210 | return -EACCES; | 2236 | return -EACCES; |
2211 | } | 2237 | } |
2212 | 2238 | ||
2239 | static const char *selinux_inode_xattr_getsuffix(void) | ||
2240 | { | ||
2241 | return XATTR_SELINUX_SUFFIX; | ||
2242 | } | ||
2243 | |||
2213 | /* | 2244 | /* |
2214 | * Copy the in-core inode security context value to the user. If the | 2245 | * Copy the in-core inode security context value to the user. If the |
2215 | * getxattr() prior to this succeeded, check to see if we need to | 2246 | * getxattr() prior to this succeeded, check to see if we need to |
@@ -2217,47 +2248,14 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name) | |||
2217 | * | 2248 | * |
2218 | * Permission check is handled by selinux_inode_getxattr hook. | 2249 | * Permission check is handled by selinux_inode_getxattr hook. |
2219 | */ | 2250 | */ |
2220 | static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) | 2251 | static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) |
2221 | { | 2252 | { |
2222 | struct inode_security_struct *isec = inode->i_security; | 2253 | struct inode_security_struct *isec = inode->i_security; |
2223 | char *context; | ||
2224 | unsigned len; | ||
2225 | int rc; | ||
2226 | |||
2227 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) { | ||
2228 | rc = -EOPNOTSUPP; | ||
2229 | goto out; | ||
2230 | } | ||
2231 | |||
2232 | rc = security_sid_to_context(isec->sid, &context, &len); | ||
2233 | if (rc) | ||
2234 | goto out; | ||
2235 | |||
2236 | /* Probe for required buffer size */ | ||
2237 | if (!buffer || !size) { | ||
2238 | rc = len; | ||
2239 | goto out_free; | ||
2240 | } | ||
2241 | 2254 | ||
2242 | if (size < len) { | 2255 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) |
2243 | rc = -ERANGE; | 2256 | return -EOPNOTSUPP; |
2244 | goto out_free; | ||
2245 | } | ||
2246 | 2257 | ||
2247 | if (err > 0) { | 2258 | return selinux_getsecurity(isec->sid, buffer, size); |
2248 | if ((len == err) && !(memcmp(context, buffer, len))) { | ||
2249 | /* Don't need to canonicalize value */ | ||
2250 | rc = err; | ||
2251 | goto out_free; | ||
2252 | } | ||
2253 | memset(buffer, 0, size); | ||
2254 | } | ||
2255 | memcpy(buffer, context, len); | ||
2256 | rc = len; | ||
2257 | out_free: | ||
2258 | kfree(context); | ||
2259 | out: | ||
2260 | return rc; | ||
2261 | } | 2259 | } |
2262 | 2260 | ||
2263 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, | 2261 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, |
@@ -4054,6 +4052,13 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | |||
4054 | return ipc_has_perm(ipcp, av); | 4052 | return ipc_has_perm(ipcp, av); |
4055 | } | 4053 | } |
4056 | 4054 | ||
4055 | static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size) | ||
4056 | { | ||
4057 | struct ipc_security_struct *isec = ipcp->security; | ||
4058 | |||
4059 | return selinux_getsecurity(isec->sid, buffer, size); | ||
4060 | } | ||
4061 | |||
4057 | /* module stacking operations */ | 4062 | /* module stacking operations */ |
4058 | static int selinux_register_security (const char *name, struct security_operations *ops) | 4063 | static int selinux_register_security (const char *name, struct security_operations *ops) |
4059 | { | 4064 | { |
@@ -4095,8 +4100,7 @@ static int selinux_getprocattr(struct task_struct *p, | |||
4095 | char *name, void *value, size_t size) | 4100 | char *name, void *value, size_t size) |
4096 | { | 4101 | { |
4097 | struct task_security_struct *tsec; | 4102 | struct task_security_struct *tsec; |
4098 | u32 sid, len; | 4103 | u32 sid; |
4099 | char *context; | ||
4100 | int error; | 4104 | int error; |
4101 | 4105 | ||
4102 | if (current != p) { | 4106 | if (current != p) { |
@@ -4105,9 +4109,6 @@ static int selinux_getprocattr(struct task_struct *p, | |||
4105 | return error; | 4109 | return error; |
4106 | } | 4110 | } |
4107 | 4111 | ||
4108 | if (!size) | ||
4109 | return -ERANGE; | ||
4110 | |||
4111 | tsec = p->security; | 4112 | tsec = p->security; |
4112 | 4113 | ||
4113 | if (!strcmp(name, "current")) | 4114 | if (!strcmp(name, "current")) |
@@ -4124,16 +4125,7 @@ static int selinux_getprocattr(struct task_struct *p, | |||
4124 | if (!sid) | 4125 | if (!sid) |
4125 | return 0; | 4126 | return 0; |
4126 | 4127 | ||
4127 | error = security_sid_to_context(sid, &context, &len); | 4128 | return selinux_getsecurity(sid, value, size); |
4128 | if (error) | ||
4129 | return error; | ||
4130 | if (len > size) { | ||
4131 | kfree(context); | ||
4132 | return -ERANGE; | ||
4133 | } | ||
4134 | memcpy(value, context, len); | ||
4135 | kfree(context); | ||
4136 | return len; | ||
4137 | } | 4129 | } |
4138 | 4130 | ||
4139 | static int selinux_setprocattr(struct task_struct *p, | 4131 | static int selinux_setprocattr(struct task_struct *p, |
@@ -4291,6 +4283,7 @@ static struct security_operations selinux_ops = { | |||
4291 | .inode_getxattr = selinux_inode_getxattr, | 4283 | .inode_getxattr = selinux_inode_getxattr, |
4292 | .inode_listxattr = selinux_inode_listxattr, | 4284 | .inode_listxattr = selinux_inode_listxattr, |
4293 | .inode_removexattr = selinux_inode_removexattr, | 4285 | .inode_removexattr = selinux_inode_removexattr, |
4286 | .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix, | ||
4294 | .inode_getsecurity = selinux_inode_getsecurity, | 4287 | .inode_getsecurity = selinux_inode_getsecurity, |
4295 | .inode_setsecurity = selinux_inode_setsecurity, | 4288 | .inode_setsecurity = selinux_inode_setsecurity, |
4296 | .inode_listsecurity = selinux_inode_listsecurity, | 4289 | .inode_listsecurity = selinux_inode_listsecurity, |
@@ -4328,6 +4321,7 @@ static struct security_operations selinux_ops = { | |||
4328 | .task_to_inode = selinux_task_to_inode, | 4321 | .task_to_inode = selinux_task_to_inode, |
4329 | 4322 | ||
4330 | .ipc_permission = selinux_ipc_permission, | 4323 | .ipc_permission = selinux_ipc_permission, |
4324 | .ipc_getsecurity = selinux_ipc_getsecurity, | ||
4331 | 4325 | ||
4332 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, | 4326 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, |
4333 | .msg_msg_free_security = selinux_msg_msg_free_security, | 4327 | .msg_msg_free_security = selinux_msg_msg_free_security, |