and associated inet_is_local_unbindable_port() helper function:
use it to make explicitly binding to an unbindable port return
-EPERM 'Operation not permitted'.
Autobind doesn't honour this new sysctl since:
(a) you can simply set both if that's the behaviour you desire
(b) there could be a use for preventing explicit while allowing auto
(c) it's faster in the relatively critical path of doing port selection
during connect() to only check one bitmap instead of both
Various ports may have special use cases which are not suitable for
use by general userspace applications. Currently, ports specified in
ip_local_reserved_ports sysctl will not be returned only in case of
automatic port assignment, but nothing prevents you from explicitly
binding to them - even from an entirely unprivileged process.
In certain cases it is desirable to prevent the host from assigning the
ports even in case of explicit binds, even from superuser processes.
Example use cases might be:
- a port being stolen by the nic for remote serial console, remote
power management or some other sort of debugging functionality
(crash collection, gdb, direct access to some other microcontroller
on the nic or motherboard, remote management of the nic itself).
- a transparent proxy where packets are being redirected: in case
a socket matches this connection, packets from this application
would be incorrectly sent to one of the endpoints.
Initially I wanted to solve this problem via the simple one line:
static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port) {
- return port < net->ipv4.sysctl_ip_prot_sock;
+ return port < net->ipv4.sysctl_ip_prot_sock || inet_is_local_reserved_port(net, port);
}
However, this doesn't work for two reasons:
(a) it changes userspace visible behaviour of the existing local
reserved ports sysctl, and there appears to be enough documentation
on the internet talking about setting it to make this a bad idea
(b) it doesn't prevent privileged apps from using these ports,
CAP_BIND_SERVICE is relatively likely to be available to, for example,
a recursive DNS server so it can listed on port 53, which also needs
to do src port randomization for outgoing queries due to security
reasons (and it thus does manual port binding).
If we *know* that certain ports are simply unusable, then it's better
nothing even gets the opportunity to try to use them. This way we at
least get a quick failure, instead of some sort of timeout (or possibly
even corruption of the data stream of the non-kernel based use case).
Test:
vm:~# cat /proc/sys/net/ipv4/ip_local_unbindable_ports
vm:~# python -c 'import socket; s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0); s.bind(("::", 3967))'
vm:~# python -c 'import socket; s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, 0); s.bind(("::", 3967))'
vm:~# echo 3967 > /proc/sys/net/ipv4/ip_local_unbindable_ports
vm:~# cat /proc/sys/net/ipv4/ip_local_unbindable_ports
3967
vm:~# python -c 'import socket; s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0); s.bind(("::", 3967))'
socket.error: (1, 'Operation not permitted')
vm:~# python -c 'import socket; s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, 0); s.bind(("::", 3967))'
socket.error: (1, 'Operation not permitted')
Cc: Sean Tranchetti <stranche@codeaurora.org>
Cc: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Linux SCTP <linux-sctp@vger.kernel.org>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Bug: 140404597
Change-Id: Ie96207bea90ae1345adf7b45724d0caf4d6e52c2
Signed-off-by: Todd Kjos <tkjos@google.com>
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
(cherry picked from commit 8a4b8ea595a515e6360dfccdb99cec2a1fed08c0)
232 lines
5.7 KiB
C
232 lines
5.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* ipv4 in net namespaces
|
|
*/
|
|
|
|
#ifndef __NETNS_IPV4_H__
|
|
#define __NETNS_IPV4_H__
|
|
|
|
#include <linux/uidgid.h>
|
|
#include <net/inet_frag.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/siphash.h>
|
|
#include <linux/android_kabi.h>
|
|
|
|
struct ctl_table_header;
|
|
struct ipv4_devconf;
|
|
struct fib_rules_ops;
|
|
struct hlist_head;
|
|
struct fib_table;
|
|
struct sock;
|
|
struct local_ports {
|
|
seqlock_t lock;
|
|
int range[2];
|
|
bool warned;
|
|
};
|
|
|
|
struct ping_group_range {
|
|
seqlock_t lock;
|
|
kgid_t range[2];
|
|
};
|
|
|
|
struct inet_hashinfo;
|
|
|
|
struct inet_timewait_death_row {
|
|
atomic_t tw_count;
|
|
char tw_pad[L1_CACHE_BYTES - sizeof(atomic_t)];
|
|
|
|
struct inet_hashinfo *hashinfo;
|
|
int sysctl_max_tw_buckets;
|
|
};
|
|
|
|
struct tcp_fastopen_context;
|
|
|
|
struct netns_ipv4 {
|
|
/* Please keep tcp_death_row at first field in netns_ipv4 */
|
|
struct inet_timewait_death_row tcp_death_row ____cacheline_aligned_in_smp;
|
|
|
|
#ifdef CONFIG_SYSCTL
|
|
struct ctl_table_header *forw_hdr;
|
|
struct ctl_table_header *frags_hdr;
|
|
struct ctl_table_header *ipv4_hdr;
|
|
struct ctl_table_header *route_hdr;
|
|
struct ctl_table_header *xfrm4_hdr;
|
|
#endif
|
|
struct ipv4_devconf *devconf_all;
|
|
struct ipv4_devconf *devconf_dflt;
|
|
struct ip_ra_chain __rcu *ra_chain;
|
|
struct mutex ra_mutex;
|
|
#ifdef CONFIG_IP_MULTIPLE_TABLES
|
|
struct fib_rules_ops *rules_ops;
|
|
struct fib_table __rcu *fib_main;
|
|
struct fib_table __rcu *fib_default;
|
|
unsigned int fib_rules_require_fldissect;
|
|
bool fib_has_custom_rules;
|
|
#endif
|
|
bool fib_has_custom_local_routes;
|
|
bool fib_offload_disabled;
|
|
#ifdef CONFIG_IP_ROUTE_CLASSID
|
|
atomic_t fib_num_tclassid_users;
|
|
#endif
|
|
struct hlist_head *fib_table_hash;
|
|
struct sock *fibnl;
|
|
|
|
struct sock * __percpu *icmp_sk;
|
|
struct sock *mc_autojoin_sk;
|
|
|
|
struct inet_peer_base *peers;
|
|
struct sock * __percpu *tcp_sk;
|
|
struct fqdir *fqdir;
|
|
|
|
u8 sysctl_icmp_echo_ignore_all;
|
|
u8 sysctl_icmp_echo_enable_probe;
|
|
u8 sysctl_icmp_echo_ignore_broadcasts;
|
|
u8 sysctl_icmp_ignore_bogus_error_responses;
|
|
u8 sysctl_icmp_errors_use_inbound_ifaddr;
|
|
int sysctl_icmp_ratelimit;
|
|
int sysctl_icmp_ratemask;
|
|
|
|
struct local_ports ip_local_ports;
|
|
|
|
u8 sysctl_tcp_ecn;
|
|
u8 sysctl_tcp_ecn_fallback;
|
|
|
|
u8 sysctl_ip_default_ttl;
|
|
u8 sysctl_ip_no_pmtu_disc;
|
|
u8 sysctl_ip_fwd_use_pmtu;
|
|
u8 sysctl_ip_fwd_update_priority;
|
|
u8 sysctl_ip_nonlocal_bind;
|
|
u8 sysctl_ip_autobind_reuse;
|
|
/* Shall we try to damage output packets if routing dev changes? */
|
|
u8 sysctl_ip_dynaddr;
|
|
u8 sysctl_ip_early_demux;
|
|
#ifdef CONFIG_NET_L3_MASTER_DEV
|
|
u8 sysctl_raw_l3mdev_accept;
|
|
#endif
|
|
u8 sysctl_tcp_early_demux;
|
|
u8 sysctl_udp_early_demux;
|
|
|
|
u8 sysctl_nexthop_compat_mode;
|
|
|
|
u8 sysctl_fwmark_reflect;
|
|
u8 sysctl_tcp_fwmark_accept;
|
|
#ifdef CONFIG_NET_L3_MASTER_DEV
|
|
u8 sysctl_tcp_l3mdev_accept;
|
|
#endif
|
|
u8 sysctl_tcp_mtu_probing;
|
|
int sysctl_tcp_mtu_probe_floor;
|
|
int sysctl_tcp_base_mss;
|
|
int sysctl_tcp_min_snd_mss;
|
|
int sysctl_tcp_probe_threshold;
|
|
u32 sysctl_tcp_probe_interval;
|
|
|
|
int sysctl_tcp_keepalive_time;
|
|
int sysctl_tcp_keepalive_intvl;
|
|
u8 sysctl_tcp_keepalive_probes;
|
|
|
|
u8 sysctl_tcp_syn_retries;
|
|
u8 sysctl_tcp_synack_retries;
|
|
u8 sysctl_tcp_syncookies;
|
|
u8 sysctl_tcp_migrate_req;
|
|
int sysctl_tcp_reordering;
|
|
u8 sysctl_tcp_retries1;
|
|
u8 sysctl_tcp_retries2;
|
|
u8 sysctl_tcp_orphan_retries;
|
|
u8 sysctl_tcp_tw_reuse;
|
|
int sysctl_tcp_fin_timeout;
|
|
unsigned int sysctl_tcp_notsent_lowat;
|
|
u8 sysctl_tcp_sack;
|
|
u8 sysctl_tcp_window_scaling;
|
|
u8 sysctl_tcp_timestamps;
|
|
u8 sysctl_tcp_early_retrans;
|
|
u8 sysctl_tcp_recovery;
|
|
u8 sysctl_tcp_thin_linear_timeouts;
|
|
u8 sysctl_tcp_slow_start_after_idle;
|
|
u8 sysctl_tcp_retrans_collapse;
|
|
u8 sysctl_tcp_stdurg;
|
|
u8 sysctl_tcp_rfc1337;
|
|
u8 sysctl_tcp_abort_on_overflow;
|
|
u8 sysctl_tcp_fack; /* obsolete */
|
|
int sysctl_tcp_max_reordering;
|
|
int sysctl_tcp_adv_win_scale;
|
|
u8 sysctl_tcp_dsack;
|
|
u8 sysctl_tcp_app_win;
|
|
u8 sysctl_tcp_frto;
|
|
u8 sysctl_tcp_nometrics_save;
|
|
u8 sysctl_tcp_no_ssthresh_metrics_save;
|
|
u8 sysctl_tcp_moderate_rcvbuf;
|
|
u8 sysctl_tcp_tso_win_divisor;
|
|
u8 sysctl_tcp_workaround_signed_windows;
|
|
int sysctl_tcp_limit_output_bytes;
|
|
int sysctl_tcp_challenge_ack_limit;
|
|
int sysctl_tcp_min_rtt_wlen;
|
|
u8 sysctl_tcp_min_tso_segs;
|
|
u8 sysctl_tcp_autocorking;
|
|
u8 sysctl_tcp_reflect_tos;
|
|
u8 sysctl_tcp_comp_sack_nr;
|
|
int sysctl_tcp_invalid_ratelimit;
|
|
int sysctl_tcp_pacing_ss_ratio;
|
|
int sysctl_tcp_pacing_ca_ratio;
|
|
int sysctl_tcp_wmem[3];
|
|
int sysctl_tcp_rmem[3];
|
|
unsigned long sysctl_tcp_comp_sack_delay_ns;
|
|
unsigned long sysctl_tcp_comp_sack_slack_ns;
|
|
int sysctl_max_syn_backlog;
|
|
int sysctl_tcp_fastopen;
|
|
const struct tcp_congestion_ops __rcu *tcp_congestion_control;
|
|
struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
|
|
unsigned int sysctl_tcp_fastopen_blackhole_timeout;
|
|
atomic_t tfo_active_disable_times;
|
|
unsigned long tfo_active_disable_stamp;
|
|
|
|
int sysctl_udp_wmem_min;
|
|
int sysctl_udp_rmem_min;
|
|
|
|
u8 sysctl_fib_notify_on_flag_change;
|
|
|
|
#ifdef CONFIG_NET_L3_MASTER_DEV
|
|
u8 sysctl_udp_l3mdev_accept;
|
|
#endif
|
|
|
|
u8 sysctl_igmp_llm_reports;
|
|
int sysctl_igmp_max_memberships;
|
|
int sysctl_igmp_max_msf;
|
|
int sysctl_igmp_qrv;
|
|
|
|
struct ping_group_range ping_group_range;
|
|
|
|
atomic_t dev_addr_genid;
|
|
|
|
#ifdef CONFIG_SYSCTL
|
|
unsigned long *sysctl_local_reserved_ports;
|
|
unsigned long *sysctl_local_unbindable_ports;
|
|
int sysctl_ip_prot_sock;
|
|
#endif
|
|
|
|
#ifdef CONFIG_IP_MROUTE
|
|
#ifndef CONFIG_IP_MROUTE_MULTIPLE_TABLES
|
|
struct mr_table *mrt;
|
|
#else
|
|
struct list_head mr_tables;
|
|
struct fib_rules_ops *mr_rules_ops;
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
|
u32 sysctl_fib_multipath_hash_fields;
|
|
u8 sysctl_fib_multipath_use_neigh;
|
|
u8 sysctl_fib_multipath_hash_policy;
|
|
#endif
|
|
|
|
struct fib_notifier_ops *notifier_ops;
|
|
unsigned int fib_seq; /* protected by rtnl_mutex */
|
|
|
|
struct fib_notifier_ops *ipmr_notifier_ops;
|
|
unsigned int ipmr_seq; /* protected by rtnl_mutex */
|
|
|
|
atomic_t rt_genid;
|
|
siphash_key_t ip_id_key;
|
|
|
|
ANDROID_KABI_RESERVE(1);
|
|
};
|
|
#endif
|