Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux: Detect 64-bit kernel (long mode) from 32-bit user mode program

What's the best and most reliable way to detect if a 32-bit user mode program is running on a 64-bit kernel or not (i.e. if the system is in 'long mode')? I'd rather not call external programs if possible (or have to load any kernel modules).

Note: I want to detect whether a 64-bit kernel is being used (or really, whether the CPU is in long mode), not simply if a 64-bit capable processor is present (/proc/cpuinfo tells me that but not whether the 64-bit capability is being used).

The kernel fakes a 32-bit processor if uname is compiled 32-bit or if setarch i686 is used.

like image 729
atomice Avatar asked May 10 '11 14:05

atomice


2 Answers

Call the uname() function and check the returned machine string, which will be x86_64 for a 64-bit Intel platform.

One way of reversing the effect of the use of setarch is to reset the personality:

#include <stdio.h>
#include <sys/utsname.h>
#include <sys/personality.h>

int main()
{
    struct utsname u;

    personality(PER_LINUX);

    uname(&u);
    puts(u.machine);
    return 0;
}

This shows the right results when compiled in 32-bit mode and run on a 64-bit system:

$ gcc -m32 -o u u.c
$ ./u
x86_64
$ setarch i686 ./u
x86_64

EDIT: Fixed code to reverse effect of setarch.

Reference.

like image 107
trojanfoe Avatar answered Sep 22 '22 22:09

trojanfoe


Assuming that uname() is cheating, there are still several mechanisms. One way is to check the width of the address of any of the kernel symbols.

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  char *inputline = malloc(1024);
  char *oinputline = inputline;
  int fd = open("/proc/kallsyms", O_RDONLY);
  int numnibbles = 0;
  if (fd == -1) {
      perror("open");
      free(inputline);
      exit(1);
  }
  read(fd, inputline, 1024);
  close(fd);
  while(!isspace(*inputline)) {
      numnibbles++;
      inputline++;
  }
  printf("%dbit\n", numnibbles*4);
  free(oinputline);
  exit (0);
}
like image 23
Petesh Avatar answered Sep 23 '22 22:09

Petesh