Skip to content

Commit 253bfae

Browse files
pcmooreJames Morris
authored andcommitted
selinux: Convert socket related access controls to use socket labels
At present, the socket related access controls use a mix of inode and socket labels; while there should be no practical difference (they _should_ always be the same), it makes the code more confusing. This patch attempts to convert all of the socket related access control points (with the exception of some of the inode/fd based controls) to use the socket's own label. In the process, I also converted the socket_has_perm() function to take a 'sock' argument instead of a 'socket' since that was adding a bit more overhead in some cases. Signed-off-by: Paul Moore <paul.moore@hp.com> Acked-by: Eric Paris <eparis@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
1 parent 84914b7 commit 253bfae

File tree

1 file changed

+45
-74
lines changed

1 file changed

+45
-74
lines changed

security/selinux/hooks.c

Lines changed: 45 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3651,26 +3651,19 @@ static u32 socket_sockcreate_sid(const struct task_security_struct *tsec)
36513651
return tsec->sockcreate_sid ? : tsec->sid;
36523652
}
36533653

3654-
static int socket_has_perm(struct task_struct *task, struct socket *sock,
3655-
u32 perms)
3654+
static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
36563655
{
3657-
struct inode_security_struct *isec;
3656+
struct sk_security_struct *sksec = sk->sk_security;
36583657
struct common_audit_data ad;
3659-
u32 sid;
3660-
int err = 0;
3658+
u32 tsid = task_sid(task);
36613659

3662-
isec = SOCK_INODE(sock)->i_security;
3663-
3664-
if (isec->sid == SECINITSID_KERNEL)
3665-
goto out;
3666-
sid = task_sid(task);
3660+
if (sksec->sid == SECINITSID_KERNEL)
3661+
return 0;
36673662

36683663
COMMON_AUDIT_DATA_INIT(&ad, NET);
3669-
ad.u.net.sk = sock->sk;
3670-
err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
3664+
ad.u.net.sk = sk;
36713665

3672-
out:
3673-
return err;
3666+
return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
36743667
}
36753668

36763669
static int selinux_socket_create(int family, int type,
@@ -3722,10 +3715,11 @@ static int selinux_socket_post_create(struct socket *sock, int family,
37223715

37233716
static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
37243717
{
3718+
struct sock *sk = sock->sk;
37253719
u16 family;
37263720
int err;
37273721

3728-
err = socket_has_perm(current, sock, SOCKET__BIND);
3722+
err = sock_has_perm(current, sk, SOCKET__BIND);
37293723
if (err)
37303724
goto out;
37313725

@@ -3734,19 +3728,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
37343728
* Multiple address binding for SCTP is not supported yet: we just
37353729
* check the first address now.
37363730
*/
3737-
family = sock->sk->sk_family;
3731+
family = sk->sk_family;
37383732
if (family == PF_INET || family == PF_INET6) {
37393733
char *addrp;
3740-
struct inode_security_struct *isec;
3734+
struct sk_security_struct *sksec = sk->sk_security;
37413735
struct common_audit_data ad;
37423736
struct sockaddr_in *addr4 = NULL;
37433737
struct sockaddr_in6 *addr6 = NULL;
37443738
unsigned short snum;
3745-
struct sock *sk = sock->sk;
37463739
u32 sid, node_perm;
37473740

3748-
isec = SOCK_INODE(sock)->i_security;
3749-
37503741
if (family == PF_INET) {
37513742
addr4 = (struct sockaddr_in *)address;
37523743
snum = ntohs(addr4->sin_port);
@@ -3770,15 +3761,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
37703761
COMMON_AUDIT_DATA_INIT(&ad, NET);
37713762
ad.u.net.sport = htons(snum);
37723763
ad.u.net.family = family;
3773-
err = avc_has_perm(isec->sid, sid,
3774-
isec->sclass,
3764+
err = avc_has_perm(sksec->sid, sid,
3765+
sksec->sclass,
37753766
SOCKET__NAME_BIND, &ad);
37763767
if (err)
37773768
goto out;
37783769
}
37793770
}
37803771

3781-
switch (isec->sclass) {
3772+
switch (sksec->sclass) {
37823773
case SECCLASS_TCP_SOCKET:
37833774
node_perm = TCP_SOCKET__NODE_BIND;
37843775
break;
@@ -3809,8 +3800,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
38093800
else
38103801
ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
38113802

3812-
err = avc_has_perm(isec->sid, sid,
3813-
isec->sclass, node_perm, &ad);
3803+
err = avc_has_perm(sksec->sid, sid,
3804+
sksec->sclass, node_perm, &ad);
38143805
if (err)
38153806
goto out;
38163807
}
@@ -3821,19 +3812,18 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
38213812
static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
38223813
{
38233814
struct sock *sk = sock->sk;
3824-
struct inode_security_struct *isec;
3815+
struct sk_security_struct *sksec = sk->sk_security;
38253816
int err;
38263817

3827-
err = socket_has_perm(current, sock, SOCKET__CONNECT);
3818+
err = sock_has_perm(current, sk, SOCKET__CONNECT);
38283819
if (err)
38293820
return err;
38303821

38313822
/*
38323823
* If a TCP or DCCP socket, check name_connect permission for the port.
38333824
*/
3834-
isec = SOCK_INODE(sock)->i_security;
3835-
if (isec->sclass == SECCLASS_TCP_SOCKET ||
3836-
isec->sclass == SECCLASS_DCCP_SOCKET) {
3825+
if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3826+
sksec->sclass == SECCLASS_DCCP_SOCKET) {
38373827
struct common_audit_data ad;
38383828
struct sockaddr_in *addr4 = NULL;
38393829
struct sockaddr_in6 *addr6 = NULL;
@@ -3856,13 +3846,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
38563846
if (err)
38573847
goto out;
38583848

3859-
perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3849+
perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
38603850
TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
38613851

38623852
COMMON_AUDIT_DATA_INIT(&ad, NET);
38633853
ad.u.net.dport = htons(snum);
38643854
ad.u.net.family = sk->sk_family;
3865-
err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
3855+
err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
38663856
if (err)
38673857
goto out;
38683858
}
@@ -3875,7 +3865,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
38753865

38763866
static int selinux_socket_listen(struct socket *sock, int backlog)
38773867
{
3878-
return socket_has_perm(current, sock, SOCKET__LISTEN);
3868+
return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
38793869
}
38803870

38813871
static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
@@ -3884,7 +3874,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
38843874
struct inode_security_struct *isec;
38853875
struct inode_security_struct *newisec;
38863876

3887-
err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3877+
err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
38883878
if (err)
38893879
return err;
38903880

@@ -3901,30 +3891,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
39013891
static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
39023892
int size)
39033893
{
3904-
return socket_has_perm(current, sock, SOCKET__WRITE);
3894+
return sock_has_perm(current, sock->sk, SOCKET__WRITE);
39053895
}
39063896

39073897
static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
39083898
int size, int flags)
39093899
{
3910-
return socket_has_perm(current, sock, SOCKET__READ);
3900+
return sock_has_perm(current, sock->sk, SOCKET__READ);
39113901
}
39123902

39133903
static int selinux_socket_getsockname(struct socket *sock)
39143904
{
3915-
return socket_has_perm(current, sock, SOCKET__GETATTR);
3905+
return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
39163906
}
39173907

39183908
static int selinux_socket_getpeername(struct socket *sock)
39193909
{
3920-
return socket_has_perm(current, sock, SOCKET__GETATTR);
3910+
return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
39213911
}
39223912

39233913
static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
39243914
{
39253915
int err;
39263916

3927-
err = socket_has_perm(current, sock, SOCKET__SETOPT);
3917+
err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
39283918
if (err)
39293919
return err;
39303920

@@ -3934,12 +3924,12 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
39343924
static int selinux_socket_getsockopt(struct socket *sock, int level,
39353925
int optname)
39363926
{
3937-
return socket_has_perm(current, sock, SOCKET__GETOPT);
3927+
return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
39383928
}
39393929

39403930
static int selinux_socket_shutdown(struct socket *sock, int how)
39413931
{
3942-
return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3932+
return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
39433933
}
39443934

39453935
static int selinux_socket_unix_stream_connect(struct socket *sock,
@@ -3977,23 +3967,15 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
39773967
static int selinux_socket_unix_may_send(struct socket *sock,
39783968
struct socket *other)
39793969
{
3980-
struct inode_security_struct *isec;
3981-
struct inode_security_struct *other_isec;
3970+
struct sk_security_struct *ssec = sock->sk->sk_security;
3971+
struct sk_security_struct *osec = other->sk->sk_security;
39823972
struct common_audit_data ad;
3983-
int err;
3984-
3985-
isec = SOCK_INODE(sock)->i_security;
3986-
other_isec = SOCK_INODE(other)->i_security;
39873973

39883974
COMMON_AUDIT_DATA_INIT(&ad, NET);
39893975
ad.u.net.sk = other->sk;
39903976

3991-
err = avc_has_perm(isec->sid, other_isec->sid,
3992-
isec->sclass, SOCKET__SENDTO, &ad);
3993-
if (err)
3994-
return err;
3995-
3996-
return 0;
3977+
return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
3978+
&ad);
39973979
}
39983980

39993981
static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
@@ -4132,26 +4114,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
41324114
int err = 0;
41334115
char *scontext;
41344116
u32 scontext_len;
4135-
struct sk_security_struct *sksec;
4136-
struct inode_security_struct *isec;
4117+
struct sk_security_struct *sksec = sock->sk->sk_security;
41374118
u32 peer_sid = SECSID_NULL;
41384119

4139-
isec = SOCK_INODE(sock)->i_security;
4140-
4141-
if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4142-
isec->sclass == SECCLASS_TCP_SOCKET) {
4143-
sksec = sock->sk->sk_security;
4120+
if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4121+
sksec->sclass == SECCLASS_TCP_SOCKET)
41444122
peer_sid = sksec->peer_sid;
4145-
}
4146-
if (peer_sid == SECSID_NULL) {
4147-
err = -ENOPROTOOPT;
4148-
goto out;
4149-
}
4123+
if (peer_sid == SECSID_NULL)
4124+
return -ENOPROTOOPT;
41504125

41514126
err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4152-
41534127
if (err)
4154-
goto out;
4128+
return err;
41554129

41564130
if (scontext_len > len) {
41574131
err = -ERANGE;
@@ -4164,9 +4138,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
41644138
out_len:
41654139
if (put_user(scontext_len, optlen))
41664140
err = -EFAULT;
4167-
41684141
kfree(scontext);
4169-
out:
41704142
return err;
41714143
}
41724144

@@ -4378,22 +4350,21 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
43784350
int err = 0;
43794351
u32 perm;
43804352
struct nlmsghdr *nlh;
4381-
struct socket *sock = sk->sk_socket;
4382-
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4353+
struct sk_security_struct *sksec = sk->sk_security;
43834354

43844355
if (skb->len < NLMSG_SPACE(0)) {
43854356
err = -EINVAL;
43864357
goto out;
43874358
}
43884359
nlh = nlmsg_hdr(skb);
43894360

4390-
err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
4361+
err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
43914362
if (err) {
43924363
if (err == -EINVAL) {
43934364
audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
43944365
"SELinux: unrecognized netlink message"
43954366
" type=%hu for sclass=%hu\n",
4396-
nlh->nlmsg_type, isec->sclass);
4367+
nlh->nlmsg_type, sksec->sclass);
43974368
if (!selinux_enforcing || security_get_allow_unknown())
43984369
err = 0;
43994370
}
@@ -4404,7 +4375,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
44044375
goto out;
44054376
}
44064377

4407-
err = socket_has_perm(current, sock, perm);
4378+
err = sock_has_perm(current, sk, perm);
44084379
out:
44094380
return err;
44104381
}

0 commit comments

Comments
 (0)