Intro
I usually tend to write longer posts on the exciting things I did, but this time I’m going to focus on a bug. It’s not a bug, but rather a consequence of a syscall interface in Linux.
So, what’s the fuss about? Somehow I treated the uname -p
output as granted:
[admin@arch ~]$ uname -p
unknown
But yet I was getting the “unknown” both on my laptop and ARM boxes. I could swear “it used to work” in the past, so I found it pretty annoying.
I guess many people would agree with me that uname -p
is just a nice and convenient method to get processor type, no need to grep /proc or anything as such. Thus I’d expect it to work.
Ubuntu test
To proof myself I am not making things up, I invoked the same command on the Ubuntu (instead of Arch Linux where the issue is present):
[admin@ubuntu ~]$ uname -p
armv7l
It looks all good here as expected.
Investigating coreutils
Where does uname reads data from? Let’s see the sources.
[admin@od1 arch]$ yay -Gf $(pkgfile -s $(which uname))
:: Querying AUR...
:: Downloaded PKGBUILD from ABS (1/1): coreutils
PKGBUILD indicates coreutils-8.31
, let’s look at src/uname.c
which looks like this:
if (toprint & PRINT_PROCESSOR)
{
char const *element = unknown;
#if HAVE_SYSINFO && defined SI_ARCHITECTURE
{
static char processor[257];
if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor))
element = processor;
}
#endif
#ifdef UNAME_PROCESSOR
if (element == unknown)
{
static char processor[257];
size_t s = sizeof processor;
static int mib[] = { CTL_HW, UNAME_PROCESSOR };
if (sysctl (mib, 2, processor, &s, 0, 0) >= 0)
element = processor;
# ifdef __APPLE__
/* This kludge works around a bug in Mac OS X. */
if (element == unknown)
{
cpu_type_t cputype;
size_t cs = sizeof cputype;
NXArchInfo const *ai;
if (sysctlbyname ("hw.cputype", &cputype, &cs, NULL, 0) == 0
&& (ai = NXGetArchInfoFromCpuType (cputype,
CPU_SUBTYPE_MULTIPLE))
!= NULL)
element = ai->name;
/* Hack "safely" around the ppc vs. powerpc return value. */
if (cputype == CPU_TYPE_POWERPC
&& STRNCMP_LIT (element, "ppc") == 0)
element = "powerpc";
}
# endif
}
#endif
if (! (toprint == UINT_MAX && element == unknown))
print_element (element);
Reading the code:
- SI_ARCHITECTURE – comes from solaris so we’re ignoring
sysinfo
syscall for now - UNAME_PROCESSOR – this is the gateway to
sysctl
syscall that works on i.e FreeBSD but no longer on Linux (kernel 5.5 patch) - APPLE – nope, not apple this time
No branch entered, so the default unknown
is set.
Mailing list
It seems it was never there or at least removed when sysctl was deprecated a decade ago. Quick googling led me to this discussion where it’s explained:
Linux doesn’t support the relevant sysinfo (Solaris-style) or sysctl (BSD-style) system calls
Coreutils team seems to be hesitant to apply proposed patches, voting for making the Linux syscall support it “the right way”:
I’d rather have the Linux folks support this stuff in their system calls; that’s where it belongs
Patch
Yup, it seems the Ubuntu/Fedora patches the coreutils with uname
syscall:
+#else
+ {
+ struct utsname u;
+ uname(&u);
+ element = u.machine;
Conclusion
It’s still odd to me the above patch isn’t pushed upstream. In any case, once I applied the patch, uname works the way I expected (y).
Overall I am not a picky user, but those small things can be annoying sometimes.