Re: nombre de processus

Page principale

Répondre à ce message
Auteur: Edgar Bonet
Date:  
À: Liste Guilde
Sujet: Re: nombre de processus
Le dimanche 11 janvier, Benoit T a écrit :
> je peux me tromper, mais il me semble bien que pam n'est utilisé qu'au
> login. y mettre une limite en nombre de processus empêchera un login si
> la limite est atteinte, mais pas un utilisateur déjà en place d'en
> créer.


et Miguel Moquillon a répondu :
> Non. PAM est utilise tout au long de l'utilisation de GNU/Linux.


Non, Benoît a raison, pam n'est utilisé qu'au login, mais ça ne veut pas
dire que la limite en question ne sera contrôlée qu'au login. Le travail
de pam_limits.so ne consiste pas à contrôler des éventuels dépassements
de limites, il consiste à fixer ces limites au niveau du noyau en
utilisant setrlimit(). C'est ensuite le noyau qui contrôle. En effet, le
noyau associe à chaque processus un ensemble de limites qui sont
héritées par fork(). pam_limits.so va modifier ces limites pour le
processus de login. Celles-ci seront ensuite héritées par tous les
processus créés à partir de celui-ci ou de ses descendants.

Pour voir comment la limite du nombre de processus est implémentée,
voici quelques extraits (avec des coupes et des simplifications) de la
doc et des sources du noyau, à commencer par man getrlimit :

    getrlimit, getrusage, setrlimit - get/set resource limits and usage


    int setrlimit(int resource, const struct rlimit *rlim);


    resource must be one of:


    RLIMIT_NPROC
           The maximum number of processes that can be created for the
           real user ID of the calling process.  Upon encountering  this
           limit, fork() fails with the error EAGAIN.


Dans include/linux/sched.h on voit que la limite quand au nombre de
processus qu'un utilisateur peut avoir (comme les autres limites) n'est
pas associée à l'utilisateur, mais à chaque processus. En revanche, un
décompte du nombre de processus est bien associé à chaque utilisateur.
Ça peut paraître surprenant, mais un utilisateur peut bien avoir
plusieurs processus avec des limites du nombre de processus différentes
[1]. Extrait :

    /*
     * Some day this will be a full-fledged user tracking system..
     */
    struct user_struct {
            atomic_t __count;   /* reference count */
            atomic_t processes; /* How many processes does this user have? */
            atomic_t files;     /* How many open files does this user have? */
            uid_t uid;
    };


    struct task_struct {
        [...]
        struct user_struct *user;
        struct rlimit rlim[RLIM_NLIMITS]; /* limits */
        [...]
    };


Les constantes étant définies dans include/asm-i386/resource.h :

    [...]
    #define RLIMIT_NPROC    6               /* max number of processes */
    [...]
    #define RLIM_NLIMITS    11


L'appel système setrlimit() (dans kernel/sys.c) ne fait que modifier
current->rlim[resource], où *current est la task_struct du processus
courant (j'ai enlevé le contrôle d'erreurs) :

    long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
    {
        struct rlimit new_rlim, *old_rlim;


        copy_from_user(&new_rlim, rlim, sizeof(*rlim));
        old_rlim = current->rlim + resource;
        *old_rlim = new_rlim;
    }


Comme indiqué dans le man, le vrai contrôle est effectué par l'appel
système fork(). Celui-ci va comparer la limite p->rlim[RLIMIT_NPROC] du
processus appelant au nombre de processus de l'utilisateur
(&p->user->processes). Si la limite est atteinte, fork() renvoie -EAGAIN
(Resource temporarily unavailable). Sinon, il incrémente
&p->user->processes avant de continuer :

    int do_fork([...])
    {
        struct task_struct *p;


        p = alloc_task_struct();  /* nouveau processus qui est... */
        *p = *current;            /* ...une copie du processus courant */


        /*
         * Check if we are over our maximum process limit, but be sure to
         * exclude root. This is needed to make it possible for login and
         * friends to set the per-user process limit to something lower
         * than the amount of processes root is running. -- Rik
         */


        if (&p->user->processes >= p->rlim[RLIMIT_NPROC].rlim_cur
                && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
            free_task_struct(p);
            return -EAGAIN;
        }
        (&p->user->__count)++;
        (&p->user->processes)++;


        [...plein d'autres choses...]


        return p->pid;        /* dans le processus appelant */
    }


Bonne nuit,

Edgar.

[1] Si un utilisateur est logué alors que tu abaisses sa limite dans
/etc/security/limits.conf, celui-ci pourra continuer à bénéficier de
l'ancienne limite, mais seulement dans les session ouvertes avant ta
modif.

-- 
Edgar Bonet           Maison : 04 76 21 29 16    Bureau : 04 76 88 10 96
3 rue Jean Prévost    Mobile : 06 77 19 79 39    Fax    : 04 76 88 11 91
38000 Grenoble        guilde@???     www.edgar-bonet.org