selinux: Set socket NetLabel based on connection endpoint
Previous work enabled the use of address based NetLabel selectors, which while highly useful, brought the potential for additional per-packet overhead when used. This patch attempts to solve that by applying NetLabel socket labels when sockets are connect()'d. This should alleviate the per-packet NetLabel labeling for all connected sockets (yes, it even works for connected DGRAM sockets). Signed-off-by: Paul Moore <paul.moore@hp.com> Reviewed-by: James Morris <jmorris@namei.org>
This commit is contained in:
@@ -1809,6 +1809,80 @@ socket_setattr_failure:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* cipso_v4_sock_delattr - Delete the CIPSO option from a socket
|
||||
* @sk: the socket
|
||||
*
|
||||
* Description:
|
||||
* Removes the CIPSO option from a socket, if present.
|
||||
*
|
||||
*/
|
||||
void cipso_v4_sock_delattr(struct sock *sk)
|
||||
{
|
||||
u8 hdr_delta;
|
||||
struct ip_options *opt;
|
||||
struct inet_sock *sk_inet;
|
||||
|
||||
sk_inet = inet_sk(sk);
|
||||
opt = sk_inet->opt;
|
||||
if (opt == NULL || opt->cipso == 0)
|
||||
return;
|
||||
|
||||
if (opt->srr || opt->rr || opt->ts || opt->router_alert) {
|
||||
u8 cipso_len;
|
||||
u8 cipso_off;
|
||||
unsigned char *cipso_ptr;
|
||||
int iter;
|
||||
int optlen_new;
|
||||
|
||||
cipso_off = opt->cipso - sizeof(struct iphdr);
|
||||
cipso_ptr = &opt->__data[cipso_off];
|
||||
cipso_len = cipso_ptr[1];
|
||||
|
||||
if (opt->srr > opt->cipso)
|
||||
opt->srr -= cipso_len;
|
||||
if (opt->rr > opt->cipso)
|
||||
opt->rr -= cipso_len;
|
||||
if (opt->ts > opt->cipso)
|
||||
opt->ts -= cipso_len;
|
||||
if (opt->router_alert > opt->cipso)
|
||||
opt->router_alert -= cipso_len;
|
||||
opt->cipso = 0;
|
||||
|
||||
memmove(cipso_ptr, cipso_ptr + cipso_len,
|
||||
opt->optlen - cipso_off - cipso_len);
|
||||
|
||||
/* determining the new total option length is tricky because of
|
||||
* the padding necessary, the only thing i can think to do at
|
||||
* this point is walk the options one-by-one, skipping the
|
||||
* padding at the end to determine the actual option size and
|
||||
* from there we can determine the new total option length */
|
||||
iter = 0;
|
||||
optlen_new = 0;
|
||||
while (iter < opt->optlen)
|
||||
if (opt->__data[iter] != IPOPT_NOP) {
|
||||
iter += opt->__data[iter + 1];
|
||||
optlen_new = iter;
|
||||
} else
|
||||
iter++;
|
||||
hdr_delta = opt->optlen;
|
||||
opt->optlen = (optlen_new + 3) & ~3;
|
||||
hdr_delta -= opt->optlen;
|
||||
} else {
|
||||
/* only the cipso option was present on the socket so we can
|
||||
* remove the entire option struct */
|
||||
sk_inet->opt = NULL;
|
||||
hdr_delta = opt->optlen;
|
||||
kfree(opt);
|
||||
}
|
||||
|
||||
if (sk_inet->is_icsk && hdr_delta > 0) {
|
||||
struct inet_connection_sock *sk_conn = inet_csk(sk);
|
||||
sk_conn->icsk_ext_hdr_len -= hdr_delta;
|
||||
sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
|
||||
* @cipso: the CIPSO v4 option
|
||||
|
Reference in New Issue
Block a user