Technische Universität Braunschweig
  • Study & Teaching
    • Beginning your Studies
      • Prospective Students
      • Degree Programmes
      • Application
      • Fit4TU
      • Why Braunschweig?
    • During your Studies
      • Fresher's Hub
      • Term Dates
      • Courses
      • Practical Information
      • Beratungsnavi
      • Additional Qualifications
      • Financing and Costs
      • Special Circumstances
      • Health and Well-being
      • Campus life
    • At the End of your Studies
      • Discontinuation and Credentials Certification
      • After graduation
      • Alumni*ae
    • For Teaching Staff
      • Strategy, Offers and Information
      • Learning Management System Stud.IP
    • Contact
      • Study Service Centre
      • Academic Advice Service
      • Student Office
      • Career Service
  • Research
    • Research Profile
      • Core Research Areas
      • Clusters of Excellence at TU Braunschweig
      • Research Projects
      • Research Centres
      • Professors‘ Research Profiles
    • Early Career Researchers
      • Support in the early stages of an academic career
      • PhD-Students
      • Postdocs
      • Junior research group leaders
      • Junior Professorship and Tenure-Track
      • Habilitation
      • Service Offers for Scientists
    • Research Data & Transparency
      • Transparency in Research
      • Research Data
      • Open Access Strategy
      • Digital Research Announcement
    • Research Funding
      • Research Funding Network
      • Research funding
    • Contact
      • Research Services
      • Academy for Graduates
  • International
    • International Students
      • Why Braunschweig?
      • Degree seeking students
      • Exchange Studies
      • TU Braunschweig Summer School
      • Refugees
      • International Student Support
    • Going Abroad
      • Studying abroad
      • Internships abroad
      • Teaching and research abroad
      • Working abroad
    • International Researchers
      • Welcome Support
      • PhD Studies
      • Service for host institutes
    • Language and intercultural competence training
      • Learning German
      • Learning Foreign Languages
      • Intercultural Communication
    • International Profile
      • Internationalisation
      • International Cooperations
      • Strategic Partnerships
      • International networks
    • International House
      • About us
      • Contact & Office Hours
      • News and Events
      • International Days
      • 5th Student Conference: Internationalisation of Higher Education
      • Newsletter, Podcast & Videos
      • Job Advertisements
  • TU Braunschweig
    • Our Profile
      • Aims & Values
      • Regulations and Guidelines
      • Alliances & Partners
      • The University Development Initiative 2030
      • Foundation University
      • Facts & Figures
      • Our History
    • Career
      • Working at TU Braunschweig
      • Vacancies
    • Economy & Business
      • Entrepreneurship
      • Friends & Supporters
    • General Public
      • Check-in for Students
      • The Student House
      • Access to the University Library
    • Media Services
      • Communications and Press Service
      • Services for media
      • Film and photo permits
      • Advices for scientists
      • Topics and stories
    • Contact
      • General Contact
      • Getting here
  • Organisation
    • Presidency & Administration
      • Executive Board
      • Designated Offices
      • Administration
      • Committees
    • Faculties
      • Carl-Friedrich-Gauß-Fakultät
      • Faculty of Life Sciences
      • Faculty of Architecture, Civil Engineering and Environmental Sciences
      • Faculty of Mechanical Engineering
      • Faculty of Electrical Engineering, Information Technology, Physics
      • Faculty of Humanities and Education
    • Institutes
      • Institutes from A to Z
    • Facilities
      • University Library
      • Gauß-IT-Zentrum
      • Professional and Personnel Development
      • International House
      • The Project House of the TU Braunschweig
      • Transfer Service
      • University Sports Center
      • Facilities from A to Z
    • Equal Opportunity Office
      • Equal Opportunity Office
      • Family
      • Diversity for Students
  • Search
  • Quicklinks
    • People Search
    • Webmail
    • cloud.TU Braunschweig
    • Messenger
    • Cafeteria
    • Courses
    • Stud.IP
    • Library Catalogue
    • IT Services
    • Information Portal (employees)
    • Link Collection
    • DE
    • EN
    • IBR YouTube
    • Facebook
    • Instagram
    • YouTube
    • LinkedIn
    • Mastodon
Menu
  • Organisation
  • Faculties
  • Carl-Friedrich-Gauß-Fakultät
  • Institutes
  • Institute of Operating Systems and Computer Networks
  • Prof. Dr.-Ing. Christian Dietrich
  • Advent(2)
  • Don't Dip Your Fingers into the Sauce!
Logo IBR
IBR Login
  • Institute of Operating Systems and Computer Networks
    • News
    • About us
      • Whole Team
      • Directions
      • Floor Plan
      • Projects
      • Publications
      • Software
      • News Archive
    • Connected and Mobile Systems
      • Team
      • Courses
      • Theses
      • Projects
      • Publications
      • Software
      • Datasets
    • Reliable System Software
      • Overview
      • Team
      • Teaching
      • Theses & Jobs
      • Research
      • Publications
    • Algorithms
      • Team
      • Courses
      • Theses
      • Projects
      • Publications
    • Microprocessor Lab
    • Education
      • Summer 2025
      • Winter 2024/2025
      • Theses
    • Services
      • Library
      • Mailinglists
      • Webmail
      • Knowledge Base
      • Wiki
      • Account Management
      • Services Status
    • Spin-Offs
      • Docoloc
      • bliq (formerly AIPARK)
      • Confidential Technologies
    • Research Cooperations
      • IST.hub
  • Task Overview
  • Git repository
  • Mailing list
  • Matrix-Channel

Don't Dip Your Fingers into the Sauce!

☃️
Git-Repository: Template Solution Solution-Diff (Solution is posted at 18:00 CET)
Workload: 52 lines of code
Important System-Calls: process_vm_readv(2), process_vm_writev(2)
Recommended Reads:
  • Dec. 8: Wishlist Sorting file 61 lines [readv(2), writev(2), preadv(2), pwritev(2)]
  • Dec. 18: A Trace of Cookie Crumbs process 63 lines [ptrace(2)]
Illustration for this exercsie

The ELFs that produce the different gifts are well on track with their duties, but all that wood turning, gluing, cropping, and sewing makes for a very hungry crowd of exhausted ELFs. For these ELFs, the Christmas village has a large but very good ELF canteen, where all kinds of treats are available. One of the most wanted goodies are the dumplings with sweet sauce. But, for today, the kitchen was a little bit slow and the hungry crowd is demanding their dumplings and are eager to get their fingers on that delicious sauce. While there are very solid walls around the kitchen, there are a few loopholes that the ELF crowd wants to exploit. However, only a finger can fit into those loopholes and you have to find the sauce pot blindly. Can you help them?

process_vm_{readv,writev}

With ptrace(2), we already know a very powerful tool to manipulate and control the run time state of another process. We can stop processes, poke around their registers, and access the remote process' memory. However, the access path is more like the eye of an needle, as we have to PTRACE_PEEKUSER and PTRACE_POKEUSER individual words (e.g. 64 bits) from/into the other process' address space. So, reading the entire memory would take an enormous amount of system calls.

For debugging purposes, this is no real limitation, but for some applications, ptrace was no option and a better interface was needed. One such application is CRIU (Checkpoint-Restore-In-Userspace), which allows the user to snapshot a running application into a collection of files and restore the process later on as if the process was only paused. It is even possible to transfer the snapshot to another machine and restart it there. CRIU is a very useful tool for containerized environments, where your "microservice" boils down to a Linux process that runs in its own VM/FS/network/user namespace. To get it's hands on the run-time state of the process that should be checkpointed, CRIU uses the process_vm_readv(2) system call.

   ssize_t process_vm_readv(pid_t pid,
                           const struct iovec *local_iov,  unsigned long liovcnt,
                           const struct iovec *remote_iov, unsigned long riovcnt,
                           unsigned long flags);

The system call, which has also a writing pendant with process_vm_writev(2), has a straight forward interface. It takes the pid of the remote process and two scattered buffers that describe areas in the remote address space (remote_iov, riovcnt) and in the local address space (local_iov, liovcnt). When invoked, the system call then copies the contents of the remote area into the local area. For example:

char buf[0x400];
struct iovec local[1] = {
    {.iov_base = buf, .iov_len = sizeof(buf)}
};
struct iovec remote[2] = {
    {.iov_base = 0x1000, .iov_len = 0x100},
    {.iov_base = 0x4000, .iov_len = 0x300},
}

process_vm_readv(1234, local, 1, remote, 2, 0);

With this piece of code, you read 0x400 bytes of memory into a buffer in your process. The source is the address space of process with the pid 1234 and we copy the bytes: [0x1000, 0x10ff] and [0x4000, 0x42ff]. As you already see from the example, it is rather easy to come up with the pointers for local_iov as they are in your own process. The pointers within the remote process are rather hard to guess though. For this, one can use ptrace() or information from the proc file system. For example, in /proc/1234/maps, we see all memory mappings of our remote process:

$ cat /proc/1234/maps
555b377ea000-555b37857000 r--p 00000000 103:04 16254201                  /usr/bin/python3.10
555b37857000-555b37afa000 r-xp 0006d000 103:04 16254201                  /usr/bin/python3.10
555b37afa000-555b37d3a000 r--p 00310000 103:04 16254201                  /usr/bin/python3.10
555b37d3a000-555b37d40000 r--p 00550000 103:04 16254201                  /usr/bin/python3.10
555b37d40000-555b37d80000 rw-p 00556000 103:04 16254201                  /usr/bin/python3.10
555b37d80000-555b37dc6000 rw-p 00000000 00:00 0 
[...]
7fffd57c3000-7fffd57e5000 rw-p 00000000 00:00 0                          [stack]
7fffd57f6000-7fffd57fa000 r--p 00000000 00:00 0                          [vvar]
7fffd57fa000-7fffd57fc000 r-xp 00000000 00:00 0                          [vdso]

What we see here, are memory areas (first range) that are mapped (see A Map to Persistance!) in the python process. We see the memory protection bits (e.g. rw-p), the size of the mapping (e.g. 00310000), the device id of the hard disk (e.g 103:04) where the file resides, the inode number of the file (e.g., 16254201), and the name of the file (e.g., /usr/bin/python3.10). So the first few lines of this listing, show those memory areas where the Python program was mapped into this Python process.

Task

Today, we want to toy around with process_vm_readv and process_vm_writev to peek and poke around in the memory of a running python3 process. We chose the CPython interpreter for this exercise as it is rather easy to get your hands onto the pointer of some object. In CPython3, which is probably the variant of Python that is installed on you computer, the id() function returns a rather useful value ($ pydoc3 id):

id(obj, /)
    Return the identity of an object.

    This is guaranteed to be unique among simultaneously existing objects.
    (CPython uses the object's memory address.)

So, when we use id() on an object, we get the address of that object in memory. So it is today's task, to use that information to get the memory of some object from a Python process and decode them. Furthermore, with process_vm_writev you can also manipulate those objects. For example, change the value of a floating point object. For your convenience, we already bring you a small test.py script:

$ python3 test.py 
pointers ['0x7f75917fdad0', '0x7f75917fe6f0', '0x7f75917fe6f0']
objects ['0xdeadbeef', 23.0, 23.0]
>>  PyObject @ 0x7f75917fdad0: refcount=3, type=int
>>  PyLongObject: ob_digit[0] = 0x1eadbeef
>>  PyObject @ 0x7f75917fe6f0: refcount=4, type=float
>>  PyFloatObject: ob_fval=23.000000
object ['0xdeadabba', 529.0, 529.0]

In this output, the >>-prefixed lines are from the remote process, while the python process printed those other three lines. In the output we also see that we quadrupled the value of D (23 -> 529). You might ask yourself, why the value of D2 also changed here. But answering that question is up to you. (Hint: Look at the pointers).

Hints

  • You will need the python3 development files to get your hands onto the Python header files. On Debian, they are in the python3-dev package. With pkg-config --cflags python3, you can test whether you have the headers correctly installed. On my machine, this results in:

    $ pkg-config --cflags python3
    -I/usr/include/python3.10 -I/usr/include/x86_64-linux-gnu/python3.10
    
  • As you have to interpret untyped memory, you will have to use the python3-dev headers to get the C types that interpret that memory. Useful C types for you today are PyObject (any python object), PyTypeObject (objects that represent types), PyFloatObject (a floating point number), and PyLongObject (an integer number). In a nutshell, you will just cast the untyped memory from peek() to those types and use them:

    PyObject *obj      = peek(pid, ptr, sizeof(PyObject));
    printf("  PyObject @ %p: refcount=%ld\n", ptr, Py_REFCNT(obj));
    
  • Have a look at the header files in /usr/include/python3.10/. A good starting point are the declarations of PyObject and PyVarObject in object.h (/usr/include/python3.10/object.h).

Last modified: 2023-12-01 15:52:27.583349, Last author: , Permalink: /p/advent-20-vmreadv


last changed 2023-12-01, 15:52 by Prof. Dr.-Ing. Christian Dietrich

For All Visitors

Vacancies of TU Braunschweig
Career Service' Job Exchange 
Merchandising

For Students

Term Dates
Courses
Degree Programmes
Information for Freshman
TUCard

Internal Tools

Glossary (GER-EN)
Change your Personal Data

Contact

Technische Universität Braunschweig
Universitätsplatz 2
38106 Braunschweig

P. O. Box: 38092 Braunschweig
GERMANY

Phone: +49 (0) 531 391-0

Getting here

© Technische Universität Braunschweig
Imprint Privacy Accessibility