getrandom syscall in C not found

♀尐吖头ヾ 提交于 2019-11-29 10:11:40

So, it seems that getrandom is not a function, just a syscall.

Hence this is needed:

/* Note that this define is required for syscalls to work. */
#define _GNU_SOURCE

#include <unistd.h>
#include <sys/syscall.h>
#include <linux/random.h>

int main(int arg, char *argv[])
{
        void *buf = NULL;
        size_t l = 5;
        unsigned int o = 1;
        int r = syscall(SYS_getrandom, buf, l, o);
        return 0;
}
lkamp

The getrandom() syscall was introduced in the linux kernel 3.17. Ubuntu 14.04 gets shipped with kernel 3.13, so you have to update to a more recent kernel to get the syscall.

To get .deb packages of the linux kernel for Ubuntu, have a look at kernel.ubuntu.com. This problem was also discussed at askubuntu.com.

getrandom and getentropy were added to glibc in version 2.25. As of July 2017, most Linux distributions have not yet updated to this version (e.g. Debian's most recent release, which just came out, has 2.24) but they should soon.

Here is how to use the glibc wrappers if available and fall back to the raw system call if not:

#define _GNU_SOURCE 1
#include <sys/types.h>
#include <unistd.h>

#if defined __GLIBC__ && defined __linux__

# if __GLIBC__ > 2 || __GLIBC_MINOR__ > 24
#  include <sys/random.h>

int
my_getentropy(void *buf, size_t buflen)
{
    return getentropy(buf, buflen);
}

# else /* older glibc */
#  include <sys/syscall.h>
#  include <errno.h>

int
my_getentropy(void *buf, size_t buflen)
{
    if (buflen > 256) {
        errno = EIO;
        return -1;
    }
    return syscall(SYS_getrandom, buf, buflen, 0);
}

# endif

#else /* not linux or not glibc */
#error "Need implementation for whatever operating system this is"

#endif

(As pointed out in other answers, it is also necessary to ensure you have kernel 3.17 or newer. Both the above versions of my_getentropy will fail and set errno to ENOSYS if run on an older kernel.)

I think with your program you will get a segmentation fault. The following code should work:

#include <iostream>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/random.h>

int main() {
  unsigned long int s;
  syscall(SYS_getrandom, &s, sizeof(unsigned long int), 0);
  std::cout << "The seed is: " << s << "." << std::endl;
}

Here, I compiled some code shown before, and corrected the bugs, included is my output from gcc -v for comparison.

// $ gcc -v
// Using built-in specs.
// COLLECT_GCC=gcc
// COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
// Target: x86_64-linux-gnu
// Configured with: ../src/configure -v --with-pkgversion='Ubuntu
//   5.4.0-6ubuntu1~16.04.9' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs
//   --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
//   --program-suffix=-5 --enable-shared --enable-linker-build-id
//   --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
//   --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
//   --enable-libstdcxx-debug --enable-libstdcxx-time=yes
//   --with-default-libstdcxx-abi=new --enable-gnu-unique-object
//   --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib
//   --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo
//   --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home
//   --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64
//   --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64
//   --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
//   --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686
//   --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib
//   --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu
//   --host=x86_64-linux-gnu --target=x86_64-linux-gnu
// Thread model: posix
// gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)

//#define _GNU_SOURCE

#include <stdio.h>

#include <unistd.h>
#include <sys/syscall.h>
#include <linux/random.h>

int main (int arg, char **argv)
{
  size_t length = 5;
  unsigned char buf[length];
  int r = syscall(SYS_getrandom, buf, length, 0);

  if (r != 0)
  {
    int iIter;
    printf ("random %zu bytes = ",length);
    for (iIter = 0 ; iIter < length-1 ; iIter++)
    {
      printf ("%02x:", buf[iIter]);
    }
    printf ("%02x\n", buf[iIter]);
  }
  else
  {
    perror ("syscall (SYS_getrandom, ...)");
  }
  return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!