diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/hooks.c | 98 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 9 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 11 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 15 |
4 files changed, 73 insertions, 60 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, |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 85e399259832..b8f4d25cf335 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -106,6 +106,9 @@ static struct nlmsg_perm nlmsg_audit_perms[] = | |||
106 | { AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV }, | 106 | { AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV }, |
107 | { AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | 107 | { AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, |
108 | { AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | 108 | { AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, |
109 | { AUDIT_LIST_RULES, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV }, | ||
110 | { AUDIT_ADD_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | ||
111 | { AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | ||
109 | { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY }, | 112 | { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY }, |
110 | { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ }, | 113 | { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ }, |
111 | }; | 114 | }; |
@@ -152,8 +155,10 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) | |||
152 | break; | 155 | break; |
153 | 156 | ||
154 | case SECCLASS_NETLINK_AUDIT_SOCKET: | 157 | case SECCLASS_NETLINK_AUDIT_SOCKET: |
155 | if (nlmsg_type >= AUDIT_FIRST_USER_MSG && | 158 | if ((nlmsg_type >= AUDIT_FIRST_USER_MSG && |
156 | nlmsg_type <= AUDIT_LAST_USER_MSG) { | 159 | nlmsg_type <= AUDIT_LAST_USER_MSG) || |
160 | (nlmsg_type >= AUDIT_FIRST_USER_MSG2 && | ||
161 | nlmsg_type <= AUDIT_LAST_USER_MSG2)) { | ||
157 | *perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY; | 162 | *perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY; |
158 | } else { | 163 | } else { |
159 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms, | 164 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms, |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index f5d78365488f..a4efc966f065 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/major.h> | 22 | #include <linux/major.h> |
23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
24 | #include <linux/percpu.h> | 24 | #include <linux/percpu.h> |
25 | #include <linux/audit.h> | ||
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | #include <asm/semaphore.h> | 27 | #include <asm/semaphore.h> |
27 | 28 | ||
@@ -127,6 +128,10 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf, | |||
127 | length = task_has_security(current, SECURITY__SETENFORCE); | 128 | length = task_has_security(current, SECURITY__SETENFORCE); |
128 | if (length) | 129 | if (length) |
129 | goto out; | 130 | goto out; |
131 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | ||
132 | "enforcing=%d old_enforcing=%d auid=%u", new_value, | ||
133 | selinux_enforcing, | ||
134 | audit_get_loginuid(current->audit_context)); | ||
130 | selinux_enforcing = new_value; | 135 | selinux_enforcing = new_value; |
131 | if (selinux_enforcing) | 136 | if (selinux_enforcing) |
132 | avc_ss_reset(0); | 137 | avc_ss_reset(0); |
@@ -177,6 +182,9 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf, | |||
177 | length = selinux_disable(); | 182 | length = selinux_disable(); |
178 | if (length < 0) | 183 | if (length < 0) |
179 | goto out; | 184 | goto out; |
185 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | ||
186 | "selinux=0 auid=%u", | ||
187 | audit_get_loginuid(current->audit_context)); | ||
180 | } | 188 | } |
181 | 189 | ||
182 | length = count; | 190 | length = count; |
@@ -262,6 +270,9 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf, | |||
262 | length = ret; | 270 | length = ret; |
263 | else | 271 | else |
264 | length = count; | 272 | length = count; |
273 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, | ||
274 | "policy loaded auid=%u", | ||
275 | audit_get_loginuid(current->audit_context)); | ||
265 | out: | 276 | out: |
266 | mutex_unlock(&sel_mutex); | 277 | mutex_unlock(&sel_mutex); |
267 | vfree(data); | 278 | vfree(data); |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 63e0b7f29cb5..61492485de84 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1759,19 +1759,22 @@ int security_set_bools(int len, int *values) | |||
1759 | goto out; | 1759 | goto out; |
1760 | } | 1760 | } |
1761 | 1761 | ||
1762 | printk(KERN_INFO "security: committed booleans { "); | ||
1763 | for (i = 0; i < len; i++) { | 1762 | for (i = 0; i < len; i++) { |
1763 | if (!!values[i] != policydb.bool_val_to_struct[i]->state) { | ||
1764 | audit_log(current->audit_context, GFP_ATOMIC, | ||
1765 | AUDIT_MAC_CONFIG_CHANGE, | ||
1766 | "bool=%s val=%d old_val=%d auid=%u", | ||
1767 | policydb.p_bool_val_to_name[i], | ||
1768 | !!values[i], | ||
1769 | policydb.bool_val_to_struct[i]->state, | ||
1770 | audit_get_loginuid(current->audit_context)); | ||
1771 | } | ||
1764 | if (values[i]) { | 1772 | if (values[i]) { |
1765 | policydb.bool_val_to_struct[i]->state = 1; | 1773 | policydb.bool_val_to_struct[i]->state = 1; |
1766 | } else { | 1774 | } else { |
1767 | policydb.bool_val_to_struct[i]->state = 0; | 1775 | policydb.bool_val_to_struct[i]->state = 0; |
1768 | } | 1776 | } |
1769 | if (i != 0) | ||
1770 | printk(", "); | ||
1771 | printk("%s:%d", policydb.p_bool_val_to_name[i], | ||
1772 | policydb.bool_val_to_struct[i]->state); | ||
1773 | } | 1777 | } |
1774 | printk(" }\n"); | ||
1775 | 1778 | ||
1776 | for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { | 1779 | for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { |
1777 | rc = evaluate_cond_node(&policydb, cur); | 1780 | rc = evaluate_cond_node(&policydb, cur); |