linux/security/keys/gc.c
<<
>>
Prefs
   1/* Key garbage collector
   2 *
   3 * Copyright (C) 2009-2011 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public Licence
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the Licence, or (at your option) any later version.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/slab.h>
  14#include <linux/security.h>
  15#include <keys/keyring-type.h>
  16#include "internal.h"
  17
  18/*
  19 * Delay between key revocation/expiry in seconds
  20 */
  21unsigned key_gc_delay = 5 * 60;
  22
  23/*
  24 * Reaper for unused keys.
  25 */
  26static void key_garbage_collector(struct work_struct *work);
  27DECLARE_WORK(key_gc_work, key_garbage_collector);
  28
  29/*
  30 * Reaper for links from keyrings to dead keys.
  31 */
  32static void key_gc_timer_func(unsigned long);
  33static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0);
  34
  35static time_t key_gc_next_run = LONG_MAX;
  36static struct key_type *key_gc_dead_keytype;
  37
  38static unsigned long key_gc_flags;
  39#define KEY_GC_KEY_EXPIRED      0       /* A key expired and needs unlinking */
  40#define KEY_GC_REAP_KEYTYPE     1       /* A keytype is being unregistered */
  41#define KEY_GC_REAPING_KEYTYPE  2       /* Cleared when keytype reaped */
  42
  43
  44/*
  45 * Any key whose type gets unregistered will be re-typed to this if it can't be
  46 * immediately unlinked.
  47 */
  48struct key_type key_type_dead = {
  49        .name = "dead",
  50};
  51
  52/*
  53 * Schedule a garbage collection run.
  54 * - time precision isn't particularly important
  55 */
  56void key_schedule_gc(time_t gc_at)
  57{
  58        unsigned long expires;
  59        time_t now = current_kernel_time().tv_sec;
  60
  61        kenter("%ld", gc_at - now);
  62
  63        if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) {
  64                kdebug("IMMEDIATE");
  65                queue_work(system_nrt_wq, &key_gc_work);
  66        } else if (gc_at < key_gc_next_run) {
  67                kdebug("DEFERRED");
  68                key_gc_next_run = gc_at;
  69                expires = jiffies + (gc_at - now) * HZ;
  70                mod_timer(&key_gc_timer, expires);
  71        }
  72}
  73
  74/*
  75 * Schedule a dead links collection run.
  76 */
  77void key_schedule_gc_links(void)
  78{
  79        set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags);
  80        queue_work(system_nrt_wq, &key_gc_work);
  81}
  82
  83/*
  84 * Some key's cleanup time was met after it expired, so we need to get the
  85 * reaper to go through a cycle finding expired keys.
  86 */
  87static void key_gc_timer_func(unsigned long data)
  88{
  89        kenter("");
  90        key_gc_next_run = LONG_MAX;
  91        key_schedule_gc_links();
  92}
  93
  94/*
  95 * wait_on_bit() sleep function for uninterruptible waiting
  96 */
  97static int key_gc_wait_bit(void *flags)
  98{
  99        schedule();
 100        return 0;
 101}
 102
 103/*
 104 * Reap keys of dead type.
 105 *
 106 * We use three flags to make sure we see three complete cycles of the garbage
 107 * collector: the first to mark keys of that type as being dead, the second to
 108 * collect dead links and the third to clean up the dead keys.  We have to be
 109 * careful as there may already be a cycle in progress.
 110 *
 111 * The caller must be holding key_types_sem.
 112 */
 113void key_gc_keytype(struct key_type *ktype)
 114{
 115        kenter("%s", ktype->name);
 116
 117        key_gc_dead_keytype = ktype;
 118        set_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags);
 119        smp_mb();
 120        set_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags);
 121
 122        kdebug("schedule");
 123        queue_work(system_nrt_wq, &key_gc_work);
 124
 125        kdebug("sleep");
 126        wait_on_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE, key_gc_wait_bit,
 127                    TASK_UNINTERRUPTIBLE);
 128
 129        key_gc_dead_keytype = NULL;
 130        kleave("");
 131}
 132
 133/*
 134 * Garbage collect pointers from a keyring.
 135 *
 136 * Not called with any locks held.  The keyring's key struct will not be
 137 * deallocated under us as only our caller may deallocate it.
 138 */
 139static void key_gc_keyring(struct key *keyring, time_t limit)
 140{
 141        struct keyring_list *klist;
 142        int loop;
 143
 144        kenter("%x", key_serial(keyring));
 145
 146        if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
 147                              (1 << KEY_FLAG_REVOKED)))
 148                goto dont_gc;
 149
 150        /* scan the keyring looking for dead keys */
 151        rcu_read_lock();
 152        klist = rcu_dereference(keyring->payload.subscriptions);
 153        if (!klist)
 154                goto unlock_dont_gc;
 155
 156        loop = klist->nkeys;
 157        smp_rmb();
 158        for (loop--; loop >= 0; loop--) {
 159                struct key *key = rcu_dereference(klist->neys;!*;
key_typeislass=de=rcu_dereference" clade=key" class="sref">k>(time_t  60
uns="sref">1now);
  62
)) {
 154                goto );
 151         148                goto :143" id="L143" class="line" namysref">nkeun) {
 130        kleave(&quoRED"1);
(&quoRf">loop;
HZ;
expi1res);
 151        1  72}
  56void ct rcu_dereference(>(time_t_gc_flag1>  73
 130        kleave(&quocomment">1/*

 1*/
 133 a feres="cspanef="+cod, detas="s klist<" name="L133"> 133loop{
/* scan the keyring looking for dekey_gc_fl1ags);
kloina hr.c#L1="L139" class="line" name="24">  _list" class="sref">klime="24">  _listcode=key_gc_keyring" class=fere_hss="sref">key_typefere_hss=     struct klistkey_gc_w1ork);
1  81}
klist  82
 159                struct key klist = kl" n/a>(>(lass="line" name="L159"> 159               (               > =  1*/
  67                kenter("%x",    17
 151   me="s="k/ href="+code=smp_rmb" class="sre f">loop{
);
9" cla_lis_  6k/ href="+code=smp_rmb" class="sreref">LONG1_MAX;
();
 * 136"> "> 1"> r> * Not caltrac   f">kalient">/* scan the keyring looking for deme="L92">1  92}
now ||                > = key_gc_wait_bit(voi 0;   93
 151   spine="L1de=rc+code=wait_on_bit" clas159               > =  r              gos      > =  151   ="L1de=r/ href="+code=smp_rmb" class="srerto get t1/*
               > =  r              gos      > = kqlist--- href="+code=smp_rmb" class="srerction ru1ng
               > =  r              gos      > = key_gc_qlbytss/gc.c-     kale0">  90     f">kale0code=unlock_dont_gc" class="sref">unomment"> 1*/
 151   spineoto                > =  r              gos      > =  151   ="L1de=r/ href="+code=smp_rmb" class="srerme="L17">lags)
1  98{
schedul2();
  "L56">  56vo>  56vWs;
nkeysmeme="L98">1  98{
"+code=rcu_derefetss/gc.c-     }
now || >  56vo>  56vWs;
nka>k/ hre68" 131" id="L131" class="line" nameme="L98">1  98{
schedul2();
  "L56">  56vo>  56vWs;
nk" class="a>        return 0;
schedul2();
  56vo>  56vWs;
nk5 href="2ebit" clas159       2comme20/keys/gc.c#L154" id="L154" class="l2" name="L204"> 104 r  f="+code=smp_rmb" class="nowpan cw awaylass="sr memorysecurity/keys/gc.c#L24" id="L24" class="l>
k9" class="line" namot;e" na2">schedul2K_UNINTERRUPTIBLE  _list" c2>
schedul2K_UNINTERRUPTIBLE);
loop{kur1ity/k18c.c#L149" id="L149" class="line" namot;="security/keys/gc.cd/k = );
 * careful as there2may a21149" cla_lis_  692 *92<" class="lass="comment"> * The ca2ler m21L70" id="L70" cL150" 8c.c#L149" id="L149" class="line" namot;="security/keys/gc.cmaginameme="L98">1  magin+code=> & ((1 <<DEBUG_MAGIC_a>( 112void  159               (loop{kmem_c"L13e f">ty/k18c.c#L149" id="L14_ja * );
2enter21"sref">queue_wuot;1);
(set_b2t21f="+code=key_garbage_collector" class="sref">key_garbage_collector2+code=key2gc_flags" class="sref">k2y_gc_22id="L28" class="line" name="L2

KEY_GC_REAP_KEYT2PE 133
  83/* 13href="seitself,tsystem_n2t_wq<22"security/keys/gc.c#L54" id="L54" class="line" name="L54">  54<224
)ecurity/keys/gcL123_s) clat" class="sref">kurity/keys/gc.c#L12L123" class="line" name="L54">  54<22
key_gc_flag2,22code=key_schedule_gc" class="sref">k2ait_bit,
loop);
 127<2a>                    loop =  r  f="+code=smp_rmb" class="Id.c#nal pers/keyntIpan e="L54" class="line" name="L54">  54<2/keys/gc.2#L129" id="L129" class="2ine" 23ef="+code=KEY_GC_KEY_EXPIRED" class="sreAGAIN>(  54<2/href="+c2;
   class="L54" class="line" name="L54">  54<2//a>(panrtmment"" id="L54" class="line" name="L54">  54<2/a>
);
     54<2/5 href="2 class="comment">/*
     54<2/4
 * Garb2ge co2lect p+code=KEY_GC_REAP_KEYTYPE" claFOUNDfDEAg_PE">(  54<2/
  54<2/it_bit
);
kme=s"security/keys/gcme=s"s            gos      > =  2 deallocated under us as2only 239 = klist 129          58ew) * 1  72}
92curity/ke2s/gc.c#L141" id="L141" c2ass="24ref="security/keys/gc.c#L151"f="+code=loop" class="sref">loop;
("sleep");
loop{kc_pan >    "1);
klist;
 142        int 1  72}
expires;
  59        kenter( 1591  72}
  54<2,  r  ft" class="sref2">1  72}
keyri2g2>1  72}
 2ref">KEY_FLAG_REVOKED 1482/a>  2             goto out w thrwelass=re gocur1thabe docur1inass="lpref="L54" class="line" name="L54">  54<2"line" na2e="L149"> 149
(
loop{kc_pan >    }
lags *<2ference(#L123"+code=rcu_dereand_hrefrefetss/gc.c-       78{
  54<2de=subscr2ptions" class="sref">sub2cript2ons);
((klist)
 154          2     25key_serial(smp_mb();
  54<2d
 152 25>  yard_schee_tloop{kc_pan >    }|=> & ((1 <<class="srefDEAg_1>(n25="L117"> 117        ewlpref=ys/gc.c#L143" id="L143" class="line"kc_pan >loop{kc_pan >    "1);
 158      2 for 25href="security/keys/gc.c#L148" id="2cu_derefe2ence" class="sref">rcu_d2refer26me="L129"> 129        ew) * kenter("");
key_type2/a>is26149" cla_lis_  692ode=klist2 class=ame="L60"1>  60
movnt"> ng/keys/gass="sr54" class="line" name="L54">  54<2class="li2e" name="L148 148   2     26id="L51" class="line" name="""""""""* ne" na tree,a>(  54<2ce=subscr2f">1now);
 """"""""* valid necu1inasse tree - evsn83frity/=key droppedecurity/keys/gc.c#L23" id="L23" class="" id="L142" class="line" namy_gc_f2ag1s<26"security/keys/gc.c#L54" id=""""""""*L54" class="line" name="L54">  54<2class="li2e" namyock_dont_)2
key_gc_wait_bit(voi 0; );
((voi 0; loop{kf=f="secuatf">    "1);
(2leave>
loop;
 12>
();
expi1res)2
k/ href>>
);
 151klist;
  56void ct <2="de=27ns);
{r1ys/gc.c#L35" id="98{r1yswait_bit(voi 0; schedul2()agu>(  54<2  73
2a href="secur1ity/k17c.c2L144"27> =  r     key" class="sref">k>foung_/k17c.c#L137_ef=144" class="lfefoung_/k17c.c#L137_ef="");
kleave(&2uocomment">1/*
(
k9" class="line" namot;e" na2">schedul2K_UNINTERRUPTIBLETASK_UNINTERRUPTIBLE);
ef="+cod2inks<1/a>(void)
k/ href>>
loop{kc_pan >    }|=> & ((1 <<claFOUNDfDEAg_PE">();
 1328.c#L68" id="L68" 131"ss="sref">k/ href>>
 1 clasDEAgc.c#L146" id="L"> 1 clasDEAg>smp_mb();
schedul2e=now" class="sref">now ||t;");
  _listcode=2ey_gc28ss=de=rcu_dereference" clade=">k/ href>>
schedul2per"9" class="line"per"    e=lcurity/keys/gc.c#L99" id="L99" c2efere_hss2     struct k/ hre68" 131"""""""""key" class="sref">k>skipa href="s.c#L119" id="L11kipa href="sode=t;");
);
);
kl" n/a>(>(lass="lin2" nam28/keys/gc.c#L154" id="L154" class="l237;x"2 r  =klist" class="srefkc_pan >loop{kc_pan >    }
 & ((1 <<claSET_TIMER>(  yard_sche159  2     2r>  yard_schee_t r  =klist" class="srefcur9" class="line" namot;e" na2">schedul2expi struct 1  72}
 & ((1 <cur9" class="line" namot;e" na2">schedul2expi struct  & ((1 <>ew) * 2enter2/a>(k/ hrennnnnnn/a>         143
 1*/
1  72}
   me="s2"k/ href">k/ hrennnnnnn/a>        ew) * k"> 1*/
r1ity/k12.c#L70" id="L70" class="2ine" 29ss=de=rcu_dereference" clade=wuot;1);
k/ hrewuot;1);
(  54<2de=wait_o2_bit" clas159       2     2 > =  r     =klist" class="sref">k9" class="line" namot;e" na2">schedul2K_UNINTERRUPTIBLETASK_UNINTERRUPTIBLE);
  54<2d7;x"2name=159            2  > =2 r          ennnnnnn/a>        loop{kc_pan >    }|=> & ((1 <<claFOUNDfDEAg_PE">();
key_gc_qlbytss2gc.c-29L136"ss="line" name="L54">  54<2de=wait_o2_bit" clas159       2     2 > = ( 146        if ( 151   =2L1de=29a href="+code=loop" css="st" class="srefunlikel=144" class="lfeunlikel=ty/k18c.c#L149" id="kc_pan >loop{kc_pan >    }
 & ((1 <<class="srefDEAg_2>(lag3)
 r     =klist" class="sref">k9" class="line" namot;e" na2">schedul2K_UNINTERRUPTIBLE(voi 0;   54<3keysmeme=3L98">1  98{
"+code=r3u_der3fetss/gc.c-     k>foung_="s="security/keys/gc.foung_="s="seode=t;");
k/ hrewuot;1);
        return 0;
(  54<3k5 href="3ebit" clas159       3comme30> =  r     =klist" class="sref">k9" class="line" namot;e" na2">schedul2K_UNINTERRUPTIBLETASK_UNINTERRUPTIBLE);
  54<3" name="L304"> 104 r  1111111111111111key" class="sref">k>d/k1roka href="s.c#L119" id="L1d/k1roka href="sode=t;");
key_gc_qlbytss3 id="30L136"ss="line" name="L54">  54<3>
 117        loop;
keyis_ecntendes/gc.c#L35" id="">keyis_ecntendeswait_bit(voi 0;         eed_re s/gc*   54<3s.  We ha3e to be
k>ecntendes/gc.c#L35" id="ecntendeswaitt;");
 * careful as there3may a31etss/gc.c-   wuot;1);
 * * The ca3ler m31L70" class="sref">k>ecntendes/gc.c#L35" id="ecntendeswaitRf">loop;
 113void  142        int kale0">  90     f">kale0code=unlock_dont_gf="secua href="+code=k"srefef=f="secua hre    "1);
3enter31f="secur1ity/k16c.c#maybe_re s/gc* loop;
,   yard_schee=klist" class="srefme=s"security/keys/gcme=s"s     );
set_b3t31a href="+code=loop" c      int key_gc_wait_bit(voi 0; );
k3y_gc_32.c#L68" id="L68" 131"key" class="sref">k>ecntinue_c" cn/k17c.c#L132" id="montinue_c" cn/k1ave);
);
KEY_GC_REAP_KEYT3PE
  54<3               * >ewlollect=klneces"ary.  Ws="sep exametcur1ollecs untillws=fity/on83">  83/*system_n3t_wq<32"security/keys/gc.c#L54" id=        * whererwe didnlass="l">   anyef="security/keys/gc.c#L23" id="L23" class=324
  54<32
key_gc_flag3,326ng-type.h<>
( 127<3a>                    ew) entre!=&quo ew) * ew) entr       
);
( 146        if (/*
 = key_gc_w1ork);
(voi 0; 
 * Garb3ge co33a href="+code=k"> r  f="+code=smp_rmb" class="Make sureae thrall pendiur1="s="se=pryload d/k1rucurits ar83">  83/* r   * fulfill_gc_fdae thrpeople ar8nlass="lnowplooecur1itirst t"s  >  83/*
 1="+code=k"> r   * dyiur1="ssae thrmeny donlass="ls of al">c.c#L13 upont"s="sec5" i>  83/* 127<3 deallocated under us as3only 33ty/k17c.c#L108" id="L108" cl="+code=k"> r   * toecurity/keys/gc.c#L23" id="L23" class=3t  r   *L54" class="line" name="L54">  54<3thref="+c3/a>, k/ href>>
);
 1k1ys/gc.c#L61" i148" id="L148"3c5 href="3ass="sref">kenter( 159key_gc_w1ork);
(voi 0;  r  ft" class="srefl" class="sre ction ru1s.
keyri3g34>  yard_schee_t/* scan the keyring looking for dekey_gc_fl1agbit(voi 0;  127<3ref">KEY_FLAG_REVOKED 1483/a>  3             g=klist" class="srefunlikel=144" class="lfeunlikel=ty/k18c.c#L149" id="kc_pan >loop{kc_pan >    }
    3_derefetss/gc.csec/a> srefDEAg_1>( 149
(
k/ hre=kli<18c.c#L149" id="kc_pan >loop{kc_pan >    }
 & ((1 <<claFOUNDfDEAg_PE">( *<3ference(main/k1 main/k154" class="line" name="L54">  54<3de=subscr3ptions" class="sref">sub3cript35" class="line" name="L132">                         * ="securl">   ollecsecurity/keys/gc.c#L23" id="L23" class=3yenter" c3ef">klist)
  54<3ne" name=3L154"> 154          3     35a href="+code=k"> r              gos      > =" class="sre ction ru1s.
 153 35>  yard_schee_t kc_pan >loop{kc_pan >    }
~    3_derefetss/gc.csec/a> srefDEAg_1>( & ((1 <<class="srefDEAg_2>(n35> = loop{kc_pan >    }|=> & ((1 <<class="srefDEAg_3>( 127<3me="L158"> 158      3 for 35a href="+code=loop" c}+rkrcu_d3refer36.c#L68" id="L68" 131"11111111KEY_GC_REAP_KEYkc_pan >loop{kc_pan >    }|=> & ((1 <<class="eAGAIN>(key_type3/a>is36etss/gc.c-       60
1now);
( 159               ()3
 r  ft" class="srefsmp_mbf="+code=k"sref"mp_mbwait_equot;1);
 sref      ();
"sleep");
 sref      );
 127<3=kleave" cla [no gc]ss="3ref">369f="secur1ity/k1ys/gc.c#L61" i148" id="L148"3D"1<3span>);
(  54<3class="li3e" namref">expi1res)3
k/ href>>
();
 151loop{kc_pan >    "1);
  56void ct <3="de=37ns);
);

">movnd83" eys/gass=tree,54" class="line" name="L54">  54<3string">&3uocomment">1/*

 1="+code=*L54" class="line" name="L54">  54<3>ef="+cod3inks<1/a>(void)
>
loop;
 1338me="L129"> 129        schedul2e="L143"> 143
);
  _listcode=3ey_gc38ity/keys/gc.c#L150" id="L150fb_ ras>loop{fb_ ras>wait_bit(voi 0; schedul2e="L14anecu>(();
loop{kf=f="secuatf">    "1);
kale0">  90     f">kale0code=unlock_dont_gf="secua href="+code=k"srefef=f="secua hre    "1);
 142        int )add_tai43"> 143
)add_tai4wait_bit(voi 0; schedul2k18s/gc.c_ec5"ref="secur1ity/k18s/gc.c_ec5" i  _mb();
kl" n/a>(>(lass="lin3" nam385"> 142        int loop{kc_pan >    }|=> & ((1 <<class="eAGAIN>(k>maybe_re s/gc* &3kir>  yard_sche159  3     38L136"ss="line" name="L54">  54<3e
3enter3/a>(llass=to54" class="line" name="L54">  54<3eef="+cod3ecuritty/k18s/gc.c#L68" 3d="L638ty/k17c.c#L108" id="L108" cl="+code=*irst t"seexpi eref="se  Ws=donlass="lsleec_foan ca">   iL10din >l= asaws54" class="line" name="L54">  54<3>   me="s3"  54<3>r1ity/k13.c#L70" id="L70" class="3ine" 39eady be a cycle in progress.="+code=*lc/k1">   ass="srs thaw/ach itl">c.csecurity/keys/gc.c#L23" id="L23" class=3 cla_lis_3 6  54<3 lass="li3);
k>foung_="s="security/keys/gc.foung_="s="seode=Rf">loop;
 142        int kale0">  90     f">kale0code=unlock_dont_gf="secua href="+code=k"srefef=f="secua hre    "1);
       3     395"> 142        int schedul2e="L143"> 143
);
1  72}
&3ss="sref">key_gc_qlbytss3gc.c-397 href="+codekey" class="sref">k>maybe_re s/gc*        3     39E_WORK( 151   =3L1de=39a href="+codecto   54<4"L17">lag4)
1  98{
"+code=r4u_der40eady be a cycle in progress.="+code=*L54" class="line" name="L54">  54<4ka>k>d/k1roka href="s.c#L119" id="L1d/k1roka href="sode=Rf">loop;
        return 0;
kale0">  90     f">kale0code=unlock_dont_gf="secua href="+code=k"srefef=f="secua hre    "1);
 142        int schedul2e="L143"> 143
);
       4comme405"> 142        int loop{down_w
wait_bit(voi 0; schedul2e="9" class="line"e="rity"1);
            4comme40to schedul2K_UNINTERRUPTIBLE(voi 0; key_gc_qlbytss4 id="40>  yard_schee=klist" class="srefk ds="sref">TASK_UNINTERRUPTIBLE);
schedul2  54<4>
TASK_UNINTERRUPTIBLE);
schedul2 151   =4" id=40a href="+codeclass="sref">k>memset* schedul2pryloady/keys/gc.c#L12pryload");
(k9" class="line" namot;e" na2">schedul2pryloady/keys/gc.c#L12pryload&quo))e=smp_rmb" class="sre>_gc_flag14s.  We ha4e to be
 129        loop{up_w
wait_bit(voi 0; schedul2e="9" class="line"e="rity"1);
 * careful as there4may a41etss/gc.c-   key" class="sref">k>maybe_re s/gc*  * * The ca4ler m41L70" c/pre c/div>


c/div>


Tss=original LXR softwa4eaby ass=1ys/gc.c#http://sourceeo4ge.net/projects/lxco>LXR  prounitrspanadss="lexp"seogreal versrityby 1ys/gc.c#mailto:lxc@nt"ux.norefxc@nt"ux.nospan.
c/div>

fxc.nt"ux.no kindly hostereby 1ys/gc.c#http://www.redpnam-nt"pro.noreRedpnam Lt"pro ASspanadprovider of Lt"ux  pnsult"se=_fdaop"saurits ="svices =iL13 1995.
c/div>