diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/dummy.c | 14 | ||||
| -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 |
5 files changed, 86 insertions, 61 deletions
diff --git a/security/dummy.c b/security/dummy.c index a678f094b72d..fd99429278e9 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
| @@ -378,7 +378,7 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name) | |||
| 378 | return 0; | 378 | return 0; |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) | 381 | static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) |
| 382 | { | 382 | { |
| 383 | return -EOPNOTSUPP; | 383 | return -EOPNOTSUPP; |
| 384 | } | 384 | } |
| @@ -393,6 +393,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu | |||
| 393 | return 0; | 393 | return 0; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | static const char *dummy_inode_xattr_getsuffix(void) | ||
| 397 | { | ||
| 398 | return NULL; | ||
| 399 | } | ||
| 400 | |||
| 396 | static int dummy_file_permission (struct file *file, int mask) | 401 | static int dummy_file_permission (struct file *file, int mask) |
| 397 | { | 402 | { |
| 398 | return 0; | 403 | return 0; |
| @@ -558,6 +563,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag) | |||
| 558 | return 0; | 563 | return 0; |
| 559 | } | 564 | } |
| 560 | 565 | ||
| 566 | static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size) | ||
| 567 | { | ||
| 568 | return -EOPNOTSUPP; | ||
| 569 | } | ||
| 570 | |||
| 561 | static int dummy_msg_msg_alloc_security (struct msg_msg *msg) | 571 | static int dummy_msg_msg_alloc_security (struct msg_msg *msg) |
| 562 | { | 572 | { |
| 563 | return 0; | 573 | return 0; |
| @@ -931,6 +941,7 @@ void security_fixup_ops (struct security_operations *ops) | |||
| 931 | set_to_dummy_if_null(ops, inode_getxattr); | 941 | set_to_dummy_if_null(ops, inode_getxattr); |
| 932 | set_to_dummy_if_null(ops, inode_listxattr); | 942 | set_to_dummy_if_null(ops, inode_listxattr); |
| 933 | set_to_dummy_if_null(ops, inode_removexattr); | 943 | set_to_dummy_if_null(ops, inode_removexattr); |
| 944 | set_to_dummy_if_null(ops, inode_xattr_getsuffix); | ||
| 934 | set_to_dummy_if_null(ops, inode_getsecurity); | 945 | set_to_dummy_if_null(ops, inode_getsecurity); |
| 935 | set_to_dummy_if_null(ops, inode_setsecurity); | 946 | set_to_dummy_if_null(ops, inode_setsecurity); |
| 936 | set_to_dummy_if_null(ops, inode_listsecurity); | 947 | set_to_dummy_if_null(ops, inode_listsecurity); |
| @@ -965,6 +976,7 @@ void security_fixup_ops (struct security_operations *ops) | |||
| 965 | set_to_dummy_if_null(ops, task_reparent_to_init); | 976 | set_to_dummy_if_null(ops, task_reparent_to_init); |
| 966 | set_to_dummy_if_null(ops, task_to_inode); | 977 | set_to_dummy_if_null(ops, task_to_inode); |
| 967 | set_to_dummy_if_null(ops, ipc_permission); | 978 | set_to_dummy_if_null(ops, ipc_permission); |
| 979 | set_to_dummy_if_null(ops, ipc_getsecurity); | ||
| 968 | set_to_dummy_if_null(ops, msg_msg_alloc_security); | 980 | set_to_dummy_if_null(ops, msg_msg_alloc_security); |
| 969 | set_to_dummy_if_null(ops, msg_msg_free_security); | 981 | set_to_dummy_if_null(ops, msg_msg_free_security); |
| 970 | set_to_dummy_if_null(ops, msg_queue_alloc_security); | 982 | set_to_dummy_if_null(ops, msg_queue_alloc_security); |
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); |
