Bir süreç için belirli bir yol yapmak sahte olabilir mi?


9

Ben kök değilim (android emülatör ile oynamak için) birden çok kullanıcı ile bir linux sunucu üzerinde ADB çalıştırmak çalışıyorum. Adb arka plan programı günlüklerini /tmp/adb.logmaalesef ADB'ye kodlanmış gibi görünüyor ve bu durum değişmeyecek şekilde dosyaya yazıyor .

Yani, adb, kaçak başarısız bariz hatayı veriyor: cannot open '/tmp/adb.log': Permission denied. Bu dosya başka bir kullanıcı tarafından oluşturulmuş ve /tmpüzerinde yapışkan bit var. Adb'yi adb nodaemon serverstdout'a yazarak başlatırsam hata oluşmaz (çakışmalardan kaçınmak için bağlantı noktasını benzersiz bir değere de ayarladım).

Benim sorum: ADB'den başka bir dosyaya yazmanın bir yolu var /tmp/adb.logmı? Daha genel olarak, sürece özgü bir sembolik bağlantı oluşturmanın bir yolu var mı? Ben tüm dosya erişimlerini yönlendirmek istiyorum /tmp/adb.log, bir dosya söyleyerek için ~/tmp/adb.log.

Yine, ben sunucu kök değilim, bu yüzden chroot, mount -o rbindve chmodgeçerli seçenekler değildir. Mümkünse, ADB kaynaklarını değiştirmek istemiyorum, ancak elbette başka çözüm yoksa bunu yapacağım.

PS özgü ADB durum için ben çalışan çare olabilir adb nodaemon serverile nohupve çıkış yönlendirme, ama genel bir soru hala geçerlidir.


2
Evet. işleminizi özel bir bağlanma ad alanına yerleştirebilir ve başka bir dosya üzerine /tmp/adb.logbağlayabilir, hatta kendi özel dosyasını da bağlayabilirsiniz /tmp. yapmak man unshareve man namespacesve man nsenter.
mikeserv

1
@mikeserv harika, tam olarak ihtiyacım olan şey gibi görünüyor, teşekkür ederim! Yorumunuzu cevap olarak yeniden biçimlendirirseniz, kabul edilmiş olarak ayarlayabilirim.
gluk47

Ya da LD_PRELOADhileler var, ama bu daha karmaşık olurdu.
thrig

@thrig evet, LD_PRELOAD hakkında olsa da, ama açıkçası, /home/$USER/tmp/adb.logadb sabit
kod

Yanıtlar:


5

İşte, özel bağlama ad alanına bir işlem koymak ve üst öğesinin şu anda sahip olduğu aynı dosya sisteminin farklı bir görünümünü vermek için util-linux'leri kullanmanın çok basit bir örneği unshare:

{   cd /tmp                      #usually a safe place for this stuff
    echo hey   >file             #some
    echo there >file2            #evidence
    sudo unshare -m sh -c '      #unshare requires root by default
         mount -B file2 file     #bind mount there over hey
         cat file                #show it
         kill -TSTP "$$"         #suspend root shell and switch back to parent
         umount file             #unbind there
         cat file'               #show it
    cat file                     #root shell just suspended
    fg                           #bring it back
    cat file2                    #round it off
}

there                            #root shell
hey                              #root shell suspended
hey                              #root shell restored
there                            #rounded

unshareBağlama ad alanı tesisinin kendisi tüm 3.x çekirdek serisi için oldukça olgun olmasına rağmen, bir sürece güncel linux sistemlerinde yardımcı programla dosya sistemine özel bir görünüm verebilirsiniz . nsenterAynı paketteki yardımcı programla her türlü önceden var olan ad alanlarını girebilir ve daha fazla bilgi edinebilirsiniz man.


Sadece bir soru: bu benim mi yoksa sadece kök kullanıcı için mükemmel bir çözüm mü?
gluk47

@ gluk47 - olmak zorunda değil. Eğer yapabilirsiniz unsharead her türlü - kullanıcı ad dahil etmek. böylece kullanıcı kök erişimine sahip olduğu bir ad alanını çalıştırabilir ve bir kök kullanıcının ayırabileceği herhangi bir şey üst ad alanını etkilemez. diğer bir deyişle, bir bağlanma ad alanı bir kullanıcı ad alanı içine gömülebilir. gerçekten bu mansayfaları okumalısın . derinleşiyor. bu tam olarak nasıl dockerve sytemd-nspawnçalışır.
mikeserv

Bu adam sayfalarını ve internetten örnekleri okudum) Görünüşe göre onları daha fazla okumam gerekiyor, sadece bu teknolojiye işaret ettiğiniz için teşekkür ederim, bir şekilde bunun farkında değildim.
gluk47

@ gluk47 - sadakat uğruna cevapları kabul etme. duyarlılık takdir edilirken, bu tür şeyler buranın amacını yener. Eğer cevabı kabul kullanın . O kimse bu biri değilse, lütfen değil bu cevabı kabul. bu arada, sadece bir süreç kök olarak başlatıldığından , bunun bir kök süreç olarak kalması gerektiği anlamına gelmez . orada runuserbirlikte kullanılabilir yarar unshareve yine derlenmiş program yazmaya açık iseniz, kullanmak olamazdı hiçbir neden yok unshare()aynı, hatta sadece yapmak syscall system()suid ikili ile.
mikeserv

Yararlı olmasaydı cevabı kabul etmediğimden eminim. Her iki yanıtı da alakalı ve yararlı buluyorum, bu yüzden bu cevaplardan birini kontrol etmenin tek ayırt edici nedeni
duygudur

11

LD_PRELOAD çok zor değil ve root olmanıza gerek yok. open()C kütüphanesindeki real yerine kendi C rutininizi ara . Rutiniz, açılacak dosyanın "/tmp/adb.log" olup olmadığını kontrol eder ve gerçek açık dosyasını farklı bir dosya adıyla çağırır. İşte shim_open.c:

/*
 * capture calls to a routine and replace with your code
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c
 * LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log
 */
#define _FCNTL_H 1 /* hack for open() prototype */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#define OLDNAME "/tmp/adb.log"
#define NEWNAME "/tmp/myadb.log"

int open(const char *pathname, int flags, mode_t mode){
    static int (*real_open)(const char *pathname, int flags, mode_t mode) = NULL;

    if (!real_open) {
        real_open = dlsym(RTLD_NEXT, "open");
        char *error = dlerror();
        if (error != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    if (strcmp(pathname,OLDNAME)==0) pathname = NEWNAME;
    fprintf(stderr, "opening: %s\n", pathname);
    return real_open(pathname, flags, mode);
}

Birlikte derleyin gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.cve içine bir şey koyarak /tmp/myadb.logkoşarak test edin LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log. Sonra adb üzerinde LD_PRELOAD deneyin.


Aslında, çözümünüz kök olmayan bir kullanıcı olarak çalışmayı başarabildiğim tek çözümdür. Paylaşım ( Operation not permitted) ile başa çıkmadım . Umarım bu openişlemek için yeterlidir, ancak son olarak, unlinkbu işleyiciye eklemek zor değildir.
gluk47

Ayy. İki cevabı kontrol edemediğim için ne yazık. Mikeserv'in çözümünü bir cevap olarak kontrol edeceğine söz verdim ve gerçekten de geçerli bir çözüm.
gluk47

2
boşver. Ben de öğrendim unshare, bu yüzden hepimiz kazanıyoruz!
meuh

Bir süre sonra LD_PRELOAD örneği için tekrar teşekkür ederiz. Kodunuzu denediğimden, LD_PRELOAD'ı bile düşünmediğim çeşitli durumlarda kullanıyorum. Hayatım değişti :)
gluk47

2
@ gluk47 Gnu / Linux hakkında bu kadar harika olan şey budur: Keşfetmeyi asla bırakmanıza gerek yok! Keşfedilecek ve paylaşılacak çok iyi şeyler var.
meuh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.