gccgo, LD_PRELOAD, and lagging behind on Go versions

209 views
Skip to first unread message

Peter JIN

unread,
May 31, 2024, 1:25:09 AMMay 31
to golang-dev
Can we please make the update of gccgo to latest Go versions a bigger priority?

My use case: I have several LD_PRELOAD libraries written in C. To make them work with programs written in Go, I have to compile it with gccgo to make it dynamically linked -- static linking is not an option. However, it seems like gccgo has been stuck on 1.18 for a while, at least I can see for about the past two years. This is problematic mostly because many of the dependencies in some of the Go programs I use require the use of later Go versions, making it not possible to use with gccgo.

Forgoing the use of LD_PRELOAD is not an option, but I would be open to any alternative ideas, including overriding functions in the standard library.

Any ideas?

side note: IMHO, static linking is a mistake. It specifically relies on the fact that the Linux kernel ABI is much more stable than the glibc API in terms of function calls. And interposing system calls is much more difficult because it involves a kernel-user boundary -- effectively, you would need to modify the CPU's interrupt vector table to "intercept" a system call, whereas function calls in glibc can much more easily be interposed in the user space.

Peter

wagner riiffel

unread,
May 31, 2024, 7:40:37 PMMay 31
to Peter JIN, golang-dev
On 5/31/2024 1:32 AM, Peter JIN wrote:
> side note: IMHO, static linking is a mistake. It specifically relies on the
> fact that the Linux kernel ABI is much more stable than the glibc API in
> terms of function calls.

If Linux has an API more stable than glibc, why would one choose the
later? Static linking is the only sane option, specially on Linux land,
where there's multiple libc implementations, e.g. Alpine Linux which
does not use glibc and is a popular target for Go programs, thus built
programs that dynamically link against glibc won't execute there, making
a needless split to distribute the program.

-w

Ian Lance Taylor

unread,
May 31, 2024, 7:43:04 PMMay 31
to Peter JIN, golang-dev
On Thu, May 30, 2024 at 10:25 PM Peter JIN <pjin...@gmail.com> wrote:
>
> Can we please make the update of gccgo to latest Go versions a bigger priority?
>
> My use case: I have several LD_PRELOAD libraries written in C. To make them work with programs written in Go, I have to compile it with gccgo to make it dynamically linked -- static linking is not an option. However, it seems like gccgo has been stuck on 1.18 for a while, at least I can see for about the past two years. This is problematic mostly because many of the dependencies in some of the Go programs I use require the use of later Go versions, making it not possible to use with gccgo.

Unfortunately at this point gccgo development is basically me working
on my own time, and I don't have much time.

Ian

Peter JIN

unread,
May 31, 2024, 10:07:37 PMMay 31
to golang-dev
As I said, the main issue is that to "intercept" a system call, you need to intercept a system call instruction like "int $0x80" in i386, "syscall" in x86_64, or "svc 0" on ARM. This is much more difficult to do, especially in a user space program, because it would ultimately require changing GDT/IDT/IVT entries in the CPU, which is not really feasible or allowed in a userspace program.

On the other hand, overriding a library function is simply just a matter of changing where the function pointers in the PLT entries point to, namely in the LD_PRELOAD library rather than to libc, which is an operation easily done in user space.

I have been considering the use of the seccomp functions SECCOMP_RET_TRAP and SECCOMP_RET_USER_NOTIF along with a "program loader" that reads the ELF header and installs a SIGSYS handler to do effectively what the LD_PRELOAD library would have done, though I'm not sure if that is a good long-term solution, especially if it requires architecture-specific assembler instructions.

That being said, my use of LD_PRELOAD is never to "decrease" the privileges of a running program. There should be other means of ensuring that the privileges are contained, such as with mount, network, and user namespaces. LD_PRELOAD is mainly intended to facilitate the use of "alternate access" where the containerized environment has access to such facilities, it just needs to be made to use it, for example, connecting to a Unix domain socket, but the app itself only supports inet sockets.

The glibc version incompatibility issue could theoretically be fixed by the use of weak symbols and by probing for the existence of those symbols at run time or by additional LD_PRELOAD libraries to retrofit in the newer-version symbols into older versions of glibc.

Hope that helps,

Peter
Reply all
Reply to author
Forward
0 new messages