2016-09-13 2 views
0

У меня возникли проблемы с пониманием того, почему моя программа setuid не кажется, что она фактически повышает права доступа, хотя идентификатор кажется правильным. Это работает на ядре 2.6 и не работает, но работает точно так, как предполагалось, на Ubuntu 14.04, делая то же самое. Мне нужна программа, которая в определенные моменты времени во время выполнения требует повышенных разрешений, а минимальная привилегия - по умолчанию.Программа setuid не работает на ядре 2.6

#include <stdio.h> 
#include <stdint.h> 
#include <arpa/inet.h> 
#include <stdint.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 

static uid_t _orig_euid; 

void save_privilege(void){ 
    _orig_euid = geteuid(); 
    printf("saved privilege: %d\n", _orig_euid); 
} 

void drop_privileges(void){ 
    if(seteuid(getuid()) == -1){ 
     exit(0); 
    } 
    printf("dropped privileges %d %d\n", getuid(), geteuid()); 
} 

void reacquire_privileges(void){ 
    if(setuid(_orig_euid) == -1){ 
     exit(0); 
    } 
    printf("reacquired privileges %d %d\n", getuid(), geteuid()); 
} 

void do_privileged(int rw){ 
    switch(rw){ 
     case 0: 
      //read from driver 
      system("dd if=/dev/myrandom bs=10 count=1"); 
     case 1: 
      //write to driver 
      system("dd if=/dev/zero of=/dev/myrandom"); 
     case 2: 
      //change something in proc fs 
      system("echo 3 > /proc/sys/vm/drop_caches"); 
     default: 
      break; 
    } 
} 

int main(int argc, char *argv[]){ 
    int i; 

    if(argc != 2){ 
     printf("usage: %s testno\n", argv[0]); 
     return 0; 
    } 

    i = atoi(argv[1]); 

    save_privilege(); 

    do_privileged(i); 

    drop_privileges(); 

    do_privileged(i); 

    reacquire_privileges(); 

    do_privileged(i); 

    return 0; 
} 

программных разрешений Мои устанавливаются как:

ls -l 
-rwsr-xr-x 1 root  root   6547 Sep 13 00:35 test 

Мой текущий идентификатор пользователя:

id 
uid=1000(user) gid=1000(user) 

PROCFS вход Я пытаюсь написать это:

ls -l /proc/sys/vm/drop_caches 
-rw-r--r-- 1 root  root   0 Sep 13 00:36 /proc/sys/vm/drop_caches 

Когда я запускаю программу, я получаю:

./test 2 
saved privilege: 0 
sh: cannot create /proc/sys/vm/drop_caches: Permission denied 
dropped privileges 1000 1000 
sh: cannot create /proc/sys/vm/drop_caches: Permission denied 
reacquired privileges 1000 0 
sh: cannot create /proc/sys/vm/drop_caches: Permission denied 

Однако выполнение той же программы на Ubuntu 14.04 работает правильно - это только не изменить запись Procfs когда привилегии отбрасываются.

Здесь strace (./test_perm - это то же самое, что и ./test).

$ strace ./test_perm 2 
execve("./test_perm", ["./test_perm", "2"], [/* 8 vars */]) = 0 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40005000 
open("/lib/libc.so.0", O_RDONLY)  = 3 
fstat(3, {st_mode=S_IFREG|0755, st_size=310348, ...}) = 0 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40006000 
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\260\256\0\0004\0\0\0"..., 4096) = 4096 
mmap2(NULL, 360448, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000e000 
mmap2(0x4000e000, 303968, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x4000e000 
mmap2(0x40060000, 4972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x4a) = 0x40060000 
mmap2(0x40062000, 15112, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40062000 
close(3)        = 0 
munmap(0x40006000, 4096)    = 0 
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=21200, ...}) = 0 
mprotect(0x40060000, 4096, PROT_READ) = 0 
mprotect(0x4000c000, 4096, PROT_READ) = 0 
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 
geteuid32()        = 1000 
write(1, "saved privilege: 1000\n", 22saved privilege: 1000 
) = 22 
rt_sigaction(SIGQUIT, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, {SIG_DFL, [], 0}, 8) = 0 
rt_sigaction(SIGINT, {SIG_IGN, [INT], SA_RESTART|0x4000000}, {SIG_DFL, [], 0}, 8) = 0 
rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, {SIG_DFL, [], 0}, 8) = 0 
vfork(sh: cannot create /proc/sys/vm/drop_caches: Permission denied 
)         = 1183 
--- SIGCHLD (Child exited) @ 0 (0) --- 
rt_sigaction(SIGQUIT, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_IGN, [INT], SA_RESTART|0x4000000}, {SIG_IGN, [INT], SA_RESTART|0x4000000}, 8) = 0 
wait4(1183, [{WIFEXITED(s) && WEXITSTATUS(s) == 2}], 0, NULL) = 1183 
rt_sigaction(SIGQUIT, {SIG_DFL, [QUIT], SA_RESTART|0x4000000}, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_DFL, [INT], SA_RESTART|0x4000000}, {SIG_IGN, [INT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, 8) = 0 
getuid32()        = 1000 
setresuid32(-1, 1000, -1)    = 0 
getuid32()        = 1000 
geteuid32()        = 1000 
write(1, "dropped privileges 1000 1000\n", 29dropped privileges 1000 1000 
) = 29 
rt_sigaction(SIGQUIT, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, {SIG_DFL, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_IGN, [INT], SA_RESTART|0x4000000}, {SIG_DFL, [INT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, 8) = 0 
vfork(sh: cannot create /proc/sys/vm/drop_caches: Permission denied 
)         = 1184 
--- SIGCHLD (Child exited) @ 0 (0) --- 
rt_sigaction(SIGQUIT, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_IGN, [INT], SA_RESTART|0x4000000}, {SIG_IGN, [INT], SA_RESTART|0x4000000}, 8) = 0 
wait4(1184, [{WIFEXITED(s) && WEXITSTATUS(s) == 2}], 0, NULL) = 1184 
rt_sigaction(SIGQUIT, {SIG_DFL, [QUIT], SA_RESTART|0x4000000}, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_DFL, [INT], SA_RESTART|0x4000000}, {SIG_IGN, [INT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, 8) = 0 
setuid32(1000)       = 0 
getuid32()        = 1000 
geteuid32()        = 1000 
write(1, "reacquired privileges 1000 1000\n", 32reacquired privileges 1000 1000 
) = 32 
rt_sigaction(SIGQUIT, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, {SIG_DFL, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_IGN, [INT], SA_RESTART|0x4000000}, {SIG_DFL, [INT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, 8) = 0 
vfork(sh: cannot create /proc/sys/vm/drop_caches: Permission denied 
)         = 1185 
--- SIGCHLD (Child exited) @ 0 (0) --- 
rt_sigaction(SIGQUIT, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_IGN, [INT], SA_RESTART|0x4000000}, {SIG_IGN, [INT], SA_RESTART|0x4000000}, 8) = 0 
wait4(1185, [{WIFEXITED(s) && WEXITSTATUS(s) == 2}], 0, NULL) = 1185 
rt_sigaction(SIGQUIT, {SIG_DFL, [QUIT], SA_RESTART|0x4000000}, {SIG_IGN, [QUIT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGINT, {SIG_DFL, [INT], SA_RESTART|0x4000000}, {SIG_IGN, [INT], SA_RESTART|0x4000000}, 8) = 0 
rt_sigaction(SIGCHLD, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, {SIG_DFL, [CHLD], SA_RESTART|0x4000000}, 8) = 0 
exit(0)         = ? 
+0

Что такое следующий номер версии 2.6? В отличие от ряда ядер 3.x и 4.x, это имеет смысл. В любом случае, ряд ядер 2.6.x относительно старый, вы уверены, что хотите его поддержать? Кроме того, компиляция старого ядра в современном дистрибутиве может привести к невозможности ядра ядра и libc. Можете ли вы выполнить ту же операцию ('echo 3>/proc/sys/vm/drop_caches') без вашей программы (используя' su' или 'sudo/bin/sh -c ')? – Tsyvarev

+0

@ Цыварев, даже * y * имеет смысл в * 2.6.x.y * версия. – 0andriy

+0

Возможно, что перенаправление вывода '>' вызывает проблемы с помощью функции system(). Является ли «echo 3> ...» единственной командой, которая не работает? Если это так, попробуйте ввести привилегированный режим, фактически открыв файл proc через open (2) и напишите (2). – kaiwan

ответ

0

Вызов вашей программы в соответствии с принципом strace привел к игнорированию бит setuid.

Вы пытались запустить двоичные файлы setuid с enid id, вызывающим пользователя. Это не работает очень хорошо; однако это, похоже, не является вашей основной проблемой.

Не стоит call system() из программы setuid еще кто-то делает SHELL=/tmp/evil your_setuid_program и имеет корень на завтрак.

Я стесняюсь даже хотеть выяснить, что вы действительно делаете неправильно здесь, что приводит к тому, что бит setuid не работает для вас, потому что вы, очевидно, не знаете, как писать бинарные файлы setuid.

+0

Ну, у меня есть приложение, работающее во встроенной Linux, которое должно иметь возможность выполнять вызовы system(), но уменьшать привилегии, когда вызовы system() не нужны, все, что я читал, делает его программой setuid, немедленно уменьшая привилегии в начале приложения, затем повторно загружать привилегии root только тогда, когда это необходимо (когда мне нужно сделать вызовы system()), а затем снова сбросить привилегии, есть ли у вас лучшее предложение о том, как это сделать? –

+0

@wireless_freedom: попробуйте написать программу, которая работает от имени root, и делает именно то, что ей нужно, без вызова системы(), а затем мы можем поговорить. Если вы не можете этого сделать, просто нет смысла. Для всех ваших примеров, кроме insmod, вы не должны запускать какие-либо программы вообще. – Joshua

 Смежные вопросы

  • Нет связанных вопросов^_^