เราจะรู้ได้อย่างไรว่าใครอยู่ที่ปลายอีกด้านของอุปกรณ์ปลายทางหลอก?


26

ถ้าฉันทำ:

echo foo > /dev/pts/12

บางกระบวนการจะอ่านสิ่งนั้นfoo\nจากตัวให้คำอธิบายไฟล์ไปยังด้านต้นแบบ

มีวิธีที่จะค้นหาว่ากระบวนการ (เหล่านั้น) คืออะไร?

หรือในคำอื่น ๆ ฉันจะรู้ได้อย่างไรว่า xterm / sshd / script / screen / tmux / expect / socat ... อยู่ที่ปลายด้านหนึ่งของ/dev/pts/12?

lsof /dev/ptmxจะบอกกระบวนการที่มีตัวอธิบายไฟล์ที่ด้านหลักของ pty ใด ๆ กระบวนการสามารถใช้ptsname()( TIOCGPTNioctl) เพื่อค้นหาอุปกรณ์ทาสตาม fd ของตัวเองไปยังด้านต้นแบบดังนั้นฉันสามารถใช้:

gdb --batch --pid "$the_pid" -ex "print ptsname($the_fd)"

สำหรับแต่ละ pid / fd ที่ส่งกลับโดยlsofสร้างการแมปนั้น แต่มีวิธีที่เชื่อถือได้และน่ารำคาญน้อยกว่าในการรับข้อมูลนั้นหรือไม่


นี่คือสิ่งที่คุณต้องการ? sudo find /proc/*/fd/0 -ls | grep '/dev/pts/4'จะให้รายชื่อของ PID ( /proc/PID) เป็นเอาท์พุท
slm

@slm ไม่มีในคำอื่น ๆ ผมต้องการที่จะหาที่ xterm / sshd / script / / จอ tmux / คาดหวัง / socat ... อยู่ที่อื่น ๆ/dev/pts/4ในตอนท้ายของ โดยปกติแล้วจะเป็นบรรพบุรุษร่วมของกระบวนการเหล่านั้นที่/dev/pts/4เปิดอยู่ แต่ไม่จำเป็นเสมอไป
Stéphane Chazelas

1
มันยิ่งแย่ไปกว่าซ็อกเก็ต - คุณต้องมีเคอร์เนลดีบักเกอร์!
Gilles 'SO- หยุดความชั่วร้าย'

1
@ ชื่อเฟรม - ฉันเข้าใจคำถามที่จะหมายถึง - อาจไม่ถูกต้อง - ไม่ใช่กระบวนการที่ส่งผ่านข้อมูลที่อ่าน - เช่นเชลล์แรกที่เรียกใช้ในเทอร์มินัล - แต่กระบวนการใดที่อ่านจากด้านต้นแบบ ตัวอย่างเช่นถ้าฉันเปิดตัวเชลล์screenมันเป็นscreenสิ่งที่จัดสรรและจัดการทาส pty อย่างแข็งขันสำหรับชีวิตของอุปกรณ์ แต่อย่างที่ฉันคิดว่า - เชลล์เป็นผู้นำในกระบวนการสำหรับ tty นั้น แสดงให้เห็นว่าการส่งออกคุณจะได้รับbashหรืออะไรก็ตามจากการไม่ได้ps screenผมตรวจสอบไม่กี่xtermsกลับไปxtermpid ขึ้นอยู่กับ/proc/locksแต่มันก็หลวม
mikeserv

1
เกี่ยวข้อง: unix.stackexchange.com/questions/492302
mosvy

คำตอบ:


3

ตอนแรกฉันพยายามติดตามบางส่วนxtermกลับไปที่xtermpid ตามข้อมูลที่ฉันพบ/proc/locksแต่มันหลวม ฉันหมายถึงมันใช้งานได้ฉันคิดว่า แต่มันเป็นเรื่องที่ดีที่สุดในด้านการเงิน - ฉันไม่เข้าใจข้อมูลทั้งหมดที่ไฟล์ให้และตรงกับสิ่งที่ดูเหมือนจะสอดคล้องระหว่างเนื้อหาและกระบวนการเทอร์มินัลที่รู้จักเท่านั้น

จากนั้นฉันก็ลองดูกระบวนการที่lsof/straceใช้งานอยู่write/talkระหว่าง ptys ผมไม่เคยใช้จริงโปรแกรมอย่างใดอย่างหนึ่งก่อน utmpแต่พวกเขาดูเหมือนจะพึ่งพา หาก pty เป้าหมายของฉันไม่มีutmpรายการไม่ว่าด้วยเหตุผลใดพวกเขาทั้งสองปฏิเสธที่จะยอมรับว่ามีอยู่จริง อาจมีวิธีแก้ไข แต่ฉันก็สับสนพอที่จะละทิ้งมัน

ฉันพยายามudevadmค้นพบบางอย่างกับโหนดอุปกรณ์หลักจำนวน 136 และ 128 ตัวตามที่โฆษณาptsและptmตามลำดับ/proc/tty/driversแต่ฉันก็ยังขาดประสบการณ์ที่มีประโยชน์มากกับเครื่องมือนั้น อย่างไรก็ตามที่น่าสนใจฉันสังเกตเห็นว่า:minช่วงของอุปกรณ์ทั้งสองประเภทนั้นอยู่ในรายการที่น่าประหลาด0-1048575ใจ

มันไม่ได้จนกว่าฉันจะกลับมายังเอกสารเคอร์เนลนี้ที่ฉันเริ่มคิดเกี่ยวกับปัญหาในแง่ของmountแม้ว่า ฉันเคยอ่านมาหลายครั้งแล้ว แต่เมื่อทำการวิจัยต่อเนื่องในบรรทัดนั้นทำให้ฉันได้รับpatchset 2012 นี้/dev/ptsฉันมีความคิด:

sudo fuser -v /dev/ptmx

ฉันคิดว่าฉันจะทำอะไรมักจะใช้กับกระบวนการร่วมกับmount? และนั่นเอง:

                     USER        PID ACCESS COMMAND
/dev/ptmx:           root      410   F.... kmscon
                     mikeserv  710   F.... terminology

ดังนั้นด้วยข้อมูลที่ฉันสามารถทำได้เช่นจากterminology:

sudo sh -c '${cmd:=grep rchar /proc/410/io} && printf 1 >/dev/pts/0 && $cmd'
###OUTPUT###
rchar: 667991010
rchar: 667991011

อย่างที่คุณเห็นด้วยการทดสอบที่ชัดเจนเพียงเล็กน้อยกระบวนการเช่นนี้อาจทำให้การส่งออกกระบวนการหลักของ pty โดยพลการได้อย่างน่าเชื่อถือ เกี่ยวกับซ็อกเก็ตฉันค่อนข้างแน่ใจว่าจะสามารถเข้าถึงได้จากทิศทางนั้นและใช้socatแทนการดีบัก แต่ฉันยังไม่ได้อธิบายวิธีการ ถึงกระนั้นฉันสงสัยว่าssอาจช่วยถ้าคุณคุ้นเคยกับมันมากกว่าฉัน:

sudo sh -c 'ss -oep | grep "$(printf "pid=%s\n" $(fuser /dev/ptmx))"'

ดังนั้นฉันจึงตั้งค่าด้วยการทดสอบที่ชัดเจนยิ่งขึ้นจริง ๆ แล้ว:

sudo sh <<\CMD
    chkio() {
        read io io <$1
        dd bs=1 count=$$ </dev/zero >$2 2>/dev/null
        return $((($(read io io <$1; echo $io)-io)!=$$))
    }
    for pts in /dev/pts/[0-9]* ; do
        for ptm in $(fuser /dev/ptmx 2>/dev/null)
            do chkio /proc/$ptm/io $pts && break
        done && set -- "$@" "$ptm owns $pts"
    done
    printf %s\\n "$@"
 CMD

มันพิมพ์$$num \0null null ไปที่แต่ละ pty และตรวจสอบกระบวนการ io ของกระบวนการหลักเทียบกับการตรวจสอบก่อนหน้า หากความแตกต่าง$$นั้นจะเชื่อมโยง pid กับ pty นี้ส่วนใหญ่ทำงาน ฉันหมายถึงสำหรับฉันมันจะกลับมา:

410 owns /dev/pts/0
410 owns /dev/pts/1
710 owns /dev/pts/2

ซึ่งถูกต้อง แต่เห็นได้ชัดว่ามันมีชีวิตชีวาเล็กน้อย ฉันหมายถึงถ้าหนึ่งในคนอื่น ๆ กำลังอ่านข้อมูลจำนวนมากในเวลาที่มันอาจจะพลาด ฉันกำลังพยายามหาวิธีการเปลี่ยนsttyโหมดใน pty อื่นเพื่อส่งบิตหยุดก่อนหรือบางอย่างเช่นนั้นเพื่อให้ฉันสามารถแก้ไขได้


2

หากคุณเพียงแค่กำลังมองหาผู้ที่เป็นเจ้าของการเชื่อมต่อและที่พวกเขาเชื่อมต่อจากคำสั่งใครจะทำงานได้ดี

$ who
falsenames   tty8         Jun 13 16:54 (:0)
falsenames   pts/0        Jun 16 11:18 (:0)
falsenames   pts/1        Jun 16 12:59 (:0)
falsenames   pts/2        Jun 16 13:46 (:0)
falsenames   pts/3        Jun 16 14:10 (:0)
falsenames   pts/4        Jun 16 16:41 (:0)

หากคุณยังต้องการที่จะรู้ว่าสิ่งที่จะฟังบนการเชื่อมต่อที่Wจะแสดงให้เห็นว่าในตอนท้าย

$ w
 16:44:09 up 2 days, 23:51,  6 users,  load average: 0.26, 0.98, 1.25
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
falsenames   tty8     :0               Fri16    2days 53:36   0.59s x-session-manager
falsenames   pts/0    :0               11:18    5:25m  1:10   1:10  synergys -a 10.23.8.245 -c .synergy.conf -f -d DEBUG
falsenames   pts/1    :0               12:59    3:44m  0.05s  0.05s bash
falsenames   pts/2    :0               13:46    2:52m  0.11s  0.11s bash
falsenames   pts/3    :0               14:10    2:17   0.07s  0.07s bash
falsenames   pts/4    :0               16:41    1.00s  0.04s  0.00s w

และเพื่อให้ได้ pids ให้ จำกัด ps ไว้ที่เซสชัน tty ที่คุณกำลังดู ไม่เป็นการรบกวนในการบู๊ตโดยสิ้นเชิง

$ ps -t pts/0 --forest 
  PID TTY          TIME CMD
23808 pts/0    00:00:00 bash
23902 pts/0    00:03:27  \_ synergys

หมายเหตุสิ่งนี้อาจนำไปสู่ปลาเฮอริ่งแดงขึ้นอยู่กับเวลา แต่มันเป็นจุดเริ่มต้นที่ดี

$ tty
/dev/pts/4
$ ps -t pts/4 --forest
  PID TTY          TIME CMD
27479 pts/4    00:00:00 bash
 3232 pts/4    00:00:00  \_ ps
27634 pts/4    00:00:00 dbus-launch

ขอบคุณ แต่นั่นไม่ใช่สิ่งที่ฉันกำลังมองหา ตัวอย่างข้างต้นฉันต้องการค้นหา pid ของแอปพลิเคชันเทอร์มินัล (Xterm / gnome-terminal ... ) ที่สอดคล้องกับ/dev/pts/4ที่ซึ่งคุณรันwคำสั่งนั้น
Stéphane Chazelas

ขออภัยพลาดส่วน pid โดยสมบูรณ์เมื่อฉันสแกนผ่านครั้งแรก ฉันคิดว่าคุณแค่อยากรู้ชื่อกระบวนการสิ้นสุด
Falsenames

2

ฉันมีปัญหาเดียวกันกับ qemu และในที่สุดฉันก็พบวิธีแก้ปัญหาที่แย่มาก (แต่ก็ยังแก้ปัญหาด้วย): การแยกวิเคราะห์หน่วยความจำกระบวนการ

นี่ทำงานได้ที่นี่เพราะฉันรู้ว่า qemu กำลังจัดเก็บ pts ระยะไกลในสตริงที่มีรูปแบบเฉพาะและจัดสรรบนฮีป อาจจะสามารถทำงานในสถานการณ์อื่น ๆ ได้เช่นกันด้วยการเปลี่ยนแปลงเล็กน้อยและโดยการนำ pid จากเอาต์พุต fuser อีกครั้ง (ตรวจสอบคำตอบอื่น ๆ )

รหัสที่ดัดแปลงมาจากที่นี่

#! /usr/bin/env python

import sys
pid = sys.argv[1]

import re
maps_file = open("/proc/" + pid + "/maps", 'r')
mem_file = open("/proc/" + pid + "/mem", 'r', 0)
for line in maps_file.readlines():
    # You may want to remove the 'heap' part to search all RAM
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r]).*\[heap\]', line)
    if m and m.group(3) == 'r':
        start = int(m.group(1), 16)
        end = int(m.group(2), 16)
        mem_file.seek(start)
        chunk = mem_file.read(end - start)
        # You may want to adapt this one to reduce false matches
        idx = chunk.find("/dev/pts/")
        if idx != -1:
            end = chunk.find("\0", idx)
            print chunk[idx:end]
maps_file.close()
mem_file.close()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.