Skip to content

Commit

Permalink
[MLSXFRM]: Auto-labeling of child sockets
Browse files Browse the repository at this point in the history
This automatically labels the TCP, Unix stream, and dccp child sockets
as well as openreqs to be at the same MLS level as the peer. This will
result in the selection of appropriately labeled IPSec Security
Associations.

This also uses the sock's sid (as opposed to the isec sid) in SELinux
enforcement of secmark in rcv_skb and postroute_last hooks.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Venkat Yekkirala authored and David S. Miller committed Sep 22, 2006
1 parent cb969f0 commit 4237c75
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 51 deletions.
55 changes: 55 additions & 0 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ extern int cap_netlink_recv(struct sk_buff *skb, int cap);
struct nfsctl_arg;
struct sched_param;
struct swap_info_struct;
struct request_sock;

/* bprm_apply_creds unsafe reasons */
#define LSM_UNSAFE_SHARE 1
Expand Down Expand Up @@ -819,6 +820,14 @@ struct swap_info_struct;
* @sk_getsecid:
* Retrieve the LSM-specific secid for the sock to enable caching of network
* authorizations.
* @sock_graft:
* Sets the socket's isec sid to the sock's sid.
* @inet_conn_request:
* Sets the openreq's sid to socket's sid with MLS portion taken from peer sid.
* @inet_csk_clone:
* Sets the new child socket's sid to the openreq sid.
* @req_classify_flow:
* Sets the flow's sid to the openreq sid.
*
* Security hooks for XFRM operations.
*
Expand Down Expand Up @@ -1358,6 +1367,11 @@ struct security_operations {
void (*sk_free_security) (struct sock *sk);
void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
void (*sk_getsecid) (struct sock *sk, u32 *secid);
void (*sock_graft)(struct sock* sk, struct socket *parent);
int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb,
struct request_sock *req);
void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down Expand Up @@ -2926,6 +2940,28 @@ static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
security_ops->sk_getsecid(sk, &fl->secid);
}

static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
{
security_ops->req_classify_flow(req, fl);
}

static inline void security_sock_graft(struct sock* sk, struct socket *parent)
{
security_ops->sock_graft(sk, parent);
}

static inline int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
return security_ops->inet_conn_request(sk, skb, req);
}

static inline void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
security_ops->inet_csk_clone(newsk, req);
}
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct socket * sock,
struct socket * other,
Expand Down Expand Up @@ -3055,6 +3091,25 @@ static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
{
}

static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
{
}

static inline void security_sock_graft(struct sock* sk, struct socket *parent)
{
}

static inline int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
return 0;
}

static inline void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
}
#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down
1 change: 1 addition & 0 deletions include/net/request_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ struct request_sock {
unsigned long expires;
struct request_sock_ops *rsk_ops;
struct sock *sk;
u32 secid;
};

static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
Expand Down
1 change: 1 addition & 0 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
sk->sk_sleep = &parent->wait;
parent->sk = sk;
sk->sk_socket = parent;
security_sock_graft(sk, parent);
write_unlock_bh(&sk->sk_callback_lock);
}

Expand Down
3 changes: 3 additions & 0 deletions net/dccp/ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)

dccp_openreq_init(req, &dp, skb);

if (security_inet_conn_request(sk, skb, req))
goto drop_and_free;

ireq = inet_rsk(req);
ireq->loc_addr = daddr;
ireq->rmt_addr = saddr;
Expand Down
7 changes: 5 additions & 2 deletions net/dccp/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
fl.oif = ireq6->iif;
fl.fl_ip_dport = inet_rsk(req)->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
security_sk_classify_flow(sk, &fl);
security_req_classify_flow(req, &fl);

if (dst == NULL) {
opt = np->opt;
Expand Down Expand Up @@ -626,7 +626,7 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb,
fl.oif = inet6_iif(rxskb);
fl.fl_ip_dport = dh->dccph_dport;
fl.fl_ip_sport = dh->dccph_sport;
security_skb_classify_flow(rxskb, &fl);
security_req_classify_flow(req, &fl);

if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
Expand Down Expand Up @@ -709,6 +709,9 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)

dccp_openreq_init(req, &dp, skb);

if (security_inet_conn_request(sk, skb, req))
goto drop_and_free;

ireq6 = inet6_rsk(req);
ireq = inet_rsk(req);
ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
Expand Down
4 changes: 3 additions & 1 deletion net/ipv4/inet_connection_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
{ .sport = inet_sk(sk)->sport,
.dport = ireq->rmt_port } } };

security_sk_classify_flow(sk, &fl);
security_req_classify_flow(req, &fl);
if (ip_route_output_flow(&rt, &fl, sk, 0)) {
IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
return NULL;
Expand Down Expand Up @@ -510,6 +510,8 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req,

/* Deinitialize accept_queue to trap illegal accesses. */
memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue));

security_inet_csk_clone(newsk, req);
}
return newsk;
}
Expand Down
6 changes: 5 additions & 1 deletion net/ipv4/syncookies.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
if (!req)
goto out;

if (security_inet_conn_request(sk, skb, req)) {
reqsk_free(req);
goto out;
}
ireq = inet_rsk(req);
treq = tcp_rsk(req);
treq->rcv_isn = htonl(skb->h.th->seq) - 1;
Expand Down Expand Up @@ -259,7 +263,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
.uli_u = { .ports =
{ .sport = skb->h.th->dest,
.dport = skb->h.th->source } } };
security_sk_classify_flow(sk, &fl);
security_req_classify_flow(req, &fl);
if (ip_route_output_key(&rt, &fl)) {
reqsk_free(req);
goto out;
Expand Down
3 changes: 3 additions & 0 deletions net/ipv4/tcp_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)

tcp_openreq_init(req, &tmp_opt, skb);

if (security_inet_conn_request(sk, skb, req))
goto drop_and_free;

ireq = inet_rsk(req);
ireq->loc_addr = daddr;
ireq->rmt_addr = saddr;
Expand Down
6 changes: 4 additions & 2 deletions net/ipv6/tcp_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
fl.oif = treq->iif;
fl.fl_ip_dport = inet_rsk(req)->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
security_sk_classify_flow(sk, &fl);
security_req_classify_flow(req, &fl);

if (dst == NULL) {
opt = np->opt;
Expand Down Expand Up @@ -826,6 +826,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)

tcp_rsk(req)->snt_isn = isn;

security_inet_conn_request(sk, skb, req);

if (tcp_v6_send_synack(sk, req, NULL))
goto drop;

Expand Down Expand Up @@ -929,7 +931,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
fl.oif = sk->sk_bound_dev_if;
fl.fl_ip_dport = inet_rsk(req)->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
security_sk_classify_flow(sk, &fl);
security_req_classify_flow(req, &fl);

if (ip6_dst_lookup(sk, &dst, &fl))
goto out;
Expand Down
24 changes: 24 additions & 0 deletions security/dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,26 @@ static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *
static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid)
{
}

static inline void dummy_sock_graft(struct sock* sk, struct socket *parent)
{
}

static inline int dummy_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
return 0;
}

static inline void dummy_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
}

static inline void dummy_req_classify_flow(const struct request_sock *req,
struct flowi *fl)
{
}
#endif /* CONFIG_SECURITY_NETWORK */

#ifdef CONFIG_SECURITY_NETWORK_XFRM
Expand Down Expand Up @@ -1084,6 +1104,10 @@ void security_fixup_ops (struct security_operations *ops)
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_getsecid);
set_to_dummy_if_null(ops, sock_graft);
set_to_dummy_if_null(ops, inet_conn_request);
set_to_dummy_if_null(ops, inet_csk_clone);
set_to_dummy_if_null(ops, req_classify_flow);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
Expand Down
Loading

0 comments on commit 4237c75

Please sign in to comment.