diff options
author | James Morris <jmorris@redhat.com> | 2004-06-17 18:15:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-06-17 18:15:37 -0700 |
commit | 5e1c337dd7ee0b2663ddc8842cfeede985f54cd3 (patch) | |
tree | ca38ada3e4b9e77ec6bd5d2f01b949fbee9f223b /security | |
parent | c83293d53792446fde0007db076947bdbdf099e7 (diff) | |
download | history-5e1c337dd7ee0b2663ddc8842cfeede985f54cd3.tar.gz |
[PATCH] SELinux: Fine-grained Netlink support - SELinux changes
This patch contains SELinux changes which add support for extended Netlink
socket classes and the associated permissions nlmsg_read and nlmsg_write.
Cc: David S. Miller <davem@redhat.com>
Signed-off-by: James Morris <jmorris@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/Makefile | 2 | ||||
-rw-r--r-- | security/selinux/hooks.c | 102 | ||||
-rw-r--r-- | security/selinux/include/av_inherit.h | 9 | ||||
-rw-r--r-- | security/selinux/include/av_perm_to_string.h | 12 | ||||
-rw-r--r-- | security/selinux/include/av_permissions.h | 223 | ||||
-rw-r--r-- | security/selinux/include/class_to_string.h | 9 | ||||
-rw-r--r-- | security/selinux/include/flask.h | 9 | ||||
-rw-r--r-- | security/selinux/include/security.h | 9 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 153 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 10 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 12 |
11 files changed, 522 insertions, 28 deletions
diff --git a/security/selinux/Makefile b/security/selinux/Makefile index 890404ed2a5e2d..b038cd0fae2e09 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ -selinux-y := avc.o hooks.o selinuxfs.o netlink.o +selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o selinux-$(CONFIG_SECURITY_NETWORK) += netif.o diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 784833f3820192..1bcad09b564dc2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -71,6 +71,9 @@ #define XATTR_SELINUX_SUFFIX "selinux" #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX +extern int policydb_loaded_version; +extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); + #ifdef CONFIG_SECURITY_SELINUX_DEVELOP int selinux_enforcing = 0; @@ -627,7 +630,7 @@ static inline u16 inode_mode_to_security_class(umode_t mode) return SECCLASS_FILE; } -static inline u16 socket_type_to_security_class(int family, int type) +static inline u16 socket_type_to_security_class(int family, int type, int protocol) { switch (family) { case PF_UNIX: @@ -648,7 +651,28 @@ static inline u16 socket_type_to_security_class(int family, int type) return SECCLASS_RAWIP_SOCKET; } case PF_NETLINK: - return SECCLASS_NETLINK_SOCKET; + switch (protocol) { + case NETLINK_ROUTE: + return SECCLASS_NETLINK_ROUTE_SOCKET; + case NETLINK_FIREWALL: + return SECCLASS_NETLINK_FIREWALL_SOCKET; + case NETLINK_TCPDIAG: + return SECCLASS_NETLINK_TCPDIAG_SOCKET; + case NETLINK_NFLOG: + return SECCLASS_NETLINK_NFLOG_SOCKET; + case NETLINK_XFRM: + return SECCLASS_NETLINK_XFRM_SOCKET; + case NETLINK_SELINUX: + return SECCLASS_NETLINK_SELINUX_SOCKET; + case NETLINK_AUDIT: + return SECCLASS_NETLINK_AUDIT_SOCKET; + case NETLINK_IP6_FW: + return SECCLASS_NETLINK_IP6FW_SOCKET; + case NETLINK_DNRTMSG: + return SECCLASS_NETLINK_DNRT_SOCKET; + default: + return SECCLASS_NETLINK_SOCKET; + } case PF_PACKET: return SECCLASS_PACKET_SOCKET; case PF_KEY: @@ -853,7 +877,8 @@ out: struct socket *sock = SOCKET_I(inode); if (sock->sk) { isec->sclass = socket_type_to_security_class(sock->sk->sk_family, - sock->sk->sk_type); + sock->sk->sk_type, + sock->sk->sk_protocol); } else { isec->sclass = SECCLASS_SOCKET; } @@ -1567,22 +1592,6 @@ static int selinux_vm_enough_memory(long pages) return -ENOMEM; } -static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) -{ - if (capable(CAP_NET_ADMIN)) - cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN); - else - NETLINK_CB(skb).eff_cap = 0; - return 0; -} - -static int selinux_netlink_recv(struct sk_buff *skb) -{ - if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) - return -EPERM; - return 0; -} - /* binprm security operations */ static int selinux_bprm_alloc_security(struct linux_binprm *bprm) @@ -2918,8 +2927,8 @@ static int selinux_socket_create(int family, int type, tsec = current->security; err = avc_has_perm(tsec->sid, tsec->sid, - socket_type_to_security_class(family, type), - SOCKET__CREATE, NULL, NULL); + socket_type_to_security_class(family, type, + protocol), SOCKET__CREATE, NULL, NULL); out: return err; @@ -2938,7 +2947,7 @@ static void selinux_socket_post_create(struct socket *sock, int family, isec = SOCK_INODE(sock)->i_security; tsec = current->security; - isec->sclass = socket_type_to_security_class(family, type); + isec->sclass = socket_type_to_security_class(family, type, protocol); isec->sid = kern ? SECINITSID_KERNEL : tsec->sid; return; @@ -3327,6 +3336,55 @@ static void selinux_sk_free_security(struct sock *sk) sk_free_security(sk); } +static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) +{ + int err = 0; + u32 perm; + struct nlmsghdr *nlh; + struct socket *sock = sk->sk_socket; + struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; + + if (skb->len < NLMSG_SPACE(0)) { + err = -EINVAL; + goto out; + } + nlh = (struct nlmsghdr *)skb->data; + + err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); + if (err) { + /* Ignore */ + if (err == -ENOENT) + err = 0; + goto out; + } + + err = socket_has_perm(current, sock, perm); +out: + return err; +} + +static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) +{ + int err = 0; + + if (capable(CAP_NET_ADMIN)) + cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN); + else + NETLINK_CB(skb).eff_cap = 0; + + if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) + err = selinux_nlmsg_perm(sk, skb); + + return err; +} + +static int selinux_netlink_recv(struct sk_buff *skb) +{ + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) + return -EPERM; + return 0; +} + #ifdef CONFIG_NETFILTER static unsigned int selinux_ip_postroute_last(unsigned int hooknum, diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h index eb3f4e141b2822..c05e2ee6febb7f 100644 --- a/security/selinux/include/av_inherit.h +++ b/security/selinux/include/av_inherit.h @@ -29,6 +29,15 @@ static struct av_inherit av_inherit[] = { { SECCLASS_SEM, common_ipc_perm_to_string, 0x00000200UL }, { SECCLASS_MSGQ, common_ipc_perm_to_string, 0x00000200UL }, { SECCLASS_SHM, common_ipc_perm_to_string, 0x00000200UL }, + { SECCLASS_NETLINK_ROUTE_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_FIREWALL_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_TCPDIAG_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_NFLOG_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_XFRM_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_SELINUX_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_AUDIT_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_IP6FW_SOCKET, common_socket_perm_to_string, 0x00400000UL }, + { SECCLASS_NETLINK_DNRT_SOCKET, common_socket_perm_to_string, 0x00400000UL }, }; diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 5b2061423b3b76..e8e2a41cff540e 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -207,6 +207,18 @@ static struct av_perm_to_string av_perm_to_string[] = { { SECCLASS_PAX, PAX__RANDMMAP, "randmmap" }, { SECCLASS_PAX, PAX__RANDEXEC, "randexec" }, { SECCLASS_PAX, PAX__SEGMEXEC, "segmexec" }, + { SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read" }, + { SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write" }, + { SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read" }, + { SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write" }, + { SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read" }, + { SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write" }, + { SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read" }, + { SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write" }, + { SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read" }, + { SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write" }, + { SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read" }, + { SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write" }, }; diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 600c00889cb75f..0a4c6e08f63ecd 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -653,5 +653,228 @@ #define PAX__RANDEXEC 0x00000010UL #define PAX__SEGMEXEC 0x00000020UL +#define NETLINK_ROUTE_SOCKET__IOCTL 0x00000001UL +#define NETLINK_ROUTE_SOCKET__READ 0x00000002UL +#define NETLINK_ROUTE_SOCKET__WRITE 0x00000004UL +#define NETLINK_ROUTE_SOCKET__CREATE 0x00000008UL +#define NETLINK_ROUTE_SOCKET__GETATTR 0x00000010UL +#define NETLINK_ROUTE_SOCKET__SETATTR 0x00000020UL +#define NETLINK_ROUTE_SOCKET__LOCK 0x00000040UL +#define NETLINK_ROUTE_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_ROUTE_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_ROUTE_SOCKET__APPEND 0x00000200UL +#define NETLINK_ROUTE_SOCKET__BIND 0x00000400UL +#define NETLINK_ROUTE_SOCKET__CONNECT 0x00000800UL +#define NETLINK_ROUTE_SOCKET__LISTEN 0x00001000UL +#define NETLINK_ROUTE_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_ROUTE_SOCKET__GETOPT 0x00004000UL +#define NETLINK_ROUTE_SOCKET__SETOPT 0x00008000UL +#define NETLINK_ROUTE_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_ROUTE_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_ROUTE_SOCKET__SENDTO 0x00040000UL +#define NETLINK_ROUTE_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_ROUTE_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_ROUTE_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_ROUTE_SOCKET__NLMSG_READ 0x00400000UL +#define NETLINK_ROUTE_SOCKET__NLMSG_WRITE 0x00800000UL + +#define NETLINK_FIREWALL_SOCKET__IOCTL 0x00000001UL +#define NETLINK_FIREWALL_SOCKET__READ 0x00000002UL +#define NETLINK_FIREWALL_SOCKET__WRITE 0x00000004UL +#define NETLINK_FIREWALL_SOCKET__CREATE 0x00000008UL +#define NETLINK_FIREWALL_SOCKET__GETATTR 0x00000010UL +#define NETLINK_FIREWALL_SOCKET__SETATTR 0x00000020UL +#define NETLINK_FIREWALL_SOCKET__LOCK 0x00000040UL +#define NETLINK_FIREWALL_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_FIREWALL_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_FIREWALL_SOCKET__APPEND 0x00000200UL +#define NETLINK_FIREWALL_SOCKET__BIND 0x00000400UL +#define NETLINK_FIREWALL_SOCKET__CONNECT 0x00000800UL +#define NETLINK_FIREWALL_SOCKET__LISTEN 0x00001000UL +#define NETLINK_FIREWALL_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_FIREWALL_SOCKET__GETOPT 0x00004000UL +#define NETLINK_FIREWALL_SOCKET__SETOPT 0x00008000UL +#define NETLINK_FIREWALL_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_FIREWALL_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_FIREWALL_SOCKET__SENDTO 0x00040000UL +#define NETLINK_FIREWALL_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_FIREWALL_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_FIREWALL_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_FIREWALL_SOCKET__NLMSG_READ 0x00400000UL +#define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE 0x00800000UL + +#define NETLINK_TCPDIAG_SOCKET__IOCTL 0x00000001UL +#define NETLINK_TCPDIAG_SOCKET__READ 0x00000002UL +#define NETLINK_TCPDIAG_SOCKET__WRITE 0x00000004UL +#define NETLINK_TCPDIAG_SOCKET__CREATE 0x00000008UL +#define NETLINK_TCPDIAG_SOCKET__GETATTR 0x00000010UL +#define NETLINK_TCPDIAG_SOCKET__SETATTR 0x00000020UL +#define NETLINK_TCPDIAG_SOCKET__LOCK 0x00000040UL +#define NETLINK_TCPDIAG_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_TCPDIAG_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_TCPDIAG_SOCKET__APPEND 0x00000200UL +#define NETLINK_TCPDIAG_SOCKET__BIND 0x00000400UL +#define NETLINK_TCPDIAG_SOCKET__CONNECT 0x00000800UL +#define NETLINK_TCPDIAG_SOCKET__LISTEN 0x00001000UL +#define NETLINK_TCPDIAG_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_TCPDIAG_SOCKET__GETOPT 0x00004000UL +#define NETLINK_TCPDIAG_SOCKET__SETOPT 0x00008000UL +#define NETLINK_TCPDIAG_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_TCPDIAG_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_TCPDIAG_SOCKET__SENDTO 0x00040000UL +#define NETLINK_TCPDIAG_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_TCPDIAG_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_TCPDIAG_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_TCPDIAG_SOCKET__NLMSG_READ 0x00400000UL +#define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE 0x00800000UL + +#define NETLINK_NFLOG_SOCKET__IOCTL 0x00000001UL +#define NETLINK_NFLOG_SOCKET__READ 0x00000002UL +#define NETLINK_NFLOG_SOCKET__WRITE 0x00000004UL +#define NETLINK_NFLOG_SOCKET__CREATE 0x00000008UL +#define NETLINK_NFLOG_SOCKET__GETATTR 0x00000010UL +#define NETLINK_NFLOG_SOCKET__SETATTR 0x00000020UL +#define NETLINK_NFLOG_SOCKET__LOCK 0x00000040UL +#define NETLINK_NFLOG_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_NFLOG_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_NFLOG_SOCKET__APPEND 0x00000200UL +#define NETLINK_NFLOG_SOCKET__BIND 0x00000400UL +#define NETLINK_NFLOG_SOCKET__CONNECT 0x00000800UL +#define NETLINK_NFLOG_SOCKET__LISTEN 0x00001000UL +#define NETLINK_NFLOG_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_NFLOG_SOCKET__GETOPT 0x00004000UL +#define NETLINK_NFLOG_SOCKET__SETOPT 0x00008000UL +#define NETLINK_NFLOG_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_NFLOG_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_NFLOG_SOCKET__SENDTO 0x00040000UL +#define NETLINK_NFLOG_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_NFLOG_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_NFLOG_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_XFRM_SOCKET__IOCTL 0x00000001UL +#define NETLINK_XFRM_SOCKET__READ 0x00000002UL +#define NETLINK_XFRM_SOCKET__WRITE 0x00000004UL +#define NETLINK_XFRM_SOCKET__CREATE 0x00000008UL +#define NETLINK_XFRM_SOCKET__GETATTR 0x00000010UL +#define NETLINK_XFRM_SOCKET__SETATTR 0x00000020UL +#define NETLINK_XFRM_SOCKET__LOCK 0x00000040UL +#define NETLINK_XFRM_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_XFRM_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_XFRM_SOCKET__APPEND 0x00000200UL +#define NETLINK_XFRM_SOCKET__BIND 0x00000400UL +#define NETLINK_XFRM_SOCKET__CONNECT 0x00000800UL +#define NETLINK_XFRM_SOCKET__LISTEN 0x00001000UL +#define NETLINK_XFRM_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_XFRM_SOCKET__GETOPT 0x00004000UL +#define NETLINK_XFRM_SOCKET__SETOPT 0x00008000UL +#define NETLINK_XFRM_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_XFRM_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_XFRM_SOCKET__SENDTO 0x00040000UL +#define NETLINK_XFRM_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_XFRM_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_XFRM_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_XFRM_SOCKET__NLMSG_READ 0x00400000UL +#define NETLINK_XFRM_SOCKET__NLMSG_WRITE 0x00800000UL + +#define NETLINK_SELINUX_SOCKET__IOCTL 0x00000001UL +#define NETLINK_SELINUX_SOCKET__READ 0x00000002UL +#define NETLINK_SELINUX_SOCKET__WRITE 0x00000004UL +#define NETLINK_SELINUX_SOCKET__CREATE 0x00000008UL +#define NETLINK_SELINUX_SOCKET__GETATTR 0x00000010UL +#define NETLINK_SELINUX_SOCKET__SETATTR 0x00000020UL +#define NETLINK_SELINUX_SOCKET__LOCK 0x00000040UL +#define NETLINK_SELINUX_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_SELINUX_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_SELINUX_SOCKET__APPEND 0x00000200UL +#define NETLINK_SELINUX_SOCKET__BIND 0x00000400UL +#define NETLINK_SELINUX_SOCKET__CONNECT 0x00000800UL +#define NETLINK_SELINUX_SOCKET__LISTEN 0x00001000UL +#define NETLINK_SELINUX_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_SELINUX_SOCKET__GETOPT 0x00004000UL +#define NETLINK_SELINUX_SOCKET__SETOPT 0x00008000UL +#define NETLINK_SELINUX_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_SELINUX_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_SELINUX_SOCKET__SENDTO 0x00040000UL +#define NETLINK_SELINUX_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_SELINUX_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_SELINUX_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_AUDIT_SOCKET__IOCTL 0x00000001UL +#define NETLINK_AUDIT_SOCKET__READ 0x00000002UL +#define NETLINK_AUDIT_SOCKET__WRITE 0x00000004UL +#define NETLINK_AUDIT_SOCKET__CREATE 0x00000008UL +#define NETLINK_AUDIT_SOCKET__GETATTR 0x00000010UL +#define NETLINK_AUDIT_SOCKET__SETATTR 0x00000020UL +#define NETLINK_AUDIT_SOCKET__LOCK 0x00000040UL +#define NETLINK_AUDIT_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_AUDIT_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_AUDIT_SOCKET__APPEND 0x00000200UL +#define NETLINK_AUDIT_SOCKET__BIND 0x00000400UL +#define NETLINK_AUDIT_SOCKET__CONNECT 0x00000800UL +#define NETLINK_AUDIT_SOCKET__LISTEN 0x00001000UL +#define NETLINK_AUDIT_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_AUDIT_SOCKET__GETOPT 0x00004000UL +#define NETLINK_AUDIT_SOCKET__SETOPT 0x00008000UL +#define NETLINK_AUDIT_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_AUDIT_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_AUDIT_SOCKET__SENDTO 0x00040000UL +#define NETLINK_AUDIT_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_AUDIT_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_AUDIT_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_AUDIT_SOCKET__NLMSG_READ 0x00400000UL +#define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL + +#define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL +#define NETLINK_IP6FW_SOCKET__READ 0x00000002UL +#define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL +#define NETLINK_IP6FW_SOCKET__CREATE 0x00000008UL +#define NETLINK_IP6FW_SOCKET__GETATTR 0x00000010UL +#define NETLINK_IP6FW_SOCKET__SETATTR 0x00000020UL +#define NETLINK_IP6FW_SOCKET__LOCK 0x00000040UL +#define NETLINK_IP6FW_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_IP6FW_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_IP6FW_SOCKET__APPEND 0x00000200UL +#define NETLINK_IP6FW_SOCKET__BIND 0x00000400UL +#define NETLINK_IP6FW_SOCKET__CONNECT 0x00000800UL +#define NETLINK_IP6FW_SOCKET__LISTEN 0x00001000UL +#define NETLINK_IP6FW_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_IP6FW_SOCKET__GETOPT 0x00004000UL +#define NETLINK_IP6FW_SOCKET__SETOPT 0x00008000UL +#define NETLINK_IP6FW_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_IP6FW_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_IP6FW_SOCKET__SENDTO 0x00040000UL +#define NETLINK_IP6FW_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_IP6FW_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_IP6FW_SOCKET__NAME_BIND 0x00200000UL + +#define NETLINK_IP6FW_SOCKET__NLMSG_READ 0x00400000UL +#define NETLINK_IP6FW_SOCKET__NLMSG_WRITE 0x00800000UL + +#define NETLINK_DNRT_SOCKET__IOCTL 0x00000001UL +#define NETLINK_DNRT_SOCKET__READ 0x00000002UL +#define NETLINK_DNRT_SOCKET__WRITE 0x00000004UL +#define NETLINK_DNRT_SOCKET__CREATE 0x00000008UL +#define NETLINK_DNRT_SOCKET__GETATTR 0x00000010UL +#define NETLINK_DNRT_SOCKET__SETATTR 0x00000020UL +#define NETLINK_DNRT_SOCKET__LOCK 0x00000040UL +#define NETLINK_DNRT_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_DNRT_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_DNRT_SOCKET__APPEND 0x00000200UL +#define NETLINK_DNRT_SOCKET__BIND 0x00000400UL +#define NETLINK_DNRT_SOCKET__CONNECT 0x00000800UL +#define NETLINK_DNRT_SOCKET__LISTEN 0x00001000UL +#define NETLINK_DNRT_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_DNRT_SOCKET__GETOPT 0x00004000UL +#define NETLINK_DNRT_SOCKET__SETOPT 0x00008000UL +#define NETLINK_DNRT_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_DNRT_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_DNRT_SOCKET__SENDTO 0x00040000UL +#define NETLINK_DNRT_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_DNRT_SOCKET__SEND_MSG 0x00100000UL /* FLASK */ diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index bbfbae7cc1a676..a65e25eb698aba 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h @@ -47,5 +47,14 @@ static char *class_to_string[] = "xserver", "xextension", "pax", + "netlink_route_socket", + "netlink_firewall_socket", + "netlink_tcpdiag_socket", + "netlink_nflog_socket", + "netlink_xfrm_socket", + "netlink_selinux_socket", + "netlink_audit_socket", + "netlink_ip6fw_socket", + "netlink_dnrt_socket", }; diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index 098a2b7a40f7c4..a392a3d06023b1 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h @@ -47,6 +47,15 @@ #define SECCLASS_XSERVER 40 #define SECCLASS_XEXTENSION 41 #define SECCLASS_PAX 42 +#define SECCLASS_NETLINK_ROUTE_SOCKET 43 +#define SECCLASS_NETLINK_FIREWALL_SOCKET 44 +#define SECCLASS_NETLINK_TCPDIAG_SOCKET 45 +#define SECCLASS_NETLINK_NFLOG_SOCKET 46 +#define SECCLASS_NETLINK_XFRM_SOCKET 47 +#define SECCLASS_NETLINK_SELINUX_SOCKET 48 +#define SECCLASS_NETLINK_AUDIT_SOCKET 49 +#define SECCLASS_NETLINK_IP6FW_SOCKET 50 +#define SECCLASS_NETLINK_DNRT_SOCKET 51 /* * Security identifier indices for initial entities diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 0413683acba26e..5931e46d44e562 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -17,13 +17,14 @@ #define SELINUX_MAGIC 0xf97cff8c /* Identify specific policy version changes */ -#define POLICYDB_VERSION_BASE 15 -#define POLICYDB_VERSION_BOOL 16 -#define POLICYDB_VERSION_IPV6 17 +#define POLICYDB_VERSION_BASE 15 +#define POLICYDB_VERSION_BOOL 16 +#define POLICYDB_VERSION_IPV6 17 +#define POLICYDB_VERSION_NLCLASS 18 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_IPV6 +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NLCLASS #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM extern int selinux_enabled; diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c new file mode 100644 index 00000000000000..08f159cfc7ea8b --- /dev/null +++ b/security/selinux/nlmsgtab.c @@ -0,0 +1,153 @@ +/* + * Netlink message type permission tables, for user generated messages. + * + * Author: James Morris <jmorris@redhat.com> + * + * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/skbuff.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <linux/if.h> +#include <linux/netfilter_ipv4/ip_queue.h> +#include <linux/tcp_diag.h> +#include <linux/xfrm.h> +#include <linux/audit.h> + +#include "flask.h" +#include "av_permissions.h" + +struct nlmsg_perm +{ + u16 nlmsg_type; + u32 perm; +}; + +static struct nlmsg_perm nlmsg_route_perms[] = +{ + { RTM_NEWLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETLINK, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_SETLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_NEWADDR, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELADDR, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETADDR, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWROUTE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELROUTE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETROUTE, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWRULE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELRULE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETRULE, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWQDISC, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELQDISC, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETQDISC, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_NEWPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, + { RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, +}; + +static struct nlmsg_perm nlmsg_firewall_perms[] = +{ + { IPQM_MODE, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE }, + { IPQM_VERDICT, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE }, +}; + +static struct nlmsg_perm nlmsg_tcpdiag_perms[] = +{ + { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, +}; + +static struct nlmsg_perm nlmsg_xfrm_perms[] = +{ + { XFRM_MSG_NEWSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_DELSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_GETSA, NETLINK_XFRM_SOCKET__NLMSG_READ }, + { XFRM_MSG_NEWPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_DELPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_GETPOLICY, NETLINK_XFRM_SOCKET__NLMSG_READ }, + { XFRM_MSG_ALLOCSPI, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_UPDPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, + { XFRM_MSG_UPDSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, +}; + +static struct nlmsg_perm nlmsg_audit_perms[] = +{ + { AUDIT_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, + { AUDIT_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, + { AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READ }, + { AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, + { AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, + { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, + { AUDIT_LOGIN, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, +}; + + +static int nlmsg_perm(u16 nlmsg_type, u32 *perm, struct nlmsg_perm *tab, size_t tabsize) +{ + int i, err = -EINVAL; + + for (i = 0; i < tabsize/sizeof(struct nlmsg_perm); i++) + if (nlmsg_type == tab[i].nlmsg_type) { + *perm = tab[i].perm; + err = 0; + break; + } + + return err; +} + +int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) +{ + int err = 0; + + switch (sclass) { + case SECCLASS_NETLINK_ROUTE_SOCKET: + err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms, + sizeof(nlmsg_route_perms)); + break; + + case SECCLASS_NETLINK_FIREWALL_SOCKET: + case NETLINK_IP6_FW: + err = nlmsg_perm(nlmsg_type, perm, nlmsg_firewall_perms, + sizeof(nlmsg_firewall_perms)); + break; + + case SECCLASS_NETLINK_TCPDIAG_SOCKET: + err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms, + sizeof(nlmsg_tcpdiag_perms)); + break; + + case SECCLASS_NETLINK_XFRM_SOCKET: + err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms, + sizeof(nlmsg_xfrm_perms)); + break; + + case SECCLASS_NETLINK_AUDIT_SOCKET: + err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms, + sizeof(nlmsg_audit_perms)); + break; + + /* No messaging from userspace, or class unknown/unhandled */ + default: + err = -ENOENT; + break; + } + + return err; +} diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index d98bb8dfeb5369..ec140934259109 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -38,6 +38,8 @@ static char *symtab_name[SYM_NUM] = { }; #endif +int policydb_loaded_version; + static unsigned int symtab_sizes[SYM_NUM] = { 2, 32, @@ -71,6 +73,11 @@ static struct policydb_compat_info policydb_compat[] = { .sym_num = SYM_NUM, .ocon_num = OCON_NUM, }, + { + .version = POLICYDB_VERSION_NLCLASS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM, + }, }; static struct policydb_compat_info *policydb_lookup_compat(int version) @@ -1125,7 +1132,7 @@ int policydb_read(struct policydb *p, void *fp) struct role_trans *tr, *ltr; struct ocontext *l, *c, *newc; struct genfs *genfs_p, *genfs, *newgenfs; - int i, j, rc, r_policyvers; + int i, j, rc, r_policyvers = 0; u32 *buf, len, len2, config, nprim, nel, nel2; char *policydb_str; struct policydb_compat_info *info; @@ -1546,6 +1553,7 @@ int policydb_read(struct policydb *p, void *fp) if (rc) goto bad; out: + policydb_loaded_version = r_policyvers; return rc; bad_newc: ocontext_destroy(newc,OCON_FSUSE); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 21ab4c975f6064..2e857b78565ef2 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -40,6 +40,7 @@ #include "mls.h" extern void selnl_notify_policyload(u32 seqno); +extern int policydb_loaded_version; static rwlock_t policy_rwlock = RW_LOCK_UNLOCKED; #define POLICY_RDLOCK read_lock(&policy_rwlock) @@ -203,6 +204,17 @@ static int context_struct_compute_av(struct context *scontext, struct avtab_datum *avdatum; struct class_datum *tclass_datum; + /* + * Remap extended Netlink classes for old policy versions. + * Do this here rather than socket_type_to_security_class() + * in case a newer policy version is loaded, allowing sockets + * to remain in the correct class. + */ + if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) + if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && + tclass <= SECCLASS_NETLINK_DNRT_SOCKET) + tclass = SECCLASS_NETLINK_SOCKET; + if (!tclass || tclass > policydb.p_classes.nprim) { printk(KERN_ERR "security_compute_av: unrecognized class %d\n", tclass); |