2015-06-12 5 views
6

Das Problem wurde durch Aktualisieren der C-Bibliothek behoben.Suffix für Zufallsgenerator in C nicht gefunden


Ich möchte die syscall getRandom verwenden (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; 
} 

oder

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

Wie dem auch sei, wenn Ich versuche es mit gcc-5 zu kompilieren:

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 

Ich benutze Ubuntu 14.04, was kann ich tun, um einen Zufallsgenerator zu verwenden? Da es sich um einen "neuen" Syscall handelt, wie kann ich ihn verwenden?

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 

wenn ich ersetzen r durch int r = syscall(SYS_getrandom, buf, l, o); oder r = getRandom (buf, l, o), ist es das gleiche ..

+1

Mit Bezug auf Ihre Bearbeitung: Fügen Sie den Prototyp zu 'syscall()' bei der Verwendung hinzu! Es ist in '' Das 'SYS_getrandom' sollte dann auch verfügbar sein. – alk

+0

Warum benutzt du nicht [random (4)] (http://man7.org/linux/man-pages/man4/random.4.html), also einige Bytes von '/ dev/random' lesen? –

+0

Nein, aber Sie werden einen viel neueren Kernel benötigen .... –

Antwort

5

Die getrandom() syscall wurde im Linux-Kernel eingeführt 3.17. Ubuntu 14.04 wird mit Kernel 3.13 ausgeliefert, also müssen Sie auf einen neueren Kernel updaten, um den syscall zu erhalten.

Um .deb Pakete des Linux-Kernels für Ubuntu zu erhalten, schauen Sie sich kernel.ubuntu.com an. Dieses Problem wurde auch unter der Nummer askubuntu.com diskutiert.

+1

@anothertest: Sie möchten auch libc aktualisieren. Oder versuchen Sie stattdessen 'int r = syscall (SYS_getrandom, buf, l, o);'. – alk

8

So scheint es, dass getrandom ist nicht eine Funktion, nur ein Syscall.

Daher ist diese benötigt:

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

Soll 'buf' initialisiert werden? Ich würde denken, dass der 'syscall()' seg Fehler wird, weil Sie es bitten, 5 Bytes zu schreiben, um Null zu adressieren. – Jamie

2

Ich denke, mit Ihrem Programm einen Segmentation Fault bekommen. Der folgende Code sollte funktionieren:

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

getrandom and getentropy were added to glibc in version 2.25. Ab Juli 2017 haben die meisten Linux-Distributionen noch nicht auf diese Version aktualisiert (z. B. Debians neueste Version, die gerade veröffentlicht wurde, hat 2.24), aber sie sollten bald.

Hier ist, wie der glibc-Wrapper falls vorhanden verwenden und auf den rohen Systemaufruf zurückfallen, wenn nicht:

#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 

(Wie in anderen Antworten erwähnte, ist es auch notwendig, Sie haben Kernel 3.17, um sicherzustellen, oder höher. Sowohl die oben genannten Versionen von my_getentropy fehlschlagen und setzen errno-ENOSYS wenn auf einem älteren Kernel.)

0

Hier habe ich einige Code kompiliert, bevor gezeigt, und korrigiert die Fehler, enthalten ist meine Ausgabe von gcc -v zum Vergleich.

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