You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
all: announce end of support for old Linux versions #60792
New Linux versions get released over time, and old ones cannot be supported indefinitely. This is the tracking recurring issue for announcing end of support for very old versions that we decide to drop support for. (The corresponding tracking issues for macOS and Windows, the other two OSes that have first class ports, are #23011 and #52188.)
The most recent change was applied in Go 1.18, where proposal #45964 increased the minimum Linux kernel version requirement from 2.6.23 to 2.6.32. See https://go.dev/doc/go1.18#linux.
Just a note that the case for Linux is a bit different than that for macOS and Windows, as Linux does not have a sole vendor. We need to identify organizations that distribute older versions of Linux that are supported and used. For example, I believe that we should continue to support all versions of Linux that are actively supported by commercial organizations, such as RHEL or Suse Linux Enterprise Server, and also all versions of Linux that are actively supported by communities supporting stable versions, such as Rocky Linux. Of course the nature of Linux is such that the set of active organizations changes over time.
Reacted by Dmitri Shuralyov, Alberto Donizetti, Ahmed W., Tobias Klauser, Meng Zhuo, Brian Wojtczak and Xiaofan Hu
For reference some facts about distros, and the kernel changes tangential to Go and userland.
Centos 7 - Linux 3.10
Centos 7: Released: 2014-07-07 , Full updates ended: 2020-08-06, Maintenance updates EOL: 2024-06-30
(Centos 8 is in maintenance for about a year now, and Centos 9 is current version)
Debian 9 - Linux 4.9
Debian 9.0 (codename Stretch) was initially released on June 17th, 2017. Last major update was Debian 9.13 was released [July 18th, 2020. Stretch had Long Term Support (LTS) until the end of June 2022.
Current stable Debian is version 12.2. So Debian 9.x is really ancient actually.
Debian 8 (Jessie), from 2015, had Linux 3.16.7-ckt9 in the 8.0
Ubuntu 16.04.7 LTS (initial relase of 16.04 - 2016-04-21; with latest minor bump 16.04.7 - August 13, 2020) - End of standard support: April 2021, EOL: April 2026
OpenSUSE 13.1, released 2013-11-19, end of life 2016-01, Linux 3.11.6
Oracle Linux 7 - initial release, Jul 2014, about same time as RHEL 7/ Centos. Extended support, Jun 2026. But if you pay, they will support you indefinitively (even on older version than 7), and it is likely there are people having such support in various industries. It is unlikely they run Go programs, and if they do, they will likely run older Go version for this anyway.
Also of note is that Oracle Linux 6.x, latest release, 6.10 from July 2018, has updated kernels, including 4.1.12, 2.6.39, and not just 2.6.32 (as RHEL 6).
These are the major ones that might be running and be sometimes hard to upgrade. Other distributions are more desktop and normal user focused, and update way faster, and earlier, and do not have LTS often. So it is close to 0% they would use old system or kernel.
For example, 3.10 would be like 20 major releases ago in world of Fedora, or Ubuntu.
The biggest risk would be probably various mobile and embedded arm devices, like Android, SBCs, routers, etc.
Linux 3.10 was release 30 June 2013, and was 10th LTS release. EOLed November 2017. Red Hat was maintaining own version of 3.10 (with backports from newer kernels, including some syscalls that were not originally in any upstream 3.10 release) until very recently.
Personally, I do not use any of these ancient systems. (Where I work, we migrated from Centos 7, about 2.5 years ago, and almost migrated from Centos 8 to Centos 9 to, already on some parts of our infra, but migrate on demand slowly instead). In other places, I run Debian 12, and still few Debian 11 systems, that could be updated anytime, but just wait their time.
Notable features added between 2.6.32 and 3.10, that might be semi related to userland go runtime
3.10:
memory mapped netlink I/O
Add new "perf mem" command for memory access profiling
POSIX and high-resolution timers support a new clock (CLOCK_TAI) which operates in international atomic time
Applications within control groups can now request memory pressure notifications when the system is running low on available memory
Make madvise(MADV_WILLNEED) support swap file prefetch
3.9
TCP and UDP sockets have a new option, SO_REUSEPORT, that allows multiple sockets listening for new connections or packets (respectively) at the same time
The PowerPC architecture supports a new set of transactional memory instructions; at this time, only user-space support is provided
3.8 (2012)
Support more page sizes for MAP_HUGETLB/SHM_HUGETLB, as some large applications want to use 1GB huge pages on some mappings
perf: x86: Make hardware event translations available in sysfs /sys/devices/cpu/events/
SCTP: support per-association statistics
386 support dropped. Minimum is 486
The ptrace() system call has a new option flag, PTRACE_O_EXITKILL, which causes all traced processes to receive a SIGKILL signal if the tracing process exits unexpectedly.
3.7
TCP Fast Open (server side) (Client side on Linux 3.6)
The epoll_ctl() system call supports a new EPOLL_CTL_DISABLE operation to disable polling on a specific file descriptor.
Applications on the s/390 architecture can now make use of the System zEC12 hardware transactional memory feature.
perf trace, an alternative to strace
Providing protocol type via system.sockprotoname xattr of /proc/PID/fd entries (commit)
default loopback interface MTU raised to 64K
Add generic netlink support for tcp_metrics
3.6
TCP Fast Open (Client side)
3.5
Introduce /proc//task//children entry, which provides information about task children
Report file/anon bit in /proc/pid/pagemap
epoll(): Add a flag, EPOLLWAKEUP, to prevent suspend while epoll events are ready
fuse: add fallocate() operation
3.4
The pipe2() system call permits a new flag, O_DIRECT, that creates a pipe that operates in "packet" mode. Each write() to the pipe creates a distinct packet, and each read() reads exactly one packet
The new PR_SET_CHILD_SUBREAPER prctl() operation allows userspace service managers/supervisors mark itself as a sort of 'sub-init', able to stay as the parent for all orphaned processes created by the started services. All SIGCHLD signals will be delivered to the service manager
Mark thread stack correctly in proc//maps
Implement IP_UNICAST_IF and IPV6_UNICAST_IF socket options - This is mostly for Wine tho
Introduce the SO_PEEK_OFF sock option, implemented for datagram, seqpacket and stream sockets
MSG_TRUNC support for dgram sockets
Add missing getsockopt for SO_NOFCS
3.3
Android merge
Add BLKROTATIONAL ioctl, which permits applications to query whether a block device is rotational
Add a few /proc entries and prctl() codes to future checkpoint/restart support
3.2
sysctl: add support for poll()
Cross memory attach
ipv4: gc_interval sysctl removed
Support for transmission of IPv6 packets as well as the formation of IPv6 link-local addresses and statelessly autoconfigured addresses on top of IEEE 802.15.4 networks
crypto: Add userspace configuration API
3.1
tcp: Lower the default initRTO from 3secs to 1sec, as per RFC2988bis. It falls back to 3secs if the SYN or SYN-ACK packet has been retransmitted, AND the TCP timestamp option is not on
tcp: Compute protocol sequence numbers and fragment IDs using MD5 instead of MD4, as is inline with both RFC1948 and other OS
cgroups; remove the Namespace cgroup subsystem. It has been replaced by a compatibility flag 'clone_children', where a newly created cgroup will copy the parent cgroup values. The userspace has to manually create a cgroup and add a task to the 'tasks' file; Make 'procs' file writable
2.6.32 - 2.6.39 - Various / A lot / Not listed here.
I also looked at some man pages, and found few bits, for Linux above 2.6.32:
vdso:
aarch64 functions
The table below lists the symbols exported by the vDSO.
symbol version
──────────────────────────────────────
__kernel_rt_sigreturn LINUX_2.6.39
__kernel_gettimeofday LINUX_2.6.39
__kernel_clock_gettime LINUX_2.6.39
__kernel_clock_getres LINUX_2.6.39
mmap
MAP_SHARED_VALIDATE (since Linux 4.15)
MAP_FIXED_NOREPLACE (since Linux 4.17)
MAP_HUGE_2MB, MAP_HUGE_1GB (since Linux 3.8)
MAP_SYNC (since Linux 4.15)
MAP_UNINITIALIZED (since Linux 2.6.33) irrelevant, requires special kernel config, for embeded single-user devices
open
O_PATH (since Linux 2.6.39)
O_TMPFILE (since Linux 3.11)
Since Linux 2.6.33, proper O_SYNC support is provided.
Since Linux 6.1, O_DIRECT support and alignment restrictions for a file can be queried using statx(2), using the STATX_DIOALIGN flag.
linkat
AT_EMPTY_PATH (since Linux 2.6.39)
execve
can no longer fail with EAGAIN error (i.e. due to switching to a different user, and exhausting max number of processes limits).
clone3 options
u64 set_tid; /* Pointer to a pid_t array
(since Linux 5.5) */
u64 set_tid_size; /* Number of elements in set_tid
(since Linux 5.5) */
u64 cgroup; /* File descriptor for target cgroup
of child (since Linux 5.7) */
flag masks
CLONE_CLEAR_SIGHAND (since Linux 5.5)
CLONE_INTO_CGROUP (since Linux 5.7)
CLONE_NEWCGROUP (since Linux 4.6)
CLONE_NEWUSER semantic fianlized between 2.6.23 and 3.5
CLONE_PIDFD (since Linux 5.2)
returns:
EINVAL and and some other could be returned, some in relation to new flags, or to previously unhandled wrong combinations of flags.
epoll_pwait2() was added in Linux 5.11.
epoll_ctl
EPOLLWAKEUP (since Linux 3.5)
EPOLLEXCLUSIVE (since Linux 4.5)
epoll_wait
Before Linux 2.6.37, a timeout value larger than approximately
LONG_MAX / HZ milliseconds is treated as -1 (i.e., infinity).
Thus, for example, on a system where sizeof(long) is 4 and the
kernel HZ value is 1000, this means that timeouts greater than
35.79 minutes are treated as infinity.
clock_gettime
CLOCK_REALTIME_ALARM (since Linux 3.0; Linux-specific)
CLOCK_TAI (since Linux 3.10; Linux-specific)
CLOCK_BOOTTIME (since Linux 2.6.39; Linux-specific)
CLOCK_BOOTTIME_ALARM (since Linux 3.0; Linux-specific)
preadv2() and pwritev2() # preadv2() and pwritev2() first appeared in Linux 4.6.
RWF_DSYNC (since Linux 4.7)
RWF_HIPRI (since Linux 4.6)
RWF_SYNC (since Linux 4.7)
RWF_NOWAIT (since Linux 4.14)
RWF_APPEND (since Linux 4.16)
sendmsg
MSG_FASTOPEN (since Linux 3.7)
recvfrom
MSG_TRUNC (since Linux 2.2)
For raw (AF_PACKET), Internet datagram (since Linux 2.4.27/2.6.8), netlink (since Linux 2.6.22), and UNIX datagram (since Linux 3.4) sockets: return the real length of the packet or datagram, even when it was longer than the passed buffer.
setsockopt
TCP_USER_TIMEOUT (since Linux 2.6.37)
TCP_FASTOPEN (since Linux 3.6)
TCP_FASTOPEN_CONNECT (since Linux 4.11)
SO_ATTACH_FILTER (since Linux 2.2), SO_ATTACH_BPF (since Linux 3.19)
SO_BINDTODEVICE (can do getsockopt since Linux 3.8)
SO_DETACH_FILTER (since Linux 2.2), SO_DETACH_BPF (since Linux 3.19)
SO_ATTACH_REUSEPORT_CBPF, SO_ATTACH_REUSEPORT_EBPF
SO_INCOMING_NAPI_ID (gettable since Linux 4.12)
SO_PEEK_OFF (since Linux 3.4)
SO_REUSEPORT (since Linux 3.9)
SO_RXQ_OVFL (since Linux 2.6.33)
SO_SELECT_ERR_QUEUE (since Linux 3.10)
SO_BUSY_POLL (since Linux 3.11)
IP_BIND_ADDRESS_NO_PORT (since Linux 4.2)
IP_NODEFRAG (since Linux 2.6.36)
The prlimit() system call is available since Linux 2.6.36.
mlock2() is available since Linux 4.4
MCL_ONFAULT (since Linux 4.4)
Some limit account bugs fixed in 4.9
pkey_mprotect() first appeared in Linux 4.9
futex
FUTEX_LOCK_PI2 (since Linux 5.14)
timerfd_create
can use boottime and realtime alarm / clocks
TFD_IOC_SET_TICKS (since Linux 3.17)
sendfile
Before Linux 2.6.33, out_fd must refer to a socket. Since Linux 2.6.33 it can be any file. If it is a regular file, then sendfile() changes the file offset appropriately. (Just like in 2.4.x and earlier).
copy_file_range
Since 5.19, can use for cross-filesystems copy, if src and dst file systems are the same and support it
Significantly improved error return codes in 5.3 and 5.19
pipe2
O_DIRECT (since Linux 3.4)
O_NOTIFICATION_PIPE
Since Linux 5.8,
fcntl
F_SETPIPE_SZ (int; since Linux 2.6.35)
F_GETPIPE_SZ (void; since Linux 2.6.35)
F_ADD_SEALS (int; since Linux 3.17)
F_GET_SEALS (void; since Linux 3.17)
F_SEAL_FUTURE_WRITE (since Linux 5.1)
F_GET_RW_HINT (uint64_t *; since Linux 4.13)
F_SET_RW_HINT (uint64_t *; since Linux 4.13)
F_GET_FILE_RW_HINT (uint64_t *; since Linux 4.13)
F_SET_FILE_RW_HINT (uint64_t *; since Linux 4.13)
RWH_WRITE_LIFE_NOT_SET
RWH_WRITE_LIFE_NONE
RWH_WRITE_LIFE_SHORT
RWH_WRITE_LIFE_MEDIUM
RWH_WRITE_LIFE_LONG
RWH_WRITE_LIFE_EXTREME
Lost locks on NFSv4 mounts, are correctly detected in 3.12 in all cases, when using default nfs kernel module params.
statfs
ST_NOSYMFOLLOW (since Linux 5.10)
From Linux 2.6.38 up to and including Linux 3.1, fstatfs() failed with the error ENOSYS for file descriptors created by pipe(2).
FWIW, it looks like Rust bumped their minimum Linux version to 3.2 last year, to align with glibc:
The new baseline requirements were picked as the least common denominator among long-term-support distributions that still have active support. This is currently RHEL 7 with glibc 2.17 and kernel 3.10. The kernel requirement is picked as 3.2 instead, because this is the minimum requirement of glibc itself, and there is little relevant API difference between these versions.
Activity
ianlancetaylor commentedon Jun 14, 2023
Just a note that the case for Linux is a bit different than that for macOS and Windows, as Linux does not have a sole vendor. We need to identify organizations that distribute older versions of Linux that are supported and used. For example, I believe that we should continue to support all versions of Linux that are actively supported by commercial organizations, such as RHEL or Suse Linux Enterprise Server, and also all versions of Linux that are actively supported by communities supporting stable versions, such as Rocky Linux. Of course the nature of Linux is such that the set of active organizations changes over time.
baryluk commentedon Nov 4, 2023
3.10 could be a reasonable target.
For reference some facts about distros, and the kernel changes tangential to Go and userland.
Centos 7 - Linux 3.10
Centos 7: Released: 2014-07-07 , Full updates ended: 2020-08-06, Maintenance updates EOL: 2024-06-30
(Centos 8 is in maintenance for about a year now, and Centos 9 is current version)
Debian 9 - Linux 4.9
Debian 9.0 (codename Stretch) was initially released on June 17th, 2017. Last major update was Debian 9.13 was released [July 18th, 2020. Stretch had Long Term Support (LTS) until the end of June 2022.
Current stable Debian is version 12.2. So Debian 9.x is really ancient actually.
Debian 8 (Jessie), from 2015, had Linux 3.16.7-ckt9 in the 8.0
Ubuntu 16.04.7 LTS (initial relase of 16.04 - 2016-04-21; with latest minor bump 16.04.7 - August 13, 2020) - End of standard support: April 2021, EOL: April 2026
OpenSUSE 13.1, released 2013-11-19, end of life 2016-01, Linux 3.11.6
Oracle Linux 7 - initial release, Jul 2014, about same time as RHEL 7/ Centos. Extended support, Jun 2026. But if you pay, they will support you indefinitively (even on older version than 7), and it is likely there are people having such support in various industries. It is unlikely they run Go programs, and if they do, they will likely run older Go version for this anyway.
Also of note is that Oracle Linux 6.x, latest release, 6.10 from July 2018, has updated kernels, including 4.1.12, 2.6.39, and not just 2.6.32 (as RHEL 6).
These are the major ones that might be running and be sometimes hard to upgrade. Other distributions are more desktop and normal user focused, and update way faster, and earlier, and do not have LTS often. So it is close to 0% they would use old system or kernel.
For example, 3.10 would be like 20 major releases ago in world of Fedora, or Ubuntu.
The biggest risk would be probably various mobile and embedded arm devices, like Android, SBCs, routers, etc.
Linux 3.10 was release 30 June 2013, and was 10th LTS release. EOLed November 2017. Red Hat was maintaining own version of 3.10 (with backports from newer kernels, including some syscalls that were not originally in any upstream 3.10 release) until very recently.
Personally, I do not use any of these ancient systems. (Where I work, we migrated from Centos 7, about 2.5 years ago, and almost migrated from Centos 8 to Centos 9 to, already on some parts of our infra, but migrate on demand slowly instead). In other places, I run Debian 12, and still few Debian 11 systems, that could be updated anytime, but just wait their time.
Notable features added between 2.6.32 and 3.10, that might be semi related to userland go runtime
3.10:
3.9
3.8 (2012)
3.7
3.6
3.5
3.4
3.3
3.2
3.1
3.0
2.6.32 - 2.6.39 - Various / A lot / Not listed here.
I also looked at some man pages, and found few bits, for Linux above 2.6.32:
vdso:
syscalls:
Extra syscall options:
dmitshur commentedon Nov 29, 2023
Thanks for the suggestion above.
We've entered the release freeze for 1.22 and there aren't announcements to make for this release, moving to the next for now.
mdempsky commentedon Nov 30, 2023
FWIW, it looks like Rust bumped their minimum Linux version to 3.2 last year, to align with glibc:
https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html
7 remaining items
dmitshur commentedon Oct 29, 2024
CL 622015 added an announcement to Go 1.24 release notes. CC @cagedmantis. Moving to the next milestone, unless there's more I missed.
dmitshur commentedon May 21, 2025
There isn't anything to pre-announce in Go 1.25 release notes, moving to the next.
dmitshur commentedon Nov 26, 2025
Nothing to pre-announce in Go 1.26 release notes, moving to the next.
dmitshur commentedon May 26, 2026
There haven't been any accepted proposals related to old versions of Linux during the Go 1.27 development cycle, so moving to the next milestone.