web-dev-qa-db-ja.com

Cでgetrandomsyscallが見つかりません

Cライブラリをアップグレードすることで問題は解決しました。


Syscall getrandomを使用したい( http://man7.org/linux/man-pages/man2/getrandom.2.html

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

または

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

とにかく、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
_

Ubuntu 14.04を使用していますが、getrandomを使用するにはどうすればよいですか?これは「新しい」システムコールなので、どうすれば使用できますか?

編集:

_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
_

rをint r = syscall(SYS_getrandom, buf, l, o);またはr = getrandom(buf、l、o)に置き換えると、同じになります。

11
anothertest

したがって、getrandomnot関数であり、単なるシステムコールのようです。

したがって、これが必要です。

/* 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;
}
9

getrandomgetentropyはバージョン2.25でglibcに追加されました 。 2017年7月の時点で、ほとんどのLinuxディストリビューションはまだこのバージョンに更新されていません(たとえば、リリースされたばかりのDebianの最新リリースは2.24です)が、まもなく更新されるはずです。

利用可能な場合は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

(他の回答で指摘されているように、カーネル3.17以降を使用していることも確認する必要があります。上記の両方のバージョンのmy_getentropyは失敗し、古いカーネルで実行した場合はerrnoENOSYSに設定します。)

6
zwol

getrandom() syscallは、Linuxカーネル3.17で導入されました。 Ubuntu 14.04にはカーネル3.13が同梱されているため、syscallを取得するには、より新しいカーネルに更新する必要があります。

Ubuntu用のLinuxカーネルの.debパッケージを入手するには、 kernel.ubuntu.com を参照してください。この問題は askubuntu.com でも議論されました。

5
lkamp

あなたのプログラムでは、セグメンテーション違反が発生すると思います。次のコードが機能するはずです。

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

ここでは、前に示したいくつかのコードをコンパイルし、バグを修正しました。比較のために、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;
}
0
Richard Wicks