forked from rubenslte/android_kernel_samsung_msm8226
Merge tag 'v3.4.113' into lineage-16.0
This is the 3.4.113 stable release Change-Id: I80791430656359c5447a675cbff4431362d18df0 Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
committed by
Francescodario Cuzzocrea
parent
36738e5d0d
commit
238a0fb5ad
@@ -205,9 +205,9 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
|
||||
rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
|
||||
&xattr_data,
|
||||
sizeof(xattr_data), 0);
|
||||
}
|
||||
else if (rc == -ENODATA)
|
||||
} else if (rc == -ENODATA && inode->i_op->removexattr) {
|
||||
rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -271,12 +271,23 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
|
||||
* @xattr_value: pointer to the new extended attribute value
|
||||
* @xattr_value_len: pointer to the new extended attribute value length
|
||||
*
|
||||
* Updating 'security.evm' requires CAP_SYS_ADMIN privileges and that
|
||||
* the current value is valid.
|
||||
* Before allowing the 'security.evm' protected xattr to be updated,
|
||||
* verify the existing value is valid. As only the kernel should have
|
||||
* access to the EVM encrypted key needed to calculate the HMAC, prevent
|
||||
* userspace from writing HMAC value. Writing 'security.evm' requires
|
||||
* requires CAP_SYS_ADMIN privileges.
|
||||
*/
|
||||
int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
|
||||
const void *xattr_value, size_t xattr_value_len)
|
||||
{
|
||||
const struct evm_ima_xattr_data *xattr_data = xattr_value;
|
||||
|
||||
if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
|
||||
if (!xattr_value_len)
|
||||
return -EINVAL;
|
||||
if (xattr_data->type != EVM_IMA_XATTR_DIGSIG)
|
||||
return -EPERM;
|
||||
}
|
||||
return evm_protect_xattr(dentry, xattr_name, xattr_value,
|
||||
xattr_value_len);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ static struct ima_measure_rule_entry default_rules[] = {
|
||||
{.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
|
||||
{.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
|
||||
|
||||
@@ -40,12 +40,12 @@ long compat_keyctl_instantiate_key_iov(
|
||||
ARRAY_SIZE(iovstack),
|
||||
iovstack, &iov, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
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;
|
||||
|
||||
@@ -1015,10 +1015,13 @@ static int __init init_encrypted(void)
|
||||
ret = encrypted_shash_alloc();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = aes_get_sizes();
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = register_key_type(&key_type_encrypted);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
return aes_get_sizes();
|
||||
return 0;
|
||||
out:
|
||||
encrypted_shash_release();
|
||||
return ret;
|
||||
|
||||
@@ -1086,12 +1086,12 @@ long keyctl_instantiate_key_iov(key_serial_t id,
|
||||
ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
|
||||
ARRAY_SIZE(iovstack), iovstack, &iov, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
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;
|
||||
|
||||
@@ -54,7 +54,7 @@ int install_user_keyrings(void)
|
||||
|
||||
kenter("%p{%u}", user, user->uid);
|
||||
|
||||
if (user->uid_keyring) {
|
||||
if (user->uid_keyring && user->session_keyring) {
|
||||
kleave(" = 0 [exist]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
+147
-39
@@ -52,6 +52,7 @@
|
||||
#include <net/icmp.h>
|
||||
#include <net/ip.h> /* for local_port_range[] */
|
||||
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
|
||||
#include <net/inet_connection_sock.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netlabel.h>
|
||||
#include <linux/uaccess.h>
|
||||
@@ -1027,7 +1028,7 @@ static void selinux_write_opts(struct seq_file *m,
|
||||
seq_puts(m, prefix);
|
||||
if (has_comma)
|
||||
seq_putc(m, '\"');
|
||||
seq_puts(m, opts->mnt_opts[i]);
|
||||
seq_escape(m, opts->mnt_opts[i], "\"\n\\");
|
||||
if (has_comma)
|
||||
seq_putc(m, '\"');
|
||||
}
|
||||
@@ -1344,15 +1345,33 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
||||
isec->sid = sbsec->sid;
|
||||
|
||||
if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
|
||||
if (opt_dentry) {
|
||||
isec->sclass = inode_mode_to_security_class(inode->i_mode);
|
||||
rc = selinux_proc_get_sid(opt_dentry,
|
||||
isec->sclass,
|
||||
&sid);
|
||||
if (rc)
|
||||
goto out_unlock;
|
||||
isec->sid = sid;
|
||||
}
|
||||
/* We must have a dentry to determine the label on
|
||||
* procfs inodes */
|
||||
if (opt_dentry)
|
||||
/* Called from d_instantiate or
|
||||
* d_splice_alias. */
|
||||
dentry = dget(opt_dentry);
|
||||
else
|
||||
/* Called from selinux_complete_init, try to
|
||||
* find a dentry. */
|
||||
dentry = d_find_alias(inode);
|
||||
/*
|
||||
* This can be hit on boot when a file is accessed
|
||||
* before the policy is loaded. When we load policy we
|
||||
* may find inodes that have no dentry on the
|
||||
* sbsec->isec_head list. No reason to complain as
|
||||
* these will get fixed up the next time we go through
|
||||
* inode_doinit() with a dentry, before these inodes
|
||||
* could be used again by userspace.
|
||||
*/
|
||||
if (!dentry)
|
||||
goto out_unlock;
|
||||
isec->sclass = inode_mode_to_security_class(inode->i_mode);
|
||||
rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
|
||||
dput(dentry);
|
||||
if (rc)
|
||||
goto out_unlock;
|
||||
isec->sid = sid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2291,7 +2310,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
|
||||
int fd;
|
||||
|
||||
j++;
|
||||
i = j * __NFDBITS;
|
||||
i = j * BITS_PER_LONG;
|
||||
fdt = files_fdtable(files);
|
||||
if (i >= fdt->max_fds)
|
||||
break;
|
||||
@@ -3936,7 +3955,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
|
||||
u32 nlbl_sid;
|
||||
u32 nlbl_type;
|
||||
|
||||
selinux_skb_xfrm_sid(skb, &xfrm_sid);
|
||||
selinux_xfrm_skb_sid(skb, &xfrm_sid);
|
||||
selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
|
||||
|
||||
err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
|
||||
@@ -3950,6 +3969,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* selinux_conn_sid - Determine the child socket label for a connection
|
||||
* @sk_sid: the parent socket's SID
|
||||
* @skb_sid: the packet's SID
|
||||
* @conn_sid: the resulting connection SID
|
||||
*
|
||||
* If @skb_sid is valid then the user:role:type information from @sk_sid is
|
||||
* combined with the MLS information from @skb_sid in order to create
|
||||
* @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
|
||||
* of @sk_sid. Returns zero on success, negative values on failure.
|
||||
*
|
||||
*/
|
||||
static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (skb_sid != SECSID_NULL)
|
||||
err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
|
||||
else
|
||||
*conn_sid = sk_sid;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* socket security operations */
|
||||
|
||||
static int socket_sockcreate_sid(const struct task_security_struct *tsec,
|
||||
@@ -4437,8 +4480,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
||||
}
|
||||
err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
|
||||
PEER__RECV, &ad);
|
||||
if (err)
|
||||
if (err) {
|
||||
selinux_netlbl_err(skb, err, 0);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (secmark_active) {
|
||||
@@ -4576,7 +4621,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
int err;
|
||||
u16 family = sk->sk_family;
|
||||
u32 newsid;
|
||||
u32 connsid;
|
||||
u32 peersid;
|
||||
|
||||
/* handle mapped IPv4 packets arriving via IPv6 sockets */
|
||||
@@ -4586,16 +4631,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||
err = selinux_skb_peerlbl_sid(skb, family, &peersid);
|
||||
if (err)
|
||||
return err;
|
||||
if (peersid == SECSID_NULL) {
|
||||
req->secid = sksec->sid;
|
||||
req->peer_secid = SECSID_NULL;
|
||||
} else {
|
||||
err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
|
||||
if (err)
|
||||
return err;
|
||||
req->secid = newsid;
|
||||
req->peer_secid = peersid;
|
||||
}
|
||||
err = selinux_conn_sid(sksec->sid, peersid, &connsid);
|
||||
if (err)
|
||||
return err;
|
||||
req->secid = connsid;
|
||||
req->peer_secid = peersid;
|
||||
|
||||
return selinux_netlbl_inet_conn_request(req, family);
|
||||
}
|
||||
@@ -4831,6 +4871,7 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
|
||||
static unsigned int selinux_ip_output(struct sk_buff *skb,
|
||||
u16 family)
|
||||
{
|
||||
struct sock *sk;
|
||||
u32 sid;
|
||||
|
||||
if (!netlbl_enabled())
|
||||
@@ -4839,8 +4880,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
|
||||
/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
|
||||
* because we want to make sure we apply the necessary labeling
|
||||
* before IPsec is applied so we can leverage AH protection */
|
||||
if (skb->sk) {
|
||||
struct sk_security_struct *sksec = skb->sk->sk_security;
|
||||
sk = skb->sk;
|
||||
if (sk) {
|
||||
struct sk_security_struct *sksec;
|
||||
|
||||
if (sk->sk_state == TCP_LISTEN)
|
||||
/* if the socket is the listening state then this
|
||||
* packet is a SYN-ACK packet which means it needs to
|
||||
* be labeled based on the connection/request_sock and
|
||||
* not the parent socket. unfortunately, we can't
|
||||
* lookup the request_sock yet as it isn't queued on
|
||||
* the parent socket until after the SYN-ACK is sent.
|
||||
* the "solution" is to simply pass the packet as-is
|
||||
* as any IP option based labeling should be copied
|
||||
* from the initial connection request (in the IP
|
||||
* layer). it is far from ideal, but until we get a
|
||||
* security label in the packet itself this is the
|
||||
* best we can do. */
|
||||
return NF_ACCEPT;
|
||||
|
||||
/* standard practice, label using the parent socket */
|
||||
sksec = sk->sk_security;
|
||||
sid = sksec->sid;
|
||||
} else
|
||||
sid = SECINITSID_KERNEL;
|
||||
@@ -4913,27 +4973,37 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
|
||||
* as fast and as clean as possible. */
|
||||
if (!selinux_policycap_netpeer)
|
||||
return selinux_ip_postroute_compat(skb, ifindex, family);
|
||||
|
||||
secmark_active = selinux_secmark_enabled();
|
||||
peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
|
||||
if (!secmark_active && !peerlbl_active)
|
||||
return NF_ACCEPT;
|
||||
|
||||
sk = skb->sk;
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
|
||||
* packet transformation so allow the packet to pass without any checks
|
||||
* since we'll have another chance to perform access control checks
|
||||
* when the packet is on it's final way out.
|
||||
* NOTE: there appear to be some IPv6 multicast cases where skb->dst
|
||||
* is NULL, in this case go ahead and apply access control. */
|
||||
if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
|
||||
* is NULL, in this case go ahead and apply access control.
|
||||
* is NULL, in this case go ahead and apply access control.
|
||||
* NOTE: if this is a local socket (skb->sk != NULL) that is in the
|
||||
* TCP listening state we cannot wait until the XFRM processing
|
||||
* is done as we will miss out on the SA label if we do;
|
||||
* unfortunately, this means more work, but it is only once per
|
||||
* connection. */
|
||||
if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
|
||||
!(sk != NULL && sk->sk_state == TCP_LISTEN))
|
||||
return NF_ACCEPT;
|
||||
#endif
|
||||
secmark_active = selinux_secmark_enabled();
|
||||
peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
|
||||
if (!secmark_active && !peerlbl_active)
|
||||
return NF_ACCEPT;
|
||||
|
||||
/* if the packet is being forwarded then get the peer label from the
|
||||
* packet itself; otherwise check to see if it is from a local
|
||||
* application or the kernel, if from an application get the peer label
|
||||
* from the sending socket, otherwise use the kernel's sid */
|
||||
sk = skb->sk;
|
||||
if (sk == NULL) {
|
||||
/* Without an associated socket the packet is either coming
|
||||
* from the kernel or it is being forwarded; check the packet
|
||||
* to determine which and if the packet is being forwarded
|
||||
* query the packet directly to determine the security label. */
|
||||
if (skb->skb_iif) {
|
||||
secmark_perm = PACKET__FORWARD_OUT;
|
||||
if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
|
||||
@@ -4942,7 +5012,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
|
||||
secmark_perm = PACKET__SEND;
|
||||
peer_sid = SECINITSID_KERNEL;
|
||||
}
|
||||
} else if (sk->sk_state == TCP_LISTEN) {
|
||||
/* Locally generated packet but the associated socket is in the
|
||||
* listening state which means this is a SYN-ACK packet. In
|
||||
* this particular case the correct security label is assigned
|
||||
* to the connection/request_sock but unfortunately we can't
|
||||
* query the request_sock as it isn't queued on the parent
|
||||
* socket until after the SYN-ACK packet is sent; the only
|
||||
* viable choice is to regenerate the label like we do in
|
||||
* selinux_inet_conn_request(). See also selinux_ip_output()
|
||||
* for similar problems. */
|
||||
u32 skb_sid;
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
|
||||
return NF_DROP;
|
||||
/* At this point, if the returned skb peerlbl is SECSID_NULL
|
||||
* and the packet has been through at least one XFRM
|
||||
* transformation then we must be dealing with the "final"
|
||||
* form of labeled IPsec packet; since we've already applied
|
||||
* all of our access controls on this packet we can safely
|
||||
* pass the packet. */
|
||||
if (skb_sid == SECSID_NULL) {
|
||||
switch (family) {
|
||||
case PF_INET:
|
||||
if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
|
||||
return NF_ACCEPT;
|
||||
break;
|
||||
case PF_INET6:
|
||||
if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
|
||||
return NF_ACCEPT;
|
||||
default:
|
||||
return NF_DROP_ERR(-ECONNREFUSED);
|
||||
}
|
||||
}
|
||||
if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
|
||||
return NF_DROP;
|
||||
secmark_perm = PACKET__SEND;
|
||||
} else {
|
||||
/* Locally generated packet, fetch the security label from the
|
||||
* associated socket. */
|
||||
struct sk_security_struct *sksec = sk->sk_security;
|
||||
peer_sid = sksec->sid;
|
||||
secmark_perm = PACKET__SEND;
|
||||
@@ -5610,11 +5718,11 @@ static int selinux_setprocattr(struct task_struct *p,
|
||||
/* Check for ptracing, and update the task SID if ok.
|
||||
Otherwise, leave SID unchanged and fail. */
|
||||
ptsid = 0;
|
||||
task_lock(p);
|
||||
rcu_read_lock();
|
||||
tracer = ptrace_parent(p);
|
||||
if (tracer)
|
||||
ptsid = task_sid(tracer);
|
||||
task_unlock(p);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (tracer) {
|
||||
error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
|
||||
|
||||
@@ -38,10 +38,10 @@ struct task_security_struct {
|
||||
|
||||
struct inode_security_struct {
|
||||
struct inode *inode; /* back pointer to inode object */
|
||||
|
||||
union {
|
||||
struct list_head list; /* list of inode_security_struct */
|
||||
struct rcu_head rcu; /* for freeing the inode_security_struct */
|
||||
|
||||
};
|
||||
u32 task_sid; /* SID of creating task */
|
||||
u32 sid; /* SID of this object */
|
||||
u16 sclass; /* security class of this object */
|
||||
|
||||
@@ -47,6 +47,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
|
||||
int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
|
||||
struct common_audit_data *ad, u8 proto);
|
||||
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
|
||||
int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid);
|
||||
|
||||
static inline void selinux_xfrm_notify_policyload(void)
|
||||
{
|
||||
@@ -79,12 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int
|
||||
static inline void selinux_xfrm_notify_policyload(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
|
||||
{
|
||||
*sid = SECSID_NULL;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
|
||||
{
|
||||
int err = selinux_xfrm_decode_session(skb, sid, 0);
|
||||
BUG_ON(err);
|
||||
}
|
||||
|
||||
#endif /* _SELINUX_XFRM_H_ */
|
||||
|
||||
@@ -442,8 +442,7 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
|
||||
sksec->nlbl_state != NLBL_CONNLABELED)
|
||||
return 0;
|
||||
|
||||
local_bh_disable();
|
||||
bh_lock_sock_nested(sk);
|
||||
lock_sock(sk);
|
||||
|
||||
/* connected sockets are allowed to disconnect when the address family
|
||||
* is set to AF_UNSPEC, if that is what is happening we want to reset
|
||||
@@ -464,7 +463,6 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
|
||||
sksec->nlbl_state = NLBL_CONNLABELED;
|
||||
|
||||
socket_connect_return:
|
||||
bh_unlock_sock(sk);
|
||||
local_bh_enable();
|
||||
release_sock(sk);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node)
|
||||
if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
|
||||
struct sel_netnode *tail;
|
||||
tail = list_entry(
|
||||
rcu_dereference(sel_netnode_hash[idx].list.prev),
|
||||
rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
|
||||
lockdep_is_held(&sel_netnode_lock)),
|
||||
struct sel_netnode, list);
|
||||
list_del_rcu(&tail->list);
|
||||
kfree_rcu(tail, rcu);
|
||||
|
||||
@@ -103,6 +103,12 @@ 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_GETSPDINFO, NETLINK_XFRM_SOCKET__NLMSG_READ },
|
||||
{ XFRM_MSG_MAPPING, NETLINK_XFRM_SOCKET__NLMSG_READ },
|
||||
};
|
||||
|
||||
static struct nlmsg_perm nlmsg_audit_perms[] =
|
||||
|
||||
@@ -158,7 +158,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
|
||||
goto out;
|
||||
|
||||
/* No partial writes. */
|
||||
length = EINVAL;
|
||||
length = -EINVAL;
|
||||
if (*ppos != 0)
|
||||
goto out;
|
||||
|
||||
@@ -1221,7 +1221,7 @@ static void sel_remove_entries(struct dentry *de)
|
||||
spin_lock(&de->d_lock);
|
||||
node = de->d_subdirs.next;
|
||||
while (node != &de->d_subdirs) {
|
||||
struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
|
||||
struct dentry *d = list_entry(node, struct dentry, d_child);
|
||||
|
||||
spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
|
||||
list_del_init(node);
|
||||
@@ -1262,6 +1262,7 @@ static int sel_make_bools(void)
|
||||
kfree(bool_pending_names[i]);
|
||||
kfree(bool_pending_names);
|
||||
kfree(bool_pending_values);
|
||||
bool_num = 0;
|
||||
bool_pending_names = NULL;
|
||||
bool_pending_values = NULL;
|
||||
|
||||
@@ -1723,12 +1724,12 @@ static void sel_remove_classes(void)
|
||||
|
||||
list_for_each(class_node, &class_dir->d_subdirs) {
|
||||
struct dentry *class_subdir = list_entry(class_node,
|
||||
struct dentry, d_u.d_child);
|
||||
struct dentry, d_child);
|
||||
struct list_head *class_subdir_node;
|
||||
|
||||
list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
|
||||
struct dentry *d = list_entry(class_subdir_node,
|
||||
struct dentry, d_u.d_child);
|
||||
struct dentry, d_child);
|
||||
|
||||
if (d->d_inode)
|
||||
if (d->d_inode->i_mode & S_IFDIR)
|
||||
|
||||
@@ -2000,7 +2000,19 @@ static int filename_trans_read(struct policydb *p, void *fp)
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
hashtab_insert(p->filename_trans, ft, otype);
|
||||
rc = hashtab_insert(p->filename_trans, ft, otype);
|
||||
if (rc) {
|
||||
/*
|
||||
* Do not return -EEXIST to the caller, or the system
|
||||
* will not boot.
|
||||
*/
|
||||
if (rc != -EEXIST)
|
||||
goto out;
|
||||
/* But free memory to avoid memory leak. */
|
||||
kfree(ft);
|
||||
kfree(name);
|
||||
kfree(otype);
|
||||
}
|
||||
}
|
||||
hash_eval(p->filename_trans, "filenametr");
|
||||
return 0;
|
||||
@@ -3329,10 +3341,10 @@ static int filename_write_helper(void *key, void *data, void *ptr)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
buf[0] = ft->stype;
|
||||
buf[1] = ft->ttype;
|
||||
buf[2] = ft->tclass;
|
||||
buf[3] = otype->otype;
|
||||
buf[0] = cpu_to_le32(ft->stype);
|
||||
buf[1] = cpu_to_le32(ft->ttype);
|
||||
buf[2] = cpu_to_le32(ft->tclass);
|
||||
buf[3] = cpu_to_le32(otype->otype);
|
||||
|
||||
rc = put_entry(buf, sizeof(u32), 4, fp);
|
||||
if (rc)
|
||||
|
||||
+43
-12
@@ -152,21 +152,13 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* LSM hook implementation that checks and/or returns the xfrm sid for the
|
||||
* incoming packet.
|
||||
*/
|
||||
|
||||
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
|
||||
static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb,
|
||||
u32 *sid, int ckall)
|
||||
{
|
||||
struct sec_path *sp;
|
||||
struct sec_path *sp = skb->sp;
|
||||
|
||||
*sid = SECSID_NULL;
|
||||
|
||||
if (skb == NULL)
|
||||
return 0;
|
||||
|
||||
sp = skb->sp;
|
||||
if (sp) {
|
||||
int i, sid_set = 0;
|
||||
|
||||
@@ -190,6 +182,45 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)
|
||||
{
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct xfrm_state *x;
|
||||
|
||||
if (dst == NULL)
|
||||
return SECSID_NULL;
|
||||
x = dst->xfrm;
|
||||
if (x == NULL || !selinux_authorizable_xfrm(x))
|
||||
return SECSID_NULL;
|
||||
|
||||
return x->security->ctx_sid;
|
||||
}
|
||||
|
||||
/*
|
||||
* LSM hook implementation that checks and/or returns the xfrm sid for the
|
||||
* incoming packet.
|
||||
*/
|
||||
|
||||
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
|
||||
{
|
||||
if (skb == NULL) {
|
||||
*sid = SECSID_NULL;
|
||||
return 0;
|
||||
}
|
||||
return selinux_xfrm_skb_sid_ingress(skb, sid, ckall);
|
||||
}
|
||||
|
||||
int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0);
|
||||
if (rc == 0 && *sid == SECSID_NULL)
|
||||
*sid = selinux_xfrm_skb_sid_egress(skb);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Security blob allocation for xfrm_policy and xfrm_state
|
||||
* CTX does not have a meaningful value on input
|
||||
@@ -310,7 +341,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
|
||||
|
||||
if (old_ctx) {
|
||||
new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
|
||||
GFP_KERNEL);
|
||||
GFP_ATOMIC);
|
||||
if (!new_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -298,6 +298,16 @@ static inline char *smk_of_current(void)
|
||||
return smk_of_task(current_security());
|
||||
}
|
||||
|
||||
static inline char *smk_of_task_struct(const struct task_struct *t)
|
||||
{
|
||||
char *skp;
|
||||
|
||||
rcu_read_lock();
|
||||
skp = smk_of_task(__task_cred(t)->security);
|
||||
rcu_read_unlock();
|
||||
return skp;
|
||||
}
|
||||
|
||||
/*
|
||||
* logging functions
|
||||
*/
|
||||
|
||||
+13
-11
@@ -41,8 +41,6 @@
|
||||
#include <linux/binfmts.h>
|
||||
#include "smack.h"
|
||||
|
||||
#define task_security(task) (task_cred_xxx((task), security))
|
||||
|
||||
#define TRANS_TRUE "TRUE"
|
||||
#define TRANS_TRUE_SIZE 4
|
||||
|
||||
@@ -164,7 +162,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
tsp = smk_of_task(task_security(ctp));
|
||||
tsp = smk_of_task_struct(ctp);
|
||||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||
smk_ad_setfield_u_tsk(&ad, ctp);
|
||||
|
||||
@@ -190,7 +188,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
tsp = smk_of_task(task_security(ptp));
|
||||
tsp = smk_of_task_struct(ptp);
|
||||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||
smk_ad_setfield_u_tsk(&ad, ptp);
|
||||
|
||||
@@ -1518,7 +1516,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access,
|
||||
|
||||
smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK);
|
||||
smk_ad_setfield_u_tsk(&ad, p);
|
||||
return smk_curacc(smk_of_task(task_security(p)), access, &ad);
|
||||
return smk_curacc(smk_of_task_struct(p), access, &ad);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1564,7 +1562,7 @@ static int smack_task_getsid(struct task_struct *p)
|
||||
*/
|
||||
static void smack_task_getsecid(struct task_struct *p, u32 *secid)
|
||||
{
|
||||
*secid = smack_to_secid(smk_of_task(task_security(p)));
|
||||
*secid = smack_to_secid(smk_of_task_struct(p));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1676,7 +1674,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
|
||||
* can write the receiver.
|
||||
*/
|
||||
if (secid == 0)
|
||||
return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE,
|
||||
return smk_curacc(smk_of_task_struct(p), MAY_WRITE,
|
||||
&ad);
|
||||
/*
|
||||
* If the secid isn't 0 we're dealing with some USB IO
|
||||
@@ -1684,7 +1682,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
|
||||
* we can't take privilege into account.
|
||||
*/
|
||||
return smk_access(smack_from_secid(secid),
|
||||
smk_of_task(task_security(p)), MAY_WRITE, &ad);
|
||||
smk_of_task_struct(p), MAY_WRITE, &ad);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1697,9 +1695,13 @@ static int smack_task_wait(struct task_struct *p)
|
||||
{
|
||||
struct smk_audit_info ad;
|
||||
char *sp = smk_of_current();
|
||||
char *tsp = smk_of_forked(task_security(p));
|
||||
char *tsp;
|
||||
int rc;
|
||||
|
||||
rcu_read_lock();
|
||||
tsp = smk_of_forked(__task_cred(p)->security);
|
||||
rcu_read_unlock();
|
||||
|
||||
/* we don't log here, we can be overriden */
|
||||
rc = smk_access(tsp, sp, MAY_WRITE, NULL);
|
||||
if (rc == 0)
|
||||
@@ -1736,7 +1738,7 @@ static int smack_task_wait(struct task_struct *p)
|
||||
static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
|
||||
{
|
||||
struct inode_smack *isp = inode->i_security;
|
||||
isp->smk_inode = smk_of_task(task_security(p));
|
||||
isp->smk_inode = smk_of_task_struct(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2719,7 +2721,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
|
||||
if (strcmp(name, "current") != 0)
|
||||
return -EINVAL;
|
||||
|
||||
cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL);
|
||||
cp = kstrdup(smk_of_task_struct(p), GFP_KERNEL);
|
||||
if (cp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
if (arg2 == 0) {
|
||||
yama_ptracer_del(NULL, myself);
|
||||
rc = 0;
|
||||
} else if (arg2 == PR_SET_PTRACER_ANY) {
|
||||
} else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) {
|
||||
rc = yama_ptracer_add(NULL, myself);
|
||||
} else {
|
||||
struct task_struct *tracer;
|
||||
|
||||
Reference in New Issue
Block a user