RANDOM BITS

A random site by a random clueless human
Random bits of programming, math, and thoughts By a clueless human          Random bits of programming, math, and thoughts By a clueless human

August Edition


`.` At The End of a URL

August 30, 2024

micro   dns   network

I recently learned that websites can be terminated with a . such as www.google.com. or https://neocities.org.. However, this does not work for all websites. I was skimming through Network for Dummies during work and while it doesn’t cover anything useful for the work I am trying to do (if you have taken a network course before, don’t bother reading this book unless you were bored like I was1), terminating a website with a . was a surprise.

The book states that If a domain name ends with a trailing dot, ..., and the domain name is said to be a fully qualified domain name (FQDN). The difference between an absolute name (FQDN) and relative name is important when working with DNS and can cause an “internet outage” if done incorrectly as one user on hackernews comments. Based on some article (linked by a stackoverflow user), websites that fail to handle . in their domain names are the ones who are in violation of RFC 1738 or at least not heeding to its recommendations.

Notes:

1 While Network for Dummies was actually fun to read surprisingly due to the author’s writing style, it lacks technical depth which should come to no surprise.


Splitting Pdfs into Even and Odd Pages

August 28, 2024

During the winter break I have obtained an old Xerox XE88 Workstation Printer released in the year of 2000, the year where the media were worried about Y2K causing havok to our digital infrastructure which never came to the scale we all feared thankfully. Though of course a bug will eventually will creep and wreck havok(i.e. Crowdstrike Falcon Update). But I digress, using this printer was filled with frustration as it is a relic from the past that is not meant to be used in 2024. Firstly, the printer requires a parallel port which no modern computer comes equip with. I have to drag out my last surviving desktop from my childhood that originally came with Windows Me that we immediately switched to the glorious Windows XP that we all know, love and dearly miss. As it turns out a few months later after my first use of the printer, my PS/2 connected mouse stopped working. I do not know if the PS/2 port is broken or if my PS/2 mouse is broken. I did manage to find another PS/2 mouse but as it was water damaged from a basement leak a few years ago, there was little chance it would work. Without a mouse made this task much harder, but I digress.

Parallel Port and connector

Parallel Port

PS/2 Port typically found in desktops from the 90s

Placing aside the hardware struggles to operate such printer in 2024, the printer does not have duplex printing so I had run commands on my pdfs on my Linux machine before transferring the files to my Windows XP machine (thankfully there are USB ports on this desktop that work or else I would have to dust off my 3.5 inch floppy disks and CDs). To split pdfs into even and odd pages turns out to be a very simple command:

pdftk A="${file}" cat Aodd output "${file}-odd.pdf"
pdftk A="${file}" cat Aeven output "${file}-even.pdf"

As I am printing a bunch of papers on Trusted Computing, I needed to split a lot of PDFs so this task can get quite tedious so I wrote a simple shell script:

for file in *pdf; do
  pdftk A="${file}" cat Aodd output "${file}-odd.pdf"
  pdftk A="${file}" cat Aeven output "${file}-even.pdf"
done

Executing Script Loophole

August 28, 2024

I recently came across an article discussing an attempt to close a loophole bypassing the normal execution permission bit. Exploiting a program suid and euid to gain high privilige is a commonly known technique called privilege escalation. This article does not cover this but it introduces a flaw in the current way Linux handles the execution of scripts. I do not know why privilige escalation came to my mind but as I usually write nonesensical things anyways, I shall keep it here for now. The article gives a neat example where a script does not have execution bit but is still executable by invoking the script via an interpreter.

$ ls -l evil-script.py 
-rw-r--r--. 1 zaku zaku 86 Aug 28 00:20 evil-script.py
$ ./evil-script.py
bash: ./evil-script.py: Permission denied
$ python3 evil-script.py 
Evil script has been invoked. Terror shall fill this land

As you can see, the script has no execute bit set. However, the script is still executable by feeding the script to the interpreter. I have never considered this a security loophole but after reading the article, I realized there are some concerns of allowing scripts to be executable bypassing the file’s permission. I have always made the habit of running many of the interpreted scripts non-executable and fed them to the interpreter due to laziness (I know it’s a one time thing to set the execute bit but I am just lazy to run chmod).

The article covers some promising approaches so I do expect a solution to be merged into the kernel sometime in the near future which will force me to change my habits once the interpreters make the change. Though if interpreters do make this patch, I do expect quite a few production and CI/CD servers to be impacted as there will always be someone like me who are lazy to set the execute bit on our scripts.

One benefit of closing this loophole is to force users to deliberately make the conscious choice to set the execute bit similar to how we have to set the flatpaks we download as executables (at least from my personal experience) before we can execute the flatpaks.


Replacing main()

August 24, 2024

micro   gcc   c

Any beginner C programmer will know that the first function executed in any program is the main() function. However, that is not the entire truth. Just like how we have learned the Bohr and Lewis diagrams in Chemistry in Highschool, this is an oversimplification. From my knowledge, the first function executed once the loader runs in a binary is _start().

Without going into any details, we can replace main() with another function such as foo() (sorry for the lack of creativity).

#include <stdio.h>
#include <stdlib.h>

int foo() {
  printf("Called foo\n");
  exit(0);
}

int main() {
  printf("Called main\n");
  return 0;
}

If we compile with -e <entry> where <entry> is the name of the function replacing main(), we can see the following results:

$ gcc foo.c -e foo
$ ./a.out 
Called foo

We can also observe from objdump and nm to see where the start_address of the C code is (here I am making a distinction between the first entry point of the C code and the binary).

$  objdump -f ./a.out | grep start
start address 0x0000000000401136
$ nm ./a.out | grep foo
0000000000401136 T foo

Few Notes

  1. You must define main() even if it’s not going to be used. CPP Reference states this explicitly:

    Every C program coded to run in a hosted execution environment contains the definition (not the prototype) of a function named main, which is the designated start of the program.

    Neglecting to define main results in an error like the following:

    $ gcc foo.c
    /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
    (.text+0x1b): undefined reference to `main'
    collect2: error: ld returned 1 exit status
    
  2. The C program entry must call exit() to terminate if it is not main() or else a segfault will occur
    $ ./a.out 
    Called foo
    Segmentation fault (core dumped)
    

    a backtrace via gdb won’t give much information as to why. Probably best to consult with glibc. Essentially it is likely due to the fact that _start is not a function that returns in the stack. It calls exit to terminate the program which probably does some cleaning via atexit and set the exit status $? to some value.

    (gdb) bt 
    #0  0x0000000000000001 in ?? ()
    #1  0x00007fffffffdd46 in ?? ()
    #2  0x0000000000000000 in ?? ()
    
  • https://vishalchovatiya.com/posts/crt-run-time-before-starting-main/
  • https://www.gnu.org/software/hurd/glibc/startup.html
  • https://stackoverflow.com/questions/63543127/return-values-in-main-vs-start

Editing GIFS and Creating 88x31 Buttons

August 18, 2024

micro   gifs   gimp

Lately I have been learning how to edit GIFS and it is painstaking difficult to remove a background from a GIF without using an AI tool, especially when the image has over 70 frames. There is likely an easier way to edit GIFs but I had to manually edit over 50 frames, erasing the clouds from a GIF using the eraser tool frame by frame which took some time to finish.

Original:

Result:

However, if you are not editing a GIF but rather trying to incorporate the GIF into your 88x31 buttons, it turns out to be quite simple. Following the instructions from a video on Youtube, I managed to create a few simple 88x31 buttons that have features cats, coffee, and the two programs I am or finished studying (i.e. doing a 2nd degree):

To resize the gifs, I used ezgif resize tool to set the height to be 31px since I didn’t know how to resize GIFs on GIMP as it would open a bunch of layers. I guess I could have used ffmpeg but using an online tool is just more convenient and easier. I do wonder if there are other standard anti-pixel button sizes aside from 80x15 pixels because a height of 31 pixels is quite limiting. It’s amazing what the community has been able to do with such limiting number of pixels.

For instance, the Bash button I have made has the subtitle “THE BOURNE-AGAIN SHELL” which is very hard to make out. I am assuming the standard practice is to render the button as a GIF and display the text on the next frame. That way users would be able to see the full-text.


multiple definition of `variable` ... first defined here

August 10, 2024

micro   gcc   c

Randomly I decided to compile some old projects I worked on and I was surprised to see a few compilation errors in an assembler I wrote years back. As it has been many years since I last touched most of the projects I looked at, I was pleased to see the compiler catching obvious mistakes I had made in the past. Though this did come to a surprise as to why the compiler I used years ago never complained such obvious mistakes. The solution and reason for the last compilation error was not immediate to me:

$ make
gcc -o assembler assembler.c symbol_table.c parser.c  -fsanitize=address -lasan
/usr/bin/ld: /tmp/cc1MoBol.o:(.bss+0x0): multiple definition of `table'; /tmp/cc0B4XxW.o:(.bss+0x0): first defined here
/usr/bin/ld: /tmp/cc1MoBol.o:(.bss+0x81): multiple definition of `__odr_asan.table'; /tmp/cc0B4XxW.o:(.bss+0x40): first defined here

At first I thought I may had made a stupid mistake and defined the struct called table twice but all I could find was symbol_table.h, the file that declared the variable, being included by assembler.c and parser.c. This led to the conclusion there must have been a compiler behavioral change between GCC 9 and GCC 14. After a quick googling and going through going through the Release Notes, it turns out that starting from GCC 10, GCC now defaults to -fno-common:

GCC now defaults to -fno-common. As a result, global variable accesses are more efficient on various targets. In C, global variables with multiple tentative definitions now result in linker errors. With -fcommon such definitions are silently merged during linking.

In the Porting to GCC 10 webpage, the developers of GCC notes:

A common mistake in C is omitting extern when declaring a global variable in a header file. If the header is included by several files it results in multiple definitions of the same variable

To resolve this issue, one can either silently ignore their mistake and compile with -fcommon or to correctly declare the global variable with the extern keyword.


Delusional Dream of a OpenPower Framework Laptop

August 4, 2024

Framework is a company that makes modular and repairable laptops that has captured the interests of tech enthusiasts over the past 4 years. Currently Framework laptops are limited to x86-64 architecture supporting Intel and later AMD CPUs in 2023. Although Framework laptops are not entirely open source, they have open source a decent chunk of their work from my understanding and which allows third party development of components and makes partnership possible for other companies such as DeepComputing to release a mainboard that runs a RISC-V CPU . While the new mainboard will not be usable for everyday applications, it is a step forward to a more open ecosystem and this is an exciting step for both Framework, RISC-V and the broader open-advocate community. This announcement makes me wonder the possibility of OpenPower running on a Framework laptop. Similarly to RISC-V, there isn’t an easily accessible way to obtain a consumer product running on OpenPower (aside from Raptor Computing with their extremely expensive machines). There is the PowerPC Notebook project ran by a group of volunteers who are trying to develop an open source PowerPC notebook to the hands of hobbyists. It would be interesting if OpenPower community could also partner with Framework to develop a mainboard once the project is complete and the software is more matured. However, this would be a difficult step as there is no dedicated company like DeepComputing that will pour resources into making this happen. The interest into OpenPower is low and overshadowed by the wider industry interest in expanding the ARM and RISC-V architecture to consumers. IBM made a huge mistake in open sourcing the POWER architecture too late. But one could always dream (even if it’s delusional) :D


2024 Update

August 4, 2024

micro   site

Website

In the past year I have been very lazy as evident with my lack of activity on my personal blog. I'm now trying to pick up blogging again. It's hard to believe that it's been almost an entire year since I created this neocity site, which has almost 0 updates since. I've been thinking about how to use this site since I already have a blog on GitHub Pages. Honestly, I forgot this corner existed, and it’s been bothering me that I couldn’t write my random, nonsensical thoughts because my main blog wouldn’t be a suitable medium until now. So, I’ve decided that this corner will be a microblog where I can share random articles and thoughts. A microblog is different from a regular blog in that the content is much shorter. This space will allow me to quickly jot down something random. I hope that a collection of these random posts will evolve into a blog post or spark an idea for my final year thesis or project.

How are my studies going?

I’m still studying Mathematics, but I’ve lost much of my initial interest in the field after taking a few third-year courses. I ended up taking fewer Math courses, which puts my ability to graduate on time at risk. Listening to lectures and reading about abstract groups and rings made me really miss programming and computer science. Despite this, there were still some Math courses I enjoyed, such as Combinatorics and Real Analysis. However, I didn’t last long in the follow-up Real Analysis courses that covered Stone-Weierstrass and Commutative C* Algebra. Feeling tired of abstract Mathematics, I decided to take a break and pursue an internship at a telecommunications enterprise.

retro computer fiddling with excel What am I doing Now?

As mentioned, I am currently doing a year-long internship with a telecommunications enterprise. Although the job isn't very exciting, it's a welcome break from Mathematics. This would typically be a great chance to catch up on my Computer Science studies by delving into textbooks and online resources, but I’ve been quite lazy. Instead, I've been focusing on learning French, a language I've always wanted to master. I started learning French in elementary school, as it’s a requirement in Canada. While it might make more sense to learn my mother tongue, I’m opting to learn French, which might seem confusing to some. For context, I don't have an English name and was born in some Asian country but I am unable to communicate with others in my mother tongue.