File: README.flow

package info (click to toggle)
stealth 4.04.00-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,540 kB
  • sloc: cpp: 2,759; sh: 151; makefile: 111; ansic: 52
file content (233 lines) | stat: -rw-r--r-- 9,783 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
Stealth may run in one of three modes:

    1. Foreground, where stealth performs one integrity scan and terminates;

    2. Background, where stealth, after performing its initial integrity scan
       waits for additional commands and/or performs additional integrity scans
       after (possibly random) time intervals.

    3. IPC, where stealth sends commands to a stealth daemon process.

Communication between stealth processes running in modes 2 and 3 is realized
through a unix domain socket, which is created by the stealth daemon process. 

Figure documentation/images/communication.jpg shows the organization:

    * Stealth --daemon starts the daemon process, its childprocess
        (stealth/childprocess) starting the ipcInterface thread (separate
        threads are shown in light green), implemented by the
        stealth/ipcinterface function.

    * ChildProcess is the main thread of the running stealth daemon. It
        performs all the tasks (through stealth/doTasks). 

        DoChores performs some bookkeeping tasks, eventually passing control
        to stealth/processrequests. 

        JobsHandler runs the current task, which may be an integrity
        scan. 

    * IpcInterface is a separate thread preparing the next task for
        jobsHandler. It creates the Unix domain server socket, and waits for
        incoming request. Incoming requests are verified, and if OK they are
        forwarded to jobsHandler. IpcInterface's mode of operation is
        described in more detail below.

    * Stealth-ipc processes handle ipc requests. These processes connect to
        the stealth daemon's unix domain socket, passing it the received
        request. It then waits for a reply from the daemon. If the daemon
        reports an error the error message is shown, and stealth running in
        ipc mode terminates with exit value 1. Otherwise exit value 0 is
        returned and no additional output is shown.

Figure documentation/images/ipcinterface.jpg shows the inner workings of
the ipcInterface function.

    * Each cycle of ipcInterface's main loop handles one incoming
        connection. If a TERMINATE request is received, the ipcInterface
        thread ends. A TERMINATE request also ends the main (jobsHandler)
        thread. Once both threads have terminated the stealth daemon ends.

    * Incoming requests are validated (by Stealth::incomingRequest), and (if
        valid) initially stored in the local Runmode incoming, processing may
        be suspended until processRequests is ready to accept the next command
        (see below at nextTask's description).

    * Incoming requests are validated. For each possible request a matching
        ...request function handles the valiadation. If a request cannot be
        granted (i.e., is invalid), an error message is sent to the
        stealth-ipc process and another cycle starts.

        Given a current task (mode of operation) the following requests are
        valid: 

        ----------------------------------------------------------
        Actual Job:            Valid Incoming Request:
        ----------------------------------------------------------
        INTEGRITY_SCAN          RELOAD, RERUN, SUSPEND, TERMINATE
        RELOAD                  TERMINATE
        SUSPEND                 RELOAD, RESUME, SUSPEND, TERMINATE
        ----------------------------------------------------------

        Requesting SUSPEND while in SUSPEND mode has no effect (validation
        returns `nop'): in this case the stealth-ipc process is informed that
        there is no error but processRequests doesn't actually receive a new
        command to process

    * If a request is valid, the incoming request is stored in
        d_pending. Ongoing jobs may inspect d_pending to see whether they
        should prematurely stop (e.g., when a TERMINATE request arrives while
        an integrity scan is being executed, the scan will end after
        completing the command currently being processed)

    * Next, ipcInterface waits until jobsHandler is ready for the next task.
        When ready, notifyTask sets the next task in d_task, and d_pending is
        reset, after which jobsHandler is notified that it has another task to
        handle.

    * The next task may be TERMINATE. If so, ipcInterface ands (and
        jobsHandler will also end).



The Stealth::jobsHandler function handles incoming requests. This function
loops until (at the end of the loop) the d_task has been set to TERMINATE. At
the top of the loop the next job is determined. Once determined, the
requested task starts.

Figure documentation/images/nextjob.jpg shows the inner workings of
Stealth::nextJob.

When returning from nextJob the d_job binary Semaphore has decayed to zero. It
is incremented again by ipcInterface once a command is requested by an
ipc-stealth process and by some of the task-handling functions (reload,
resume, rerun).

Since ipcInterface and some of the task-handling functions may set the next
command to process, the permission to set the next command is set by the d_ipc
semaphore. Once ipcInterface returns from d_ipc.wait() d_ipc blocks until it
is incremented by d_ipc.notify(). Initially d_ipc blocks, but it is
incremented by startScan and suspend.

When nextJob returns the next task has been set. This is realized as follows:

    * If at daemon startup --repeat was not specified then nextJob simply
waits for a command which is received from an ipc-stealth process through
ipcInterface (alternatively, the command may be set by the mentioned
request-processing functions). 

    * time-limited wait: otherwise, nextJobs waits until either a command was
        set (as with the plain wait), or until a (random) delay has passed.
    
    * If no timeout occurred, then a command was specified and nextJob
        returns with the next command.

    * Otherwise, in suspend mode or while an integrity scan is still active,
        nextJob loops back to the time-limited wait step.

    * Otherwise, --repeat was specified, and the waiting time has passed, so
        the next task automatically becomes INTEGRITY_SCAN (and nextJob
        returns)


Integrity scans are performed by Stealth::integrityScan.

    



Flow control is handled by communicating through a Unix Domain Socket, which
uses the run-file. Requests are:

    suspend,
    resume,
    rerun       - rerun the full itegrity scan
    reload      - after the current scan has completed (it may already have
                    completed) load a new policy- and possibly skip-file
                    and perform another integrity scan.
    terminate

    Requests are received through the Unix domain socket defined by the run-file
    the daemon performs the request and replies with an answer indicating
    success or failure. Success is inferred when an empty line is received.
    Failure information contains an indication of the nature of the failure.

Requests are passed to the daemon from the function Stealth::contactPeer.

|    - the pid file is locked
|    - the request is written to the pid-file
|    - the pid file is unlocked.
| 
| A request is written to the PID file, followed by sending the daemon a SIGUSR1
| signal. When the daemon has completed the request it sends the requesting
| process a SIGUSR1 signal; 


Stealth uses a RunMode object to keep track of its current mode of operation
| now OBS? and an IPC object to handle the inter process communication.

The member Stealth::policyMode handles the actual commands.

policyMode:
==============
policyMode forks if a Stealth should run as a daemon, in which case the
fork's child process performs the daemon's tasks, and the parent process
immediately finishes. 

When a daemon starts its childProcess prepares the daemon (using
Fork::prepareDaemon), and the communication thread starts, defining the
unix domain server socket. Hereafter 'doTasks' starts.

communicator:
=============

The communicator creates the LocalServerSocket, and loops while d_run.mode()
is unequal TERMINATE. When a request arrives, the matching function is
called. These functions should return an empty string indicating that the
request can be handled. Otherwise the returned string contains an error
message which is returned to the requestor. 

If the request can be handled d_chore is notified, and the communicator waits
for d_communicate to return, indicating that the request has been
handled. When d_communicate.wait() returns the contents of d_result is
returned to the requestor. Again: an empty string indicates that the request
was successfully processed.

doTasks:
=========

With foreground runs 'doTasks' is directly started.

The flow of control handling requests is defined in processRequests,
called from doTasks. ProcessRequests defines a loop basically processing a
request and waiting for the next request ((waitForRequest)

The file integrity scan itself is handled by an IntegrityScanner object.

| 
| Communications with the daemon use the run-file and signals SIGUSR1 (and
| SIGTERM). The run-file by default contains the pid of the daemon process. The
| signalling stealth process adds a request to the
| file. The daemon reads the request and honors it if possible.


processRequests:
================

Stealth (when performing integrity scans) starts up with an initial mode
INTEGRITY_SCAN. At processRequests netTask() returns the next mode, which is
then processed by 'process'. 

NextTask() inspects the current mode. If it's WAIT wait() is called, which 



Possible task requests:
=======================
rerun:      OK in mode WAIT
suspend:    OK in mode SCAN, WAIT, SUSPEND
resume:     OK in mode SUSPEND
reload:     OK in mode SCAN, WAIT, SUSPEND
terminate:  always OK.