Hello community, here is the log from the commit of package reptyr for openSUSE:Factory checked in at 2018-12-12 17:28:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/reptyr (Old) and /work/SRC/openSUSE:Factory/.reptyr.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "reptyr" Wed Dec 12 17:28:02 2018 rev:11 rq:655903 version:0.7.0 Changes: -------- --- /work/SRC/openSUSE:Factory/reptyr/reptyr.changes 2017-03-20 17:10:09.308851825 +0100 +++ /work/SRC/openSUSE:Factory/.reptyr.new.28833/reptyr.changes 2018-12-12 17:28:03.846908871 +0100 @@ -1,0 +2,17 @@ +Thu Dec 6 00:19:42 UTC 2018 - Jan Engelhardt <jeng...@inai.de> + +- Use %make_install. + +------------------------------------------------------------------- +Wed Dec 5 05:27:04 UTC 2018 - Martin Herkt <9+suse@cirno.systems> + +- Update to version 0.7.0 + * Add bash completion support + * Fix compilation with musl libc, CentOS, or GCC 7+ + * Support for PowerPC and aarch64 +- Drop patches + 0001-Placate-a-gcc7-warning.patch + 0002-Include-sysmacros.h.patch + 0003-Build-with-fstrict-aliasing.patch + +------------------------------------------------------------------- Old: ---- 0001-Placate-a-gcc7-warning.patch 0002-Include-sysmacros.h.patch 0003-Build-with-fstrict-aliasing.patch reptyr-0.6.2.tar.gz New: ---- reptyr-0.7.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ reptyr.spec ++++++ --- /var/tmp/diff_new_pack.jHpsDy/_old 2018-12-12 17:28:04.330908257 +0100 +++ /var/tmp/diff_new_pack.jHpsDy/_new 2018-12-12 17:28:04.334908252 +0100 @@ -1,7 +1,7 @@ # # spec file for package reptyr # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,24 +12,20 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # Name: reptyr -Version: 0.6.2 +Version: 0.7.0 Release: 0 Summary: A tool for "re-ptying" programs License: MIT Group: System/Console -Url: http://github.com/nelhage/reptyr +URL: http://github.com/nelhage/reptyr Source: https://github.com/nelhage/reptyr/archive/%{name}-%{version}.tar.gz -Patch0: 0001-Placate-a-gcc7-warning.patch -Patch1: 0002-Include-sysmacros.h.patch -Patch2: 0003-Build-with-fstrict-aliasing.patch +BuildRequires: bash-completion BuildRequires: gcc -BuildRoot: %{_tmppath}/%{name}-%{version}-build -ExclusiveArch: %{ix86} x86_64 %{arm} %description reptyr is a utility for taking an existing running program and @@ -40,23 +36,21 @@ %prep %setup -q -n %{name}-%{name}-%{version} -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 %build export CFLAGS="%{optflags}" export CXXFLAGS="%{optflags}" -make +make %{?_smp_mflags} %install -make PREFIX="%{buildroot}%{_prefix}" install +%make_install PREFIX="%{_prefix}" BASHCOMPDIR="%{_datadir}/bash-completion/completions" %files -%defattr(-,root,root) -%doc ChangeLog COPYING README.md NOTES -%doc %{_mandir}/man1/reptyr.1%{ext_man} -%doc %{_mandir}/fr/man1/reptyr.1%{ext_man} +%doc ChangeLog README.md NOTES +%license COPYING +%{_mandir}/man1/reptyr.1%{?ext_man} +%{_mandir}/fr/man1/reptyr.1%{?ext_man} %{_bindir}/reptyr +%{_datadir}/bash-completion/completions/reptyr %changelog ++++++ reptyr-0.6.2.tar.gz -> reptyr-0.7.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/.travis.yml new/reptyr-reptyr-0.7.0/.travis.yml --- old/reptyr-reptyr-0.6.2/.travis.yml 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/.travis.yml 2018-12-05 04:48:42.000000000 +0100 @@ -1,7 +1,15 @@ script: make test +sudo: required +language: python +python: + - "2.7" +install: + - env -u CFLAGS -u LDFLAGS pip install -r test/requirements.txt +addons: + apt: + packages: + - gcc-multilib + - libcap-dev env: - CFLAGS=-m32 LDFLAGS=-m32 DISABLE_TESTS=1 - CFLAGS=-m64 LDFLAGS=-m64 -before_install: - - sudo apt-get update - - sudo apt-get -y install gcc-multilib python-pexpect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/ChangeLog new/reptyr-reptyr-0.7.0/ChangeLog --- old/reptyr-reptyr-0.6.2/ChangeLog 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/ChangeLog 2018-12-05 04:48:42.000000000 +0100 @@ -1,3 +1,8 @@ +* 0.7.0 (Dec 05, 2018) + - Add bash completion support + - Fix compilation with musl libc, CentOS, or GCC 7+ + - Support for PowerPC and aarch64 + * 0.6.2 (Jan 31, 2015) - Fix tty-stealing on i386 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/Makefile new/reptyr-reptyr-0.7.0/Makefile --- old/reptyr-reptyr-0.6.2/Makefile 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/Makefile 2018-12-05 04:48:42.000000000 +0100 @@ -1,4 +1,4 @@ -override CFLAGS+=-Wall -Werror -D_GNU_SOURCE -g +override CFLAGS := -Wall -Werror -D_GNU_SOURCE -g $(CFLAGS) OBJS=reptyr.o reallocarray.o attach.o UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) @@ -8,11 +8,15 @@ OBJS += platform/freebsd/freebsd_ptrace.o platform/freebsd/freebsd.o LDFLAGS += -lprocstat endif -# Note that because of how Make works, this can be overriden from the +# Note that because of how Make works, this can be overridden from the # command-line. # # e.g. install to /usr with `make PREFIX=/usr` PREFIX=/usr/local +BINDIR=$(PREFIX)/bin +MANDIR=$(PREFIX)/share/man + +PKG_CONFIG ?= pkg-config all: reptyr @@ -20,8 +24,8 @@ ifeq ($(DISABLE_TESTS),) test: reptyr test/victim PHONY - python test/basic.py - python test/tty-steal.py + python2 test/basic.py + python2 test/tty-steal.py else test: all endif @@ -39,12 +43,18 @@ clean: rm -f reptyr $(OBJS) test/victim.o test/victim +BASHCOMPDIR ?= $(shell $(PKG_CONFIG) --variable=completionsdir bash-completion 2>/dev/null) + install: reptyr - install -d -m 755 $(DESTDIR)$(PREFIX)/bin/ - install -m 755 reptyr $(DESTDIR)$(PREFIX)/bin/reptyr - install -d -m 755 $(DESTDIR)$(PREFIX)/share/man/man1 - install -m 644 reptyr.1 $(DESTDIR)$(PREFIX)/share/man/man1/reptyr.1 - install -d -m 755 $(DESTDIR)$(PREFIX)/share/man/fr/man1 - install -m 644 reptyr.fr.1 $(DESTDIR)$(PREFIX)/share/man/fr/man1/reptyr.1 + install -d -m 755 $(DESTDIR)$(BINDIR) + install -m 755 reptyr $(DESTDIR)$(BINDIR)/reptyr + install -d -m 755 $(DESTDIR)$(MANDIR)/man1 + install -m 644 reptyr.1 $(DESTDIR)$(MANDIR)/man1/reptyr.1 + install -d -m 755 $(DESTDIR)$(MANDIR)/fr/man1 + install -m 644 reptyr.fr.1 $(DESTDIR)$(MANDIR)/fr/man1/reptyr.1 + bashcompdir=$(BASHCOMPDIR) ; \ + test -z "$$bashcompdir" && bashcompdir=/etc/bash_completion.d ; \ + install -d -m 755 $(DESTDIR)$$bashcompdir ; \ + install -m 644 reptyr.bash $(DESTDIR)$$bashcompdir/reptyr .PHONY: PHONY diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/README.md new/reptyr-reptyr-0.7.0/README.md --- old/reptyr-reptyr-0.6.2/README.md 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/README.md 2018-12-05 04:48:42.000000000 +0100 @@ -21,6 +21,21 @@ terminal. This is likely impossible to fix in a reasonable way without patching your shell.) +Typical usage pattern +--------------------- + +* Start a long running process, e.g. `top` +* Background the process with CTRL-Z +* Resume the process in the background: `bg` +* Display your running background jobs with `jobs -l`, this should look like this: + * `[1]+ 4711 Stopped (signal) top` + * (The `-l` in `jobs -l` makes sure you'll get the PID) +* Disown the jobs from the current parent with `disown top`. After that, `jobs` will not show the job any more, but `ps -a` will. +* Start your terminal multiplexer of choice, e.g. `tmux` +* Reattach to the backgrounded process: `reptyr 4711` +* Detach your terminal multiplexer (e.g. CTRL-A D) and close ssh +* Reconnect ssh, attach to your multiplexer (e.g. `tmux attach`), rejoice! + "But wait, isn't this just screenify?" -------------------------------------- @@ -41,11 +56,16 @@ PORTABILITY ----------- -reptyr is Linux-only. It uses ptrace to attach to the target and control it at -the syscall level, so it is highly dependent on Linux's particular syscall API, -syscalls, and terminal ioctl()s. A port to Solaris or BSD may be technically -feasible, but would probably require significant re-architecting to abstract out -the platform-specific bits. +reptyr supports Linux and FreeBSD. Not all functionality is currently +available on FreeBSD. (Notably, FreeBSD doesn't support `reptyr -T` at +this time. + +`reptyr` uses ptrace to attach to the target and control it at the +syscall level, so it is highly dependent on details of the syscall +API, available syscalls, and terminal ioctl()s. A port to other +operating systems may be technically feasible, but requires +significant low-level knowledge of the relevant platform, and may +entail significant refactors. reptyr works on i386, x86_64, and ARM. Ports to other architectures should be straightforward, and should in most cases be as simple as adding an arch/ARCH.h @@ -98,4 +118,4 @@ URL --- -[http://github.com/nelhage/reptyr]() +http://github.com/nelhage/reptyr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/Vagrantfile new/reptyr-reptyr-0.7.0/Vagrantfile --- old/reptyr-reptyr-0.6.2/Vagrantfile 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/Vagrantfile 2018-12-05 04:48:42.000000000 +0100 @@ -23,6 +23,14 @@ machine.vm.box = 'chef/fedora-20' end + config.vm.define 'centos-6-x86_64' do |machine| + machine.vm.box = 'bento/centos-6.7' + end + + config.vm.define 'centos-5-x86_64' do |machine| + machine.vm.box = 'bento/centos-5.11' + end + config.vm.synced_folder ".", "/vagrant", type: 'nfs', id: 'vagrant-root' end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/attach.c new/reptyr-reptyr-0.7.0/attach.c --- old/reptyr-reptyr-0.6.2/attach.c 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/attach.c 2018-12-05 04:48:42.000000000 +0100 @@ -69,11 +69,19 @@ do_syscall(child, munmap, (unsigned long)addr, len, 0, 0, 0, 0); } +static int do_fork(struct ptrace_child *child) { + if (ptrace_syscall_numbers(child)->nr_fork != -1) { + return do_syscall(child, fork, 0, 0, 0, 0, 0, 0); + } else { + return do_syscall(child, clone, SIGCHLD, 0, 0, 0, 0, 0); + } +} + int do_setsid(struct ptrace_child *child) { int err = 0; struct ptrace_child dummy; - err = do_syscall(child, fork, 0, 0, 0, 0, 0, 0); + err = do_fork(child); if (err < 0) return err; @@ -109,12 +117,23 @@ out_kill: kill(dummy.pid, SIGKILL); + ptrace_wait(&dummy); ptrace_detach_child(&dummy); - //ptrace_wait(&dummy); do_syscall(child, wait4, dummy.pid, 0, WNOHANG, 0, 0, 0); return err; } +static int do_dup2(struct ptrace_child *child, int oldfd, int newfd) { + if (oldfd == newfd) { + return 0; + } + if (ptrace_syscall_numbers(child)->nr_dup2 != -1) { + return do_syscall(child, dup2, oldfd, newfd, 0, 0, 0, 0); + } else { + return do_syscall(child, dup3, oldfd, newfd, 0, 0, 0, 0); + } +} + int ignore_hup(struct ptrace_child *child, child_addr_t scratch_page) { int err; @@ -237,6 +256,16 @@ return err; } +int preflight_check(pid_t pid) { + struct ptrace_child child; + debug("Making sure we have permission to attach..."); + if (ptrace_attach_child(&child, pid)) { + return child.error; + } + ptrace_detach_child(&child); + return 0; +} + int attach_child(pid_t pid, const char *pty, int force_stdio) { struct ptrace_child child; child_addr_t scratch_page = -1; @@ -252,6 +281,10 @@ return err; } + if ((err = preflight_check(pid))) { + return err; + } + debug("Using tty: %s", pty); if ((err = copy_tty_state(pid, pty))) { @@ -302,9 +335,9 @@ goto out_free_fds; } - child_fd = do_syscall(&child, open, - scratch_page, O_RDWR | O_NOCTTY, - 0, 0, 0, 0); + child_fd = do_syscall(&child, openat, + -1, scratch_page, O_RDWR | O_NOCTTY, + 0, 0, 0); if (child_fd < 0) { err = child_fd; error("Unable to open the tty in the child."); @@ -336,7 +369,7 @@ debug("Set the controlling tty"); for (i = 0; i < n_fds; i++) { - err = do_syscall(&child, dup2, child_fd, child_tty_fds[i], 0, 0, 0, 0); + err = do_dup2(&child, child_fd, child_tty_fds[i]); if (err < 0) error("Problem moving child fd number %d to new tty: %s", child_tty_fds[i], strerror(errno)); } @@ -375,8 +408,11 @@ return errno; steal->addr_un.sun_family = AF_UNIX; - snprintf(steal->addr_un.sun_path, sizeof(steal->addr_un.sun_path), - "%s/reptyr.sock", steal->tmpdir); + if (snprintf(steal->addr_un.sun_path, sizeof(steal->addr_un.sun_path), + "%s/reptyr.sock", steal->tmpdir) >= sizeof(steal->addr_un.sun_path)) { + error("tmpdir path too long!"); + return ENAMETOOLONG; + } if ((steal->sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) return errno; @@ -384,9 +420,9 @@ if (bind(steal->sockfd, &steal->addr, sizeof(steal->addr_un)) < 0) return errno; - if (chown(steal->addr_un.sun_path, steal->target_stat.uid, steal->target_stat.gid) < 0) + if (chown(steal->addr_un.sun_path, steal->emulator_uid, -1) < 0) debug("chown %s: %s", steal->addr_un.sun_path, strerror(errno)); - if (chown(steal->tmpdir, steal->target_stat.uid, steal->target_stat.gid) < 0) + if (chown(steal->tmpdir, steal->emulator_uid, -1) < 0) debug("chown %s: %s", steal->tmpdir, strerror(errno)); return 0; @@ -484,7 +520,7 @@ // it doesn't die. int steal_block_hup(struct steal_pty_state *steal) { struct ptrace_child leader; - child_addr_t scratch; + child_addr_t scratch = 0; int err = 0; if ((err = grab_pid(steal->target_stat.sid, &leader, &scratch))) @@ -505,14 +541,14 @@ return steal->child.error; } - int nullfd = do_syscall(&steal->child, open, steal->child_scratch, O_RDWR, 0, 0, 0, 0); + int nullfd = do_syscall(&steal->child, openat, -1, steal->child_scratch, O_RDWR, 0, 0, 0); if (nullfd < 0) { return steal->child.error; } int i; for (i = 0; i < steal->master_fds.n; ++i) { - do_syscall(&steal->child, dup2, nullfd, steal->master_fds.fds[i], 0, 0, 0, 0); + do_dup2(&steal->child, nullfd, steal->master_fds.fds[i]); } do_syscall(&steal->child, close, nullfd, 0, 0, 0, 0, 0); @@ -532,6 +568,9 @@ struct steal_pty_state steal = {}; long page_size = sysconf(_SC_PAGE_SIZE); + if ((err = preflight_check(pid))) + goto out; + if ((err = get_terminal_state(&steal, pid))) goto out; @@ -539,6 +578,7 @@ goto out; debug("Listening on socket: %s", steal.addr_un.sun_path); + debug("Attaching terminal emulator pid=%d", steal.emulator_pid); if ((err = grab_pid(steal.emulator_pid, &steal.child, &steal.child_scratch))) goto out; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/freebsd/arch/default-syscalls.h new/reptyr-reptyr-0.7.0/platform/freebsd/arch/default-syscalls.h --- old/reptyr-reptyr-0.6.2/platform/freebsd/arch/default-syscalls.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/freebsd/arch/default-syscalls.h 2018-12-05 04:48:42.000000000 +0100 @@ -1,14 +1,11 @@ #define SC(name) .nr_##name = SYS_##name { -#ifdef SYS_mmap - SC(mmap), -#else - .nr_mmap = -1, -#endif #ifdef SYS_mmap2 + .nr_mmap = -1, SC(mmap2), #else + SC(mmap), .nr_mmap2 = -1, #endif SC(munmap), @@ -16,6 +13,7 @@ SC(setsid), SC(setpgid), SC(fork), + .nr_clone = -1, SC(wait4), #ifdef SYS_signal SC(signal), @@ -23,10 +21,11 @@ .nr_signal = -1, #endif .nr_rt_sigaction = SYS_sigaction, - SC(open), + SC(openat), SC(close), SC(ioctl), SC(dup2), + .nr_dup3 = -1, #ifdef SYS_socketcall SC(socketcall), #else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/freebsd/arch/x86_common.h new/reptyr-reptyr-0.7.0/platform/freebsd/arch/x86_common.h --- old/reptyr-reptyr-0.6.2/platform/freebsd/arch/x86_common.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/freebsd/arch/x86_common.h 2018-12-05 04:48:42.000000000 +0100 @@ -34,7 +34,7 @@ struct x86_personality *x86pers = x86_pers(child); struct ptrace_personality *pers = personality(child); struct reg *regs = &child->regs; -#define ptr(user, off) ((unsigned long*)((void*)(user)+(off))) +#define ptr(regs, off) ((unsigned long*)((void*)(regs)+(off))) *ptr(regs, pers->reg_ip) -= 2; *ptr(regs, x86pers->ax) = child->saved_syscall; //*ptr(user, x86pers->ax) = *ptr(user, x86pers->orig_ax); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/freebsd/freebsd.h new/reptyr-reptyr-0.7.0/platform/freebsd/freebsd.h --- old/reptyr-reptyr-0.6.2/platform/freebsd/freebsd.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/freebsd/freebsd.h 2018-12-05 04:48:42.000000000 +0100 @@ -39,9 +39,9 @@ #include <stdio.h> #include <string.h> -#define do_socketcall(child, name, a0, a1, a2, a3, a4) \ +#define do_socketcall(child, scratch, name, a0, a1, a2, a3, a4) \ ({ \ - int __ret=-1; \ + int __ret=-1; \ if (ptrace_syscall_numbers((child))->nr_##name) { \ __ret = do_syscall((child), name, a0, a1, a2, a3, a4, 0); \ } \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/freebsd/freebsd_ptrace.c new/reptyr-reptyr-0.7.0/platform/freebsd/freebsd_ptrace.c --- old/reptyr-reptyr-0.6.2/platform/freebsd/freebsd_ptrace.c 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/freebsd/freebsd_ptrace.c 2018-12-05 04:48:42.000000000 +0100 @@ -47,7 +47,7 @@ static int __ptrace_command(struct ptrace_child *child, int req, void *, int); -#define ptrace_command(cld, req, ...) _ptrace_command(cld, req, ## __VA_ARGS__, NULL, NULL) +#define ptrace_command(cld, req, ...) _ptrace_command(cld, req, ## __VA_ARGS__, 0, 0) #define _ptrace_command(cld, req, addr, data, ...) __ptrace_command((cld), (req), (void*)(addr), (int)(data)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/arch/aarch64.h new/reptyr-reptyr-0.7.0/platform/linux/arch/aarch64.h --- old/reptyr-reptyr-0.6.2/platform/linux/arch/aarch64.h 1970-01-01 01:00:00.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/arch/aarch64.h 2018-12-05 04:48:42.000000000 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 by Nelson Elhage + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +static struct ptrace_personality arch_personality[1] = { + { + offsetof(struct user_regs_struct, regs[0]), + offsetof(struct user_regs_struct, regs[0]), + offsetof(struct user_regs_struct, regs[1]), + offsetof(struct user_regs_struct, regs[2]), + offsetof(struct user_regs_struct, regs[3]), + offsetof(struct user_regs_struct, regs[4]), + offsetof(struct user_regs_struct, regs[5]), + offsetof(struct user_regs_struct, pc), + } +}; + +static inline void arch_fixup_regs(struct ptrace_child *child) { + child->regs.pc -= 4; +} + +static inline int arch_set_syscall(struct ptrace_child *child, + unsigned long sysno) { + int syscall_reg = sysno; + struct iovec reg_iovec = { + .iov_base = &syscall_reg, + .iov_len = sizeof(syscall_reg) + }; + return ptrace_command(child, PTRACE_SETREGSET, NT_ARM_SYSTEM_CALL, ®_iovec); +} + +static inline int arch_save_syscall(struct ptrace_child *child) { + int syscall_reg; + struct iovec reg_iovec = { + .iov_base = &syscall_reg, + .iov_len = sizeof(syscall_reg) + }; + if (ptrace_command(child, PTRACE_GETREGSET, NT_ARM_SYSTEM_CALL, ®_iovec) < 0) + return -1; + + child->saved_syscall = syscall_reg; + return 0; +} + +static inline int arch_restore_syscall(struct ptrace_child *child) { + return arch_set_syscall(child, child->saved_syscall); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/arch/amd64.h new/reptyr-reptyr-0.7.0/platform/linux/arch/amd64.h --- old/reptyr-reptyr-0.6.2/platform/linux/arch/amd64.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/arch/amd64.h 2018-12-05 04:48:42.000000000 +0100 @@ -25,35 +25,35 @@ static struct ptrace_personality arch_personality[2] = { { - offsetof(struct user, regs.rax), - offsetof(struct user, regs.rdi), - offsetof(struct user, regs.rsi), - offsetof(struct user, regs.rdx), - offsetof(struct user, regs.r10), - offsetof(struct user, regs.r8), - offsetof(struct user, regs.r9), - offsetof(struct user, regs.rip), + offsetof(struct user_regs_struct, rax), + offsetof(struct user_regs_struct, rdi), + offsetof(struct user_regs_struct, rsi), + offsetof(struct user_regs_struct, rdx), + offsetof(struct user_regs_struct, r10), + offsetof(struct user_regs_struct, r8), + offsetof(struct user_regs_struct, r9), + offsetof(struct user_regs_struct, rip), }, { - offsetof(struct user, regs.rax), - offsetof(struct user, regs.rbx), - offsetof(struct user, regs.rcx), - offsetof(struct user, regs.rdx), - offsetof(struct user, regs.rsi), - offsetof(struct user, regs.rdi), - offsetof(struct user, regs.rbp), - offsetof(struct user, regs.rip), + offsetof(struct user_regs_struct, rax), + offsetof(struct user_regs_struct, rbx), + offsetof(struct user_regs_struct, rcx), + offsetof(struct user_regs_struct, rdx), + offsetof(struct user_regs_struct, rsi), + offsetof(struct user_regs_struct, rdi), + offsetof(struct user_regs_struct, rbp), + offsetof(struct user_regs_struct, rip), }, }; struct x86_personality x86_personality[2] = { { - offsetof(struct user, regs.orig_rax), - offsetof(struct user, regs.rax), + offsetof(struct user_regs_struct, orig_rax), + offsetof(struct user_regs_struct, rax), }, { - offsetof(struct user, regs.orig_rax), - offsetof(struct user, regs.rax), + offsetof(struct user_regs_struct, orig_rax), + offsetof(struct user_regs_struct, rax), }, }; @@ -65,7 +65,7 @@ * include unistd_32.h, but those definitions would conflict with the * standard ones. So, let's just hardcode the values for now. Probably * we should generate this from unistd_32.h during the build process or - * soemthing. + * something. */ .nr_mmap = 90, .nr_mmap2 = 192, @@ -77,7 +77,7 @@ .nr_wait4 = 114, .nr_signal = 48, .nr_rt_sigaction = 174, - .nr_open = 5, + .nr_openat = 295, .nr_close = 6, .nr_ioctl = 54, .nr_dup2 = 63, @@ -89,7 +89,7 @@ unsigned long cs; cs = ptrace_command(child, PTRACE_PEEKUSER, - offsetof(struct user, regs.cs)); + offsetof(struct user_regs_struct, cs)); if (child->error) return -1; if (cs == 0x23) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/arch/arm.h new/reptyr-reptyr-0.7.0/platform/linux/arch/arm.h --- old/reptyr-reptyr-0.6.2/platform/linux/arch/arm.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/arch/arm.h 2018-12-05 04:48:42.000000000 +0100 @@ -21,19 +21,19 @@ */ static struct ptrace_personality arch_personality[1] = { { - offsetof(struct user, regs.uregs[0]), - offsetof(struct user, regs.uregs[0]), - offsetof(struct user, regs.uregs[1]), - offsetof(struct user, regs.uregs[2]), - offsetof(struct user, regs.uregs[3]), - offsetof(struct user, regs.uregs[4]), - offsetof(struct user, regs.uregs[5]), - offsetof(struct user, regs.ARM_pc), + offsetof(struct user_regs, uregs[0]), + offsetof(struct user_regs, uregs[0]), + offsetof(struct user_regs, uregs[1]), + offsetof(struct user_regs, uregs[2]), + offsetof(struct user_regs, uregs[3]), + offsetof(struct user_regs, uregs[4]), + offsetof(struct user_regs, uregs[5]), + offsetof(struct user_regs, ARM_pc), } }; static inline void arch_fixup_regs(struct ptrace_child *child) { - child->user.regs.ARM_pc -= 4; + child->regs.ARM_pc -= 4; } static inline int arch_set_syscall(struct ptrace_child *child, @@ -43,11 +43,11 @@ static inline int arch_save_syscall(struct ptrace_child *child) { unsigned long swi; - swi = ptrace_command(child, PTRACE_PEEKTEXT, child->user.regs.ARM_pc); + swi = ptrace_command(child, PTRACE_PEEKTEXT, child->regs.ARM_pc); if (child->error) return -1; if (swi == 0xef000000) - child->saved_syscall = child->user.regs.uregs[7]; + child->saved_syscall = child->regs.uregs[7]; else child->saved_syscall = (swi & 0x000fffff); return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/arch/default-syscalls.h new/reptyr-reptyr-0.7.0/platform/linux/arch/default-syscalls.h --- old/reptyr-reptyr-0.6.2/platform/linux/arch/default-syscalls.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/arch/default-syscalls.h 2018-12-05 04:48:42.000000000 +0100 @@ -1,21 +1,24 @@ #define SC(name) .nr_##name = __NR_##name { -#ifdef __NR_mmap - SC(mmap), -#else - .nr_mmap = -1, -#endif #ifdef __NR_mmap2 + .nr_mmap = -1, SC(mmap2), #else + SC(mmap), .nr_mmap2 = -1, #endif SC(munmap), SC(getsid), SC(setsid), SC(setpgid), +#ifdef __NR_fork SC(fork), + .nr_clone = -1, +#else + .nr_fork = -1, + SC(clone), +#endif SC(wait4), #ifdef __NR_signal SC(signal), @@ -23,10 +26,16 @@ .nr_signal = -1, #endif SC(rt_sigaction), - SC(open), + SC(openat), SC(close), SC(ioctl), +#ifdef __NR_dup2 SC(dup2), + .nr_dup3 = -1, +#else + .nr_dup2 = -1, + SC(dup3), +#endif #ifdef __NR_socketcall SC(socketcall), #else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/arch/i386.h new/reptyr-reptyr-0.7.0/platform/linux/arch/i386.h --- old/reptyr-reptyr-0.6.2/platform/linux/arch/i386.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/arch/i386.h 2018-12-05 04:48:42.000000000 +0100 @@ -23,20 +23,20 @@ static struct ptrace_personality arch_personality[1] = { { - offsetof(struct user, regs.eax), - offsetof(struct user, regs.ebx), - offsetof(struct user, regs.ecx), - offsetof(struct user, regs.edx), - offsetof(struct user, regs.esi), - offsetof(struct user, regs.edi), - offsetof(struct user, regs.ebp), - offsetof(struct user, regs.eip), + offsetof(struct user_regs_struct, eax), + offsetof(struct user_regs_struct, ebx), + offsetof(struct user_regs_struct, ecx), + offsetof(struct user_regs_struct, edx), + offsetof(struct user_regs_struct, esi), + offsetof(struct user_regs_struct, edi), + offsetof(struct user_regs_struct, ebp), + offsetof(struct user_regs_struct, eip), } }; struct x86_personality x86_personality[1] = { { - offsetof(struct user, regs.orig_eax), - offsetof(struct user, regs.eax), + offsetof(struct user_regs_struct, orig_eax), + offsetof(struct user_regs_struct, eax), } }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/arch/powerpc.h new/reptyr-reptyr-0.7.0/platform/linux/arch/powerpc.h --- old/reptyr-reptyr-0.6.2/platform/linux/arch/powerpc.h 1970-01-01 01:00:00.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/arch/powerpc.h 2018-12-05 04:48:42.000000000 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 by Nelson Elhage + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +static struct ptrace_personality arch_personality[1] = { + { + offsetof(struct pt_regs, gpr[3]), + offsetof(struct pt_regs, gpr[3]), + offsetof(struct pt_regs, gpr[4]), + offsetof(struct pt_regs, gpr[5]), + offsetof(struct pt_regs, gpr[6]), + offsetof(struct pt_regs, gpr[7]), + offsetof(struct pt_regs, gpr[8]), + offsetof(struct pt_regs, nip), + } +}; + +static const unsigned long r0off = offsetof(struct pt_regs, gpr[0]); + +static inline void arch_fixup_regs(struct ptrace_child *child) { + child->regs.nip -= 4; +} + +static inline int arch_set_syscall(struct ptrace_child *child, + unsigned long sysno) { + return ptrace_command(child, PTRACE_POKEUSER, r0off, sysno); +} + +static inline int arch_save_syscall(struct ptrace_child *child) { + child->saved_syscall = *ptr(&child->regs, r0off); + return 0; +} + +static inline int arch_restore_syscall(struct ptrace_child *child) { + return arch_set_syscall(child, child->saved_syscall); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/arch/x86_common.h new/reptyr-reptyr-0.7.0/platform/linux/arch/x86_common.h --- old/reptyr-reptyr-0.6.2/platform/linux/arch/x86_common.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/arch/x86_common.h 2018-12-05 04:48:42.000000000 +0100 @@ -34,10 +34,9 @@ static inline void arch_fixup_regs(struct ptrace_child *child) { struct x86_personality *x86pers = x86_pers(child); struct ptrace_personality *pers = personality(child); - struct user *user = &child->user; -#define ptr(user, off) ((unsigned long*)((void*)(user)+(off))) - *ptr(user, pers->reg_ip) -= 2; - *ptr(user, x86pers->ax) = *ptr(user, x86pers->orig_ax); + struct user_regs_struct *regs = &child->regs; + *ptr(regs, pers->reg_ip) -= 2; + *ptr(regs, x86pers->ax) = *ptr(regs, x86pers->orig_ax); } static inline int arch_set_syscall(struct ptrace_child *child, @@ -48,12 +47,10 @@ } static inline int arch_save_syscall(struct ptrace_child *child) { - child->saved_syscall = *ptr(&child->user, x86_pers(child)->orig_ax); + child->saved_syscall = *ptr(&child->regs, x86_pers(child)->orig_ax); return 0; } static inline int arch_restore_syscall(struct ptrace_child *child) { return 0; } - -#undef ptr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/linux.c new/reptyr-reptyr-0.7.0/platform/linux/linux.c --- old/reptyr-reptyr-0.6.2/platform/linux/linux.c 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/linux.c 2018-12-05 04:48:42.000000000 +0100 @@ -46,13 +46,6 @@ } out->ctty = dev; - struct stat st; - if (fstat(statfd, &st) != 0) - return assert_nonzero(errno); - - out->uid = st.st_uid; - out->gid = st.st_gid; - return 0; } @@ -67,8 +60,51 @@ error("Unable to open %s: %s", stat_path, strerror(errno)); return -statfd; } - err = parse_proc_stat(statfd, out); + + + close(statfd); + return err; +} + +int read_uid(pid_t pid, uid_t *out) { + char stat_path[PATH_MAX]; + char buf[1024]; + int statfd; + int err = 0; + int n; + char *p = buf; + + snprintf(stat_path, sizeof stat_path, "/proc/%d/status", pid); + statfd = open(stat_path, O_RDONLY); + if (statfd < 0) { + error("Unable to open %s: %s", stat_path, strerror(errno)); + return -statfd; + } + + if ((n = read(statfd, buf, sizeof(buf))) < 0) { + err = assert_nonzero(errno); + goto out; + } + while (p < buf + n) { + if (strncmp(p, "Uid:\t", strlen("Uid:\t")) == 0) + break; + p = memchr(p, '\n', buf+n-p); + if (p == NULL) + break; + p++; + continue; + } + if (p == NULL || p >= buf + n) { + debug("Unable to parse emulator uid: no Uid line found"); + *out = -1; + goto out; + } + if(sscanf(p, "Uid:\t%d", out) < 0) { + debug("Unable to parse emulator uid: unparseable Uid line"); + } + + out: close(statfd); return err; } @@ -148,7 +184,7 @@ memcpy(pid_stat.comm, "???", 4); } error("Process %d (%.*s) shares %d's process group. Unable to attach.\n" - "(This most commonly means that %d has suprocesses).", + "(This most commonly means that %d has sub-processes).", (int)pid, TASK_COMM_LENGTH, pid_stat.comm, (int)target, (int)target); err = EINVAL; goto out; @@ -192,9 +228,10 @@ } if (stat("/dev/console", &console_st) < 0) { - child->error = errno; error("Unable to stat /dev/console"); - return NULL; + console_st = (struct stat){ + .st_rdev = -1, + }; } snprintf(buf, sizeof buf, "/proc/%d/fd/", child->pid); @@ -237,6 +274,9 @@ if ((err = find_terminal_emulator(steal))) return err; + if ((err = read_uid(steal->emulator_pid, &steal->emulator_uid))) + return err; + return 0; } @@ -362,7 +402,7 @@ } void copy_user(struct ptrace_child *d, struct ptrace_child *s) { - memcpy(&d->user, &s->user, sizeof(s->user)); + memcpy(&d->regs, &s->regs, sizeof(s->regs)); } unsigned long ptrace_socketcall(struct ptrace_child *child, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/linux.h new/reptyr-reptyr-0.7.0/platform/linux/linux.h --- old/reptyr-reptyr-0.6.2/platform/linux/linux.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/linux.h 2018-12-05 04:48:42.000000000 +0100 @@ -24,6 +24,14 @@ #define LINUX_H #ifdef __linux__ + +// Important that we include <sys/wait.h> before <linux/*>, for +// compatibility with certain older libcs, in which <linux/wait.h> +// #define's some symbols that <sys/wait.h> defines via +// `enum. c.f. https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1261872/ +// and https://github.com/nelhage/reptyr/issues/67 +#include <sys/wait.h> + #include <linux/major.h> #include <linux/net.h> #include <linux/limits.h> @@ -32,8 +40,8 @@ #include <sys/ptrace.h> #include <asm/ptrace.h> #include <sys/types.h> +#include <sys/sysmacros.h> #include <sys/user.h> -#include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/linux/linux_ptrace.c new/reptyr-reptyr-0.7.0/platform/linux/linux_ptrace.c --- old/reptyr-reptyr-0.6.2/platform/linux/linux_ptrace.c 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/linux/linux_ptrace.c 2018-12-05 04:48:42.000000000 +0100 @@ -22,6 +22,7 @@ #ifdef __linux__ +#include <elf.h> #include "../../ptrace.h" #include "../platform.h" @@ -47,12 +48,18 @@ typeof(y) _min2 = (y); \ _min1 < _min2 ? _min1 : _min2; }) +#ifdef PTRACE_TRACEME +static long __ptrace_command(struct ptrace_child *child, int req, + void *, void*); +#else static long __ptrace_command(struct ptrace_child *child, enum __ptrace_request req, void *, void*); +#endif #define ptrace_command(cld, req, ...) _ptrace_command(cld, req, ## __VA_ARGS__, NULL, NULL) #define _ptrace_command(cld, req, addr, data, ...) __ptrace_command((cld), (req), (void*)(addr), (void*)(data)) +#define ptr(regs, off) ((unsigned long*)((void*)(regs)+(off))) struct ptrace_personality { size_t syscall_rv; @@ -73,6 +80,10 @@ #include "arch/i386.h" #elif defined(__arm__) #include "arch/arm.h" +#elif defined(__aarch64__) +#include "arch/aarch64.h" +#elif defined(__powerpc__) +#include "arch/powerpc.h" #else #error Unsupported architecture. #endif @@ -195,7 +206,12 @@ int ptrace_save_regs(struct ptrace_child *child) { if (ptrace_advance_to_state(child, ptrace_at_syscall) < 0) return -1; - if (ptrace_command(child, PTRACE_GETREGS, 0, &child->user) < 0) + + struct iovec reg_iovec = { + .iov_base = &child->regs, + .iov_len = sizeof(child->regs) + }; + if (ptrace_command(child, PTRACE_GETREGSET, NT_PRSTATUS, ®_iovec) < 0) return -1; arch_fixup_regs(child); if (arch_save_syscall(child) < 0) @@ -205,7 +221,11 @@ int ptrace_restore_regs(struct ptrace_child *child) { int err; - err = ptrace_command(child, PTRACE_SETREGS, 0, &child->user); + struct iovec reg_iovec = { + .iov_base = &child->regs, + .iov_len = sizeof(child->regs) + }; + err = ptrace_command(child, PTRACE_SETREGSET, NT_PRSTATUS, ®_iovec); if (err < 0) return err; return arch_restore_syscall(child); @@ -220,15 +240,21 @@ if (ptrace_advance_to_state(child, ptrace_at_syscall) < 0) return -1; -#define setreg(r, v) do { \ - if (ptrace_command(child, PTRACE_POKEUSER, \ - personality(child)->r, \ - (v)) < 0) \ - return -1; \ - } while (0) - if (arch_set_syscall(child, sysno) < 0) return -1; + + typeof(child->regs) regs; + + struct iovec reg_iovec = { + .iov_base = ®s, + .iov_len = sizeof(regs) + }; + +#define setreg(r, v) (*ptr(®s, (personality(child)->r))) = (v) + + if (ptrace_command(child, PTRACE_GETREGSET, NT_PRSTATUS, ®_iovec) < 0) + return -1; + setreg(syscall_arg0, p0); setreg(syscall_arg1, p1); setreg(syscall_arg2, p2); @@ -236,16 +262,21 @@ setreg(syscall_arg4, p4); setreg(syscall_arg5, p5); + if (ptrace_command(child, PTRACE_SETREGSET, NT_PRSTATUS, ®_iovec) < 0) + return -1; + if (ptrace_advance_to_state(child, ptrace_after_syscall) < 0) return -1; - rv = ptrace_command(child, PTRACE_PEEKUSER, - personality(child)->syscall_rv); - if (child->error) + if (ptrace_command(child, PTRACE_GETREGSET, NT_PRSTATUS, ®_iovec) < 0) return -1; - setreg(reg_ip, *(unsigned long*)((void*)&child->user + - personality(child)->reg_ip)); + rv = *ptr(®s, (personality(child)->syscall_rv)); + + setreg(reg_ip, *(unsigned long*)((void*)&child->regs + personality(child)->reg_ip)); + + if (ptrace_command(child, PTRACE_SETREGSET, NT_PRSTATUS, ®_iovec) < 0) + return -1; #undef setreg @@ -293,8 +324,13 @@ return 0; } +#ifdef PTRACE_TRACEME +static long __ptrace_command(struct ptrace_child *child, int req, + void *addr, void *data) { +#else static long __ptrace_command(struct ptrace_child *child, enum __ptrace_request req, void *addr, void *data) { +#endif long rv; errno = 0; rv = ptrace(req, child->pid, addr, data); @@ -302,31 +338,4 @@ return rv; } - -#ifdef BUILD_PTRACE_MAIN -int main(int argc, char **argv) { - struct ptrace_child child; - pid_t pid; - - if (argc < 2) { - printf("Usage: %s pid\n", argv[0]); - return 1; - } - pid = atoi(argv[1]); - - assert(!ptrace_attach_child(&child, pid)); - assert(!ptrace_save_regs(&child)); - - printf("mmap = %lx\n", ptrace_remote_syscall(&child, mmap_syscall, 0, - 4096, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, 0, 0)); - - reset_user_struct(&child.user); - assert(!ptrace_restore_regs(&child)); - assert(!ptrace_detach_child(&child)); - - return 0; -} -#endif - #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/platform/platform.h new/reptyr-reptyr-0.7.0/platform/platform.h --- old/reptyr-reptyr-0.6.2/platform/platform.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/platform/platform.h 2018-12-05 04:48:42.000000000 +0100 @@ -23,6 +23,10 @@ #ifndef PLATFORM_H #define PLATFORM_H +#ifdef __APPLE__ +#error "reptyr does not currently support macOS" +#endif + #include "linux/linux.h" #include "freebsd/freebsd.h" #include "../ptrace.h" @@ -45,14 +49,14 @@ char state; pid_t ppid, sid, pgid; dev_t ctty; - uid_t uid; - gid_t gid; }; struct steal_pty_state { struct proc_stat target_stat; pid_t emulator_pid; + uid_t emulator_uid; + struct fd_array master_fds; char tmpdir[PATH_MAX]; @@ -75,7 +79,7 @@ int *get_child_tty_fds(struct ptrace_child *child, int statfd, int *count); int get_terminal_state(struct steal_pty_state *steal, pid_t target); int find_master_fd(struct steal_pty_state *steal); -int get_pt(); +int get_pt(void); int get_process_tty_termios(pid_t pid, struct termios *tio); void move_process_group(struct ptrace_child *child, pid_t from, pid_t to); void copy_user(struct ptrace_child *d, struct ptrace_child *s); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/ptrace.h new/reptyr-reptyr-0.7.0/ptrace.h --- old/reptyr-reptyr-0.6.2/ptrace.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/ptrace.h 2018-12-05 04:48:42.000000000 +0100 @@ -63,9 +63,14 @@ unsigned long forked_pid; unsigned long saved_syscall; #ifdef __linux__ - struct user user; +#ifdef __arm__ + struct user_regs regs; +#elif defined(__powerpc__) + struct pt_regs regs; +#else + struct user_regs_struct regs; #endif -#ifdef __FreeBSD__ +#elif defined(__FreeBSD__) struct reg regs; #endif }; @@ -78,13 +83,15 @@ long nr_setsid; long nr_setpgid; long nr_fork; + long nr_clone; long nr_wait4; long nr_signal; long nr_rt_sigaction; - long nr_open; + long nr_openat; long nr_close; long nr_ioctl; long nr_dup2; + long nr_dup3; long nr_socket; long nr_connect; long nr_sendmsg; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/reptyr.bash new/reptyr-reptyr-0.7.0/reptyr.bash --- old/reptyr-reptyr-0.6.2/reptyr.bash 1970-01-01 01:00:00.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/reptyr.bash 2018-12-05 04:48:42.000000000 +0100 @@ -0,0 +1,19 @@ +# bash completion for reptyr(1) + +_reptyr() +{ + case $3 in + -l|-L|-h|-v) return ;; + esac + + if [[ $2 == -* ]]; then + COMPREPLY=( $(compgen -W '-l -L -s -T -h -v -V' -- "$2") ) + return + fi + + case $3 in + [1-9]*) ;; + *) COMPREPLY=( $(compgen -W '$(command ps axo pid=)' -- "$2") ) ;; + esac +} && +complete -F _reptyr reptyr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/reptyr.c new/reptyr-reptyr-0.7.0/reptyr.c --- old/reptyr-reptyr-0.6.2/reptyr.c 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/reptyr.c 2018-12-05 04:48:42.000000000 +0100 @@ -124,23 +124,34 @@ char buf[4096]; ssize_t count; fd_set set; - struct timeval timeout; + sigset_t mask; + sigset_t select_mask; + struct sigaction sa; + + // Block WINCH while we're outside the select, but unblock it + // while we're inside: + sigemptyset(&mask); + sigaddset(&mask, SIGWINCH); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { + fprintf(stderr, "sigprocmask: %m"); + return; + } + sa.sa_handler = do_winch; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGWINCH, &sa, NULL); + resize_pty(pty); + while (1) { if (winch_happened) { winch_happened = 0; - /* - * FIXME: If a signal comes in after this point but before - * select(), the resize will be delayed until we get more - * input. signalfd() is probably the cleanest solution. - */ resize_pty(pty); } FD_ZERO(&set); FD_SET(0, &set); FD_SET(pty, &set); - timeout.tv_sec = 0; - timeout.tv_usec = 1000; - if (select(pty + 1, &set, NULL, NULL, &timeout) < 0) { + sigemptyset(&select_mask); + if (pselect(pty + 1, &set, NULL, NULL, NULL, &select_mask) < 0) { if (errno == EINTR) continue; fprintf(stderr, "select: %m"); @@ -179,7 +190,6 @@ int main(int argc, char **argv) { struct termios saved_termios; - struct sigaction act; int pty; int opt; int err; @@ -287,11 +297,6 @@ } setup_raw(&saved_termios); - memset(&act, 0, sizeof act); - act.sa_handler = do_winch; - act.sa_flags = 0; - sigaction(SIGWINCH, &act, NULL); - resize_pty(pty); do_proxy(pty); do { errno = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/reptyr.fr.1 new/reptyr-reptyr-0.7.0/reptyr.fr.1 --- old/reptyr-reptyr-0.6.2/reptyr.fr.1 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/reptyr.fr.1 2018-12-05 04:48:42.000000000 +0100 @@ -51,7 +51,7 @@ .B \-l .IP Plutôt que d'attacher un nouveau processus, crée un couveau couple de -pty, redirige l'extrémité maîtresse vers le terminal en corus, puis +pty, redirige l'extrémité maîtresse vers le terminal en cours, puis affiche le nom du pty esclave. Il pourra être passé en argument par exemple à l'option .I set inferior-tty diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/reptyr.h new/reptyr-reptyr-0.7.0/reptyr.h --- old/reptyr-reptyr-0.6.2/reptyr.h 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/reptyr.h 2018-12-05 04:48:42.000000000 +0100 @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -#define REPTYR_VERSION "0.6.2" +#define REPTYR_VERSION "0.7.0" #define assert_nonzero(expr) ({ \ typeof(expr) __val = expr; \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/test/basic.py new/reptyr-reptyr-0.7.0/test/basic.py --- old/reptyr-reptyr-0.6.2/test/basic.py 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/test/basic.py 2018-12-05 04:48:42.000000000 +0100 @@ -1,11 +1,14 @@ import pexpect +import sys child = pexpect.spawn("test/victim") +child.logfile = sys.stdout child.setecho(False) child.sendline("hello") child.expect("ECHO: hello") -reptyr = pexpect.spawn("./reptyr %d" % (child.pid,)) +reptyr = pexpect.spawn("./reptyr -V %d" % (child.pid,)) +reptyr.logfile = sys.stdout reptyr.sendline("world") reptyr.expect("ECHO: world") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/test/requirements.txt new/reptyr-reptyr-0.7.0/test/requirements.txt --- old/reptyr-reptyr-0.6.2/test/requirements.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/test/requirements.txt 2018-12-05 04:48:42.000000000 +0100 @@ -0,0 +1,2 @@ +pexpect +python-prctl>1.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/test/tty-steal.py new/reptyr-reptyr-0.7.0/test/tty-steal.py --- old/reptyr-reptyr-0.6.2/test/tty-steal.py 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/test/tty-steal.py 2018-12-05 04:48:42.000000000 +0100 @@ -3,15 +3,31 @@ import sys if os.getenv("NO_TEST_STEAL") is not None: - print "Skipping tty-stealing tests because $NO_TEST_STEAL is set." + print("Skipping tty-stealing tests because $NO_TEST_STEAL is set.") sys.exit(0) +did_prctl = False +try: + import prctl + PR_SET_PTRACER_ANY = 0xffffffff + if hasattr(prctl, 'set_ptracer'): + did_prctl = True + prctl.set_ptracer(PR_SET_PTRACER_ANY) +except ImportError: + pass + +if not did_prctl: + print("Unable to find `prctl.set_ptracer`, skipping `PR_SET_PTRACER`.") + child = pexpect.spawn("test/victim") child.setecho(False) child.sendline("hello") child.expect("ECHO: hello") -reptyr = pexpect.spawn("./reptyr -T %d" % (child.pid,)) +reptyr = pexpect.spawn("./reptyr -V -T %d" % (child.pid,)) +print("spawned children: me={} victim={} reptyr={}".format(os.getpid(), child.pid, reptyr.pid)) +reptyr.logfile = sys.stdout + reptyr.sendline("world") reptyr.expect("ECHO: world") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reptyr-reptyr-0.6.2/test/victim.c new/reptyr-reptyr-0.7.0/test/victim.c --- old/reptyr-reptyr-0.6.2/test/victim.c 2015-02-01 02:14:27.000000000 +0100 +++ new/reptyr-reptyr-0.7.0/test/victim.c 2018-12-05 04:48:42.000000000 +0100 @@ -1,9 +1,23 @@ #include <stdio.h> +#include <sys/prctl.h> + +#ifndef PR_SET_PTRACER +#define PR_SET_PTRACER +#endif + +#ifndef PR_SET_PTRACER_ANY +# define PR_SET_PTRACER_ANY ((unsigned long)-1) +#endif int main(int argc, char **argv) { char *line = NULL; size_t cap = 0; + int err = prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY); + if (err != 0) { + fprintf(stderr, "Unable to PR_SET_PTRACER: %m\n"); + } + while(getline(&line, &cap, stdin) != -1) { printf("ECHO: %s", line); }