Bug 628557 - SELinux policy denies icecast daemon to make TCP connection
Summary: SELinux policy denies icecast daemon to make TCP connection
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: selinux-policy
Version: 13
Hardware: All
OS: Linux
low
medium
Target Milestone: ---
Assignee: Miroslav Grepl
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2010-08-30 11:45 UTC by Petr Pisar
Modified: 2010-09-22 00:38 UTC (History)
3 users (show)

Fixed In Version: selinux-policy-3.7.19-57.fc13
Clone Of:
Environment:
Last Closed: 2010-09-22 00:38:10 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)

Description Petr Pisar 2010-08-30 11:45:46 UTC
Define a on-demand mount point in /etc/icecast.xml, e.g.:

    <relay>
        <server>amp1.cesnet.cz</server>
        <port>8000</port>
        <mount>/cro-d-dur-256.ogg</mount>
        <local-mount>/cro_d_dur-256-ipv4.ogg</local-mount>
        <relay-shoutcast-metadata>1</relay-shoutcast-metadata>
    </relay>

and run a music client to connect to the mount-point:

mplayer -cache 32 'http://localhost:8000/cro_d_dur-256-ipv4.ogg'

The /usr/bin/icecast deamon will be blocked by SELinux to connect to uplink server (TCP/amp1.cesnet.cz:8000).

This should be fixed as icecast daemon is supposed to initiate TCP connections.

adit.log:

type=AVC msg=audit(1283168337.935:22642): avc:  denied  { name_connect } for  pid=21319 comm="icecast" dest=8000 scontext=unconfined_u:system_r:icecast_t:s0 tcontext=system_u:object_r:soundd_port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1283168337.935:22642): arch=c000003e syscall=42 success=no exit=-13 a0=1 a1=7fbf9c000b90 a2=10 a3=7fbfb82f7970 items=0 ppid=1 pid=21319 auid=500 uid=490 gid=0 euid=490 suid=490 fsuid=490 egid=0 sgid=0 fsgid=0 tty=(none) ses=1 comm="icecast" exe="/usr/bin/icecast" subj=unconfined_u:system_r:icecast_t:s0 key=(null)

strace:

[pid 21319] connect(1, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = 0
[pid 21319] connect(1, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = 0
[pid 21319] connect(1, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr("195.113.161.81")}, 16) = -1 EACCES (Permission denied)

icecast/error.log:
[2010-08-30  13:38:57] WARN slave/open_relay_connection Failed to connect to amp1.cesnet.cz:8000

Comment 1 Petr Pisar 2010-08-30 11:47:32 UTC
The /usr/bin/icecast daemon comes from icecast package and its label is system_u:object_r:icecast_exec_t:s0.

Comment 2 Daniel Walsh 2010-08-30 12:42:00 UTC
Which ports besides the sound_port(8000) should it be allowed to connect?

Comment 3 Daniel Walsh 2010-08-30 12:45:04 UTC
Miroslav looks like it already binds sound port so add

corenet_tcp_connect_soundd_port(icecast_t)

Comment 4 Petr Pisar 2010-08-30 12:52:42 UTC
Icecast is like a proxy. It listens on a socket and connects from different sockets to anywhere in the Internet. In addition, it acts like push proxy, where so called `source clients' connect to the icecast (to the same port as icecast listens for standard clients) and pushes multimedia to the server. And next, there is other feature: icecast can publish all of it's mount points on remote stream directory (a directory provided by Xiph organization).

I think forcing icecast to connect from a specific socket is wrong idea as one can have IPv6 only parent and IPv4 only clients (or vice versa).

Comment 5 Miroslav Grepl 2010-09-01 10:05:25 UTC
Fixed in selinux-policy-3.7.19-53.fc13.

Comment 6 Petr Pisar 2010-09-06 08:43:50 UTC
Just installed selinux-policy-3.7.19-54.fc13.noarch, restored original label for the executable and found out icecast daemon could connect to TCP port 8000 but any other ports.

The audit.log message is the same:

type=AVC msg=audit(1283761002.271:22640): avc:  denied  { name_connect } for  pid=3927 comm="icecast" dest=80 scontext=unconfined_u:system_r:icecast_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1283761002.271:22640): arch=c000003e syscall=42 success=yes exit=68719476864 a0=7 a1=7f885c0307e0 a2=10 a3=7f887796bbbc items=0 ppid=1 pid=3927 auid=500 uid=490 gid=501 euid=490 suid=490 fsuid=490 egid=501 sgid=501 fsgid=501 tty=(none) ses=1 comm="icecast" exe="/usr/bin/icecast" subj=unconfined_u:system_r:icecast_t:s0 key=(null)

or:

type=AVC msg=audit(1283762512.616:22643): avc:  denied  { name_connect } for  pid=4556 comm="icecast" dest=900 scontext=unconfined_u:system_r:icecast_t:s0 tcontext=system_u:object_r:hi_reserved_port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1283762512.616:22643): arch=c000003e syscall=42 success=no exit=-13 a0=7 a1=7f885c015be0 a2=10 a3=7f887796bbbc items=0 ppid=1 pid=4556 auid=500 uid=490 gid=501 euid=490 suid=490 fsuid=490 egid=501 sgid=501 fsgid=501 tty=(none) ses=1 comm="icecast" exe="/usr/bin/icecast" subj=unconfined_u:system_r:icecast_t:s0 key=(null)

As I said icecast daemon must be able to connect to _any_ TCP port. Port 8000 is just a number from default icecast configuration.

Comment 7 Miroslav Grepl 2010-09-07 10:44:42 UTC
Let's add

corenet_tcp_connect_http_port(icecast_t)
corenet_tcp_connect_http_cache_port(iceast_t)

which is the default option from the icecast.xml conf file and I believe this is common option. But I don't think icecast should be able to connect to _any_ TCP port by default. 


From the icecast doc:

port - state the port to connect to, this will be the port icecast is listening on, typically 8000 but can be any. 


So I would suggest to add

## <desc>
## <p>
## Allow icecast to connect to all ports.
## </p>
## </desc>
gen_tunable(icecast_connect_any, false)

tunable_policy(`icecast_connect_any',`
        corenet_tcp_connect_all_ports(icecast_t)
        corenet_sendrecv_all_client_packets(icecast_t)
')

Comment 8 Petr Pisar 2010-09-07 11:05:16 UTC
Icecast implements ICY protocol that looks as HTTP, but it isn't HTTP. Even Squid provides special patches to add support for ICY.

ICY is implemented by Shoutcast server too. It's successful commercial implementation used by stream service providers. They bind they sockets to really random ports, a lot of times running tens servers on one machine occupying whole series of TCP ports. Icecast when configured as relay is supposed to connect to these ports.

Thus I do not see any reason why icecast should be restricted to few ports. This is like restricting telnet client to port 23.

Here is statistics from my relay:
  Count Port
     61 80
      2 443
      1 900
      2 3000
      4 4040
      1 4086
      1 5000
      1 5222
      1 5926
      1 6626
      2 7000
      1 7124
      1 7146
      1 7592
      1 7978
      1 7992
      1 7996
    132 8000
      5 8001
      1 8006
      5 8008
      3 8010
      1 8030
      2 8038
      1 8048
      4 8050
      1 8060
      1 8070
      4 8080
      1 8081
      1 8082
      1 8083
      2 8090
      4 8100
      1 8106
      1 8108
      1 8124
      1 8160
      1 8190
      1 8272
      1 8400
      2 8460
      7 8500
      1 8555
      1 8611
      1 8814
      1 8888
      4 9000
      1 9004
      1 9030
      1 9622
      1 9999
      2 19000
      1 19581
      1 23613
      1 23615

Comment 9 Daniel Walsh 2010-09-07 15:35:42 UTC
Except telnet is not a server, and I believe it would be perfectly valid to configure telnet policy to allow it to only connect to port 23.  The same argument could be made for httpd or sshd, having the ability to listen on any port,  If you feel that icecast could be setup to forward to any port then we should add a boolean, like we do for squid.  We are trying to lock down the system.  If every service has to be able to connect and bind to every port because they possible could be setup that way, then we might as well turn off the protection of that daemon.

Comment 10 Daniel Walsh 2010-09-07 15:59:47 UTC
Miroslav lets add

## <desc>
## <p>
## Allow icecast to connect to all ports, not just
## sound ports.
## </p>
## </desc>
gen_tunable(icecast_connect_any, false)

tunable_policy(`icecast_connect_any',`
	corenet_tcp_connect_all_ports(icecast_t)
	corenet_tcp_bind_all_ports(icecast_t)
	corenet_sendrecv_all_packets(icecast_t)
')

Comment 11 Petr Pisar 2010-09-08 13:05:01 UTC
Regarding telnet client you are completely wrong as there is lot of protocols based on telnet and administrators use telnet to manually interact with servers (e.g. sending e-mails).

However I understand the purpose of confining daemons. And I agree that administrator should be able to adapt the policy for his system as much as possible.

Thus I believe the tunable_policy boolean is configurable by root. I'm not experienced with SELinux. Am I right there is a file under /etc/selinux where I can redefine the `icecast_connect_any' variable and then reload policies to fit for my needs (i.e. allow icecast daemon to connect to non-8000 port)?

Comment 12 Daniel Walsh 2010-09-08 15:57:13 UTC
No you can execute 

setsebool -P icecast_connect_any 1

Which uses /selinux/booleans directory to tell the kernel to turn on/off the boolean.  It also recompiles the policy if you use the -P qualifier.

Comment 13 Petr Pisar 2010-09-08 16:54:36 UTC
Excuse me I use this report as SELinux tutorial. What will happen with compiled policy if new selinux-policy package is installed? Will I lose the boolean settings? If not, then list of booleans must be stored somewhere. Where? Why policy recompilation and permanent boolean settings are manipulated at one step (setsebool -P)?

Comment 14 Daniel Walsh 2010-09-08 17:40:35 UTC
Updates to selinux-policy will not alter the boolean settings.

If you do not use the -P qualifier, a reboot would go back to the default settings.

/etc/selinux/targeted/modules/active/booleans.local

Comment 15 Miroslav Grepl 2010-09-09 11:13:47 UTC
Fixed in selinux-policy-3.7.19-55.fc13.

Comment 16 Fedora Update System 2010-09-13 16:08:25 UTC
selinux-policy-3.7.19-57.fc13 has been submitted as an update for Fedora 13.
https://admin.fedoraproject.org/updates/selinux-policy-3.7.19-57.fc13

Comment 17 Fedora Update System 2010-09-15 05:29:42 UTC
selinux-policy-3.7.19-57.fc13 has been pushed to the Fedora 13 testing repository.  If problems still persist, please make note of it in this bug report.
 If you want to test the update, you can install it with 
 su -c 'yum --enablerepo=updates-testing update selinux-policy'.  You can provide feedback for this update here: https://admin.fedoraproject.org/updates/selinux-policy-3.7.19-57.fc13

Comment 18 Greg 2010-09-17 18:27:38 UTC
I've applied selinux-policy-3.7.19-57.fc13 and then ran `setsebool icecast_connect_any 1`.  I am now able to connect the icecast without selinux blocking&complaining.

Without 'icecast_connect_any 1'  selinux gives the following message


avc:  denied  { name_connect } for  pid=2995 comm="icecast" dest=8052 scontext=unconfined_u:system_r:icecast_t:s0 tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1284746034.504:26308): arch=c000003e syscall=42 success=no exit=-13 a0=1 a1=7fe710001120 a2=10 a3=7fe72ea62970 items=0 ppid=1 pid=2995 auid=500 uid=489 gid=485 euid=489 suid=489 fsuid=489 egid=485 sgid=485 fsgid=485 tty=(none) ses=1 comm="icecast" exe="/usr/bin/icecast" subj=unconfined_u:system_r:icecast_t:s0 key=(null)


The tcp port 8052 that icecast is trying to connect to above, is the port on the remote icecast server.

client --> local icecast --> remote icecast server
local icecast(running on fedora 13 box) is listening on port 8888
remote icecast server(some random internet radio station) is listening on port 8052

This configuration has icecast acting as a sort of proxy server.  Maybe borrowing the rules that allow squid to make outbound connections would work for icecast in this scenario?

Or for a tighter configuration... some sort of knob that allows the administrator to list which ports icecast can connect to remotely.  The remote ports would be listed in /etc/icecast.xml

just my two bits

Comment 19 Fedora Update System 2010-09-22 00:37:08 UTC
selinux-policy-3.7.19-57.fc13 has been pushed to the Fedora 13 stable repository.  If problems still persist, please make note of it in this bug report.


Note You need to log in before you can comment on or make changes to this bug.