ฉันจะหลอกให้กระบวนการคิดว่าไฟล์ไม่มีอยู่ได้อย่างไร


31

ฉันมีโปรแกรมที่จัดเก็บการตั้งค่าใน ~/.config/myprogramฉันใช้ทั้งแบบโต้ตอบและกับระบบคิวแบบแบตช์ เมื่อเรียกใช้แบบโต้ตอบฉันต้องการให้โปรแกรมนี้ใช้ไฟล์การกำหนดค่าของฉัน แต่เมื่อทำงานในโหมดแบทช์ไฟล์การกำหนดค่าไม่จำเป็นเพราะฉันระบุตัวเลือกบรรทัดคำสั่งที่เขียนทับการตั้งค่าที่เกี่ยวข้องทั้งหมด นอกจากนี้การเข้าถึงไฟล์กำหนดค่าผ่านเครือข่ายจะเพิ่มเวลาเริ่มต้นของโปรแกรมเป็นเวลาหลายวินาที หากไฟล์ไม่มีอยู่โปรแกรมจะเริ่มเร็วขึ้นมาก (เนื่องจากแต่ละงานใช้เวลาเพียงหนึ่งนาทีเท่านั้น แต่เนื่องจากฉันใช้โปรแกรมแบบโต้ตอบฉันไม่ต้องการย้าย / ลบไฟล์การกำหนดค่าตลอดเวลา ขึ้นอยู่กับเวลาที่งานแบ็ตช์ของฉันถูกกำหนดเวลาไว้ในคลัสเตอร์ (ขึ้นอยู่กับการใช้งานของผู้ใช้รายอื่น)

(นอกเหนือจาก: ประสิทธิภาพของไฟล์เครือข่ายช้ามากอาจเป็นข้อบกพร่อง แต่ฉันเป็นเพียงผู้ใช้ของคลัสเตอร์ดังนั้นฉันสามารถแก้ไขได้เท่านั้นไม่สามารถแก้ไขได้)

ฉันสามารถสร้างเวอร์ชันของโปรแกรมที่ไม่อ่านไฟล์การกำหนดค่า (หรือมีตัวเลือกบรรทัดคำสั่งไม่ให้ใช้) สำหรับการใช้แบทช์ แต่สภาพแวดล้อมการสร้างของโปรแกรมนี้ออกแบบมาไม่ดีและติดตั้งยาก ฉันชอบที่จะใช้ไบนารีที่ติดตั้งผ่านผู้จัดการแพ็คเกจของระบบของฉัน

ฉันจะหลอกลวงอินสแตนซ์ของโปรแกรมนี้โดยเฉพาะเพื่อแกล้งทำเป็นไฟล์การกำหนดค่าของฉันไม่มีอยู่ (โดยไม่ต้องแก้ไขโปรแกรม) ฉันหวังว่าจะได้รูปแบบ pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...แต่ฉันเปิดให้โซลูชั่นอื่น ๆ


2
คุณสามารถเรียกใช้ในฐานะผู้ใช้ที่ไม่มีสิทธิ์ในการอ่านไฟล์
psimon

1
@psimon ในฐานะ "ผู้ใช้เพียงคนเดียว" ของคลัสเตอร์ฉันไม่สามารถสร้างผู้ใช้ใหม่ให้ทำงานชุดงานของฉันได้ นั่นเป็นความคิดที่ฉลาดและหากไม่มีคำแนะนำที่ดีกว่านี้ฉันจะทำให้ผู้ดูแลระบบคลัสเตอร์ทำเพื่อฉัน
Jeffrey Bosboom

หรือตั้งค่าสคริปต์ที่เปลี่ยนชื่อไฟล์กำหนดค่าครั้งแรกรันโปรแกรมแล้วเปลี่ยนชื่อไฟล์กำหนดค่าอีกครั้ง
psimon

@psimon ฉันเดาว่าฉันจะชัดเจนกว่านี้: ฉันอาจใช้โปรแกรมแบบโต้ตอบและในโหมดแบทช์ในเวลาเดียวกันขึ้นอยู่กับว่างานแบ็ตช์ของฉันได้รับการกำหนดเวลาในคลัสเตอร์
Jeffrey Bosboom

1
ใช่หากมีการเชื่อมโยงแบบไดนามิกคุณสามารถใช้LD_PRELOADเบ็ด ที่ง่าย (คุณสามารถดำเนินการว่าในหนึ่งหรือสองชั่วโมงถ้าคุณรู้ว่า C) ptraceกว่าทางเลือกซึ่งเป็น คุณอาจใช้ปลอมแปลงรูทเพื่อทำสิ่งนี้ (ซึ่งก็คือ LD_PRELOAD ฉันเชื่อ)
Derobert

คำตอบ:


33

โปรแกรมนั้นอาจแก้ไขพา ธ ไปยังไฟล์$HOME/.config/myprogramนั้น ดังนั้นคุณสามารถบอกได้ว่าไดเรกทอรีบ้านของคุณอยู่ที่อื่นเช่น:

HOME=/nowhere your-program

ตอนนี้โปรแกรมของคุณอาจต้องการทรัพยากรอื่นในโฮมไดเร็กตอรี่ของคุณ หากคุณรู้ว่าพวกเขาคือใครคุณสามารถเตรียมบ้านปลอมสำหรับโปรแกรมของคุณพร้อมลิงค์ไปยังแหล่งข้อมูลที่ต้องการ

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram

5
คำตอบนี้แก้ปัญหาของฉันได้ดังนั้นฉันจึงยอมรับแม้ว่ามันจะไม่ใช่คำตอบทั่วไปสำหรับคำถามในชื่อของคำถามนี้ preload hook ดังที่อธิบายไว้ในคำตอบอื่นเป็นโซลูชันทั่วไป (แต่ยังมีความพยายามสูงกว่า)
Jeffrey Bosboom

28

หากสิ่งอื่นล้มเหลวให้เขียนไลบรารี wrapper ที่คุณจะใช้LD_PRELOADเพื่อให้การโทรopen("/home/you/my-program/config.interactive")ถูกดักข้อมูล แต่จะถูกส่งผ่าน สิ่งนี้ใช้ได้กับโปรแกรมทุกประเภทแม้แต่เชลล์สคริปต์เนื่องจากมันจะกรองการเรียกระบบ

extern int errno;

int open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    return get_real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}

หมายเหตุ: ฉันยังไม่ได้ทดสอบรหัสนี้และฉันไม่แน่ใจ 100% ว่าerrnoชิ้นส่วนใช้งานได้

ดูที่วิธีการfakerootไม่ได้สำหรับการโทรชอบและgetuid(2)stat(2)

โดยพื้นฐานแล้วตัวเชื่อมโยงจะเชื่อมโยงแอปพลิเคชันนั้นไปยังไลบรารีของคุณซึ่งจะแทนที่openสัญลักษณ์ เนื่องจากคุณไม่สามารถใช้ฟังก์ชั่นที่แตกต่างกันสองชื่อopenในห้องสมุดของคุณเองคุณต้องแยกมันในส่วนที่สอง (เช่นget_real_open) ซึ่งจะเปิดลิงค์ไปยังการopenโทรเดิม

เดิม: ./Application

Application -----> libc.so
            open()

ดัก: LD_PRELOAD=yourlib_wrap.so ./Application

Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
            open()                 get_real_open()                 open()

แก้ไข: เห็นได้ชัดว่ามีการldตั้งค่าสถานะที่คุณสามารถเปิดใช้งาน ( --wrap <symbol>) ที่ช่วยให้คุณสามารถเขียน wrappers โดยไม่ต้องหันไปเชื่อมโยงสองครั้ง:

/* yourlib.c */
#include <stdio.h>

int __real_open(const char *pathname, int flags)

int __wrap_open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    /* the undefined reference here will resolve to "open" at linking time */
    return __real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1; 
  }
}

2

ย้ายไฟล์ปรับแต่งของคุณออกไปแล้วเขียน shell wrapper สำหรับกรณีการใช้งานแบบโต้ตอบที่คัดลอกไฟล์ไปยังปลายทางปกติรันโปรแกรมและลบออกเมื่อออกจากโปรแกรม


ดูการแก้ไขล่าสุดของฉัน: ฉันไม่ได้ควบคุมการตั้งเวลาแบทช์ดังนั้นฉันอาจใช้โปรแกรมแบบโต้ตอบและเป็นส่วนหนึ่งของงานแบ็ตช์ในเวลาเดียวกัน
Jeffrey Bosboom

1

สิ่งนี้ควรเป็นไปได้ด้วย unionfs / aufs คุณสร้างchrootสภาพแวดล้อมสำหรับกระบวนการ คุณใช้ไดเรกทอรีจริงเป็นเลเยอร์แบบอ่านอย่างเดียวและวางว่างไว้ด้านบน จากนั้นคุณเมานต์ยูเนี่ยนวอลุ่มไปยังไดเรกทอรีที่เกี่ยวข้องในchrootสภาพแวดล้อมและลบไฟล์ที่นั่น กระบวนการจะไม่เห็น แต่คนอื่น ๆ ทำ


0

เปลี่ยนชื่อไฟล์ config config.interactiveไปเช่น config.scriptสร้างไฟล์ที่ว่างเปล่าที่เรียกว่าเช่น

ตอนนี้สร้างซอฟต์ลิงค์ที่เรียกว่าconfig(หรืออะไรก็ตามที่แอปพลิเคชันคาดหวังว่าจะเป็นไฟล์กำหนดค่า) เพื่อกำหนดว่าคุณต้องการตั้งค่าจริงและเรียกใช้แอปพลิเคชันของคุณแบบใด

ln -s config.interactive config

อย่าลืมจัดระเบียบลิงก์ของคุณในภายหลัง


ดูการแก้ไขล่าสุดของฉัน: ฉันไม่ได้ควบคุมการตั้งเวลาแบทช์ดังนั้นฉันอาจใช้โปรแกรมแบบโต้ตอบและเป็นส่วนหนึ่งของงานแบ็ตช์ในเวลาเดียวกัน คำตอบนี้เป็นหลักเหมือนกับการย้ายไฟล์ไปรอบ ๆ ไม่ว่าจะด้วยตนเองหรือด้วยสคริปต์
Jeffrey Bosboom

1
Doh! ฉันต้องคิดและพิมพ์ให้เร็วขึ้น มันเป็นแอพพลิเคชั่นขนาดใหญ่หรือไม่? มันจะถูกโอนไปยัง chroot และวิ่งจากที่นั่นแบบโต้ตอบ ทุกอย่างขึ้นอยู่กับสิ่งที่โปรแกรมโต้ตอบฉันคิด นอกจากนี้ยังอาจเป็นงานที่น่าเบื่อมากที่จะได้ทุกอย่างที่มันต้องการใน chroot ด้วย (ฉันคิดว่าฉันได้พูดคุยกับตัวเลือกนั้นแล้ว!)
ธันวาคม 2557

0

หากคุณมีลักษณะที่แน่นอนว่าโปรแกรมของคุณใช้ไฟล์กำหนดค่าอย่างไรฉันก็มองข้ามไป หลายโปรแกรม (เช่นbashและvi) จะตรวจสอบไฟล์กำหนดค่าทันทีที่เริ่มต้น หากไฟล์มีอยู่ให้อ่านและปิดมัน โปรแกรมเหล่านี้ไม่เคยเข้าถึงไฟล์เริ่มต้นเหล่านี้อีกครั้ง หากโปรแกรมของคุณเป็นเช่นนั้นอ่านต่อ

ฉันรู้ว่าคุณปฏิเสธคำตอบที่ทำให้ไฟล์กำหนดค่าไม่มีอยู่จริง (โดยการเปลี่ยนชื่อ) แต่ฉันมีรอยย่นที่ฉันไม่เคยเห็นใครเสนอมาเลย ทำสิ่งนี้เมื่อคุณเรียกใช้โปรแกรมในโหมดแบทช์:

DELAY_TIME=1
REALPATH="~/.config/myprogram"
HOLDPATH="${REALPATH}.hold"

mv "$REALPATH" "$HOLDPATH"
(sleep "$DELAY_TIME"; mv "$HOLDPATH" "$REALPATH")&
myprogram

สิ่งนี้จะย้ายไฟล์การกำหนดค่าไปให้พ้นทาง แต่จากนั้นจะย้ายมันกลับหนึ่งวินาทีในภายหลังแม้ว่าmyprogramจะยังคงทำงานอยู่ นี่เป็นการสร้างช่วงเวลาสั้น ๆ ในช่วงที่ไฟล์ไม่พร้อมใช้งาน - ความน่าจะเป็นที่คุณจะเรียกใช้โปรแกรมแบบโต้ตอบระหว่างหน้าต่างนี้คืออะไร? (แม้ว่าคุณจะทำคุณสามารถออกและรีสตาร์ทและไฟล์ปรับแต่งอาจจะกลับมาใช้ได้)

สิ่งนี้จะสร้างสภาพการแข่งขัน หากโปรแกรมใช้เวลานานเกินไปในการเปิดไฟล์อาจเป็นไฟล์จริง หากสิ่งนี้เกิดขึ้นบ่อยครั้งเพียงพอที่จะเป็นปัญหาให้เพิ่มมูลค่าของ DELAY_TIME


1
อะไรคือสิ่งที่แย่ที่สุดที่จะผิดพลาด? ฉันเห็นว่าเกิดขึ้นจริง ในการผลิต
Henk Langeveld

-1

ฉันชอบคำตอบของ Stephane แต่สิ่งนี้จะหลอกให้โปรแกรมเชื่อว่าไฟล์ใด ๆว่างเปล่า - (เพราะ Dentry ชี้ไปที่ไฟล์ที่ว่างเปล่า) :

cat <./test.txt
###OUTPUT###
notempty

mount --bind /dev/null ./test.txt
cat <./test.txt
###NO OUTPUT###

umount ./test.txt
cat <./test.txt
###OUTPUT###
notempty

คุณสามารถ:

mount --bind ./someotherconfig.conf ./unwanted.conf

หากคุณต้องการ


นี่เทียบเท่ากับคำตอบก่อนหน้านี้สองสามข้อ (ยกเว้นฉันเชื่อว่าคำตอบนี้ต้องการให้ผู้ใช้ได้รับสิทธิพิเศษ) OP ปฏิเสธคำตอบอื่น ๆ เหล่านั้นเพราะเขาไม่ต้องการหลอกลวงกระบวนการใด ๆ - เขาต้องการหลอกแบตช์การเรียกใช้โปรแกรมในขณะที่ให้การเรียกใช้แบบโต้ตอบดูไฟล์ปรับแต่งตามปกติ
สกอตต์

@Scott - ฉันไม่เห็นด้วย - คำตอบอื่น ๆ ก่อนหน้านี้ขอแนะนำการเปลี่ยนแปลงบางอย่างในmvไฟล์ - ซึ่งอาจมีผลกระทบอื่น ๆ กว่าที่ส่งผลกระทบต่อเนื้อฟันของมันเช่นจริง ๆ แล้วตัดไฟล์หรืออื่น ๆ และอื่น ๆ ยังฉันควรunshareที่mountผมคิดว่า ...
mikeserv
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.