Linux From Nothing

1. Kernel, Shell, Libs

We need to install a bunch of things that may be useful in the close future.

sudo apt install bc binutils bison dwarves flex gcc git gnupg2 gzip libelf-dev libncurses5-dev libssl-dev make openssl pahole perl-base rsync tar xz-utils autoconf gperf autopoint texinfo texi2html gettext gawk bzip2 qemu-system-x86 libtool

Lets create our project directories.

mkdir LFN
cd LFN

mkdir root
cd root

mkdir boot
mkdir proc
mkdir sys
mkdir dev

mkdir usr
cd usr

mkdir lib
mkdir lib64
mkdir bin
mkdir sbin
cd ..

ln -s usr/lib lib
ln -s usr/lib64 lib64
ln -s usr/bin bin
ln -s usr/sbin sbin
cd ..

export LFN="/home/user/LFN/root"

Kernel

git clone --depth 1 https://github.com/torvalds/linux
cd linux

make tinyconfig
make menuconfig

Here we have the choice to enable a bunch of option in the kernel, here is the minimum.


General setup --->

----Configure standard kernel features --->

--------[*] Enable support for printk

[*] 64-bit kernel

[*] Enable the block layer

Executable file formats --->

----[*] Kernel support for ELF binaries

----[*] Kernel support for scripts starting with #!

Device Drivers --->

----[*] PCI support

----Generic Driver Options --->

--------[*] Maintain a devtmpfs filesystem to mount at /dev

--------[*] Automount devtmpfs at /dev, after the kernel mounted the rootfs

----SCSI device support --->

--------[*] SCSI disk support (this will unlock after serial ATA)

----[*] Serial ATA and Parallel ATA drivers (libata) --->

--------[*] Intel ESB, ICH, PIIX3, PIIX4 PATA/SATA support

----Character devices --->

--------[*] Enable TTY

--------Serial drivers --->

------------[*] 8250/16550 and compatible serial support

------------[*] Console on 8250/16550 and compatible serial port

File systems --->

----[*] The Extended 4 (ext4) filesystem

----Pseudo filesystems --->

--------[*] /proc file system support

--------[*] sysfs file system support


Compile and dump our kernel in the root(boot) of our project.

make -j8

mv arch/x86/boot/bzImage ..
cd ..
mv bzImage root/boot/

Bash

We need a shell in order to interact with our kernel. Remember to replace user to your own user as written in your home dir.

git clone --depth 1 https://git.savannah.gnu.org/git/bash.git

mkdir bash-build
cd bash-build

../bash/configure --prefix=/usr

make -j8
make DESTDIR=$LFN install
cd ..

ln -s bash root/bin/sh

Coreutils

We need core utilities like cat ,cp, rm... NOTE bootstrap type scripts can be not necessary if you downloaded from a release instead of git.

git clone --depth 1 https://github.com/coreutils/coreutils

mkdir coreutils-build

cd coreutils
./bootstrap
cd ..

cd coreutils-build
../coreutils/configure --without-selinux --disable-libcap --prefix=/usr

make -j8
make DESTDIR=$LFN install
cd ..

Util-Linux

Gives us a bunch of Linux tools like mount.

git clone --depth 1 https://github.com/util-linux/util-linux

mkdir util-build

cd util-linux
./autogen.sh
cd ..

cd util-build
../util-linux/configure --disable-liblastlog2 --prefix=/usr

make -j8
make DESTDIR=$LFN install
cd ..

Nano

Yes, Nano, deal with it XD

git clone --depth 1 git://git.savannah.gnu.org/nano.git

mkdir nano-build

cd nano
./autogen.sh
cd ..

cd nano-build
../nano/configure --prefix=/usr

make -j8
make DESTDIR=$LFN install
cd ..

Glibc (Lib)

[The GNU C Library - GNU Project - Free Software Foundation](https://www.gnu.org/software/libc/

Gnu C library contains a bunch of good things and it is the basic for any linux. it contains the lib loader ld-linux which allows for dynamic library.

git clone --depth 1 https://sourceware.org/git/glibc

mkdir glibc-build

cd glibc-build
../glibc/configure --libdir=/lib --prefix=/usr

make -j8
make DESTDIR=$LFN install
cd ..

Ncurses (Lib)

Ncurses' libs allows bash (and more) to work, we also need to compile the wide character version which has its libs end in 'w'. (get the latest here: https://ftp.gnu.org/gnu/ncurses/)

wget https://ftp.gnu.org/gnu/ncurses/ncurses-6.5.tar.gz

tar -xvzf ncurses-6.5.tar.gz

mkdir ncurses-build

cd ncurses-build
../ncurses-6.5/configure --with-shared --with-termlib --enable-widec --with-versioned-syms --prefix=/usr

make -j8
make DESTDIR=$LFN install
cd ..

cd root
ln -s libncursesw.so.6 lib/libncurses.so.6
ln -s libtinfow.so.6 lib/libtinfo.so.6

nano etc/ld.so.conf

Content of the file (exit using Ctrl-x and than y, than Enter).

/usr/lib
/usr/lib64

Update the ld.so.cache .

ldconfig -v -r ./

Init

Now lets make the init, it can be placed in /, /bin or /sbin, always need to be called "init" and be executable.

nano sbin/init

Content of the file (exit using Ctrl-x and than y, than Enter).

#!/bin/bash

mount -t proc none /proc
mount -t sysfs none /sys

exec /bin/bash

Make it executable and leave dir.

chmod +x sbin/init
cd ..

Creating disk

We need to create a disk (in our case 1GB).

dd if=/dev/zero of=disk.img bs=1M count=1024

fdisk disk.img
n - p - 1 (leave default 2048sectors)
a
w

Mounting disk (you can follow again to mount existing one)

Mounting our disk using losetup, it will find the next available /dev/loop# and give us access to the partitions at /dev/loop#p#. it will also tell us which loop# it chose.

sudo losetup -fP --show disk.img

Creating partition (only if you have a new disk)

You can now put the FS of your choice, given that it was configured into your kernel. if you followed this tutorial without change, you will be using EXT4.

sudo mkfs.ext4 /dev/loop#p1

Mounting partition

This will be the last thing you have to do to mount an not-new image. don't stop the tutorial if its new (; .

sudo mount /dev/loop#p1 /mnt

Copy our data

self explanatory...

sudo cp -R root/* /mnt/

Grub

We need a bootloader to tell our system what to do at boot, Grub is a complete, battle-harden bootloader and you will learn to use it. Lets get it onto our drive!

sudo grub-install --target=i386-pc --root-directory=/mnt --no-floppy --modules="normal part_msdos ext2 multiboot" /dev/loop#

Now lets create the boot entry.

sudo nano /mnt/boot/grub/grub.cfg

Content of the file (exit using Ctrl-x and than y, than Enter).

menuentry 'LFN' {
        set root='(hd0,1)'
        linux /boot/bzImage root=/dev/sda1 rw
}

Explanations: you can change LFN for what you want.

We have only one drive so our root drive and partition will be:

hd0<- this is the drive, counting from 0.

hd0,1<- this is the partition, counting from 1 (yes, death to the one that made that choice).

For the linux line, it need to point to our kernel image and we need to tell it to mount /dev/sda1 (we have 1 disk so makes sense) and don't forget the rw to tell it that it can write to it, by default you can't.

You can now follow #Running LFN to test your creation!

Unmount / Sync your disk

Before you run your LFN it is important that you sync your data to insure that whatever modification you made will be written and usable.

#I like to spam it 3x
sync

Then you can #Running LFN, but if you are done for the day, it is always important to umount both the FS and the loopback device using:

sudo umount /mnt
sudo losetup -d /dev/loop#

Running LFN

Here is the basic command:

qemu-system-x86_64 disk.img

There is some options that you can add to better your experience.

Ram

By default, QEMU gives you 128MB, not alot...

-m 1G

You can change 1G for the amount that you want.

CPU

By default, QEMU gives you 1 core.

-smp 8

Here we have 8 core, you can change it for the needed amount. (and yes cursed amounts like 7 work)

KVM

KVM will harness the power of virtualization provided by the hardware and it is wayyyy faster, the host kernel needs to have it enabled and bios too but they are both default now....

-enable-kvm -cpu host

Network

The simplest way to get network on QEMU is:

-net nic -net user

2. Internet From scratch

You may need:

sudo apt install libcap-dev

cd LFN

Want to start from here? Here is the image: https://d2xw7bkejy3jlh.cloudfront.net/disk.img.xz

Lets start by mounting our disk and FS:

sudo losetup -fP --show disk.img
sudo mount /dev/loop#p1 /mnt

This section is build with more details to take you through the process of making the system work, so you can apply the same logic for your own software.

Iproute2

Iproute2 is the default network tool for linux, and with it, we will be connection our LFN to the network.

git clone --depth 1 https://github.com/iproute2/iproute2.git
cd iproute2
./configure --libbpf_force=off --prefix=/usr
nano config.mk

Edit this line from y→n

HAVE_SELINUX:=n

Compile and check which libs we need to make this work!

make -j8

ldd ip/ip

We have a couple of missing libs:

  • linux-vdso.so.1 (0x00007ffc1812b000)
  • libelf.so.1
  • libcap.so.2
  • libc.so.6
  • libz.so.1
  • libzstd.so.1
  • /lib64/ld-linux-x86-64.so.2

Lets install them!

sudo make DESTDIR="/mnt" install
cd ..

ElfUtils

ElfUtils will provide libelf and simple elf editing tools.

git clone --depth 1 git://sourceware.org/git/elfutils.git
cd elfutils

autoreconf -i -f

autoreconf is an automated way to generate a configure file, here is the options:

-f--force

consider all files obsolete

-i--install

copy missing auxiliary files

cd ..
mkdir elfutils-build
cd elfutils-build

../elfutils/configure --enable-maintainer-mode --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

LibCap

https://sites.google.com/site/fullycapable/

LibCap is a privilege/permission lib that is a default in ... all distros!

git clone --depth 1 https://git.kernel.org/pub/scm/libs/libcap/libcap.git
cd libcap

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Zlib

Zlib is a compression lib, it provides libz.

wget https://zlib.net/current/zlib.tar.gz

tar -xvzf zlib.tar.gz

mkdir zlib-build
cd zlib-build

../zlib-1.3.1/configure --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Zstd (Zstandard)

https://github.com/facebook/zstd

Zstd is a compression lib/program that can produce and decode .zst .gz .xz .lz4 . Provides libzstd.

git clone --depth 1 https://github.com/facebook/zstd
cd zstd

make -j8
sudo make DESTDIR="/mnt" prefix=/usr install

cd ..

First test

Lets Sync to test it!

sync
sync
sync

sudo umount /mnt
sudo losetup -d /dev/loop#
qemu-system-x86_64 disk.img

Lets try our command:

ip
	Cannot open netlink socket: Function not implemented

We have missing kernel option, lets fix that!

Mount everything back up:

sudo losetup -fP --show disk.img
sudo mount /dev/loop#p1 /mnt

Kernel options

if you downloaded the pre-made image, you will need to follow the first #Kernel part.

cd linux
make menuconfig

General setup --->

----[*] Configure standard kernel features (expert users) --->

--------[*] Enable futex support

General architecture-dependent options --->

----[*] Provide system calls for 32-bit time_t

[*] Networking support --->

----Networking options --->

--------[*] Packet socket

--------[*] Unix domain sockets

--------[*] TCP/IP networking

Device Drivers --->

----[*] Network device support --->

--------[*] Ethernet driver support (NEW) ---> (THIS IS ALREADY MARKED)

------------[*] Intel(R) PRO/1000 Gigabit Ethernet support

File systems --->

----[*] Inotify support for userspace


Lets compile again and mv to our LFN.

make -j8
sudo mv arch/x86/boot/bzImage /mnt/boot/
cd ..

Second test

Lets Sync to test it!

sync
sync
sync

sudo umount /mnt
sudo losetup -d /dev/loop#
qemu-system-x86_64 disk.img

On your LFN:

ip
	Works!
ip link
	Works!

Mount everything back up:

sudo losetup -fP --show disk.img
sudo mount /dev/loop#p1 /mnt

Wget

https://www.gnu.org/software/wget/

Wget will allow us to start downloading thing.

wget https://ftp.gnu.org/gnu/wget/wget-latest.tar.gz

tar -xvzf wget-latest.tar.gz

mkdir wget-build
cd wget-build

../wget-1.25.0/configure --with-ssl=openssl --prefix=/usr

--with-ssl=openssl is there to avoid GnuTLS which we don't/won't have.

make -j8
sudo make DESTDIR="/mnt" install

ldd /mnt/bin/wget

libs needed (will highlight missing ones and keep in mind that you can run this in LFN as we have ldd installed):

  • linux-vdso.so.1
  • libpcre2-8.so.0 regular expression pattern matching
  • libuuid.so.1
  • libssl.so.3 OpenSSL
  • libcrypto.so.3 OpenSSL
  • libz.so.1
  • libc.so.6
  • /lib64/ld-linux-x86-64.so.2
  • cd ..
    

    PCRE2

https://github.com/PCRE2Project/pcre2

The PCRE2 lib implements regular expression pattern matching.

git clone --depth 1 https://github.com/PCRE2Project/pcre2
cd pcre2

./autogen.sh

cd ..
mkdir pcre2-build
cd pcre2-build

../pcre2/configure --prefix=/usr

make -j8

make install does not seem to work... Lets use mv on the lib dir.

sudo mv .libs/* /mnt/lib/

cd ..

OpenSSL

https://github.com/openssl/openssl

King Lib for SSL,TLS,HTTPS....

git clone --depth 1 https://github.com/openssl/openssl

mkdir openssl-build
cd openssl-build

../openssl/Configure --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Update init V1

Now that we have the command to connect ourselves to the internet, we should add to our init to do it automatically.

sudo nano /mnt/sbin/init

This is the updated content:

#!/bin/bash

mount -t proc none /proc
mount -t sysfs none /sys

ip link set up eth0
ip addr add 10.0.2.15/24 dev eth0
ip route add 10.0.2.2 dev eth0
ip route add 0/0 via 10.0.2.2 dev eth0

exec /bin/bash

Lets talk about what we just did, we first enable eth0 which is our default network connector.

We set our IP to 10.0.2.15, the default with QEMU.

We create a route to our gateway 10.0.2.2, the default with QEMU.

Finally, we tell the system to route all traffic (0/0) via 10.0.2.2 connecting our LFN to the internet!

Important note QEMU uses SLIRP by default which very limited support for ICMP which is used for pings... TCP and UDP is fully supported.

Third test

Lets Sync to test it!

sync
sync
sync

sudo umount /mnt
sudo losetup -d /dev/loop#
qemu-system-x86_64 disk.img

On LFN:

wget maplecircuit.dev
	Resolving maplecircuit.dev... failed: Temporary failure in name resolution.
	wget: unable to resolve host address 'maplecircuit.dev'

We can see here that we have an issue with name resolution, this should be fixed by adding a small DNS server.

Mount everything back up:

sudo losetup -fP --show disk.img
sudo mount /dev/loop#p1 /mnt

DNSMasq

DNSMasq is a small DNS server, it can be used for a bunch of other things and it was more widely used before systemd was the solution to everything (; .

git clone --depth 1 git://thekelleys.org.uk/dnsmasq.git
cd dnsmasq

make -j8

sudo mv src/dnsmasq /mnt/bin/

cd ..

Update init V2

Lets add DNSMasq to our init.

sudo nano /mnt/sbin/init

This is the updated content:

#!/bin/bash

mount -t proc none /proc
mount -t sysfs none /sys

ip link set up eth0
ip addr add 10.0.2.15/24 dev eth0
ip route add 10.0.2.2 dev eth0
ip route add 0/0 via 10.0.2.2 dev eth0

dnsmasq -uroot

exec /bin/bash

Lets Sync to test it!

sync
sync
sync

sudo umount /mnt
sudo losetup -d /dev/loop#
qemu-system-x86_64 disk.img

On LFN

dnsmasq: no user root

nano /etc/passwd

Content of the file

root:x:0:0:root:/root:/bin/bash

here is what it means:

  1. Username
  2. Password
  3. User ID
  4. Group ID
  5. User ID Info (comment)
  6. Home Directory
  7. Login Shell

mkdir /root
dnsmasq -uroot

On LFN

dnsmasq: failed to open pidfile /var/run/dnsmasq.pid: No such file or directory

We indeed, do not have a /var/run dir... lets fix that:

mkdir /var/run

While we are making files lets create /etc/resolv.conf

nano /etc/resolv.conf

Content of /etc/resolv.conf:

nameserver 1.1.1.1

Sync and restart LFN:

sync
#restart the LFN

lets try this:

wget maplecircuit.dev
	Unable to locally verify the issuers authority
wget maplecircuit.dev --no-check-certificate
nano index.html

It works!!!

Here is the image: https://d2xw7bkejy3jlh.cloudfront.net/disk2.img.xz

3. Compiler

Convert our disk to qcow2

cd LFN

sudo losetup -fP --show disk.img
sudo mount /dev/loop#p1 /mnt

sudo mkdir /mnt2
sudo modprobe nbd max_part=8
qemu-img create -f qcow2 disk2.img 100G
sudo qemu-nbd -c /dev/nbd0 disk2.img

sudo fdisk /dev/nbd0
n - p - 1 (leave default 2048sectors)
a
w

sudo mkfs.ext4 /dev/nbd0p1

sudo mount /dev/nbd0p1 /mnt2
sudo cp -R /mnt/* /mnt2/
sudo grub-install --target=i386-pc --root-directory=/mnt2 --no-floppy --modules="normal part_msdos ext2 multiboot" /dev/nbd0

sudo umount /mnt
sudo umount /mnt2

sudo mount /dev/nbd0p1 /mnt

Linux Headers

The linux headers are used by alot of basic program to get access to kernel functions.

cd linux

make headers

sudo cp -r usr/include/* /mnt/usr/include/

cd ..

Glibc (Lib)

[The GNU C Library - GNU Project - Free Software Foundation](https://www.gnu.org/software/libc/

We downloaded it from git and thats kinda suicide, so lets get a real version (;

rm -r glibc-build

wget https://ftp.gnu.org/gnu/glibc/glibc-2.41.tar.gz

tar -xvzf glibc-2.41.tar.gz

mkdir glibc-build

cd glibc-build
../glibc-2.41/configure --with-headers=/mnt/usr/include --without-selinux --libdir=/lib --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install
cd ..

GCC & libstdc++

The basic Gnu C Compiler and its c++ libs.

https://gcc.gnu.org/

wget https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.gz

tar -xvzf gcc-14.2.0.tar.gz

cd gcc-14.2.0
./contrib/download_prerequisites
cd ..

mkdir gcc-build
cd gcc-build
../gcc-14.2.0/configure --with-glibc-version=2.41 --disable-multilib --enable-languages=c,c++ --disable-bootstrap --prefix=/usr

make -j8

sudo make DESTDIR="/mnt" install
cd ..

Make

Make, we all know what it is by now.

wget https://ftp.gnu.org/gnu/make/make-4.4.tar.gz

tar -xvzf make-4.4.tar.gz

mkdir make-build
cd make-build
../make-4.4/configure --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Tar

https://www.gnu.org/software/tar/

We will need alot!

wget https://ftp.gnu.org/gnu/tar/tar-1.35.tar.gz

tar -xvzf tar-1.35.tar.gz

mkdir tar-build
cd tar-build
../tar-1.35/configure --without-selinux --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Gzip

https://www.gnu.org/software/gzip/

We will need with Tar.

wget https://ftp.gnu.org/gnu/gzip/gzip-1.13.tar.gz

tar -xvzf gzip-1.13.tar.gz

mkdir gzip-build
cd gzip-build
../gzip-1.13/configure --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Sed

https://www.gnu.org/software/sed/

Used with Make.

wget https://ftp.gnu.org/gnu/sed/sed-4.9.tar.gz

tar -xvzf sed-4.9.tar.gz

mkdir sed-build
cd sed-build
../sed-4.9/configure --without-selinux --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Grep

https://www.gnu.org/software/grep/

Used with Make.

wget https://ftp.gnu.org/gnu/grep/grep-3.11.tar.gz

tar -xvzf grep-3.11.tar.gz

mkdir grep-build
cd grep-build
../grep-3.11/configure --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Awk

https://www.gnu.org/software/gawk/

Needed by perl

wget https://ftp.gnu.org/gnu/gawk/gawk-5.3.1.tar.gz

tar -xvzf gawk-5.3.1.tar.gz

mkdir gawk-build
cd gawk-build

../gawk-5.3.1/configure --prefix=/usr

make -j8

sudo make DESTDIR="/mnt" install

cd ..

Binutils

https://www.gnu.org/software/binutils/

Used with Make.

wget https://sourceware.org/pub/binutils/releases/binutils-2.44.tar.gz

tar -xvzf binutils-2.44.tar.gz

mkdir binutils-build
cd binutils-build
../binutils-2.44/configure --prefix=/usr

make -j8
sudo make DESTDIR="/mnt" install

cd ..

Make internet work

Lets download that missing Cert for https.

wget https://curl.se/ca/cacert.pem

sudo mkdir /mnt/etc/ssl/
sudo mkdir /mnt/etc/ssl/certs/
sudo mv cacert.pem /mnt/etc/ssl/certs/ca-certificates.crt

sudo nano /mnt/sbin/init

Should look like

#!/bin/bash

mount -t proc none /proc
mount -t sysfs none /sys

ip link set up eth0
ip addr add 10.0.2.15/24 dev eth0
ip route add 10.0.2.2 dev eth0
ip route add 0/0 via 10.0.2.2 dev eth0

dnsmasq -uroot

export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
export COMPILER_PATH=/usr/libexec/gcc/x86_64-pc-linux-gnu/14.2.0:/usr/bin
export LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.0
export CPATH=/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.0/include

exec /bin/bash

and lets umount and start LFN

sudo mkdir /mnt/tmp

sync
sudo umount /mnt
sudo qemu-nbd -d /dev/nbd0
qemu-system-x86_64 disk2.img -smp 8 -m 8G

XZ Utils

https://github.com/tukaani-project/xz

Lets test our LFN with XZ

#On LFN
cd root

wget https://github.com/tukaani-project/xz/releases/download/v5.6.4/xz-5.6.4.tar.gz

tar -xvf xz-5.6.4.tar.gz

mkdir xz-build
cd xz-build
../xz-5.6.4/configure --prefix=/usr

make -j8
make install

sync
sync
sync

Here is the image: https://d2xw7bkejy3jlh.cloudfront.net/disk3.img.xz

4. Git, Perl, Strace

Lets mount things up and config a new kernel.

cd LFN

sudo modprobe nbd max_part=8
sudo qemu-nbd -c /dev/nbd0 disk2.img
sudo mount /dev/nbd0p1 /mnt

cd linux

make menuconfig

General setup --->

----[*] Configure standard kernel features (expert users) --->

--------[*] Posix Clocks timers

[*] Networking support --->

----Networking options --->

--------[*] DNS Resolver support (needs the other option ↓ to be shown)

Security options --->

----[*] Enable access key retention support


Posix Clocks timers WILL ENABLE timers/NANOSLEEP and fix freeze with m4 and others:

checking for working nanosleep..

The other 2 option are for Curl

Lets compile again and mv to our LFN.

make -j8
sudo mv arch/x86/boot/bzImage /mnt/boot/
sudo cp .config /mnt/boot/
cd ..

Now we unmount everything and boot LFN

sudo umount /mnt
sudo qemu-nbd -d /dev/nbd0
qemu-system-x86_64 disk2.img -smp 8 -m 8G -enable-kvm -cpu host

Fix $PATH

$PATH is not properly set in LFN, lets fix that so our programs know where to look for bin.

#on LFN
nano /sbin/init

Init should look like:

#!/bin/bash

mount -t proc none /proc
mount -t sysfs none /sys

ip link set up eth0
ip addr add 10.0.2.15/24 dev eth0
ip route add 10.0.2.2 dev eth0
ip route add 0/0 via 10.0.2.2 dev eth0

dnsmasq -uroot

export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
export COMPILER_PATH=/usr/libexec/gcc/x86_64-pc-linux-gnu/14.2.0:/usr/bin
export LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.0
export CPATH=/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.0/include
export PATH=/usr/bin:/usr/sbin

exec /bin/bash

Sync and reboot to make the change take effect.

#on LFN
sync
#reboot LFN

Diffutils

https://www.gnu.org/software/diffutils/

Provides diff and cmp needed broadly across GNU software.

#on LFN
cd root
wget https://ftp.gnu.org/gnu/diffutils/diffutils-3.11.tar.xz

tar -xvf diffutils-3.11.tar.xz

mkdir diffutils-build
cd diffutils-build

../diffutils-3.11/configure --prefix=/usr
make -j8
make install

cd ..

M4

Macros M4 needed by autoconf.

#on LFN
wget https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz

tar -xvf m4-1.4.19.tar.xz

mkdir m4-build
cd m4-build
../m4-1.4.19/configure --prefix=/usr

make -j8
make install

cd ..

Bison

Needed by the kernel and GNU software.

#on LFN
wget https://ftp.gnu.org/gnu/bison/bison-3.8.tar.xz

tar -xvf bison-3.8.tar.xz

mkdir bison-build
cd bison-build
../bison-3.8/configure --prefix=/usr

make -j8
make install

cd ..

Bzip2

https://sourceware.org/bzip2/

We didn't have it!

#on LFN
wget https://sourceware.org/pub/bzip2/bzip2-latest.tar.gz

tar -xvf bzip2-latest.tar.gz


cd bzip2-1.0.8

make -j8
make install

cd ..

FLEX

used by the kernel and others.

#on LFN
wget https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz

tar -xvf flex-2.6.4.tar.gz

mkdir flex-build
cd flex-build
../flex-2.6.4/configure --prefix=/usr

make -j8
make install

cd ..

FindUtils

https://www.gnu.org/software/findutils/

Provides find.

#on LFN
wget https://ftp.gnu.org/gnu/findutils/findutils-4.10.0.tar.xz

tar -xvf findutils-4.10.0.tar.xz

mkdir findutils-build
cd findutils-build
../findutils-4.10.0/configure --prefix=/usr

make -j8
make install

cd ..

Perl

https://www.perl.org/get.html

Needed everywhere... and Curl.

#on LFN
ln -s gcc /bin/cc

wget https://cpan.org/src/5.0/perl-5.40.1.tar.gz

tar -xvf perl-5.40.1.tar.gz

cd perl-5.40.1

./Configure -d 
#not needed with configure -D prefix=/usr
make -j8
make install

cd ..

Autoconf

Needed by Git

#on LFN
wget https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.xz

tar -xvf autoconf-2.72.tar.xz

mkdir autoconf-build
cd autoconf-build

../autoconf-2.72/configure --prefix=/usr

make
# DO NOT USE -J8
make install

cd ..

Texinfo

https://www.gnu.org/software/texinfo/

Needed by bc which is needed by the kernel.

#on LFN
wget https://ftp.gnu.org/gnu/texinfo/texinfo-7.2.tar.xz

tar -xvf texinfo-7.2.tar.xz

mkdir texinfo-build
cd texinfo-build

../texinfo-7.2/configure --prefix=/usr

make -j8
make install

cd ..

BC

https://www.gnu.org/software/bc/

BC is needed to compile the Linux Kernel.

#on LFN
wget https://ftp.gnu.org/gnu/bc/bc-1.08.1.tar.xz

tar -xvf bc-1.08.1.tar.xz

mkdir bc-build
cd bc-build

../bc-1.08.1/configure --prefix=/usr

make -j8
make install

cd ..

Curl (Libcurl)

https://github.com/curl/curl/

Used to download everything... and Git.

#on LFN
wget https://github.com/curl/curl/releases/download/curl-8_12_1/curl-8.12.1.tar.gz

tar -xvf curl-8.12.1.tar.gz

mkdir curl-build
cd curl-build

../curl-8.12.1/configure --with-openssl --without-libpsl --prefix=/usr

make -j8
make install

cd ..

Git

https://github.com/git/git

Git, we all know what it is by now.

#on LFN
wget https://github.com/git/git/archive/refs/tags/v2.48.1.tar.gz
tar -xvf v2.48.1.tar.gz
cd git-2.48.1

make configure
#we can ignore the error which is about perl's flock (not implemented)
./configure --prefix=/usr

make NO_GETTEXT=1 NO_TCLTK=1 install -j8

cd ..

git clone --depth 1 https://github.com/torvalds/linux
#and we see that it does not work
curl -v google.com
#not working too!

Strace

More and more we are having small issues with missing functions, to find what we need lets download Strace!

#on LFN
wget https://github.com/strace/strace/releases/download/v6.13/strace-6.13.tar.xz

tar -xvf strace-6.13.tar.xz

mkdir strace-build
cd strace-build

../strace-6.13/configure --prefix=/usr

make -j8
make install

cd ..

Debugging with Strace

So we need to know what function we are missing in order to add it to our system.

Lets run:

strace -o trace.log curl -v google.com

nano trace.log

Inside of trace.log we can see eventfd2 being called and ending in -1 enosys (Function not implemented)

So we need to implement it!

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.13.6.tar.xz
tar -xvf linux-6.13.6.tar.xz

cd linux-6.13.6

cp /boot/.config ./

ln -s /usr/lib/libncursesw.a /usr/lib/libncurses.a

make menuconfig
#big fail
cd ..

Ncurses (no-widec)

Lets do it again but without widec

wget https://ftp.gnu.org/gnu/ncurses/ncurses-6.5.tar.gz

tar -xvzf ncurses-6.5.tar.gz

mkdir ncurses-build

cd ncurses-build
../ncurses-6.5/configure --with-shared --disable-widec --prefix=/usr

make -j8
make install
cd ..

cd linux-6.13.6

make menuconfig

General setup --->

----[*] Configure standard kernel features (expert users) --->

--------[*] Enable eventfd() system call


make -j8

mv arch/x86/boot/bzImage /boot/LFN-4

make headers

cp -r usr/include/* /usr/include/

nano /boot/grub/grub.cfg

Here is the new content:

menuentry 'LFN-4' {
        set root='(hd0,1)'
        linux /boot/LFN-4 root=/dev/sda1 rw
}
menuentry 'LFN' {
        set root='(hd0,1)'
        linux /boot/bzImage root=/dev/sda1 rw
}

Lets sync reboot and test again!

sync
#reboot
cd root

git clone --depth 1 https://github.com/torvalds/linux
#it works!

ls linux
#it works!
#lets purge root because we dont need the source anymore!
cd ..
rm -r root
mkdir root

sync

Here is the image: https://d2xw7bkejy3jlh.cloudfront.net/disk4.img.xz

5. Python, Ninja and Meson

Lets open LFN

cd LFN

qemu-system-x86_64 disk2.img -smp 8 -m 8G -enable-kvm -cpu host

cd root



git clone --depth 1 https://github.com/torvalds/linux


Device Drivers --->

----Graphics support --->

--------Frame buffer Devices --->

------------[*] Support for frame buffer device drivers --->

---------------[*] VESA VGA graphics support

Python

wget https://github.com/python/cpython/archive/refs/tags/v3.13.3.tar.gz
mkdir cpython-build
cd cpython-build
../cpython-3.13.3/configure --prefix=/usr

make -j8

make install
cd ..

Ninja

git clone --depth 1 https://github.com/ninja-build/ninja
cd ninja

./configure.py --bootstrap

ninja
(pls check if multithread and how to send bin to the right place...)
cd ..

Meson

git clone --depth 1 https://github.com/mesonbuild/meson
cd meson

./meson.py

cd ..

useful command that i don't want to loose...

Gives you the drivers used by the kernel for a given pci(e) device, to use on full kernel to get info on what you need to add to tinyconfig.

lspci -k