diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 96 |
1 files changed, 45 insertions, 51 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b65c201e9ff5..9c08a19cc81b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -117,6 +117,32 @@ static struct security_operations *secondary_ops = NULL; | |||
| 117 | static LIST_HEAD(superblock_security_head); | 117 | static LIST_HEAD(superblock_security_head); |
| 118 | static DEFINE_SPINLOCK(sb_security_lock); | 118 | static DEFINE_SPINLOCK(sb_security_lock); |
| 119 | 119 | ||
| 120 | /* Return security context for a given sid or just the context | ||
| 121 | length if the buffer is null or length is 0 */ | ||
| 122 | static int selinux_getsecurity(u32 sid, void *buffer, size_t size) | ||
| 123 | { | ||
| 124 | char *context; | ||
| 125 | unsigned len; | ||
| 126 | int rc; | ||
| 127 | |||
| 128 | rc = security_sid_to_context(sid, &context, &len); | ||
| 129 | if (rc) | ||
| 130 | return rc; | ||
| 131 | |||
| 132 | if (!buffer || !size) | ||
| 133 | goto getsecurity_exit; | ||
| 134 | |||
| 135 | if (size < len) { | ||
| 136 | len = -ERANGE; | ||
| 137 | goto getsecurity_exit; | ||
| 138 | } | ||
| 139 | memcpy(buffer, context, len); | ||
| 140 | |||
| 141 | getsecurity_exit: | ||
| 142 | kfree(context); | ||
| 143 | return len; | ||
| 144 | } | ||
| 145 | |||
| 120 | /* Allocate and free functions for each kind of security blob. */ | 146 | /* Allocate and free functions for each kind of security blob. */ |
| 121 | 147 | ||
| 122 | static int task_alloc_security(struct task_struct *task) | 148 | static int task_alloc_security(struct task_struct *task) |
| @@ -2209,6 +2235,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name) | |||
| 2209 | return -EACCES; | 2235 | return -EACCES; |
| 2210 | } | 2236 | } |
| 2211 | 2237 | ||
| 2238 | static const char *selinux_inode_xattr_getsuffix(void) | ||
| 2239 | { | ||
| 2240 | return XATTR_SELINUX_SUFFIX; | ||
| 2241 | } | ||
| 2242 | |||
| 2212 | /* | 2243 | /* |
| 2213 | * Copy the in-core inode security context value to the user. If the | 2244 | * Copy the in-core inode security context value to the user. If the |
| 2214 | * getxattr() prior to this succeeded, check to see if we need to | 2245 | * getxattr() prior to this succeeded, check to see if we need to |
| @@ -2219,44 +2250,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name) | |||
| 2219 | static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) | 2250 | static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) |
| 2220 | { | 2251 | { |
| 2221 | struct inode_security_struct *isec = inode->i_security; | 2252 | struct inode_security_struct *isec = inode->i_security; |
| 2222 | char *context; | ||
| 2223 | unsigned len; | ||
| 2224 | int rc; | ||
| 2225 | |||
| 2226 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) { | ||
| 2227 | rc = -EOPNOTSUPP; | ||
| 2228 | goto out; | ||
| 2229 | } | ||
| 2230 | |||
| 2231 | rc = security_sid_to_context(isec->sid, &context, &len); | ||
| 2232 | if (rc) | ||
| 2233 | goto out; | ||
| 2234 | |||
| 2235 | /* Probe for required buffer size */ | ||
| 2236 | if (!buffer || !size) { | ||
| 2237 | rc = len; | ||
| 2238 | goto out_free; | ||
| 2239 | } | ||
| 2240 | 2253 | ||
| 2241 | if (size < len) { | 2254 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) |
| 2242 | rc = -ERANGE; | 2255 | return -EOPNOTSUPP; |
| 2243 | goto out_free; | ||
| 2244 | } | ||
| 2245 | 2256 | ||
| 2246 | if (err > 0) { | 2257 | return selinux_getsecurity(isec->sid, buffer, size); |
| 2247 | if ((len == err) && !(memcmp(context, buffer, len))) { | ||
| 2248 | /* Don't need to canonicalize value */ | ||
| 2249 | rc = err; | ||
| 2250 | goto out_free; | ||
| 2251 | } | ||
| 2252 | memset(buffer, 0, size); | ||
| 2253 | } | ||
| 2254 | memcpy(buffer, context, len); | ||
| 2255 | rc = len; | ||
| 2256 | out_free: | ||
| 2257 | kfree(context); | ||
| 2258 | out: | ||
| 2259 | return rc; | ||
| 2260 | } | 2258 | } |
| 2261 | 2259 | ||
| 2262 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, | 2260 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, |
| @@ -4022,6 +4020,13 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | |||
| 4022 | return ipc_has_perm(ipcp, av); | 4020 | return ipc_has_perm(ipcp, av); |
| 4023 | } | 4021 | } |
| 4024 | 4022 | ||
| 4023 | static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size) | ||
| 4024 | { | ||
| 4025 | struct ipc_security_struct *isec = ipcp->security; | ||
| 4026 | |||
| 4027 | return selinux_getsecurity(isec->sid, buffer, size); | ||
| 4028 | } | ||
| 4029 | |||
| 4025 | /* module stacking operations */ | 4030 | /* module stacking operations */ |
| 4026 | static int selinux_register_security (const char *name, struct security_operations *ops) | 4031 | static int selinux_register_security (const char *name, struct security_operations *ops) |
| 4027 | { | 4032 | { |
| @@ -4063,8 +4068,7 @@ static int selinux_getprocattr(struct task_struct *p, | |||
| 4063 | char *name, void *value, size_t size) | 4068 | char *name, void *value, size_t size) |
| 4064 | { | 4069 | { |
| 4065 | struct task_security_struct *tsec; | 4070 | struct task_security_struct *tsec; |
| 4066 | u32 sid, len; | 4071 | u32 sid; |
| 4067 | char *context; | ||
| 4068 | int error; | 4072 | int error; |
| 4069 | 4073 | ||
| 4070 | if (current != p) { | 4074 | if (current != p) { |
| @@ -4073,9 +4077,6 @@ static int selinux_getprocattr(struct task_struct *p, | |||
| 4073 | return error; | 4077 | return error; |
| 4074 | } | 4078 | } |
| 4075 | 4079 | ||
| 4076 | if (!size) | ||
| 4077 | return -ERANGE; | ||
| 4078 | |||
| 4079 | tsec = p->security; | 4080 | tsec = p->security; |
| 4080 | 4081 | ||
| 4081 | if (!strcmp(name, "current")) | 4082 | if (!strcmp(name, "current")) |
| @@ -4092,16 +4093,7 @@ static int selinux_getprocattr(struct task_struct *p, | |||
| 4092 | if (!sid) | 4093 | if (!sid) |
| 4093 | return 0; | 4094 | return 0; |
| 4094 | 4095 | ||
| 4095 | error = security_sid_to_context(sid, &context, &len); | 4096 | return selinux_getsecurity(sid, value, size); |
| 4096 | if (error) | ||
| 4097 | return error; | ||
| 4098 | if (len > size) { | ||
| 4099 | kfree(context); | ||
| 4100 | return -ERANGE; | ||
| 4101 | } | ||
| 4102 | memcpy(value, context, len); | ||
| 4103 | kfree(context); | ||
| 4104 | return len; | ||
| 4105 | } | 4097 | } |
| 4106 | 4098 | ||
| 4107 | static int selinux_setprocattr(struct task_struct *p, | 4099 | static int selinux_setprocattr(struct task_struct *p, |
| @@ -4259,6 +4251,7 @@ static struct security_operations selinux_ops = { | |||
| 4259 | .inode_getxattr = selinux_inode_getxattr, | 4251 | .inode_getxattr = selinux_inode_getxattr, |
| 4260 | .inode_listxattr = selinux_inode_listxattr, | 4252 | .inode_listxattr = selinux_inode_listxattr, |
| 4261 | .inode_removexattr = selinux_inode_removexattr, | 4253 | .inode_removexattr = selinux_inode_removexattr, |
| 4254 | .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix, | ||
| 4262 | .inode_getsecurity = selinux_inode_getsecurity, | 4255 | .inode_getsecurity = selinux_inode_getsecurity, |
| 4263 | .inode_setsecurity = selinux_inode_setsecurity, | 4256 | .inode_setsecurity = selinux_inode_setsecurity, |
| 4264 | .inode_listsecurity = selinux_inode_listsecurity, | 4257 | .inode_listsecurity = selinux_inode_listsecurity, |
| @@ -4296,6 +4289,7 @@ static struct security_operations selinux_ops = { | |||
| 4296 | .task_to_inode = selinux_task_to_inode, | 4289 | .task_to_inode = selinux_task_to_inode, |
| 4297 | 4290 | ||
| 4298 | .ipc_permission = selinux_ipc_permission, | 4291 | .ipc_permission = selinux_ipc_permission, |
| 4292 | .ipc_getsecurity = selinux_ipc_getsecurity, | ||
| 4299 | 4293 | ||
| 4300 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, | 4294 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, |
| 4301 | .msg_msg_free_security = selinux_msg_msg_free_security, | 4295 | .msg_msg_free_security = selinux_msg_msg_free_security, |
