Package: incron
Version: 0.5.12-1
Severity: grave
Tags: security patch upstream

Hi,

incron crashes for me frequently. As incron runs as root, but is controllable
by users, this bug might be security-relevant, so I'm reporting it a severity
grave and tagging it security.  Please downgrade if you can rule out this
concern.

Further investigation shows that the problem is caused by the creation of new
directories within watched paths: these trigger a reload of the inotify watch
target, rendering the old watch structure invalid. Only after the reload,
potential commands are executed. This may require to get path of the event, but
the corresponding pointer is invalid after the reload.

Attached is a patch that extracts the path before the reload, making this
problem disappear for me. Note that the patch assumes that LOOPER is not
defined, which seems to be the case for the Debian package.

Backtrace for reference:

bt full
#0  0x004ba484 in IncronTabEntry::GetSafePath (rPath=<error: Cannot access 
memory at address 0x7475612f>) at /usr/include/c++/8/bits/basic_string.h:1046
        i = 0
        stream = <incomplete type>
        len = 1919509615
#1  0x004c43f3 in UserTable::OnEvent (this=<optimized out>, rEvt=...) at 
inotify-cxx.h:428
        px = 40
        pW = 0x1fbde40
        pE = 0x1fbc920
        events = "IN_CREATE,IN_ISDIR"
        cmd = "/home/user/autoscripts/imageresize.sh "
        cs = "/home/user/autoscripts/imageresize.sh $@/$# $# $%"
        pos = 39
        oldpos = 0
        len = <optimized out>
        pid = <optimized out>
#2  0x004c4767 in EventDispatcher::ProcessEvents (this=<optimized out>) at 
usertable.cpp:110
        pIn = 0x1fc7d24
        it = {first = 1702521203, second = 0x1fc0072}
        i = 2
        pipe = false
        evt = {m_uMask = 1073742080, m_uCookie = 0, m_name = "Neuer Ordner", 
m_pWatch = 0x1fbde40}
#3  0x004b8650 in main (argc=<optimized out>, argv=<optimized out>) at 
icd-main.cpp:458
        res = <optimized out>
        wm = 10184
        in = {m_fd = 6, m_watches = std::map with 2 elements = {[1] = 
0xbfc8ab40, [2] = 0xbfc8ab68}, m_paths = std::map with 2 elements = {
            ["/etc/incron.d"] = 0xbfc8ab40, ["/var/spool/incron"] = 
0xbfc8ab68}, m_buf = '\000' <repeats 29450 times>..., m_events = std::deque 
with 0 elements}
        stw = {m_path = "/etc/incron.d", m_uMask = 10184, m_wd = 1, m_pInotify 
= 0xbfc8ab90, m_fEnabled = true}
        utw = {m_path = "/var/spool/incron", m_uMask = 10184, m_wd = 2, 
m_pInotify = 0xbfc8ab90, m_fEnabled = true}
        ed = {m_iPipeFd = 4, m_iMgmtFd = 6, m_pIn = 0xbfc8ab90, m_pSys = 
0xbfc8ab40, m_pUser = 0xbfc8ab68, m_maps = std::map with 1 element = {[8] = 
0x1fc7d20}, 
          m_size = 3, m_pPoll = 0x1fbe080}
        cfg = "/etc/incron.conf"
        lckdir = "/var/run"
        lckfile = "incrond"
        app = {m_path = "/var/run/incrond.pid", m_fLocked = true}
        ret = 0
        sysBase = "/etc/incron.d"
        userBase = "/var/spool/incron"

-- System Information:
Debian Release: 10.2
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-debug'), (500, 'stable')
Architecture: i386 (i686)

Kernel: Linux 4.19.0-6-686-pae (SMP w/4 CPU cores)
Locale: LANG=de_AT.UTF-8, LC_CTYPE=de_AT.UTF-8 (charmap=UTF-8), 
LANGUAGE=de_AT.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages incron depends on:
ii  adduser              3.118
ii  init-system-helpers  1.56+nmu1
ii  libc6                2.28-10
ii  libgcc1              1:8.3.0-6
ii  libstdc++6           8.3.0-6
ii  lsb-base             10.2019051400

incron recommends no packages.

incron suggests no packages.

-- Configuration Files:
/etc/incron.allow [Errno 13] Keine Berechtigung: '/etc/incron.allow'
/etc/incron.deny [Errno 13] Keine Berechtigung: '/etc/incron.deny'

-- no debconf information
diff --git a/usertable.cpp b/usertable.cpp
index 3f1ef4a..bdc7f29 100644
--- a/usertable.cpp
+++ b/usertable.cpp
@@ -370,6 +370,8 @@ void UserTable::OnEvent(InotifyEvent& rEvt)
 {
   InotifyWatch* pW = rEvt.GetWatch();
   IncronTabEntry* pE = FindEntry(pW);
+
+  std::string pWPath = pW->GetPath();
 
   // no entry found - this shouldn't occur
   if (pE == NULL)
@@ -422,7 +424,7 @@ void UserTable::OnEvent(InotifyEvent& rEvt)
       else {
         cmd.append(cs.substr(oldpos, pos-oldpos));
         if (cs[px] == '@') {          // base path
-          cmd.append(IncronTabEntry::GetSafePath(pW->GetPath()));
+          cmd.append(IncronTabEntry::GetSafePath(pWPath));
           oldpos = pos + 2;
         }
         else if (cs[px] == '#') {     // file name

Reply via email to