Lotfi ben Othmane, Martin Gilje Jaatun and Edgar Weippl's Empirical Research for Software Security (CRC Press)

Developing truly secure software is no walk through the park. more>>

Update Tickets from the Command Line

In the April 2017 issue, I wrote about how to use ticketing systems as a sysadmin to organize your tasks better. more>>

Programmation embarquée sur Raspberry Pi sans sonde JTAG – Partie 2/2

2.1.2 GDB

glmf-rpi/ $ arm-none-eabi-gdb hello.elf
GNU gdb (GNU Tools for ARM Embedded Processors) 7.12.0.20161204-git
...
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) # 1. Configuration GDB dépendante de Alpha
(gdb) source sdk/alpha.gdb
(gdb)
(gdb) # 2. Connexion a la RPi
(gdb) # Nécessite les droits de lecture/écriture sur le TTY du lien série,
(gdb) # ici le nœud `/dev/ttyUSB0`
(gdb) set serial baud 115200
(gdb) target remote /dev/ttyUSB0
(gdb)
(gdb) # 3. Téléchargement sur la RPi du programme passé en argument à GDB
(gdb) load
(gdb) # `load` place aussi le pointeur sur instruction sur son point
(gdb) # d’entrée `_start`
(gdb)
(gdb) # 4. Lancer alors l’exécution jusqu’à atteindre la fonction main
(gdb) tbreak main
(gdb) continue

Il est conseillé d’écrire ces commandes, préalables à toute les prochaines sessions de debug, dans un fichier que GDB pourra alors lire et exécuter via l’option de lancement -x <fichier>, ou la commande source <fichier>. Le fichier run.gdb, dont le TTY doit être ajusté selon le cas, est à ce titre fourni à la racine du dépôt.

glmf-rpi/ $ arm-none-eabi-gdb -x run.gdb hello.elf
...
Temporary breakpoint 1, main () at src/hello-world/HelloWorld.c:5
5 printf("Hello %s!\n", "RPi");
(gdb) # Nous avons atteint la fonction main()
(gdb) list
1 #include <stdio.h>
2
3 int main(void)
4 {
5 printf("Hello RPi!\n");
6 }
(gdb) # Prêt pour une nouvelle session de debug

Ou encore :

glmf-rpi/ $ arm-none-eabi-gdb hello.elf
(gdb) source -v run.gdb
...
Temporary breakpoint 1, main () at src/hello-world/HelloWorld.c:5
5 printf("Hello %s!\n", "RPi");
(gdb) # Nous avons atteint la fonction main()
(gdb) list
1 #include <stdio.h>
2
3 int main(void)
4 {
5 printf("Hello RPi!\n");
6 }
(gdb) # Prêt pour une nouvelle session de debug

Nous pouvons alors le laisser s’exécuter et observer la sortie standard sur la console GDB :

(gdb) continue
Continuing.
Hello RPi!
Program received signal SIGTRAP, Trace/breakpoint trap.
_exit (rc=0) at SYSFILEIO/MAKEFILE/../SOURCE/SYSFILEIO_EXIT.c:11
11 SYSFILEIO/MAKEFILE/../SOURCE/SYSFILEIO_EXIT.c: No such file or directory.
(gdb)

Ou encore l’exécuter au pas-à-pas :

(gdb) source run.gdb
...
Temporary breakpoint 1, main () at src/hello-world/HelloWorld.c:5
5 printf("Hello %s!\n", "RPi");
(gdb) break printf
Breakpoint 2 at 0x854c
(gdb) continue
Continuing.
Breakpoint 2, 0x0000854c in printf ()
(gdb) bt
#0 0x0000854c in printf ()
#1 0x00008334 in main () at src/hello-world/HelloWorld.c:5
(gdb) finish
Run till exit from #0 0x0000854c in printf ()
Hello RPi!
0x00008334 in main () at src/hello-world/HelloWorld.c:5
5 printf("Hello %s!\n", "RPi");
(gdb) next
6 }
(gdb) delete 2
(gdb) call printf("appel dynamique!\n")
appel dynamique!
$1 = 17

Les fonctionnalités de GDB se classent en deux grandes catégories : le debug de code et le debug de données. Entre autres, il est possible de visualiser la pile d’appel, de lire/écrire les données, les registres et la mémoire. Mais aussi d’insérer des breakpoints, d’intercepter des appels de fonctions à l’aide de breakpoints conditionnels…

Il est également possible d’envoyer des commandes spécifiques au serveur GDB via la commande monitor <commande>, lui permettant d’implémenter ses propres commandes. Par exemple, ici, la capture d’exceptions :

(gdb) monitor help
...
(gdb) monitor gdb/catch
RST : no : Reset Exception
UND : no : Undefined Instruction Exception
SWI : no : Software Interrupt Exception
PABRT : no : Prefetch Abort Exception
DABRT : no : Data Abort Exception
IRQ : no : IRQ (interrupt) Exception
FIQR : no : FIQ (fast interrupt) Exception

Cet exemple de programme constitue donc un point de départ idéal pour une exploration plus approfondie des possibilités de GDB et/ou du développement embarqué sur RPi. Le lecteur peut laisser libre cours à son imagination pour exploiter d’autres fonctions de la bibliothèque C (ex. : scanf(), fopen()…) ou en utilisant d’autres exemples de programmes C standards à embarquer sur la RPi en se reposant sur la bibliothèque C fournie (ex. : la runtime C++).

Un programme se reposant sur l’extension File I/O ne peut pas s’exécuter sans client ou serveur GDB puisque ce sont eux qui échangent et exécutent les appels systèmes (figure 9). Cette fonctionnalité doit donc être considérée comme un moyen de développement supplémentaire dont les utilisateurs peuvent bénéficier ou non selon leur bon vouloir. À bon entendeur.

2.2 Raytracer

Cet exemple est une nouvelle illustration des concepts vus jusqu’à présent et appliqués cette fois-ci à un programme exploitant de manière plus avancée la RPi. Il utilise en effet son unité flottante ainsi que son GPU. Nous finirons avec sa « mise en production » sur la carte microSD de la RPi pour qu’il démarre de manière autonome, sans aucune intervention de GDB.

Figure 10 : Image générée par le raytracer en bare-metal sur la sortie HDMI de la RPi.

2.2.1 Compilation

Ce raytracer affiche sur la sortie HDMI les images calculées par l’algorithme de raytracing (figure 10), contrôlé par le GPU, lui-même commandé par le processeur ARM à travers des requêtes échangées par mailbox [10]. Le calcul se fait pixel par pixel et les résultats sont écrits dans le framebuffer alloué par le GPU. Le fichier VC.c contient le code source des fonctions d’affichage graphiques : une fonction pour demander au GPU de préparer un framebuffer, et une seconde fonction pour récupérer son adresse. Le framebuffer consiste alors en une matrice de pixels à écrire au format 32 bits ARGB.

Pour le compiler :

glmf-rpi/ $ make raytracer.elf
arm-none-eabi-gcc -specs=sdk/Alpha.specs -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -g3 -ggdb -Wl,-Tsdk/link.ld -Lsdk -Wl,-umalloc -Wl,-Map,raytracer.map -o raytracer.elf -Og src/raytracer/main.c src/raytracer/Raytracing.c src/raytracer/VC.c src/raytracer/VC_aligned_buffer.S -lm

Cet exemple introduit aussi le niveau d’optimisation g avec l’option -Og qui permet d’optimiser le programme tout en conservant une qualité de debug du programme acceptable. Elle évite donc les optimisations les plus agressives qui entraînent trop de perte de traçabilité entre le code objet et son code source. L’expérience de debug est quoi qu’il en soit dégradée (par exemple, impossibilité de lire certaines variables, exécution au pas-à-pas du code réordonnancé, etc.) par rapport à un programme compilé sans aucune optimisation.

2.2.2 GDB

Nous allons utiliser GDB afin d’observer le fonctionnement de l’algorithme de raytracing en employant les moyens de modification dynamique des données du programme.

Démarrer d’abord la session de debug :

glmf-rpi/ $ arm-none-eabi-gdb -x run.gdb raytracer.elf
...
Temporary breakpoint 1, main () at src/raytracer/main.c:221
221 {
(gdb)

Les temps de traitement longs du raytracer et sa boucle infinie de rendu vidéo sont de parfaits candidats à la fonctionnalité d’interruption asynchrone de l’exécution de la cible, c’est-à-dire tandis qu’elle exécute le raytracer, lorsque le client reçoit le signal <Ctrl> + <c> (SIGINT). Cette fonctionnalité repose sur une interruption matérielle qui nécessite donc de démasquer les interruptions externes du processeur. Pour ce faire, nous utilisons les fonctionnalités de modification des registres ainsi que de scripting GDB, dont la syntaxe des expressions est identique à celle du langage C. Le registre en question est en plus l’un des registres superviseurs, absents du mode GDB « natif », mais ici communiqué par Alpha :

(gdb) # Démasquer les interruptions externes pour rendre possible
(gdb) # l’interruption du programme via ctrl-c.
(gdb) print /x $cpsr &= ~(1 << 7)
$1 = 0x6000015f

Nous sommes désormais en mesure d’interrompre à tout moment l’exécution du raytracer sur la RPi :

(gdb) continue
Continuing.
^C
Program received signal SIGSTOP, Stopped (signal).
0x0000921c in __ieee754_sqrt ()

Les interruptions externes sont masquées par le point d’entrée _start tel qu’implémenté par la bibliothèque C newlib. Le démasquage doit donc intervenir une fois cette fonction terminée, lorsque nous atteignons la fonction main().

Nous reprenons alors la main avec GDB où le programme a été interrompu. Voici donc un exemple modifiant successivement la couleur d’une sphère :

(gdb) set A_SPHERE[0].S_PROPERTY.S_A.F_GREEN = 0.9
(gdb) continue
Continuing.
^C
Program received signal SIGSTOP, Stopped (signal).
0x00008aa0 in RAYT_TRACE (…) at src/raytracer/Raytracing.c:306
306 S_RGB.F_BLUE = (P_PROPERTY->S_A.F_BLUE * P_RAYT_WORLD->S_AMBIANT_LIGHT.F_BLUE);
(gdb) bt
#0 0x00008aa0 in RAYT_TRACE (…) at src/raytracer/Raytracing.c:306
#1 0x00008e24 in RAYT_RENDER (…) at src/raytracer/Raytracing.c:421
#2 0x000083d0 in main () at src/raytracer/main.c:239
(gdb) set A_SPHERE[0].S_PROPERTY.S_A.F_GREEN = 0.3
(gdb) continue
Continuing.
^C
Program received signal SIGSTOP, Stopped (signal).
0x00009080 in sqrt ()
(gdb) set A_SPHERE[0].S_PROPERTY.S_A.F_GREEN = 0.6
(gdb) # Execution background
(gdb) # Permet de garder la main sur le client tandis que le serveur la rend au programme.
(gdb) continue &
Continuing.
(gdb) # Commande GDB équivalente au signal ctrl-c
(gdb) interrupt
Program received signal SIGSTOP, Stopped (signal).
0x00009240 in __ieee754_sqrt ()
(gdb) # Les variables telles que I_RESOLUTION_FACTOR sont lues une seule fois
(gdb) # lors de l’initialisation du programme. Il est donc nécessaire de reprendre
(gdb) # depuis le début l’exécution du programme pour pouvoir la modifier.
(gdb) print I_RESOLUTION_FACTOR
$2 = 2
(gdb) # Alpha reset le processeur lorsqu’il reçoit la commande kill, aussi induite
(gdb) # par d’autres commandes GDB. C’est le cas notamment de la commande de
(gdb) # connexion contenue dans le script run.gdb. Il suffit donc de le relancer
(gdb) # pour recommencer une session.
(gdb) source run.gdb
...
Temporary breakpoint 1, main () at src/raytracer/main.c:221
221 {
(gdb) # Nous pouvons ici modifier la résolution de l’image avant sa lecture
(gdb) # par la fonction d’initialisation du GPU.
(gdb) set I_RESOLUTION_FACTOR = 4
(gdb) continue
(gdb) # Observer la nouvelle résolution.

Le raytracer est statistiquement le plus souvent interrompu durant l’exécution de la fonction sqrt() (racine carré), car longue à exécuter et appelée très fréquemment.

2.2.3 Embarquement

Nous souhaitons finalement embarquer le programme et qu’il s’exécute automatiquement au démarrage de la RPi sans avoir besoin d’utiliser GDB pour le charger. Nous allons donc l’interfacer avec le bootloader de la RPi qui charge puis exécute le contenu de la carte microSD, selon les directives contenues dans le fichier config.txt. En l’absence de ce fichier, le comportement par défaut copie le fichier kernel.img dans la RAM à l’adresse 0x8000 et lance l’exécution à cette adresse.

Il est avant tout nécessaire de prendre en compte les dépendances avec l’utilisation de GDB (ex. : File I/O) ou du serveur Alpha (ex. : mapping mémoire). Si nécessaire, il convient alors de les implémenter. Ainsi, nous avons fait le choix arbitraire de profiter du comportement par défaut du bootloader pour placer à l’adresse 0x8000 un second point d’entrée contenant le code d’initialisation, puis invoquant le point d’entrée de la runtime C _start. D’autres solutions sont parfaitement envisageables et le code source de cette implémentation est fourni à titre d’exemple dans sdk/CPU_start.S.

Pour générer kernel.img et le copier sur la carte microSD :

glmf-rpi/ $ make kernel.img
arm-none-eabi-objcopy -O binary raytracer.elf kernel.img
arm-none-eabi-objcopy --only-keep-debug raytracer.elf kernel.dbg
glmf-rpi/ $ # Insérer la carte microSD dans le poste de travail
glmf-rpi/ $ sudo mount -t vfat -o rw,umask=0000 /dev/sdc /mnt
glmf-rpi/ $ mv /mnt/config.txt /mnt/config.txt.gdb
glmf-rpi/ $ cp -v kernel.img /mnt
'kernel.img' -> '/mnt/hdd/kernel.img'
glmf-rpi/ $ sudo umount /mnt

Insérez à nouveau la carte microSD dans la RPi. Celle-ci démarre directement avec le raytracer sans plus aucune intervention de GDB.

Enfin, le fichier kernel.img, forme purement binaire de l’exécutable raytracer.elf, ne contient plus aucune information de debug. Il n’est donc plus possible de le débugger depuis le code source en tant que tel, mais uniquement sous forme binaire désassemblée par GDB (layout asm). Il est toutefois possible d’obtenir les informations de debug dans un fichier séparé. Le fichier kernel.dbg généré à ses côtés par la commande de compilation précédente contient toutes les informations de debug de kernel.img. Pour finir, voici comment les utiliser :

glmf-rpi/ $ # Une fois le fichier config.txt restauré…
glmf-rpi/ $ arm-none-eabi-gdb
(gdb) source sdk/alpha.gdb
(gdb) set serial baud 115200
(gdb) target remote /dev/ttyUSB0
Remote debugging using /dev/ttyUSB0
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x07f10570 in ?? ()
(gdb) # 1. Lecture des informations de debug
(gdb) file kernel.dbg
program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from kernel.dbg...done.
(gdb) # 2. Téléchargement binaire de kernel.img à l’adresse 0x8000
(gdb) restore kernel.img binary 0x8000
Restoring binary file kernel.img into memory (0x8000 to 0x1b130)
(gdb) # 3. Placer le registre pointeur sur instruction à l’adresse
(gdb) # de démarrage avec Alpha
(gdb) set $pc = &_start
(gdb) break main
Breakpoint 1 at 0x8320: file src/raytracer/main.c, line 221.
(gdb) continue
Continuing.
Breakpoint 1, main () at src/raytracer/main.c:221
221 {
(gdb) # Prêt pour débugger kernel.img

Dans cet exemple, nous faisons manuellement ce que la commande load effectuait pour nous depuis le fichier ELF raytracer.elf. Les deux méthodes sont d’ailleurs strictement équivalentes dans le cas présent qui ne comporte aucune autre distinction que les formats des fichiers raytracer.elf et kernel.img : tous deux contiennent le même programme binaire.

Ce dernier exemple est un moyen de distribuer le programme tout en conservant les informations de debug. Il constitue le point de départ d’une possible stratégie de support et maintenance d’une distribution binaire d’un programme embarqué.

Conclusion

Nous nous sommes donc totalement affranchis du coût et de la complexité que peut représenter une sonde JTAG. Maîtriser un tel équipement est une tâche complexe, souvent attribuée aux professionnels les plus aguerris. L’utilisation de GDB, couplée à une implémentation du serveur entièrement logicielle, facilite la démocratisation et la simplification du développement embarqué au quotidien. L’effort nécessaire pour mettre en œuvre le serveur relève strictement des mêmes compétences que celles du développement embarqué. GDB est en plus le débugger bénéficiant de la plus large communauté en ligne, et tout étudiant en informatique sait par exemple l’utiliser après avoir débuggé son premier programme C ou C++. Depuis les choix d’architecture en phases amont de R&D jusqu’à la vérification et la validation d’un logiciel embarqué complet en phase de production, chacun peut trouver son compte parmi les fonctionnalités de GDB. Les sondes restent néanmoins nécessaires dans certains cas bien précis, comme le debug des firmwares, le debug spécialisé de certaines unités processeur (ex. : lire/écrire des caches internes) ou encore le debug temps réel de bus rapides (ex. : debug PCIe).

Les opportunités sont désormais nombreuses sur ce terrain de jeu RPi. Comprendre le mode superviseur ARM, développer du logiciel bare-metal haute performance, ou encore découvrir les interfaces SPI ou USB, sont tout autant de sujets bas niveaux et universels à explorer.

Christophe Plé
[CEO de Farjump et Expert en développement logiciel embarqué]

Julio Guerra
[CTO de Farjump]

Références

[1] Distribution ARM officielle de la toolchain GNU sur https://developer.arm.com/open-source/gnu-toolchain/gnu-rm
[2] Exemple de convertisseur seul sur http://amzn.eu/3H5FIx9
[3] Exemple de câbles jumper sur http://amzn.eu/jiuRBbi
[4] Exemple de câble USB pour le convertisseur [1] sur http://amzn.eu/ihFNmFf
[5] Exemple de convertisseur format « câble » sur http://amzn.eu/flbbyHF
[6] Documentation des tracepoints sur https://sourceware.org/gdb/onlinedocs/gdb/Tracepoints.html
[7] Documentation de l’extension File I/O de GDB sur https://sourceware.org/gdb/onlinedocs/gdb/File_002dI_002fO-Remote-Protocol-Extension.html
[8] Documentation de l’interface texte sur https://sourceware.org/gdb/onlinedocs/gdb/TUI.html
[9] Liste des appels système supportés sur https://sourceware.org/gdb/onlinedocs/gdb/List-of-Supported-Calls.html
[10] Documentation du framebuffer du SoC BCM2835 sur http://elinux.org/RPi_Framebuffer

 

Secure Boot et UEFI

Introduction

Le boot sécurisé, ou Secure Boot, est arrivé avec les EFI et permet de restreindre le lancement de certaines applications seulement au démarrage de la machine. Une application UEFI est un binaire au format Portable Executable, au même titre que les .exe de Windows, dont l’extension est .EFI. Le boot sécurisé permet donc de contrôler l’exécution de ces fichiers binaires en les autorisant ou non à s’exécuter. Afin d’être bootables, ces programmes doivent se trouver sur une partition FAT (16 ou 32) lors du démarrage de la machine. Ces dernières peuvent être situées sur une clé USB ou sur une partition du disque dur.

Avec l’arrivée de Windows 8, Microsoft a imposé aux constructeurs de mettre en place le boot sécurisé sur les (U)EFI afin de permettre le démarrage uniquement au bootloader de Windows et cela pour des raisons de sécurité. Ainsi, par défaut aucun autre programme .EFI n’est bootable (leur boot sécurisé étant actif par défaut). Une méthode consiste à désactiver le Secure Boot dans le BIOS/UEFI. À partir de là, n’importe quel programme .EFI est bootable.

But final

À travers ce mini tutoriel, notre but est d’être capable d’exécuter un seul et unique programme .EFI au démarrage avec le Secure Boot actif. Il s’agit du programme Pong.efi que avons réalisé lors du précédent tutoriel. Nous allons faire en sorte que ce programme s’exécute avec le Secure Boot activé.

Note: Afin de suivre ce tutoriel, vous devez au préalable savoir démarrer un programme .EFI et savoir comment accéder au menu (U)EFI (ancien BIOS menu), qui se fait généralement avec la touche F7, F12 ou Échap au démarrage de la machine.

État des lieux

Après avoir activé le Secure Boot, en essayant de démarrer sur le Pong, voici le message obtenu :

Image verification failed !
Image certification not foud in Authorized Database(db)!

Ceci est dû au fait que les clés, installées par défaut dans les PC vendus avec Windows 8, permettent de démarrer uniquement sur le bootloader de Windows. Nous allons donc générer nos propres clés qui permettront de démarrer notre Pong, et seulement lui.

En (U)EFI, il existe 4 variables non volatiles importantes qui s’installent dans une ROM de la carte mère, donc de manière persistante. Les voici :

  • La Platform Key (PK) : Cette clé contient au plus une entrée. Lorsqu’elle est effacée, le système désactive le Secure Boot et l’utilisateur peut modifier les clés présentées ci-dessous librement, c’est-à-dire sans vérification de signature.
  • La Key Exchange Key (KEK) : Cette variable contient une ou plusieurs clés publiques RSA. Ainsi, la mise à jour des variables db ou dbx (ci-dessous) nécessite d’être signée avec l’une des clés privées associées aux clés publiques contenues dans cette variable KEK.
  • Signature Database (db) : Cette variable contient une base de données des signatures, des clés publiques, voire même des hash des programmes qui sont autorisés à s’exécuter.
  • Forbidden Signatures Database (dbx) : Cette variable agit comme une blacklist des programmes voulant s’exécuter.

Génération de nouvelles clés

La première étape consiste à générer nos propres clés PK, KEK et db. Pour ce faire, nous aurons besoin d’un PC sous Linux muni d’OpenSSL. Créons un dossier qui contiendra nos clés :

$ mkdir efikeys
$ cd efikeys
efikeys/ $

Maintenant, utilisons OpenSSL afin de générer des clés RSA de longueur 2048 bits, puis un certificat X.509 utilisant SHA-256 et expirant dans 10 ans :

efikeys/ $ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=platform key PONG/" -keyout PK.key -out PK.crt -days 3650 -nodes -sha256
efikeys/ $ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=key-exchange-key PONG/" -keyout KEK.key -out KEK.crt -days 3650 -nodes -sha256
efikeys/ $ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=kernel-signing key PONG/" -keyout db.key -out db.crt -days 3650 -nodes -sha256

Note : Le contenu du “Common name” (CN) peut être remplacé par ce que vous souhaitez.

Nous avons dès lors trois certificats (PK.crt, KEK.crt et db.crt) ainsi que les clés privées associées (PK.key, KEK.key et db.key)

Préparation et mise en place des clés

Maintenant que nous avons nos clés et certificats, nous devons générer une liste de signatures que nous aurons signé au format .auth. Certains UEFI, y compris celui de notre machine de test, n’acceptent que ce format. Pour cela, nous aurons besoin d’un utilitaire open-source téléchargable ici : app-crypt/efitools.

Générons notre liste de signatures dans un premier temps, puis signons la avec notre Platform Key privée. Voici les commandes à utiliser :

efikeys/ $ cert-to-efi-sig-list -g "$(uuidgen)" PK.crt PK.esl
efikeys/ $ sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth

Faisons de même pour la KEK et la db :

efikeys/ $ cert-to-efi-sig-list -g "$(uuidgen)" KEK.crt KEK.esl
efikeys/ $ sign-efi-sig-list -a -k PK.key -c PK.crt KEK KEK.esl KEK.auth
efikeys/ $ cert-to-efi-sig-list -g "$(uuidgen)" db.crt db.esl
efikeys/ $ sign-efi-sig-list -a -k KEK.key -c KEK.crt db db.esl db.auth

Afin de mettre en place ces clés .auth dans notre UEFI, transférons les sur une clé USB, démarrons sur le menu UEFI, rendons-nous dans la section “Key Management”, puis dans cet ordre là :
– Effaçons les clés existantes (Clear Secure Boot keys)
– Mettons en place la clé db.auth (Set DB from File)
– Mettons en place la clé KEK.auth (Set KEK from File)
– Mettons en place la clé PK.auth (Set PK from File)

Dans ces trois dernières étapes, une fenêtre graphique apparaîtra dans laquelle il sera possible de sélectionner les fichiers .auth présents sur la clé USB. Une fois mis en place, quittons le menu avec “Save & Exit”.

Note : La clé dbx a été délaissée délibérément, nous pourrons alors soit générer une liste vierge, soit récupérer l’ancien fichier dbx présent dans le Secure Boot de l’UEFI (faisable directement depuis le menu), le re-signer avec notre nouvelle clé KEK.key et le remettre en place avec sa nouvelle signature.

Signer le binaire

Maintenant que nos clés sont en place, essayons d’exécuter notre Pong.efi. La même erreur que précédemment s’affiche :

Image verification failed !
Image certification not foud in Authorized Database(db)!

En effet, le binaire n’est toujours pas signé. Signons-le avec notre clé. Pour cela, nous allons utiliser l’utilitaire sibsign issu du paquet sbsigntool. Prenons notre binaire Pong.efi et créons un binaire Pong-signed.efi :

efikeys/ $ sbsign --key db.key --cert db.crt --output Pong-signed.efi Pong.efi

Remarquons que dans notre cas, il a fallu utiliser la clé privée db (et non KEK) ainsi que son certificat. Cela n’est pas une généralité et dépend des machines.

Après avoir généré ce binaire signé, plaçons-le sur notre clé USB sous le nom de BOOTX64.EFI de manière à avoir l’arborescence suivante :

└── EFI
    └── BOOT
       └── BOOTX64.EFI

Démarrons sur la clé et hop ! Notre Pong a démarré !

Pour aller plus loin

Dans ce tutoriel, nous avons généré des clés qui permettent l’exécution uniquement de notre programme, le bootloader Windows ne sera ainsi plus autorisé à démarrer. Une solution est de “fusionner” nos fichiers esl afin de pouvoir profiter de l’ancienne certification ainsi que de la nouvelle. De plus, l’installation peut se faire aussi directement depuis la machine cible si cette dernière est munie d’une distribution Linux. Toutes ces informations ainsi que toutes les informations précédentes données dans ce tutoriel sont détaillées et expliquées dans le lien suivant (en anglais), dont notre article s’inspire grandement :

Sakaki’s EFI Install Guide/Configuring Secure Boot

A Virtual Android

My phone is dead. I'm not exactly sure what happened to it, but for some reason, my beloved Sony Xperia Z5 Compact no longer turns on. Granted, it's not my main work phone, but it's my personal phone and also my audiobook player. The biggest problem is that when I'm exploring new Android apps, the Sony is the device I use for testing. Thankfully, there are other options. more>>

Image Processing on Linux

I've covered several scientific packages in this space that generate nice graphical representations of your data and work, but I've not gone in the other direction much. So in this article, I cover a popular image processing package called ImageJ. more>>

Programmation embarquée sur Raspberry Pi sans sonde JTAG -Partie 1/2

Le standard JTAG, au succès indéniable, est aujourd’hui ancré dans la majorité des processeurs et proposé comme moyen privilégié de programmation embarquée et de debug. Toutefois, l’utilisation d’une sonde JTAG n’est en rien triviale. L’utilisation du débuggeur GNU s’impose alors, car il est possible de l’employer en bare-metal, c’est-à-dire sans aucun système d’exploitation embarqué pour gérer le processeur et sa carte. À titre d’illustration, nous nous intéressons dans cet article à la programmation bare-metal d’une Raspberry Pi à l’aide de GDB uniquement.

En situation de développement embarqué, la Raspberry Pi (RPi) est appelée « système cible » (target), tandis que le poste de travail est appelé « système hôte » (host). L’hôte doit donc programmer le système cible à distance (remote) via un moyen de communication dédié. À noter également que nous sommes dans une situation de développement croisé : la RPi, bare-metal et architecture ARM, ne correspond pas au système hôte, couramment muni d’une architecture Intel avec un système d’exploitation (OS). Il convient donc d’utiliser une chaîne d’outils croisés pour produire et manipuler un programme cible depuis un système hôte.

Pour ce faire, nous déploierons d’abord sur le poste de travail la chaîne d’outils GNU croisés, arm-none-eabi, incluant le compilateur GCC et le débuggeur GDB, puis embarquerons le serveur GDB freemium Alpha directement sur la RPi, et l’utiliserons comme moyen de développement afin de développer et d’embarquer, avec la seule aide de GDB, une série d’exemples de programmes C standards allant du simple Hello World sur la sortie standard, au plus avancé raytracer utilisant le processeur graphique (GPU) pour produire des images sur la sortie HDMI de la RPi. Nous finirons enfin par embarquer le raytracer directement sur la RPi, pour qu’il soit démarré par son bootloader, comme si nous passions en production une fois le développement terminé.

Figure 1 : Vue générale du développement embarqué à l’aide de GDB.

1. Installation

Figure 2 : Matériel complet nécessaire : une RPi, un poste de travail, une carte microSD pour la RPi, un lecteur de carte microSD pour le poste de travail, un câble HDMI pour la RPi, un câble micro-USB pour alimenter la RPi, un convertisseur USB/UART-TTL3.3V, trois câbles jumper femelle pour le branchement convertisseur/RPi, un câble mini-USB pour le branchement convertisseur/poste de travail.

1.1 Poste de travail

Un poste de travail POSIX (GNU/Linux, Cygwin, OS X…) est nécessaire. Il exécutera la compilation croisée ARM pour RPi, ainsi que le client GDB. Les droits de lecture et écriture sont également nécessaires sur l’interface de communication employée et décrite plus bas.

Un dépôt git est mis à disposition : il contient les éléments nécessaires pour la suite (et pour échanger sur https://github.com/farjump/raspberry-pi en cas de problème). Les commandes ci-dessous permettent de le cloner :

$ git clone https://github.com/farjump/raspberry-pi.git glmf-rpi
$ cd glmf-rpi
glmf-rpi/ $ git checkout v1.0.0
glmf-rpi/ $ ls
LICENSE Makefile boot/ run.gdb scripts/ sdk/ src/

Optionnellement, les plus modernes d’entre nous apprécieront certainement la commande make shell qui produit directement le poste de travail attendu dans un container docker basé sur Debian 9, puis y lance un terminal dans lequel peut s’exécuter de manière garantie la suite de l’article.

1.1.1 Chaîne de compilation croisée ARM

ARM distribue la chaîne de compilation croisée pour les principaux systèmes d’exploitation au format 64 bits uniquement [1]. Le script scripts/install-toolchain.sh, fourni dans le dépôt, télécharge et décompresse la version Linux 64 bits de la chaîne :

glmf-rpi/ $ sudo ./scripts/install-toolchain.sh --prefix /opt/glmf-arm-none-eabi
[+] Installing ARM cross-compiler into `/opt/glmf-arm-none-eabi`
[+] The toolchain has been successfully installed
glmf-rpi/ $ PATH=/opt/glmf-arm-none-eabi/bin:$PATH
glmf-rpi/ $ export PATH
glmf-rpi/ $ arm-none-eabi-gcc -v && arm-none-eabi-gdb -v && echo mini test ok
...
mini test ok

Compte tenu du succès de l’architecture ARM, les distributions les plus courantes (Debian, Archlinux, Fedora, etc.) la mettent aussi directement à disposition dans leurs gestionnaires de paquets, toujours en partie nommée avec le triplet arm-none-eabi. Pour OS X et Windows, il convient d’adapter les étapes précédentes à la distribution officielle ARM [1] en la déployant dans votre environnement.

1.2 Raspberry Pi

1.2.1 Carte microSD

La RPi démarre le programme qu’elle trouve sur sa carte microSD suivant les directives contenues dans le fichier de configuration config.txt. Le serveur GDB Alpha doit donc être copié sur la carte microSD pour être démarré à l’allumage de la RPi.

L’étape décrite ici simplifie au maximum la préparation de la carte microSD pour la RPi et son bootloader. Elle suppose une carte microSD vierge compatible avec la RPi. Un script d’aide à son installation est fourni, mais l’étape de formatage en FAT32, attendu par le firmware et le bootloader de la RPi, est laissée explicite afin d’insister sur le caractère irréversible de cette opération destructrice pour la carte microSD. Enfin, le script scripts/install-rpi-boot.sh installe le firmware, le bootloader et Alpha sur la carte microSD :

glmf-rpi/ $ # 1. Insérer la carte microSD dans le lecteur de carte du poste de travail
glmf-rpi/ $ # 2. Trouver son point de montage
glmf-rpi/ $ dmesg -H | tail
[Feb14 13:37] sd 3:0:0:0: [sdc] 30318592 512-byte logical blocks: (15.5 GB/14.5 GiB)
[ +0.026020] sdc:
glmf-rpi/ $ # La carte microSD est ici apparue sur le nœud /dev/sdc
glmf-rpi/ $ # 3. Formater la carte microSD en FAT32
glmf-rpi/ $ # Attention, cette étape supprime entièrement le contenu de la carte microSD
glmf-rpi/ $ sudo mkfs.vfat -F 32 -n RPI -I /dev/sdc
glmf-rpi/ $ # 4. Utiliser le script fourni, installant les fichiers sur la carte formatée
glmf-rpi/ $ ./scripts/install-rpi-boot.sh /dev/sdc
[+] Downloading the Raspberry Pi's firmware version 1.20161215
######################################################################## 100.0%
######################################################################## 100.0%
[+] Temporarily mounting `/dev/sdc` into `/tmp/rpi-sdcard-mountpoint`
[+] Installing the RPi firmware and the Alpha debugger
'boot/bootcode.bin' -> '/tmp/rpi-sdcard-mountpoint/bootcode.bin'
'boot/start.elf' -> '/tmp/rpi-sdcard-mountpoint/start.elf'
'boot/Alpha.bin' -> '/tmp/rpi-sdcard-mountpoint/Alpha.bin'
'boot/config.txt' -> '/tmp/rpi-sdcard-mountpoint/config.txt'
[+] Checking the integrity
/tmp/rpi-sdcard-mountpoint/bootcode.bin: OK
/tmp/rpi-sdcard-mountpoint/start.elf: OK
/tmp/rpi-sdcard-mountpoint/Alpha.bin: OK
[+] Un-mounting `/tmp/rpi-sdcard-mountpoint`
[+] Your SD card is ready!
[+] You can now insert it into the RPi and use Alpha through the RPI's Mini-UART

La carte microSD est alors prête à l’emploi et la RPi y trouvera tout le nécessaire pour démarrer le serveur GDB. À son prochain démarrage, le firmware, ayant pour tâche d’initialiser le processeur et sa carte, lira les directives contenues dans le fichier config.txt indiquant que le programme Alpha.bin doit être copié à l’adresse d’exécution 0x7F0_8000, point d’entrée du serveur.

1.2.2 Interface de communication GDB

Une fois le serveur GDB en cours d’exécution, celui-ci attend la connexion d’un client GDB et ses commandes, en écoutant une interface de communication. Le serveur GDB Alpha utilise l’interface série Mini-UART, car commune à toutes les versions de la RPi. Le port de cette interface n’étant pas disponible tel quel sur un poste de travail standard, il est nécessaire d’interposer un convertisseur entre les deux.

Du coté poste de travail, les ports séries sont les ports USB (et RS232 pour les plus anciens). Du côté RPi, l’interface Mini-UART, présente sur le connecteur GPIO (figure 3), se décompose en trois broches TTL 3.3 Volts. Il est donc nécessaire d’utiliser un convertisseur UART TTL 3.3V vers USB. Attention à bien utiliser un modèle 3.3V.

Figure 3 : Les connecteurs TTL 3.3V de l’interface Mini-UART sont toujours les mêmes pour toutes les RPi.

Figure 4 : Schéma de câblage entre la RPi 3 et un convertisseur : connexion de la masse et croisement entre les fils d’émission et réception.

Figure 5 : Exemple de câblage d’une RPi 3 avec un convertisseur série UART TTL-3.3V vers USB.

 

Figure 6 : Exemple de câblage d’une RPi 1 A+ avec un convertisseur série UART TTL-3.3V vers USB.


Une fois relié au poste de travail par un câble USB, le convertisseur est géré par l’OS et son driver de périphériques série, dont les points de montage possibles sont /dev/ttyUSBx ou bien /dev/ttyACMx pour Linux, COMx pour Windows, ou encore /dev/cu.usbserial-xxxxxx pour OS X. Pour la suite de cet article, /dev/ttyUSB0 désignera notre port série de communication GDB.

Le coût total du montage avoisine les 9€ et nécessite l’achat d’un convertisseur [2], de trois câbles jumper femelle [3] ainsi que d’un câble USB [4]. Des montages complets, couramment nommés « câbles TTL », plus compacts et incluant les câbles, sont aussi disponibles, mais à des prix beaucoup plus aléatoires [5].

2. Éditer, compiler & débugger

Nous sommes désormais prêts à utiliser GDB comme moyen de développement embarqué. Mais contrairement à une utilisation classique de GDB, dite « native », où le programme à exécuter et débugger est au préalable préparé par le système d’exploitation, il est nécessaire ici d’effectuer explicitement ces mêmes étapes préliminaires : téléchargement du programme sur la cible une fois la connexion distante établie. Le mode client/serveur de GDB offre en effet au serveur la possibilité de supporter la commande load qui prend alors directement en charge le format d’exécutable ELF et en télécharge les sections de code et de données sur la cible, puis place finalement le pointeur sur instruction sur son point d’entrée. Les sections de debug sont quant à elles lues et chargées par le client GDB et lui permettent d’apporter les fonctionnalités de debug de code et de données depuis le code source (source-level debugging).

Une session de debug d’un logiciel embarqué commence donc souvent par :

$ arm-none-eabi-gdb <fichier ELF avec informations de debug>
(gdb) # 1. Configuration de l’interface de communication et connexion à la cible
(gdb) target remote <interface>
(gdb) # 2. Téléchargement du programme sur la cible
(gdb) load
(gdb) # Prêt!

Il est ensuite possible de profiter des fonctionnalités élémentaires de debug de code et de données. Les fonctionnalités plus avancées dépendent quant à elles du serveur. Par exemple, la version freemium d’Alpha, le serveur GDB utilisé, n’implémente pas les tracepoints [6], mais implémente l’extension File I/O [7] (dont l’utilité sera révélée par la suite). GDB signalera au final son incapacité à exécuter une commande si le serveur n’en est pas capable.

GDB est une solution d’instrumentation dynamique, par opposition à l’instrumentation statique qui se fait à la compilation du code source en le modifiant. GDB n’altère donc pas le programme et utilise les ressources de debug du processeur afin d’arrêter et d’observer l’exécution du programme.

De plus, Alpha met en place un environnement d’exécution permettant un développement bare-metal plus simple et dont le programme embarqué via GDB peut alors profiter. Alpha initialise en effet le processeur plus vastement que le bootloader de la RPi en activant, par exemple, l’unité flottante ou encore en programmant un espace mémoire (figure 7). Ceci doit donc être pris en considération lorsque GDB n’est plus utilisé pour charger le programme, qui doit alors lui-même effectuer les initialisations dont il a besoin. Il en est de même pour toutes les fonctionnalités nécessaires et en dehors du périmètre de cet environnement d’exécution.

Figure 7 : Mapping mémoire initialisé par Alpha dont le programme hérite.


Enfin, il ne sera pas nécessaire de redémarrer manuellement la RPi entre chaque session de debug puisqu’Alpha effectue un reset du processeur lorsque GDB lui transmet la commande kill. Cette commande est aussi induite par toutes celles impliquant, en debug natif, l’arrêt du processus, et notamment celle de connexion distante target remote <interface>, ainsi que la commande quit lorsque GDB est quitté. Relancer l’un des scripts GDB qui suit ou bien quitter GDB (correctement) implique donc un reset de la RPi, permettant ainsi de repartir depuis l’état zéro du processeur et d’éviter les effets de bord indésirables d’une session à une autre. À noter que le reset est observable grâce aux LED situées sur la RPi.

Toutes les sessions de debug présentées par la suite utilisent exclusivement l’interface ligne de commandes de GDB (CLI). Il est toutefois conseillé de profiter de son interface texte, TUI [8], et ce à tout moment, grâce à la commande tui enable (figure 8).

Figure 8 : Interface utilisateur texte de GDB.

2.1 Hello World

2.1.1 Compilation

Soit le programme :

#include <stdio.h>
void main(void)
{
   printf("Hello RPi!\n");
}

Malgré les apparences, ce programme n’est en rien anodin. Il fait en effet appel à des fonctions de la bibliothèque C standard alors qu’elles nécessitent normalement un système d’exploitation, absent dans le cas présent. Il y a d’une part l’initialisation de l’environnement d’exécution (runtime) C préalable à l’appel de la fonction main() (initialisation de la pile et des données), et d’autre part l’écriture sur la sortie standard par printf().

Pour ce faire, les fonctions et appels systèmes nécessaires sont implémentés dans la mesure du possible dans le contexte bare-metal. GDB bénéficie d’une fonctionnalité peu connue que le serveur GDB peut optionnellement implémenter pour transmettre et déléguer au client les appels système, alors exécutés sur le poste de travail sur lequel le client GDB s’exécute. Ainsi, printf()utilise l’appel système write() qui est communiqué et délégué au client tel quel, pour écrire donc finalement sur la sortie standard du client GDB, sur le poste de travail.

Figure 9 : Un appel système effectué depuis la bibliothèque C sur la RPi est délégué au client GDB sur le système hôte.


Cette astuce n’est possible qu’avec un nombre restreint d’appels systèmes [9] dont les capacités sont parfois limitées par GDB (ex. : ouvrir un fichier spécial), tandis que d’autres pourront être implémentés très simplement sans aucune aide d’un système d’exploitation ou de GDB (ex. : brk() pour malloc()).

Cette fonctionnalité de GDB s’appelle File I/O [7] et est implémentée par Alpha. Nous l’interfaçons avec la bibliothèque C newlib en remplaçant ses appels systèmes par des appels à Alpha (figure 9). Cette bibliothèque C est la seule, avec la bibliothèque C GNU glibc, à s’intégrer officiellement dans la chaîne de compilation GCC, ce qui en rend l’utilisation aussi aisée qu’en compilation native : compiler un programme est aussi simple et direct que arm-eabi-none-gcc <cppflags> <cflags> <ldflags> -o main.elf main.c <libs>. Le résultat final est la possibilité d’embarquer n’importe quel programme C standard.

Pour compiler le programme :

glmf-rpi/ $ make hello.elf
arm-none-eabi-gcc -specs=sdk/Alpha.specs -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -g3 -ggdb -Wl,-Tsdk/link.ld -Lsdk -Wl,-Map,hello.map -o hello.elf src/hello-world/HelloWorld.c

Les options de compilation gcc présentes dans le Makefile sont précisément adaptées au processeur ARM11 de la première RPi : -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s.

L’option –gN permet d’activer la génération des informations de debug du programme, où N est le niveau d’informations souhaité allant de 0 (désactivation) à 3 (maximum). L’option -ggdb permet quant à elle d’activer les extensions spécifiques à GDB.

Christophe Plé
[CEO de Farjump et Expert en développement logiciel embarqué]

Julio Guerra
[CTO de Farjump]

La seconde partie de cet article sera publiée prochainement sur le blog, restez connectés 😉

Retrouvez cet article (et bien d’autres) dans GNU/Linux Magazine n°203, disponible sur la boutique et sur la plateforme de lecture en ligne Connect !

SENSO : 5th International Conference - Gardanne (13) Le 15 novembre 2017

The fifth edition of this workshop will be dedicated to « Sensors, Energy harvesting, wireless Network and Smart Objects.

The aim of this event is to provide a more integrated vision of the way IoT smart sensor nodes work and communicate, from the way they are wirelessly powered to their final deployment into a network for an actual working environment. That will make an unmissable event for all the different actors to meet each other and foster new exciting opportunities.

Program

Wednesday, November 15

9.15 am : Registration
9.45 am : Workshop opening (ARCSIS and CMP)

  • Session 1 - Sensing Devices - Part 1

10.00 am : TUTORIAL - Yvan Bonnassieux, Ecole Polytechnique - University Paris-Saclay (France) - "Flexible electronic for smart sensor"

11.00 am : Break

11.25 am : KEYNOTE SPEAKER - Dr. Vardan Galstyan, University of Brescia (Italy) - "Porous titania nanomaterials for security and healthcare"-

12.10 am : "Sensor applications of organic ferroelectric capacitances integrated on CMOS" - Lionel Fritsch, Irlynx (France)

12.35 am : Lunch

  • Session 2 - Harvesting and Energy management - Part 1

1.45 pm : KEYNOTE SPEAKER – Nageh Allam, The American University in Cairo, AUC (Egypt) - "Earth-Abundant Nanostructured Materials for Efficient Solar Fuel Production"

2.30 pm : INVITED SPEAKER – Christophe Lethien, IEMN - University of Lille (France) - "On chip micro-batteries and micro-supercapacitors for IoT applications"

3.05 pm : Break

3.30 pm : "System-based characterization and power consumption of microcontrollers for wearable sensors in medical applications" - Bertrand Massot, INL Lyon (France)

3.55 pm : "Wind Energy Harvester Based on Triboelectricity : Large-Scale Energy Nanogenerator" - Aravind Ravichandran, EMSE-CMP (France)

4.20 pm : "Functional Oxides for Low-Power Applications and Energy Harvesting" - Bertrand Vilquin, University of Lyon (France)

4.45 pm : "Soft hybrid generators for embedded applications" - Claire Jean-Mistral, LaMCoS/INSA Lyon (France)

5.10 pm : End of the day

Thursday, November 16

9.00 am : Registration

  • Session 3 - Sensor network

9.30 am : "Security of IoT : a major challenge " Vincent Bonzom, CEA Tech France / Pôle SCS (France)

10.00 am : TUTORIAL - Nadia El Mrabet, EMSE, Systèmes et Architectures Sécurisées (France) - "Security exchange for IOT"

11.00 am : Break

11.25 am : "End-to-end security for LPWANs" – Hervé Roche, Trusted Objects (France)

11.50 am : "Radio Triggered Asynchronous Protocol for ULP Sensor Network Based on a UWB Sub-GHz communication Link" - Rémy Vauché, IM2NP, Aix-Marseille University (France)

12.15 pm : Lunch + Demonstrations + Posters + Exhibitors

  • Session 4 - Applications

2.00 pm : "Pulse mode for power reduction for gas sensor" - Hatem Majeri, STMicroelectronics (Singapore)

2.25 pm : "A wireless contact lens eye tracking system (example of a smart sensors development platform)" - Jean-Louis de Bougrenet de la Tocnaye, IMT-Atlantique Brest(France)

2.50 pm : "Mox sensors for transdermal alcohol measurement : clinical trials and SNO2 sensors studies" - Bruno Lawson, Aix-Marseille University / INSERM (France)

3.15 pm : "Study and development of preventive and curative methods against bedsores : risk detection by pressure sensor network on textile" - Maxime-Jean Chaudon, Feeligreen / Flexible Electronics (France)

3.40 pm : Break

  • Session 1 - Sensing Devices - Part 2

4.05 pm : KEYNOTE SPEAKER - Olivier Le Neel, STMicroelectronics (Singapore) - "From ‘Connected Objects' to ‘Smart Things', The Augmented Path"

4.50 pm : "Low Power IoT Design using FDSOI Technology" - Zhaopeng Wei, Polytech'Lab, University of Nice Sophia Antipolis (France)

5.15 pm : End of the day

8.00 pm : Conference dinner (Aix en Provence)

Friday, November 17

8.45 am : Registration

  • Session 2 - Harvesting and Energy management - Part 2

9.00 am : TUTORIAL - Thierry Djenizian, EMSE-CMP (France) - "Electrochemical energy storage at the micrometer scale"

10.00 am : INVITED SPEAKER - Yair Ein-Eli, Technion-Israel Institute of Technology (Israel) - "Advanced Li-ion Batteries - Going Lighter, Moving Higher"applications"–

10.35 am : Break

11.00 am : "Electronic Circuit design for RF Energy Harvesting using 28nm FD-SOI" - Jean-Marc Duchamp, University of Grenoble Alpes (France)

11.25 am : "Autonomous Micro camera system for understanding the typical level of insect contamination on drag" - Alain Laurent, La Mesure sur Mesure (France)

  • Session 1 - Sensing devices - Part 3

11.50 am : "Long term stability of a new WO3 gas sensor for the PPB level BTEX detection" - Alexandre Favard, IM2NP - CNRS / EcoLogicSense (France)

12.15 pm : "Self-Powered Pressure Sensor Array Based on Piezoelectric ZnO Nanowires" - Kiron Prabha Rajeev, GREMAN Laboratory, University of Tours (France)

12.40 pm : Lunch

2.00 pm : End of the conference

Programme complet et inscription

Lieu :
Centre de microélectronique de Provence
880 route de Mimet
13120 GARDANNE

Contact :
Alain BRITON - 06 30 46 78 99

PSSC Labs' PowerServe HPC Servers and PowerWulf HPC Clusters

In its quest to provide customers the latest and best computing solutions that deliver relentless performance with the absolute lowest TCO, PSSC Labs has supercharged two server solutions with next-generation processing power. more>>

La nouvelle règlementation des produits radio : RED 2014/53/UE. Quelles différences avec la R&TTE – Conséquences sur l'intégration des modules radio Le 16 novembre 2017

La Directive européenne 2014/53/UE relative aux équipements radioélectriques (RED) est entrée en application le 13 juillet 2016, avec une période transitoire qui s'est terminée le 13 juin 2017, date d'abrogation de la directive R&TTe.
La directive RED est donc à ce jour la seule directive en application. Les normes harmonisées ont été publiées, elles permettent à tout fabricant de déclarer, sous sa responsabilité, la conformité de ses produits aux exigences essentielles de la Directive et lui donnent ainsi accès à l'ensemble du marché européen.

La Directive RED couvre désormais tous les équipements qui peuvent transmettre ou recevoir des signaux radio, que cela soit à des fins de communication ou de radiorepérage. Elle possède donc un champ d'application très large, comprenant par exemple les récepteurs GPS, les radios Bluetooth ou encore la NFC (Near Field Communication). L'Internet of Things (IoT) qui a amené à la multiplication des appareils connectés et intelligents est au cœur de cette nouvelle directive.

Intervenants

- Olivier HEYER, Responsable du Site EMITECH de Montpellier
- Fanny LE FLOCH – Responsable Entité Sécurité Electrique EMITECH Montpellier
- David MONTAULON – Responsable Entité CEM et Radio EMITECH Montpellier.

PROGRAMME

- Rappel du domaine d'application et des exigences essentielles de la RED - Olivier HEYER
Produits concernés
Exigences sécurité et santé
Exigence CEM
Exigence radio

- Nouveaux processus de validation - Olivier HEYER
Définitions et responsabilité des acteurs économiques
Processus « d'auto-certification »
Rôle de l'Organisme Notifié
Processus de traçabilité

- Marquages et informations - Olivier HEYER
Ce qu'il faut indiquer sur le produit
Ce qu'il faut mettre dans la notice d'utilisation
Ce qu'il faut mettre dans le dossier technique

- Cas particulier des modules radio et chips intégrés - Olivier HEYER
Quel processus choisir
Quelles normes appliquer
Quels essais réaliser

- Importance de la sécurité électrique dans l'application de la RED - Fanny LE FLOCH
Rappel des principales exigences de sécurité
Les atouts de l'ingénierie avant essai

- Nouveautés normatives liées à la RED - cas de la norme EN 300 220-2 - David MONTAULON
Les principales modifications apparues dans les normes suite l'entrée en vigueur de la RED
Cas particulier de la norme EN 300 220-2 pour les équipements faible portée de 30 à 1000MHz

INFORMATIONS PRATIQUES

Personnes concernées : Responsables de projets, Ingénieurs, Techniciens en charge de la conception, de la fabrication, des achats ou de la qualité… bref, à tous les acteurs qui souhaitent assurer le développement, l'industrialisation et la commercialisation d'un produit intégrant un système de communication radiofréquence.

Lieu : Pôle Formation des Industries Technologiques – ZAC Aftalion - 14 rue François Perroux – BAILLARGUES (34)

Date : jeudi 16 novembre 2017 de 14h00 à 17h00 – Accueil des participants 13h45

Prix : Gratuit - Les frais liés à ce séminaire sont pris en charge par les organisateurs.

Contact :

  • José REBEJAC – 06 79 49 72 23 – rebejac@captronic.fr
  • Mohamed BENFEDDA – 06 72 04 28 68 - m.benfedda@formation-industries-lr.fr

Inscription obligatoire avant le 13/11/17

Datamation's "Leading Big Data Companies" Report

The Big Data market is in a period of remarkable transition. If keeping tabs on this dynamic sector is in your wheelhouse, Datamation has made your homework easier by developing "Leading Big Data Companies", a report that provides "a snapshot of a market sector in transition". more>>

TEC'95 : « RENCONTRES DE L'INNOV'INDUSTRIE » thématique de l'industrie du futur - Argenteuil Le 21 novembre 2017

La DIRECCTE – UT 95, son opérateur TEC'95, le Conseil Economique d'Argenteuil et ses partenaires ont le plaisir de vous convier aux prochaines « RENCONTRES DE L'INNOV'INDUSTRIE » sur la thématique de l'industrie du futur.

Ces rencontres seront animées par des experts du secteur industriel et par des témoignages de chefs d'entreprises du territoire (DASSAULT, COEXFI, DEFACTO…).
Elles présenteront des solutions technologiques innovantes pour répondre à vos besoins.

Programme

16h00 Accueil café

16h20 Mots d'accueil des organisateurs

17h00 Table ronde 1 : « La digitalisation des outils de production au service de la performance industrielle » - Animée par Cécile NOGUEIRA
- Introduction de la thématique par Yann BEGUE, correspondant Alliance Industrie du Futur
- Témoignage de l'entreprise DASSAULT
- Témoignage d'une entreprise sous-traitante de DASSAULT
- Témoignage du cabinet FRS, avec l'appui d'une entreprise accompagnée

18h00 Table ronde 2 : « Le management à l'ère du digital » - Animée par Cécile NOGUEIRA
- Introduction de la thématique par Etienne BAUDOUIN, Directeur du HRM Digital Lab
- Témoignage de Michel STALLIVIERI du cabinet comptable COEXFI
- Témoignage de Mickael CAMILLERI de l'entreprise DEFACTO
- Témoignage du centre de formation AFORP, avec l'appui d'une entreprise accompagnée

19h00 Discours de clôture

19h15 / 20h30 Temps de rencontre

Lieu de l'événement

Espace Jean VILAR - Salle Pierre DUX
9 Boulevard Héloïse
95100 Argenteuil

Contact

Christophe Bricout : 06.43.59.74.97
bricout@captronic.fr

Inscription en ligne en cliquant ici

À nouveau disponible en kiosque : notre hors-série spécial programmation réseau !

Vous l’avez manqué ? Sachez que notre guide dédié à la programmation réseau en Python est actuellement de retour en kiosque ! Vous commencerez tout d’abord par y découvrir les modules essentiels à la programmation réseau, puis serez accompagné dans la création de plusieurs projets (client XMPP, bot IRC, robot Slack). Pour finir, vous apprendrez à créer un script communiquant par SMS et analyserez un serveur de fichiers. Ce guide est toujours disponible sur notre boutique et bien entendu sur notre plateforme de lecture en ligne Connect

Au sommaire

DÉMARREZ… la programmation réseau en Python avec les modules essentiels

p. 08 Utilisez TCP et UDP en Python

p. 22 Développez une application graphique utilisant le réseau

p. 34 Utilisez des API REST en Python

p. 46 Scapy, le couteau suisse Python pour le réseau

CRÉEZ… vos robots et clients en Python pour interagir avec des services web tels que GitHub, Google Drive, etc.

p. 58 Créez un système de migration des rapports de bug de GitHub à votre GitLab

p. 68 Créez un driver FUSE pour Google Drive

p. 76 Créez un bot IRC

p. 86 Créez un robot Slack

p. 98 Créez un client XMPP

PROGRESSEZ… en créant un script communiquant par SMS et en analysant un serveur de fichiers

p. 108 Envoyez des SMS avec un Raspberry Pi et Python

p. 116 Un exemple concret de serveur HTTP servant des fichiers

À nouveau disponible en kiosque : notre hors-série spécial programmation réseau !

Vous l’avez manqué ? Sachez que notre guide dédié à la programmation réseau en Python est actuellement de retour en kiosque ! Vous commencerez tout d’abord par y découvrir les modules essentiels à la programmation réseau, puis serez accompagné dans la création de plusieurs projets (client XMPP, bot IRC, robot Slack). Pour finir, vous apprendrez à créer un script communiquant par SMS et analyserez un serveur de fichiers. Ce guide est toujours disponible sur notre boutique et bien entendu sur notre plateforme de lecture en ligne Connect

Au sommaire

DÉMARREZ… la programmation réseau en Python avec les modules essentiels

p. 08 Utilisez TCP et UDP en Python

p. 22 Développez une application graphique utilisant le réseau

p. 34 Utilisez des API REST en Python

p. 46 Scapy, le couteau suisse Python pour le réseau

CRÉEZ… vos robots et clients en Python pour interagir avec des services web tels que GitHub, Google Drive, etc.

p. 58 Créez un système de migration des rapports de bug de GitHub à votre GitLab

p. 68 Créez un driver FUSE pour Google Drive

p. 76 Créez un bot IRC

p. 86 Créez un robot Slack

p. 98 Créez un client XMPP

PROGRESSEZ… en créant un script communiquant par SMS et en analysant un serveur de fichiers

p. 108 Envoyez des SMS avec un Raspberry Pi et Python

p. 116 Un exemple concret de serveur HTTP servant des fichiers

Creating an Application-Based Terminal Session

One of my first exposures to computers in a work environment was using a Wyse terminal to access a console-based application for data entry. It wasn't until a while later that I learned about terminals in UNIX and how they work. Once I understood it, I wanted to create my own self-contained application that was tied to a telnet or SSH session. more>>

SUSE Software-Defined Storage Leverages Open Source to Break Proprietary Lock-in and Reduce Cost

Gartner analysts noted in a recent Cool Vendor report: more>>

SUSE Unveils Near-Zero Downtime for SAP Apps

Zero downtime is, of course, a mythical holy grail. According to IDC senior market analyst Prabhitha Sheethal Dcruz: more>>

LINBIT's DRBD Top

Many proprietary high-availability (HA) software providers require users to pay extra for system-management capabilities. Bucking this convention and driving down costs is LINBIT, whose DRBD HA software solution, part of the Linux kernel since 2009, powers thousands of digital enterprises. more>>

Working with YouTube and Extracting Audio

In my last few articles, I've been exploring the capabilities of ImageMagick, showing that just because you're working on a command line doesn't mean you're stuck processing only text. more>>

SUSE and SAP: Shared Roots Produce Fruit

SUSE and SAP have been collaborating for 18 years now. SAP is ubiquitous in the enterprise environment, and SUSE is now powering its robust SAP Cloud Platform. more>>

How to Make Windows Better? Make It Chocolatey!

Once again, my friend and fellow Linux Journal club member Kris Occhipinti introduced me to an awesome bit of software. This time, it's an open-source project that brings Linux-like package management to Windows! Don't get me wrong; installing software on Windows isn't difficult, but it's definitely more cumbersome than with Linux. more>>

iStorage diskAshur Storage Drives

With software-free setup and operation, the new iStorage diskAshur group of ultra-secure storage drives works across all operating systems, including Linux, macOS, Android, Chrome, thin and zero clients, MS Windows and embedded systems. more>>

Le guide pour créer et administrer votre réseau !

Avec son nouveau hors-série, Linux Pratique vous accompagne dans la création de votre réseau local. À travers ces 128 pages, vous apprendrez à construire et configurer votre réseau. La première partie vous permettra de vous familiariser avec ses mécanismes. Vous découvrirez ensuite comment mettre en place routage, firewall, serveur DHCP et DNS. Vous installerez des points d’accès Wifi pour permettre la connectivité sans fil, apprendrez à gérer vos utilisateurs et leur mettrez en place un partage de fichiers et d’impression. La dernière partie de ce numéro spécial est consacrée à la sécurité avec la mise en place d’un VPN et d’une connexion SSH. Retrouvez ce guide en kiosque, sur notre boutique et sur notre plateforme de lecture en ligne Connect

Au sommaire

Introduction au réseau : Familiarisez-vous avec les mécanismes du réseau et ses outils
p.12 Comprenons le réseau
p.24 Installons nos systèmes d’exploitation

Architecture : Dressez le plan de votre réseau, mettez en place routage et firewall et installez un serveur DHCP et DNS
p.32 Mettons en place les nœuds du réseau : routage et firewall
p.46 Distribuons les paramètres réseau : DHCP et DNS

Wifi : Installez des points d’accès Wifi pour permettre la connectivité sans fil
p.56 Mettons en place un point d’accès Wifi
p.68 Utilisons plusieurs réseaux Wifi

Services : Gérez les utilisateurs de votre réseau et mettez-leur à disposition un partage de fichiers et d’impression
p.78 Gérons les utilisateurs de notre réseau
p.90 Partageons nos fichiers
p.96 Faisons bonne impression

Sécurité : Créez un VPN et mettez en place une connexion sécurisée avec SSH
p.106 Établissons un réseau privé virtuel
p.116 Connectons-nous dans tous les sens avec SSH

Say Hi to Subutai

I learned about Subutai from Philip Sheldrake of the Digital Life Collective (and much else) and thought it deserved attention here at Linux Journal, so I offered this space for that. Alex Karasulu did most of the writing, but it was a team effort with help from Jon 'maddog' Hall, Philip Sheldrake and Steve Taylor.—Doc Searls more>>

Étendre un serveur MySQL/MariaDB avec des fonctions compilées – Partie 2/2

2.3 Installation

Une fois programmée, puis compilée, la fonction UDF se trouve sous la forme d’un binaire partagé (.so) qu’il est nécessaire de déposer à un endroit du système de fichiers où le serveur MySQL saura le trouver.

Ce chemin peut être différent selon les distributions, et surtout il peut être modifié par l’administrateur, dans la configuration de lancement du service.

La variable MySQL globale @@plugin_dir a pour rôle d’indiquer le chemin où le serveur obtient les binaires des UDF :

mysql> select @@plugin_dir;
+------------------------+
| @@plugin_dir |
+------------------------+
| /usr/lib/mysql/plugin/ |
+------------------------+

C’est à cet emplacement que vous déposerez votre binaire. Le fichier doit appartenir au compte sous lequel tourne le service, lui être accessible en lecture et en exécution. En outre pour des raisons évidentes de sécurité vous devrez veiller à ce qu’il ne soit pas modifiable par d’autres utilisateurs.

$ sudo cp glmf-udf.so /usr/lib/mysql/plugin/
$ cd /usr/lib/mysql/plugin/
$ sudo chown mysql glmf-udf.so
$ sudo chmod 0500 glmf-udf.so

2.4 Déclaration

Une fois que le serveur MySQL est en mesure de trouver et d’exécuter votre binaire, il faut lui indiquer la ou les fonctions UDF qu’il fournit.

mysql> CREATE AGGREGATE FUNCTION xxx RETURNS INTEGER SONAME "glmf-udf.so";

Le mot AGGREGATE n’est à indiquer que s’il s’agit d’une fonction d’agrégat. L’argument fourni après le mot SONAME est le nom du shared object relatif au chemin des plugins du serveur.

3. Pièges courants

3.1 Calculs et arrondis

À la lumière de la démonstration [5] faite dans GNU/Linux Magazine n°194 sur les difficultés liées au calcul à virgule flottante ou avec des très grands ou très petits nombres, la prudence s’impose dans les formules arithmétiques des fonctions UDF. Bien que les types double et long long laissent une bonne latitude concernant la précision ou la taille des nombres, la manipulation de valeurs potentiellement hétérogènes peut causer des inexactitudes difficiles à détecter.

Par exemple :

mysql> select 1e16 + 1 - 1e16;
+-----------------+
| 1e16 + 1 - 1e16 |
+-----------------+
| 0 |
+-----------------+

3.2 Mémoire

Une fois chargée en mémoire lors de la première utilisation d’une fonction UDF, la bibliothèque reste montée. Les fuites de mémoire occasionnées par du code UDF accompagnent toute la durée d’exécution du service MySQL, jusqu’à son redémarrage.

3.3 Encodage des chaînes de caractères

Les arguments textuels sont passés aux UDF sous forme de char *. L’inconvénient direct est que le contenu de ces chaînes varie selon l’encodage (charset) en vigueur lors de l’appel à la fonction UDF. Il n’existe pas de moyen simple d’identifier automatiquement (dès l’appel) l’encodage des paramètres. Des hypothèses doivent être faites (sous forme de convention d’appel à votre fonction, ou par un argument supplémentaire qui contiendrait le charset si c’est important pour votre traitement).

3.4 Mise au point

Il n’est pas rare de devoir effectuer plusieurs essais lors de la création d’une fonction UDF, or la mise au point n’est pas aisée, car le code s’exécute dans le contexte du service MySQL lui-même. Aussi, il est conseillé d’effectuer les tests dans un serveur de développement, voire un conteneur Docker [6] :

$ docker run -d --name mysqlsrv -h mysqlsrv -e MYSQL_ROOT_PASSWORD=glmf mysql:5.7
$ docker exec -it mysqlsrv bash
root@mysqlsrv:/#

3.5 Sécurité

Le code présent dans une bibliothèque UDF peut exécuter tout ce qui est autorisé au compte du service MySQL, et peut être déclenché par un simple utilisateur de la base de données sur simple appel de la fonction. Il est donc important de veiller à ce que les droits du compte du service soient convenablement configurés. En outre, il convient de ne pas faire confiance d’emblée à un binaire UDF, qui pourrait effectuer des actions sensibles ou malveillantes (ou mal codées !) provoquant des dégâts même sous le compte limité du service MySQL (qui possède tout de même tous les fichiers de données de la base…).

Avant de la déployer, il est préférable de toujours compiler le source d’une fonction UDF, à partir d’un dépôt de confiance.

Conclusion

La criticité de l’aspect sécuritaire des UDF oblige généralement les hébergeurs de serveurs de bases de données dans le nuage à les proscrire, à juste titre.

À l’heure où les directions informatiques tendent à s’orienter vers l’infrastructure locative, de façon à s’affranchir des tâches de maintenance et de supervision des serveurs de bases de données, il est à prévoir que les UDF, qui nécessitent un accès administratif à l’hôte, disparaîtront progressivement des architectures applicatives. Par ailleurs, l’augmentation des puissances de calcul permettent le plus souvent d’envisager une solution programmatique au niveau de la couche de persistance des applications, en lieu et place d’une fonction compilée dans le SGBD, même pour ce qui est des agrégats.

Néanmoins, la connaissance de ces possibilités d’extension de MySQL/MariaDB et leurs points faibles, demeure recommandée pour savoir sécuriser un système ou faire les bons choix de conception d’un applicatif.

Notez qu’il existe un projet d’inventaire et de contributions open source de fonctions UDF utiles et populaires [7]. Vos besoins particuliers sont peut-être déjà couverts, et vous pourrez souhaiter contribuer à cette plateforme avec vos prochaines créations.

Références

[1] http://www.mathematik.uni-ulm.de/help/mysql-3.22.25/manual.html
[2] http://dev.mysql.com/doc/refman/5.7/en/adding-native-function.html
[3] http://dev.mysql.com/doc/refman/5.7/en/adding-udf.html
[4] https://github.com/mysql/mysql-server/blob/5.7/sql/udf_example.cc
[5] LANGRONET F., « Peut-on vraiment calculer avec un ordinateur », GNU/Linux Magazine n°194, pp 22-31
[6] https://hub.docker.com/_/mysql/
[7] http://www.mysqludf.org/

Retrouvez cet article (et bien d’autres) dans GNU/Linux Magazine n°203, disponible sur la boutique et sur la plateforme de lecture en ligne Connect !

IOTUESDAY : CYBERSECURITE - Rennes (35) Le 24 octobre 2017

L'arrivée massive des objets connectés, l'interdépendance des systèmes, des données et des process améliorent notre quotidien mais ouvrent aussi de nombreuses failles de sécurité.Face à ces réelles menaces, les entreprises doivent prendre conscience des enjeux, des risques et de la nécessité de mettre en place les actions adéquates. Cet iot tuesday vous présentera les concepts importants de cette problématique.

Programme

19h00 - Démonstration technique d'attaque sur les objets connectés
Acceis

19h20 - Méthodes et bonnes pratiques organisationnelles pour un développement sécurisé d'un objet connecté
Acceis

Informations pratiques

Inscription en ligne

Lieu
LA FRENCH TECH RENNES SAINT-MALO
Neway Mabilais
2 Rue de la Mabilais
35000 Rennes

Contact :
Yohann DESILES, Ingénieur CAP'TRONIC - 06 09 86 49 44

Étendre un serveur MySQL/MariaDB avec des fonctions compilées – Partie 1/2

MySQL et MariaDB offrent la possibilité de développer des fonctions compilées, à utiliser comme toute autre fonction native dans vos requêtes SQL. Étudions la puissance et les dangers d’ajouter du code au serveur.

Les User Defined Functions sont un moyen d’étendre les possibilités du serveur MySQL en ajoutant des fonctions écrites en C ou C++, qui peuvent être utilisées comme d’autres fonctions SQL dans des requêtes (c’estàdire, qui se comportent comme les fonctions natives telles que REPLACE, SUBSTR ou SUM).

Elles sont entièrement compatibles entre MySQL et MariaDB, y compris au niveau binaire, car ces deux systèmes s’appuient sur la même interface pour l’écriture des UDF. Par souci de clarté, dans la suite de cet article les informations sont mentionnées pour MySQL, mais elles sont équivalentes pour MariaDB.

1. Qu’est-ce qu’une User Defined Function ?

1.1 Les fonctions en SQL

Tout d’abord, une fonction stockée est, à l’instar d’une procédure stockée, une fonction écrite comme une série d’instructions SQL, et enregistrée au niveau de la base de données. Elle porte un nom, et accepte un nombre arbitraire d’arguments. En plus des arguments d’appel, la fonction peut travailler avec d’autres données de la base, telles que le résultat d’une requête SELECT.

Le code SQL d’une fonction stockée est lisible en clair, et modifiable (par les personnes autorisées). Un export de la base peut contenir le code des fonctions et procédures stockées, si l’option –routines est précisée à l’outil de dump :

$ mysqldump --routines [autres options] nom_de_la_base

1.2 Cas des fonctions UDF

Une fonction User-Defined, quant à elle, est du code compilé sous la forme d’un fichier binaire partagé (shared object), et installé puis déclaré au niveau du serveur de bases de données. La fonction peut accepter par valeur un nombre prédéfini d’arguments, mais elle ne peut pas travailler sur d’autres données de la base.

Le code, puisque compilé, n’est pas lisible. Il n’est pas non plus exporté dans un dump de la base.

Une fonction UDF est généralement considérée plus véloce qu’une fonction SQL. Mais surtout, il n’est pas toujours possible, ou optimal, d’obtenir un résultat souhaité à l’aide des seules fonctions SQL. Par exemple, pour transformer une chaîne de caractères en mettant une majuscule à chaque mot, il peut s’avérer très complexe, voire impossible, de n’utiliser que les fonctions natives de MySQL (telles que LOCATE et SUBSTR). Et, même avec une boucle WHILE écrite en SQL, la complexité d’exécution et l’efficacité de l’algorithme sont considérablement moins contrôlables qu’avec du code C. La fonction compilée peut également utiliser des ressources (système, fichiers, structures de données, etc.) auxquelles les fonctions SQL natives n’ont pas accès (voir plus loin la section Sécurité).

En outre, UDF est actuellement (v5.7) la seule voie pour créer une fonction d’agrégat (à utiliser en conjonction avec la clause GROUP BY), fournissant un résultat à partir de plusieurs enregistrements (ayant un comportement similaire à SUM, AVG, etc.). Par exemple, MySQL ne fournit pas nativement de fonction pour calculer la valeur médiane d’une population de nombres : certains projets pourraient avoir besoin de cet outil.

Dans leur forme actuelle, les UDF ont été introduites dans MySQL à la version 3.23 (janvier 2001). Auparavant, qui voulait enrichir les possibilités de MySQL avec des fonctions écrites en langage C, devait recompiler [1] le serveur avec son code personnalisé (cette option demeure possible pour ajouter des fonctions natives [2]).

Les fonctions UDF peuvent servir à des fins très diverses, de l’implémentation de formules mathématiques ou statistiques, jusqu’à l’émission de requêtes HTTP, en passant par l’interprétation de balises XML ou l’extraction d’éléments HTML par exemple.

2. Mise en œuvre

Supposons que l’on souhaite réaliser une bibliothèque qui contiendra une fonction UDF que nous nommerons XXX (les noms de fonctions SQL sont indifférents à la casse). Le code source de chaque UDF se compose d’un ensemble de fonctions C que le moteur exécute selon un certain cycle. Notez qu’il est possible d’écrire plusieurs fonctions UDF dans un même shared object.

Il faut écrire le code en respectant certaines règles, puis le compiler, installer le binaire sur l’hôte qui exécute le service de bases de données, et déclarer la bibliothèque au serveur MySQL.

2.1 Prérequis

Pour pouvoir compiler le code d’une fonction UDF, le système doit disposer des paquets suivants (si basé sur Debian) :

$ sudo apt-get install gcc libmysqlclient-dev

2.2 Écriture d’une UDF

Une fonction UDF peut retourner un des trois types SQL suivants : INTEGER, REAL, STRING, qui correspondent respectivement aux types C : long long, double et char *. Les arguments qu’elle accepte sont de ces mêmes types, et par valeur (c’est-à-dire qu’une fonction ne peut pas modifier la valeur d’un champ de la base ou d’une variable MySQL).

Le code source d’une fonction UDF doit respecter certaines conventions et signatures [3]. Un exemple complet et instructif est fourni [4] avec le code source du serveur MySQL.

2.2.1 Fonctions simples

Une UDF simple (sans agrégat) se compose de trois fonctions C : xxx_init(), xxx(), et xxx_deinit(). Elles sont invoquées selon le cycle suivant :

Dans toute la suite, les xxx sont à comprendre comme un préfixe aux différentes fonctions C. Vous devrez le remplacer par le vrai nom de votre fonction UDF, tel qu’utilisé dans vos requêtes SQL.

  1. Le moteur identifie qu’une requête utilise la fonction XXX( ), et charge la bibliothèque correspondante si ce n’est pas déjà fait.
  2. Le moteur invoque le point d’entrée d’initialisation de la fonction : par convention, il s’agit obligatoirement du symbole xxx_init(), où le nom de la fonction UDF est en minuscules (ici xxx). La présence de cette fonction dans votre bibliothèque est optionnelle ; le moteur ne l’invoque que si elle s’y trouve, sans lever d’erreur dans le cas contraire. L’appel à _init a lieu une fois avant l’exécution de la requête (mais de nouveau pour chaque requête utilisant votre fonction, et autant de fois que la fonction y apparaît). Elle vous offre la possibilité d’allouer les ressources nécessaires (mémoire, etc.), de mettre à zéro vos compteurs, et autres opérations préliminaires. C’est également dans cette fonction que vous pouvez indiquer si la valeur NULL est une valeur de retour possible pour votre UDF.
  3. Une fois pour chaque ligne, le serveur appelle votre fonction xxx(), qui est la fonction principale (et qui porte obligatoirement le même nom que la fonction SQL). C’est elle qui retourne le résultat, ou qui indique si une erreur s’est produite (par exemple, en cas de division par zéro).
  4. Une fois la requête terminée, et toutes les lignes traitées, votre fonction xxx_deinit() (optionnelle) est appelée. C’est ici que vous libérez toutes les ressources réservées par _init ou dans votre fonction principale.

Si le code est en C++, penser à exporter les points d’entrée avec la directive extern “C” afin que les noms soient conservés.

2.2.2 Agrégats

Pour une fonction d’agrégat, deux points d’entrée supplémentaires doivent être fournis : xxx_add() et xxx_clear(). Le cycle devient le suivant :

  1. Identification et chargement.
  2. Appel à xxx_init().
  3. Le moteur groupe et trie les lignes selon les prescriptions de la clause GROUP BY.
  4. Au début de chaque nouveau groupe de lignes, appel de la fonction xxx_clear(). Vous y réinitialisez tous les compteurs et ressources communs à un même groupe de lignes.
  5. Pour chaque ligne du groupe, invocation de xxx_add(). Dans cette fonction, vous incrémentez vos compteurs et autres valeurs cumulatives dans vos propres structures de données (voir plus loin).
  6. À la fin de chaque groupe (une fois que _add a été appelé sur toutes les lignes du groupe), le moteur exécute votre fonction principale xxx() sur l’ensemble des données cumulées au cours de chaque appel _add dans votre structure personnelle.
  7. Reprise de l’étape 3, tant qu’il reste des groupes à traiter.
  8. Appel final à xxx_deinit().

Le nom _add() pourrait semer la confusion, mais il s’agit bien sûr d’ajouter une valeur à son groupe, afin d’y appliquer le calcul de votre choix. Il ne s’agit pas d’effectuer obligatoirement une simple addition.

2.2.3 Arguments et structure de travail

Chacune de ces fonctions reçoit en paramètre un pointeur vers une structure C UDF_INIT, toujours la même entre tous les appels au sein d’un même cycle.

Par exemple :

void xxx_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);

Un des membres de cette struct est char *ptr, réservé aux besoins du développeur : c’est par lui que vous pouvez maintenir vos compteurs et autres variables partagées via votre propre structure de données (particulièrement utile pour le cas des fonctions d’agrégat), en ayant pris soin d’allouer la mémoire nécessaire dans _init, et de la libérer dans _deinit.

Les arguments SQL passés à la fonction (les vraies valeurs, pour chaque ligne) se récupèrent grâce à la structure UDF_ARGS. Cette struct contient (entre autres) :

  • le membre unsigned int arg_count qui indique le nombre d’arguments ;
  • le membre enum Item_result *arg_type qui est un tableau indiquant le type SQL de chaque argument ;
  • le membre char **args qui fournit un tableau des valeurs effectives des arguments.

L’argument char *error vous permet d’indiquer (en lui donnant la valeur 1) si les paramètres d’appel à votre fonction provoquent une erreur. Dans ce cas, la valeur de retour de votre UDF pour cette ligne sera NULL.

2.2.4 Compilation

Une fois votre code rédigé (par exemple, dans un fichier glmf-udf.c), la compilation se fait par la commande :

$ gcc -fPIC -shared -I/usr/include/mysql -o glmf-udf.so glmf-udf.c

Ceci produit le fichier glmf-udf.so. L’argument -I (i majuscule) précise le chemin des en-têtes MySQL, qui peut se trouver à un autre emplacement sur votre distribution. C’est le rôle du paquet libmysqlclient-dev installé en prérequis.

Tout votre code doit être thread-safe : plusieurs requêtes peuvent s’exécuter en même temps, et une même requête peut faire appel plusieurs fois à votre fonction en différents endroits. Il faut donc notamment proscrire les variables globales et statiques.

Gabriel Zerbib

La seconde partie de cet article sera publiée prochainement sur le blog, restez connectés 😉

Retrouvez cet article (et bien d’autres) dans GNU/Linux Magazine n°203, disponible sur la boutique et sur la plateforme de lecture en ligne Connect !

La lutte contre la contrefaçon : un enjeu stratégique pour les entreprises - Toulouse (31) Le 25 octobre 2017

La contrefaçon porte atteinte à la compétitivité des entreprises et constitue un frein à leur développement et à l'innovation. Toutes les entreprises de toutes les filières économiques sont concernées, quels que soient leur taille et leur degré de développement. Du fait de leur extrême complexité, les chaînes d'approvisionnement internationales sont devenues sensibles à l'infiltration de contrefaçons. Par ailleurs, dans le contexte de transition numérique, l'explosion de la cybercontrefaçon peut fragiliser la confiance des entrepreneurs et des consommateurs dans le commerce électronique.

En partenariat avec la CCI de Toulouse, la Direccte Occitanie, la DGE, la Douane, l'INPI, la Mécanic Vallée et Captronic.

Lors de cette conférence, les solutions offertes par l'Etat en matière de propriété industrielle et de lutte contre la contrefaçon seront présentées.

Avec les interventions de :

- Mme Angélique MONNERAYE, Chargée de mission Lutte contre la contrefaçon, DGE (Direction Générale des Entreprises),

- Mme Elsa OELHOFFEN, Chargée d'affaires PI à l'INPI OCCITANIE PYRENEES - MEDITERRANEE

- M. Denis HELLERINGER, Chef du Pôle Action Economique à la DGDDI (Direction Générale de la Douane et des Droits Indirects),

- M. Jérôme PHILIBERT, Chef du Pôle Orientation des Contrôles à la DGDDI (Direction Générale de la Douane et des Droits Indirects).

Retrouvez le programme complet du SIANE : http://www.salonsiane.com/

Date : jeudi 25 octobre 2017 de 17h00 à 18h00

Lieu : Salle de conférence - SIANE

Frais : gratuit mais il faut prendre un badge visiteur obligatoire au SIANE pour participer : http://www.salonsiane.com/

Les objets connectés et la cybersécurité - Toulouse (31) Le 24 octobre 2017

La CCI de Toulouse vous invite à la prochaine Rencontre de l'Industrie, organisée en partenariat avec MADEELI, la DIRECCTE, le Salon SIANE et CAP'TRONIC pendant le salon
SIANE, Parc des Expositions, Rond-Point Michel Bénech, 31400 TOULOUSE

Les filières numériques 4.0 (Smart Cities, Smart Factories, etc) doivent prendre en compte le « risque Cyber » dès la mise en place des objets numériques implantés dans leur environnement et le considérer comme en enjeu majeur pour assurer la sécurité des filières de demain. Il s'agit là de conserver la confiance numérique dans cette transformation de notre environnement que l'industrie 4.0 va devoir prendre en compte, sachant que les objets connectés sont étudiés pour être présents dans cet environnement durant plus de 15 ans, pour faire face aux cybermenaces de masse, de plus en plus complexes, que nous montre l'actualité chaque jour (Petya, NotPetya, wannacry, etc) .

En élargissant notre horizon des filières numériques 4.0 à l'écosystème de la Smart City, il apparaît indispensable d'étudier le comportement de ces objets représentant l'extension d'Internet à des choses et à des lieux du monde physique pour faire face aux usages et à la confiance citoyenne que nous devrons avoir dans ses matériels numériques. L'un des axes de recherche du projet neOCampus de l'Université Paul Sabatier de Toulouse (représentant l'équivalent d'une ville : 36 000 étudiants et personnels sur près de 250 ha) préfigure l'avenir de ces nouveaux usages et du besoin de confiance et de protection qu'il est nécessaire d'avoir sur les données numériques et sur les objets eux-mêmes.

Enfin, il est également important de se poser la question de la nécessité de transporter toutes les données dans le cyberespace et de l'intérêt de faire transiter l'ensemble des données (industrielles et territoriales) autour de la planète au lieu de recourir à un nouveau mode de transmission des données numériques au travers de nœud d'échanges Internet régionaux comme TOUIX (Toulouse Internet Exchange) point d'échange Internet dont l'infrastructure physique est situé en Midi-Pyrénées.

Intervenants

- Fabrice CRASNIER, Expert en cybercriminalité, ancien commandant de la Division analyse criminelle et investigations spécialisées de la section d'appui judiciaire de Toulouse et pilote du relais Cyberdéfense de la réserve citoyenne de la région Midi-Pyrénées, Doctorant en informatique sur la dynamique complexe des systèmes ambiants auto-adaptatifs dans le projet néOCampus, au laboratoire IRIT

- Marie-Pierre GLEIZES, Professeure responsable de l'équipe SMAC au laboratoire IRIT (Institut de Recherche en Informatique de Toulouse), et Chargée de mission néOCampus à l'Université Toulouse III Paul Sabatier

- Claude COMBES, président de l'association TOUIX, présentera le projet TouSIX, nœud d'échanges Internet régionaux
- Questions / réponses

Inscription gratuite ici

Retrouvez le programme complet du SIANE : http://www.salonsiane.com/

Les autres conférences de la CCI au SIANE

La Réalité Augmentée dans l'industrie - Toulouse (31) Le 24 octobre 2017

Cap'tronic sera associé à l'association GIPI (Groupement d'Industriels Pour l'Innovation) pour proposer une conférence sur les contraintes physiques et cognitives à prendre en compte pour intégrer la réalité augmentée dans un procédé industriel.

Il vous sera présenté un état de l'art sur la Réalité Augmentée par Antoine MORICE (ISM (Institut des Sciences du Mouvement) Université. Aix-Marseille puis des retours d'expériences de PME locales.

Objectifs :
Pendant le salon SIANE, il s'agit d'apporter un éclairage sur le sujet et rencontrer d'autres entrepreneurs du secteur et les acteurs de l'association GIPI autour d'un moment de grande convivialité.
Cette manifestation se terminera par un cocktail où les échanges « réalité augmentée » se poursuivront.

Personnes concernées : Chef d'entreprises, Responsables de projets, Ingénieurs, Techniciens en charge de la conception et du développement des systèmes embarqués.

PROGRAMME

• Mot d'accueil du Gipi et Captronic

• Etat de l'art sur la technologie « Réalité Augmentée » et ses contraintes cognitives pour des applications industrielles par Antoine MORICE, ISM (Institut des Sciences du Mouvement) Université. Aix-Marseille

• Témoignages d'entreprises
- ASYSTOM balise de supervision pour la maintenance industrielle, Pierre NACCACHE
- INGENUITY IO produits interactifs industriels Stéphane VALES

• Questions – réponses

L'ensemble des planches de présentations sera remis aux participants à l'issue de la présentation par mail.

Date : Mercredi 24 octobre 2017 de 16h00 à 17h30

Lieu : Salle de conférence - SIANE

Frais : gratuit mais il faut prendre un badge visiteur obligatoire au SIANE pour participer : http://www.salonsiane.com/

Contact : Sébastien SALAS (06 87 83 32 32) ou salas@captronic.fr