2015-06-12 20 views
6

Il problema è stato risolto aggiornando la libreria C.srall casuale in C non trovato


Vorrei utilizzare il getrandom syscall (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; 
} 

o

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

In ogni caso, quando Provo a compilarlo con 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 

Sto usando Ubuntu 14.04, cosa posso fare per usare getrandom? Poiché è un "nuovo" syscall, come posso usarlo?

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 

quando sostituisco r da int r = syscall(SYS_getrandom, buf, l, o); o r = getrandom (buf, l, o) è lo stesso ..

+1

Riferimento alla modifica: aggiungi il prototipo a 'syscall()' quando lo si utilizza! È in '' Anche il 'SYS_getrandom' dovrebbe essere disponibile. – alk

+0

Perché non usi [random (4)] (http://man7.org/linux/man-pages/man4/random.4.html), cioè leggi alcuni byte da '/ dev/random'? –

+0

No, ma è necessario un kernel più recente .... –

risposta

5

La getrandom() syscall è stato introdotto nel kernel di Linux 3.17. Ubuntu 14.04 viene fornito con il kernel 3.13, quindi devi aggiornare ad un kernel più recente per ottenere syscall.

Per ottenere pacchetti .deb del kernel linux per Ubuntu, dare un'occhiata a kernel.ubuntu.com. Questo problema è stato anche discusso allo askubuntu.com.

+1

@anothertest: si desidera aggiornare anche libc. Oppure prova 'int r = syscall (SYS_getrandom, buf, l, o);' invece. – alk

8

Quindi, sembra che getrandom sia non una funzione, solo un syscall.

Quindi questo è necessario:

/* 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

Il messaggio "buf" deve essere inizializzato? Penserei che 'syscall()' segherà l'errore perché lo chiedi di scrivere 5 byte per indirizzare lo zero. – Jamie

2

Penso che con il vostro programma si otterrà un errore di segmentazione. Il seguente codice dovrebbe funzionare:

#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. A partire da luglio 2017, la maggior parte delle distribuzioni Linux non sono ancora state aggiornate a questa versione (ad esempio, la versione più recente di Debian, appena uscita, ha 2.24), ma dovrebbero presto.

Ecco come utilizzare i wrapper glibc se disponibile e ricadere alla chiamata di sistema cruda, se non:

#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 

(Come sottolineato in altre risposte, è anche necessario assicurarsi di avere il kernel 3.17 o più recente. Entrambe le versioni precedenti di my_getentropy falliranno e impostare errno-ENOSYS se eseguito su un kernel più vecchio.)

0

Qui, ho compilato un codice mostrato prima, e corretto i bug, incluso è la mia uscita da gcc -v per confronto.

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