sobomax / mfc_notifications

Source code for the "MFC notification service" created for FreeBSD developers to get automatic merge reminders
1 stars 6 forks source link

Merge From CURRENT ("MFC") notification service ("MFCns") for the FreeBSD Project.

Introduction

At the some point of FreeBSD development it became apparent that in order to help developers to perform timely features merge from the developent branch (aka FreeBSD-CURRENT) into stable branch (aka FreeBSD-STABLE) some form of automatic system, which will track outstanding merges and notify appropriate developer when the time for a merge has come, is necessary. Otherwise, developers are often stick with two extreme cases: some of them forget to merge changes, even those that are clearly safe to merge, while some performing merge shorly after committing the change into a development branch fearing that if the merge is delayed they will forget to do it at all. Both those cases introduce problems to the Project, because in the former case stable branch experiences feature stagnation, while the latter leads to stability degradation, as the features are often being merged without proper testing in the development branch.

To address the problem the MFCns service was created. It works as follows: when committing a change to a development branch a developer specifies a time period during which the appropriate change has to be tested before being merged into a stable branch. The system notes this request and after this time period is over, it notifies the developer about that fact. It is important to emphasise that the final decision as to whether to merge change in question or not is up to the developer, because at that time he might have received an information that makes a merge undesirable (e.g. bug report from user who experieces problem with the change, security advisory from a security officer, negative feedback from other developers and so on).

Design

When designing the MFCns the following goals were attacked:

  1. The service should be triggered by the presence of the special field in the commit message;
  2. due to the fact that it will have to parse all commit messages it should be speed-efficient during initial selection of messages, when it have to separate few messages which cointain that special field from a much larger number of those that do not;
  3. it should be robust enough to minimise possibility of the accidental match and provide some form of resilence, so that if the service is halted for some reason (e.g. machine maintenance, program error etc.) already queued notifications aren't lost and will be sent once the operation of the service is resumed.

Implementation

The service is implemented in two parts. First part written in C is a simple mail filter, which reads mail message (one a time) from the standard input, looks for a set of patterns and if all conditions are satisfied writes copy of message into a specially designated spool folder. To avoid using locks the filter initially writes message into a temporary folder and then moves it into a spool folder using rename(2) system call, which is guranteed to be atomic operation. Obviously this means that both temporary and spool folders have to reside on the same filesystem, so please keep this in mind if you are going to use the service elsewhere. The name of the file in the spool directory is generated using value in the "Message-ID" field of the message, allowing to avoid duplicated notification if for some reason more than one copy of the same commit message will be received by the filter. Since e-mail messages is considered as an "unsafe" medium, the filter puts significant restrictions on the part of the "Message-ID" field to be used as the filename, so that it is impossible to use forged message to overwrite a file outside of the spool directory.

The second part of the service does most of the job, which includes spool and queue processing and sending reminders. Since this part is not speed-critical (it only invoked once a day), it was implemented in Python. Its operation consists of the following phases:

Security

Since e-mail is widely known as a not very safe medium, the service was designed with security in mind, however no formal security audit was performed yet. The part of the service written in C doesn't use any statically allocated string buffers, so it should not be vulnerable to various smash-the-stack attacks, while part written in Python was specially tailored to not pass any of the shell metacharacters to a subshell invoked for sending notification. All this makes a potential attack pretty meaningless, because all that an attacker could do is to make service sending fake MFC notifications, but he can do this even without any help from the service.

Obtaining the code

https://github.com/sobomax/mfc_notifications

Feedback

If you have any questions/suggestions/requests please don't hesitate to contact Maxim Sobolev sobomax@FreeBSD.org. Also, if possible, drop me a line if you will find this code useful somewhere outside of the FreeBSD Project.

Usage Statistics

MFC Notification Service Statistics
-----------------------------------

Period: Wed May 9 00:22:02 2001 - Thu May 9 00:23:03 2019
Total number of notifications sent: 41356

Committer   MFCs    % total
---------   ----    -------

kib     2998       7.25
jhb     1544       3.73
hselasky    1462       3.54
ngie        1426       3.45
rwatson     1217       2.94
mav     1007       2.43
trasz        953       2.30
markj        938       2.27
pjd      922       2.23
avg      902       2.18
delphij      861       2.08
dim      724       1.75
sephe        703       1.70
tuexen       665       1.61
bz       652       1.58
brueffer     581       1.40
bdrewery     564       1.36
pfg      540       1.31
ae       539       1.30
des      509       1.23
marius       474       1.15
rmacklem     469       1.13
emaste       439       1.06
np       430       1.04
asomers      429       1.04
arybchik     409       0.99
gjb      400       0.97
eadler       390       0.94
sam      385       0.93
ume      357       0.86
alc      345       0.83
maxim        332       0.80
mm       311       0.75
mjacob       271       0.66
nwhitehorn   260       0.63
sobomax      257       0.62
jilles       229       0.55
brooks       211       0.51
bapt         210       0.51
yar      204       0.49
ru       201       0.49
dteske       196       0.47
sbruno       192       0.46
smh      189       0.46
jhibbits     186       0.45
rpaulo       183       0.44
luigi        182       0.44
emax         180       0.44
gad      180       0.44
cy       174       0.42
dchagin      171       0.41
gavin        170       0.41
ken      167       0.40
brian        161       0.39
cperciva     161       0.39
trociny      161       0.39
kevans       157       0.38
melifaro     157       0.38
simon        157       0.38
julian       154       0.37
imp      152       0.37
andrew       150       0.36
pluknet      144       0.35
mjg      136       0.33
gnn      134       0.32
kmacy        134       0.32
njl      133       0.32
keramida     131       0.32
rnoland      131       0.32
ed       130       0.31
kientzle     128       0.31
gshapiro     126       0.30
marcel       125       0.30
jimharris    122       0.29
avos         120       0.29
scottl       119       0.29
dumbbell     117       0.28
rstone       116       0.28
bms      115       0.28
jkim         115       0.28
andre        113       0.27
manu         113       0.27
vangyzen     109       0.26
csjp         108       0.26
truckman     107       0.26
dwmalone     106       0.26
attilio      104       0.25
yongari      103       0.25
edwin        102       0.25
schweikh     101       0.24
rrs       99       0.24
gonzo         98       0.24
jmg       98       0.24
glebius       97       0.23
bschmidt      92       0.22
kp        91       0.22
joerg         90       0.22
mlaier        90       0.22
dillon        89       0.22
silby         88       0.21
thompsa       88       0.21
kris          86       0.21
mckusick      86       0.21
lstewart      85       0.21
mmel          83       0.20
allanjude     82       0.20
hrs       80       0.19
slavash       77       0.19
flz       73       0.18
philip        72       0.17
grehan        71       0.17
neel          71       0.17
davidcs       69       0.17
iedowse       69       0.17
wblock        69       0.17
kadesai       66       0.16
brucec        65       0.16
bryanv        64       0.15
cognet        64       0.15
dds       64       0.15
matteo        63       0.15
remko         63       0.15
sevan         62       0.15
will          62       0.15
ache          61       0.15
eugen         61       0.15
loos          61       0.15
nyan          60       0.15
fabient       58       0.14
ariff         57       0.14
gibbs         56       0.14
suz       56       0.14
jh        55       0.13
kensmith      55       0.13
ceri          53       0.13
jamie         53       0.13
stas          53       0.13
oleg          50       0.12
adrian        48       0.12
qingli        48       0.12
roam          47       0.11
royger        47       0.11
tjr       46       0.11
amdmi3        45       0.11
n_hibma       45       0.11
wulf          45       0.11
bcr       44       0.11
cjc       44       0.11
antoine       43       0.10
oshogbo       43       0.10
se        42       0.10
archie        41       0.10
erj       41       0.10
jfv       41       0.10
mikeh         41       0.10
pkelsey       41       0.10
danger        40       0.10
hiren         40       0.10
murray        40       0.10
zec       40       0.10
gabor         39       0.09
jkoshy        39       0.09
jpaetzel      39       0.09
mdf       39       0.09
tijl          38       0.09
grog          37       0.09
jdp       37       0.09
jmallett      37       0.09
jtl       37       0.09
rodrigc       37       0.09
iwasaki       36       0.09
mbr       36       0.09
thomas        36       0.09
pav       35       0.08
vmaffione     35       0.08
fsu       34       0.08
kaiw          33       0.08
sanpei        33       0.08
bmah          32       0.08
dab       32       0.08
gallatin      32       0.08
netchild      32       0.08
simokawa      32       0.08
uqs       32       0.08
dfr       31       0.07
ambrisko      30       0.07
mtm       30       0.07
ray       30       0.07
fjoe          29       0.07
krion         29       0.07
roberto       29       0.07
avatar        28       0.07
davidxu       28       0.07
rik       28       0.07
zont          28       0.07
dexuan        27       0.07
pdeuskar      27       0.07
araujo        26       0.06
bp        26       0.06
jeff          26       0.06
semenu        26       0.06
davidch       25       0.06
marck         25       0.06
mike          25       0.06
ups       24       0.06
wollman       24       0.06
lidl          23       0.06
mux       23       0.06
scf       23       0.06
damien        22       0.05
kan       22       0.05
markus        22       0.05
mmacy         22       0.05
shurd         22       0.05
wilko         22       0.05
daichi        21       0.05
lulf          21       0.05
rgrimes       21       0.05
rpokala       21       0.05
slm       21       0.05
das       20       0.05
garga         20       0.05
jmmv          20       0.05
bde       19       0.05
jhay          19       0.05
jlh       19       0.05
joe       19       0.05
mp        19       0.05
raj       19       0.05
theraven      19       0.05
trhodes       19       0.05
weongyo       19       0.05
cem       18       0.04
phk       18       0.04
yokota        18       0.04
alfred        17       0.04
guido         17       0.04
harti         17       0.04
blackend      16       0.04
hm        16       0.04
kevlo         16       0.04
pirzyk        16       0.04
stevek        16       0.04
jah       15       0.04
pho       15       0.04
ssouhlal      15       0.04
tsoome        15       0.04
issyl0        14       0.03
jesper        14       0.03
mr        14       0.03
rse       14       0.03
cokane        13       0.03
matusita      13       0.03
ps        13       0.03
rafan         13       0.03
akiyama       12       0.03
andreast      12       0.03
gj        12       0.03
jon       12       0.03
kbyanc        12       0.03
mdodd         12       0.03
orion         12       0.03
rink          12       0.03
sheldonh      12       0.03
vanhu         12       0.03
asmodai       11       0.03
brd       11       0.03
dcs       11       0.03
eri       11       0.03
ivoras        11       0.03
jcamou        11       0.03
jch       11       0.03
johan         11       0.03
le        11       0.03
sumikawa      11       0.03
wes       11       0.03
zack          11       0.03
gordon        10       0.02
ian       10       0.02
rmh       10       0.02
stefanf       10       0.02
wkoszek       10       0.02
ygy       10       0.02
0mp        9       0.02
davide         9       0.02
fanf           9       0.02
kuriyama       9       0.02
pb         9       0.02
rea        9       0.02
tmm        9       0.02
zeising        9       0.02
badger         8       0.02
benno          8       0.02
chuck          8       0.02
darrenr        8       0.02
dwhite         8       0.02
erwin          8       0.02
green          8       0.02
jkh        8       0.02
jonathan       8       0.02
jwd        8       0.02
marcus         8       0.02
marks          8       0.02
phantom        8       0.02
randi          8       0.02
anholt         7       0.02
bsd        7       0.02
deischen       7       0.02
eik        7       0.02
garys          7       0.02
karels         7       0.02
mmokhi         7       0.02
peterj         7       0.02
sepotvin       7       0.02
tobez          7       0.02
bjk        6       0.01
den        6       0.01
dg         6       0.01
dhartmei       6       0.01
feld           6       0.01
fenner         6       0.01
gahr           6       0.01
keichii        6       0.01
markm          6       0.01
msmith         6       0.01
mw         6       0.01
olgeni         6       0.01
olli           6       0.01
ram        6       0.01
sef        6       0.01
syrinx         6       0.01
whu        6       0.01
yuripv         6       0.01
bwidawsk       5       0.01
eric           5       0.01
ghelmer        5       0.01
greid          5       0.01
hmp        5       0.01
jlemon         5       0.01
mckay          5       0.01
mizhka         5       0.01
mnag           5       0.01
nsayer         5       0.01
peadar         5       0.01
rdivacky       5       0.01
robak          5       0.01
seanc          5       0.01
bruno          4       0.01
cel        4       0.01
dannyboy       4       0.01
grembo         4       0.01
imura          4       0.01
jceel          4       0.01
jgh        4       0.01
jinmei         4       0.01
knu        4       0.01
lwhsu          4       0.01
matthew        4       0.01
mjoras         4       0.01
nectar         4       0.01
olivier        4       0.01
piso           4       0.01
rsm        4       0.01
skra           4       0.01
takawata       4       0.01
ticso          4       0.01
tom        4       0.01
wpaul          4       0.01
assar          3       0.01
benjsc         3       0.01
bmilekic       3       0.01
chinsan        3       0.01
dmlb           3       0.01
emoore         3       0.01
groudier       3       0.01
jedgar         3       0.01
lioux          3       0.01
mini           3       0.01
phil           3       0.01
rakuco         3       0.01
rees           3       0.01
robert         3       0.01
ade        2       0.00
ale        2       0.00
amorita        2       0.00
babkin         2       0.00
billf          2       0.00
bland          2       0.00
brix           2       0.00
cg         2       0.00
chris          2       0.00
crees          2       0.00
dbaker         2       0.00
dd         2       0.00
gleb           2       0.00
jb         2       0.00
jmcneill       2       0.00
lme        2       0.00
luoqi          2       0.00
motoyuki       2       0.00
nork           2       0.00
osa        2       0.00
snb        2       0.00
sos        2       0.00
svn        2       0.00
tabthorpe      2       0.00
tmunro         2       0.00
zml        2       0.00
adamw          1       0.00
alex           1       0.00
anish          1       0.00
art        1       0.00
beat           1       0.00
ben        1       0.00
chm        1       0.00
dan        1       0.00
danny          1       0.00
davidn         1       0.00
dbaio          1       0.00
dru        1       0.00
edavis         1       0.00
gber           1       0.00
hsu        1       0.00
jasone         1       0.00
jim        1       0.00
jmb        1       0.00
jmz        1       0.00
johalun        1       0.00
kato           1       0.00
lawrance       1       0.00
lifanov        1       0.00
matk           1       0.00
mhorne         1       0.00
miwi           1       0.00
mpp        1       0.00
mwlucas        1       0.00
novel          1       0.00
pgj        1       0.00
pst        1       0.00
rene           1       0.00
riggs          1       0.00
rushani        1       0.00
sjg        1       0.00
skreuzer       1       0.00
tackerman      1       0.00
tanimura       1       0.00
thj        1       0.00
tomsoft        1       0.00
twinterg       1       0.00
ue         1       0.00
versus         1       0.00
vsevolod       1       0.00
xride          1       0.00

-- Maxim Sobolev sobomax@FreeBSD.org