* which is used to copy security attributes between local stream sockets.
* @sk_free_security:
* Deallocate security structure.
+ * @sk_clone_security:
+ * Clone/copy security structure.
* @sk_getsid:
* Retrieve the LSM-specific sid for the sock to enable caching of network
* authorizations.
int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid);
int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
void (*sk_free_security) (struct sock *sk);
+ void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir);
#endif /* CONFIG_SECURITY_NETWORK */
return security_ops->sk_free_security(sk);
}
+static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
+{
+ return security_ops->sk_clone_security(sk, newsk);
+}
+
static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir)
{
return security_ops->sk_getsid(sk, fl, dir);
{
}
+static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
+{
+}
+
static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir)
{
return 0;
write_unlock_bh(&sk->sk_callback_lock);
}
+static inline void sock_copy(struct sock *nsk, const struct sock *osk)
+{
+#ifdef CONFIG_SECURITY_NETWORK
+ void *sptr = nsk->sk_security;
+#endif
+
+ memcpy(nsk, osk, osk->sk_prot->obj_size);
+#ifdef CONFIG_SECURITY_NETWORK
+ nsk->sk_security = sptr;
+ security_sk_clone(osk, nsk);
+#endif
+}
+
extern int sock_i_uid(struct sock *sk);
extern unsigned long sock_i_ino(struct sock *sk);
if (newsk != NULL) {
struct sk_filter *filter;
- memcpy(newsk, sk, sk->sk_prot->obj_size);
+ sock_copy(newsk, sk);
/* SANITY */
sk_node_init(&newsk->sk_node);
{
}
+static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *newsk)
+{
+}
+
static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir)
{
return 0;
set_to_dummy_if_null(ops, socket_getpeersec_dgram);
set_to_dummy_if_null(ops, sk_alloc_security);
set_to_dummy_if_null(ops, sk_free_security);
+ set_to_dummy_if_null(ops, sk_clone_security);
set_to_dummy_if_null(ops, sk_getsid);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
{
struct sk_security_struct *ssec;
- if (family != PF_UNIX)
- return 0;
-
ssec = kzalloc(sizeof(*ssec), priority);
if (!ssec)
return -ENOMEM;
ssec->sk = sk;
ssec->peer_sid = SECINITSID_UNLABELED;
+ ssec->sid = SECINITSID_UNLABELED;
sk->sk_security = ssec;
return 0;
{
struct sk_security_struct *ssec = sk->sk_security;
- if (sk->sk_family != PF_UNIX)
- return;
-
sk->sk_security = NULL;
kfree(ssec);
}
{
struct inode_security_struct *isec;
struct task_security_struct *tsec;
+ struct sk_security_struct *sksec;
u32 newsid;
isec = SOCK_INODE(sock)->i_security;
isec->sid = kern ? SECINITSID_KERNEL : newsid;
isec->initialized = 1;
+ if (sock->sk) {
+ sksec = sock->sk->sk_security;
+ sksec->sid = isec->sid;
+ }
+
return;
}
sk_free_security(sk);
}
-static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir)
+static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
{
- struct inode_security_struct *isec;
- u32 sock_sid = SECINITSID_ANY_SOCKET;
+ struct sk_security_struct *ssec = sk->sk_security;
+ struct sk_security_struct *newssec = newsk->sk_security;
+ newssec->sid = ssec->sid;
+ newssec->peer_sid = ssec->peer_sid;
+}
+
+static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir)
+{
if (!sk)
return selinux_no_sk_sid(fl);
+ else {
+ struct sk_security_struct *sksec = sk->sk_security;
- read_lock_bh(&sk->sk_callback_lock);
- isec = get_sock_isec(sk);
-
- if (isec)
- sock_sid = isec->sid;
-
- read_unlock_bh(&sk->sk_callback_lock);
- return sock_sid;
+ return sksec->sid;
+ }
}
static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
.socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
.sk_alloc_security = selinux_sk_alloc_security,
.sk_free_security = selinux_sk_free_security,
+ .sk_clone_security = selinux_sk_clone_security,
.sk_getsid = selinux_sk_getsid_security,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
struct sk_security_struct {
struct sock *sk; /* back pointer to sk object */
+ u32 sid; /* SID of this object */
u32 peer_sid; /* SID of peer */
};