예제 #1
0
func listen_events(mount_point string, stop chan bool) chan map[event]bool {
	log.Println("monitor: listen_events start")

	nd, err := fanotify.Initialize(fanotify.FAN_CLASS_NOTIF, os.O_RDONLY)
	check(err)
	err = nd.Mark(fanotify.FAN_MARK_ADD|fanotify.FAN_MARK_MOUNT, fanotify.FAN_ACCESS|fanotify.FAN_OPEN, -1, mount_point)
	check(err)

	events_chan := make(chan map[event]bool, 1)

	go func() {
		events := make(map[event]bool, 1)
		s := false
		for !s {
			select {
			case <-stop:
				s = true
			default:
				data, err := nd.GetEvent()
				check(err)
				path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd()))
				check(err)
				e := event{data.Pid, path}
				data.File.Close()
				events[e] = true
			}
		}
		events_chan <- events
	}()

	return events_chan
}
예제 #2
0
func listen_events(mount_point string, stop chan bool) chan map[event]bool {
	log.Println("monitor: listen_events start")

	nd, err := fanotify.Initialize(fanotify.FAN_CLASS_NOTIF, os.O_RDONLY)
	check(err)
	err = nd.Mark(fanotify.FAN_MARK_ADD|fanotify.FAN_MARK_MOUNT, fanotify.FAN_ACCESS|fanotify.FAN_OPEN, -1, mount_point)
	check(err)

	events_chan := make(chan map[event]bool, 1)

	go func() {
		log.Println("monitor: listen_events worker starting")
		events := make(map[event]bool, 1)
		eventChan := make(chan event)
		go func() {
			for {
				data, err := nd.GetEvent()
				check(err)
				path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd()))
				check(err)
				e := event{data.Pid, path}
				data.File.Close()
				eventChan <- e
			}
		}()

		s := false
		for !s {
			select {
			case <-time.After(20 * time.Second):
				log.Println("monitor: listen_events - event timeout...")
				s = true
			case <-stop:
				log.Println("monitor: listen_events stopping...")
				s = true
			case e := <-eventChan:
				events[e] = true
				log.Printf("monitor: listen_events event => %#v\n", e)
			}
		}

		log.Printf("monitor: listen_events sending %v events...\n", len(events))
		events_chan <- events
	}()

	return events_chan
}
예제 #3
0
//func listen_events(mount_point string, stopChan chan bool) chan map[event]bool {
func listen_events(mount_point string, stopChan chan bool) <-chan *monitorReport {
	log.Println("monitor: listen_events start")

	nd, err := fanotify.Initialize(fanotify.FAN_CLASS_NOTIF, os.O_RDONLY)
	check(err)
	err = nd.Mark(fanotify.FAN_MARK_ADD|fanotify.FAN_MARK_MOUNT,
		fanotify.FAN_MODIFY|fanotify.FAN_ACCESS|fanotify.FAN_OPEN, -1, mount_point)
	check(err)

	//events_chan := make(chan map[event]bool, 1)
	events_chan := make(chan *monitorReport, 1)

	go func() {
		log.Println("monitor: listen_events worker starting")
		//events := make(map[event]bool, 1)
		report := &monitorReport{
			MonitorPid:       os.Getpid(),
			MonitorParentPid: os.Getppid(),
			ProcessFiles:     make(map[string]map[string]*fileInfo),
		}

		eventChan := make(chan event)
		go func() {
			var eventId uint32 = 0

			for {
				data, err := nd.GetEvent()
				check(err)
				//log.Printf("TMP: monitor: listen_events: data.Mask =>%x\n",data.Mask)

				if (data.Mask & fanotify.FAN_Q_OVERFLOW) == fanotify.FAN_Q_OVERFLOW {
					log.Println("monitor: listen_events: overflow event")
					continue
				}

				doNotify := false
				isRead := false
				isWrite := false

				if (data.Mask & fanotify.FAN_OPEN) == fanotify.FAN_OPEN {
					//log.Println("TMP: monitor: listen_events: file open")
					doNotify = true
				}

				if (data.Mask & fanotify.FAN_ACCESS) == fanotify.FAN_ACCESS {
					//log.Println("TMP: monitor: listen_events: file read")
					isRead = true
					doNotify = true
				}

				if (data.Mask & fanotify.FAN_MODIFY) == fanotify.FAN_MODIFY {
					//log.Println("TMP: monitor: listen_events: file write")
					isWrite = true
					doNotify = true
				}

				path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd()))
				check(err)
				//log.Println("TMP: monitor: listen_events: file path =>",path)

				data.File.Close()
				if doNotify {
					eventId++
					e := event{Id: eventId, Pid: data.Pid, File: path, IsRead: isRead, IsWrite: isWrite}
					eventChan <- e
				}
			}
		}()

		s := false
		for !s {
			select {
			//case <-time.After(110 * time.Second):
			//	log.Println("monitor: listen_events - event timeout...")
			//	s = true
			case <-stopChan:
				log.Println("monitor: listen_events stopping...")
				s = true
			case e := <-eventChan:
				report.EventCount++
				//log.Println("TMP: monitor: listen_events: event ",report.EventCount)

				if e.Id == 1 {
					//first event represents the main process
					if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) {
						report.MainProcess = pinfo
						report.Processes = make(map[string]*processInfo)
						report.Processes[strconv.Itoa(int(e.Pid))] = pinfo
						//log.Println("TMP: monitor: listen_events: (1) adding pi for ",
						//	e.Pid,"info:",report.Processes[strconv.Itoa(int(e.Pid))])
					}
				} else {
					if _, ok := report.Processes[strconv.Itoa(int(e.Pid))]; !ok {
						if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) {
							report.Processes[strconv.Itoa(int(e.Pid))] = pinfo
							//log.Println("TMP: monitor: listen_events: (2) adding pi for ",
							//	e.Pid,"info:",report.Processes[strconv.Itoa(int(e.Pid))])
						}
					}
				}

				if _, ok := report.ProcessFiles[strconv.Itoa(int(e.Pid))]; !ok {
					report.ProcessFiles[strconv.Itoa(int(e.Pid))] = make(map[string]*fileInfo)
					//log.Println("TMP: monitor: listen_events: adding pf for ",e.Pid)
				}

				if existingFi, ok := report.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File]; !ok {
					fi := &fileInfo{
						EventCount: 1,
						Name:       e.File,
					}

					if e.IsRead {
						fi.ReadCount = 1
					}

					if e.IsWrite {
						fi.WriteCount = 1
					}

					if pi, ok := report.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) {
						fi.ExeCount = 1
					}

					report.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File] = fi
				} else {
					existingFi.EventCount++

					if e.IsRead {
						existingFi.ReadCount++
					}

					if e.IsWrite {
						existingFi.WriteCount++
					}

					if pi, ok := report.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) {
						existingFi.ExeCount++
					}
				}

				log.Printf("monitor: listen_events event => %#v\n", e)
			}
		}

		log.Printf("monitor: listen_events - sending report (processed %v events)...\n", report.EventCount)
		events_chan <- report
	}()

	return events_chan
}
예제 #4
0
func Run(mountPoint string, stopChan chan struct{}) <-chan *report.FanMonitorReport {
	log.Info("fanmon: starting...")

	nd, err := fanapi.Initialize(fanapi.FAN_CLASS_NOTIF, os.O_RDONLY)
	utils.FailOn(err)
	err = nd.Mark(fanapi.FAN_MARK_ADD|fanapi.FAN_MARK_MOUNT,
		fanapi.FAN_MODIFY|fanapi.FAN_ACCESS|fanapi.FAN_OPEN, -1, mountPoint)
	utils.FailOn(err)

	eventsChan := make(chan *report.FanMonitorReport, 1)

	go func() {
		log.Debug("fanmon: fanRunMonitor worker starting")

		fanReport := &report.FanMonitorReport{
			MonitorPid:       os.Getpid(),
			MonitorParentPid: os.Getppid(),
			ProcessFiles:     make(map[string]map[string]*report.FileInfo),
		}

		eventChan := make(chan Event)
		go func() {
			log.Debug("fanmon: fanRunMonitor worker (monitor) starting")
			var eventID uint32

			for {
				data, err := nd.GetEvent()
				utils.FailOn(err)
				log.Debugf("fanmon: data.Mask =>%x\n", data.Mask)

				if (data.Mask & fanapi.FAN_Q_OVERFLOW) == fanapi.FAN_Q_OVERFLOW {
					log.Debug("fanmon: overflow event")
					continue
				}

				doNotify := false
				isRead := false
				isWrite := false

				if (data.Mask & fanapi.FAN_OPEN) == fanapi.FAN_OPEN {
					log.Debug("fanmon: file open")
					doNotify = true
				}

				if (data.Mask & fanapi.FAN_ACCESS) == fanapi.FAN_ACCESS {
					log.Debug("fanmon: file read")
					isRead = true
					doNotify = true
				}

				if (data.Mask & fanapi.FAN_MODIFY) == fanapi.FAN_MODIFY {
					log.Debug("fanmon: file write")
					isWrite = true
					doNotify = true
				}

				path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd()))
				utils.FailOn(err)
				log.Debug("fanmon: file path =>", path)

				data.File.Close()
				if doNotify {
					eventID++
					e := Event{ID: eventID, Pid: data.Pid, File: path, IsRead: isRead, IsWrite: isWrite}
					eventChan <- e
				}
			}
		}()

	done:
		for {
			select {
			case <-stopChan:
				log.Info("fanmon: stopping...")
				break done
			case e := <-eventChan:
				fanReport.EventCount++
				log.Debug("fanmon: event ", fanReport.EventCount)

				if e.ID == 1 {
					//first event represents the main process
					if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) {
						fanReport.MainProcess = pinfo
						fanReport.Processes = make(map[string]*report.ProcessInfo)
						fanReport.Processes[strconv.Itoa(int(e.Pid))] = pinfo
					}
				} else {
					if _, ok := fanReport.Processes[strconv.Itoa(int(e.Pid))]; !ok {
						if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) {
							fanReport.Processes[strconv.Itoa(int(e.Pid))] = pinfo
						}
					}
				}

				if _, ok := fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))]; !ok {
					fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))] = make(map[string]*report.FileInfo)
				}

				if existingFi, ok := fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File]; !ok {
					fi := &report.FileInfo{
						EventCount: 1,
						Name:       e.File,
					}

					if e.IsRead {
						fi.ReadCount = 1
					}

					if e.IsWrite {
						fi.WriteCount = 1
					}

					if pi, ok := fanReport.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) {
						fi.ExeCount = 1
					}

					fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File] = fi
				} else {
					existingFi.EventCount++

					if e.IsRead {
						existingFi.ReadCount++
					}

					if e.IsWrite {
						existingFi.WriteCount++
					}

					if pi, ok := fanReport.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) {
						existingFi.ExeCount++
					}
				}
			}
		}

		log.Debugf("fanmon: sending report (processed %v events)...\n", fanReport.EventCount)
		eventsChan <- fanReport
	}()

	return eventsChan
}