New discussions and RFCs should also include netdev and netfilter mailing lists. For people new to Landlock, the goal is to enable unprivileged processes (and then potentially malicious ones) to limit their own network access (i.e. create a security sandbox for themselves).
Thinking more about network access control for Landlock use case, here are better suggestions:
On 14/12/2021 12:51, Mickaël Salaün wrote:
On 14/12/2021 04:49, Konstantin Meskhidze wrote:
quoted
Hi Mickaёl.
I've been thinking about your reply:
quoted
4. Kernel objects.
For filesystem restrictions inodes objects are used to tie landlock rules.
But for socket operations it's preferred to use task_struct object of
a process, cause sockets' inodes are created just after
security_socket_create() hook is called, and if its needed to have
some restriction rule for creating sockets, this rule can't be tied
to a socket inode cause there is no any has been created at the hook's
catching moment, see the sock_create_lite() function below:
- For the file system, we use inodes to identify hierarchies. We can't
- safely rely on stateless objects (e.g. path strings) because the file
- system changes, and then the rules must change with it.
- To identify network objects (from the user point of view), we can rely
- on stateless rule definitions because they may be absolute (i.e. IP
- address), e.g. sandbox process creating a new connection or receveing an
- UDP packet. It is not be the case with UNIX socket if they are come from
- a path (i.e. inode) though. In this case we'll have to use the existing
- file system identification mechanism and probably extend the current FS
- access rights.
- A sandbox is a set of processes handled as "subjects". Generic inet
- rules should not be tied to processes (for now) but on subnets/protocols.
In current Landlock version inodes are the objects to tie rules to.
For network you are saying that we can rely on stateless rule definitions and
rules should be tied to subnets/protocols, not to processes' task_struct objects.
Cause Landlock architecture requires all rules to be tied to a different
kernel objects, and when LSM hooks are caught there must be search
procedure completed in a ruleset's red-black tree structure:
kernel_object -> landlock_object <- landlock_rule <-----landlock_ruleset
What kind of kernel objects do you mean by subnets/protocols?
Do you suggest using sockets' inodes in this case or using network rules
without to be tied to any kernel object?
The subnets/protocols is the definition provided when creating a rule (i.e. the object from the user point of view), but the kernel may relies on other internal representations. I guess datagram packets would need to be matched against IP/port everytime they are received by a sandboxed process, but tagging sockets or their underlying inodes for stream connections make sense.
I don't have experience in the network LSM hooks though, any input is welcome.
quoted
socket_inode -> landlock_object <- landlock_rule <-----landlock_ruleset
OR
landlock_object <- landlock_rule <-----landlock_ruleset
-----Original Message-----
From: Mickaël Salaün <mic@digikod.net>
Sent: Monday, December 13, 2021 4:30 PM
To: Konstantin Meskhidze <redacted>
Cc: linux-security-module@vger.kernel.org; yusongping <redacted>; Artem Kuzin <redacted>
Subject: Re: [RFC PATCH 0/2] Landlock network PoC implementation
Hi Konstantin,
On 10/12/2021 08:21, Konstantin Meskhidze wrote:
[...]
quoted
To sum up, for IPv4 restrictions, we need a new rule type identified
with LANDLOCK_RULE_NET_CIDR4. This will handle a new
struct landlock_net_cidr4_attr {
__u64 allowed_access;
__u32 address; // IPv4
__u8 prefix; // From 0 to 32
__u8 type; // SOCK_DGRAM, SOCK_STREAM
__u16 port;
} __attribute__((packed));
// https://datatracker.ietf.org/doc/html/rfc4632
IP addresses (and subnets) should not be part of a rule, at least for now. Indeed, IP addresses are tied either to the system architecture (e.g. container configuration), the local network or Internet, hence moving targets not controlled by application developers. Moreover, from a kernel point of view, it is more complex to check and handle subnets, which are most of the time tied to the Netfilter infrastructure, not suitable for Landlock because of its unprivileged nature.
On the other side, protocols such as TCP and their associated ports are normalized and are tied to an application semantic (e.g. TCP/443 for HTTPS).
There is other advantages to exclude subnets from this type of rules for now (e.g. they could be composed with protocols/ports), but that may come later.
I then think that a first MVP to bring network access control support to Landlock should focus only on TCP and related ports (i.e. services). I propose to not use my previous definition of landlock_net_cidr4_attr but to have a landlock_net_service_attr instead:
struct landlock_net_service_attr {
__u64 allowed_access; // LANDLOCK_NET_*_TCP
__u16 port;
} __attribute__((packed));
This attribute should handle IPv4 and IPv6 indistinguishably.
[...]
quoted
Accesses/suffixes should be:
- CREATE
- ACCEPT
- BIND
- LISTEN
- CONNECT
- RECEIVE (RECEIVE_FROM and SEND_TO should not be needed)
- SEND
- SHUTDOWN
- GET_OPTION (GETSOCKOPT)
- SET_OPTION (SETSOCKOPT)
For now, the only access rights should be LANDLOCK_ACCESS_NET_BIND_TCP and LANDLOCK_ACCESS_NET_CONNECT_TCP (tie to two LSM hooks with struct sockaddr).
These attribute and access right changes reduce the scope of the network access control and make it simpler but still really useful. Datagram (e.g. UDP, which could add BIND_UDP and SEND_UDP) sockets will be more complex to restrict correctly and should then come in another patch series, once TCP is supported.
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: 2021-12-17 21:29:40
On Fri, Dec 17, 2021 at 4:38 AM Mickaël Salaün [off-list ref] wrote:
New discussions and RFCs should also include netdev and netfilter
mailing lists. For people new to Landlock, the goal is to enable
unprivileged processes (and then potentially malicious ones) to limit
their own network access (i.e. create a security sandbox for themselves).
Thinking more about network access control for Landlock use case, here
are better suggestions:
On 14/12/2021 12:51, Mickaël Salaün wrote:
quoted
On 14/12/2021 04:49, Konstantin Meskhidze wrote:
quoted
Hi Mickaёl.
I've been thinking about your reply:
quoted
4. Kernel objects.
For filesystem restrictions inodes objects are used to tie landlock
rules.
But for socket operations it's preferred to use task_struct object of
a process, cause sockets' inodes are created just after
security_socket_create() hook is called, and if its needed to have
some restriction rule for creating sockets, this rule can't be tied
to a socket inode cause there is no any has been created at the hook's
catching moment, see the sock_create_lite() function below:
- For the file system, we use inodes to identify hierarchies. We can't
- safely rely on stateless objects (e.g. path strings) because the file
- system changes, and then the rules must change with it.
- To identify network objects (from the user point of view), we can rely
- on stateless rule definitions because they may be absolute (i.e. IP
- address), e.g. sandbox process creating a new connection or
receveing an
- UDP packet. It is not be the case with UNIX socket if they are come
from
- a path (i.e. inode) though. In this case we'll have to use the existing
- file system identification mechanism and probably extend the current FS
- access rights.
- A sandbox is a set of processes handled as "subjects". Generic inet
- rules should not be tied to processes (for now) but on
subnets/protocols.
In current Landlock version inodes are the objects to tie rules to.
For network you are saying that we can rely on stateless rule
definitions and
rules should be tied to subnets/protocols, not to processes'
task_struct objects.
Cause Landlock architecture requires all rules to be tied to a different
kernel objects, and when LSM hooks are caught there must be search
procedure completed in a ruleset's red-black tree structure:
kernel_object -> landlock_object <- landlock_rule
<-----landlock_ruleset
What kind of kernel objects do you mean by subnets/protocols?
Do you suggest using sockets' inodes in this case or using network rules
without to be tied to any kernel object?
The subnets/protocols is the definition provided when creating a rule
(i.e. the object from the user point of view), but the kernel may relies
on other internal representations. I guess datagram packets would need
to be matched against IP/port everytime they are received by a sandboxed
process, but tagging sockets or their underlying inodes for stream
connections make sense.
I don't have experience in the network LSM hooks though, any input is
welcome.
quoted
socket_inode -> landlock_object <- landlock_rule
<-----landlock_ruleset
OR
landlock_object <- landlock_rule <-----landlock_ruleset
-----Original Message-----
From: Mickaël Salaün <mic@digikod.net>
Sent: Monday, December 13, 2021 4:30 PM
To: Konstantin Meskhidze <redacted>
Cc: linux-security-module@vger.kernel.org; yusongping
[off-list ref]; Artem Kuzin [off-list ref]
Subject: Re: [RFC PATCH 0/2] Landlock network PoC implementation
Hi Konstantin,
On 10/12/2021 08:21, Konstantin Meskhidze wrote:
[...]
quoted
quoted
To sum up, for IPv4 restrictions, we need a new rule type identified
with LANDLOCK_RULE_NET_CIDR4. This will handle a new
struct landlock_net_cidr4_attr {
__u64 allowed_access;
__u32 address; // IPv4
__u8 prefix; // From 0 to 32
__u8 type; // SOCK_DGRAM, SOCK_STREAM
__u16 port;
} __attribute__((packed));
// https://datatracker.ietf.org/doc/html/rfc4632
IP addresses (and subnets) should not be part of a rule, at least for
now. Indeed, IP addresses are tied either to the system architecture
(e.g. container configuration), the local network or Internet, hence
moving targets not controlled by application developers. Moreover, from
a kernel point of view, it is more complex to check and handle subnets,
which are most of the time tied to the Netfilter infrastructure, not
suitable for Landlock because of its unprivileged nature.
On the other side, protocols such as TCP and their associated ports are
normalized and are tied to an application semantic (e.g. TCP/443 for HTTPS).
There is other advantages to exclude subnets from this type of rules for
now (e.g. they could be composed with protocols/ports), but that may
come later.
I then think that a first MVP to bring network access control support to
Landlock should focus only on TCP and related ports (i.e. services). I
propose to not use my previous definition of landlock_net_cidr4_attr but
to have a landlock_net_service_attr instead:
struct landlock_net_service_attr {
__u64 allowed_access; // LANDLOCK_NET_*_TCP
__u16 port;
} __attribute__((packed));
This attribute should handle IPv4 and IPv6 indistinguishably.
[...]
quoted
quoted
Accesses/suffixes should be:
- CREATE
- ACCEPT
- BIND
- LISTEN
- CONNECT
- RECEIVE (RECEIVE_FROM and SEND_TO should not be needed)
- SEND
- SHUTDOWN
- GET_OPTION (GETSOCKOPT)
- SET_OPTION (SETSOCKOPT)
For now, the only access rights should be LANDLOCK_ACCESS_NET_BIND_TCP
and LANDLOCK_ACCESS_NET_CONNECT_TCP (tie to two LSM hooks with struct
sockaddr).
These attribute and access right changes reduce the scope of the network
access control and make it simpler but still really useful. Datagram
(e.g. UDP, which could add BIND_UDP and SEND_UDP) sockets will be more
complex to restrict correctly and should then come in another patch
series, once TCP is supported.
Thanks for cc:ing the netdev list. I miss some of context, assume that
limits are configured on a socket basis.
One practical use-case I had for voluntary relinquish of privileges:
do not allow connect AF_UNSPEC. This is a little-used feature that
allows an already established connection to disconnect and create a
new connection. Without this option, it is possible for a privileged
process to create connections and hand those off to a less privileged
process. Also, do not allow listen calls, to avoid elevating a socket
to a listener.
From: Konstantin Meskhidze <hidden> Date: 2021-12-18 08:26:20
Hi, Mickaёl
Thanks again for your opinion about minimal Landlock IPv4 network version.
I have already started refactoring the code.
Here are some additional thoughts about the design.
-----Original Message-----
From: Mickaël Salaün <mic@digikod.net>
Sent: Friday, December 17, 2021 5:39 PM
To: Konstantin Meskhidze <redacted>
Cc: yusongping <redacted>; Artem Kuzin <redacted>; linux-security-module <redacted>; Network Development <redacted>; netfilter@vger.kernel.org
Subject: Re: [RFC PATCH 0/2] Landlock network PoC implementation
New discussions and RFCs should also include netdev and netfilter mailing lists. For people new to Landlock, the goal is to enable unprivileged processes (and then potentially malicious ones) to limit their own network access (i.e. create a security sandbox for themselves).
Thinking more about network access control for Landlock use case, here are better suggestions:
On 14/12/2021 12:51, Mickaël Salaün wrote:
On 14/12/2021 04:49, Konstantin Meskhidze wrote:
quoted
Hi Mickaёl.
I've been thinking about your reply:
quoted
4. Kernel objects.
For filesystem restrictions inodes objects are used to tie landlock
rules.
But for socket operations it's preferred to use task_struct object
of a process, cause sockets' inodes are created just after
security_socket_create() hook is called, and if its needed to have
some restriction rule for creating sockets, this rule can't be tied
to a socket inode cause there is no any has been created at the
hook's catching moment, see the sock_create_lite() function below:
- For the file system, we use inodes to identify hierarchies. We
can't
- safely rely on stateless objects (e.g. path strings) because the
file
- system changes, and then the rules must change with it.
- To identify network objects (from the user point of view), we can
rely
- on stateless rule definitions because they may be absolute (i.e. IP
- address), e.g. sandbox process creating a new connection or
receveing an
- UDP packet. It is not be the case with UNIX socket if they are come
from
- a path (i.e. inode) though. In this case we'll have to use the
existing
- file system identification mechanism and probably extend the
current FS
- access rights.
- A sandbox is a set of processes handled as "subjects". Generic inet
- rules should not be tied to processes (for now) but on
subnets/protocols.
In current Landlock version inodes are the objects to tie rules to.
For network you are saying that we can rely on stateless rule
definitions and rules should be tied to subnets/protocols, not to
processes'
task_struct objects.
Cause Landlock architecture requires all rules to be tied to a
different kernel objects, and when LSM hooks are caught there must be
search procedure completed in a ruleset's red-black tree structure:
kernel_object -> landlock_object <- landlock_rule
<-----landlock_ruleset
What kind of kernel objects do you mean by subnets/protocols?
Do you suggest using sockets' inodes in this case or using network
rules without to be tied to any kernel object?
The subnets/protocols is the definition provided when creating a rule
(i.e. the object from the user point of view), but the kernel may
relies on other internal representations. I guess datagram packets
would need to be matched against IP/port everytime they are received
by a sandboxed process, but tagging sockets or their underlying inodes
for stream connections make sense.
I don't have experience in the network LSM hooks though, any input is
welcome.
quoted
socket_inode -> landlock_object <- landlock_rule
<-----landlock_ruleset
OR
landlock_object <- landlock_rule <-----landlock_ruleset
-----Original Message-----
From: Mickaël Salaün <mic@digikod.net>
Sent: Monday, December 13, 2021 4:30 PM
To: Konstantin Meskhidze <redacted>
Cc: linux-security-module@vger.kernel.org; yusongping
[off-list ref]; Artem Kuzin [off-list ref]
Subject: Re: [RFC PATCH 0/2] Landlock network PoC implementation
Hi Konstantin,
On 10/12/2021 08:21, Konstantin Meskhidze wrote:
[...]
quoted
To sum up, for IPv4 restrictions, we need a new rule type identified
with LANDLOCK_RULE_NET_CIDR4. This will handle a new struct
landlock_net_cidr4_attr {
__u64 allowed_access;
__u32 address; // IPv4
__u8 prefix; // From 0 to 32
__u8 type; // SOCK_DGRAM, SOCK_STREAM
__u16 port;
} __attribute__((packed));
// https://datatracker.ietf.org/doc/html/rfc4632
quoted
IP addresses (and subnets) should not be part of a rule, at least for now. Indeed, IP addresses are tied either to the system architecture (e.g. container configuration), the local network or Internet, hence moving targets not >> controlled by application developers. Moreover, from a kernel point of view, it is more complex to check and handle subnets, which are most of the time tied to the Netfilter infrastructure, not suitable for Landlock because >> of its unprivileged nature.
quoted
On the other side, protocols such as TCP and their associated ports are normalized and are tied to an application semantic (e.g. TCP/443 for HTTPS).
quoted
There is other advantages to exclude subnets from this type of rules for now (e.g. they could be composed with protocols/ports), but that may come later.
quoted
I then think that a first MVP to bring network access control support to Landlock should focus only on TCP and related ports (i.e. services). I propose to not use my previous definition of landlock_net_cidr4_attr but to have a >> landlock_net_service_attr instead:
This attribute should handle IPv4 and IPv6 indistinguishably.
[...]
quoted
Accesses/suffixes should be:
- CREATE
- ACCEPT
- BIND
- LISTEN
- CONNECT
- RECEIVE (RECEIVE_FROM and SEND_TO should not be needed)
- SEND
- SHUTDOWN
- GET_OPTION (GETSOCKOPT)
- SET_OPTION (SETSOCKOPT)
quoted
For now, the only access rights should be LANDLOCK_ACCESS_NET_BIND_TCP and LANDLOCK_ACCESS_NET_CONNECT_TCP (tie to two LSM hooks with struct sockaddr).
quoted
These attribute and access right changes reduce the scope of the network access control and make it simpler but still really useful. Datagram (e.g. UDP, which could add BIND_UDP and SEND_UDP) sockets will be more
complex to restrict correctly and should then come in another patch series, once TCP is supported.
I think that having access rights like LANDLOCK_ACCESS_NET_CREATE_TCP_SOCKET_DENY/LANDLOCK_ACCESS_NET_CREATE_UDP_SOCKET_DENY might be useful during initialization phase of container/sandbox, cause a user could have the possibility to restrict the creation of some type of sockets at all, and to reduce the attack surface related to security aspect.
So the logic could be the following:
1. Process restricts creation UDP sockets, allows TCP one.
- LANDLOCK_ACCESS_NET_CREATE_*_SOCKET_DENY rules are tied to process task_struct cause there are no sockets inodes created at this moment.
2. Creates necessary number of sockets.
3. Restricts sockets' access rights.
- LANDLOCK_ACCESS_NET_BIND_* / LANDLOCK_ACCESS_NET_CONNECT_* access rights are tied to sockets inodes individually.
On Fri, Dec 17, 2021 at 4:38 AM Mickaël Salaün [off-list ref] wrote:
[...]
quoted
quoted
quoted
Accesses/suffixes should be:
- CREATE
- ACCEPT
- BIND
- LISTEN
- CONNECT
- RECEIVE (RECEIVE_FROM and SEND_TO should not be needed)
- SEND
- SHUTDOWN
- GET_OPTION (GETSOCKOPT)
- SET_OPTION (SETSOCKOPT)
For now, the only access rights should be LANDLOCK_ACCESS_NET_BIND_TCP
and LANDLOCK_ACCESS_NET_CONNECT_TCP (tie to two LSM hooks with struct
sockaddr).
These attribute and access right changes reduce the scope of the network
access control and make it simpler but still really useful. Datagram
(e.g. UDP, which could add BIND_UDP and SEND_UDP) sockets will be more
complex to restrict correctly and should then come in another patch
series, once TCP is supported.
Thanks for cc:ing the netdev list. I miss some of context, assume that
limits are configured on a socket basis.
One practical use-case I had for voluntary relinquish of privileges:
do not allow connect AF_UNSPEC. This is a little-used feature that
allows an already established connection to disconnect and create a
new connection. Without this option, it is possible for a privileged
process to create connections and hand those off to a less privileged
process. Also, do not allow listen calls, to avoid elevating a socket
to a listener.
Thanks for the heads up. connect + AF_UNSPEC is a nice trick but the security_socket_connect() hook should handle that, and then the LANDOCK_ACCESS_NET_CONNECT_TCP right too. This should be part of tests though.
Hi, Mickaёl
Thanks again for your opinion about minimal Landlock IPv4 network version.
I have already started refactoring the code.
Here are some additional thoughts about the design.
[...]
quoted
quoted
Accesses/suffixes should be:
- CREATE
- ACCEPT
- BIND
- LISTEN
- CONNECT
- RECEIVE (RECEIVE_FROM and SEND_TO should not be needed)
- SEND
- SHUTDOWN
- GET_OPTION (GETSOCKOPT)
- SET_OPTION (SETSOCKOPT)
quoted
quoted
For now, the only access rights should be LANDLOCK_ACCESS_NET_BIND_TCP and LANDLOCK_ACCESS_NET_CONNECT_TCP (tie to two LSM hooks with struct sockaddr).
quoted
quoted
These attribute and access right changes reduce the scope of the network access control and make it simpler but still really useful. Datagram (e.g. UDP, which could add BIND_UDP and SEND_UDP) sockets will be more
complex to restrict correctly and should then come in another patch series, once TCP is supported.
I think that having access rights like LANDLOCK_ACCESS_NET_CREATE_TCP_SOCKET_DENY/LANDLOCK_ACCESS_NET_CREATE_UDP_SOCKET_DENY might be useful during initialization phase of container/sandbox, cause a user could have the possibility to restrict the creation of some type of sockets at all, and to reduce the attack surface related to security aspect.
So the logic could be the following:
1. Process restricts creation UDP sockets, allows TCP one.
- LANDLOCK_ACCESS_NET_CREATE_*_SOCKET_DENY rules are tied to process task_struct cause there are no sockets inodes created at this moment.
2. Creates necessary number of sockets.
3. Restricts sockets' access rights.
- LANDLOCK_ACCESS_NET_BIND_* / LANDLOCK_ACCESS_NET_CONNECT_* access rights are tied to sockets inodes individually.
Reducing the attack surface on the kernel is valuable but not the primary goal of Landlock. seccomp is designed for this task and a seccomp filters can easily forbid creation of specific sockets. We should consider using both Landlock and seccomp, and your use case of denying UDP vs. TCP is good.
Anyway, the LANDLOCK_ACCESS_NET_CREATE_TCP_SOCKET_DENY name in not appropriate. Indeed, mixing "access" and "deny" doesn't make sense. A LANDLOCK_ACCESS_NET_CREATE_TCP access could be useful if we can define such TCP socket semantic, e.g. with a port, which is not possible when creating a socket, and it is OK.
From: Konstantin Meskhidze <hidden> Date: 2021-12-20 03:52:51
Hi, Mickaёl!
-----Original Message-----
From: Mickaël Salaün <mic@digikod.net>
Sent: Saturday, December 18, 2021 7:01 PM
To: Konstantin Meskhidze <redacted>
Cc: yusongping <redacted>; Artem Kuzin <redacted>; linux-security-module <redacted>; Network Development <redacted>; netfilter@vger.kernel.org; Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Subject: Re: [RFC PATCH 0/2] Landlock network PoC implementation
On 18/12/2021 09:26, Konstantin Meskhidze wrote:
Hi, Mickaёl
Thanks again for your opinion about minimal Landlock IPv4 network version.
I have already started refactoring the code.
Here are some additional thoughts about the design.
[...]
quoted
quoted
Accesses/suffixes should be:
- CREATE
- ACCEPT
- BIND
- LISTEN
- CONNECT
- RECEIVE (RECEIVE_FROM and SEND_TO should not be needed)
- SEND
- SHUTDOWN
- GET_OPTION (GETSOCKOPT)
- SET_OPTION (SETSOCKOPT)
quoted
quoted
For now, the only access rights should be LANDLOCK_ACCESS_NET_BIND_TCP and LANDLOCK_ACCESS_NET_CONNECT_TCP (tie to two LSM hooks with struct sockaddr).
quoted
quoted
These attribute and access right changes reduce the scope of the
network access control and make it simpler but still really useful. Datagram (e.g. UDP, which could add BIND_UDP and SEND_UDP) sockets will be more complex to restrict correctly and should then come in another patch series, once TCP is supported.
I think that having access rights like LANDLOCK_ACCESS_NET_CREATE_TCP_SOCKET_DENY/LANDLOCK_ACCESS_NET_CREATE_UDP_SOCKET_DENY might be useful during initialization phase of container/sandbox, cause a user could have the possibility to restrict the creation of some type of sockets at all, and to reduce the attack surface related to security aspect.
So the logic could be the following:
1. Process restricts creation UDP sockets, allows TCP one.
- LANDLOCK_ACCESS_NET_CREATE_*_SOCKET_DENY rules are tied to process task_struct cause there are no sockets inodes created at this moment.
2. Creates necessary number of sockets.
3. Restricts sockets' access rights.
- LANDLOCK_ACCESS_NET_BIND_* / LANDLOCK_ACCESS_NET_CONNECT_* access rights are tied to sockets inodes individually.
Reducing the attack surface on the kernel is valuable but not the primary goal of Landlock. seccomp is designed for this task and a seccomp filters can easily forbid creation of specific sockets. We should consider using > both Landlock and seccomp, and your use case of denying UDP vs. TCP is good.
Anyway, the LANDLOCK_ACCESS_NET_CREATE_TCP_SOCKET_DENY name in not appropriate. Indeed, mixing "access" and "deny" doesn't make sense. A LANDLOCK_ACCESS_NET_CREATE_TCP access could be useful if > > we can define such TCP socket semantic, e.g. with a port, which is not possible when creating a socket, and it is OK.
I think we can define if it’s a TCP or UDP socket in the moment of its creating using TYPE field in socket(domain, TYPE, protocol) function:
- TCP services use SOCK_STREAM type.
- UDP ones use SOCK_DGRAM type.
So we can have LANDLOCK_ACCESS_NET_CREATE_TCP access rule in TCP socket semantic, and therefore check socket_create(domain, SOCK_STREAM, protocol) hook.
The similar rule( LANDLOCK_ACCESS_NET_CREATE_UPD) could be used for recognizing UDP sockets in future patches.
Hi, Mickaёl!
-----Original Message-----
From: Mickaël Salaün <mic@digikod.net>
Sent: Saturday, December 18, 2021 7:01 PM
To: Konstantin Meskhidze <redacted>
Cc: yusongping <redacted>; Artem Kuzin <redacted>; linux-security-module <redacted>; Network Development <redacted>; netfilter@vger.kernel.org; Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Subject: Re: [RFC PATCH 0/2] Landlock network PoC implementation
On 18/12/2021 09:26, Konstantin Meskhidze wrote:
quoted
Hi, Mickaёl
Thanks again for your opinion about minimal Landlock IPv4 network version.
I have already started refactoring the code.
Here are some additional thoughts about the design.
[...]
quoted
quoted
quoted
Accesses/suffixes should be:
- CREATE
- ACCEPT
- BIND
- LISTEN
- CONNECT
- RECEIVE (RECEIVE_FROM and SEND_TO should not be needed)
- SEND
- SHUTDOWN
- GET_OPTION (GETSOCKOPT)
- SET_OPTION (SETSOCKOPT)
quoted
quoted
For now, the only access rights should be LANDLOCK_ACCESS_NET_BIND_TCP and LANDLOCK_ACCESS_NET_CONNECT_TCP (tie to two LSM hooks with struct sockaddr).
quoted
quoted
These attribute and access right changes reduce the scope of the
network access control and make it simpler but still really useful. Datagram (e.g. UDP, which could add BIND_UDP and SEND_UDP) sockets will be more complex to restrict correctly and should then come in another patch series, once TCP is supported.
I think that having access rights like LANDLOCK_ACCESS_NET_CREATE_TCP_SOCKET_DENY/LANDLOCK_ACCESS_NET_CREATE_UDP_SOCKET_DENY might be useful during initialization phase of container/sandbox, cause a user could have the possibility to restrict the creation of some type of sockets at all, and to reduce the attack surface related to security aspect.
So the logic could be the following:
1. Process restricts creation UDP sockets, allows TCP one.
- LANDLOCK_ACCESS_NET_CREATE_*_SOCKET_DENY rules are tied to process task_struct cause there are no sockets inodes created at this moment.
2. Creates necessary number of sockets.
3. Restricts sockets' access rights.
- LANDLOCK_ACCESS_NET_BIND_* / LANDLOCK_ACCESS_NET_CONNECT_* access rights are tied to sockets inodes individually.
quoted
Reducing the attack surface on the kernel is valuable but not the primary goal of Landlock. seccomp is designed for this task and a seccomp filters can easily forbid creation of specific sockets. We should consider using > both Landlock and seccomp, and your use case of denying UDP vs. TCP is good.
quoted
Anyway, the LANDLOCK_ACCESS_NET_CREATE_TCP_SOCKET_DENY name in not appropriate. Indeed, mixing "access" and "deny" doesn't make sense. A LANDLOCK_ACCESS_NET_CREATE_TCP access could be useful if > > we can define such TCP socket semantic, e.g. with a port, which is not possible when creating a socket, and it is OK.
I think we can define if it’s a TCP or UDP socket in the moment of its creating using TYPE field in socket(domain, TYPE, protocol) function:
- TCP services use SOCK_STREAM type.
- UDP ones use SOCK_DGRAM type.
So we can have LANDLOCK_ACCESS_NET_CREATE_TCP access rule in TCP socket semantic, and therefore check socket_create(domain, SOCK_STREAM, protocol) hook.
The similar rule( LANDLOCK_ACCESS_NET_CREATE_UPD) could be used for recognizing UDP sockets in future patches.
Allowing or forbidding socket creation is easy (and can also be done with seccomp), but it is not an access control per se (i.e. a socket doesn't give access to any data, but communicating with a peer does). Restricting access to network peers makes sense for Landlock, but not (only) file descriptor creation for now. In the future, this kind of restriction could make sense to implement Capsicum but it would probably be another interface.