简体   繁体   English

找不到C中的getrandom系统调用

[英]getrandom syscall in C not found

The problem was resolved by upgrading the C library. 通过升级C库解决了该问题。


I would like to use the syscall getrandom ( http://man7.org/linux/man-pages/man2/getrandom.2.html ) 我想使用syscall getrandom( http://man7.org/linux/man-pages/man2/getrandom.2.html

gcc-5 -std=c11 test.c gcc-5 -std = c11 test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <linux/random.h>
#include <sys/syscall.h>

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

or 要么

 int main(void)
    {
            void *buf = NULL;
            size_t l = 5;
            unsigned int o = 1;
            int r = getrandom(buf, l, o);
            return 0;
    }

Anyway when I try to compile it with gcc-5: 无论如何,当我尝试用gcc-5编译它时:

test.c: In function ‘main’:
test.c:14:17: warning: implicit declaration of function ‘getrandom’ [-Wimplicit-function-declaration]
         int r = getrandom(buf, l, o);
                 ^
/tmp/ccqFdJAJ.o: In function `main':
test.c:(.text+0x36): undefined reference to `getrandom'
collect2: error: ld returned 1 exit status

I am using Ubuntu 14.04, what can I do to use getrandom? 我正在使用Ubuntu 14.04,我该怎么做才能使用getrandom? As it is a "new" syscall, how can I use it? 因为它是一个“新的”系统调用,我该如何使用它?

edit: 编辑:

uname -r
-> 4.0.3-040003-generic #201505131441 SMP Wed May 13 13:43:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

when I replace r by int r = syscall(SYS_getrandom, buf, l, o); 当我用int r = syscall(SYS_getrandom, buf, l, o);替换r时int r = syscall(SYS_getrandom, buf, l, o); or r = getrandom(buf, l, o) it is the same.. 或者r = getrandom(buf,l,o)它是一样的..

So, it seems that getrandom is not a function, just a syscall. 因此,似乎getrandom 不是一个函数,只是一个系统调用。

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;
}

The getrandom() syscall was introduced in the linux kernel 3.17. getrandom()系统调用是在linux内核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. Ubuntu 14.04随内核3.13一起提供,所以你必须更新到更新的内核才能获得系统调用。

To get .deb packages of the linux kernel for Ubuntu, have a look at kernel.ubuntu.com . 要获取Ubuntu的linux内核的.deb包,请查看kernel.ubuntu.com This problem was also discussed at askubuntu.com . askubuntu.com也讨论了这个问题。

getrandom and getentropy were added to glibc in version 2.25 . 在版本2.25中, getrandomgetentropy被添加到glibc中 As of July 2017, most Linux distributions have not yet updated to this version (eg Debian's most recent release, which just came out, has 2.24) but they should soon. 截至2017年7月,大多数Linux发行版尚未更新到此版本(例如Debian最新发布的版本,刚刚发布,有2.24版),但很快就会发布。

Here is how to use the glibc wrappers if available and fall back to the raw system call if not: 以下是如何使用glibc包装器(如果可用),如果不是,则回退到原始系统调用:

#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.) (正如其他答案中所指出的,还有必要确保你有内核3.17或更新。如果在较旧的内核上运行,上述版本的my_getentropy都将失败并将errnoENOSYS 。)

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进行比较。

// $ 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM