J'utilise pdftoppm
pour convertir un PDF fourni par l'utilisateur en une image 300DPI. Cela fonctionne très bien, sauf si l'utilisateur fournit un PDF avec une très grande taille de page. pdftoppm
allouera suffisamment de mémoire pour contenir une image 300 DPI de cette taille en mémoire, ce qui pour une page carrée de 100 pouces est de 100*300 * 100*300 * 4 octets par pixel =3,5 Go. Un utilisateur malveillant pourrait simplement me donner un fichier PDF ridiculement volumineux et causer toutes sortes de problèmes.
Donc, ce que j'aimerais faire, c'est mettre une sorte de limite stricte sur l'utilisation de la mémoire pour un processus enfant que je suis sur le point d'exécuter - faites simplement mourir le processus s'il essaie d'allouer plus de, disons, 500 Mo de mémoire. Est-ce possible ?
Je ne pense pas que ulimit puisse être utilisé pour cela, mais existe-t-il un équivalent à un processus ?
Réponse acceptée :
Il y a quelques problèmes avec ulimit. Voici une lecture utile sur le sujet :Limiter le temps et la consommation de mémoire d'un programme sous Linux, ce qui conduit à l'outil de temporisation, qui vous permet de mettre en cage un processus (et ses fourches) en fonction du temps ou de la consommation de mémoire.
L'outil de temporisation nécessite Perl 5+ et le /proc
système de fichiers monté. Après cela, vous copiez l'outil, par ex. /usr/local/bin
comme ça :
curl https://raw.githubusercontent.com/pshved/timeout/master/timeout |
sudo tee /usr/local/bin/timeout && sudo chmod 755 /usr/local/bin/timeout
Après cela, vous pouvez "mettre en cage" votre processus en consommant de la mémoire comme dans votre question :
timeout -m 500 pdftoppm Sample.pdf
Vous pouvez également utiliser -t <seconds>
et -x <hertz>
pour limiter respectivement le processus par des contraintes de temps ou de CPU.
Le fonctionnement de cet outil consiste à vérifier plusieurs fois par seconde si le processus généré n'a pas dépassé ses limites définies. Cela signifie qu'il y a en fait une petite fenêtre où un processus pourrait potentiellement sursouscription avant l'expiration du délai et tue le processus.
Une approche plus correcte impliquerait donc probablement des cgroups, mais cela est beaucoup plus complexe à mettre en place, même si vous utilisez Docker ou runC, qui, entre autres, offrent une abstraction plus conviviale autour des cgroups.