Skip to content

Commit a2af031

Browse files
cschauflerCasey Schaufler
authored andcommitted
Smack: Set socket labels only once
Refactor the IP send checks so that the netlabel value is set only when necessary, not on every send. Some functions get renamed as the changes made the old name misleading. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
1 parent 36be812 commit a2af031

2 files changed

Lines changed: 98 additions & 89 deletions

File tree

security/smack/smack.h

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ struct socket_smack {
100100
struct smack_known *smk_out; /* outbound label */
101101
struct smack_known *smk_in; /* inbound label */
102102
struct smack_known *smk_packet; /* TCP peer label */
103+
int smk_state; /* netlabel socket states */
103104
};
105+
#define SMK_NETLBL_UNSET 0
106+
#define SMK_NETLBL_UNLABELED 1
107+
#define SMK_NETLBL_LABELED 2
108+
#define SMK_NETLBL_REQSKB 3
104109

105110
/*
106111
* Inode smack data
@@ -196,19 +201,6 @@ enum {
196201
#define SMACK_DELETE_OPTION "-DELETE"
197202
#define SMACK_CIPSO_OPTION "-CIPSO"
198203

199-
/*
200-
* How communications on this socket are treated.
201-
* Usually it's determined by the underlying netlabel code
202-
* but there are certain cases, including single label hosts
203-
* and potentially single label interfaces for which the
204-
* treatment can not be known in advance.
205-
*
206-
* The possibility of additional labeling schemes being
207-
* introduced in the future exists as well.
208-
*/
209-
#define SMACK_UNLABELED_SOCKET 0
210-
#define SMACK_CIPSO_SOCKET 1
211-
212204
/*
213205
* CIPSO defaults.
214206
*/

security/smack/smack_lsm.c

Lines changed: 93 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,38 +2383,31 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
23832383
}
23842384

23852385
/**
2386-
* smack_netlabel - Set the secattr on a socket
2386+
* smack_netlbl_add - Set the secattr on a socket
23872387
* @sk: the socket
2388-
* @labeled: socket label scheme
23892388
*
2390-
* Convert the outbound smack value (smk_out) to a
2391-
* secattr and attach it to the socket.
2389+
* Attach the outbound smack value (smk_out) to the socket.
23922390
*
23932391
* Returns 0 on success or an error code
23942392
*/
2395-
static int smack_netlabel(struct sock *sk, int labeled)
2393+
static int smack_netlbl_add(struct sock *sk)
23962394
{
2397-
struct smack_known *skp;
23982395
struct socket_smack *ssp = sk->sk_security;
2399-
int rc = 0;
2396+
struct smack_known *skp = ssp->smk_out;
2397+
int rc;
24002398

2401-
/*
2402-
* Usually the netlabel code will handle changing the
2403-
* packet labeling based on the label.
2404-
* The case of a single label host is different, because
2405-
* a single label host should never get a labeled packet
2406-
* even though the label is usually associated with a packet
2407-
* label.
2408-
*/
24092399
local_bh_disable();
24102400
bh_lock_sock_nested(sk);
24112401

2412-
if (ssp->smk_out == smack_net_ambient ||
2413-
labeled == SMACK_UNLABELED_SOCKET)
2414-
netlbl_sock_delattr(sk);
2415-
else {
2416-
skp = ssp->smk_out;
2417-
rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
2402+
rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
2403+
switch (rc) {
2404+
case 0:
2405+
ssp->smk_state = SMK_NETLBL_LABELED;
2406+
break;
2407+
case -EDESTADDRREQ:
2408+
ssp->smk_state = SMK_NETLBL_REQSKB;
2409+
rc = 0;
2410+
break;
24182411
}
24192412

24202413
bh_unlock_sock(sk);
@@ -2424,7 +2417,31 @@ static int smack_netlabel(struct sock *sk, int labeled)
24242417
}
24252418

24262419
/**
2427-
* smack_netlbel_send - Set the secattr on a socket and perform access checks
2420+
* smack_netlbl_delete - Remove the secattr from a socket
2421+
* @sk: the socket
2422+
*
2423+
* Remove the outbound smack value from a socket
2424+
*/
2425+
static void smack_netlbl_delete(struct sock *sk)
2426+
{
2427+
struct socket_smack *ssp = sk->sk_security;
2428+
2429+
/*
2430+
* Take the label off the socket if one is set.
2431+
*/
2432+
if (ssp->smk_state != SMK_NETLBL_LABELED)
2433+
return;
2434+
2435+
local_bh_disable();
2436+
bh_lock_sock_nested(sk);
2437+
netlbl_sock_delattr(sk);
2438+
bh_unlock_sock(sk);
2439+
local_bh_enable();
2440+
ssp->smk_state = SMK_NETLBL_UNLABELED;
2441+
}
2442+
2443+
/**
2444+
* smk_ipv4_check - Perform IPv4 host access checks
24282445
* @sk: the socket
24292446
* @sap: the destination address
24302447
*
@@ -2434,11 +2451,10 @@ static int smack_netlabel(struct sock *sk, int labeled)
24342451
* Returns 0 on success or an error code.
24352452
*
24362453
*/
2437-
static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
2454+
static int smk_ipv4_check(struct sock *sk, struct sockaddr_in *sap)
24382455
{
24392456
struct smack_known *skp;
2440-
int rc;
2441-
int sk_lbl;
2457+
int rc = 0;
24422458
struct smack_known *hkp;
24432459
struct socket_smack *ssp = sk->sk_security;
24442460
struct smk_audit_info ad;
@@ -2454,19 +2470,18 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
24542470
ad.a.u.net->dport = sap->sin_port;
24552471
ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
24562472
#endif
2457-
sk_lbl = SMACK_UNLABELED_SOCKET;
24582473
skp = ssp->smk_out;
24592474
rc = smk_access(skp, hkp, MAY_WRITE, &ad);
24602475
rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc);
2461-
} else {
2462-
sk_lbl = SMACK_CIPSO_SOCKET;
2463-
rc = 0;
2476+
/*
2477+
* Clear the socket netlabel if it's set.
2478+
*/
2479+
if (!rc)
2480+
smack_netlbl_delete(sk);
24642481
}
24652482
rcu_read_unlock();
2466-
if (rc != 0)
2467-
return rc;
24682483

2469-
return smack_netlabel(sk, sk_lbl);
2484+
return rc;
24702485
}
24712486

24722487
/**
@@ -2703,7 +2718,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
27032718
else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
27042719
ssp->smk_out = skp;
27052720
if (sock->sk->sk_family == PF_INET) {
2706-
rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
2721+
rc = smack_netlbl_add(sock->sk);
27072722
if (rc != 0)
27082723
printk(KERN_WARNING
27092724
"Smack: \"%s\" netlbl error %d.\n",
@@ -2754,7 +2769,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
27542769
/*
27552770
* Set the outbound netlbl.
27562771
*/
2757-
return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
2772+
return smack_netlbl_add(sock->sk);
27582773
}
27592774

27602775
/**
@@ -2845,7 +2860,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
28452860
}
28462861
if (sap->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
28472862
return 0;
2848-
rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
2863+
rc = smk_ipv4_check(sock->sk, (struct sockaddr_in *)sap);
28492864
return rc;
28502865
}
28512866

@@ -3663,7 +3678,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
36633678
if (msg->msg_namelen < sizeof(struct sockaddr_in) ||
36643679
sip->sin_family != AF_INET)
36653680
return -EINVAL;
3666-
rc = smack_netlabel_send(sock->sk, sip);
3681+
rc = smk_ipv4_check(sock->sk, sip);
36673682
break;
36683683
#if IS_ENABLED(CONFIG_IPV6)
36693684
case AF_INET6:
@@ -3824,6 +3839,33 @@ static struct smack_known *smack_from_skb(struct sk_buff *skb)
38243839
return smack_from_secid(skb->secmark);
38253840
}
38263841

3842+
/**
3843+
* smack_from_netlbl - Smack data from the IP options in an skb
3844+
* @sk: socket data came in on
3845+
* @family: address family
3846+
* @skb: packet
3847+
*
3848+
* Returns smack_known of the IP options or NULL if that won't work.
3849+
*/
3850+
static struct smack_known *smack_from_netlbl(struct sock *sk, u16 family,
3851+
struct sk_buff *skb)
3852+
{
3853+
struct netlbl_lsm_secattr secattr;
3854+
struct socket_smack *ssp = NULL;
3855+
struct smack_known *skp = NULL;
3856+
3857+
netlbl_secattr_init(&secattr);
3858+
3859+
if (sk)
3860+
ssp = sk->sk_security;
3861+
if (netlbl_skbuff_getattr(skb, family, &secattr) == 0)
3862+
skp = smack_from_secattr(&secattr, ssp);
3863+
3864+
netlbl_secattr_destroy(&secattr);
3865+
3866+
return skp;
3867+
}
3868+
38273869
/**
38283870
* smack_socket_sock_rcv_skb - Smack packet delivery access check
38293871
* @sk: socket
@@ -3833,7 +3875,6 @@ static struct smack_known *smack_from_skb(struct sk_buff *skb)
38333875
*/
38343876
static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
38353877
{
3836-
struct netlbl_lsm_secattr secattr;
38373878
struct socket_smack *ssp = sk->sk_security;
38383879
struct smack_known *skp = NULL;
38393880
int rc = 0;
@@ -3858,22 +3899,11 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
38583899
* The secmark is assumed to reflect policy better.
38593900
*/
38603901
skp = smack_from_skb(skb);
3861-
if (skp)
3862-
goto access_check;
3863-
/*
3864-
* Translate what netlabel gave us.
3865-
*/
3866-
netlbl_secattr_init(&secattr);
3867-
3868-
rc = netlbl_skbuff_getattr(skb, family, &secattr);
3869-
if (rc == 0)
3870-
skp = smack_from_secattr(&secattr, ssp);
3871-
else
3872-
skp = smack_net_ambient;
3873-
3874-
netlbl_secattr_destroy(&secattr);
3875-
3876-
access_check:
3902+
if (skp == NULL) {
3903+
skp = smack_from_netlbl(sk, family, skb);
3904+
if (skp == NULL)
3905+
skp = smack_net_ambient;
3906+
}
38773907

38783908
#ifdef CONFIG_AUDIT
38793909
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
@@ -3979,12 +4009,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
39794009
struct sk_buff *skb, u32 *secid)
39804010

39814011
{
3982-
struct netlbl_lsm_secattr secattr;
39834012
struct socket_smack *ssp = NULL;
39844013
struct smack_known *skp;
4014+
struct sock *sk = NULL;
39854015
int family = PF_UNSPEC;
39864016
u32 s = 0; /* 0 is the invalid secid */
3987-
int rc;
39884017

39894018
if (skb != NULL) {
39904019
if (skb->protocol == htons(ETH_P_IP))
@@ -4011,15 +4040,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
40114040
/*
40124041
* Translate what netlabel gave us.
40134042
*/
4014-
if (sock != NULL && sock->sk != NULL)
4015-
ssp = sock->sk->sk_security;
4016-
netlbl_secattr_init(&secattr);
4017-
rc = netlbl_skbuff_getattr(skb, family, &secattr);
4018-
if (rc == 0) {
4019-
skp = smack_from_secattr(&secattr, ssp);
4043+
if (sock != NULL)
4044+
sk = sock->sk;
4045+
skp = smack_from_netlbl(sk, family, skb);
4046+
if (skp != NULL)
40204047
s = skp->smk_secid;
4021-
}
4022-
netlbl_secattr_destroy(&secattr);
40234048
break;
40244049
case PF_INET6:
40254050
#ifdef SMACK_IPV6_SECMARK_LABELING
@@ -4073,7 +4098,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
40734098
u16 family = sk->sk_family;
40744099
struct smack_known *skp;
40754100
struct socket_smack *ssp = sk->sk_security;
4076-
struct netlbl_lsm_secattr secattr;
40774101
struct sockaddr_in addr;
40784102
struct iphdr *hdr;
40794103
struct smack_known *hskp;
@@ -4103,18 +4127,11 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
41034127
* The secmark is assumed to reflect policy better.
41044128
*/
41054129
skp = smack_from_skb(skb);
4106-
if (skp)
4107-
goto access_check;
4108-
4109-
netlbl_secattr_init(&secattr);
4110-
rc = netlbl_skbuff_getattr(skb, family, &secattr);
4111-
if (rc == 0)
4112-
skp = smack_from_secattr(&secattr, ssp);
4113-
else
4114-
skp = &smack_known_huh;
4115-
netlbl_secattr_destroy(&secattr);
4116-
4117-
access_check:
4130+
if (skp == NULL) {
4131+
skp = smack_from_netlbl(sk, family, skb);
4132+
if (skp == NULL)
4133+
skp = &smack_known_huh;
4134+
}
41184135

41194136
#ifdef CONFIG_AUDIT
41204137
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);

0 commit comments

Comments
 (0)