diff options
author | Dave Airlie <airlied@redhat.com> | 2015-04-20 11:32:26 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-04-20 13:05:20 +1000 |
commit | 2c33ce009ca2389dbf0535d0672214d09738e35e (patch) | |
tree | 6186a6458c3c160385d794a23eaf07c786a9e61b /security | |
parent | cec32a47010647e8b0603726ebb75b990a4057a4 (diff) | |
parent | 09d51602cf84a1264946711dd4ea0dddbac599a1 (diff) |
Merge Linus master into drm-next
The merge is clean, but the arm build fails afterwards,
due to API changes in the regulator tree.
I've included the patch into the merge to fix the build.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'security')
31 files changed, 421 insertions, 269 deletions
diff --git a/security/Kconfig b/security/Kconfig index beb86b500adf..bf4ec46474b6 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -21,6 +21,7 @@ config SECURITY_DMESG_RESTRICT config SECURITY bool "Enable different security models" depends on SYSFS + depends on MULTIUSER help This allows you to choose different security modules to be configured into your kernel. diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 107db88b1d5f..dd56bffd6500 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -364,12 +364,12 @@ static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid) return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond); } -static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +static int apparmor_inode_getattr(const struct path *path) { - if (!mediated_filesystem(dentry)) + if (!mediated_filesystem(path->dentry)) return 0; - return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry, + return common_perm_mnt_dentry(OP_GETATTR, path->mnt, path->dentry, AA_MAY_META_READ); } diff --git a/security/capability.c b/security/capability.c index 070dd46f62f4..0d03fcc489a4 100644 --- a/security/capability.c +++ b/security/capability.c @@ -225,7 +225,7 @@ static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr) return 0; } -static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +static int cap_inode_getattr(const struct path *path) { return 0; } @@ -776,11 +776,6 @@ static int cap_tun_dev_open(void *security) { return 0; } - -static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk) -{ -} - #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM @@ -1134,7 +1129,6 @@ void __init security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, tun_dev_open); set_to_cap_if_null(ops, tun_dev_attach_queue); set_to_cap_if_null(ops, tun_dev_attach); - set_to_cap_if_null(ops, skb_owned_by); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM set_to_cap_if_null(ops, xfrm_policy_alloc_security); diff --git a/security/keys/compat.c b/security/keys/compat.c index 347896548ad3..25430a3aa7f7 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -31,30 +31,21 @@ static long compat_keyctl_instantiate_key_iov( key_serial_t ringid) { struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + struct iov_iter from; long ret; - if (!_payload_iov || !ioc) - goto no_payload; + if (!_payload_iov) + ioc = 0; - ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc, - ARRAY_SIZE(iovstack), - iovstack, &iov); + ret = compat_import_iovec(WRITE, _payload_iov, ioc, + ARRAY_SIZE(iovstack), &iov, + &from); if (ret < 0) - goto err; - if (ret == 0) - goto no_payload_free; - - ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); -err: - if (iov != iovstack) - kfree(iov); - return ret; + return ret; -no_payload_free: - if (iov != iovstack) - kfree(iov); -no_payload: - return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); + ret = keyctl_instantiate_key_common(id, &from, ringid); + kfree(iov); + return ret; } /* diff --git a/security/keys/internal.h b/security/keys/internal.h index 200e37867336..5105c2c2da75 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -243,9 +243,10 @@ extern long keyctl_instantiate_key_iov(key_serial_t, unsigned, key_serial_t); extern long keyctl_invalidate_key(key_serial_t); +struct iov_iter; extern long keyctl_instantiate_key_common(key_serial_t, - const struct iovec *, - unsigned, size_t, key_serial_t); + struct iov_iter *, + key_serial_t); #ifdef CONFIG_PERSISTENT_KEYRINGS extern long keyctl_get_persistent(uid_t, key_serial_t); extern unsigned persistent_keyring_expiry; diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4743d71e4aa6..0b9ec78a7a7a 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -998,21 +998,6 @@ static int keyctl_change_reqkey_auth(struct key *key) } /* - * Copy the iovec data from userspace - */ -static long copy_from_user_iovec(void *buffer, const struct iovec *iov, - unsigned ioc) -{ - for (; ioc > 0; ioc--) { - if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0) - return -EFAULT; - buffer += iov->iov_len; - iov++; - } - return 0; -} - -/* * Instantiate a key with the specified payload and link the key into the * destination keyring if one is given. * @@ -1022,20 +1007,21 @@ static long copy_from_user_iovec(void *buffer, const struct iovec *iov, * If successful, 0 will be returned. */ long keyctl_instantiate_key_common(key_serial_t id, - const struct iovec *payload_iov, - unsigned ioc, - size_t plen, + struct iov_iter *from, key_serial_t ringid) { const struct cred *cred = current_cred(); struct request_key_auth *rka; struct key *instkey, *dest_keyring; + size_t plen = from ? iov_iter_count(from) : 0; void *payload; long ret; - bool vm = false; kenter("%d,,%zu,%d", id, plen, ringid); + if (!plen) + from = NULL; + ret = -EINVAL; if (plen > 1024 * 1024 - 1) goto error; @@ -1054,20 +1040,19 @@ long keyctl_instantiate_key_common(key_serial_t id, /* pull the payload in if one was supplied */ payload = NULL; - if (payload_iov) { + if (from) { ret = -ENOMEM; payload = kmalloc(plen, GFP_KERNEL); if (!payload) { if (plen <= PAGE_SIZE) goto error; - vm = true; payload = vmalloc(plen); if (!payload) goto error; } - ret = copy_from_user_iovec(payload, payload_iov, ioc); - if (ret < 0) + ret = -EFAULT; + if (copy_from_iter(payload, plen, from) != plen) goto error2; } @@ -1089,10 +1074,7 @@ long keyctl_instantiate_key_common(key_serial_t id, keyctl_change_reqkey_auth(NULL); error2: - if (!vm) - kfree(payload); - else - vfree(payload); + kvfree(payload); error: return ret; } @@ -1112,15 +1094,19 @@ long keyctl_instantiate_key(key_serial_t id, key_serial_t ringid) { if (_payload && plen) { - struct iovec iov[1] = { - [0].iov_base = (void __user *)_payload, - [0].iov_len = plen - }; + struct iovec iov; + struct iov_iter from; + int ret; - return keyctl_instantiate_key_common(id, iov, 1, plen, ringid); + ret = import_single_range(WRITE, (void __user *)_payload, plen, + &iov, &from); + if (unlikely(ret)) + return ret; + + return keyctl_instantiate_key_common(id, &from, ringid); } - return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); + return keyctl_instantiate_key_common(id, NULL, ringid); } /* @@ -1138,29 +1124,19 @@ long keyctl_instantiate_key_iov(key_serial_t id, key_serial_t ringid) { struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + struct iov_iter from; long ret; - if (!_payload_iov || !ioc) - goto no_payload; + if (!_payload_iov) + ioc = 0; - ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, - ARRAY_SIZE(iovstack), iovstack, &iov); + ret = import_iovec(WRITE, _payload_iov, ioc, + ARRAY_SIZE(iovstack), &iov, &from); if (ret < 0) - goto err; - if (ret == 0) - goto no_payload_free; - - ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); -err: - if (iov != iovstack) - kfree(iov); + return ret; + ret = keyctl_instantiate_key_common(id, &from, ringid); + kfree(iov); return ret; - -no_payload_free: - if (iov != iovstack) - kfree(iov); -no_payload: - return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid); } /* diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 69fdf3bc765b..b526ddc3add5 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -211,7 +211,7 @@ static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr, static void dump_common_audit_data(struct audit_buffer *ab, struct common_audit_data *a) { - struct task_struct *tsk = current; + char comm[sizeof(current->comm)]; /* * To keep stack sizes in check force programers to notice if they @@ -220,8 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab, */ BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); - audit_log_format(ab, " pid=%d comm=", task_pid_nr(tsk)); - audit_log_untrustedstring(ab, tsk->comm); + audit_log_format(ab, " pid=%d comm=", task_pid_nr(current)); + audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(comm))); switch (a->type) { case LSM_AUDIT_DATA_NONE: @@ -276,16 +276,19 @@ static void dump_common_audit_data(struct audit_buffer *ab, audit_log_format(ab, " ino=%lu", inode->i_ino); break; } - case LSM_AUDIT_DATA_TASK: - tsk = a->u.tsk; + case LSM_AUDIT_DATA_TASK: { + struct task_struct *tsk = a->u.tsk; if (tsk) { pid_t pid = task_pid_nr(tsk); if (pid) { + char comm[sizeof(tsk->comm)]; audit_log_format(ab, " pid=%d comm=", pid); - audit_log_untrustedstring(ab, tsk->comm); + audit_log_untrustedstring(ab, + memcpy(comm, tsk->comm, sizeof(comm))); } } break; + } case LSM_AUDIT_DATA_NET: if (a->u.net->sk) { struct sock *sk = a->u.net->sk; diff --git a/security/security.c b/security/security.c index e81d5bbe7363..730ac65a5737 100644 --- a/security/security.c +++ b/security/security.c @@ -608,11 +608,11 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr) } EXPORT_SYMBOL_GPL(security_inode_setattr); -int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +int security_inode_getattr(const struct path *path) { - if (unlikely(IS_PRIVATE(dentry->d_inode))) + if (unlikely(IS_PRIVATE(path->dentry->d_inode))) return 0; - return security_ops->inode_getattr(mnt, dentry); + return security_ops->inode_getattr(path); } int security_inode_setxattr(struct dentry *dentry, const char *name, @@ -1359,11 +1359,6 @@ int security_tun_dev_open(void *security) } EXPORT_SYMBOL(security_tun_dev_open); -void security_skb_owned_by(struct sk_buff *skb, struct sock *sk) -{ - security_ops->skb_owned_by(skb, sk); -} - #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM diff --git a/security/selinux/avc.c b/security/selinux/avc.c index afcc0aed9393..3c17dda9571d 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -724,12 +724,10 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, rcu_read_lock(); node = avc_lookup(ssid, tsid, tclass); - if (unlikely(!node)) { + if (unlikely(!node)) node = avc_compute_av(ssid, tsid, tclass, avd); - } else { + else memcpy(avd, &node->ae.avd, sizeof(*avd)); - avd = &node->ae.avd; - } denied = requested & ~(avd->allowed); if (unlikely(denied)) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4d1a54190388..c318b304ee2f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -51,7 +51,6 @@ #include <linux/tty.h> #include <net/icmp.h> #include <net/ip.h> /* for local_port_range[] */ -#include <net/sock.h> #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ #include <net/inet_connection_sock.h> #include <net/net_namespace.h> @@ -1623,7 +1622,7 @@ static inline int dentry_has_perm(const struct cred *cred, the path to help the auditing code to more easily generate the pathname if needed. */ static inline int path_has_perm(const struct cred *cred, - struct path *path, + const struct path *path, u32 av) { struct inode *inode = path->dentry->d_inode; @@ -2954,15 +2953,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) return dentry_has_perm(cred, dentry, av); } -static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +static int selinux_inode_getattr(const struct path *path) { - const struct cred *cred = current_cred(); - struct path path; - - path.dentry = dentry; - path.mnt = mnt; - - return path_has_perm(cred, &path, FILE__GETATTR); + return path_has_perm(current_cred(), path, FILE__GETATTR); } static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) @@ -4652,11 +4645,6 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); } -static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk) -{ - skb_set_owner_w(skb, sk); -} - static int selinux_secmark_relabel_packet(u32 sid) { const struct task_security_struct *__tsec; @@ -4858,21 +4846,17 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) + const struct nf_hook_state *state) { - return selinux_ip_forward(skb, in, PF_INET); + return selinux_ip_forward(skb, state->in, PF_INET); } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) + const struct nf_hook_state *state) { - return selinux_ip_forward(skb, in, PF_INET6); + return selinux_ip_forward(skb, state->in, PF_INET6); } #endif /* IPV6 */ @@ -4920,9 +4904,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb, static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) + const struct nf_hook_state *state) { return selinux_ip_output(skb, PF_INET); } @@ -5097,21 +5079,17 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) + const struct nf_hook_state *state) { - return selinux_ip_postroute(skb, out, PF_INET); + return selinux_ip_postroute(skb, state->out, PF_INET); } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) + const struct nf_hook_state *state) { - return selinux_ip_postroute(skb, out, PF_INET6); + return selinux_ip_postroute(skb, state->out, PF_INET6); } #endif /* IPV6 */ @@ -6041,7 +6019,6 @@ static struct security_operations selinux_ops = { .tun_dev_attach_queue = selinux_tun_dev_attach_queue, .tun_dev_attach = selinux_tun_dev_attach, .tun_dev_open = selinux_tun_dev_open, - .skb_owned_by = selinux_skb_owned_by, #ifdef CONFIG_SECURITY_NETWORK_XFRM .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 2df7b900e259..2bbb41822d8e 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -73,6 +73,9 @@ static struct nlmsg_perm nlmsg_route_perms[] = { RTM_NEWMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_DELMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_GETMDB, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWNSID, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELNSID, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_GETNSID, NETLINK_ROUTE_SOCKET__NLMSG_READ }, }; static struct nlmsg_perm nlmsg_tcpdiag_perms[] = @@ -100,6 +103,13 @@ static struct nlmsg_perm nlmsg_xfrm_perms[] = { XFRM_MSG_FLUSHPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, { XFRM_MSG_NEWAE, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, { XFRM_MSG_GETAE, NETLINK_XFRM_SOCKET__NLMSG_READ }, + { XFRM_MSG_REPORT, NETLINK_XFRM_SOCKET__NLMSG_READ }, + { XFRM_MSG_MIGRATE, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_NEWSADINFO, NETLINK_XFRM_SOCKET__NLMSG_READ }, + { XFRM_MSG_GETSADINFO, NETLINK_XFRM_SOCKET__NLMSG_READ }, + { XFRM_MSG_NEWSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_GETSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_READ }, + { XFRM_MSG_MAPPING, NETLINK_XFRM_SOCKET__NLMSG_READ }, }; static struct nlmsg_perm nlmsg_audit_perms[] = @@ -143,6 +153,8 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) switch (sclass) { case SECCLASS_NETLINK_ROUTE_SOCKET: + /* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */ + BUILD_BUG_ON(RTM_MAX != (RTM_NEWNSID + 3)); err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms, sizeof(nlmsg_route_perms)); break; @@ -153,6 +165,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) break; case SECCLASS_NETLINK_XFRM_SOCKET: + BUILD_BUG_ON(XFRM_MSG_MAX != XFRM_MSG_MAPPING); err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms, sizeof(nlmsg_xfrm_perms)); break; diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index a3dd9faa19c0..b64f2772b030 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -25,10 +25,43 @@ static struct kmem_cache *avtab_node_cachep; -static inline int avtab_hash(struct avtab_key *keyp, u16 mask) +/* Based on MurmurHash3, written by Austin Appleby and placed in the + * public domain. + */ +static inline int avtab_hash(struct avtab_key *keyp, u32 mask) { - return ((keyp->target_class + (keyp->target_type << 2) + - (keyp->source_type << 9)) & mask); + static const u32 c1 = 0xcc9e2d51; + static const u32 c2 = 0x1b873593; + static const u32 r1 = 15; + static const u32 r2 = 13; + static const u32 m = 5; + static const u32 n = 0xe6546b64; + + u32 hash = 0; + +#define mix(input) { \ + u32 v = input; \ + v *= c1; \ + v = (v << r1) | (v >> (32 - r1)); \ + v *= c2; \ + hash ^= v; \ + hash = (hash << r2) | (hash >> (32 - r2)); \ + hash = hash * m + n; \ +} + + mix(keyp->target_class); + mix(keyp->target_type); + mix(keyp->source_type); + +#undef mix + + hash ^= hash >> 16; + hash *= 0x85ebca6b; + hash ^= hash >> 13; + hash *= 0xc2b2ae35; + hash ^= hash >> 16; + + return hash & mask; } static struct avtab_node* @@ -46,8 +79,12 @@ avtab_insert_node(struct avtab *h, int hvalue, newnode->next = prev->next; prev->next = newnode; } else { - newnode->next = h->htable[hvalue]; - h->htable[hvalue] = newnode; + newnode->next = flex_array_get_ptr(h->htable, hvalue); + if (flex_array_put_ptr(h->htable, hvalue, newnode, + GFP_KERNEL|__GFP_ZERO)) { + kmem_cache_free(avtab_node_cachep, newnode); + return NULL; + } } h->nel++; @@ -64,7 +101,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat return -EINVAL; hvalue = avtab_hash(key, h->mask); - for (prev = NULL, cur = h->htable[hvalue]; + for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && @@ -104,7 +141,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu if (!h || !h->htable) return NULL; hvalue = avtab_hash(key, h->mask); - for (prev = NULL, cur = h->htable[hvalue]; + for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && @@ -135,7 +172,8 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) return NULL; hvalue = avtab_hash(key, h->mask); - for (cur = h->htable[hvalue]; cur; cur = cur->next) { + for (cur = flex_array_get_ptr(h->htable, hvalue); cur; + cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && @@ -170,7 +208,8 @@ avtab_search_node(struct avtab *h, struct avtab_key *key) return NULL; hvalue = avtab_hash(key, h->mask); - for (cur = h->htable[hvalue]; cur; cur = cur->next) { + for (cur = flex_array_get_ptr(h->htable, hvalue); cur; + cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && @@ -228,15 +267,14 @@ void avtab_destroy(struct avtab *h) return; for (i = 0; i < h->nslot; i++) { - cur = h->htable[i]; + cur = flex_array_get_ptr(h->htable, i); while (cur) { temp = cur; cur = cur->next; kmem_cache_free(avtab_node_cachep, temp); } - h->htable[i] = NULL; } - kfree(h->htable); + flex_array_free(h->htable); h->htable = NULL; h->nslot = 0; h->mask = 0; @@ -251,7 +289,7 @@ int avtab_init(struct avtab *h) int avtab_alloc(struct avtab *h, u32 nrules) { - u16 mask = 0; + u32 mask = 0; u32 shift = 0; u32 work = nrules; u32 nslot = 0; @@ -270,7 +308,8 @@ int avtab_alloc(struct avtab *h, u32 nrules) nslot = MAX_AVTAB_HASH_BUCKETS; mask = nslot - 1; - h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL); + h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot, + GFP_KERNEL | __GFP_ZERO); if (!h->htable) return -ENOMEM; @@ -293,7 +332,7 @@ void avtab_hash_eval(struct avtab *h, char *tag) max_chain_len = 0; chain2_len_sum = 0; for (i = 0; i < h->nslot; i++) { - cur = h->htable[i]; + cur = flex_array_get_ptr(h->htable, i); if (cur) { slots_used++; chain_len = 0; @@ -534,7 +573,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) return rc; for (i = 0; i < a->nslot; i++) { - for (cur = a->htable[i]; cur; cur = cur->next) { + for (cur = flex_array_get_ptr(a->htable, i); cur; + cur = cur->next) { rc = avtab_write_item(p, cur, fp); if (rc) return rc; diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 63ce2f9e441d..adb451cd44f9 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -23,6 +23,8 @@ #ifndef _SS_AVTAB_H_ #define _SS_AVTAB_H_ +#include <linux/flex_array.h> + struct avtab_key { u16 source_type; /* source type */ u16 target_type; /* target type */ @@ -51,10 +53,10 @@ struct avtab_node { }; struct avtab { - struct avtab_node **htable; + struct flex_array *htable; u32 nel; /* number of elements */ u32 nslot; /* number of hash slots */ - u16 mask; /* mask to compute hash func */ + u32 mask; /* mask to compute hash func */ }; @@ -84,7 +86,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified void avtab_cache_init(void); void avtab_cache_destroy(void); -#define MAX_AVTAB_HASH_BITS 11 +#define MAX_AVTAB_HASH_BITS 16 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) #endif /* _SS_AVTAB_H_ */ diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index d307b37ddc2b..e1088842232c 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -654,19 +654,15 @@ int mls_import_netlbl_cat(struct context *context, rc = ebitmap_netlbl_import(&context->range.level[0].cat, secattr->attr.mls.cat); - if (rc != 0) - goto import_netlbl_cat_failure; - - rc = ebitmap_cpy(&context->range.level[1].cat, - &context->range.level[0].cat); - if (rc != 0) + if (rc) goto import_netlbl_cat_failure; + memcpy(&context->range.level[1].cat, &context->range.level[0].cat, + sizeof(context->range.level[0].cat)); return 0; import_netlbl_cat_failure: ebitmap_destroy(&context->range.level[0].cat); - ebitmap_destroy(&context->range.level[1].cat); return rc; } #endif /* CONFIG_NETLABEL */ diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index a1d3944751b9..9e2d82070915 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -3179,13 +3179,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, ctx_new.type = ctx->type; mls_import_netlbl_lvl(&ctx_new, secattr); if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { - rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat, - secattr->attr.mls.cat); + rc = mls_import_netlbl_cat(&ctx_new, secattr); if (rc) goto out; - memcpy(&ctx_new.range.level[1].cat, - &ctx_new.range.level[0].cat, - sizeof(ctx_new.range.level[0].cat)); } rc = -EIDRM; if (!mls_context_isvalid(&policydb, &ctx_new)) diff --git a/security/smack/smack.h b/security/smack/smack.h index 67ccb7b2b89b..49eada6266ec 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -105,6 +105,7 @@ struct task_smack { #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ #define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ +#define SMK_INODE_IMPURE 0x08 /* involved in an impure transaction */ /* * A label access rule. @@ -193,6 +194,10 @@ struct smk_port_label { #define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ #define MAY_BRINGUP 0x00004000 /* Report use of this rule */ +#define SMACK_BRINGUP_ALLOW 1 /* Allow bringup mode */ +#define SMACK_UNCONFINED_SUBJECT 2 /* Allow unconfined label */ +#define SMACK_UNCONFINED_OBJECT 3 /* Allow unconfined label */ + /* * Just to make the common cases easier to deal with */ @@ -254,6 +259,9 @@ extern int smack_cipso_mapped; extern struct smack_known *smack_net_ambient; extern struct smack_known *smack_onlycap; extern struct smack_known *smack_syslog_label; +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +extern struct smack_known *smack_unconfined; +#endif extern struct smack_known smack_cipso_option; extern int smack_ptrace_rule; diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 1158430f5bb9..0f410fc56e33 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -130,7 +130,8 @@ int smk_access(struct smack_known *subject, struct smack_known *object, /* * Hardcoded comparisons. - * + */ + /* * A star subject can't access any object. */ if (subject == &smack_known_star) { @@ -189,10 +190,20 @@ int smk_access(struct smack_known *subject, struct smack_known *object, * succeed because of "b" rules. */ if (may & MAY_BRINGUP) - rc = MAY_BRINGUP; + rc = SMACK_BRINGUP_ALLOW; #endif out_audit: + +#ifdef CONFIG_SECURITY_SMACK_BRINGUP + if (rc < 0) { + if (object == smack_unconfined) + rc = SMACK_UNCONFINED_OBJECT; + if (subject == smack_unconfined) + rc = SMACK_UNCONFINED_SUBJECT; + } +#endif + #ifdef CONFIG_AUDIT if (a) smack_log(subject->smk_known, object->smk_known, @@ -338,19 +349,16 @@ static void smack_log_callback(struct audit_buffer *ab, void *a) void smack_log(char *subject_label, char *object_label, int request, int result, struct smk_audit_info *ad) { +#ifdef CONFIG_SECURITY_SMACK_BRINGUP + char request_buffer[SMK_NUM_ACCESS_TYPE + 5]; +#else char request_buffer[SMK_NUM_ACCESS_TYPE + 1]; +#endif struct smack_audit_data *sad; struct common_audit_data *a = &ad->a; -#ifdef CONFIG_SECURITY_SMACK_BRINGUP - /* - * The result may be positive in bringup mode. - */ - if (result > 0) - result = 0; -#endif /* check if we have to log the current event */ - if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) + if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) return; if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) return; @@ -364,6 +372,21 @@ void smack_log(char *subject_label, char *object_label, int request, smack_str_from_perm(request_buffer, request); sad->subject = subject_label; sad->object = object_label; +#ifdef CONFIG_SECURITY_SMACK_BRINGUP + /* + * The result may be positive in bringup mode. + * A positive result is an allow, but not for normal reasons. + * Mark it as successful, but don't filter it out even if + * the logging policy says to do so. + */ + if (result == SMACK_UNCONFINED_SUBJECT) + strcat(request_buffer, "(US)"); + else if (result == SMACK_UNCONFINED_OBJECT) + strcat(request_buffer, "(UO)"); + + if (result > 0) + result = 0; +#endif sad->request = request_buffer; sad->result = result; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index c934311812f1..69fdc384af30 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -57,6 +57,13 @@ static struct kmem_cache *smack_inode_cache; int smack_enabled; #ifdef CONFIG_SECURITY_SMACK_BRINGUP +static char *smk_bu_mess[] = { + "Bringup Error", /* Unused */ + "Bringup", /* SMACK_BRINGUP_ALLOW */ + "Unconfined Subject", /* SMACK_UNCONFINED_SUBJECT */ + "Unconfined Object", /* SMACK_UNCONFINED_OBJECT */ +}; + static void smk_bu_mode(int mode, char *s) { int i = 0; @@ -87,9 +94,11 @@ static int smk_bu_note(char *note, struct smack_known *sskp, if (rc <= 0) return rc; + if (rc > SMACK_UNCONFINED_OBJECT) + rc = 0; smk_bu_mode(mode, acc); - pr_info("Smack Bringup: (%s %s %s) %s\n", + pr_info("Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc], sskp->smk_known, oskp->smk_known, acc, note); return 0; } @@ -106,9 +115,11 @@ static int smk_bu_current(char *note, struct smack_known *oskp, if (rc <= 0) return rc; + if (rc > SMACK_UNCONFINED_OBJECT) + rc = 0; smk_bu_mode(mode, acc); - pr_info("Smack Bringup: (%s %s %s) %s %s\n", + pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc], tsp->smk_task->smk_known, oskp->smk_known, acc, current->comm, note); return 0; @@ -126,9 +137,11 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc) if (rc <= 0) return rc; + if (rc > SMACK_UNCONFINED_OBJECT) + rc = 0; smk_bu_mode(mode, acc); - pr_info("Smack Bringup: (%s %s %s) %s to %s\n", + pr_info("Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc], tsp->smk_task->smk_known, smk_task->smk_known, acc, current->comm, otp->comm); return 0; @@ -141,14 +154,25 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc) static int smk_bu_inode(struct inode *inode, int mode, int rc) { struct task_smack *tsp = current_security(); + struct inode_smack *isp = inode->i_security; char acc[SMK_NUM_ACCESS_TYPE + 1]; + if (isp->smk_flags & SMK_INODE_IMPURE) + pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n", + inode->i_sb->s_id, inode->i_ino, current->comm); + if (rc <= 0) return rc; + if (rc > SMACK_UNCONFINED_OBJECT) + rc = 0; + if (rc == SMACK_UNCONFINED_SUBJECT && + (mode & (MAY_WRITE | MAY_APPEND))) + isp->smk_flags |= SMK_INODE_IMPURE; smk_bu_mode(mode, acc); - pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n", - tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc, + + pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc], + tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc, inode->i_sb->s_id, inode->i_ino, current->comm); return 0; } @@ -162,13 +186,20 @@ static int smk_bu_file(struct file *file, int mode, int rc) struct task_smack *tsp = current_security(); struct smack_known *sskp = tsp->smk_task; struct inode *inode = file_inode(file); + struct inode_smack *isp = inode->i_security; char acc[SMK_NUM_ACCESS_TYPE + 1]; + if (isp->smk_flags & SMK_INODE_IMPURE) + pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n", + inode->i_sb->s_id, inode->i_ino, current->comm); + if (rc <= 0) return rc; + if (rc > SMACK_UNCONFINED_OBJECT) + rc = 0; smk_bu_mode(mode, acc); - pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", + pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc], sskp->smk_known, smk_of_inode(inode)->smk_known, acc, inode->i_sb->s_id, inode->i_ino, file, current->comm); @@ -185,13 +216,20 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file, struct task_smack *tsp = cred->security; struct smack_known *sskp = tsp->smk_task; struct inode *inode = file->f_inode; + struct inode_smack *isp = inode->i_security; char acc[SMK_NUM_ACCESS_TYPE + 1]; + if (isp->smk_flags & SMK_INODE_IMPURE) + pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n", + inode->i_sb->s_id, inode->i_ino, current->comm); + if (rc <= 0) return rc; + if (rc > SMACK_UNCONFINED_OBJECT) + rc = 0; smk_bu_mode(mode, acc); - pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n", + pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc], sskp->smk_known, smk_of_inode(inode)->smk_known, acc, inode->i_sb->s_id, inode->i_ino, file, current->comm); @@ -1034,19 +1072,16 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +static int smack_inode_getattr(const struct path *path) { struct smk_audit_info ad; - struct path path; + struct inode *inode = path->dentry->d_inode; int rc; - path.dentry = dentry; - path.mnt = mnt; - smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); - smk_ad_setfield_u_fs_path(&ad, path); - rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); - rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); + smk_ad_setfield_u_fs_path(&ad, *path); + rc = smk_curacc(smk_of_inode(inode), MAY_READ, &ad); + rc = smk_bu_inode(inode, MAY_READ, rc); return rc; } @@ -2452,7 +2487,21 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, static int smack_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern) { - if (family != PF_INET || sock->sk == NULL) + struct socket_smack *ssp; + + if (sock->sk == NULL) + return 0; + + /* + * Sockets created by kernel threads receive web label. + */ + if (unlikely(current->flags & PF_KTHREAD)) { + ssp = sock->sk->sk_security; + ssp->smk_in = &smack_known_web; + ssp->smk_out = &smack_known_web; + } + + if (family != PF_INET) return 0; /* * Set the outbound netlbl. @@ -3986,6 +4035,36 @@ static int smack_key_permission(key_ref_t key_ref, rc = smk_bu_note("key access", tkp, keyp->security, request, rc); return rc; } + +/* + * smack_key_getsecurity - Smack label tagging the key + * @key points to the key to be queried + * @_buffer points to a pointer that should be set to point to the + * resulting string (if no label or an error occurs). + * Return the length of the string (including terminating NUL) or -ve if + * an error. + * May also return 0 (and a NULL buffer pointer) if there is no label. + */ +static int smack_key_getsecurity(struct key *key, char **_buffer) +{ + struct smack_known *skp = key->security; + size_t length; + char *copy; + + if (key->security == NULL) { + *_buffer = NULL; + return 0; + } + + copy = kstrdup(skp->smk_known, GFP_KERNEL); + if (copy == NULL) + return -ENOMEM; + length = strlen(copy) + 1; + + *_buffer = copy; + return length; +} + #endif /* CONFIG_KEYS */ /* @@ -4310,6 +4389,7 @@ struct security_operations smack_ops = { .key_alloc = smack_key_alloc, .key_free = smack_key_free, .key_permission = smack_key_permission, + .key_getsecurity = smack_key_getsecurity, #endif /* CONFIG_KEYS */ /* Audit hooks */ diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c index c952632afb0d..a455cfc9ec1f 100644 --- a/security/smack/smack_netfilter.c +++ b/security/smack/smack_netfilter.c @@ -23,9 +23,7 @@ static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) + const struct nf_hook_state *state) { struct socket_smack *ssp; struct smack_known *skp; @@ -42,9 +40,7 @@ static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops, static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops, struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) + const struct nf_hook_state *state) { struct socket_smack *ssp; struct smack_known *skp; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index bce4e8f1b267..06f719ed63c9 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -54,6 +54,9 @@ enum smk_inos { SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */ SMK_SYSLOG = 20, /* change syslog label) */ SMK_PTRACE = 21, /* set ptrace rule */ +#ifdef CONFIG_SECURITY_SMACK_BRINGUP + SMK_UNCONFINED = 22, /* define an unconfined label */ +#endif }; /* @@ -61,7 +64,6 @@ enum smk_inos { */ static DEFINE_MUTEX(smack_cipso_lock); static DEFINE_MUTEX(smack_ambient_lock); -static DEFINE_MUTEX(smack_syslog_lock); static DEFINE_MUTEX(smk_netlbladdr_lock); /* @@ -95,6 +97,16 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT; */ struct smack_known *smack_onlycap; +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +/* + * Allow one label to be unconfined. This is for + * debugging and application bring-up purposes only. + * It is bad and wrong, but everyone seems to expect + * to have it. + */ +struct smack_known *smack_unconfined; +#endif + /* * If this value is set restrict syslog use to the label specified. * It can be reset via smackfs/syslog @@ -1717,6 +1729,85 @@ static const struct file_operations smk_onlycap_ops = { .llseek = default_llseek, }; +#ifdef CONFIG_SECURITY_SMACK_BRINGUP +/** + * smk_read_unconfined - read() for smackfs/unconfined + * @filp: file pointer, not actually used + * @buf: where to put the result + * @cn: maximum to send along + * @ppos: where to start + * + * Returns number of bytes read or error code, as appropriate + */ +static ssize_t smk_read_unconfined(struct file *filp, char __user *buf, + size_t cn, loff_t *ppos) +{ + char *smack = ""; + ssize_t rc = -EINVAL; + int asize; + + if (*ppos != 0) + return 0; + + if (smack_unconfined != NULL) + smack = smack_unconfined->smk_known; + + asize = strlen(smack) + 1; + + if (cn >= asize) + rc = simple_read_from_buffer(buf, cn, ppos, smack, asize); + + return rc; +} + +/** + * smk_write_unconfined - write() for smackfs/unconfined + * @file: file pointer, not actually used + * @buf: where to get the data from + * @count: bytes sent + * @ppos: where to start + * + * Returns number of bytes written or error code, as appropriate + */ +static ssize_t smk_write_unconfined(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + char *data; + int rc = count; + + if (!smack_privileged(CAP_MAC_ADMIN)) + return -EPERM; + + data = kzalloc(count + 1, GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + /* + * Should the null string be passed in unset the unconfined value. + * This seems like something to be careful with as usually + * smk_import only expects to return NULL for errors. It + * is usually the case that a nullstring or "\n" would be + * bad to pass to smk_import but in fact this is useful here. + * + * smk_import will also reject a label beginning with '-', + * so "-confine" will also work. + */ + if (copy_from_user(data, buf, count) != 0) + rc = -EFAULT; + else + smack_unconfined = smk_import_entry(data, count); + + kfree(data); + return rc; +} + +static const struct file_operations smk_unconfined_ops = { + .read = smk_read_unconfined, + .write = smk_write_unconfined, + .llseek = default_llseek, +}; +#endif /* CONFIG_SECURITY_SMACK_BRINGUP */ + /** * smk_read_logging - read() for /smack/logging * @filp: file pointer, not actually used @@ -2384,6 +2475,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR}, [SMK_PTRACE] = { "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR}, +#ifdef CONFIG_SECURITY_SMACK_BRINGUP + [SMK_UNCONFINED] = { + "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR}, +#endif /* last one */ {""} }; diff --git a/security/tomoyo/.gitignore b/security/tomoyo/.gitignore index 5caf1a6f5907..dc0f220a210b 100644 --- a/security/tomoyo/.gitignore +++ b/security/tomoyo/.gitignore @@ -1,2 +1,2 @@ builtin-policy.h -policy/ +policy/*.conf diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig index 604e718d68d3..404dce66952a 100644 --- a/security/tomoyo/Kconfig +++ b/security/tomoyo/Kconfig @@ -6,6 +6,7 @@ config SECURITY_TOMOYO select SECURITY_PATH select SECURITY_NETWORK select SRCU + select BUILD_BIN2C default n help This selects TOMOYO Linux, pathname-based access control. diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 56a0c7be409e..65dbcb2fd850 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile @@ -1,48 +1,15 @@ obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o -$(obj)/policy/profile.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/profile.conf - @touch $@ - -$(obj)/policy/exception_policy.conf: - @mkdir -p $(obj)/policy/ - @echo Creating a default policy/exception_policy.conf - @echo initialize_domain /sbin/modprobe from any >> $@ - @echo initialize_domain /sbin/hotplug from any >> $@ - -$(obj)/policy/domain_policy.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/domain_policy.conf - @touch $@ - -$(obj)/policy/manager.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/manager.conf - @touch $@ - -$(obj)/policy/stat.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/stat.conf - @touch $@ - -$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf - @echo Generating built-in policy for TOMOYO 2.5.x. - @echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_exception_policy[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_domain_policy[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_manager[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_stat[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @mv $@.tmp $@ +targets += builtin-policy.h +define do_policy +echo "static char tomoyo_builtin_$(1)[] __initdata ="; \ +$(objtree)/scripts/basic/bin2c <$(firstword $(wildcard $(obj)/policy/$(1).conf $(srctree)/$(src)/policy/$(1).conf.default) /dev/null); \ +echo ";" +endef +quiet_cmd_policy = POLICY $@ + cmd_policy = ($(call do_policy,profile); $(call do_policy,exception_policy); $(call do_policy,domain_policy); $(call do_policy,manager); $(call do_policy,stat)) >$@ + +$(obj)/builtin-policy.h: $(wildcard $(obj)/policy/*.conf $(src)/policy/*.conf.default) FORCE + $(call if_changed,policy) $(obj)/common.o: $(obj)/builtin-policy.h diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index b897d4862016..f9c9fb1d56b4 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -945,7 +945,7 @@ char *tomoyo_encode2(const char *str, int str_len); char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, va_list args); char *tomoyo_read_token(struct tomoyo_acl_param *param); -char *tomoyo_realpath_from_path(struct path *path); +char *tomoyo_realpath_from_path(const struct path *path); char *tomoyo_realpath_nofollow(const char *pathname); const char *tomoyo_get_exe(void); const char *tomoyo_yesno(const unsigned int value); @@ -978,7 +978,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, struct path *path2); int tomoyo_path_number_perm(const u8 operation, struct path *path, unsigned long number); -int tomoyo_path_perm(const u8 operation, struct path *path, +int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target); unsigned int tomoyo_poll_control(struct file *file, poll_table *wait); unsigned int tomoyo_poll_log(struct file *file, poll_table *wait); diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index c151a1869597..2367b100cc62 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -145,7 +145,7 @@ static void tomoyo_add_slash(struct tomoyo_path_info *buf) * * Returns true on success, false otherwise. */ -static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) +static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path) { buf->name = tomoyo_realpath_from_path(path); if (buf->name) { @@ -782,7 +782,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, * * Returns 0 on success, negative value otherwise. */ -int tomoyo_path_perm(const u8 operation, struct path *path, const char *target) +int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target) { struct tomoyo_request_info r; struct tomoyo_obj_info obj = { diff --git a/security/tomoyo/policy/exception_policy.conf.default b/security/tomoyo/policy/exception_policy.conf.default new file mode 100644 index 000000000000..2678df4964ee --- /dev/null +++ b/security/tomoyo/policy/exception_policy.conf.default @@ -0,0 +1,2 @@ +initialize_domain /sbin/modprobe from any +initialize_domain /sbin/hotplug from any diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index bed745c8b1a3..1e0d480ff6a6 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -89,7 +89,7 @@ char *tomoyo_encode(const char *str) * * If dentry is a directory, trailing '/' is appended. */ -static char *tomoyo_get_absolute_path(struct path *path, char * const buffer, +static char *tomoyo_get_absolute_path(const struct path *path, char * const buffer, const int buflen) { char *pos = ERR_PTR(-ENOMEM); @@ -216,7 +216,7 @@ out: * * Returns the buffer. */ -static char *tomoyo_get_socket_name(struct path *path, char * const buffer, +static char *tomoyo_get_socket_name(const struct path *path, char * const buffer, const int buflen) { struct inode *inode = path->dentry->d_inode; @@ -247,7 +247,7 @@ static char *tomoyo_get_socket_name(struct path *path, char * const buffer, * These functions use kzalloc(), so the caller must call kfree() * if these functions didn't return NULL. */ -char *tomoyo_realpath_from_path(struct path *path) +char *tomoyo_realpath_from_path(const struct path *path) { char *buf = NULL; char *name = NULL; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index f0b756e27fed..57c88d52ffa5 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -144,10 +144,9 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) * * Returns 0 on success, negative value otherwise. */ -static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) +static int tomoyo_inode_getattr(const struct path *path) { - struct path path = { mnt, dentry }; - return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL); + return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL); } /** diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 2952ba576fb9..b974a6997d7f 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -948,15 +948,18 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, */ const char *tomoyo_get_exe(void) { + struct file *exe_file; + const char *cp; struct mm_struct *mm = current->mm; - const char *cp = NULL; if (!mm) return NULL; - down_read(&mm->mmap_sem); - if (mm->exe_file) - cp = tomoyo_realpath_from_path(&mm->exe_file->f_path); - up_read(&mm->mmap_sem); + exe_file = get_mm_exe_file(mm); + if (!exe_file) + return NULL; + + cp = tomoyo_realpath_from_path(&exe_file->f_path); + fput(exe_file); return cp; } diff --git a/security/yama/Kconfig b/security/yama/Kconfig index 20ef5143c0c0..3123e1da2fed 100644 --- a/security/yama/Kconfig +++ b/security/yama/Kconfig @@ -1,8 +1,6 @@ config SECURITY_YAMA bool "Yama support" depends on SECURITY - select SECURITYFS - select SECURITY_PATH default n help This selects Yama, which extends DAC support with additional diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 13c88fbcf037..24aae2ae2b30 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -379,20 +379,17 @@ static struct security_operations yama_ops = { static int yama_dointvec_minmax(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - int rc; + struct ctl_table table_copy; if (write && !capable(CAP_SYS_PTRACE)) return -EPERM; - rc = proc_dointvec_minmax(table, write, buffer, lenp, ppos); - if (rc) - return rc; - /* Lock the max value if it ever gets set. */ - if (write && *(int *)table->data == *(int *)table->extra2) - table->extra1 = table->extra2; + table_copy = *table; + if (*(int *)table_copy.data == *(int *)table_copy.extra2) + table_copy.extra1 = table_copy.extra2; - return rc; + return proc_dointvec_minmax(&table_copy, write, buffer, lenp, ppos); } static int zero; |