{
	"id": "ee87b914-d9d3-47dd-b7be-ce9c598a4a52",
	"created_at": "2026-04-06T00:08:56.88537Z",
	"updated_at": "2026-04-10T13:11:57.134493Z",
	"deleted_at": null,
	"sha1_hash": "0d75b20ba842ed65a567eeb0b33c440b42e87799",
	"title": "What is linux-gate.so.1?",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 65831,
	"plain_text": "What is linux-gate.so.1?\r\nBy Johan Petersson\r\nArchived: 2026-04-05 18:03:33 UTC\r\nThe Wayback Machine -\r\nhttps://web.archive.org/web/20051013084246/http://www.trilithium.com:80/johan/2005/08/linux-gate/\r\nWhen you use the ldd utility on a reasonably recent Linux system you'll frequently see a reference to an ethereal\r\nentity known as linux-gate.so.1:\r\nldd /bin/sh\r\n linux-gate.so.1 =\u003e (0xffffe000)\r\n libdl.so.2 =\u003e /lib/libdl.so.2 (0xb7fb2000)\r\n libc.so.6 =\u003e /lib/libc.so.6 (0xb7e7c000)\r\n /lib/ld-linux.so.2 (0xb7fba000)\r\nWhat's so strange about that? It's just a dynamically loaded library, right?\r\nSort of, for sufficiently generous definitions of dynamically loaded library. The lack of file name in the output\r\nindicates that ldd was unable to locate a file by that name. Indeed, any attempt to find the corresponding file –\r\nwhether manually or by software designed to automatically load and analyze such libraries – will be unsuccessful.\r\nFrom time to time this is a cause of befuddlement and frustration for users as they go searching for a non-existent\r\nsystem file. You can confidently tell users on this futile quest that there's not supposed to be a linux-gate.so.1\r\nfile present anywhere on the file system; it's a virtual DSO, a shared object exposed by the kernel at a fixed\r\naddress in every process' memory:\r\ncat /proc/self/maps\r\n08048000-0804c000 r-xp 00000000 08:03 7971106 /bin/cat\r\n0804c000-0804d000 rwxp 00003000 08:03 7971106 /bin/cat\r\n0804d000-0806e000 rwxp 0804d000 00:00 0 [heap]\r\nb7e88000-b7e89000 rwxp b7e88000 00:00 0\r\nb7e89000-b7fb8000 r-xp 00000000 08:03 8856588 /lib/libc-2.3.5.so\r\nb7fb8000-b7fb9000 r-xp 0012e000 08:03 8856588 /lib/libc-2.3.5.so\r\nb7fb9000-b7fbc000 rwxp 0012f000 08:03 8856588 /lib/libc-2.3.5.so\r\nb7fbc000-b7fbe000 rwxp b7fbc000 00:00 0\r\nb7fc2000-b7fd9000 r-xp 00000000 08:03 8856915 /lib/ld-2.3.5.so\r\nb7fd9000-b7fdb000 rwxp 00016000 08:03 8856915 /lib/ld-2.3.5.so\r\nbfac3000-bfad9000 rw-p bfac3000 00:00 0 [stack]\r\nffffe000-fffff000 ---p 00000000 00:00 0 [vdso]\r\nhttps://web.archive.org/web/20051013084246/http://www.trilithium.com/johan/2005/08/linux-gate/\r\nPage 1 of 4\n\nHere cat prints its own memory map. The line marked [vdso] is the linux-gate.so.1 object in that process, a\r\nsingle memory page mapped at address ffffe000. A program can determine the location of the shared object in\r\nmemory by examining an AT_SYSINFO entry in the ELF auxiliary vector. The auxiliary vector ( auxv ) is an array\r\nof pointers passed to new processes in the same way program arguments ( argv ) and environment variables\r\n( envp ) are.\r\nIn theory the address could differ between processes, but as far as I know the Linux kernel always maps it at a\r\nfixed location. The sample output above come from an x86 box where processes live in plain old 32-bit address\r\nspaces divided into pages of 4096 bytes, making ffffe000 the penultimate page. The very last page is reserved to\r\ncatch accesses through invalid pointers, e.g. dereferencing a decremented NULL pointer or a MAP_FAILED pointer\r\nreturned from mmap .\r\nSince all processes share the same object at the same location, it's easy to extract a copy of it if we want to take a\r\ncloser look at it. For example, we can simply ask dd to dump the page from its own memory (carefully choosing\r\nan output name different from linux-gate.so.1 to avoid creating a file that's not supposed to exist):\r\ndd if=/proc/self/mem of=linux-gate.dso bs=4096 skip=1048574 count=1\r\n1+0 records in\r\n1+0 records out\r\nWe skip 1048574 because there are 220 = 1048576 pages in total and we want to extract the next to last page. The\r\nresult looks like any other shared ELF object file:\r\nfile -b linux-gate.dso\r\nELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped\r\nobjdump -T linux-gate.dso\r\nlinux-gate.dso: file format elf32-i386\r\nDYNAMIC SYMBOL TABLE:\r\nffffe400 l d .text 00000000\r\nffffe460 l d .eh_frame_hdr 00000000\r\nffffe484 l d .eh_frame 00000000\r\nffffe608 l d .useless 00000000\r\nffffe400 g DF .text 00000014 LINUX_2.5 __kernel_vsyscall\r\n00000000 g DO *ABS* 00000000 LINUX_2.5 LINUX_2.5\r\nffffe440 g DF .text 00000007 LINUX_2.5 __kernel_rt_sigreturn\r\nffffe420 g DF .text 00000008 LINUX_2.5 __kernel_sigreturn\r\nThese symbols are entry points for the rt_sigreturn / sigreturn functions and for making virtual system calls.\r\nOn the x86 platform linux-gate.so.1 was initially called linux-vsyscall.so.1, but this was changed during\r\ndevelopment to get a common name accurately reflecting its purpose across platforms: to act as a gateway\r\nhttps://web.archive.org/web/20051013084246/http://www.trilithium.com/johan/2005/08/linux-gate/\r\nPage 2 of 4\n\nbetween user and kernel space. Not all platforms need virtual syscalls, but they must be fairly important for x86 to\r\nwarrant this elaborate mechanism.\r\nTraditionally, x86 system calls have been done with interrupts. You may remember that the way to request\r\noperating system functions was via interrupt 33 (21h) back in the bad old MS-DOS days. Windows system calls\r\nare buried beneath layers of user-mode APIs, but at some point they too boil down to int 0x2e . Similarly,\r\nsyscall implementations in Linux and other *nix kernels have been using int 0x80 .\r\nIt turns out, though, that system calls invoked via interrupts are remarkably slow on the more recent members of\r\nthe x86 processor family. An int 0x80 system call can be as much as an order of magnitude slower on a 2 GHz\r\nPentium 4 than on an 850 MHz Pentium III. The impact on performance resulting from this could easily be\r\nsignificant, at least for applications that do a lot of system calls.\r\nIntel recognized this problem early on and introduced a more efficient system call interface in the form of\r\nsysenter and sysexit instructions. This fast system call feature first appeared in the Pentium Pro processor,\r\nbut due to hardware bugs it's actually broken in most of the early CPUs. That's why you may see claims that\r\nsysenter was introduced with Pentium II or even Pentium III.\r\nThe hardware problems also help explain why it took quite some time before operating systems started supporting\r\nfast system calls. If we ignore earlier experimental patches, Linux support for sysenter appeared in December\r\n2002 during kernel 2.5 development. That's ten years after the instruction was defined! Microsoft started using\r\nsysenter only slightly earlier, in Windows XP.\r\nYou can find out if your Linux machine is using the sysenter instruction for system calls by disassembling\r\n__kernel_vsyscall :\r\nobjdump -d --start-address=0xffffe400 --stop-address=0xffffe414 linux-gate.dso\r\nlinux-gate.dso: file format elf32-i386\r\nDisassembly of section .text:\r\nffffe400 \u003c__kernel_vsyscall\u003e:\r\nffffe400: 51 push %ecx\r\nffffe401: 52 push %edx\r\nffffe402: 55 push %ebp\r\nffffe403: 89 e5 mov %esp,%ebp\r\nffffe405: 0f 34 sysenter\r\nffffe407: 90 nop\r\nffffe408: 90 nop\r\nffffe409: 90 nop\r\nffffe40a: 90 nop\r\nffffe40b: 90 nop\r\nffffe40c: 90 nop\r\nffffe40d: 90 nop\r\nffffe40e: eb f3 jmp ffffe403 \u003c__kernel_vsyscall+0x3\u003e\r\nhttps://web.archive.org/web/20051013084246/http://www.trilithium.com/johan/2005/08/linux-gate/\r\nPage 3 of 4\n\nffffe410: 5d pop %ebp\r\nffffe411: 5a pop %edx\r\nffffe412: 59 pop %ecx\r\nffffe413: c3 ret\r\nThe preferred way of invoking a system call is determined by the kernel at boot time, and evidently this box uses\r\nsysenter . On an older machine you may see int 0x80 being used instead. In case you are struggling to make\r\nsense of that jump (like I was the first time I saw it) you might be interested to learn that it's there because Linus\r\nTorvalds is a disgusting pig and proud of it. (It's a trick to handle restarting of system calls with six parameters).\r\n14 August, 2005\r\nSource: https://web.archive.org/web/20051013084246/http://www.trilithium.com/johan/2005/08/linux-gate/\r\nhttps://web.archive.org/web/20051013084246/http://www.trilithium.com/johan/2005/08/linux-gate/\r\nPage 4 of 4",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://web.archive.org/web/20051013084246/http://www.trilithium.com/johan/2005/08/linux-gate/"
	],
	"report_names": [
		"linux-gate"
	],
	"threat_actors": [],
	"ts_created_at": 1775434136,
	"ts_updated_at": 1775826717,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/0d75b20ba842ed65a567eeb0b33c440b42e87799.pdf",
		"text": "https://archive.orkl.eu/0d75b20ba842ed65a567eeb0b33c440b42e87799.txt",
		"img": "https://archive.orkl.eu/0d75b20ba842ed65a567eeb0b33c440b42e87799.jpg"
	}
}