Skyld AV  0.6
On access virus scanning for Linux
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
MountPolling.cc
Go to the documentation of this file.
1 /*
2  * File: MountPolling.c
3  *
4  * Copyright 2012 Heinrich Schuchardt <xypron.glpk@gmx.de>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 
24 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE // enable ppoll
26 #endif // _GNU_SOURCE
27 #define _POSIX_C_SOURCE 200809L // enable nanosleep
28 #include <errno.h>
29 #include <features.h>
30 #include <fcntl.h>
31 #include <iostream>
32 #include <poll.h>
33 #include <pthread.h>
34 #include <sstream>
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <sys/types.h>
39 #include <time.h>
40 #include <unistd.h>
41 #include "Environment.h"
42 #include "FanotifyPolling.h"
43 #include "listmounts.h"
44 #include "Messaging.h"
45 #include "MountPolling.h"
46 #include "ScanCache.h"
47 
51 static pthread_t thread;
52 
59 void * MountPolling::run(void *obj) {
60  MountPolling *mp = static_cast<MountPolling *> (obj);
61  /*
62  * file descriptor.
63  */
64  int mfd;
68  struct pollfd fds;
72  nfds_t nfds = 1;
76  char errbuf[256];
77 
78  mp->status = INITIAL;
79 
80  // Open file /proc/mounts.
81  mfd = open("/proc/mounts", O_RDONLY, 0);
82  if (mfd < 0) {
83  std::stringstream msg;
84  msg << "Failure to open /proc/mounts: "
85  << strerror_r(errno, errbuf, sizeof(errbuf));
87 
88  mp->status = FAILURE;
89  return NULL;
90  }
91  fds.fd = mfd;
92  fds.events = POLLERR | POLLPRI;
93  fds.revents = 0;
94  mp->status = RUNNING;
95  while (mp->status == RUNNING) {
96  /*
97  * number of structures with nonzero revents fields, 0 = timeout
98  */
99  int ret;
100  ret = poll(&fds, nfds, 1);
101  if (ret > 0) {
102  if (fds.revents & POLLERR) {
103  mp->callback();
104  }
105  fds.revents = 0;
106  } else if (ret < 0) {
107  if (errno != EINTR) {
108  std::stringstream msg;
109  msg << "Failure to poll /proc/mounts: "
110  << strerror_r(errno, errbuf, sizeof(errbuf));
112  close(mfd);
113  mp->status = FAILURE;
114  return NULL;
115  }
116  }
117  }
118  close(mfd);
119  mp->status = SUCCESS;
120  return NULL;
121 }
122 
127  const char *dir;
128  const char *type;
129  StringSet *cbmounts;
130  StringSet::iterator pos;
131  std::string *str;
132  int newMount = 0;
133 
134  cbmounts = new StringSet();
135 
136  do {
137  if (listmountinit()) {
138  break;
139  }
140  while (!listmountnext(&dir, &type)) {
141  if (!isFuse(type)
142  && !nomarkfs->find(type)
143  && !nomarkmnt->find(dir)) {
144  cbmounts->add(dir);
145  }
146  }
147  } while (0);
148 
149  for (pos = cbmounts->begin(); pos != cbmounts->end(); ++pos) {
150  if (0 == mounts->count(*pos)) {
151  str = *pos;
152  FanotifyPolling::markMount(fd, str->c_str());
153  newMount = 1;
154  }
155  }
156  for (pos = mounts->begin(); pos != mounts->end(); ++pos) {
157  if (0 == cbmounts->count(*pos)) {
158  str = *pos;
159  FanotifyPolling::unmarkMount(fd, str->c_str());
160  }
161  }
162  if (newMount) {
163  // If new mounts are marked clear the cache.
164  env->getScanCache()->clear();
165  }
166 
167  delete(mounts);
168  mounts = cbmounts;
169 
171 }
172 
178 int MountPolling::isFuse(const char *type) {
179  int ret = 0;
180  if (type[0] == 'f'
181  && type[1] == 'u'
182  && type[2] == 's'
183  && type[3] == 'e'
184  && (type[4] == '.' || type[4] == '\0')) {
185  ret = 1;
186  }
187  return ret;
188 }
189 
197  pthread_attr_t attr;
198  int ret;
199  struct timespec waiting_time_rem;
200  struct timespec waiting_time_req;
201  char errbuf[256];
202 
203  env = e;
204  fd = ffd;
205  this->nomarkfs = env->getNoMarkFileSystems();
206  this->nomarkmnt = env->getNoMarkMounts();
207 
208  status = INITIAL;
209 
210  this->mounts = new StringSet();
211  if (this->mounts == NULL) {
212  throw FAILURE;
213  }
214 
216 
217  ret = pthread_attr_init(&attr);
218  if (ret != 0) {
219  std::stringstream msg;
220  msg << "Failure to set thread attributes: "
221  << strerror_r(errno, errbuf, sizeof(errbuf));
223  throw FAILURE;
224  }
225  ret = pthread_create(&thread, &attr, run, (void *) this);
226  if (ret != 0) {
227  std::stringstream msg;
228  msg << "Failure to create thread: "
229  << strerror_r(errno, errbuf, sizeof(errbuf));
231  throw FAILURE;
232  }
233  waiting_time_req.tv_sec = 0;
234  waiting_time_req.tv_nsec = 100;
235  while (status == INITIAL) {
236  nanosleep(&waiting_time_req, &waiting_time_rem);
237  }
238  if (status == FAILURE) {
239  throw FAILURE;
240  }
241 }
242 
247  void *result;
248  int ret;
249 
250  if (status != RUNNING) {
251  Messaging::message(Messaging::ERROR, "Polling not started.\n");
252  return;
253  }
254 
255  // Ask polling thread to stop.
256  status = STOPPING;
257 
258  // Unmark all mounts.
259  if (mounts != NULL) {
260  StringSet::iterator pos;
261  for (pos = mounts->begin(); pos != mounts->end(); ++pos) {
262  std::string *str;
263  str = *pos;
264  FanotifyPolling::unmarkMount(fd, str->c_str());
265  }
266  delete(MountPolling::mounts);
267  MountPolling::mounts = NULL;
268  }
269 
270  // Wait for thread to stop.
271  ret = (int) pthread_join(thread, &result);
272  if (ret != 0) {
273  std::stringstream msg;
274  char errbuf[256];
275  msg << "Failure to join thread: "
276  << strerror_r(errno, errbuf, sizeof(errbuf));
278  return;
279  }
280  if (status != SUCCESS) {
282  "Ending thread signals failure.\n");
283  }
284 }
static void * run(void *)
Thread listening to mount events.
Definition: MountPolling.cc:59
static int markMount(int fd, const char *mount)
Marks a mount for polling fanotify events.
static pthread_t thread
thread.
Definition: MountPolling.cc:51
Error, e.g. malfunction of the code, malware detected.
Definition: Messaging.h:56
int fd
Fanotify file descriptor.
Definition: MountPolling.h:64
void add(const char *value)
Adds entry to string set.
Definition: StringSet.cc:38
Set of pointers to strings.
Definition: StringSet.h:56
int listmountinit()
Definition: listmounts.c:38
int find(const char *value)
Finds entry in string set.
Definition: StringSet.cc:50
List mounts.
Send messages.
int isFuse(const char *)
Checks if a mount is using a filesystem in userspace (fuse).
void clear()
Removes all entries from the cache.
Definition: ScanCache.cc:104
void callback()
Tracks mountevents.
StringSet * getNoMarkMounts()
Gets the list of mounts not to be scanned.
Definition: Environment.cc:73
static void message(const enum Level, const std::string &)
Sends message.
Definition: Messaging.cc:101
static int unmarkMount(int fd, const char *mount)
Removes a mount from polling fanotify events.
~MountPolling()
Deletes mount polling object.
MountPolling(int ffd, Environment *)
Polls mount and unmout events.
Definition: MountPolling.h:36
Cache for virus scanning results.
Poll fanotify events.
ScanCache * getScanCache()
Gets the scan cache.
Definition: Environment.cc:110
StringSet * getNoMarkFileSystems()
Gets the list of file systems that shall not be scanned.
Definition: Environment.cc:64
Envronment.
StringSet * nomarkmnt
Mount points that shall not be tracked.
Definition: MountPolling.h:76
sig_atomic_t status
Status of thread.
Definition: MountPolling.h:81
Poll /proc/mounts to detect mount events.
StringSet * nomarkfs
File systems that shall not be tracked.
Definition: MountPolling.h:72
StringSet * mounts
Mounts.
Definition: MountPolling.h:68
The environment holds variables that are shared by instances of multiple classes. ...
Definition: Environment.h:38
void listmountfinalize()
Definition: listmounts.c:77
Environment * env
Environment.
Definition: MountPolling.h:60
int listmountnext(const char **dir, const char **type)
Definition: listmounts.c:63