Re: [RFC PATCH 1/2] landlock: TCP network hooks implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





2/1/2022 3:28 PM, Mickaël Salaün пишет:

On 26/01/2022 15:15, Willem de Bruijn wrote:
On Wed, Jan 26, 2022 at 3:06 AM Konstantin Meskhidze
<konstantin.meskhidze@xxxxxxxxxx> wrote:



1/25/2022 5:17 PM, Willem de Bruijn пишет:
On Mon, Jan 24, 2022 at 3:02 AM Konstantin Meskhidze
<konstantin.meskhidze@xxxxxxxxxx> wrote:

Support of socket_bind() and socket_connect() hooks.
Current prototype can restrict binding and connecting of TCP
types of sockets. Its just basic idea how Landlock could support
network confinement.

Changes:
1. Access masks array refactored into 1D one and changed
to 32 bits. Filesystem masks occupy 16 lower bits and network
masks reside in 16 upper bits.
2. Refactor API functions in ruleset.c:
      1. Add void *object argument.
      2. Add u16 rule_type argument.
3. Use two rb_trees in ruleset structure:
      1. root_inode - for filesystem objects
      2. root_net_port - for network port objects

Signed-off-by: Konstantin Meskhidze <konstantin.meskhidze@xxxxxxxxxx>

+static int hook_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
+{
+       short socket_type;
+       struct sockaddr_in *sockaddr;
+       u16 port;
+       const struct landlock_ruleset *const dom = landlock_get_current_domain();
+
+       /* Check if the hook is AF_INET* socket's action */
+       if ((address->sa_family != AF_INET) && (address->sa_family != AF_INET6))
+               return 0;

Should this be a check on the socket family (sock->ops->family)
instead of the address family?

Actually connect() function checks address family:

int __inet_stream_connect(... ,struct sockaddr *uaddr ,...) {
...
         if (uaddr) {
                 if (addr_len < sizeof(uaddr->sa_family))
                 return -EINVAL;

                 if (uaddr->sa_family == AF_UNSPEC) {
                         err = sk->sk_prot->disconnect(sk, flags);
                         sock->state = err ? SS_DISCONNECTING :
                         SS_UNCONNECTED;
                 goto out;
                 }
         }

...
}

Right. My question is: is the intent of this feature to be limited to
sockets of type AF_INET(6) or to addresses?

This feature should handle all "TCP" sockets/ports, IPv4 or IPv6 or unspecified, the same way. What do you suggest to not miss corner cases? What are the guarantees about socket types we can trust/rely on?



I would think the first. Then you also want to catch operations on
such sockets that may pass a different address family. AF_UNSPEC is
the known offender that will effect a state change on AF_INET(6)
sockets.

Indeed, Landlock needs to handle this case to avoid bypasses. This must be part of the tests.

 Agree. I will add into tests a case with AF_UNSPEC.




It is valid to pass an address with AF_UNSPEC to a PF_INET(6) socket.
And there are legitimate reasons to want to deny this. Such as passing
a connection to a unprivileged process and disallow it from disconnect
and opening a different new connection.

As far as I know using AF_UNSPEC to unconnect takes effect on
UDP(DATAGRAM) sockets.
To unconnect a UDP socket, we call connect but set the family member of
the socket address structure (sin_family for IPv4 or sin6_family for
IPv6) to AF_UNSPEC. It is the process of calling connect on an already
connected UDP socket that causes the socket to become unconnected.

This RFC patch just supports TCP connections. I need to check the logic
if AF_UNSPEC provided in connenct() function for TCP(STREAM) sockets.
Does it disconnect already established TCP connection?

Thank you for noticing about this issue. Need to think through how
to manage it with Landlock network restrictions for both TCP and UDP
sockets.

AF_UNSPEC also disconnects TCP.


+
+       socket_type = sock->type;
+       /* Check if it's a TCP socket */
+       if (socket_type != SOCK_STREAM)
+               return 0;
+
+       if (!dom)
+               return 0;
+
+       /* Get port value in host byte order */
+       sockaddr = (struct sockaddr_in *)address;
+       port = ntohs(sockaddr->sin_port);
+
+       return check_socket_access(dom, port, LANDLOCK_ACCESS_NET_CONNECT_TCP);
+}
.
.



[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux