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, |