{ "info": { "author": "Danny Shemesh (dany74q)", "author_email": "dany74q@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "## PyEBPF\r\n\r\nA bcc-based, eBPF (Extended-Berkeley-Packet-Filter) wrapper for Python.\r\n\r\n*Note*: Using this library requires a working installation of BCC, please refer to this [guide](https://github.com/iovisor/bcc/blob/master/INSTALL.md).\r\n\r\nThis small library serves two main purposes:\r\n\r\n1. It lets you attach BPF kernel probes without writing native code\r\n2. It lets you write BPF routine callbacks in Python [1]\r\n\r\nYou may still write, compile and use your native routines \r\njust as you would have with bcc's BPF library, in case you need the functionality.\r\n\r\n[1] See 'How does this library work ?' below\r\n\r\n### What is eBPF\r\n\r\nExtended-Berkeley-Packet-Filters are a superset of BPF filters (traditionally available for packet-filtering), that lets you \r\nwrite small kernel-routines, using a dedicated eBPF instruction set.\r\n\r\nTo use eBPF, one needs to compile a routine, call the bpf(2) syscall, and attach a kernel-probe.\r\n\r\nbpf(2) will make sure to take your compiled routine, statically analyze and jit it, and \r\nthen copy it to kernel space for later use.\r\n\r\nYou attach a probe to a kernel trace event (such as a syscall invocation),\r\nand once your probe is attached, your eBPF routine will be invoked appropriately.\r\n\r\nSharing data between eBPF routines, or between an eBPF routine and user-space, is possible via eBPF maps,\r\nwhich operate on top of a FD that lets one communicate between those two ends.\r\n\r\n### What is IOVisor / BCC\r\n\r\nBCC (BPF Compiler Collection) is a toolkit that helps you generate and use BPF routine in a user-friendly manner.\r\n\r\nIt abstracts some eBPF features (such as BPF shared data structures) via C-Macros,\r\nand lets you focus on your routine's logic, and gathering appropriate metrics.\r\n\r\nCode generation is managed by LLVM, hence you need an appropriate version installed.\r\n\r\nMore about the project [here](https://github.com/iovisor/bcc). \r\n\r\n### How does this library work ?\r\n\r\nGiven an event to attach a kernel-probe to, this library will (In order):\r\n\r\n1. Try to implicitly guess any extra parameters the event passes to your routine.\r\nThis is done best-effortly, by reading the */sys/kernel/debug/tracing/events/syscalls/sys_enter_/format* file.\r\nThis file contains a text description of the parameters the event-trace may contain.\r\n\r\n2. It will then generate a crafted native data structure, that will be populated with relevant context, including:\r\n - Current time in nanosecond (via bpf_ktime_get_ns)\r\n - PID and TID (via bpf_get_current_pid_tgid)\r\n - GID and UID (via bpf_get_current_uid_gid)\r\n - Process name (via bpf_get_current_comm)\r\n - Any extra implicitly guessed event-trace parameters\r\n e.g. for the *bind* syscall, the data structure will additionally contain a: socket FD, socket address and address length\r\n\r\n3. It will create an eBPF shared data-structure (using the BPF_PERF_OUTPUT macro) that will be used as the communication\r\ngateway with user mode routine\r\n\r\n4. A dedicated polling daemon thread will be spawned, and for each output to the shared structure above, your python\r\ncallback will be invoked, passing it a ctypes class representing the native data structure\r\n\r\nThus, on any event your kernel probe attaches to, an internal BPF routine will be called, and in turn\r\nit will copy all relevant members via the constructed data structure back to user mode via the BPF structure. \r\nThen, an internal python thread will poll on said structure, and will call the registered python callback. \r\n\r\n### Using this wrapper effectively\r\n\r\nFirst, install the library via:\r\n\r\n$> pip install pyebpf\r\n\r\nNext, import the EBPFWrapper object, instantiate it, and attach a function to an event.\r\n\r\n```python\r\n# trace_fields.py bcc example, using pyebpf\r\n\r\n\r\nb = EBPFWrapper()\r\nprint 'PID MESSAGE'\r\n\r\ndef hello(data, **kwargs):\r\n print '{pid} Hello, World!'.format(pid=data.process_id)\r\n\r\nb.attach_kprobe(event=b.get_syscall_fnname('clone'), fn=hello)\r\n\r\nwhile True:\r\n try:\r\n time.sleep(1)\r\n except KeyboardInterrupt:\r\n print 'Bye !'\r\n break\r\n\r\nb = EBPFWrapper()\r\nprint 'COMM PID SOCKETFD'\r\n\r\ndef on_bind(data, **kwargs):\r\n print '{comm} {pid} {fd}'.format(comm=data.process_name, pid=data.process_id, fd=data.fd, addr=data.umyaddr)\r\n\r\nb.attach_kprobe(event=b.get_syscall_fnname('bind'), fn=on_bind)\r\n\r\n# Will print 'python '\r\ns = socket()\r\ns.bind(('0.0.0.0', 31337))\r\n\r\nwhile True:\r\n try:\r\n time.sleep(1)\r\n except KeyboardInterrupt:\r\n print 'Bye !'\r\n break\r\n\r\n# Supplying a native route\r\n\r\nfrom pyebpf.ebpf_wrapper import EBPFWrapper\r\n\r\nprog = '''\r\nint hello(struct pt_regs* ctx) {\r\n bpf_trace_printk(\"Hello from eBPF routine!\\\\n\");\r\n return 0;\r\n}\r\n'''\r\nb = EBPFWrapper(text=prog)\r\nb.attach_kprobe(event='sys_open', fn_name='hello')\r\n\r\nwhile True:\r\n try:\r\n print b.trace_fields()\r\n except KeyboardInterrupt:\r\n print 'Bye !'\r\n break\r\n```\r\n\r\n### eBPF related resources\r\n\r\nHere are a few eBPF-related resources that I found useful during the writing of this library:\r\n\r\n1. http://www.brendangregg.com/ebpf.html\r\n2. https://bolinfest.github.io/opensnoop-native\r\n3. https://github.com/iovisor/bcc\r\n4. https://lwn.net/Articles/740157/\r\n\r\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/dany74q/pyebpf", "keywords": "bpf ebpf", "license": "", "maintainer": "", "maintainer_email": "", "name": "pyebpf", "package_url": "https://pypi.org/project/pyebpf/", "platform": "", "project_url": "https://pypi.org/project/pyebpf/", "project_urls": { "Bug Reports": "https://github.com/dany74q/pyebpf/issues", "Homepage": "https://github.com/dany74q/pyebpf", "Source": "https://github.com/dany74q/pyebpf/" }, "release_url": "https://pypi.org/project/pyebpf/1.0.4/", "requires_dist": null, "requires_python": "", "summary": "A bcc-based Python eBPF (Extended-Berkeley-Packet-Filter) wrapper", "version": "1.0.4" }, "last_serial": 4716503, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "27a81852b3599921e4a911f730322397", "sha256": "540125e17aee38ba90a9222d4f456aeb3a617fef00e67fdcee93bf405187e147" }, "downloads": -1, "filename": "pyebpf-1.0.0-py2-none-any.whl", "has_sig": false, "md5_digest": "27a81852b3599921e4a911f730322397", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 3414, "upload_time": "2019-01-19T16:41:46", "url": "https://files.pythonhosted.org/packages/11/cd/c0321a641d56482f6ed5345cfe738640b7364b850f878dfc89c5037babd4/pyebpf-1.0.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e8e5466aea7d3bfadf3b4cc334d53944", "sha256": "0a2ea5f6a04849133fbb4bbac2d02b19dd540f976cdef7ab61e9b50c9c09bebe" }, "downloads": -1, "filename": "pyebpf-1.0.0.tar.gz", "has_sig": false, "md5_digest": "e8e5466aea7d3bfadf3b4cc334d53944", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3880, "upload_time": "2019-01-19T16:41:49", "url": "https://files.pythonhosted.org/packages/1b/77/9fd3cbcec7b8bd65a1121db59655796ac4cf299b3df6a4b5aa2dc9c5ca69/pyebpf-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "bdce97f15c1d3db0385e8e80da436b90", "sha256": "b6038af94fc856715678037642bd4051db2d7c6cc3db3439f7e6caad155704b1" }, "downloads": -1, "filename": "pyebpf-1.0.1-py2-none-any.whl", "has_sig": false, "md5_digest": "bdce97f15c1d3db0385e8e80da436b90", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10792, "upload_time": "2019-01-19T16:49:32", "url": "https://files.pythonhosted.org/packages/86/bd/1a3284677c703deb325411055d969752637d2a2893db237e6c9d2c3e21fb/pyebpf-1.0.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "dd194c237b2aacdee8e08a8b312f8c13", "sha256": "761491f9d6d070780f57e83e9f22173a0f9938f584c94b805825c40141bb266b" }, "downloads": -1, "filename": "pyebpf-1.0.1.tar.gz", "has_sig": false, "md5_digest": "dd194c237b2aacdee8e08a8b312f8c13", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12484, "upload_time": "2019-01-19T16:49:35", "url": "https://files.pythonhosted.org/packages/f3/33/00da6e87b7e139bc7618307144e47c7f3b0cc6cbe94a13f5177e8830c360/pyebpf-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "90575cf7a0e9888012e98f867058ce52", "sha256": "fbf0143e3c8bb4e9a8c79333eade98cc85bd7cb90b7c4d8d98693b439eec328c" }, "downloads": -1, "filename": "pyebpf-1.0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "90575cf7a0e9888012e98f867058ce52", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10780, "upload_time": "2019-01-19T20:38:22", "url": "https://files.pythonhosted.org/packages/90/51/882400201f063e276f57b2e844d2e44e824cd1723d16c9932eb9c220381b/pyebpf-1.0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5d715cbfed3a8139dc926a5a08861872", "sha256": "8e4f580bbf269a591e6c6603910eac3be2b64ac855f8bd76bba4295d04d3aa02" }, "downloads": -1, "filename": "pyebpf-1.0.2.tar.gz", "has_sig": false, "md5_digest": "5d715cbfed3a8139dc926a5a08861872", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12485, "upload_time": "2019-01-19T20:38:24", "url": "https://files.pythonhosted.org/packages/70/7b/75a8ab8523ac3d1a6d6097120210aabf5a9da61b9efa83af90f3d945e367/pyebpf-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "e5469d1ffb1d0b84b0a95b09f710fc89", "sha256": "815a3a998e687d3d68cff0d58c04e6ea6e35e96168f25add70cc14c17d422c0c" }, "downloads": -1, "filename": "pyebpf-1.0.3-py2-none-any.whl", "has_sig": false, "md5_digest": "e5469d1ffb1d0b84b0a95b09f710fc89", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10765, "upload_time": "2019-01-19T20:43:26", "url": "https://files.pythonhosted.org/packages/35/77/315d834d4011be23adbf22c1311d119d2fd8ab343e441cf11825331211c5/pyebpf-1.0.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e100bf2bf4f3b16d6f5a8773c8c72171", "sha256": "e4f682fddc5eaf4fb4a6246ea5370e82c6b1d6711eda2acda9d300e5ff88cb8a" }, "downloads": -1, "filename": "pyebpf-1.0.3.tar.gz", "has_sig": false, "md5_digest": "e100bf2bf4f3b16d6f5a8773c8c72171", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12364, "upload_time": "2019-01-19T20:43:27", "url": "https://files.pythonhosted.org/packages/1c/21/1025e8925bc053e70b424cd0ea75ddc74135f9c96727ff68b067b746a3b8/pyebpf-1.0.3.tar.gz" } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "164a19626c2d12e34a3c53a55ebee43b", "sha256": "606a214006ed27a0cb4639b6557f6851a5cc676d5f4d59a97fd6343dc0df1fd9" }, "downloads": -1, "filename": "pyebpf-1.0.4-py2-none-any.whl", "has_sig": false, "md5_digest": "164a19626c2d12e34a3c53a55ebee43b", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10858, "upload_time": "2019-01-19T20:48:21", "url": "https://files.pythonhosted.org/packages/2c/07/f1c189d3f26fa842ea99400a3ff0db847213aa5781a0e8e9ff5d745f7a21/pyebpf-1.0.4-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e624f38fd73e2596270910ab33ca3184", "sha256": "f563cc0e1759b165d89aab03db01252cc2b4c40805f6bd32485fdcb710584bb0" }, "downloads": -1, "filename": "pyebpf-1.0.4.tar.gz", "has_sig": false, "md5_digest": "e624f38fd73e2596270910ab33ca3184", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12666, "upload_time": "2019-01-19T20:48:22", "url": "https://files.pythonhosted.org/packages/09/7a/ec23a0851d39adb1997f38be10857dabca2affba3cb4664d0b66efbc4cd0/pyebpf-1.0.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "164a19626c2d12e34a3c53a55ebee43b", "sha256": "606a214006ed27a0cb4639b6557f6851a5cc676d5f4d59a97fd6343dc0df1fd9" }, "downloads": -1, "filename": "pyebpf-1.0.4-py2-none-any.whl", "has_sig": false, "md5_digest": "164a19626c2d12e34a3c53a55ebee43b", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10858, "upload_time": "2019-01-19T20:48:21", "url": "https://files.pythonhosted.org/packages/2c/07/f1c189d3f26fa842ea99400a3ff0db847213aa5781a0e8e9ff5d745f7a21/pyebpf-1.0.4-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e624f38fd73e2596270910ab33ca3184", "sha256": "f563cc0e1759b165d89aab03db01252cc2b4c40805f6bd32485fdcb710584bb0" }, "downloads": -1, "filename": "pyebpf-1.0.4.tar.gz", "has_sig": false, "md5_digest": "e624f38fd73e2596270910ab33ca3184", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12666, "upload_time": "2019-01-19T20:48:22", "url": "https://files.pythonhosted.org/packages/09/7a/ec23a0851d39adb1997f38be10857dabca2affba3cb4664d0b66efbc4cd0/pyebpf-1.0.4.tar.gz" } ] }